summaryrefslogtreecommitdiff
path: root/chromium/ui
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2018-12-10 16:19:40 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2018-12-10 16:01:50 +0000
commit51f6c2793adab2d864b3d2b360000ef8db1d3e92 (patch)
tree835b3b4446b012c75e80177cef9fbe6972cc7dbe /chromium/ui
parent6036726eb981b6c4b42047513b9d3f4ac865daac (diff)
downloadqtwebengine-chromium-51f6c2793adab2d864b3d2b360000ef8db1d3e92.tar.gz
BASELINE: Update Chromium to 71.0.3578.93
Change-Id: I6a32086c33670e1b033f8b10e6bf1fd4da1d105d Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/ui')
-rw-r--r--chromium/ui/accelerated_widget_mac/display_link_mac.cc45
-rw-r--r--chromium/ui/accelerated_widget_mac/display_link_mac.h18
-rw-r--r--chromium/ui/accessibility/BUILD.gn10
-rw-r--r--chromium/ui/accessibility/PRESUBMIT.py4
-rw-r--r--chromium/ui/accessibility/ax_action_data.h3
-rw-r--r--chromium/ui/accessibility/ax_enum_util.cc28
-rw-r--r--chromium/ui/accessibility/ax_enums.mojom13
-rw-r--r--chromium/ui/accessibility/ax_event_generator.cc20
-rw-r--r--chromium/ui/accessibility/ax_event_generator.h2
-rw-r--r--chromium/ui/accessibility/ax_event_generator_unittest.cc49
-rw-r--r--chromium/ui/accessibility/ax_host_delegate.cc2
-rw-r--r--chromium/ui/accessibility/ax_host_delegate.h15
-rw-r--r--chromium/ui/accessibility/ax_mode.h (renamed from chromium/ui/accessibility/ax_modes.h)6
-rw-r--r--chromium/ui/accessibility/ax_mode_observer.h2
-rw-r--r--chromium/ui/accessibility/ax_node_data.cc30
-rw-r--r--chromium/ui/accessibility/ax_node_data.h3
-rw-r--r--chromium/ui/accessibility/ax_node_position.cc10
-rw-r--r--chromium/ui/accessibility/ax_node_position.h6
-rw-r--r--chromium/ui/accessibility/ax_node_position_unittest.cc2
-rw-r--r--chromium/ui/accessibility/ax_position.h47
-rw-r--r--chromium/ui/accessibility/ax_role_properties.cc34
-rw-r--r--chromium/ui/accessibility/ax_role_properties.h10
-rw-r--r--chromium/ui/accessibility/ax_tree.cc54
-rw-r--r--chromium/ui/accessibility/ax_tree.h4
-rw-r--r--chromium/ui/accessibility/ax_tree_combiner.cc30
-rw-r--r--chromium/ui/accessibility/ax_tree_combiner.h9
-rw-r--r--chromium/ui/accessibility/ax_tree_combiner_unittest.cc26
-rw-r--r--chromium/ui/accessibility/ax_tree_data.cc12
-rw-r--r--chromium/ui/accessibility/ax_tree_data.h7
-rw-r--r--chromium/ui/accessibility/ax_tree_id.cc62
-rw-r--r--chromium/ui/accessibility/ax_tree_id.h58
-rw-r--r--chromium/ui/accessibility/ax_tree_id_registry.cc28
-rw-r--r--chromium/ui/accessibility/ax_tree_id_registry.h10
-rw-r--r--chromium/ui/accessibility/ax_tree_serializer.h50
-rw-r--r--chromium/ui/accessibility/ax_tree_serializer_unittest.cc72
-rw-r--r--chromium/ui/accessibility/ax_tree_unittest.cc53
-rw-r--r--chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_cs.xtb2
-rw-r--r--chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_gu.xtb16
-rw-r--r--chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_mr.xtb2
-rw-r--r--chromium/ui/accessibility/mojom/BUILD.gn1
-rw-r--r--chromium/ui/accessibility/mojom/ax_action_data.mojom3
-rw-r--r--chromium/ui/accessibility/mojom/ax_action_data_mojom_traits.cc3
-rw-r--r--chromium/ui/accessibility/mojom/ax_action_data_mojom_traits.h11
-rw-r--r--chromium/ui/accessibility/mojom/ax_action_data_mojom_traits_unittest.cc4
-rw-r--r--chromium/ui/accessibility/mojom/ax_host.mojom12
-rw-r--r--chromium/ui/accessibility/mojom/ax_tree_data.mojom7
-rw-r--r--chromium/ui/accessibility/mojom/ax_tree_data_mojom_traits.cc9
-rw-r--r--chromium/ui/accessibility/mojom/ax_tree_data_mojom_traits.h21
-rw-r--r--chromium/ui/accessibility/mojom/ax_tree_data_mojom_traits_unittest.cc12
-rw-r--r--chromium/ui/accessibility/mojom/ax_tree_id.mojom10
-rw-r--r--chromium/ui/accessibility/mojom/ax_tree_id.typemap15
-rw-r--r--chromium/ui/accessibility/mojom/ax_tree_id_mojom_traits.cc18
-rw-r--r--chromium/ui/accessibility/mojom/ax_tree_id_mojom_traits.h22
-rw-r--r--chromium/ui/accessibility/mojom/ax_tree_id_mojom_traits_unittest.cc18
-rw-r--r--chromium/ui/accessibility/mojom/typemaps.gni1
-rw-r--r--chromium/ui/accessibility/platform/aura_window_properties.cc5
-rw-r--r--chromium/ui/accessibility/platform/aura_window_properties.h10
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_atk_hyperlink.cc99
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_atk_hyperlink.h9
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node.h2
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_auralinux.cc740
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_auralinux.h31
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_auralinux_unittest.cc86
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_base.cc13
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_delegate_base.cc14
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_mac.mm51
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_test_helper.cc47
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_test_helper.h22
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_win.cc11
-rw-r--r--chromium/ui/accessibility/platform/ax_system_caret_win.cc35
-rw-r--r--chromium/ui/accessibility/platform/ax_system_caret_win.h1
-rw-r--r--chromium/ui/android/BUILD.gn8
-rw-r--r--chromium/ui/android/delegated_frame_host_android.cc165
-rw-r--r--chromium/ui/android/delegated_frame_host_android.h7
-rw-r--r--chromium/ui/android/delegated_frame_host_android_unittest.cc59
-rw-r--r--chromium/ui/android/display_android_manager.cc2
-rw-r--r--chromium/ui/android/junit/src/org/chromium/ui/AsyncViewProviderTest.java131
-rw-r--r--chromium/ui/android/junit/src/org/chromium/ui/AsyncViewStubTest.java75
-rw-r--r--chromium/ui/android/junit/src/org/chromium/ui/base/ClipboardTest.java56
-rw-r--r--chromium/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java147
-rw-r--r--chromium/ui/android/junit/src/org/chromium/ui/drawable/StateListDrawableBuilderTest.java62
-rw-r--r--chromium/ui/android/junit/src/org/chromium/ui/shadows/ShadowAnimatedStateListDrawable.java18
-rw-r--r--chromium/ui/android/junit/src/org/chromium/ui/shadows/ShadowAppCompatResources.java25
-rw-r--r--chromium/ui/android/junit/src/org/chromium/ui/shadows/ShadowAppCompatResourcesTest.java32
-rw-r--r--chromium/ui/android/junit/src/org/chromium/ui/shadows/ShadowAsyncLayoutInflater.java33
-rw-r--r--chromium/ui/android/junit/src/org/chromium/ui/text/SpanApplierTest.java179
-rw-r--r--chromium/ui/android/junit/src/org/chromium/ui/widget/AnchoredPopupWindowTest.java202
-rw-r--r--chromium/ui/aura/BUILD.gn5
-rw-r--r--chromium/ui/aura/client/aura_constants.cc6
-rw-r--r--chromium/ui/aura/client/aura_constants.h14
-rw-r--r--chromium/ui/aura/env.cc28
-rw-r--r--chromium/ui/aura/env.h7
-rw-r--r--chromium/ui/aura/event_injector.cc21
-rw-r--r--chromium/ui/aura/gestures/gesture_recognizer_unittest.cc3
-rw-r--r--chromium/ui/aura/hit_test_data_provider_aura_unittest.cc23
-rw-r--r--chromium/ui/aura/local/window_port_local.cc15
-rw-r--r--chromium/ui/aura/mus/client_surface_embedder.cc14
-rw-r--r--chromium/ui/aura/mus/client_surface_embedder.h5
-rw-r--r--chromium/ui/aura/mus/embed_root.cc1
-rw-r--r--chromium/ui/aura/mus/gesture_synchronizer.cc55
-rw-r--r--chromium/ui/aura/mus/gesture_synchronizer.h45
-rw-r--r--chromium/ui/aura/mus/gesture_synchronizer_unittest.cc90
-rw-r--r--chromium/ui/aura/mus/input_method_mus.cc45
-rw-r--r--chromium/ui/aura/mus/input_method_mus.h9
-rw-r--r--chromium/ui/aura/mus/input_method_mus_unittest.cc94
-rw-r--r--chromium/ui/aura/mus/mus_mouse_location_updater.cc24
-rw-r--r--chromium/ui/aura/mus/mus_types.h10
-rw-r--r--chromium/ui/aura/mus/os_exchange_data_provider_mus.cc3
-rw-r--r--chromium/ui/aura/mus/property_converter.cc109
-rw-r--r--chromium/ui/aura/mus/property_converter.h20
-rw-r--r--chromium/ui/aura/mus/property_converter_unittest.cc91
-rw-r--r--chromium/ui/aura/mus/text_input_client_impl.cc5
-rw-r--r--chromium/ui/aura/mus/window_mus.h2
-rw-r--r--chromium/ui/aura/mus/window_port_mus.cc163
-rw-r--r--chromium/ui/aura/mus/window_port_mus.h28
-rw-r--r--chromium/ui/aura/mus/window_port_mus_unittest.cc62
-rw-r--r--chromium/ui/aura/mus/window_tree_client.cc192
-rw-r--r--chromium/ui/aura/mus/window_tree_client.h41
-rw-r--r--chromium/ui/aura/mus/window_tree_client_unittest.cc213
-rw-r--r--chromium/ui/aura/mus/window_tree_host_mus.cc4
-rw-r--r--chromium/ui/aura/mus/window_tree_host_mus.h3
-rw-r--r--chromium/ui/aura/mus/window_tree_host_mus_delegate.h5
-rw-r--r--chromium/ui/aura/mus/window_tree_host_mus_unittest.cc26
-rw-r--r--chromium/ui/aura/screen_ozone.h2
-rw-r--r--chromium/ui/aura/test/ui_controls_factory_ozone.cc64
-rw-r--r--chromium/ui/aura/window.cc67
-rw-r--r--chromium/ui/aura/window.h15
-rw-r--r--chromium/ui/aura/window_delegate.h8
-rw-r--r--chromium/ui/aura/window_event_dispatcher.cc16
-rw-r--r--chromium/ui/aura/window_event_dispatcher.h2
-rw-r--r--chromium/ui/aura/window_event_dispatcher_unittest.cc93
-rw-r--r--chromium/ui/aura/window_occlusion_tracker.cc59
-rw-r--r--chromium/ui/aura/window_occlusion_tracker.h35
-rw-r--r--chromium/ui/aura/window_occlusion_tracker_unittest.cc35
-rw-r--r--chromium/ui/aura/window_port.cc2
-rw-r--r--chromium/ui/aura/window_port.h24
-rw-r--r--chromium/ui/aura/window_port_for_shutdown.cc3
-rw-r--r--chromium/ui/aura/window_targeter.cc57
-rw-r--r--chromium/ui/aura/window_targeter.h22
-rw-r--r--chromium/ui/aura/window_targeter_unittest.cc31
-rw-r--r--chromium/ui/aura/window_tree_host.cc13
-rw-r--r--chromium/ui/aura/window_tree_host.h19
-rw-r--r--chromium/ui/aura/window_tree_host_platform.cc23
-rw-r--r--chromium/ui/aura/window_tree_host_platform.h3
-rw-r--r--chromium/ui/aura/window_tree_host_unittest.cc41
-rw-r--r--chromium/ui/aura/window_unittest.cc6
-rw-r--r--chromium/ui/base/BUILD.gn63
-rw-r--r--chromium/ui/base/accelerators/accelerator.cc2
-rw-r--r--chromium/ui/base/accelerators/accelerator.h5
-rw-r--r--chromium/ui/base/accelerators/accelerator_history.h4
-rw-r--r--chromium/ui/base/accelerators/accelerator_manager.cc34
-rw-r--r--chromium/ui/base/accelerators/accelerator_manager.h5
-rw-r--r--chromium/ui/base/accelerators/accelerator_manager_delegate.h35
-rw-r--r--chromium/ui/base/accelerators/accelerator_manager_unittest.cc105
-rw-r--r--chromium/ui/base/class_property.cc2
-rw-r--r--chromium/ui/base/clipboard/clipboard.cc2
-rw-r--r--chromium/ui/base/clipboard/clipboard.h2
-rw-r--r--chromium/ui/base/clipboard/clipboard_android.cc37
-rw-r--r--chromium/ui/base/clipboard/clipboard_aura.cc41
-rw-r--r--chromium/ui/base/clipboard/clipboard_aurax11.cc54
-rw-r--r--chromium/ui/base/clipboard/clipboard_mac.mm37
-rw-r--r--chromium/ui/base/clipboard/clipboard_util_mac.h8
-rw-r--r--chromium/ui/base/clipboard/clipboard_util_mac.mm30
-rw-r--r--chromium/ui/base/cocoa/a11y_util.h28
-rw-r--r--chromium/ui/base/cocoa/a11y_util.mm25
-rw-r--r--chromium/ui/base/cocoa/accessibility_hostable.h25
-rw-r--r--chromium/ui/base/cocoa/appkit_utils.h31
-rw-r--r--chromium/ui/base/cocoa/appkit_utils.mm76
-rw-r--r--chromium/ui/base/cocoa/constrained_window/constrained_window_animation.mm38
-rw-r--r--chromium/ui/base/cocoa/controls/blue_label_button.h20
-rw-r--r--chromium/ui/base/cocoa/controls/blue_label_button.mm152
-rw-r--r--chromium/ui/base/cocoa/controls/blue_label_button_unittest.mm40
-rw-r--r--chromium/ui/base/cocoa/controls/button_utils.h3
-rw-r--r--chromium/ui/base/cocoa/controls/button_utils.mm16
-rw-r--r--chromium/ui/base/cocoa/controls/hover_image_menu_button.h29
-rw-r--r--chromium/ui/base/cocoa/controls/hover_image_menu_button.mm44
-rw-r--r--chromium/ui/base/cocoa/controls/hover_image_menu_button_cell.h35
-rw-r--r--chromium/ui/base/cocoa/controls/hover_image_menu_button_cell.mm69
-rw-r--r--chromium/ui/base/cocoa/controls/hover_image_menu_button_unittest.mm175
-rw-r--r--chromium/ui/base/cocoa/controls/hyperlink_button_cell.h58
-rw-r--r--chromium/ui/base/cocoa/controls/hyperlink_button_cell.mm167
-rw-r--r--chromium/ui/base/cocoa/controls/hyperlink_button_cell_unittest.mm143
-rw-r--r--chromium/ui/base/cocoa/controls/hyperlink_text_view.h39
-rw-r--r--chromium/ui/base/cocoa/controls/hyperlink_text_view.mm179
-rw-r--r--chromium/ui/base/cocoa/controls/hyperlink_text_view_unittest.mm155
-rw-r--r--chromium/ui/base/cocoa/controls/imageview_utils.h23
-rw-r--r--chromium/ui/base/cocoa/controls/imageview_utils.mm15
-rw-r--r--chromium/ui/base/cocoa/menu_controller.h42
-rw-r--r--chromium/ui/base/cocoa/menu_controller.mm40
-rw-r--r--chromium/ui/base/cocoa/ns_view_ids.h49
-rw-r--r--chromium/ui/base/cocoa/ns_view_ids.mm49
-rw-r--r--chromium/ui/base/cocoa/nsgraphics_context_additions.h23
-rw-r--r--chromium/ui/base/cocoa/nsgraphics_context_additions.mm42
-rw-r--r--chromium/ui/base/cocoa/nsgraphics_context_additions_unittest.mm28
-rw-r--r--chromium/ui/base/cocoa/nsview_additions.h57
-rw-r--r--chromium/ui/base/cocoa/nsview_additions.mm126
-rw-r--r--chromium/ui/base/cocoa/nsview_additions_unittest.mm106
-rw-r--r--chromium/ui/base/cocoa/scoped_cg_context_smooth_fonts.h34
-rw-r--r--chromium/ui/base/cocoa/scoped_cg_context_smooth_fonts.mm20
-rw-r--r--chromium/ui/base/cocoa/three_part_image.h54
-rw-r--r--chromium/ui/base/cocoa/three_part_image.mm82
-rw-r--r--chromium/ui/base/cocoa/three_part_image_unittest.mm84
-rw-r--r--chromium/ui/base/cocoa/view_description.h21
-rw-r--r--chromium/ui/base/cocoa/view_description.mm31
-rw-r--r--chromium/ui/base/cocoa/views_hostable.h78
-rw-r--r--chromium/ui/base/cursor/cursor_util.cc4
-rw-r--r--chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.cc4
-rw-r--r--chromium/ui/base/default_theme_provider.h12
-rw-r--r--chromium/ui/base/default_theme_provider_mac.mm47
-rw-r--r--chromium/ui/base/dragdrop/file_info.cc4
-rw-r--r--chromium/ui/base/dragdrop/file_info.h1
-rw-r--r--chromium/ui/base/dragdrop/os_exchange_data_provider_aurax11.cc4
-rw-r--r--chromium/ui/base/dragdrop/os_exchange_data_provider_mac.h3
-rw-r--r--chromium/ui/base/dragdrop/os_exchange_data_provider_mac.mm28
-rw-r--r--chromium/ui/base/dragdrop/os_exchange_data_provider_win.cc89
-rw-r--r--chromium/ui/base/dragdrop/os_exchange_data_unittest.cc25
-rw-r--r--chromium/ui/base/dragdrop/os_exchange_data_win_unittest.cc1
-rw-r--r--chromium/ui/base/ime/BUILD.gn129
-rw-r--r--chromium/ui/base/ime/candidate_window.h8
-rw-r--r--chromium/ui/base/ime/composition_text.h4
-rw-r--r--chromium/ui/base/ime/constants.cc11
-rw-r--r--chromium/ui/base/ime/constants.h21
-rw-r--r--chromium/ui/base/ime/fuchsia/input_method_keyboard_controller_fuchsia.cc96
-rw-r--r--chromium/ui/base/ime/fuchsia/input_method_keyboard_controller_fuchsia.h59
-rw-r--r--chromium/ui/base/ime/ime_text_span.h4
-rw-r--r--chromium/ui/base/ime/infolist_entry.h4
-rw-r--r--chromium/ui/base/ime/input_method_auralinux.cc36
-rw-r--r--chromium/ui/base/ime/input_method_auralinux.h1
-rw-r--r--chromium/ui/base/ime/input_method_auralinux_unittest.cc90
-rw-r--r--chromium/ui/base/ime/input_method_base.cc28
-rw-r--r--chromium/ui/base/ime/input_method_base.h5
-rw-r--r--chromium/ui/base/ime/input_method_chromeos.cc2
-rw-r--r--chromium/ui/base/ime/input_method_chromeos_unittest.cc4
-rw-r--r--chromium/ui/base/ime/input_method_delegate.cc22
-rw-r--r--chromium/ui/base/ime/input_method_delegate.h21
-rw-r--r--chromium/ui/base/ime/input_method_factory.cc8
-rw-r--r--chromium/ui/base/ime/input_method_fuchsia.cc66
-rw-r--r--chromium/ui/base/ime/input_method_fuchsia.h49
-rw-r--r--chromium/ui/base/ime/input_method_mac.mm4
-rw-r--r--chromium/ui/base/ime/input_method_minimal.cc6
-rw-r--r--chromium/ui/base/ime/input_method_minimal_unittest.cc4
-rw-r--r--chromium/ui/base/ime/input_method_win_base.cc4
-rw-r--r--chromium/ui/base/ime/input_method_win_imm32.cc1
-rw-r--r--chromium/ui/base/ime/input_method_win_tsf.cc1
-rw-r--r--chromium/ui/base/ime/linux/BUILD.gn29
-rw-r--r--chromium/ui/base/ime/linux/fake_input_method_context.cc5
-rw-r--r--chromium/ui/base/ime/linux/fake_input_method_context.h2
-rw-r--r--chromium/ui/base/ime/linux/fake_input_method_context_factory.h3
-rw-r--r--chromium/ui/base/ime/linux/linux_input_method_context.h16
-rw-r--r--chromium/ui/base/ime/linux/linux_input_method_context_factory.h4
-rw-r--r--chromium/ui/base/ime/linux/ui_base_ime_linux_export.h34
-rw-r--r--chromium/ui/base/ime/mock_input_method.cc6
-rw-r--r--chromium/ui/base/ime/text_input_flags.h2
-rw-r--r--chromium/ui/base/ime/ui_base_ime_types_export.h34
-rw-r--r--chromium/ui/base/l10n/l10n_util.cc10
-rw-r--r--chromium/ui/base/l10n/l10n_util_win.cc61
-rw-r--r--chromium/ui/base/l10n/l10n_util_win.h21
-rw-r--r--chromium/ui/base/l10n/l10n_util_win_unittest.cc60
-rw-r--r--chromium/ui/base/material_design/material_design_controller.cc116
-rw-r--r--chromium/ui/base/material_design/material_design_controller.h50
-rw-r--r--chromium/ui/base/material_design/material_design_controller_observer.h24
-rw-r--r--chromium/ui/base/material_design/material_design_controller_unittest.cc211
-rw-r--r--chromium/ui/base/models/list_selection_model.cc9
-rw-r--r--chromium/ui/base/models/simple_menu_model.cc4
-rw-r--r--chromium/ui/base/mojo/clipboard_host.h2
-rw-r--r--chromium/ui/base/mojo/ui_base_types.mojom7
-rw-r--r--chromium/ui/base/mojo/ui_base_types.typemap5
-rw-r--r--chromium/ui/base/mojo/ui_base_types_struct_traits.h35
-rw-r--r--chromium/ui/base/resource/resource_bundle.cc180
-rw-r--r--chromium/ui/base/resource/resource_bundle.h46
-rw-r--r--chromium/ui/base/resource/resource_bundle_android.cc17
-rw-r--r--chromium/ui/base/resource/resource_bundle_android.h5
-rw-r--r--chromium/ui/base/resource/resource_bundle_ios.mm7
-rw-r--r--chromium/ui/base/resource/resource_bundle_mac.mm7
-rw-r--r--chromium/ui/base/resource/resource_bundle_unittest.cc61
-rw-r--r--chromium/ui/base/template_expressions.cc2
-rw-r--r--chromium/ui/base/theme_provider.h43
-rw-r--r--chromium/ui/base/touch/touch_editing_controller.h5
-rw-r--r--chromium/ui/base/ui_base_features.cc18
-rw-r--r--chromium/ui/base/ui_base_features.h14
-rw-r--r--chromium/ui/base/ui_base_switches.cc22
-rw-r--r--chromium/ui/base/ui_base_switches.h6
-rw-r--r--chromium/ui/base/ui_features.gni3
-rw-r--r--chromium/ui/base/view_prop.cc4
-rw-r--r--chromium/ui/base/webui/i18n_source_stream_unittest.cc2
-rw-r--r--chromium/ui/base/x/selection_owner.cc14
-rw-r--r--chromium/ui/base/x/selection_requestor.cc6
-rw-r--r--chromium/ui/base/x/selection_utils.cc10
-rw-r--r--chromium/ui/base/x/x11_menu_list.cc3
-rw-r--r--chromium/ui/base/x/x11_util.cc7
-rw-r--r--chromium/ui/chromeos/BUILD.gn2
-rw-r--r--chromium/ui/compositor/BUILD.gn2
-rw-r--r--chromium/ui/compositor/compositor.cc22
-rw-r--r--chromium/ui/compositor/compositor.h29
-rw-r--r--chromium/ui/compositor/compositor_lock.cc28
-rw-r--r--chromium/ui/compositor/compositor_lock.h30
-rw-r--r--chromium/ui/compositor/compositor_lock_unittest.cc53
-rw-r--r--chromium/ui/compositor/compositor_unittest.cc8
-rw-r--r--chromium/ui/compositor/compositor_vsync_manager.cc13
-rw-r--r--chromium/ui/compositor/compositor_vsync_manager.h10
-rw-r--r--chromium/ui/compositor/host/host_context_factory_private.cc55
-rw-r--r--chromium/ui/compositor/host/host_context_factory_private.h13
-rw-r--r--chromium/ui/compositor/layer.cc30
-rw-r--r--chromium/ui/compositor/layer.h10
-rw-r--r--chromium/ui/compositor/layer_animation_observer.cc3
-rw-r--r--chromium/ui/compositor/layer_animator.cc6
-rw-r--r--chromium/ui/compositor/layer_animator_collection.cc4
-rw-r--r--chromium/ui/compositor/layer_animator_unittest.cc116
-rw-r--r--chromium/ui/compositor/layer_unittest.cc70
-rw-r--r--chromium/ui/display/BUILD.gn10
-rw-r--r--chromium/ui/display/display.cc84
-rw-r--r--chromium/ui/display/display.h12
-rw-r--r--chromium/ui/display/display_change_notifier.cc10
-rw-r--r--chromium/ui/display/display_change_notifier.h2
-rw-r--r--chromium/ui/display/display_list.h6
-rw-r--r--chromium/ui/display/display_observer.h5
-rw-r--r--chromium/ui/display/display_switches.cc6
-rw-r--r--chromium/ui/display/display_switches.h3
-rw-r--r--chromium/ui/display/mac/screen_mac.mm2
-rw-r--r--chromium/ui/display/manager/BUILD.gn2
-rw-r--r--chromium/ui/display/manager/display_manager.cc25
-rw-r--r--chromium/ui/display/manager/display_manager.h2
-rw-r--r--chromium/ui/display/manager/touch_device_manager.cc4
-rw-r--r--chromium/ui/display/manager/touch_device_manager_unittest.cc50
-rw-r--r--chromium/ui/display/manager/touch_transform_controller_unittest.cc2
-rw-r--r--chromium/ui/display/util/BUILD.gn2
-rw-r--r--chromium/ui/display/util/edid_parser.h1
-rw-r--r--chromium/ui/display/win/dpi.cc49
-rw-r--r--chromium/ui/display/win/dpi.h30
-rw-r--r--chromium/ui/display/win/screen_win.cc162
-rw-r--r--chromium/ui/display/win/screen_win.h30
-rw-r--r--chromium/ui/display/win/screen_win_unittest.cc132
-rw-r--r--chromium/ui/display/win/uwp_text_scale_factor.cc236
-rw-r--r--chromium/ui/display/win/uwp_text_scale_factor.h73
-rw-r--r--chromium/ui/events/BUILD.gn114
-rw-r--r--chromium/ui/events/blink/blink_features.cc6
-rw-r--r--chromium/ui/events/blink/blink_features.h10
-rw-r--r--chromium/ui/events/blink/input_handler_proxy.cc59
-rw-r--r--chromium/ui/events/blink/input_handler_proxy_unittest.cc643
-rw-r--r--chromium/ui/events/blink/prediction/input_predictor_unittest_helpers.cc31
-rw-r--r--chromium/ui/events/blink/prediction/input_predictor_unittest_helpers.h (renamed from chromium/ui/events/blink/prediction/input_predictor_unittest.cc)34
-rw-r--r--chromium/ui/events/blink/prediction/kalman_predictor_unittest.cc4
-rw-r--r--chromium/ui/events/blink/prediction/least_squares_predictor.cc4
-rw-r--r--chromium/ui/events/blink/prediction/least_squares_predictor_unittest.cc2
-rw-r--r--chromium/ui/events/blink/web_input_event.cc54
-rw-r--r--chromium/ui/events/blink/web_input_event.h38
-rw-r--r--chromium/ui/events/blink/web_input_event_traits.cc12
-rw-r--r--chromium/ui/events/blink/web_input_event_traits.h3
-rw-r--r--chromium/ui/events/blink/web_input_event_unittest.cc51
-rw-r--r--chromium/ui/events/cocoa/events_mac.mm1
-rw-r--r--chromium/ui/events/devices/device_util_linux.cc12
-rw-r--r--chromium/ui/events/devices/input_device.h7
-rw-r--r--chromium/ui/events/devices/mojo/input_device_struct_traits.cc13
-rw-r--r--chromium/ui/events/devices/mojo/input_devices.mojom3
-rw-r--r--chromium/ui/events/devices/x11/device_data_manager_x11.cc12
-rw-r--r--chromium/ui/events/devices/x11/touch_factory_x11.cc6
-rw-r--r--chromium/ui/events/event.cc53
-rw-r--r--chromium/ui/events/event.h42
-rw-r--r--chromium/ui/events/event_handler.cc5
-rw-r--r--chromium/ui/events/event_rewriter_unittest.cc3
-rw-r--r--chromium/ui/events/event_source.cc3
-rw-r--r--chromium/ui/events/event_target.cc30
-rw-r--r--chromium/ui/events/event_target.h8
-rw-r--r--chromium/ui/events/event_unittest.cc78
-rw-r--r--chromium/ui/events/event_utils.cc24
-rw-r--r--chromium/ui/events/fuchsia/input_event_dispatcher.cc194
-rw-r--r--chromium/ui/events/fuchsia/input_event_dispatcher.h44
-rw-r--r--chromium/ui/events/fuchsia/input_event_dispatcher_delegate.h22
-rw-r--r--chromium/ui/events/fuchsia/input_event_dispatcher_unittest.cc263
-rw-r--r--chromium/ui/events/gesture_detection/filtered_gesture_provider.cc4
-rw-r--r--chromium/ui/events/gesture_detection/filtered_gesture_provider.h2
-rw-r--r--chromium/ui/events/gesture_detection/gesture_provider.cc4
-rw-r--r--chromium/ui/events/gesture_detection/gesture_provider_unittest.cc13
-rw-r--r--chromium/ui/events/gesture_detection/touch_disposition_gesture_filter.cc10
-rw-r--r--chromium/ui/events/gesture_detection/touch_disposition_gesture_filter.h2
-rw-r--r--chromium/ui/events/gestures/gesture_provider_aura.cc8
-rw-r--r--chromium/ui/events/gestures/gesture_provider_aura.h2
-rw-r--r--chromium/ui/events/gestures/gesture_provider_aura_unittest.cc42
-rw-r--r--chromium/ui/events/gestures/gesture_recognizer.cc22
-rw-r--r--chromium/ui/events/gestures/gesture_recognizer.h34
-rw-r--r--chromium/ui/events/gestures/gesture_recognizer_impl.cc139
-rw-r--r--chromium/ui/events/gestures/gesture_recognizer_impl.h14
-rw-r--r--chromium/ui/events/gestures/gesture_recognizer_impl_mac.cc2
-rw-r--r--chromium/ui/events/gestures/gesture_recognizer_impl_mac.h7
-rw-r--r--chromium/ui/events/gestures/gesture_recognizer_impl_unittest.cc163
-rw-r--r--chromium/ui/events/gestures/gesture_recognizer_observer.cc11
-rw-r--r--chromium/ui/events/gestures/gesture_recognizer_observer.h30
-rw-r--r--chromium/ui/events/gestures/gesture_types.h11
-rw-r--r--chromium/ui/events/gestures/motion_event_aura_unittest.cc4
-rw-r--r--chromium/ui/events/keyboard_hook.h2
-rw-r--r--chromium/ui/events/keyboard_hook_base.cc2
-rw-r--r--chromium/ui/events/keyboard_hook_base.h2
-rw-r--r--chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm2
-rw-r--r--chromium/ui/events/keycodes/keysym_to_unicode.cc2
-rw-r--r--chromium/ui/events/keycodes/platform_key_map_win.cc11
-rw-r--r--chromium/ui/events/keycodes/platform_key_map_win.h8
-rw-r--r--chromium/ui/events/keycodes/platform_key_map_win_unittest.cc4
-rw-r--r--chromium/ui/events/mojo/BUILD.gn13
-rw-r--r--chromium/ui/events/mojo/event.mojom53
-rw-r--r--chromium/ui/events/mojo/event.typemap2
-rw-r--r--chromium/ui/events/mojo/event_constants.mojom17
-rw-r--r--chromium/ui/events/mojo/event_struct_traits.cc270
-rw-r--r--chromium/ui/events/mojo/event_struct_traits.h75
-rw-r--r--chromium/ui/events/mojo/struct_traits_unittest.cc326
-rw-r--r--chromium/ui/events/mojo/traits_test_service.mojom12
-rw-r--r--chromium/ui/events/ozone/evdev/event_device_info.cc5
-rw-r--r--chromium/ui/events/ozone/evdev/event_device_test_util.cc2
-rw-r--r--chromium/ui/events/ozone/evdev/event_factory_evdev.cc4
-rw-r--r--chromium/ui/events/platform/x11/x11_event_source.cc2
-rw-r--r--chromium/ui/events/platform/x11/x11_event_source.h5
-rw-r--r--chromium/ui/events/win/events_win_utils.cc2
-rw-r--r--chromium/ui/events/win/keyboard_hook_win.cc345
-rw-r--r--chromium/ui/events/win/keyboard_hook_win.h52
-rw-r--r--chromium/ui/events/win/keyboard_hook_win_unittest.cc1085
-rw-r--r--chromium/ui/events/x/events_x.cc4
-rw-r--r--chromium/ui/events/x/events_x_unittest.cc63
-rw-r--r--chromium/ui/events/x/events_x_utils.cc94
-rw-r--r--chromium/ui/events/x/events_x_utils.h14
-rw-r--r--chromium/ui/file_manager/BUILD.gn4
-rw-r--r--chromium/ui/file_manager/audio_player/js/BUILD.gn10
-rw-r--r--chromium/ui/file_manager/base/js/BUILD.gn27
-rw-r--r--chromium/ui/file_manager/externs/BUILD.gn26
-rw-r--r--chromium/ui/file_manager/file_manager/background/js/BUILD.gn41
-rw-r--r--chromium/ui/file_manager/file_manager/common/js/BUILD.gn111
-rw-r--r--chromium/ui/file_manager/file_manager/foreground/elements/BUILD.gn8
-rw-r--r--chromium/ui/file_manager/file_manager/foreground/js/BUILD.gn98
-rw-r--r--chromium/ui/file_manager/file_manager/foreground/js/metadata/BUILD.gn8
-rw-r--r--chromium/ui/file_manager/file_manager/foreground/js/ui/BUILD.gn26
-rw-r--r--chromium/ui/file_manager/file_manager/test/BUILD.gn17
-rw-r--r--chromium/ui/file_manager/file_manager/test/js/BUILD.gn2
-rw-r--r--chromium/ui/file_manager/gallery/js/BUILD.gn21
-rw-r--r--chromium/ui/file_manager/gallery/js/image_editor/BUILD.gn4
-rw-r--r--chromium/ui/file_manager/image_loader/BUILD.gn84
-rw-r--r--chromium/ui/file_manager/js_unit_tests.gni68
-rw-r--r--chromium/ui/file_manager/video_player/js/BUILD.gn10
-rw-r--r--chromium/ui/file_manager/video_player/js/cast/BUILD.gn7
-rw-r--r--chromium/ui/gfx/BUILD.gn44
-rw-r--r--chromium/ui/gfx/OWNERS5
-rw-r--r--chromium/ui/gfx/android/java_bitmap.h1
-rw-r--r--chromium/ui/gfx/animation/animation_container.cc2
-rw-r--r--chromium/ui/gfx/buffer_format_util.cc66
-rw-r--r--chromium/ui/gfx/buffer_types.h5
-rw-r--r--chromium/ui/gfx/canvas.cc14
-rw-r--r--chromium/ui/gfx/codec/chromeos/jpeg_codec_robust_slow.cc101
-rw-r--r--chromium/ui/gfx/codec/jpeg_codec.cc95
-rw-r--r--chromium/ui/gfx/codec/jpeg_codec.h15
-rw-r--r--chromium/ui/gfx/color_analysis.cc45
-rw-r--r--chromium/ui/gfx/color_palette.h4
-rw-r--r--chromium/ui/gfx/color_space.cc88
-rw-r--r--chromium/ui/gfx/color_space.h62
-rw-r--r--chromium/ui/gfx/color_space_win.cc5
-rw-r--r--chromium/ui/gfx/color_space_win.h9
-rw-r--r--chromium/ui/gfx/color_transform_unittest.cc7
-rw-r--r--chromium/ui/gfx/color_utils.cc7
-rw-r--r--chromium/ui/gfx/color_utils_unittest.cc26
-rw-r--r--chromium/ui/gfx/font_list_impl.cc3
-rw-r--r--chromium/ui/gfx/font_render_params_android.cc5
-rw-r--r--chromium/ui/gfx/font_render_params_fuchsia.cc5
-rw-r--r--chromium/ui/gfx/font_render_params_linux.cc3
-rw-r--r--chromium/ui/gfx/font_render_params_mac.cc5
-rw-r--r--chromium/ui/gfx/font_unittest.cc33
-rw-r--r--chromium/ui/gfx/geometry/BUILD.gn4
-rw-r--r--chromium/ui/gfx/geometry/angle_conversions.h10
-rw-r--r--chromium/ui/gfx/geometry/axis_transform2d.h4
-rw-r--r--chromium/ui/gfx/geometry/box_f.h4
-rw-r--r--chromium/ui/gfx/geometry/cubic_bezier.h4
-rw-r--r--chromium/ui/gfx/geometry/dip_util.h46
-rw-r--r--chromium/ui/gfx/geometry/geometry_export.h29
-rw-r--r--chromium/ui/gfx/geometry/insets.h4
-rw-r--r--chromium/ui/gfx/geometry/insets_f.h4
-rw-r--r--chromium/ui/gfx/geometry/matrix3_f.h8
-rw-r--r--chromium/ui/gfx/geometry/point.h28
-rw-r--r--chromium/ui/gfx/geometry/point3_f.h10
-rw-r--r--chromium/ui/gfx/geometry/point_conversions.h6
-rw-r--r--chromium/ui/gfx/geometry/point_f.h8
-rw-r--r--chromium/ui/gfx/geometry/quad_f.h8
-rw-r--r--chromium/ui/gfx/geometry/quaternion.h4
-rw-r--r--chromium/ui/gfx/geometry/rect.h14
-rw-r--r--chromium/ui/gfx/geometry/rect_conversions.cc25
-rw-r--r--chromium/ui/gfx/geometry/rect_conversions.h20
-rw-r--r--chromium/ui/gfx/geometry/rect_f.h10
-rw-r--r--chromium/ui/gfx/geometry/rect_unittest.cc85
-rw-r--r--chromium/ui/gfx/geometry/safe_integer_conversions.h1
-rw-r--r--chromium/ui/gfx/geometry/scroll_offset.h4
-rw-r--r--chromium/ui/gfx/geometry/size.h28
-rw-r--r--chromium/ui/gfx/geometry/size_conversions.h6
-rw-r--r--chromium/ui/gfx/geometry/size_f.h6
-rw-r--r--chromium/ui/gfx/geometry/vector2d.h4
-rw-r--r--chromium/ui/gfx/geometry/vector2d_conversions.h6
-rw-r--r--chromium/ui/gfx/geometry/vector2d_f.h14
-rw-r--r--chromium/ui/gfx/geometry/vector3d_f.h20
-rw-r--r--chromium/ui/gfx/geometry_skia_export.h29
-rw-r--r--chromium/ui/gfx/gpu_memory_buffer.cc3
-rw-r--r--chromium/ui/gfx/harfbuzz_font_skia.cc8
-rw-r--r--chromium/ui/gfx/icc_profile.cc3
-rw-r--r--chromium/ui/gfx/image/canvas_image_source.cc32
-rw-r--r--chromium/ui/gfx/image/image.cc3
-rw-r--r--chromium/ui/gfx/image/image_family.cc11
-rw-r--r--chromium/ui/gfx/image/image_generic.cc6
-rw-r--r--chromium/ui/gfx/image/image_mac_unittest.mm6
-rw-r--r--chromium/ui/gfx/image/image_skia.cc59
-rw-r--r--chromium/ui/gfx/image/image_skia_operations.cc40
-rw-r--r--chromium/ui/gfx/image/image_skia_rep.h74
-rw-r--r--chromium/ui/gfx/image/image_skia_rep_default.cc106
-rw-r--r--chromium/ui/gfx/image/image_skia_rep_default.h98
-rw-r--r--chromium/ui/gfx/image/image_skia_rep_ios.cc (renamed from chromium/ui/gfx/image/image_skia_rep.cc)37
-rw-r--r--chromium/ui/gfx/image/image_skia_rep_ios.h67
-rw-r--r--chromium/ui/gfx/image/image_skia_util_ios.mm2
-rw-r--r--chromium/ui/gfx/image/image_skia_util_mac.mm8
-rw-r--r--chromium/ui/gfx/image/image_unittest.cc8
-rw-r--r--chromium/ui/gfx/image/image_unittest_util.cc2
-rw-r--r--chromium/ui/gfx/image/image_util.cc4
-rw-r--r--chromium/ui/gfx/image/mojo/image_skia_struct_traits.h2
-rw-r--r--chromium/ui/gfx/image/mojo/image_traits_unittest.cc8
-rw-r--r--chromium/ui/gfx/interpolated_transform.h1
-rw-r--r--chromium/ui/gfx/linux/OWNERS1
-rw-r--r--chromium/ui/gfx/mac/io_surface.cc10
-rw-r--r--chromium/ui/gfx/mojo/BUILD.gn1
-rw-r--r--chromium/ui/gfx/mojo/buffer_types.mojom5
-rw-r--r--chromium/ui/gfx/mojo/buffer_types_struct_traits.cc8
-rw-r--r--chromium/ui/gfx/mojo/buffer_types_struct_traits.h25
-rw-r--r--chromium/ui/gfx/mojo/selection_bound.typemap3
-rw-r--r--chromium/ui/gfx/mojo/selection_bound_struct_traits.h1
-rw-r--r--chromium/ui/gfx/mojo/swap_result.mojom16
-rw-r--r--chromium/ui/gfx/mojo/swap_result.typemap8
-rw-r--r--chromium/ui/gfx/mojo/swap_result_enum_traits.h48
-rw-r--r--chromium/ui/gfx/platform_font_win.cc323
-rw-r--r--chromium/ui/gfx/platform_font_win.h87
-rw-r--r--chromium/ui/gfx/platform_font_win_unittest.cc119
-rw-r--r--chromium/ui/gfx/render_text.cc13
-rw-r--r--chromium/ui/gfx/render_text_harfbuzz.cc5
-rw-r--r--chromium/ui/gfx/sequential_id_generator.cc4
-rw-r--r--chromium/ui/gfx/skia_paint_util.cc19
-rw-r--r--chromium/ui/gfx/skia_util.h56
-rw-r--r--chromium/ui/gfx/skia_vector_animation.cc261
-rw-r--r--chromium/ui/gfx/skia_vector_animation.h241
-rw-r--r--chromium/ui/gfx/skia_vector_animation_observer.h33
-rw-r--r--chromium/ui/gfx/skia_vector_animation_unittest.cc835
-rw-r--r--chromium/ui/gfx/skottie_wrapper.cc36
-rw-r--r--chromium/ui/gfx/skottie_wrapper.h55
-rw-r--r--chromium/ui/gfx/switches.cc18
-rw-r--r--chromium/ui/gfx/switches.h6
-rw-r--r--chromium/ui/gfx/transform.h4
-rw-r--r--chromium/ui/gfx/transform_util.h26
-rw-r--r--chromium/ui/gfx/typemaps.gni1
-rw-r--r--chromium/ui/gl/BUILD.gn16
-rw-r--r--chromium/ui/gl/android/android_surface_composer_compat.cc253
-rw-r--r--chromium/ui/gl/android/android_surface_composer_compat.h86
-rw-r--r--chromium/ui/gl/angle_platform_impl.cc39
-rw-r--r--chromium/ui/gl/angle_platform_impl.h5
-rw-r--r--chromium/ui/gl/egl_bindings_autogen_mock.cc60
-rw-r--r--chromium/ui/gl/egl_bindings_autogen_mock.h21
-rwxr-xr-xchromium/ui/gl/generate_bindings.py42
-rw-r--r--chromium/ui/gl/gl_bindings.h8
-rw-r--r--chromium/ui/gl/gl_bindings_api_autogen_egl.h18
-rw-r--r--chromium/ui/gl/gl_bindings_api_autogen_gl.h2
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_egl.cc171
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_egl.h59
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_gl.cc63
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_gl.h16
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_mock.cc19
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_mock.h3
-rw-r--r--chromium/ui/gl/gl_context_egl.cc6
-rw-r--r--chromium/ui/gl/gl_context_glx_unittest.cc1
-rw-r--r--chromium/ui/gl/gl_enums_implementation_autogen.h4902
-rw-r--r--chromium/ui/gl/gl_gl_api_implementation.cc19
-rw-r--r--chromium/ui/gl/gl_image.cc17
-rw-r--r--chromium/ui/gl/gl_image.h31
-rw-r--r--chromium/ui/gl/gl_image_ahardwarebuffer.cc8
-rw-r--r--chromium/ui/gl/gl_image_ahardwarebuffer.h4
-rw-r--r--chromium/ui/gl/gl_image_io_surface.mm20
-rw-r--r--chromium/ui/gl/gl_image_io_surface_egl.mm5
-rw-r--r--chromium/ui/gl/gl_image_memory.cc158
-rw-r--r--chromium/ui/gl/gl_image_native_pixmap.cc17
-rw-r--r--chromium/ui/gl/gl_image_native_pixmap_unittest.cc3
-rw-r--r--chromium/ui/gl/gl_mock_autogen_egl.h21
-rw-r--r--chromium/ui/gl/gl_mock_autogen_gl.h3
-rw-r--r--chromium/ui/gl/gl_share_group.cc4
-rw-r--r--chromium/ui/gl/gl_stub_autogen_gl.h3
-rw-r--r--chromium/ui/gl/gl_surface_egl.cc16
-rw-r--r--chromium/ui/gl/gl_surface_egl_surface_control.cc250
-rw-r--r--chromium/ui/gl/gl_surface_egl_surface_control.h121
-rw-r--r--chromium/ui/gl/gl_surface_egl_unittest.cc3
-rw-r--r--chromium/ui/gl/gpu_timing_fake.cc4
-rw-r--r--chromium/ui/gl/init/BUILD.gn5
-rw-r--r--chromium/ui/gl/init/create_gr_gl_interface.cc63
-rw-r--r--chromium/ui/gl/init/create_gr_gl_interface.h4
-rw-r--r--chromium/ui/gl/init/gl_initializer_android.cc33
-rw-r--r--chromium/ui/gl/progress_reporter.h22
-rw-r--r--chromium/ui/gl/trace_util.cc19
-rw-r--r--chromium/ui/gl/trace_util.h9
-rw-r--r--chromium/ui/keyboard/BUILD.gn10
-rw-r--r--chromium/ui/keyboard/DEPS3
-rw-r--r--chromium/ui/keyboard/keyboard.mojom25
-rw-r--r--chromium/ui/keyboard/keyboard_controller.cc330
-rw-r--r--chromium/ui/keyboard/keyboard_controller.h133
-rw-r--r--chromium/ui/keyboard/keyboard_controller_observer.h5
-rw-r--r--chromium/ui/keyboard/keyboard_controller_unittest.cc24
-rw-r--r--chromium/ui/keyboard/keyboard_event_filter.cc2
-rw-r--r--chromium/ui/keyboard/keyboard_layout_manager.cc1
-rw-r--r--chromium/ui/keyboard/keyboard_switches.cc2
-rw-r--r--chromium/ui/keyboard/keyboard_switches.h3
-rw-r--r--chromium/ui/keyboard/keyboard_ui.cc14
-rw-r--r--chromium/ui/keyboard/keyboard_ui.h12
-rw-r--r--chromium/ui/keyboard/keyboard_util.cc173
-rw-r--r--chromium/ui/keyboard/keyboard_util.h106
-rw-r--r--chromium/ui/keyboard/keyboard_util_unittest.cc34
-rw-r--r--chromium/ui/keyboard/public/OWNERS2
-rw-r--r--chromium/ui/keyboard/public/keyboard_config.mojom40
-rw-r--r--chromium/ui/latency/frame_metrics.cc103
-rw-r--r--chromium/ui/latency/frame_metrics.h52
-rw-r--r--chromium/ui/latency/frame_metrics_test_common.h25
-rw-r--r--chromium/ui/latency/frame_metrics_unittest.cc81
-rw-r--r--chromium/ui/latency/latency_info.cc4
-rw-r--r--chromium/ui/latency/latency_tracker.cc31
-rw-r--r--chromium/ui/latency/mojo/BUILD.gn1
-rw-r--r--chromium/ui/latency/mojo/DEPS1
-rw-r--r--chromium/ui/latency/mojo/latency_info.mojom1
-rw-r--r--chromium/ui/latency/mojo/latency_info.typemap1
-rw-r--r--chromium/ui/latency/mojo/latency_info_struct_traits.h1
-rw-r--r--chromium/ui/latency/stream_analyzer.cc11
-rw-r--r--chromium/ui/latency/stream_analyzer_unittest.cc70
-rw-r--r--chromium/ui/latency/windowed_analyzer.cc12
-rw-r--r--chromium/ui/latency/windowed_analyzer_unittest.cc69
-rw-r--r--chromium/ui/login/account_picker/md_user_pod_template.html3
-rw-r--r--chromium/ui/login/account_picker/user_pod_template.html2
-rw-r--r--chromium/ui/login/display_manager.js26
-rw-r--r--chromium/ui/message_center/BUILD.gn2
-rw-r--r--chromium/ui/message_center/message_center_impl.cc3
-rw-r--r--chromium/ui/message_center/message_center_impl_unittest.cc6
-rw-r--r--chromium/ui/message_center/message_center_stats_collector.cc10
-rw-r--r--chromium/ui/message_center/notification_list_unittest.cc19
-rw-r--r--chromium/ui/message_center/popup_timers_controller.cc3
-rw-r--r--chromium/ui/message_center/public/cpp/features.cc3
-rw-r--r--chromium/ui/message_center/public/cpp/features.h4
-rw-r--r--chromium/ui/message_center/views/message_popup_view.cc2
-rw-r--r--chromium/ui/message_center/views/message_view.cc93
-rw-r--r--chromium/ui/message_center/views/message_view.h7
-rw-r--r--chromium/ui/message_center/views/message_view_factory.cc22
-rw-r--r--chromium/ui/message_center/views/message_view_factory.h2
-rw-r--r--chromium/ui/message_center/views/notification_background_painter.cc9
-rw-r--r--chromium/ui/message_center/views/notification_background_painter.h7
-rw-r--r--chromium/ui/message_center/views/notification_view_md.cc12
-rw-r--r--chromium/ui/message_center/views/notification_view_md.h1
-rw-r--r--chromium/ui/message_center/views/notification_view_md_unittest.cc39
-rw-r--r--chromium/ui/message_center/views/notification_view_unittest.cc31
-rw-r--r--chromium/ui/message_center/views/slidable_message_view.cc67
-rw-r--r--chromium/ui/message_center/views/slidable_message_view.h74
-rw-r--r--chromium/ui/message_center/views/slide_out_controller.cc8
-rw-r--r--chromium/ui/message_center/views/slide_out_controller.h1
-rw-r--r--chromium/ui/native_theme/common_theme.cc189
-rw-r--r--chromium/ui/native_theme/native_theme.h20
-rw-r--r--chromium/ui/native_theme/native_theme_android.cc4
-rw-r--r--chromium/ui/native_theme/native_theme_android.h2
-rw-r--r--chromium/ui/native_theme/native_theme_aura.cc10
-rw-r--r--chromium/ui/native_theme/native_theme_aura.h2
-rw-r--r--chromium/ui/native_theme/native_theme_dark_aura.cc49
-rw-r--r--chromium/ui/native_theme/native_theme_dark_aura.h3
-rw-r--r--chromium/ui/native_theme/native_theme_mac.h2
-rw-r--r--chromium/ui/native_theme/native_theme_mac.mm4
-rw-r--r--chromium/ui/native_theme/native_theme_win.cc72
-rw-r--r--chromium/ui/native_theme/native_theme_win.h2
-rw-r--r--chromium/ui/ozone/common/linux/OWNERS1
-rw-r--r--chromium/ui/ozone/common/linux/gbm_buffer.h4
-rw-r--r--chromium/ui/ozone/common/linux/gbm_wrapper.cc28
-rw-r--r--chromium/ui/ozone/demo/BUILD.gn4
-rw-r--r--chromium/ui/ozone/demo/demo_window.cc12
-rw-r--r--chromium/ui/ozone/demo/demo_window.h2
-rw-r--r--chromium/ui/ozone/demo/simple_renderer_factory.cc6
-rw-r--r--chromium/ui/ozone/demo/vulkan_overlay_renderer.cc147
-rw-r--r--chromium/ui/ozone/demo/vulkan_overlay_renderer.h3
-rw-r--r--chromium/ui/ozone/demo/vulkan_renderer.cc281
-rw-r--r--chromium/ui/ozone/demo/vulkan_renderer.h46
-rw-r--r--chromium/ui/ozone/platform/drm/BUILD.gn10
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/crtc_controller.cc12
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/crtc_controller.h9
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_buffer.cc64
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_console_buffer.cc53
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_console_buffer.h63
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_device.cc20
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_device.h15
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_device_manager.cc4
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_device_manager.h2
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_display.h2
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_dumb_buffer.cc101
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_dumb_buffer.h (renamed from chromium/ui/ozone/platform/drm/gpu/drm_buffer.h)34
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_framebuffer.h14
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h4
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.h2
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator_unittest.cc78
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_thread.cc15
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_thread.h3
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.h2
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_vsync_provider.cc34
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_vsync_provider.h35
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_window.cc17
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_window.h22
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_window_proxy.cc8
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_window_proxy.h7
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_overlay_surface.h2
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_pixmap.h6
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_surface.cc155
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_surface.h60
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc25
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.h2
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc8
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.h9
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc18
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h9
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc3
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane.h2
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.cc30
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h10
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc11
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h4
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc13
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h4
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc64
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc40
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/mock_drm_device.h11
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/mock_gbm_device.cc3
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/page_flip_request.h3
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/screen_manager.cc53
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc72
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/vulkan_implementation_gbm.cc2
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_cursor.h2
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_device_connector.h4
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_display_host.h2
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_display_host_manager.h10
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h2
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_native_display_delegate.h2
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_overlay_candidates_host.h4
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_overlay_manager.h4
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_window_host.h16
-rw-r--r--chromium/ui/ozone/platform/drm/host/host_drm_device.h2
-rw-r--r--chromium/ui/ozone/platform/scenic/BUILD.gn25
-rw-r--r--chromium/ui/ozone/platform/scenic/DEPS1
-rw-r--r--chromium/ui/ozone/platform/scenic/ozone_platform_scenic.cc31
-rw-r--r--chromium/ui/ozone/platform/scenic/scenic_screen.h2
-rw-r--r--chromium/ui/ozone/platform/scenic/scenic_session.cc19
-rw-r--r--chromium/ui/ozone/platform/scenic/scenic_session.h7
-rw-r--r--chromium/ui/ozone/platform/scenic/scenic_surface_factory.cc11
-rw-r--r--chromium/ui/ozone/platform/scenic/scenic_surface_factory.h5
-rw-r--r--chromium/ui/ozone/platform/scenic/scenic_window.cc188
-rw-r--r--chromium/ui/ozone/platform/scenic/scenic_window.h29
-rw-r--r--chromium/ui/ozone/platform/scenic/scenic_window_manager.cc11
-rw-r--r--chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.cc132
-rw-r--r--chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.h49
-rw-r--r--chromium/ui/ozone/platform/scenic/vulkan_magma.h159
-rw-r--r--chromium/ui/ozone/platform/wayland/BUILD.gn22
-rw-r--r--chromium/ui/ozone/platform/wayland/DEPS9
-rw-r--r--chromium/ui/ozone/platform/wayland/client_native_pixmap_factory_wayland.cc6
-rw-r--r--chromium/ui/ozone/platform/wayland/fake_server.cc208
-rw-r--r--chromium/ui/ozone/platform/wayland/fake_server.h57
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc6
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc34
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h6
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.cc10
-rw-r--r--chromium/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.h13
-rw-r--r--chromium/ui/ozone/platform/wayland/ozone_platform_wayland.cc32
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_buffer_manager.cc295
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_buffer_manager.h116
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_connection.cc133
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_connection.h62
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_connection_unittest.cc52
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_data_device.cc362
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_data_device.h98
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_data_device_unittest.cc60
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_data_offer.cc52
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_data_offer.h18
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_data_source.cc99
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_data_source.h22
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_input_method_context.cc151
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_input_method_context.h59
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_input_method_context_factory.cc39
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_input_method_context_factory.h38
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_input_method_context_unittest.cc140
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_keyboard.cc6
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_native_display_delegate.cc105
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_native_display_delegate.h65
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_object.cc33
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_object.h28
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_output.cc73
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_output.h35
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_output_manager.cc117
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_output_manager.h59
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_pointer.cc21
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_pointer.h1
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_screen.cc107
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_screen.h62
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_screen_unittest.cc187
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_surface_factory.cc10
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_surface_factory.h17
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_util.cc91
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_util.h18
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_window.cc55
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_window.h27
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_window_unittest.cc32
-rw-r--r--chromium/ui/ozone/platform/wayland/xdg_surface_wrapper_v5.cc17
-rw-r--r--chromium/ui/ozone/platform/wayland/xdg_surface_wrapper_v6.cc19
-rw-r--r--chromium/ui/ozone/platform/wayland/zwp_text_input_wrapper.h74
-rw-r--r--chromium/ui/ozone/platform/wayland/zwp_text_input_wrapper_v1.cc197
-rw-r--r--chromium/ui/ozone/platform/wayland/zwp_text_input_wrapper_v1.h106
-rw-r--r--chromium/ui/ozone/public/input_controller.cc163
-rw-r--r--chromium/ui/ozone/public/interfaces/wayland/BUILD.gn1
-rw-r--r--chromium/ui/ozone/public/interfaces/wayland/wayland_connection.mojom8
-rw-r--r--chromium/ui/ozone/public/ozone_platform.cc2
-rw-r--r--chromium/ui/ozone/public/ozone_platform.h5
-rw-r--r--chromium/ui/ozone/public/ozone_switches.cc3
-rw-r--r--chromium/ui/ozone/public/ozone_switches.h2
-rw-r--r--chromium/ui/platform_window/BUILD.gn2
-rw-r--r--chromium/ui/platform_window/DEPS3
-rw-r--r--chromium/ui/platform_window/android/java/src/org/chromium/ui/PlatformImeControllerAndroid.java107
-rw-r--r--chromium/ui/platform_window/android/java/src/org/chromium/ui/PlatformWindowAndroid.java207
-rw-r--r--chromium/ui/platform_window/android/platform_window_android.cc4
-rw-r--r--chromium/ui/platform_window/platform_window.h3
-rw-r--r--chromium/ui/platform_window/platform_window_handler/BUILD.gn22
-rw-r--r--chromium/ui/platform_window/platform_window_handler/DEPS4
-rw-r--r--chromium/ui/platform_window/platform_window_handler/wm_move_resize_handler.cc28
-rw-r--r--chromium/ui/platform_window/platform_window_handler/wm_move_resize_handler.h62
-rw-r--r--chromium/ui/platform_window/platform_window_handler/wm_platform_export.h32
-rw-r--r--chromium/ui/shell_dialogs/base_shell_dialog_win.cc37
-rw-r--r--chromium/ui/shell_dialogs/base_shell_dialog_win.h37
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog_android.cc9
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog_android.h5
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog_win.cc5
-rw-r--r--chromium/ui/snapshot/snapshot_aura_unittest.cc7
-rw-r--r--chromium/ui/strings/translations/ui_strings_am.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_ar.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_bg.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_bn.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_ca.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_cs.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_da.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_de.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_el.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_en-GB.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_es-419.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_es.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_et.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_fa.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_fi.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_fil.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_fr.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_gu.xtb13
-rw-r--r--chromium/ui/strings/translations/ui_strings_hi.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_hr.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_hu.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_id.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_it.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_iw.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_ja.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_kn.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_ko.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_lt.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_lv.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_ml.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_mr.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_ms.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_nl.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_no.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_pl.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_pt-BR.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_pt-PT.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_ro.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_ru.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_sk.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_sl.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_sr.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_sv.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_sw.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_ta.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_te.xtb9
-rw-r--r--chromium/ui/strings/translations/ui_strings_th.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_tr.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_uk.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_vi.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_zh-CN.xtb3
-rw-r--r--chromium/ui/strings/translations/ui_strings_zh-TW.xtb3
-rw-r--r--chromium/ui/strings/ui_strings.grd12
-rw-r--r--chromium/ui/strings/ui_strings_grd/IDS_APP_ACCNAME_COLOR_CHOOSER_HEX_INPUT.png.sha11
-rw-r--r--chromium/ui/strings/ui_strings_grd/OWNERS1
-rw-r--r--chromium/ui/views/BUILD.gn75
-rw-r--r--chromium/ui/views/DEPS2
-rw-r--r--chromium/ui/views/OWNERS3
-rw-r--r--chromium/ui/views/accessibility/ax_aura_obj_cache.cc40
-rw-r--r--chromium/ui/views/accessibility/ax_aura_obj_cache.h14
-rw-r--r--chromium/ui/views/accessibility/ax_root_obj_wrapper.cc115
-rw-r--r--chromium/ui/views/accessibility/ax_root_obj_wrapper.h60
-rw-r--r--chromium/ui/views/accessibility/ax_system_caret_win_interactive_uitest.cc204
-rw-r--r--chromium/ui/views/accessibility/ax_window_obj_wrapper.cc11
-rw-r--r--chromium/ui/views/accessibility/view_accessibility_utils.cc44
-rw-r--r--chromium/ui/views/accessibility/view_accessibility_utils.h29
-rw-r--r--chromium/ui/views/accessibility/view_ax_platform_node_delegate.cc48
-rw-r--r--chromium/ui/views/accessibility/view_ax_platform_node_delegate.h6
-rw-r--r--chromium/ui/views/accessible_pane_view.cc3
-rw-r--r--chromium/ui/views/accessible_pane_view_unittest.cc33
-rw-r--r--chromium/ui/views/animation/ink_drop_host_view.cc4
-rw-r--r--chromium/ui/views/animation/ink_drop_mask.cc16
-rw-r--r--chromium/ui/views/animation/ink_drop_mask.h21
-rw-r--r--chromium/ui/views/bubble/OWNERS1
-rw-r--r--chromium/ui/views/bubble/bubble_border.cc31
-rw-r--r--chromium/ui/views/bubble/bubble_border.h3
-rw-r--r--chromium/ui/views/bubble/bubble_border_unittest.cc9
-rw-r--r--chromium/ui/views/bubble/bubble_dialog_delegate_view.cc76
-rw-r--r--chromium/ui/views/bubble/bubble_dialog_delegate_view.h19
-rw-r--r--chromium/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc62
-rw-r--r--chromium/ui/views/bubble/bubble_frame_view.cc21
-rw-r--r--chromium/ui/views/bubble/bubble_frame_view.h11
-rw-r--r--chromium/ui/views/bubble/bubble_frame_view_unittest.cc31
-rw-r--r--chromium/ui/views/bubble/info_bubble.cc2
-rw-r--r--chromium/ui/views/bubble/tooltip_icon.cc2
-rw-r--r--chromium/ui/views/bubble/tray_bubble_view.cc496
-rw-r--r--chromium/ui/views/bubble/tray_bubble_view.h230
-rw-r--r--chromium/ui/views/cocoa/DEPS1
-rw-r--r--chromium/ui/views/cocoa/bridge_factory_host.cc35
-rw-r--r--chromium/ui/views/cocoa/bridge_factory_host.h47
-rw-r--r--chromium/ui/views/cocoa/bridged_native_widget_host.h152
-rw-r--r--chromium/ui/views/cocoa/bridged_native_widget_host_impl.h228
-rw-r--r--chromium/ui/views/cocoa/bridged_native_widget_host_impl.mm500
-rw-r--r--chromium/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm4
-rw-r--r--chromium/ui/views/cocoa/bridged_native_widget_owner.h44
-rw-r--r--chromium/ui/views/cocoa/bridged_native_widget_unittest.mm198
-rw-r--r--chromium/ui/views/cocoa/cocoa_mouse_capture_unittest.mm8
-rw-r--r--chromium/ui/views/cocoa/drag_drop_client_mac.h29
-rw-r--r--chromium/ui/views/cocoa/drag_drop_client_mac.mm6
-rw-r--r--chromium/ui/views/cocoa/drag_drop_client_mac_unittest.mm14
-rw-r--r--chromium/ui/views/cocoa/tooltip_manager_mac.h15
-rw-r--r--chromium/ui/views/cocoa/tooltip_manager_mac.mm26
-rw-r--r--chromium/ui/views/cocoa/widget_owner_nswindow_adapter.h53
-rw-r--r--chromium/ui/views/cocoa/widget_owner_nswindow_adapter.mm166
-rw-r--r--chromium/ui/views/color_chooser/color_chooser_view.cc4
-rw-r--r--chromium/ui/views/controls/animated_image_view.cc139
-rw-r--r--chromium/ui/views/controls/animated_image_view.h91
-rw-r--r--chromium/ui/views/controls/button/button.cc6
-rw-r--r--chromium/ui/views/controls/button/button.h3
-rw-r--r--chromium/ui/views/controls/button/checkbox.cc5
-rw-r--r--chromium/ui/views/controls/button/image_button_factory.cc3
-rw-r--r--chromium/ui/views/controls/button/label_button_unittest.cc3
-rw-r--r--chromium/ui/views/controls/button/md_text_button.cc10
-rw-r--r--chromium/ui/views/controls/button/radio_button.cc2
-rw-r--r--chromium/ui/views/controls/focus_ring.cc6
-rw-r--r--chromium/ui/views/controls/focus_ring.h3
-rw-r--r--chromium/ui/views/controls/image_view.cc133
-rw-r--r--chromium/ui/views/controls/image_view.h66
-rw-r--r--chromium/ui/views/controls/image_view_base.cc160
-rw-r--r--chromium/ui/views/controls/image_view_base.h94
-rw-r--r--chromium/ui/views/controls/image_view_unittest.cc19
-rw-r--r--chromium/ui/views/controls/label_unittest.cc9
-rw-r--r--chromium/ui/views/controls/menu/menu_closure_animation_mac.h21
-rw-r--r--chromium/ui/views/controls/menu/menu_closure_animation_mac.mm12
-rw-r--r--chromium/ui/views/controls/menu/menu_config.cc5
-rw-r--r--chromium/ui/views/controls/menu/menu_config_win.cc13
-rw-r--r--chromium/ui/views/controls/menu/menu_controller.cc27
-rw-r--r--chromium/ui/views/controls/menu/menu_controller_unittest.cc8
-rw-r--r--chromium/ui/views/controls/menu/menu_host.cc2
-rw-r--r--chromium/ui/views/controls/menu/menu_item_view.cc15
-rw-r--r--chromium/ui/views/controls/menu/menu_item_view_unittest.cc7
-rw-r--r--chromium/ui/views/controls/menu/menu_pre_target_handler_aura.cc18
-rw-r--r--chromium/ui/views/controls/menu/menu_runner_cocoa_unittest.mm20
-rw-r--r--chromium/ui/views/controls/menu/menu_runner_impl.cc3
-rw-r--r--chromium/ui/views/controls/menu/submenu_view.cc8
-rw-r--r--chromium/ui/views/controls/menu/submenu_view.h3
-rw-r--r--chromium/ui/views/controls/native/native_view_host.cc6
-rw-r--r--chromium/ui/views/controls/native/native_view_host.h4
-rw-r--r--chromium/ui/views/controls/native/native_view_host_aura.cc15
-rw-r--r--chromium/ui/views/controls/native/native_view_host_aura.h1
-rw-r--r--chromium/ui/views/controls/native/native_view_host_mac.h26
-rw-r--r--chromium/ui/views/controls/native/native_view_host_mac.mm142
-rw-r--r--chromium/ui/views/controls/native/native_view_host_mac_unittest.mm42
-rw-r--r--chromium/ui/views/controls/native/native_view_host_wrapper.h4
-rw-r--r--chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.h4
-rw-r--r--chromium/ui/views/controls/styled_label.cc49
-rw-r--r--chromium/ui/views/controls/styled_label.h1
-rw-r--r--chromium/ui/views/controls/styled_label_unittest.cc29
-rw-r--r--chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc2
-rw-r--r--chromium/ui/views/controls/textfield/textfield.cc63
-rw-r--r--chromium/ui/views/controls/textfield/textfield.h8
-rw-r--r--chromium/ui/views/controls/textfield/textfield_model.cc9
-rw-r--r--chromium/ui/views/controls/textfield/textfield_unittest.cc41
-rw-r--r--chromium/ui/views/controls/views_text_services_context_menu.h5
-rw-r--r--chromium/ui/views/controls/views_text_services_context_menu_base.cc39
-rw-r--r--chromium/ui/views/controls/views_text_services_context_menu_base.h7
-rw-r--r--chromium/ui/views/controls/webview/unhandled_keyboard_event_handler_mac.mm2
-rw-r--r--chromium/ui/views/controls/webview/web_dialog_view.cc8
-rw-r--r--chromium/ui/views/controls/webview/web_dialog_view.h1
-rw-r--r--chromium/ui/views/controls/webview/webview.cc25
-rw-r--r--chromium/ui/views/controls/webview/webview.h9
-rw-r--r--chromium/ui/views/corewm/tooltip_controller.cc8
-rw-r--r--chromium/ui/views/corewm/tooltip_controller_unittest.cc6
-rw-r--r--chromium/ui/views/corewm/tooltip_win.cc56
-rw-r--r--chromium/ui/views/corewm/tooltip_win.h20
-rw-r--r--chromium/ui/views/event_utils.cc22
-rw-r--r--chromium/ui/views/event_utils.h28
-rw-r--r--chromium/ui/views/examples/BUILD.gn2
-rw-r--r--chromium/ui/views/examples/animated_image_view_example.cc143
-rw-r--r--chromium/ui/views/examples/animated_image_view_example.h29
-rw-r--r--chromium/ui/views/examples/examples_main.cc5
-rw-r--r--chromium/ui/views/examples/examples_window.cc16
-rw-r--r--chromium/ui/views/examples/examples_window.h7
-rw-r--r--chromium/ui/views/examples/examples_window_with_content.cc5
-rw-r--r--chromium/ui/views/examples/examples_window_with_content.h2
-rw-r--r--chromium/ui/views/examples/examples_with_content_main_exe.cc12
-rw-r--r--chromium/ui/views/examples/menu_example.cc2
-rw-r--r--chromium/ui/views/focus/focus_manager_unittest.cc6
-rw-r--r--chromium/ui/views/focus/widget_focus_manager.cc54
-rw-r--r--chromium/ui/views/focus/widget_focus_manager.h13
-rw-r--r--chromium/ui/views/layout/box_layout.cc4
-rw-r--r--chromium/ui/views/linux_ui/linux_ui.h4
-rw-r--r--chromium/ui/views/mus/ax_remote_host.cc46
-rw-r--r--chromium/ui/views/mus/ax_remote_host.h13
-rw-r--r--chromium/ui/views/mus/ax_remote_host_unittest.cc53
-rw-r--r--chromium/ui/views/mus/ax_tree_source_mus.cc7
-rw-r--r--chromium/ui/views/mus/ax_tree_source_mus.h6
-rw-r--r--chromium/ui/views/mus/ax_tree_source_mus_unittest.cc9
-rw-r--r--chromium/ui/views/mus/desktop_window_tree_host_mus.cc71
-rw-r--r--chromium/ui/views/mus/desktop_window_tree_host_mus.h1
-rw-r--r--chromium/ui/views/mus/desktop_window_tree_host_mus_unittest.cc45
-rw-r--r--chromium/ui/views/mus/drag_interactive_uitest.cc26
-rw-r--r--chromium/ui/views/mus/mus_client.cc4
-rw-r--r--chromium/ui/views/mus/mus_views_delegate.cc16
-rw-r--r--chromium/ui/views/mus/mus_views_delegate.h4
-rw-r--r--chromium/ui/views/mus/remote_view/remote_view_host.cc45
-rw-r--r--chromium/ui/views/mus/remote_view/remote_view_host.h6
-rw-r--r--chromium/ui/views/mus/remote_view/remote_view_host_unittest.cc15
-rw-r--r--chromium/ui/views/mus/views_mus_test_suite.cc38
-rw-r--r--chromium/ui/views/mus/views_mus_test_suite.h10
-rw-r--r--chromium/ui/views/painter.cc57
-rw-r--r--chromium/ui/views/painter.h9
-rw-r--r--chromium/ui/views/touchui/touch_selection_controller_impl.cc101
-rw-r--r--chromium/ui/views/touchui/touch_selection_controller_impl.h41
-rw-r--r--chromium/ui/views/view.cc18
-rw-r--r--chromium/ui/views/view.h1
-rw-r--r--chromium/ui/views/view_properties.cc3
-rw-r--r--chromium/ui/views/view_properties.h9
-rw-r--r--chromium/ui/views/views_delegate.cc28
-rw-r--r--chromium/ui/views/views_delegate.h19
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_capture_client.cc3
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc5
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc3
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drop_target_win.cc2
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc8
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc10
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc6
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_ozone.cc12
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc8
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc53
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h10
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform_interactive_uitest.cc272
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc23
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h8
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc8
-rw-r--r--chromium/ui/views/widget/desktop_aura/window_event_filter.cc44
-rw-r--r--chromium/ui/views/widget/desktop_aura/window_event_filter.h14
-rw-r--r--chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc9
-rw-r--r--chromium/ui/views/widget/native_widget_aura.cc22
-rw-r--r--chromium/ui/views/widget/native_widget_mac.h28
-rw-r--r--chromium/ui/views/widget/native_widget_mac.mm291
-rw-r--r--chromium/ui/views/widget/native_widget_mac_unittest.mm266
-rw-r--r--chromium/ui/views/widget/widget.cc6
-rw-r--r--chromium/ui/views/widget/widget_unittest.cc15
-rw-r--r--chromium/ui/views/widget/widget_utils_mac.mm4
-rw-r--r--chromium/ui/views/widget/window_reorderer.cc5
-rw-r--r--chromium/ui/views/widget/window_reorderer_unittest.cc5
-rw-r--r--chromium/ui/views/win/hwnd_message_handler.cc22
-rw-r--r--chromium/ui/views/win/pen_event_processor.cc11
-rw-r--r--chromium/ui/views/window/custom_frame_view.cc7
-rw-r--r--chromium/ui/views/window/dialog_client_view.cc15
-rw-r--r--chromium/ui/views/window/dialog_client_view.h10
-rw-r--r--chromium/ui/views/window/dialog_client_view_unittest.cc25
-rw-r--r--chromium/ui/views_bridge_mac/BUILD.gn27
-rw-r--r--chromium/ui/views_bridge_mac/DEPS13
-rw-r--r--chromium/ui/views_bridge_mac/bridge_factory_impl.h41
-rw-r--r--chromium/ui/views_bridge_mac/bridge_factory_impl.mm86
-rw-r--r--chromium/ui/views_bridge_mac/bridged_content_view.h (renamed from chromium/ui/views/cocoa/bridged_content_view.h)23
-rw-r--r--chromium/ui/views_bridge_mac/bridged_content_view.mm (renamed from chromium/ui/views/cocoa/bridged_content_view.mm)197
-rw-r--r--chromium/ui/views_bridge_mac/bridged_content_view_touch_bar.mm (renamed from chromium/ui/views/cocoa/bridged_content_view_touch_bar.mm)6
-rw-r--r--chromium/ui/views_bridge_mac/bridged_native_widget_host_helper.h67
-rw-r--r--chromium/ui/views_bridge_mac/bridged_native_widget_impl.h (renamed from chromium/ui/views/cocoa/bridged_native_widget.h)197
-rw-r--r--chromium/ui/views_bridge_mac/bridged_native_widget_impl.mm (renamed from chromium/ui/views/cocoa/bridged_native_widget.mm)575
-rw-r--r--chromium/ui/views_bridge_mac/cocoa_mouse_capture.h (renamed from chromium/ui/views/cocoa/cocoa_mouse_capture.h)14
-rw-r--r--chromium/ui/views_bridge_mac/cocoa_mouse_capture.mm (renamed from chromium/ui/views/cocoa/cocoa_mouse_capture.mm)8
-rw-r--r--chromium/ui/views_bridge_mac/cocoa_mouse_capture_delegate.h (renamed from chromium/ui/views/cocoa/cocoa_mouse_capture_delegate.h)10
-rw-r--r--chromium/ui/views_bridge_mac/cocoa_window_move_loop.h (renamed from chromium/ui/views/cocoa/cocoa_window_move_loop.h)18
-rw-r--r--chromium/ui/views_bridge_mac/cocoa_window_move_loop.mm (renamed from chromium/ui/views/cocoa/cocoa_window_move_loop.mm)31
-rw-r--r--chromium/ui/views_bridge_mac/drag_drop_client.h37
-rw-r--r--chromium/ui/views_bridge_mac/mojo/bridge_factory.mojom20
-rw-r--r--chromium/ui/views_bridge_mac/mojo/bridged_native_widget.mojom52
-rw-r--r--chromium/ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom159
-rw-r--r--chromium/ui/views_bridge_mac/native_widget_mac_nswindow.h (renamed from chromium/ui/views/cocoa/native_widget_mac_nswindow.h)10
-rw-r--r--chromium/ui/views_bridge_mac/native_widget_mac_nswindow.mm (renamed from chromium/ui/views/cocoa/native_widget_mac_nswindow.mm)79
-rw-r--r--chromium/ui/views_bridge_mac/views_bridge_mac_export.h32
-rw-r--r--chromium/ui/views_bridge_mac/views_nswindow_delegate.h (renamed from chromium/ui/views/cocoa/views_nswindow_delegate.h)19
-rw-r--r--chromium/ui/views_bridge_mac/views_nswindow_delegate.mm (renamed from chromium/ui/views/cocoa/views_nswindow_delegate.mm)31
-rw-r--r--chromium/ui/views_bridge_mac/views_scrollbar_bridge.h (renamed from chromium/ui/views/cocoa/views_scrollbar_bridge.h)8
-rw-r--r--chromium/ui/views_bridge_mac/views_scrollbar_bridge.mm (renamed from chromium/ui/views/cocoa/views_scrollbar_bridge.mm)2
-rw-r--r--chromium/ui/views_bridge_mac/window_touch_bar_delegate.h (renamed from chromium/ui/views/cocoa/window_touch_bar_delegate.h)6
-rw-r--r--chromium/ui/views_content_client/views_content_client.h8
-rw-r--r--chromium/ui/views_content_client/views_content_client_main_parts.cc2
-rw-r--r--chromium/ui/web_dialogs/BUILD.gn2
-rw-r--r--chromium/ui/web_dialogs/web_dialog_delegate.cc4
-rw-r--r--chromium/ui/web_dialogs/web_dialog_delegate.h3
-rw-r--r--chromium/ui/webui/PLATFORM_OWNERS2
-rw-r--r--chromium/ui/webui/mojo_web_ui_controller.cc6
-rw-r--r--chromium/ui/webui/resources/cr_components/BUILD.gn5
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/BUILD.gn3
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/.eslintrc.js13
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/BUILD.gn129
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/OWNERS1
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/button_bar.html31
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/button_bar.js46
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/fake_mojo_service.html4
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/fake_mojo_service.js108
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/icons.html36
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/mojo_api.html10
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/mojo_api.js40
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.html67
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.js312
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_browser_proxy.html3
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_browser_proxy.js41
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_delegate.html4
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_delegate.js33
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_shared_css.html19
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/password_page.html51
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/password_page.js167
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_failed_page.html18
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_failed_page.js43
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_succeeded_icon_1x.pngbin0 -> 10988 bytes
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_succeeded_icon_2x.pngbin0 -> 24434 bytes
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_succeeded_page.html35
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_succeeded_page.js59
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_icon_1x.pngbin0 -> 8246 bytes
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_icon_2x.pngbin0 -> 18298 bytes
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.html135
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.js155
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/ui_page.html42
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/ui_page.js34
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/ui_page_container_behavior.html5
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/ui_page_container_behavior.js141
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_config.html2
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy.js3
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/BUILD.gn19
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/lock_screen_constants.html1
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/lock_screen_constants.js47
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html256
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.js60
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.html103
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.js377
-rw-r--r--chromium/ui/webui/resources/cr_components/cr_components_images.grdp21
-rw-r--r--chromium/ui/webui/resources/cr_components/cr_components_resources.grdp134
-rw-r--r--chromium/ui/webui/resources/cr_elements/BUILD.gn1
-rw-r--r--chromium/ui/webui/resources/cr_elements/README.md (renamed from chromium/ui/webui/resources/cr_elements/READE.md)0
-rw-r--r--chromium/ui/webui/resources/cr_elements/chromeos/network/cr_network_select.js2
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.html2
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js20
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_container_shadow_behavior.js2
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.js66
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_input/cr_input.html42
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_input/cr_input.js30
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_input/cr_input_style_css.html12
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field_behavior.js24
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html3
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.js2
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_slider/BUILD.gn4
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_slider/cr_slider.html227
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_slider/cr_slider.js518
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html1
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_view_manager/BUILD.gn19
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_view_manager/cr_view_manager.html26
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_view_manager/cr_view_manager.js115
-rw-r--r--chromium/ui/webui/resources/cr_elements/policy/BUILD.gn1
-rw-r--r--chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_behavior.js36
-rw-r--r--chromium/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js5
-rw-r--r--chromium/ui/webui/resources/cr_elements/policy/cr_tooltip_icon.js5
-rw-r--r--chromium/ui/webui/resources/cr_elements/shared_vars_css.html4
-rw-r--r--chromium/ui/webui/resources/cr_elements_resources.grdp6
-rw-r--r--chromium/ui/webui/resources/js/assert.js2
-rw-r--r--chromium/ui/webui/resources/js/cr/ui/dialogs.js21
-rw-r--r--chromium/ui/webui/resources/js/cr/ui/focus_grid.js2
-rw-r--r--chromium/ui/webui/resources/js/cr/ui/focus_row.js217
-rw-r--r--chromium/ui/webui/resources/js/util.js12
-rw-r--r--chromium/ui/webui/resources/js/webui_resource_test.js59
-rw-r--r--chromium/ui/webui/resources/webui_resources.grd1
-rw-r--r--chromium/ui/wm/BUILD.gn4
-rw-r--r--chromium/ui/wm/core/base_focus_rules.cc4
-rw-r--r--chromium/ui/wm/core/easy_resize_window_targeter.cc107
-rw-r--r--chromium/ui/wm/core/easy_resize_window_targeter.h30
-rw-r--r--chromium/ui/wm/core/easy_resize_window_targeter_unittest.cc66
-rw-r--r--chromium/ui/wm/core/transient_window_manager.cc11
-rw-r--r--chromium/ui/wm/core/transient_window_stacking_client.cc4
-rw-r--r--chromium/ui/wm/core/window_animations.cc25
-rw-r--r--chromium/ui/wm/core/window_animations.h10
-rw-r--r--chromium/ui/wm/core/window_animations_unittest.cc3
-rw-r--r--chromium/ui/wm/core/window_properties.cc19
-rw-r--r--chromium/ui/wm/core/window_properties.h28
-rw-r--r--chromium/ui/wm/public/BUILD.gn2
-rw-r--r--chromium/ui/wm/public/scoped_drag_drop_disabler.cc53
-rw-r--r--chromium/ui/wm/public/scoped_drag_drop_disabler.h45
1198 files changed, 32736 insertions, 18455 deletions
diff --git a/chromium/ui/accelerated_widget_mac/display_link_mac.cc b/chromium/ui/accelerated_widget_mac/display_link_mac.cc
index a20981063ac..81de0b1942a 100644
--- a/chromium/ui/accelerated_widget_mac/display_link_mac.cc
+++ b/chromium/ui/accelerated_widget_mac/display_link_mac.cc
@@ -31,6 +31,36 @@ struct ScopedTypeRefTraits<CVDisplayLinkRef> {
namespace ui {
+using DisplayLinkMap = std::map<CGDirectDisplayID, DisplayLinkMac*>;
+
+namespace {
+
+// The task runner to post tasks to from the display link thread. Note that this
+// is initialized with the very first DisplayLinkMac instance, and is never
+// changed (even, e.g, in tests that re-initialize the main thread task runner).
+// https://885329
+scoped_refptr<base::SingleThreadTaskRunner> GetMainThreadTaskRunner() {
+ static scoped_refptr<base::SingleThreadTaskRunner> task_runner =
+ base::ThreadTaskRunnerHandle::Get();
+ return task_runner;
+}
+
+// Each display link instance consumes a non-negligible number of cycles, so
+// make all display links on the same screen share the same object.
+//
+// Note that this is a weak map, holding non-owning pointers to the
+// DisplayLinkMac objects. DisplayLinkMac is a ref-counted class, and is
+// jointly owned by the various callers that got a copy by calling
+// GetForDisplay().
+//
+// ** This map may only be accessed from the main thread. **
+DisplayLinkMap& GetAllDisplayLinks() {
+ static base::NoDestructor<DisplayLinkMap> all_display_links;
+ return *all_display_links;
+}
+
+} // namespace
+
// static
scoped_refptr<DisplayLinkMac> DisplayLinkMac::GetForDisplay(
CGDirectDisplayID display_id) {
@@ -193,21 +223,6 @@ void DisplayLinkMac::StopDisplayLink() {
}
// static
-DisplayLinkMac::DisplayLinkMap& DisplayLinkMac::GetAllDisplayLinks() {
- DCHECK_EQ(base::ThreadTaskRunnerHandle::Get(), GetMainThreadTaskRunner());
- static base::NoDestructor<DisplayLinkMac::DisplayLinkMap> all_display_links;
- return *all_display_links;
-}
-
-// static
-scoped_refptr<base::SingleThreadTaskRunner>
-DisplayLinkMac::GetMainThreadTaskRunner() {
- static scoped_refptr<base::SingleThreadTaskRunner> task_runner =
- base::ThreadTaskRunnerHandle::Get();
- return task_runner;
-}
-
-// static
CVReturn DisplayLinkMac::DisplayLinkCallback(
CVDisplayLinkRef display_link,
const CVTimeStamp* now,
diff --git a/chromium/ui/accelerated_widget_mac/display_link_mac.h b/chromium/ui/accelerated_widget_mac/display_link_mac.h
index 2fce8971bed..b552163bff7 100644
--- a/chromium/ui/accelerated_widget_mac/display_link_mac.h
+++ b/chromium/ui/accelerated_widget_mac/display_link_mac.h
@@ -14,10 +14,6 @@
#include "base/time/time.h"
#include "ui/accelerated_widget_mac/accelerated_widget_mac_export.h"
-namespace base {
-class SingleThreadTaskRunner;
-}
-
namespace ui {
class ACCELERATED_WIDGET_MAC_EXPORT DisplayLinkMac
@@ -52,20 +48,6 @@ class ACCELERATED_WIDGET_MAC_EXPORT DisplayLinkMac
// Processes the display link callback.
void UpdateVSyncParameters(const CVTimeStamp& time);
- // Each display link instance consumes a non-negligible number of cycles, so
- // make all display links on the same screen share the same object. This map
- // must only be changed from the main thread.
- //
- // Note that this is a weak map, holding non-owning pointers to the
- // DisplayLinkMac objects. DisplayLinkMac is a ref-counted class, and is
- // jointly owned by the various callers that got a copy by calling
- // GetForDisplay().
- using DisplayLinkMap = std::map<CGDirectDisplayID, DisplayLinkMac*>;
- static DisplayLinkMap& GetAllDisplayLinks();
-
- // The task runner to post tasks to from the display link thread.
- static scoped_refptr<base::SingleThreadTaskRunner> GetMainThreadTaskRunner();
-
// Called by the system on the display link thread, and posts a call to
// DoUpdateVSyncParameters() to the UI thread.
static CVReturn DisplayLinkCallback(
diff --git a/chromium/ui/accessibility/BUILD.gn b/chromium/ui/accessibility/BUILD.gn
index b5471edc3ee..085e5d6da13 100644
--- a/chromium/ui/accessibility/BUILD.gn
+++ b/chromium/ui/accessibility/BUILD.gn
@@ -4,6 +4,7 @@
import("//build/config/linux/pkg_config.gni")
import("//build/config/features.gni")
+import("//build/config/jumbo.gni")
import("//build/config/ui.gni")
import("//mojo/public/tools/bindings/mojom.gni")
import("//services/service_manager/public/service_manifest.gni")
@@ -28,7 +29,7 @@ mojom("ax_enums_mojo") {
]
}
-component("accessibility") {
+jumbo_component("accessibility") {
sources = [
"ax_action_data.cc",
"ax_action_data.h",
@@ -41,6 +42,8 @@ component("accessibility") {
"ax_export.h",
"ax_host_delegate.cc",
"ax_host_delegate.h",
+ "ax_mode.h",
+ "ax_mode_observer.h",
"ax_node.cc",
"ax_node.h",
"ax_node_data.cc",
@@ -65,6 +68,8 @@ component("accessibility") {
"ax_tree_combiner.h",
"ax_tree_data.cc",
"ax_tree_data.h",
+ "ax_tree_id.cc",
+ "ax_tree_id.h",
"ax_tree_id_registry.cc",
"ax_tree_id_registry.h",
"ax_tree_serializer.cc",
@@ -75,6 +80,8 @@ component("accessibility") {
"platform/ax_android_constants.h",
"platform/ax_platform_node.cc",
"platform/ax_platform_node.h",
+ "platform/ax_platform_node_test_helper.cc",
+ "platform/ax_platform_node_test_helper.h",
"platform/ax_unique_id.cc",
"platform/ax_unique_id.h",
]
@@ -199,6 +206,7 @@ test("accessibility_unittests") {
"mojom/ax_event_mojom_traits_unittest.cc",
"mojom/ax_node_data_mojom_traits_unittest.cc",
"mojom/ax_tree_data_mojom_traits_unittest.cc",
+ "mojom/ax_tree_id_mojom_traits_unittest.cc",
"mojom/ax_tree_update_mojom_traits_unittest.cc",
"platform/ax_platform_node_unittest.cc",
"platform/ax_platform_node_unittest.h",
diff --git a/chromium/ui/accessibility/PRESUBMIT.py b/chromium/ui/accessibility/PRESUBMIT.py
index b0d403420f7..44659333f39 100644
--- a/chromium/ui/accessibility/PRESUBMIT.py
+++ b/chromium/ui/accessibility/PRESUBMIT.py
@@ -9,8 +9,8 @@ import os, re, json
AX_MOJOM = 'ui/accessibility/ax_enums.mojom'
AUTOMATION_IDL = 'chrome/common/extensions/api/automation.idl'
-AX_JS_FILE = 'content/browser/resources/accessibility/accessibility.js'
-AX_MODE_HEADER = 'ui/accessibility/ax_modes.h'
+AX_JS_FILE = 'chrome/browser/resources/accessibility/accessibility.js'
+AX_MODE_HEADER = 'ui/accessibility/ax_mode.h'
def InitialLowerCamelCase(unix_name):
words = unix_name.split('_')
diff --git a/chromium/ui/accessibility/ax_action_data.h b/chromium/ui/accessibility/ax_action_data.h
index bc3fc27c545..543c072caa6 100644
--- a/chromium/ui/accessibility/ax_action_data.h
+++ b/chromium/ui/accessibility/ax_action_data.h
@@ -7,6 +7,7 @@
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_export.h"
+#include "ui/accessibility/ax_tree_id.h"
#include "ui/gfx/geometry/rect.h"
namespace ui {
@@ -31,7 +32,7 @@ struct AX_EXPORT AXActionData {
ax::mojom::Action action = ax::mojom::Action::kNone;
// The ID of the tree that this action should be performed on.
- int target_tree_id = -1;
+ ui::AXTreeID target_tree_id = ui::AXTreeIDUnknown();
// The source extension id (if any) of this action.
std::string source_extension_id;
diff --git a/chromium/ui/accessibility/ax_enum_util.cc b/chromium/ui/accessibility/ax_enum_util.cc
index 2a38f68c589..654deaf19b9 100644
--- a/chromium/ui/accessibility/ax_enum_util.cc
+++ b/chromium/ui/accessibility/ax_enum_util.cc
@@ -54,6 +54,8 @@ const char* ToString(ax::mojom::Event event) {
return "liveRegionChanged";
case ax::mojom::Event::kLoadComplete:
return "loadComplete";
+ case ax::mojom::Event::kLoadStart:
+ return "loadStart";
case ax::mojom::Event::kLocationChanged:
return "locationChanged";
case ax::mojom::Event::kMediaStartedPlaying:
@@ -162,6 +164,8 @@ ax::mojom::Event ParseEvent(const char* event) {
return ax::mojom::Event::kLiveRegionChanged;
if (0 == strcmp(event, "loadComplete"))
return ax::mojom::Event::kLoadComplete;
+ if (0 == strcmp(event, "loadStart"))
+ return ax::mojom::Event::kLoadStart;
if (0 == strcmp(event, "locationChanged"))
return ax::mojom::Event::kLocationChanged;
if (0 == strcmp(event, "mediaStartedPlaying"))
@@ -1162,8 +1166,8 @@ const char* ToString(ax::mojom::StringAttribute string_attribute) {
return "ariaInvalidValue";
case ax::mojom::StringAttribute::kAutoComplete:
return "autoComplete";
- case ax::mojom::StringAttribute::kChromeChannel:
- return "chromeChannel";
+ case ax::mojom::StringAttribute::kChildTreeId:
+ return "childTreeId";
case ax::mojom::StringAttribute::kClassName:
return "className";
case ax::mojom::StringAttribute::kContainerLiveRelevant:
@@ -1216,8 +1220,8 @@ ax::mojom::StringAttribute ParseStringAttribute(const char* string_attribute) {
return ax::mojom::StringAttribute::kAriaInvalidValue;
if (0 == strcmp(string_attribute, "autoComplete"))
return ax::mojom::StringAttribute::kAutoComplete;
- if (0 == strcmp(string_attribute, "chromeChannel"))
- return ax::mojom::StringAttribute::kChromeChannel;
+ if (0 == strcmp(string_attribute, "childTreeId"))
+ return ax::mojom::StringAttribute::kChildTreeId;
if (0 == strcmp(string_attribute, "className"))
return ax::mojom::StringAttribute::kClassName;
if (0 == strcmp(string_attribute, "containerLiveRelevant"))
@@ -1333,8 +1337,6 @@ const char* ToString(ax::mojom::IntAttribute int_attribute) {
return "nextOnLineId";
case ax::mojom::IntAttribute::kPreviousOnLineId:
return "previousOnLineId";
- case ax::mojom::IntAttribute::kChildTreeId:
- return "childTreeId";
case ax::mojom::IntAttribute::kRestriction:
return "restriction";
case ax::mojom::IntAttribute::kSetSize:
@@ -1443,8 +1445,6 @@ ax::mojom::IntAttribute ParseIntAttribute(const char* int_attribute) {
return ax::mojom::IntAttribute::kNextOnLineId;
if (0 == strcmp(int_attribute, "previousOnLineId"))
return ax::mojom::IntAttribute::kPreviousOnLineId;
- if (0 == strcmp(int_attribute, "childTreeId"))
- return ax::mojom::IntAttribute::kChildTreeId;
if (0 == strcmp(int_attribute, "restriction"))
return ax::mojom::IntAttribute::kRestriction;
if (0 == strcmp(int_attribute, "setSize"))
@@ -1592,8 +1592,6 @@ const char* ToString(ax::mojom::IntListAttribute int_list_attribute) {
return "labelledbyIds";
case ax::mojom::IntListAttribute::kRadioGroupIds:
return "radioGroupIds";
- case ax::mojom::IntListAttribute::kLineBreaks:
- return "lineBreaks";
case ax::mojom::IntListAttribute::kMarkerTypes:
return "markerTypes";
case ax::mojom::IntListAttribute::kMarkerStarts:
@@ -1631,8 +1629,6 @@ ax::mojom::IntListAttribute ParseIntListAttribute(
return ax::mojom::IntListAttribute::kLabelledbyIds;
if (0 == strcmp(int_list_attribute, "radioGroupIds"))
return ax::mojom::IntListAttribute::kRadioGroupIds;
- if (0 == strcmp(int_list_attribute, "lineBreaks"))
- return ax::mojom::IntListAttribute::kLineBreaks;
if (0 == strcmp(int_list_attribute, "markerTypes"))
return ax::mojom::IntListAttribute::kMarkerTypes;
if (0 == strcmp(int_list_attribute, "markerStarts"))
@@ -2155,12 +2151,16 @@ const char* ToString(ax::mojom::NameFrom name_from) {
return "attribute";
case ax::mojom::NameFrom::kAttributeExplicitlyEmpty:
return "attributeExplicitlyEmpty";
+ case ax::mojom::NameFrom::kCaption:
+ return "caption";
case ax::mojom::NameFrom::kContents:
return "contents";
case ax::mojom::NameFrom::kPlaceholder:
return "placeholder";
case ax::mojom::NameFrom::kRelatedElement:
return "relatedElement";
+ case ax::mojom::NameFrom::kTitle:
+ return "title";
case ax::mojom::NameFrom::kValue:
return "value";
}
@@ -2177,12 +2177,16 @@ ax::mojom::NameFrom ParseNameFrom(const char* name_from) {
return ax::mojom::NameFrom::kAttribute;
if (0 == strcmp(name_from, "attributeExplicitlyEmpty"))
return ax::mojom::NameFrom::kAttributeExplicitlyEmpty;
+ if (0 == strcmp(name_from, "caption"))
+ return ax::mojom::NameFrom::kCaption;
if (0 == strcmp(name_from, "contents"))
return ax::mojom::NameFrom::kContents;
if (0 == strcmp(name_from, "placeholder"))
return ax::mojom::NameFrom::kPlaceholder;
if (0 == strcmp(name_from, "relatedElement"))
return ax::mojom::NameFrom::kRelatedElement;
+ if (0 == strcmp(name_from, "title"))
+ return ax::mojom::NameFrom::kTitle;
if (0 == strcmp(name_from, "value"))
return ax::mojom::NameFrom::kValue;
return ax::mojom::NameFrom::kNone;
diff --git a/chromium/ui/accessibility/ax_enums.mojom b/chromium/ui/accessibility/ax_enums.mojom
index 7469bfdfd21..2c35cf14722 100644
--- a/chromium/ui/accessibility/ax_enums.mojom
+++ b/chromium/ui/accessibility/ax_enums.mojom
@@ -49,6 +49,7 @@ enum Event {
kLiveRegionCreated, // Implicit
kLiveRegionChanged, // Web
kLoadComplete, // Web
+ kLoadStart, // Web / AuraLinux
kLocationChanged, // Web
kMediaStartedPlaying, // Native / Automation
kMediaStoppedPlaying, // Native / Automation
@@ -426,7 +427,7 @@ enum StringAttribute {
// Only used when invalid_state == invalid_state_other.
kAriaInvalidValue,
kAutoComplete,
- kChromeChannel, // Native / Automation
+ kChildTreeId,
kClassName, // Native / Android
kContainerLiveRelevant,
kContainerLiveStatus,
@@ -511,9 +512,6 @@ enum IntAttribute {
kNextOnLineId,
kPreviousOnLineId,
- // Identifies a child tree which this node hosts.
- kChildTreeId,
-
// Input restriction, if any, such as readonly or disabled.
// Of type AXRestriction, see below.
// No value or enabled control or other object that is not disabled.
@@ -632,11 +630,6 @@ enum IntListAttribute {
kLabelledbyIds,
kRadioGroupIds,
- // For static text. Character indices where line breaks occur. Note that
- // this attribute is only available on Chrome OS and will be deprecated
- // soon.
- kLineBreaks,
-
// For static text. These int lists must be the same size; they represent
// the start and end character offset of each marker. Examples of markers
// include spelling and grammar errors, and find-in-page matches.
@@ -816,9 +809,11 @@ enum NameFrom {
kUninitialized,
kAttribute,
kAttributeExplicitlyEmpty,
+ kCaption,
kContents,
kPlaceholder,
kRelatedElement,
+ kTitle,
kValue,
};
diff --git a/chromium/ui/accessibility/ax_event_generator.cc b/chromium/ui/accessibility/ax_event_generator.cc
index 25dd625a1fa..ed747ec39cc 100644
--- a/chromium/ui/accessibility/ax_event_generator.cc
+++ b/chromium/ui/accessibility/ax_event_generator.cc
@@ -304,8 +304,11 @@ void AXEventGenerator::OnTreeDataChanged(AXTree* tree,
const ui::AXTreeData& new_tree_data) {
DCHECK_EQ(tree_, tree);
- if (new_tree_data.loaded && !old_tree_data.loaded)
+ if (new_tree_data.loaded && !old_tree_data.loaded &&
+ ShouldFireLoadEvents(tree->root())) {
AddEvent(tree->root(), Event::LOAD_COMPLETE);
+ }
+
if (new_tree_data.sel_anchor_object_id !=
old_tree_data.sel_anchor_object_id ||
new_tree_data.sel_anchor_offset != old_tree_data.sel_anchor_offset ||
@@ -355,8 +358,12 @@ void AXEventGenerator::OnAtomicUpdateFinished(
const std::vector<Change>& changes) {
DCHECK_EQ(tree_, tree);
- if (root_changed && tree->data().loaded)
- AddEvent(tree->root(), Event::LOAD_COMPLETE);
+ if (root_changed && ShouldFireLoadEvents(tree->root())) {
+ if (tree->data().loaded)
+ AddEvent(tree->root(), Event::LOAD_COMPLETE);
+ else
+ AddEvent(tree->root(), Event::LOAD_START);
+ }
for (const auto& change : changes) {
if ((change.type == NODE_CREATED || change.type == SUBTREE_CREATED)) {
@@ -450,4 +457,11 @@ void AXEventGenerator::FireRelationSourceEvents(AXTree* tree,
tree->intlist_reverse_relations().end(), callback);
}
+// Attempts to suppress load-related events that we presume no AT will be
+// interested in under any circumstances, such as pages which have no size.
+bool AXEventGenerator::ShouldFireLoadEvents(AXNode* node) {
+ const AXNodeData& data = node->data();
+ return data.location.width() || data.location.height();
+}
+
} // namespace ui
diff --git a/chromium/ui/accessibility/ax_event_generator.h b/chromium/ui/accessibility/ax_event_generator.h
index cc89b5d7e22..4e84982bcf9 100644
--- a/chromium/ui/accessibility/ax_event_generator.h
+++ b/chromium/ui/accessibility/ax_event_generator.h
@@ -35,6 +35,7 @@ class AX_EXPORT AXEventGenerator : public AXTreeDelegate {
LIVE_REGION_CREATED,
LIVE_REGION_NODE_CHANGED, // Fired on a node within a live region.
LOAD_COMPLETE,
+ LOAD_START,
MENU_ITEM_SELECTED,
NAME_CHANGED,
OTHER_ATTRIBUTE_CHANGED,
@@ -186,6 +187,7 @@ class AX_EXPORT AXEventGenerator : public AXTreeDelegate {
void FireLiveRegionEvents(AXNode* node);
void FireActiveDescendantEvents();
void FireRelationSourceEvents(AXTree* tree, AXNode* target_node);
+ bool ShouldFireLoadEvents(AXNode* node);
AXTree* tree_ = nullptr; // Not owned.
std::map<AXNode*, std::set<EventParams>> tree_events_;
diff --git a/chromium/ui/accessibility/ax_event_generator_unittest.cc b/chromium/ui/accessibility/ax_event_generator_unittest.cc
index 7ed3e0a6a41..99db15e9015 100644
--- a/chromium/ui/accessibility/ax_event_generator_unittest.cc
+++ b/chromium/ui/accessibility/ax_event_generator_unittest.cc
@@ -62,6 +62,9 @@ std::string DumpEvents(AXEventGenerator* generator) {
case AXEventGenerator::Event::LOAD_COMPLETE:
event_name = "LOAD_COMPLETE";
break;
+ case AXEventGenerator::Event::LOAD_START:
+ event_name = "LOAD_START";
+ break;
case AXEventGenerator::Event::MENU_ITEM_SELECTED:
event_name = "MENU_ITEM_SELECTED";
break;
@@ -118,6 +121,7 @@ TEST(AXEventGeneratorTest, LoadCompleteSameTree) {
initial_state.root_id = 1;
initial_state.nodes.resize(1);
initial_state.nodes[0].id = 1;
+ initial_state.nodes[0].location = gfx::RectF(0, 0, 800, 600);
initial_state.has_tree_data = true;
AXTree tree(initial_state);
@@ -142,10 +146,55 @@ TEST(AXEventGeneratorTest, LoadCompleteNewTree) {
load_complete_update.root_id = 2;
load_complete_update.nodes.resize(1);
load_complete_update.nodes[0].id = 2;
+ load_complete_update.nodes[0].location = gfx::RectF(0, 0, 800, 600);
load_complete_update.has_tree_data = true;
load_complete_update.tree_data.loaded = true;
EXPECT_TRUE(tree.Unserialize(load_complete_update));
EXPECT_EQ("LOAD_COMPLETE on 2", DumpEvents(&event_generator));
+
+ // Load complete should not be emitted for sizeless roots.
+ load_complete_update.root_id = 3;
+ load_complete_update.nodes.resize(1);
+ load_complete_update.nodes[0].id = 3;
+ load_complete_update.nodes[0].location = gfx::RectF(0, 0, 0, 0);
+ load_complete_update.has_tree_data = true;
+ load_complete_update.tree_data.loaded = true;
+ EXPECT_TRUE(tree.Unserialize(load_complete_update));
+ EXPECT_EQ("", DumpEvents(&event_generator));
+
+ // TODO(accessibility): http://crbug.com/888758
+ // Load complete should not be emitted for chrome-search URLs.
+ load_complete_update.root_id = 4;
+ load_complete_update.nodes.resize(1);
+ load_complete_update.nodes[0].id = 4;
+ load_complete_update.nodes[0].location = gfx::RectF(0, 0, 800, 600);
+ load_complete_update.nodes[0].AddStringAttribute(
+ ax::mojom::StringAttribute::kUrl, "chrome-search://foo");
+ load_complete_update.has_tree_data = true;
+ load_complete_update.tree_data.loaded = true;
+ EXPECT_TRUE(tree.Unserialize(load_complete_update));
+ EXPECT_EQ("LOAD_COMPLETE on 4", DumpEvents(&event_generator));
+}
+
+TEST(AXEventGeneratorTest, LoadStart) {
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(1);
+ initial_state.nodes[0].id = 1;
+ initial_state.nodes[0].location = gfx::RectF(0, 0, 800, 600);
+ initial_state.has_tree_data = true;
+ AXTree tree(initial_state);
+
+ AXEventGenerator event_generator(&tree);
+ AXTreeUpdate load_start_update;
+ load_start_update.root_id = 2;
+ load_start_update.nodes.resize(1);
+ load_start_update.nodes[0].id = 2;
+ load_start_update.nodes[0].location = gfx::RectF(0, 0, 800, 600);
+ load_start_update.has_tree_data = true;
+ load_start_update.tree_data.loaded = false;
+ EXPECT_TRUE(tree.Unserialize(load_start_update));
+ EXPECT_EQ("LOAD_START on 2", DumpEvents(&event_generator));
}
TEST(AXEventGeneratorTest, DocumentSelectionChanged) {
diff --git a/chromium/ui/accessibility/ax_host_delegate.cc b/chromium/ui/accessibility/ax_host_delegate.cc
index a7ecd1b0cda..9e7104d488e 100644
--- a/chromium/ui/accessibility/ax_host_delegate.cc
+++ b/chromium/ui/accessibility/ax_host_delegate.cc
@@ -11,7 +11,7 @@ namespace ui {
AXHostDelegate::AXHostDelegate()
: tree_id_(AXTreeIDRegistry::GetInstance()->GetOrCreateAXTreeID(this)) {}
-AXHostDelegate::AXHostDelegate(int32_t tree_id) : tree_id_(tree_id) {
+AXHostDelegate::AXHostDelegate(AXTreeID tree_id) : tree_id_(tree_id) {
AXTreeIDRegistry::GetInstance()->SetDelegateForID(this, tree_id);
}
diff --git a/chromium/ui/accessibility/ax_host_delegate.h b/chromium/ui/accessibility/ax_host_delegate.h
index 785df2594c5..4d4960914cf 100644
--- a/chromium/ui/accessibility/ax_host_delegate.h
+++ b/chromium/ui/accessibility/ax_host_delegate.h
@@ -5,9 +5,8 @@
#ifndef UI_ACCESSIBILITY_AX_HOST_DELEGATE_H_
#define UI_ACCESSIBILITY_AX_HOST_DELEGATE_H_
-#include <stdint.h>
-
#include "ui/accessibility/ax_export.h"
+#include "ui/accessibility/ax_tree_id.h"
namespace ui {
@@ -26,23 +25,23 @@ class AX_EXPORT AXHostDelegate {
// Handle an action from an accessibility client.
virtual void PerformAction(const ui::AXActionData& data) = 0;
+ // A tree id appropriate for annotating events sent to an accessibility
+ // client.
+ AXTreeID tree_id() const { return tree_id_; }
+
protected:
// A delegate with an automatically assigned tree id.
AXHostDelegate();
// A delegate with an explicit tree id. The caller is responsible for ensuring
// the uniqueness of the id.
- explicit AXHostDelegate(int32_t tree_id);
-
- // A tree id appropriate for annotating events sent to an accessibility
- // client.
- int32_t tree_id() const { return tree_id_; }
+ explicit AXHostDelegate(AXTreeID tree_id);
private:
// Register or unregister this class with |AXTreeIDRegistry|.
void UpdateActiveState(bool active);
- int32_t tree_id_;
+ AXTreeID tree_id_;
};
} // namespace ui
diff --git a/chromium/ui/accessibility/ax_modes.h b/chromium/ui/accessibility/ax_mode.h
index b6015763e1e..ac52a5ecc5c 100644
--- a/chromium/ui/accessibility/ax_modes.h
+++ b/chromium/ui/accessibility/ax_mode.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_ACCESSIBILITY_PLATFORM_AX_MODE_H_
-#define UI_ACCESSIBILITY_PLATFORM_AX_MODE_H_
+#ifndef UI_ACCESSIBILITY_AX_MODE_H_
+#define UI_ACCESSIBILITY_AX_MODE_H_
namespace ui {
@@ -89,4 +89,4 @@ static constexpr AXMode kAXModeComplete(AXMode::kNativeAPIs |
} // namespace ui
-#endif // UI_ACCESSIBILITY_PLATFORM_AX_MODE_H_
+#endif // UI_ACCESSIBILITY_AX_MODE_H_
diff --git a/chromium/ui/accessibility/ax_mode_observer.h b/chromium/ui/accessibility/ax_mode_observer.h
index f517c36d7bb..1f2f2afa18a 100644
--- a/chromium/ui/accessibility/ax_mode_observer.h
+++ b/chromium/ui/accessibility/ax_mode_observer.h
@@ -6,7 +6,7 @@
#define UI_ACCESSIBILITY_PLATFORM_AX_MODE_OBSERVER_H_
#include "ui/accessibility/ax_export.h"
-#include "ui/accessibility/ax_modes.h"
+#include "ui/accessibility/ax_mode.h"
namespace ui {
diff --git a/chromium/ui/accessibility/ax_node_data.cc b/chromium/ui/accessibility/ax_node_data.cc
index 159933ca13d..9f72d3026df 100644
--- a/chromium/ui/accessibility/ax_node_data.cc
+++ b/chromium/ui/accessibility/ax_node_data.cc
@@ -9,6 +9,7 @@
#include <algorithm>
#include <set>
+#include "base/no_destructor.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
@@ -132,7 +133,6 @@ bool IsNodeIdIntAttribute(ax::mojom::IntAttribute attr) {
case ax::mojom::IntAttribute::kHierarchicalLevel:
case ax::mojom::IntAttribute::kNameFrom:
case ax::mojom::IntAttribute::kDescriptionFrom:
- case ax::mojom::IntAttribute::kChildTreeId:
case ax::mojom::IntAttribute::kSetSize:
case ax::mojom::IntAttribute::kPosInSet:
case ax::mojom::IntAttribute::kColorValue:
@@ -174,7 +174,6 @@ bool IsNodeIdIntListAttribute(ax::mojom::IntListAttribute attr) {
// add a new attribute without explicitly considering whether it's
// a node id attribute or not.
case ax::mojom::IntListAttribute::kNone:
- case ax::mojom::IntListAttribute::kLineBreaks:
case ax::mojom::IntListAttribute::kMarkerTypes:
case ax::mojom::IntListAttribute::kMarkerStarts:
case ax::mojom::IntListAttribute::kMarkerEnds:
@@ -311,9 +310,9 @@ bool AXNodeData::HasStringAttribute(
const std::string& AXNodeData::GetStringAttribute(
ax::mojom::StringAttribute attribute) const {
- CR_DEFINE_STATIC_LOCAL(std::string, empty_string, ());
+ static base::NoDestructor<std::string> empty_string;
auto iter = FindInVectorOfPairs(attribute, string_attributes);
- return iter != string_attributes.end() ? iter->second : empty_string;
+ return iter != string_attributes.end() ? iter->second : *empty_string;
}
bool AXNodeData::GetStringAttribute(ax::mojom::StringAttribute attribute,
@@ -352,11 +351,11 @@ bool AXNodeData::HasIntListAttribute(
const std::vector<int32_t>& AXNodeData::GetIntListAttribute(
ax::mojom::IntListAttribute attribute) const {
- CR_DEFINE_STATIC_LOCAL(std::vector<int32_t>, empty_vector, ());
+ static base::NoDestructor<std::vector<int32_t>> empty_vector;
auto iter = FindInVectorOfPairs(attribute, intlist_attributes);
if (iter != intlist_attributes.end())
return iter->second;
- return empty_vector;
+ return *empty_vector;
}
bool AXNodeData::GetIntListAttribute(ax::mojom::IntListAttribute attribute,
@@ -378,11 +377,11 @@ bool AXNodeData::HasStringListAttribute(
const std::vector<std::string>& AXNodeData::GetStringListAttribute(
ax::mojom::StringListAttribute attribute) const {
- CR_DEFINE_STATIC_LOCAL(std::vector<std::string>, empty_vector, ());
+ static base::NoDestructor<std::vector<std::string>> empty_vector;
auto iter = FindInVectorOfPairs(attribute, stringlist_attributes);
if (iter != stringlist_attributes.end())
return iter->second;
- return empty_vector;
+ return *empty_vector;
}
bool AXNodeData::GetStringListAttribute(
@@ -567,6 +566,11 @@ void AXNodeData::AddAction(ax::mojom::Action action_enum) {
actions = ModifyFlag(actions, static_cast<uint32_t>(action_enum), true);
}
+void AXNodeData::RemoveState(ax::mojom::State state_enum) {
+ DCHECK_NE(state_enum, ax::mojom::State::kNone);
+ state = ModifyFlag(state, static_cast<uint32_t>(state_enum), false);
+}
+
std::string AXNodeData::ToString() const {
std::string result;
@@ -718,9 +722,6 @@ std::string AXNodeData::ToString() const {
case ax::mojom::IntAttribute::kPreviousOnLineId:
result += " previous_on_line_id=" + value;
break;
- case ax::mojom::IntAttribute::kChildTreeId:
- result += " child_tree_id=" + value;
- break;
case ax::mojom::IntAttribute::kColorValue:
result += base::StringPrintf(" color_value=&%X", int_attribute.second);
break;
@@ -915,8 +916,8 @@ std::string AXNodeData::ToString() const {
case ax::mojom::StringAttribute::kAutoComplete:
result += " autocomplete=" + value;
break;
- case ax::mojom::StringAttribute::kChromeChannel:
- result += " chrome_channel=" + value;
+ case ax::mojom::StringAttribute::kChildTreeId:
+ result += " child_tree_id=" + value;
break;
case ax::mojom::StringAttribute::kClassName:
result += " class_name=" + value;
@@ -1073,9 +1074,6 @@ std::string AXNodeData::ToString() const {
case ax::mojom::IntListAttribute::kRadioGroupIds:
result += " radio_group_ids=" + IntVectorToString(values);
break;
- case ax::mojom::IntListAttribute::kLineBreaks:
- result += " line_breaks=" + IntVectorToString(values);
- break;
case ax::mojom::IntListAttribute::kMarkerTypes: {
std::string types_str;
for (size_t i = 0; i < values.size(); ++i) {
diff --git a/chromium/ui/accessibility/ax_node_data.h b/chromium/ui/accessibility/ax_node_data.h
index 468b13fc775..c7d3320e7aa 100644
--- a/chromium/ui/accessibility/ax_node_data.h
+++ b/chromium/ui/accessibility/ax_node_data.h
@@ -134,6 +134,9 @@ struct AX_EXPORT AXNodeData {
void AddState(ax::mojom::State state_enum);
void AddAction(ax::mojom::Action action_enum);
+ // Remove bits in the given enum's corresponding bitfield.
+ void RemoveState(ax::mojom::State state_enum);
+
// Helper functions to get some common int attributes with some specific
// enum types:
ax::mojom::CheckedState GetCheckedState() const {
diff --git a/chromium/ui/accessibility/ax_node_position.cc b/chromium/ui/accessibility/ax_node_position.cc
index 9711f344677..3e522353332 100644
--- a/chromium/ui/accessibility/ax_node_position.cc
+++ b/chromium/ui/accessibility/ax_node_position.cc
@@ -33,13 +33,13 @@ base::string16 AXNodePosition::GetInnerText() const {
}
void AXNodePosition::AnchorChild(int child_index,
- int* tree_id,
+ AXTreeID* tree_id,
int32_t* child_id) const {
DCHECK(tree_id);
DCHECK(child_id);
if (!GetAnchor() || child_index < 0 || child_index >= AnchorChildCount()) {
- *tree_id = INVALID_TREE_ID;
+ *tree_id = AXTreeIDUnknown();
*child_id = INVALID_ANCHOR_ID;
return;
}
@@ -58,12 +58,12 @@ int AXNodePosition::AnchorIndexInParent() const {
return GetAnchor() ? GetAnchor()->index_in_parent() : INVALID_INDEX;
}
-void AXNodePosition::AnchorParent(int* tree_id, int32_t* parent_id) const {
+void AXNodePosition::AnchorParent(AXTreeID* tree_id, int32_t* parent_id) const {
DCHECK(tree_id);
DCHECK(parent_id);
if (!GetAnchor() || !GetAnchor()->parent()) {
- *tree_id = INVALID_TREE_ID;
+ *tree_id = AXTreeIDUnknown();
*parent_id = INVALID_ANCHOR_ID;
return;
}
@@ -73,7 +73,7 @@ void AXNodePosition::AnchorParent(int* tree_id, int32_t* parent_id) const {
*parent_id = parent->id();
}
-AXNode* AXNodePosition::GetNodeInTree(int tree_id, int32_t node_id) const {
+AXNode* AXNodePosition::GetNodeInTree(AXTreeID tree_id, int32_t node_id) const {
if (!tree_ || node_id == INVALID_ANCHOR_ID)
return nullptr;
return AXNodePosition::tree_->GetFromId(node_id);
diff --git a/chromium/ui/accessibility/ax_node_position.h b/chromium/ui/accessibility/ax_node_position.h
index ec8d7715b3e..e40fd12e6c3 100644
--- a/chromium/ui/accessibility/ax_node_position.h
+++ b/chromium/ui/accessibility/ax_node_position.h
@@ -32,12 +32,12 @@ class AX_EXPORT AXNodePosition : public AXPosition<AXNodePosition, AXNode> {
protected:
AXNodePosition(const AXNodePosition& other) = default;
void AnchorChild(int child_index,
- int* tree_id,
+ AXTreeID* tree_id,
int32_t* child_id) const override;
int AnchorChildCount() const override;
int AnchorIndexInParent() const override;
- void AnchorParent(int* tree_id, int32_t* parent_id) const override;
- AXNode* GetNodeInTree(int tree_id, int32_t node_id) const override;
+ void AnchorParent(AXTreeID* tree_id, int32_t* parent_id) const override;
+ AXNode* GetNodeInTree(AXTreeID tree_id, int32_t node_id) const override;
int MaxTextOffset() const override;
bool IsInWhiteSpace() const override;
std::vector<int32_t> GetWordStartOffsets() const override;
diff --git a/chromium/ui/accessibility/ax_node_position_unittest.cc b/chromium/ui/accessibility/ax_node_position_unittest.cc
index 86028fad895..55c0753aaa6 100644
--- a/chromium/ui/accessibility/ax_node_position_unittest.cc
+++ b/chromium/ui/accessibility/ax_node_position_unittest.cc
@@ -201,7 +201,7 @@ void AXPositionTest::SetUp() {
initial_state.nodes.push_back(static_text2_);
initial_state.nodes.push_back(inline_box2_);
initial_state.has_tree_data = true;
- initial_state.tree_data.tree_id = 0;
+ initial_state.tree_data.tree_id = AXTreeID::FromString("0");
initial_state.tree_data.title = "Dialog title";
AXSerializableTree src_tree(initial_state);
diff --git a/chromium/ui/accessibility/ax_position.h b/chromium/ui/accessibility/ax_position.h
index 6115ded53bb..0f3e6296a32 100644
--- a/chromium/ui/accessibility/ax_position.h
+++ b/chromium/ui/accessibility/ax_position.h
@@ -20,6 +20,7 @@
#include "base/strings/utf_string_conversions.h"
#include "ui/accessibility/ax_enum_util.h"
#include "ui/accessibility/ax_enums.mojom.h"
+#include "ui/accessibility/ax_tree_id.h"
namespace ui {
@@ -63,7 +64,7 @@ bool operator!=(const AXPosition<AXPositionType, AXNodeType>& first,
// distinguish between "before text" and "after text" positions. To do this, if
// the child index is 0 and the anchor is a leaf node, then it's an "after text"
// position. If the child index is |BEFORE_TEXT| and the anchor is a leaf node,
-// then his is a "before text" position.
+// then this is a "before text" position.
// It doesn't make sense to have a "before text" position on a text position,
// because it is identical to setting its offset to the first character.
//
@@ -80,13 +81,13 @@ bool operator!=(const AXPosition<AXPositionType, AXNodeType>& first,
//
// This class can be copied using the |Clone| method. It is designed to be
// immutable.
+
template <class AXPositionType, class AXNodeType>
class AXPosition {
public:
using AXPositionInstance =
std::unique_ptr<AXPosition<AXPositionType, AXNodeType>>;
- static const int INVALID_TREE_ID = -1;
static const int32_t INVALID_ANCHOR_ID = -1;
static const int BEFORE_TEXT = -1;
static const int INVALID_INDEX = -2;
@@ -94,13 +95,13 @@ class AXPosition {
static AXPositionInstance CreateNullPosition() {
AXPositionInstance new_position(new AXPositionType());
- new_position->Initialize(AXPositionKind::NULL_POSITION, INVALID_TREE_ID,
+ new_position->Initialize(AXPositionKind::NULL_POSITION, AXTreeIDUnknown(),
INVALID_ANCHOR_ID, INVALID_INDEX, INVALID_OFFSET,
ax::mojom::TextAffinity::kDownstream);
return new_position;
}
- static AXPositionInstance CreateTreePosition(int tree_id,
+ static AXPositionInstance CreateTreePosition(AXTreeID tree_id,
int32_t anchor_id,
int child_index) {
AXPositionInstance new_position(new AXPositionType());
@@ -111,7 +112,7 @@ class AXPosition {
}
static AXPositionInstance CreateTextPosition(
- int tree_id,
+ AXTreeID tree_id,
int32_t anchor_id,
int text_offset,
ax::mojom::TextAffinity affinity) {
@@ -139,9 +140,9 @@ class AXPosition {
} else {
str_child_index = base::IntToString(child_index_);
}
- str = "TreePosition tree_id=" + base::IntToString(tree_id_) +
- " anchor_id=" + base::IntToString(anchor_id_) + " child_index=" +
- str_child_index;
+ str = "TreePosition tree_id=" + tree_id_.ToString() +
+ " anchor_id=" + base::IntToString(anchor_id_) +
+ " child_index=" + str_child_index;
break;
}
case AXPositionKind::TEXT_POSITION: {
@@ -151,7 +152,7 @@ class AXPosition {
} else {
str_text_offset = base::IntToString(text_offset_);
}
- str = "TextPosition tree_id=" + base::IntToString(tree_id_) +
+ str = "TextPosition tree_id=" + tree_id_.ToString() +
" anchor_id=" + base::IntToString(anchor_id_) +
" text_offset=" + str_text_offset + " affinity=" +
ui::ToString(static_cast<ax::mojom::TextAffinity>(affinity_));
@@ -176,13 +177,12 @@ class AXPosition {
return str + " annotated_text=" + annotated_text;
}
- int tree_id() const { return tree_id_; }
+ AXTreeID tree_id() const { return tree_id_; }
int32_t anchor_id() const { return anchor_id_; }
AXNodeType* GetAnchor() const {
- if (tree_id_ == INVALID_TREE_ID || anchor_id_ == INVALID_ANCHOR_ID)
+ if (tree_id_ == AXTreeIDUnknown() || anchor_id_ == INVALID_ANCHOR_ID)
return nullptr;
- DCHECK_GE(tree_id_, 0);
DCHECK_GE(anchor_id_, 0);
return GetNodeInTree(tree_id_, anchor_id_);
}
@@ -513,10 +513,10 @@ class AXPosition {
if (child_index < 0 || child_index >= AnchorChildCount())
return CreateNullPosition();
- int tree_id = INVALID_TREE_ID;
+ AXTreeID tree_id = AXTreeIDUnknown();
int32_t child_id = INVALID_ANCHOR_ID;
AnchorChild(child_index, &tree_id, &child_id);
- DCHECK_NE(tree_id, INVALID_TREE_ID);
+ DCHECK_NE(tree_id, AXTreeIDUnknown());
DCHECK_NE(child_id, INVALID_ANCHOR_ID);
switch (kind_) {
case AXPositionKind::NULL_POSITION:
@@ -543,10 +543,10 @@ class AXPosition {
if (IsNullPosition())
return CreateNullPosition();
- int tree_id = INVALID_TREE_ID;
+ AXTreeID tree_id = AXTreeIDUnknown();
int32_t parent_id = INVALID_ANCHOR_ID;
AnchorParent(&tree_id, &parent_id);
- if (tree_id == INVALID_TREE_ID || parent_id == INVALID_ANCHOR_ID)
+ if (tree_id == AXTreeIDUnknown() || parent_id == INVALID_ANCHOR_ID)
return CreateNullPosition();
switch (kind_) {
@@ -1153,7 +1153,7 @@ class AXPosition {
const AXPosition<AXPositionType, AXNodeType>& other) = default;
virtual void Initialize(AXPositionKind kind,
- int tree_id,
+ AXTreeID tree_id,
int32_t anchor_id,
int child_index,
int text_offset,
@@ -1173,7 +1173,7 @@ class AXPosition {
(text_offset_ < 0 || text_offset_ > MaxTextOffset()))) {
// Reset to the null position.
kind_ = AXPositionKind::NULL_POSITION;
- tree_id_ = INVALID_TREE_ID;
+ tree_id_ = AXTreeIDUnknown();
anchor_id_ = INVALID_ANCHOR_ID;
child_index_ = INVALID_INDEX;
text_offset_ = INVALID_OFFSET;
@@ -1267,12 +1267,13 @@ class AXPosition {
// Abstract methods.
virtual void AnchorChild(int child_index,
- int* tree_id,
+ AXTreeID* tree_id,
int32_t* child_id) const = 0;
virtual int AnchorChildCount() const = 0;
virtual int AnchorIndexInParent() const = 0;
- virtual void AnchorParent(int* tree_id, int32_t* parent_id) const = 0;
- virtual AXNodeType* GetNodeInTree(int tree_id, int32_t node_id) const = 0;
+ virtual void AnchorParent(AXTreeID* tree_id, int32_t* parent_id) const = 0;
+ virtual AXNodeType* GetNodeInTree(AXTreeID tree_id,
+ int32_t node_id) const = 0;
// Returns the length of text 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.
@@ -1285,7 +1286,7 @@ class AXPosition {
private:
AXPositionKind kind_;
- int tree_id_;
+ AXTreeID tree_id_;
int32_t anchor_id_;
// For text positions, |child_index_| is initially set to |-1| and only
@@ -1299,8 +1300,6 @@ class AXPosition {
};
template <class AXPositionType, class AXNodeType>
-const int AXPosition<AXPositionType, AXNodeType>::INVALID_TREE_ID;
-template <class AXPositionType, class AXNodeType>
const int32_t AXPosition<AXPositionType, AXNodeType>::INVALID_ANCHOR_ID;
template <class AXPositionType, class AXNodeType>
const int AXPosition<AXPositionType, AXNodeType>::BEFORE_TEXT;
diff --git a/chromium/ui/accessibility/ax_role_properties.cc b/chromium/ui/accessibility/ax_role_properties.cc
index 4641a52c25c..487ba26d71a 100644
--- a/chromium/ui/accessibility/ax_role_properties.cc
+++ b/chromium/ui/accessibility/ax_role_properties.cc
@@ -8,7 +8,7 @@
namespace ui {
namespace {
-#if defined(OS_WIN)
+#if defined(OS_WIN) || defined(OS_CHROMEOS)
static bool kExposeLayoutTableAsDataTable = true;
#else
static bool kExposeLayoutTableAsDataTable = false;
@@ -120,6 +120,27 @@ bool IsTableLikeRole(ax::mojom::Role role) {
}
}
+bool IsTableHeaderRole(ax::mojom::Role role) {
+ switch (role) {
+ case ax::mojom::Role::kColumnHeader:
+ case ax::mojom::Role::kRowHeader:
+ return true;
+ default:
+ return false;
+ }
+}
+
+bool IsTableRowRole(ax::mojom::Role role) {
+ switch (role) {
+ case ax::mojom::Role::kRow:
+ return true;
+ case ax::mojom::Role::kLayoutTableRow:
+ return kExposeLayoutTableAsDataTable;
+ default:
+ return false;
+ }
+}
+
bool IsContainerWithSelectableChildrenRole(ax::mojom::Role role) {
switch (role) {
case ax::mojom::Role::kComboBoxGrouping:
@@ -214,6 +235,17 @@ bool IsMenuRelated(ax::mojom::Role role) {
}
}
+bool IsMenuItem(ax::mojom::Role role) {
+ switch (role) {
+ case ax::mojom::Role::kMenuItem:
+ case ax::mojom::Role::kMenuItemCheckBox:
+ case ax::mojom::Role::kMenuItemRadio:
+ return true;
+ default:
+ return false;
+ }
+}
+
bool IsImage(ax::mojom::Role role) {
switch (role) {
case ax::mojom::Role::kCanvas:
diff --git a/chromium/ui/accessibility/ax_role_properties.h b/chromium/ui/accessibility/ax_role_properties.h
index 3b6776ada78..bfb756f9800 100644
--- a/chromium/ui/accessibility/ax_role_properties.h
+++ b/chromium/ui/accessibility/ax_role_properties.h
@@ -32,6 +32,12 @@ AX_EXPORT bool IsCellOrTableHeaderRole(ax::mojom::Role role);
// Returns true if this node is a table, a grid or a treegrid.
AX_EXPORT bool IsTableLikeRole(ax::mojom::Role role);
+// Returns true if this node is a table header.
+AX_EXPORT bool IsTableHeaderRole(ax::mojom::Role role);
+
+// Returns true if this node is a row.
+AX_EXPORT bool IsTableRowRole(ax::mojom::Role role);
+
// Returns true if the provided role is selectable from the standpoint of UI
// automation.
AX_EXPORT bool IsUIASelectable(ax::mojom::Role role);
@@ -48,6 +54,10 @@ AX_EXPORT bool IsControl(ax::mojom::Role role);
// Returns true if this node is a menu or related role.
AX_EXPORT bool IsMenuRelated(ax::mojom::Role role);
+// Returns true if the role is a menu item, including menu item
+// check box and menu item radio buttons.
+AX_EXPORT bool IsMenuItem(ax::mojom::Role role);
+
// Returns true if it's an image, graphic, canvas, etc.
AX_EXPORT bool IsImage(ax::mojom::Role role);
diff --git a/chromium/ui/accessibility/ax_tree.cc b/chromium/ui/accessibility/ax_tree.cc
index 7b7f71aece4..648a3f3c30d 100644
--- a/chromium/ui/accessibility/ax_tree.cc
+++ b/chromium/ui/accessibility/ax_tree.cc
@@ -324,7 +324,7 @@ std::set<int32_t> AXTree::GetReverseRelations(ax::mojom::IntListAttribute attr,
}
std::set<int32_t> AXTree::GetNodeIdsForChildTreeId(
- int32_t child_tree_id) const {
+ AXTreeID child_tree_id) const {
// Conceptually, this is the "const" version of:
// return child_tree_id_reverse_map_[child_tree_id];
const auto& result = child_tree_id_reverse_map_.find(child_tree_id);
@@ -349,16 +349,11 @@ bool AXTree::Unserialize(const AXTreeUpdate& update) {
bool root_updated = false;
if (update.node_id_to_clear != 0) {
AXNode* node = GetFromId(update.node_id_to_clear);
- if (!node) {
- error_ = base::StringPrintf("Bad node_id_to_clear: %d",
- update.node_id_to_clear);
- return false;
- }
// Only destroy the root if the root was replaced and not if it's simply
// updated. To figure out if the root was simply updated, we compare the ID
// of the new root with the existing root ID.
- if (node == root_) {
+ if (node && node == root_) {
if (update.root_id != old_root_id) {
// Clear root_ before calling DestroySubtree so that root_ doesn't ever
// point to an invalid node.
@@ -372,7 +367,7 @@ bool AXTree::Unserialize(const AXTreeUpdate& update) {
// If the root has simply been updated, we treat it like an update to any
// other node.
- if (root_ && (node != root_ || root_updated)) {
+ if (node && root_ && (node != root_ || root_updated)) {
for (int i = 0; i < node->child_count(); ++i)
DestroySubtree(node->ChildAtIndex(i), &update_state);
std::vector<AXNode*> children;
@@ -679,22 +674,6 @@ void AXTree::UpdateReverseRelations(AXNode* node, const AXNodeData& new_data) {
int id = new_data.id;
auto int_callback = [this, node, id](ax::mojom::IntAttribute attr,
const int& old_id, const int& new_id) {
- if (attr == ax::mojom::IntAttribute::kChildTreeId) {
- // Remove old_id -> id from the map, and clear map keys if
- // their values are now empty.
- if (child_tree_id_reverse_map_.find(old_id) !=
- child_tree_id_reverse_map_.end()) {
- child_tree_id_reverse_map_[old_id].erase(id);
- if (child_tree_id_reverse_map_[old_id].empty())
- child_tree_id_reverse_map_.erase(old_id);
- }
-
- // Add new_id -> id to the map, unless new_id is zero indicating that
- // we're only removing a relation.
- if (new_id)
- child_tree_id_reverse_map_[new_id].insert(id);
- }
-
if (!IsNodeIdIntAttribute(attr))
return;
@@ -736,6 +715,33 @@ void AXTree::UpdateReverseRelations(AXNode* node, const AXNodeData& new_data) {
CallIfAttributeValuesChanged(old_data.intlist_attributes,
new_data.intlist_attributes,
std::vector<int32_t>(), intlist_callback);
+
+ auto string_callback = [this, node, id](ax::mojom::StringAttribute attr,
+ const std::string& old_string,
+ const std::string& new_string) {
+ if (attr == ax::mojom::StringAttribute::kChildTreeId) {
+ // Remove old_string -> id from the map, and clear map keys if
+ // their values are now empty.
+ AXTreeID old_ax_tree_id = AXTreeID::FromString(old_string);
+ if (child_tree_id_reverse_map_.find(old_ax_tree_id) !=
+ child_tree_id_reverse_map_.end()) {
+ child_tree_id_reverse_map_[old_ax_tree_id].erase(id);
+ if (child_tree_id_reverse_map_[old_ax_tree_id].empty())
+ child_tree_id_reverse_map_.erase(old_ax_tree_id);
+ }
+
+ // Add new_string -> id to the map, unless new_id is zero indicating that
+ // we're only removing a relation.
+ if (!new_string.empty()) {
+ AXTreeID new_ax_tree_id = AXTreeID::FromString(new_string);
+ child_tree_id_reverse_map_[new_ax_tree_id].insert(id);
+ }
+ }
+ };
+
+ CallIfAttributeValuesChanged(old_data.string_attributes,
+ new_data.string_attributes, std::string(),
+ string_callback);
}
void AXTree::DestroySubtree(AXNode* node,
diff --git a/chromium/ui/accessibility/ax_tree.h b/chromium/ui/accessibility/ax_tree.h
index 3d3d744f89f..993eb22faab 100644
--- a/chromium/ui/accessibility/ax_tree.h
+++ b/chromium/ui/accessibility/ax_tree.h
@@ -224,7 +224,7 @@ class AX_EXPORT AXTree {
// Given a child tree ID, return the node IDs of all nodes in the tree who
// have a kChildTreeId int attribute with that value.
- std::set<int32_t> GetNodeIdsForChildTreeId(int32_t child_tree_id) const;
+ std::set<int32_t> GetNodeIdsForChildTreeId(AXTreeID child_tree_id) const;
// Map from a relation attribute to a map from a target id to source ids.
const IntReverseRelationMap& int_reverse_relations() {
@@ -318,7 +318,7 @@ class AX_EXPORT AXTree {
// a reverse mapping from target nodes to source nodes.
IntListReverseRelationMap intlist_reverse_relations_;
// Map from child tree ID to the set of node IDs that contain that attribute.
- std::map<int32_t, std::set<int32_t>> child_tree_id_reverse_map_;
+ std::map<AXTreeID, std::set<int32_t>> child_tree_id_reverse_map_;
// Map from node ID to cached table info, if the given node is a table.
// Invalidated every time the tree is updated.
diff --git a/chromium/ui/accessibility/ax_tree_combiner.cc b/chromium/ui/accessibility/ax_tree_combiner.cc
index 06a6ac15726..b0ab36fa1f4 100644
--- a/chromium/ui/accessibility/ax_tree_combiner.cc
+++ b/chromium/ui/accessibility/ax_tree_combiner.cc
@@ -17,7 +17,7 @@ AXTreeCombiner::~AXTreeCombiner() {
void AXTreeCombiner::AddTree(const AXTreeUpdate& tree, bool is_root) {
trees_.push_back(tree);
if (is_root) {
- DCHECK_EQ(root_tree_id_, -1);
+ DCHECK_EQ(root_tree_id_, AXTreeIDUnknown());
root_tree_id_ = tree.tree_data.tree_id;
}
}
@@ -25,7 +25,7 @@ void AXTreeCombiner::AddTree(const AXTreeUpdate& tree, bool is_root) {
bool AXTreeCombiner::Combine() {
// First create a map from tree ID to tree update.
for (const auto& tree : trees_) {
- int32_t tree_id = tree.tree_data.tree_id;
+ AXTreeID tree_id = tree.tree_data.tree_id;
if (tree_id_map_.find(tree_id) != tree_id_map_.end())
return false;
tree_id_map_[tree.tree_data.tree_id] = &tree;
@@ -46,7 +46,7 @@ bool AXTreeCombiner::Combine() {
// have focus and mapping IDs from the tree data appropriately.
combined_.has_tree_data = true;
combined_.tree_data = root->tree_data;
- int32_t focused_tree_id = root->tree_data.focused_tree_id;
+ AXTreeID focused_tree_id = root->tree_data.focused_tree_id;
const AXTreeUpdate* focused_tree = root;
if (tree_id_map_.find(focused_tree_id) != tree_id_map_.end())
focused_tree = tree_id_map_[focused_tree_id];
@@ -69,7 +69,7 @@ bool AXTreeCombiner::Combine() {
return true;
}
-int32_t AXTreeCombiner::MapId(int32_t tree_id, int32_t node_id) {
+int32_t AXTreeCombiner::MapId(AXTreeID tree_id, int32_t node_id) {
auto tree_id_node_id = std::make_pair(tree_id, node_id);
if (tree_id_node_id_map_[tree_id_node_id] == 0)
tree_id_node_id_map_[tree_id_node_id] = next_id_++;
@@ -77,11 +77,11 @@ int32_t AXTreeCombiner::MapId(int32_t tree_id, int32_t node_id) {
}
void AXTreeCombiner::ProcessTree(const AXTreeUpdate* tree) {
- int32_t tree_id = tree->tree_data.tree_id;
+ AXTreeID tree_id = tree->tree_data.tree_id;
for (size_t i = 0; i < tree->nodes.size(); ++i) {
AXNodeData node = tree->nodes[i];
- int32_t child_tree_id =
- node.GetIntAttribute(ax::mojom::IntAttribute::kChildTreeId);
+ AXTreeID child_tree_id = AXTreeID::FromString(
+ node.GetStringAttribute(ax::mojom::StringAttribute::kChildTreeId));
// Map the node's ID.
node.id = MapId(tree_id, node.id);
@@ -94,16 +94,11 @@ void AXTreeCombiner::ProcessTree(const AXTreeUpdate* tree) {
if (node.offset_container_id > 0)
node.offset_container_id = MapId(tree_id, node.offset_container_id);
- // Map other int attributes that refer to node IDs, and remove the
- // ax::mojom::IntAttribute::kChildTreeId attribute.
+ // Map other int attributes that refer to node IDs.
for (size_t j = 0; j < node.int_attributes.size(); ++j) {
auto& attr = node.int_attributes[j];
if (IsNodeIdIntAttribute(attr.first))
attr.second = MapId(tree_id, attr.second);
- if (attr.first == ax::mojom::IntAttribute::kChildTreeId) {
- attr.first = ax::mojom::IntAttribute::kNone;
- attr.second = 0;
- }
}
// Map other int list attributes that refer to node IDs.
@@ -115,6 +110,15 @@ void AXTreeCombiner::ProcessTree(const AXTreeUpdate* tree) {
}
}
+ // Remove the ax::mojom::StringAttribute::kChildTreeId attribute.
+ for (size_t j = 0; j < node.string_attributes.size(); ++j) {
+ auto& attr = node.string_attributes[j];
+ if (attr.first == ax::mojom::StringAttribute::kChildTreeId) {
+ attr.first = ax::mojom::StringAttribute::kNone;
+ attr.second = "";
+ }
+ }
+
// See if this node has a child tree. As a sanity check make sure the
// child tree lists this tree as its parent tree id.
const AXTreeUpdate* child_tree = nullptr;
diff --git a/chromium/ui/accessibility/ax_tree_combiner.h b/chromium/ui/accessibility/ax_tree_combiner.h
index ce8fbc792d5..4dc2b63f8af 100644
--- a/chromium/ui/accessibility/ax_tree_combiner.h
+++ b/chromium/ui/accessibility/ax_tree_combiner.h
@@ -8,6 +8,7 @@
#include <vector>
#include "ui/accessibility/ax_export.h"
+#include "ui/accessibility/ax_tree_id_registry.h"
#include "ui/accessibility/ax_tree_update.h"
namespace ui {
@@ -33,15 +34,15 @@ class AX_EXPORT AXTreeCombiner {
const AXTreeUpdate& combined() { return combined_; }
private:
- int32_t MapId(int32_t tree_id, int32_t node_id);
+ int32_t MapId(AXTreeID tree_id, int32_t node_id);
void ProcessTree(const AXTreeUpdate* tree);
std::vector<ui::AXTreeUpdate> trees_;
- int32_t root_tree_id_ = -1;
+ AXTreeID root_tree_id_;
int32_t next_id_ = 1;
- std::map<int32_t, const AXTreeUpdate*> tree_id_map_;
- std::map<std::pair<int32_t, int32_t>, int32_t> tree_id_node_id_map_;
+ std::map<AXTreeID, const AXTreeUpdate*> tree_id_map_;
+ std::map<std::pair<AXTreeID, int32_t>, int32_t> tree_id_node_id_map_;
AXTreeUpdate combined_;
};
diff --git a/chromium/ui/accessibility/ax_tree_combiner_unittest.cc b/chromium/ui/accessibility/ax_tree_combiner_unittest.cc
index 43116ac87cd..5e8d1dc7825 100644
--- a/chromium/ui/accessibility/ax_tree_combiner_unittest.cc
+++ b/chromium/ui/accessibility/ax_tree_combiner_unittest.cc
@@ -10,7 +10,7 @@ namespace ui {
TEST(CombineAXTreesTest, RenumberOneTree) {
AXTreeUpdate tree;
tree.has_tree_data = true;
- tree.tree_data.tree_id = 1;
+ tree.tree_data.tree_id = ui::AXTreeID::FromString("1");
tree.root_id = 2;
tree.nodes.resize(3);
tree.nodes[0].id = 2;
@@ -39,7 +39,7 @@ TEST(CombineAXTreesTest, EmbedChildTree) {
AXTreeUpdate parent_tree;
parent_tree.root_id = 1;
parent_tree.has_tree_data = true;
- parent_tree.tree_data.tree_id = 1;
+ parent_tree.tree_data.tree_id = ui::AXTreeID::FromString("1");
parent_tree.nodes.resize(3);
parent_tree.nodes[0].id = 1;
parent_tree.nodes[0].child_ids.push_back(2);
@@ -48,14 +48,14 @@ 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].AddIntAttribute(ax::mojom::IntAttribute::kChildTreeId,
- 2);
+ parent_tree.nodes[2].AddStringAttribute(
+ ax::mojom::StringAttribute::kChildTreeId, "2");
AXTreeUpdate child_tree;
child_tree.root_id = 1;
child_tree.has_tree_data = true;
- child_tree.tree_data.parent_tree_id = 1;
- child_tree.tree_data.tree_id = 2;
+ child_tree.tree_data.parent_tree_id = ui::AXTreeID::FromString("1");
+ child_tree.tree_data.tree_id = ui::AXTreeID::FromString("2");
child_tree.nodes.resize(3);
child_tree.nodes[0].id = 1;
child_tree.nodes[0].child_ids.push_back(2);
@@ -97,7 +97,7 @@ TEST(CombineAXTreesTest, MapAllIdAttributes) {
AXTreeUpdate tree;
tree.has_tree_data = true;
- tree.tree_data.tree_id = 1;
+ tree.tree_data.tree_id = ui::AXTreeID::FromString("1");
tree.root_id = 11;
tree.nodes.resize(2);
tree.nodes[0].id = 11;
@@ -157,8 +157,8 @@ TEST(CombineAXTreesTest, MapAllIdAttributes) {
TEST(CombineAXTreesTest, FocusedTree) {
AXTreeUpdate parent_tree;
parent_tree.has_tree_data = true;
- parent_tree.tree_data.tree_id = 1;
- parent_tree.tree_data.focused_tree_id = 2;
+ parent_tree.tree_data.tree_id = ui::AXTreeID::FromString("1");
+ parent_tree.tree_data.focused_tree_id = ui::AXTreeID::FromString("2");
parent_tree.tree_data.focus_id = 2;
parent_tree.root_id = 1;
parent_tree.nodes.resize(3);
@@ -169,13 +169,13 @@ 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].AddIntAttribute(ax::mojom::IntAttribute::kChildTreeId,
- 2);
+ parent_tree.nodes[2].AddStringAttribute(
+ ax::mojom::StringAttribute::kChildTreeId, "2");
AXTreeUpdate child_tree;
child_tree.has_tree_data = true;
- child_tree.tree_data.parent_tree_id = 1;
- child_tree.tree_data.tree_id = 2;
+ child_tree.tree_data.parent_tree_id = ui::AXTreeID::FromString("1");
+ child_tree.tree_data.tree_id = ui::AXTreeID::FromString("2");
child_tree.tree_data.focus_id = 3;
child_tree.root_id = 1;
child_tree.nodes.resize(3);
diff --git a/chromium/ui/accessibility/ax_tree_data.cc b/chromium/ui/accessibility/ax_tree_data.cc
index 20e5f1ccce8..ec452ba6d57 100644
--- a/chromium/ui/accessibility/ax_tree_data.cc
+++ b/chromium/ui/accessibility/ax_tree_data.cc
@@ -23,12 +23,12 @@ AXTreeData::~AXTreeData() = default;
std::string AXTreeData::ToString() const {
std::string result;
- if (tree_id != -1)
- result += " tree_id=" + base::NumberToString(tree_id);
- if (parent_tree_id != -1)
- result += " parent_tree_id=" + base::NumberToString(parent_tree_id);
- if (focused_tree_id != -1)
- result += " focused_tree_id=" + base::NumberToString(focused_tree_id);
+ if (tree_id != AXTreeIDUnknown())
+ result += " tree_id=" + tree_id.ToString();
+ if (parent_tree_id != AXTreeIDUnknown())
+ result += " parent_tree_id=" + parent_tree_id.ToString();
+ if (focused_tree_id != AXTreeIDUnknown())
+ result += " focused_tree_id=" + focused_tree_id.ToString();
if (!doctype.empty())
result += " doctype=" + doctype;
diff --git a/chromium/ui/accessibility/ax_tree_data.h b/chromium/ui/accessibility/ax_tree_data.h
index 0233764b109..dec27f4b145 100644
--- a/chromium/ui/accessibility/ax_tree_data.h
+++ b/chromium/ui/accessibility/ax_tree_data.h
@@ -15,6 +15,7 @@
#include "base/strings/string_split.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_export.h"
+#include "ui/accessibility/ax_tree_id_registry.h"
#include "ui/gfx/geometry/rect.h"
namespace ui {
@@ -33,14 +34,14 @@ struct AX_EXPORT AXTreeData {
// public and copyable.
// The globally unique ID of this accessibility tree.
- int32_t tree_id = -1;
+ AXTreeID tree_id;
// The ID of the accessibility tree that this tree is contained in, if any.
- int32_t parent_tree_id = -1;
+ AXTreeID parent_tree_id;
// The ID of the accessibility tree that has focus. This is typically set
// on the root frame in a frame tree.
- int32_t focused_tree_id = -1;
+ AXTreeID focused_tree_id;
// Attributes specific to trees that are web frames.
std::string doctype;
diff --git a/chromium/ui/accessibility/ax_tree_id.cc b/chromium/ui/accessibility/ax_tree_id.cc
new file mode 100644
index 00000000000..6076f1122b5
--- /dev/null
+++ b/chromium/ui/accessibility/ax_tree_id.cc
@@ -0,0 +1,62 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/accessibility/ax_tree_id.h"
+
+#include <iostream>
+
+#include "base/no_destructor.h"
+
+namespace ui {
+
+AXTreeID::AXTreeID() : id_("") {}
+
+AXTreeID::AXTreeID(const std::string& string) : id_(string) {}
+
+// static
+AXTreeID AXTreeID::FromString(const std::string& string) {
+ return AXTreeID(string);
+}
+
+bool AXTreeID::operator==(const AXTreeID& rhs) const {
+ return id_ == rhs.id_;
+}
+
+bool AXTreeID::operator!=(const AXTreeID& rhs) const {
+ return id_ != rhs.id_;
+}
+
+bool AXTreeID::operator<(const AXTreeID& rhs) const {
+ return id_ < rhs.id_;
+}
+
+bool AXTreeID::operator<=(const AXTreeID& rhs) const {
+ return id_ <= rhs.id_;
+}
+
+bool AXTreeID::operator>(const AXTreeID& rhs) const {
+ return id_ > rhs.id_;
+}
+
+bool AXTreeID::operator>=(const AXTreeID& rhs) const {
+ return id_ >= rhs.id_;
+}
+
+std::ostream& operator<<(std::ostream& stream, const AXTreeID& value) {
+ return stream << 0;
+}
+
+const AXTreeID& AXTreeIDUnknown() {
+ static const base::NoDestructor<AXTreeID> ax_tree_id_unknown(
+ AXTreeID::FromString(""));
+ return *ax_tree_id_unknown;
+}
+
+const AXTreeID& DesktopAXTreeID() {
+ static const base::NoDestructor<AXTreeID> desktop_ax_tree_id(
+ AXTreeID::FromString("0"));
+ return *desktop_ax_tree_id;
+}
+
+} // namespace ui
diff --git a/chromium/ui/accessibility/ax_tree_id.h b/chromium/ui/accessibility/ax_tree_id.h
new file mode 100644
index 00000000000..946181bbbf3
--- /dev/null
+++ b/chromium/ui/accessibility/ax_tree_id.h
@@ -0,0 +1,58 @@
+// 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_TREE_ID_H_
+#define UI_ACCESSIBILITY_AX_TREE_ID_H_
+
+#include <string>
+
+#include "ui/accessibility/ax_export.h"
+
+namespace mojo {
+template <typename DataViewType, typename T>
+struct StructTraits;
+}
+
+namespace ax {
+namespace mojom {
+class AXTreeIDDataView;
+}
+} // namespace ax
+
+namespace ui {
+
+// A unique ID representing an accessibility tree.
+class AX_EXPORT AXTreeID {
+ public:
+ AXTreeID();
+ static AXTreeID FromString(const std::string& string);
+ const std::string& ToString() const { return id_; }
+ operator std::string() const { return id_; }
+
+ bool operator==(const AXTreeID& rhs) const;
+ bool operator!=(const AXTreeID& rhs) const;
+ bool operator<(const AXTreeID& rhs) const;
+ bool operator<=(const AXTreeID& rhs) const;
+ bool operator>(const AXTreeID& rhs) const;
+ bool operator>=(const AXTreeID& rhs) const;
+
+ private:
+ explicit AXTreeID(const std::string& string);
+
+ friend struct mojo::StructTraits<ax::mojom::AXTreeIDDataView, ui::AXTreeID>;
+
+ std::string id_;
+};
+
+AX_EXPORT std::ostream& operator<<(std::ostream& stream, const AXTreeID& value);
+
+// The value to use when an AXTreeID is unknown.
+AX_EXPORT extern const AXTreeID& AXTreeIDUnknown();
+
+// The AXTreeID of the desktop.
+AX_EXPORT extern const AXTreeID& DesktopAXTreeID();
+
+} // namespace ui
+
+#endif // UI_ACCESSIBILITY_AX_TREE_ID_H_
diff --git a/chromium/ui/accessibility/ax_tree_id_registry.cc b/chromium/ui/accessibility/ax_tree_id_registry.cc
index d05fa5eebec..f0a47078aac 100644
--- a/chromium/ui/accessibility/ax_tree_id_registry.cc
+++ b/chromium/ui/accessibility/ax_tree_id_registry.cc
@@ -5,6 +5,7 @@
#include "ui/accessibility/ax_tree_id_registry.h"
#include "base/memory/singleton.h"
+#include "base/strings/string_number_conversions.h"
#include "ui/accessibility/ax_host_delegate.h"
namespace ui {
@@ -14,23 +15,21 @@ AXTreeIDRegistry* AXTreeIDRegistry::GetInstance() {
return base::Singleton<AXTreeIDRegistry>::get();
}
-AXTreeIDRegistry::AXTreeID AXTreeIDRegistry::GetOrCreateAXTreeID(
- int process_id,
- int routing_id) {
+AXTreeID AXTreeIDRegistry::GetOrCreateAXTreeID(int process_id, int routing_id) {
FrameID frame_id(process_id, routing_id);
auto it = frame_to_ax_tree_id_map_.find(frame_id);
if (it != frame_to_ax_tree_id_map_.end())
return it->second;
- AXTreeID new_id = ++ax_tree_id_counter_;
+ AXTreeID new_id =
+ AXTreeID::FromString(base::IntToString(++ax_tree_id_counter_));
frame_to_ax_tree_id_map_[frame_id] = new_id;
ax_tree_to_frame_id_map_[new_id] = frame_id;
return new_id;
}
-AXTreeIDRegistry::FrameID AXTreeIDRegistry::GetFrameID(
- AXTreeIDRegistry::AXTreeID ax_tree_id) {
+AXTreeIDRegistry::FrameID AXTreeIDRegistry::GetFrameID(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;
@@ -38,30 +37,29 @@ AXTreeIDRegistry::FrameID AXTreeIDRegistry::GetFrameID(
return FrameID(-1, -1);
}
-AXTreeIDRegistry::AXTreeID AXTreeIDRegistry::GetOrCreateAXTreeID(
- AXHostDelegate* delegate) {
+AXTreeID AXTreeIDRegistry::GetOrCreateAXTreeID(AXHostDelegate* delegate) {
for (auto it : id_to_host_delegate_) {
if (it.second == delegate)
return it.first;
}
- id_to_host_delegate_[++ax_tree_id_counter_] = delegate;
- return ax_tree_id_counter_;
+ AXTreeID new_id =
+ AXTreeID::FromString(base::IntToString(++ax_tree_id_counter_));
+ id_to_host_delegate_[new_id] = delegate;
+ return new_id;
}
-AXHostDelegate* AXTreeIDRegistry::GetHostDelegate(
- AXTreeIDRegistry::AXTreeID ax_tree_id) {
+AXHostDelegate* AXTreeIDRegistry::GetHostDelegate(AXTreeID ax_tree_id) {
auto it = id_to_host_delegate_.find(ax_tree_id);
if (it == id_to_host_delegate_.end())
return nullptr;
return it->second;
}
-void AXTreeIDRegistry::SetDelegateForID(AXHostDelegate* delegate,
- AXTreeIDRegistry::AXTreeID id) {
+void AXTreeIDRegistry::SetDelegateForID(AXHostDelegate* delegate, AXTreeID id) {
id_to_host_delegate_[id] = delegate;
}
-void AXTreeIDRegistry::RemoveAXTreeID(AXTreeIDRegistry::AXTreeID ax_tree_id) {
+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);
diff --git a/chromium/ui/accessibility/ax_tree_id_registry.h b/chromium/ui/accessibility/ax_tree_id_registry.h
index 3cdcc61ad5c..24e40bd1fc3 100644
--- a/chromium/ui/accessibility/ax_tree_id_registry.h
+++ b/chromium/ui/accessibility/ax_tree_id_registry.h
@@ -6,10 +6,12 @@
#define UI_ACCESSIBILITY_AX_TREE_ID_REGISTRY_H_
#include <map>
+#include <string>
#include <utility>
#include "base/macros.h"
#include "ui/accessibility/ax_export.h"
+#include "ui/accessibility/ax_tree_id.h"
namespace base {
template <typename T>
@@ -32,10 +34,6 @@ class AX_EXPORT AXTreeIDRegistry {
public:
using FrameID = std::pair<int, int>;
- using AXTreeID = int;
-
- static constexpr AXTreeID kNoAXTreeID = -1;
-
// Get the single instance of this class.
static AXTreeIDRegistry* GetInstance();
@@ -59,8 +57,8 @@ class AX_EXPORT AXTreeIDRegistry {
AXTreeIDRegistry();
virtual ~AXTreeIDRegistry();
- // Tracks the current unique ax frame id.
- AXTreeID ax_tree_id_counter_;
+ // Tracks the current unique ax tree id.
+ int ax_tree_id_counter_;
// Maps an accessibility tree to its frame via ids.
std::map<AXTreeID, FrameID> ax_tree_to_frame_id_map_;
diff --git a/chromium/ui/accessibility/ax_tree_serializer.h b/chromium/ui/accessibility/ax_tree_serializer.h
index 5b835a45c50..f11ded45a69 100644
--- a/chromium/ui/accessibility/ax_tree_serializer.h
+++ b/chromium/ui/accessibility/ax_tree_serializer.h
@@ -88,6 +88,16 @@ class AXTreeSerializer {
// being serialized.
void InvalidateSubtree(AXSourceNode node);
+ // Return whether or not this node is in the client tree. If you call
+ // this immediately after serializing, this indicates whether a given
+ // node is in the set of nodes that the client (the recipient of
+ // the AXTreeUpdates) is aware of.
+ //
+ // For example, you could use this to determine if a given node is
+ // reachable. If one of its ancestors is hidden and it was pruned
+ // from the accessibility tree, this would return false.
+ bool IsInClientTree(AXSourceNode node);
+
// Only for unit testing. Normally this class relies on getting a call
// to SerializeChanges() every time the source tree changes. For unit
// testing, it's convenient to create a static AXTree for the initial
@@ -162,6 +172,10 @@ class AXTreeSerializer {
// Visit all of the descendants of |node| once.
void WalkAllDescendants(AXSourceNode node);
+ // Delete the entire client subtree but don't set the did_reset_ flag
+ // like when Reset() is called.
+ void InternalReset();
+
// The tree source.
AXTreeSource<AXSourceNode, AXNodeData, AXTreeData>* tree_;
@@ -177,6 +191,11 @@ class AXTreeSerializer {
// The maximum number of nodes to serialize in a given call to
// SerializeChanges, or 0 if there's no maximum.
size_t max_node_count_ = 0;
+
+ // Keeps track of if Reset() was called. If so, we need to always
+ // explicitly set node_id_to_clear to ensure that the next serialized
+ // tree is treated as a completely new tree and not a partial update.
+ bool did_reset_ = false;
};
// In order to keep track of what nodes the client knows about, we keep a
@@ -203,6 +222,12 @@ AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::~AXTreeSerializer() {
template <typename AXSourceNode, typename AXNodeData, typename AXTreeData>
void AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::Reset() {
+ InternalReset();
+ did_reset_ = true;
+}
+
+template <typename AXSourceNode, typename AXNodeData, typename AXTreeData>
+void AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::InternalReset() {
client_tree_data_ = AXTreeData();
// Normally we use DeleteClientSubtree to remove nodes from the tree,
@@ -371,7 +396,7 @@ bool AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::SerializeChanges(
// If there's no LCA, just tell the client to destroy the whole
// tree and then we'll serialize everything from the new root.
out_update->node_id_to_clear = client_root_->id;
- Reset();
+ InternalReset();
} else if (need_delete) {
// Otherwise, if we need to reserialize a subtree, first we need
// to delete those nodes in our client tree so that
@@ -394,7 +419,19 @@ bool AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::SerializeChanges(
// DumpAccessibilityTreeTest.AccessibilityAriaOwns.
WalkAllDescendants(lca);
- return SerializeChangedNodes(lca, out_update);
+ if (!SerializeChangedNodes(lca, out_update))
+ return false;
+
+ // If we had a reset, ensure that the old tree is cleared before the client
+ // unserializes this update. If we didn't do this, there's a chance that
+ // treating this update as an incremental update could result in some
+ // reparenting.
+ if (did_reset_) {
+ out_update->node_id_to_clear = tree_->GetId(lca);
+ did_reset_ = false;
+ }
+
+ return true;
}
template <typename AXSourceNode, typename AXNodeData, typename AXTreeData>
@@ -406,6 +443,12 @@ void AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::InvalidateSubtree(
}
template <typename AXSourceNode, typename AXNodeData, typename AXTreeData>
+bool AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::IsInClientTree(
+ AXSourceNode node) {
+ return !!ClientTreeNodeById(tree_->GetId(node));
+}
+
+template <typename AXSourceNode, typename AXNodeData, typename AXTreeData>
void AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::
InvalidateClientSubtree(ClientTreeNode* client_node) {
client_node->invalid = true;
@@ -444,7 +487,8 @@ bool AXTreeSerializer<AXSourceNode, AXNodeData, AXTreeData>::
int id = tree_->GetId(node);
ClientTreeNode* client_node = ClientTreeNodeById(id);
if (!client_node) {
- Reset();
+ if (client_root_)
+ Reset();
client_root_ = new ClientTreeNode();
client_node = client_root_;
client_node->id = id;
diff --git a/chromium/ui/accessibility/ax_tree_serializer_unittest.cc b/chromium/ui/accessibility/ax_tree_serializer_unittest.cc
index 023945043b4..3a5724b3f64 100644
--- a/chromium/ui/accessibility/ax_tree_serializer_unittest.cc
+++ b/chromium/ui/accessibility/ax_tree_serializer_unittest.cc
@@ -389,4 +389,76 @@ TEST_F(AXTreeSerializerTest, DuplicateIdsReturnsErrorAndFlushes) {
ASSERT_EQ(static_cast<size_t>(5), update.nodes.size());
}
+// If a tree serializer is reset, that means it doesn't know about
+// the state of the client tree anymore. The safest thing to do in
+// that circumstance is to force the client to clear everything.
+TEST_F(AXTreeSerializerTest, ResetUpdatesNodeIdToClear) {
+ // (1 (2 (3 (4 (5)))))
+ treedata0_.root_id = 1;
+ treedata0_.nodes.resize(5);
+ treedata0_.nodes[0].id = 1;
+ treedata0_.nodes[0].child_ids.push_back(2);
+ treedata0_.nodes[1].id = 2;
+ treedata0_.nodes[1].child_ids.push_back(3);
+ treedata0_.nodes[2].id = 3;
+ treedata0_.nodes[2].child_ids.push_back(4);
+ treedata0_.nodes[3].id = 4;
+ treedata0_.nodes[3].child_ids.push_back(5);
+ treedata0_.nodes[4].id = 5;
+
+ // Node 5 has been reparented from being a child of node 4,
+ // to a child of node 2.
+ // (1 (2 (3 (4) 5)))
+ treedata1_.root_id = 1;
+ treedata1_.nodes.resize(5);
+ treedata1_.nodes[0].id = 1;
+ treedata1_.nodes[0].child_ids.push_back(2);
+ treedata1_.nodes[1].id = 2;
+ treedata1_.nodes[1].child_ids.push_back(3);
+ treedata1_.nodes[1].child_ids.push_back(5);
+ treedata1_.nodes[2].id = 3;
+ treedata1_.nodes[2].child_ids.push_back(4);
+ treedata1_.nodes[3].id = 4;
+ treedata1_.nodes[4].id = 5;
+
+ CreateTreeSerializer();
+
+ serializer_->Reset();
+
+ AXTreeUpdate update;
+ ASSERT_TRUE(serializer_->SerializeChanges(tree1_->GetFromId(4), &update));
+
+ // The update should unserialize without errors.
+ AXTree dst_tree(treedata0_);
+ EXPECT_TRUE(dst_tree.Unserialize(update)) << dst_tree.error();
+}
+
+// Ensure that calling Reset doesn't cause any problems if
+// the root changes.
+TEST_F(AXTreeSerializerTest, ResetWorksWithNewRootId) {
+ // (1 (2))
+ treedata0_.root_id = 1;
+ treedata0_.nodes.resize(2);
+ treedata0_.nodes[0].id = 1;
+ treedata0_.nodes[0].child_ids.push_back(2);
+ treedata0_.nodes[1].id = 2;
+
+ // (3 (4))
+ treedata1_.root_id = 3;
+ treedata1_.nodes.resize(2);
+ treedata1_.nodes[0].id = 3;
+ treedata1_.nodes[0].child_ids.push_back(4);
+ treedata1_.nodes[1].id = 4;
+
+ CreateTreeSerializer();
+ serializer_->Reset();
+
+ AXTreeUpdate update;
+ ASSERT_TRUE(serializer_->SerializeChanges(tree1_->GetFromId(4), &update));
+
+ // The update should unserialize without errors.
+ AXTree dst_tree(treedata0_);
+ EXPECT_TRUE(dst_tree.Unserialize(update)) << dst_tree.error();
+}
+
} // namespace ui
diff --git a/chromium/ui/accessibility/ax_tree_unittest.cc b/chromium/ui/accessibility/ax_tree_unittest.cc
index bb1d3a24534..42d660a491d 100644
--- a/chromium/ui/accessibility/ax_tree_unittest.cc
+++ b/chromium/ui/accessibility/ax_tree_unittest.cc
@@ -323,25 +323,6 @@ TEST(AXTreeTest, SerializeAXTreeUpdate) {
update.ToString());
}
-TEST(AXTreeTest, DeleteUnknownSubtreeFails) {
- AXNodeData root;
- root.id = 1;
-
- AXTreeUpdate initial_state;
- initial_state.root_id = 1;
- initial_state.nodes.push_back(root);
- AXTree tree(initial_state);
-
- // This should fail because we're asking it to delete
- // a subtree rooted at id=2, which doesn't exist.
- AXTreeUpdate update;
- update.node_id_to_clear = 2;
- update.nodes.resize(1);
- update.nodes[0].id = 1;
- EXPECT_FALSE(tree.Unserialize(update));
- ASSERT_EQ("Bad node_id_to_clear: 2", tree.error());
-}
-
TEST(AXTreeTest, LeaveOrphanedDeletedSubtreeFails) {
AXTreeUpdate initial_state;
initial_state.root_id = 1;
@@ -1444,41 +1425,47 @@ 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].AddIntAttribute(ax::mojom::IntAttribute::kChildTreeId,
- 92);
+ initial_state.nodes[1].AddStringAttribute(
+ ax::mojom::StringAttribute::kChildTreeId, "92");
initial_state.nodes[2].id = 3;
- initial_state.nodes[2].AddIntAttribute(ax::mojom::IntAttribute::kChildTreeId,
- 93);
+ initial_state.nodes[2].AddStringAttribute(
+ ax::mojom::StringAttribute::kChildTreeId, "93");
initial_state.nodes[3].id = 4;
- initial_state.nodes[3].AddIntAttribute(ax::mojom::IntAttribute::kChildTreeId,
- 93);
+ initial_state.nodes[3].AddStringAttribute(
+ ax::mojom::StringAttribute::kChildTreeId, "93");
AXTree tree(initial_state);
- auto child_tree_91_nodes = tree.GetNodeIdsForChildTreeId(91);
+ auto child_tree_91_nodes =
+ tree.GetNodeIdsForChildTreeId(AXTreeID::FromString("91"));
EXPECT_EQ(0U, child_tree_91_nodes.size());
- auto child_tree_92_nodes = tree.GetNodeIdsForChildTreeId(92);
+ auto child_tree_92_nodes =
+ tree.GetNodeIdsForChildTreeId(AXTreeID::FromString("92"));
EXPECT_EQ(1U, child_tree_92_nodes.size());
EXPECT_TRUE(base::ContainsKey(child_tree_92_nodes, 2));
- auto child_tree_93_nodes = tree.GetNodeIdsForChildTreeId(93);
+ auto child_tree_93_nodes =
+ tree.GetNodeIdsForChildTreeId(AXTreeID::FromString("93"));
EXPECT_EQ(2U, child_tree_93_nodes.size());
EXPECT_TRUE(base::ContainsKey(child_tree_93_nodes, 3));
EXPECT_TRUE(base::ContainsKey(child_tree_93_nodes, 4));
AXTreeUpdate update = initial_state;
- update.nodes[2].int_attributes.clear();
- update.nodes[2].AddIntAttribute(ax::mojom::IntAttribute::kChildTreeId, 92);
- update.nodes[3].int_attributes.clear();
+ update.nodes[2].string_attributes.clear();
+ update.nodes[2].AddStringAttribute(ax::mojom::StringAttribute::kChildTreeId,
+ "92");
+ update.nodes[3].string_attributes.clear();
EXPECT_TRUE(tree.Unserialize(update));
- child_tree_92_nodes = tree.GetNodeIdsForChildTreeId(92);
+ child_tree_92_nodes =
+ tree.GetNodeIdsForChildTreeId(AXTreeID::FromString("92"));
EXPECT_EQ(2U, child_tree_92_nodes.size());
EXPECT_TRUE(base::ContainsKey(child_tree_92_nodes, 2));
EXPECT_TRUE(base::ContainsKey(child_tree_92_nodes, 3));
- child_tree_93_nodes = tree.GetNodeIdsForChildTreeId(93);
+ child_tree_93_nodes =
+ tree.GetNodeIdsForChildTreeId(AXTreeID::FromString("93"));
EXPECT_EQ(0U, child_tree_93_nodes.size());
}
diff --git a/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_cs.xtb b/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_cs.xtb
index a2be5d28572..7a6fd118c61 100644
--- a/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_cs.xtb
+++ b/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_cs.xtb
@@ -10,7 +10,7 @@
<translation id="1703735871906654364">Procházení pomocí kurzoru</translation>
<translation id="1791496371305830581">Povolit všechny animované obrázky</translation>
<translation id="1996252509865389616">Aktivovat?</translation>
-<translation id="2079545284768500474" />
+<translation id="2079545284768500474">Vrátit zpět</translation>
<translation id="2179565792157161713">Otevřít dlouhý popis na nové kartě</translation>
<translation id="2223143012868735942">Přizpůsobitelný barevný filtr používaný na webové stránky s cílem zlepšit vnímání barev.</translation>
<translation id="2394933097471027016">Vyzkoušejte to – procházení pomocí kurzoru je na této stránce vždy aktivováno.</translation>
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 a2198a23de5..9c3b1d0116c 100644
--- a/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_gu.xtb
+++ b/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_gu.xtb
@@ -6,28 +6,28 @@
<translation id="145360476452865422">એનિમેશન નીતિ:</translation>
<translation id="1555130319947370107">વાદળી</translation>
<translation id="1588438908519853928">સામાન્ય</translation>
-<translation id="1591070050619849194">બધા છબી એનિમેશન અક્ષમ કરો.</translation>
+<translation id="1591070050619849194">બધા છબી એનિમેશન બંધ કરો.</translation>
<translation id="1703735871906654364">કૅરેટ બ્રાઉઝિંગ</translation>
<translation id="1791496371305830581">બધી એનિમેટ થતી છબીઓને મંજૂરી આપો.</translation>
-<translation id="1996252509865389616">સક્ષમ કરીએ?</translation>
-<translation id="2079545284768500474">પૂર્વવત કરો</translation>
+<translation id="1996252509865389616">ચાલુ કરીએ?</translation>
+<translation id="2079545284768500474">છેલ્લો ફેરફાર રદ કરો</translation>
<translation id="2179565792157161713">નવા ટૅબમાં લાંબુ વર્ણન ખોલો</translation>
<translation id="2223143012868735942">રંગ વિભાવના સુધારવા માટે વેબ પેજીસને કસ્ટમાઇઝ કરી શકાય તેવું રંગ ફિલ્ટર લાગુ કરવામાં આવ્યું.</translation>
<translation id="2394933097471027016">તેને હમણાં અજમાવી જુઓ - કૅરેટ બ્રાઉઝિંગ આ પૃષ્ઠ પર હંમેશા સક્ષમ હોય છે!</translation>
<translation id="2471847333270902538"><ph name="SITE" /> માટે રંગ યોજના:</translation>
<translation id="2648340354586434750">શબ્દો દ્વારા ખસવા માટે &lt;span class='key'&gt;વિકલ્પ&lt;/span&gt; ને પકડી રાખો.</translation>
-<translation id="2795227192542594043">કીબોર્ડ દ્વારા ટેક્સ્ટ પસંદ કરવા દઈને, આ એક્સ્ટેન્શન તમને વેબ પૃષ્ઠોમાં એક ખસેડવા યોગ્ય કર્સર આપે છે.</translation>
+<translation id="2795227192542594043">કીબોર્ડ દ્વારા ટેક્સ્ટ પસંદ કરવા દઈને, આ એક્સ્ટેંશન તમને વેબ પેજમાં એક ખસેડવા યોગ્ય કર્સર આપે છે.</translation>
<translation id="2808027189040546825">પગલું 1: ફિન્ટેસ્ટ તારાઓ સાથે પંક્તિ પસંદ કરો:</translation>
-<translation id="2965611304828530558">&lt;p&gt;જ્યારે તમે કોઈ લિંક અથવા કન્ટ્રોલ પર પહોંચો છો, ત્યારે તે આપમેળે ફોકસ થાય છે. લિંક અથવા બટનને ક્લિક કરવા માટે &lt;span class='key'&gt;Enter&lt;/span&gt; દબાવો. &lt;/p&gt; &lt;p&gt; જ્યારે કોઈ ફોકસ કરેલ કન્ટ્રોલ (જેમ કે ટેક્સ્ટ બોક્સ અથવા કોઈ સૂચિ બોક્સ) તીર કીઝને કેપ્ચર કરી રહી હોય, ત્યારે કૅરેટ બ્રાઉઝિંગને ચાલુ રાખવા માટે ડાબા અથવા જમણા તીર પછી &lt;span class='key'&gt;Esc&lt;/span&gt; દબાવો. &lt;/p&gt; &lt;p&gt; વૈકલ્પિક રીતે, ફોકસ કરવા યોગ્ય કન્ટ્રોલ પર ખસવા માટે &lt;span class='key'&gt;Tab&lt;/span&gt; દબાવો. &lt;/p&gt;</translation>
+<translation id="2965611304828530558">&lt;p&gt;જ્યારે તમે કોઈ લિંક અથવા કન્ટ્રોલ પર પહોંચો છો, ત્યારે તે ઑટોમૅટિક રીતે ફોકસ થાય છે. લિંક અથવા બટનને ક્લિક કરવા માટે &lt;span class='key'&gt;Enter&lt;/span&gt; દબાવો. &lt;/p&gt; &lt;p&gt; જ્યારે કોઈ ફોકસ કરેલ કન્ટ્રોલ (જેમ કે ટેક્સ્ટ બોક્સ અથવા કોઈ સૂચિ બોક્સ) Arrow કીને કેપ્ચર કરી રહી હોય, ત્યારે કૅરેટ બ્રાઉઝિંગને ચાલુ રાખવા માટે ડાબા અથવા જમણા તીર પછી &lt;span class='key'&gt;Esc&lt;/span&gt; દબાવો. &lt;/p&gt; &lt;p&gt; વૈકલ્પિક રીતે, ફોકસ કરવા યોગ્ય કન્ટ્રોલ પર ખસવા માટે &lt;span class='key'&gt;Tab&lt;/span&gt; દબાવો. &lt;/p&gt;</translation>
<translation id="3252573918265662711">સેટઅપ</translation>
<translation id="3410969471888629217">સાઇટ કસ્ટમાઇઝેશન ભૂલી જાઓ</translation>
-<translation id="3435896845095436175">સક્ષમ કરો</translation>
+<translation id="3435896845095436175">ચાલુ કરો</translation>
<translation id="3622586652998721735">ડિફૉલ્ટ યોજના તરીકે સેટ કરો</translation>
<translation id="3812541808639806898">છબી 'Alt' ટેક્સ્ટ દર્શક</translation>
<translation id="381767806621926835">કોઈપણ વસ્તુનું લાંબુ વર્ણન ઍક્સેસ કરવા માટે, તેના પર "longdesc" અથવા "aria-describedat" લક્ષણ વડે રાઇટ-ક્લિક કરો.</translation>
<translation id="4023902424053835668">તીર કીઝનો ઉપયોગ કરીને વેબ પૃષ્ઠોની ટેક્સ્ટને બ્રાઉઝ કરો.</translation>
<translation id="4388820049312272371">એક ઝડપી ફ્લેશ સાથે કર્સરની સ્થિતિને હાઇલાઇટ કરો.</translation>
-<translation id="4394049700291259645">અક્ષમ કરો</translation>
+<translation id="4394049700291259645">બંધ કરો</translation>
<translation id="4769065380738716500">છબીઓ તેમની વૈકલ્પિક ટેક્સ્ટ દ્વારા બદલવામાં આવી છે.</translation>
<translation id="4896660567607030658">કોઈ પ્રતિસાદ નથી, માત્ર કર્સર દર્શાવો.</translation>
<translation id="4937901943818762779">એનિમેટ થતી છબીઓને મંજૂરી આપો, પરંતુ માત્ર એકજ વાર.</translation>
@@ -39,7 +39,7 @@
<translation id="5331422999063554397">વિપરિત રંગ</translation>
<translation id="5555153510860501336">ઉચ્ચ કોન્ટ્રાસ્ટ અક્ષમ છે</translation>
<translation id="5558600050691192317">કીબોર્ડ આદેશો</translation>
-<translation id="5594989420907487559">એનિમેશન્સ માત્ર એકજ વાર ચલાવો અથવા સંપૂર્ણપણે એનિમેશન્સ અક્ષમ કરો.</translation>
+<translation id="5594989420907487559">એનિમેશન્સ માત્ર એકજ વાર ચલાવો અથવા સંપૂર્ણપણે એનિમેશન્સ બંધ કરો.</translation>
<translation id="5631241868147802353">ડિફૉલ્ટ રંગ યોજના:</translation>
<translation id="5650358096585648000">વિઝ્યુઅલ પ્રતિસાદ</translation>
<translation id="5710185147685935461">વેબપૃષ્ઠોને વાંચવામાં વધુ સરળ બનાવવા માટે રંગ યોજનાને બદલો અથવા વિપરિત કરો.</translation>
diff --git a/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_mr.xtb b/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_mr.xtb
index 4c569304cd5..6c0a8abc85d 100644
--- a/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_mr.xtb
+++ b/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_mr.xtb
@@ -18,7 +18,7 @@
<translation id="2648340354586434750">शब्दांनुसार हलविण्‍यासाठी &lt;span class='key'&gt;पर्याय&lt;/span&gt; धरून ठेवा.</translation>
<translation id="2795227192542594043">हा विस्‍तार आपल्‍याला कीबोर्डसह मजकूर निवडण्‍याची अनुमती देणारा, वेबपृष्‍ठामधील हलणारा कर्सर देतो.</translation>
<translation id="2808027189040546825">चरण 1: सर्वाधिक अंधुक तारे असलेली पंक्ती निवडा:</translation>
-<translation id="2965611304828530558">&lt;p&gt;आपण दुव्‍यावर किंवा नियंत्रणावर पोहचता तेव्‍हा, ते स्‍वयंचलितपणे फोकस केले जाते. दुवा किंवा बटण क्लिक करण्यासाठी &lt;span class='key'&gt;Enter&lt;/span&gt; दाबा. &lt;/p&gt; &lt;p&gt; फोकस केलेले नियंत्रण (जसे की मजकूर बॉक्‍स किंवा सूची बॉक्‍स) बाण की कॅप्‍चर करतात तेव्‍हा, कॅरेट ब्राउझिंग करणे सुरु ठेवण्‍यासाठी &lt;span class='key'&gt;Esc&lt;/span&gt; त्यानंतर डावा किंवा उजवा बाण दाबा. &lt;/p&gt; &lt;p&gt; वैकल्पिकपणे, पुढील फोकस करण्‍यायोग्य नियंत्रणावर हलविण्‍यासाठी &lt;span class='key'&gt;Tab&lt;/span&gt; दाबा. &lt;/p&gt;</translation>
+<translation id="2965611304828530558">&lt;p&gt;तुम्ही दुव्‍यावर किंवा नियंत्रणावर पोहचता तेव्‍हा, ते स्‍वयंचलितपणे फोकस केले जाते. दुवा किंवा बटण क्लिक करण्यासाठी &lt;span class='key'&gt;Enter&lt;/span&gt; दाबा. &lt;/p&gt; &lt;p&gt; फोकस केलेले नियंत्रण (जसे की मजकूर बॉक्‍स किंवा सूची बॉक्‍स) बाण की कॅप्‍चर करतात तेव्‍हा, कॅरेट ब्राउझिंग करणे सुरु ठेवण्‍यासाठी &lt;span class='key'&gt;Esc&lt;/span&gt; त्यानंतर डावा किंवा उजवा बाण दाबा. &lt;/p&gt; &lt;p&gt; वैकल्पिकपणे, पुढील फोकस करण्‍यायोग्य नियंत्रणावर हलविण्‍यासाठी &lt;span class='key'&gt;Tab&lt;/span&gt; दाबा. &lt;/p&gt;</translation>
<translation id="3252573918265662711">सेटअप</translation>
<translation id="3410969471888629217">साइट सानुकूलने विसरा</translation>
<translation id="3435896845095436175">सक्षम करा</translation>
diff --git a/chromium/ui/accessibility/mojom/BUILD.gn b/chromium/ui/accessibility/mojom/BUILD.gn
index d41dbd61dd7..ac10ca35074 100644
--- a/chromium/ui/accessibility/mojom/BUILD.gn
+++ b/chromium/ui/accessibility/mojom/BUILD.gn
@@ -12,6 +12,7 @@ mojom("mojom") {
"ax_host.mojom",
"ax_node_data.mojom",
"ax_tree_data.mojom",
+ "ax_tree_id.mojom",
"ax_tree_update.mojom",
]
diff --git a/chromium/ui/accessibility/mojom/ax_action_data.mojom b/chromium/ui/accessibility/mojom/ax_action_data.mojom
index 69ca868982e..f7e3238542d 100644
--- a/chromium/ui/accessibility/mojom/ax_action_data.mojom
+++ b/chromium/ui/accessibility/mojom/ax_action_data.mojom
@@ -5,13 +5,14 @@
module ax.mojom;
import "ui/accessibility/ax_enums.mojom";
+import "ui/accessibility/mojom/ax_tree_id.mojom";
import "ui/gfx/geometry/mojo/geometry.mojom";
// A compact representation of an accessibility action and the arguments
// associated with that action. See ui::AXActionData for full documentation.
struct AXActionData {
Action action;
- int32 target_tree_id;
+ ax.mojom.AXTreeID target_tree_id;
string source_extension_id;
int32 target_node_id;
int32 request_id;
diff --git a/chromium/ui/accessibility/mojom/ax_action_data_mojom_traits.cc b/chromium/ui/accessibility/mojom/ax_action_data_mojom_traits.cc
index 5e4010ec1a0..cfab7ca502b 100644
--- a/chromium/ui/accessibility/mojom/ax_action_data_mojom_traits.cc
+++ b/chromium/ui/accessibility/mojom/ax_action_data_mojom_traits.cc
@@ -12,7 +12,8 @@ bool StructTraits<ax::mojom::AXActionDataDataView, ui::AXActionData>::Read(
ui::AXActionData* out) {
if (!data.ReadAction(&out->action))
return false;
- out->target_tree_id = data.target_tree_id();
+ if (!data.ReadTargetTreeId(&out->target_tree_id))
+ return false;
if (!data.ReadSourceExtensionId(&out->source_extension_id))
return false;
out->target_node_id = data.target_node_id();
diff --git a/chromium/ui/accessibility/mojom/ax_action_data_mojom_traits.h b/chromium/ui/accessibility/mojom/ax_action_data_mojom_traits.h
index 39782b5734d..3a0b5730b90 100644
--- a/chromium/ui/accessibility/mojom/ax_action_data_mojom_traits.h
+++ b/chromium/ui/accessibility/mojom/ax_action_data_mojom_traits.h
@@ -7,6 +7,7 @@
#include "ui/accessibility/ax_action_data.h"
#include "ui/accessibility/mojom/ax_action_data.mojom-shared.h"
+#include "ui/accessibility/mojom/ax_tree_id_mojom_traits.h"
#include "ui/gfx/geometry/mojo/geometry_struct_traits.h"
namespace mojo {
@@ -16,10 +17,10 @@ struct StructTraits<ax::mojom::AXActionDataDataView, ui::AXActionData> {
static ax::mojom::Action action(const ui::AXActionData& a) {
return a.action;
}
- static int32_t target_tree_id(const ui::AXActionData& a) {
+ static const ui::AXTreeID& target_tree_id(const ui::AXActionData& a) {
return a.target_tree_id;
}
- static std::string source_extension_id(const ui::AXActionData& a) {
+ static const std::string& source_extension_id(const ui::AXActionData& a) {
return a.source_extension_id;
}
static int32_t target_node_id(const ui::AXActionData& a) {
@@ -42,13 +43,13 @@ struct StructTraits<ax::mojom::AXActionDataDataView, ui::AXActionData> {
static int32_t custom_action_id(const ui::AXActionData& a) {
return a.custom_action_id;
}
- static gfx::Rect target_rect(const ui::AXActionData& a) {
+ static const gfx::Rect& target_rect(const ui::AXActionData& a) {
return a.target_rect;
}
- static gfx::Point target_point(const ui::AXActionData& a) {
+ static const gfx::Point& target_point(const ui::AXActionData& a) {
return a.target_point;
}
- static std::string value(const ui::AXActionData& a) { return a.value; }
+ static const std::string& value(const ui::AXActionData& a) { return a.value; }
static ax::mojom::Event hit_test_event_to_fire(const ui::AXActionData& a) {
return a.hit_test_event_to_fire;
}
diff --git a/chromium/ui/accessibility/mojom/ax_action_data_mojom_traits_unittest.cc b/chromium/ui/accessibility/mojom/ax_action_data_mojom_traits_unittest.cc
index 5ff45afc3c5..68603e3c5b5 100644
--- a/chromium/ui/accessibility/mojom/ax_action_data_mojom_traits_unittest.cc
+++ b/chromium/ui/accessibility/mojom/ax_action_data_mojom_traits_unittest.cc
@@ -17,7 +17,7 @@ using mojo::test::SerializeAndDeserialize;
TEST(AXActionDataMojomTraitsTest, RoundTrip) {
ui::AXActionData input;
input.action = ax::mojom::Action::kBlur;
- input.target_tree_id = 1;
+ input.target_tree_id = ui::AXTreeID::FromString("1");
input.source_extension_id = "extension_id";
input.target_node_id = 2;
input.request_id = 3;
@@ -37,7 +37,7 @@ TEST(AXActionDataMojomTraitsTest, RoundTrip) {
SerializeAndDeserialize<ax::mojom::AXActionData>(&input, &output));
EXPECT_EQ(output.action, ax::mojom::Action::kBlur);
- EXPECT_EQ(output.target_tree_id, 1);
+ EXPECT_EQ(output.target_tree_id.ToString(), "1");
EXPECT_EQ(output.source_extension_id, "extension_id");
EXPECT_EQ(output.target_node_id, 2);
EXPECT_EQ(output.request_id, 3);
diff --git a/chromium/ui/accessibility/mojom/ax_host.mojom b/chromium/ui/accessibility/mojom/ax_host.mojom
index ac5b143828c..10c300b8747 100644
--- a/chromium/ui/accessibility/mojom/ax_host.mojom
+++ b/chromium/ui/accessibility/mojom/ax_host.mojom
@@ -7,6 +7,7 @@ module ax.mojom;
import "ui/accessibility/ax_enums.mojom";
import "ui/accessibility/mojom/ax_action_data.mojom";
import "ui/accessibility/mojom/ax_event.mojom";
+import "ui/accessibility/mojom/ax_tree_id.mojom";
import "ui/accessibility/mojom/ax_tree_update.mojom";
const string kAXHostServiceName = "ax_host_service";
@@ -18,14 +19,17 @@ const string kAXHostServiceName = "ax_host_service";
// browser.
// * Sends requests for actions (e.g. click a button) to the remote process.
interface AXHost {
- // Registers a host in a remote process.
- // TODO(jamescook): Support multiple remote processes.
- SetRemoteHost(AXRemoteHost remote);
+ // Registers a host in a remote process. |tree_id| is the ID to use as the
+ // root of the AX node tree. If |automation_enabled| is true then the remote
+ // process must send its initial AX node tree immediately (because a feature
+ // like ChromeVox is enabled).
+ RegisterRemoteHost(AXRemoteHost remote) =>
+ (ax.mojom.AXTreeID tree_id, bool automation_enabled);
// Handles an accessibility |event| (e.g. focus change) for |tree_id| in the
// remote process. Includes |updates| to child nodes.
HandleAccessibilityEvent(
- int32 tree_id, array<AXTreeUpdate> updates, AXEvent event);
+ ax.mojom.AXTreeID tree_id, array<AXTreeUpdate> updates, AXEvent event);
};
// Remote hosts run outside the browser process, for example in a mojo app like
diff --git a/chromium/ui/accessibility/mojom/ax_tree_data.mojom b/chromium/ui/accessibility/mojom/ax_tree_data.mojom
index 668134576bd..c2fabbf2be9 100644
--- a/chromium/ui/accessibility/mojom/ax_tree_data.mojom
+++ b/chromium/ui/accessibility/mojom/ax_tree_data.mojom
@@ -5,12 +5,13 @@
module ax.mojom;
import "ui/accessibility/ax_enums.mojom";
+import "ui/accessibility/mojom/ax_tree_id.mojom";
// See ui::AXTreeData for comments / explanations of these fields.
struct AXTreeData {
- int32 tree_id;
- int32 parent_tree_id;
- int32 focused_tree_id;
+ ax.mojom.AXTreeID tree_id;
+ ax.mojom.AXTreeID parent_tree_id;
+ ax.mojom.AXTreeID focused_tree_id;
string doctype;
bool loaded;
float loading_progress;
diff --git a/chromium/ui/accessibility/mojom/ax_tree_data_mojom_traits.cc b/chromium/ui/accessibility/mojom/ax_tree_data_mojom_traits.cc
index 4c465686e8c..50ad6115221 100644
--- a/chromium/ui/accessibility/mojom/ax_tree_data_mojom_traits.cc
+++ b/chromium/ui/accessibility/mojom/ax_tree_data_mojom_traits.cc
@@ -10,9 +10,12 @@ namespace mojo {
bool StructTraits<ax::mojom::AXTreeDataDataView, ui::AXTreeData>::Read(
ax::mojom::AXTreeDataDataView data,
ui::AXTreeData* out) {
- out->tree_id = data.tree_id();
- out->parent_tree_id = data.parent_tree_id();
- out->focused_tree_id = data.focused_tree_id();
+ if (!data.ReadTreeId(&out->tree_id))
+ return false;
+ if (!data.ReadParentTreeId(&out->parent_tree_id))
+ return false;
+ if (!data.ReadFocusedTreeId(&out->focused_tree_id))
+ return false;
if (!data.ReadDoctype(&out->doctype))
return false;
out->loaded = data.loaded();
diff --git a/chromium/ui/accessibility/mojom/ax_tree_data_mojom_traits.h b/chromium/ui/accessibility/mojom/ax_tree_data_mojom_traits.h
index 0b3a2b138b9..6beea9732ad 100644
--- a/chromium/ui/accessibility/mojom/ax_tree_data_mojom_traits.h
+++ b/chromium/ui/accessibility/mojom/ax_tree_data_mojom_traits.h
@@ -7,26 +7,33 @@
#include "ui/accessibility/ax_tree_data.h"
#include "ui/accessibility/mojom/ax_tree_data.mojom-shared.h"
+#include "ui/accessibility/mojom/ax_tree_id_mojom_traits.h"
namespace mojo {
template <>
struct StructTraits<ax::mojom::AXTreeDataDataView, ui::AXTreeData> {
- static int32_t tree_id(const ui::AXTreeData& p) { return p.tree_id; }
- static int32_t parent_tree_id(const ui::AXTreeData& p) {
+ static const ui::AXTreeID& tree_id(const ui::AXTreeData& p) {
+ return p.tree_id;
+ }
+ static const ui::AXTreeID& parent_tree_id(const ui::AXTreeData& p) {
return p.parent_tree_id;
}
- static int32_t focused_tree_id(const ui::AXTreeData& p) {
+ static const ui::AXTreeID& focused_tree_id(const ui::AXTreeData& p) {
return p.focused_tree_id;
}
- static std::string doctype(const ui::AXTreeData& p) { return p.doctype; }
+ static const std::string& doctype(const ui::AXTreeData& p) {
+ return p.doctype;
+ }
static bool loaded(const ui::AXTreeData& p) { return p.loaded; }
static float loading_progress(const ui::AXTreeData& p) {
return p.loading_progress;
}
- static std::string mimetype(const ui::AXTreeData& p) { return p.mimetype; }
- static std::string title(const ui::AXTreeData& p) { return p.title; }
- static std::string url(const ui::AXTreeData& p) { return p.url; }
+ static const std::string& mimetype(const ui::AXTreeData& p) {
+ return p.mimetype;
+ }
+ static const std::string& title(const ui::AXTreeData& p) { return p.title; }
+ static const std::string& url(const ui::AXTreeData& p) { return p.url; }
static int32_t focus_id(const ui::AXTreeData& p) { return p.focus_id; }
static int32_t sel_anchor_object_id(const ui::AXTreeData& p) {
return p.sel_anchor_object_id;
diff --git a/chromium/ui/accessibility/mojom/ax_tree_data_mojom_traits_unittest.cc b/chromium/ui/accessibility/mojom/ax_tree_data_mojom_traits_unittest.cc
index 02496fbb001..d64ff2c8fe7 100644
--- a/chromium/ui/accessibility/mojom/ax_tree_data_mojom_traits_unittest.cc
+++ b/chromium/ui/accessibility/mojom/ax_tree_data_mojom_traits_unittest.cc
@@ -12,9 +12,9 @@ using mojo::test::SerializeAndDeserialize;
TEST(AXTreeDataMojomTraitsTest, TestSerializeAndDeserializeAXTreeData) {
ui::AXTreeData input, output;
- input.tree_id = 1;
- input.parent_tree_id = 2;
- input.focused_tree_id = 3;
+ input.tree_id = ui::AXTreeID::FromString("1");
+ input.parent_tree_id = ui::AXTreeID::FromString("2");
+ input.focused_tree_id = ui::AXTreeID::FromString("3");
input.doctype = "4";
input.loaded = true;
input.loading_progress = 5;
@@ -31,9 +31,9 @@ TEST(AXTreeDataMojomTraitsTest, TestSerializeAndDeserializeAXTreeData) {
EXPECT_TRUE(SerializeAndDeserialize<ax::mojom::AXTreeData>(&input, &output));
- EXPECT_EQ(1, output.tree_id);
- EXPECT_EQ(2, output.parent_tree_id);
- EXPECT_EQ(3, output.focused_tree_id);
+ EXPECT_EQ("1", output.tree_id.ToString());
+ EXPECT_EQ("2", output.parent_tree_id.ToString());
+ EXPECT_EQ("3", output.focused_tree_id.ToString());
EXPECT_EQ("4", output.doctype);
EXPECT_EQ(true, output.loaded);
EXPECT_EQ(5, output.loading_progress);
diff --git a/chromium/ui/accessibility/mojom/ax_tree_id.mojom b/chromium/ui/accessibility/mojom/ax_tree_id.mojom
new file mode 100644
index 00000000000..6cc327b402d
--- /dev/null
+++ b/chromium/ui/accessibility/mojom/ax_tree_id.mojom
@@ -0,0 +1,10 @@
+// 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.
+
+module ax.mojom;
+
+struct AXTreeID {
+ // Eventually this may become a base::UnguessableToken.
+ string id;
+};
diff --git a/chromium/ui/accessibility/mojom/ax_tree_id.typemap b/chromium/ui/accessibility/mojom/ax_tree_id.typemap
new file mode 100644
index 00000000000..034ddbe036c
--- /dev/null
+++ b/chromium/ui/accessibility/mojom/ax_tree_id.typemap
@@ -0,0 +1,15 @@
+# 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.
+
+mojom = "//ui/accessibility/mojom/ax_tree_id.mojom"
+public_headers = [ "//ui/accessibility/ax_tree_id.h" ]
+traits_headers = [ "//ui/accessibility/mojom/ax_tree_id_mojom_traits.h" ]
+sources = [
+ "ax_tree_id_mojom_traits.cc",
+ "ax_tree_id_mojom_traits.h",
+]
+public_deps = [
+ "//ui/accessibility",
+]
+type_mappings = [ "ax.mojom.AXTreeID=ui::AXTreeID" ]
diff --git a/chromium/ui/accessibility/mojom/ax_tree_id_mojom_traits.cc b/chromium/ui/accessibility/mojom/ax_tree_id_mojom_traits.cc
new file mode 100644
index 00000000000..949b7db86e4
--- /dev/null
+++ b/chromium/ui/accessibility/mojom/ax_tree_id_mojom_traits.cc
@@ -0,0 +1,18 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/accessibility/mojom/ax_tree_id_mojom_traits.h"
+
+namespace mojo {
+
+// static
+bool StructTraits<ax::mojom::AXTreeIDDataView, ui::AXTreeID>::Read(
+ ax::mojom::AXTreeIDDataView data,
+ ui::AXTreeID* out) {
+ if (!data.ReadId(&out->id_))
+ return false;
+ return true;
+}
+
+} // namespace mojo
diff --git a/chromium/ui/accessibility/mojom/ax_tree_id_mojom_traits.h b/chromium/ui/accessibility/mojom/ax_tree_id_mojom_traits.h
new file mode 100644
index 00000000000..df481aad53a
--- /dev/null
+++ b/chromium/ui/accessibility/mojom/ax_tree_id_mojom_traits.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_ACCESSIBILITY_MOJOM_AX_TREE_ID_MOJOM_TRAITS_H_
+#define UI_ACCESSIBILITY_MOJOM_AX_TREE_ID_MOJOM_TRAITS_H_
+
+#include "ui/accessibility/ax_tree_id.h"
+#include "ui/accessibility/mojom/ax_tree_id.mojom-shared.h"
+
+namespace mojo {
+
+template <>
+struct StructTraits<ax::mojom::AXTreeIDDataView, ui::AXTreeID> {
+ static const std::string& id(const ui::AXTreeID& p) { return p.ToString(); }
+
+ static bool Read(ax::mojom::AXTreeIDDataView data, ui::AXTreeID* out);
+};
+
+} // namespace mojo
+
+#endif // UI_ACCESSIBILITY_MOJOM_AX_TREE_ID_MOJOM_TRAITS_H_
diff --git a/chromium/ui/accessibility/mojom/ax_tree_id_mojom_traits_unittest.cc b/chromium/ui/accessibility/mojom/ax_tree_id_mojom_traits_unittest.cc
new file mode 100644
index 00000000000..3f0f4837caf
--- /dev/null
+++ b/chromium/ui/accessibility/mojom/ax_tree_id_mojom_traits_unittest.cc
@@ -0,0 +1,18 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/accessibility/mojom/ax_tree_id_mojom_traits.h"
+#include "mojo/public/cpp/test_support/test_utils.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/accessibility/ax_tree_id.h"
+#include "ui/accessibility/mojom/ax_tree_id.mojom.h"
+
+using mojo::test::SerializeAndDeserialize;
+
+TEST(AXTreeIDMojomTraitsTest, TestSerializeAndDeserializeAXTreeID) {
+ ui::AXTreeID input = ui::AXTreeID::FromString("abc");
+ ui::AXTreeID output;
+ EXPECT_TRUE(SerializeAndDeserialize<ax::mojom::AXTreeID>(&input, &output));
+ EXPECT_EQ("abc", output.ToString());
+}
diff --git a/chromium/ui/accessibility/mojom/typemaps.gni b/chromium/ui/accessibility/mojom/typemaps.gni
index 0ed9a30f168..ba8b1e10e01 100644
--- a/chromium/ui/accessibility/mojom/typemaps.gni
+++ b/chromium/ui/accessibility/mojom/typemaps.gni
@@ -8,5 +8,6 @@ typemaps = [
"//ui/accessibility/mojom/ax_event.typemap",
"//ui/accessibility/mojom/ax_node_data.typemap",
"//ui/accessibility/mojom/ax_tree_data.typemap",
+ "//ui/accessibility/mojom/ax_tree_id.typemap",
"//ui/accessibility/mojom/ax_tree_update.typemap",
]
diff --git a/chromium/ui/accessibility/platform/aura_window_properties.cc b/chromium/ui/accessibility/platform/aura_window_properties.cc
index e72b2d26e9a..2a51fadc5b8 100644
--- a/chromium/ui/accessibility/platform/aura_window_properties.cc
+++ b/chromium/ui/accessibility/platform/aura_window_properties.cc
@@ -4,15 +4,14 @@
#include "ui/accessibility/platform/aura_window_properties.h"
+#include "ui/accessibility/ax_tree_id.h"
#include "ui/base/class_property.h"
DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AX_EXPORT, ax::mojom::Role)
namespace ui {
-DEFINE_UI_CLASS_PROPERTY_KEY(AXTreeIDRegistry::AXTreeID,
- kChildAXTreeID,
- AXTreeIDRegistry::kNoAXTreeID);
+DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(std::string, kChildAXTreeID, nullptr);
DEFINE_UI_CLASS_PROPERTY_KEY(ax::mojom::Role,
kAXRoleOverride,
diff --git a/chromium/ui/accessibility/platform/aura_window_properties.h b/chromium/ui/accessibility/platform/aura_window_properties.h
index c78850da22f..8fcf89fd3f7 100644
--- a/chromium/ui/accessibility/platform/aura_window_properties.h
+++ b/chromium/ui/accessibility/platform/aura_window_properties.h
@@ -5,15 +5,19 @@
#ifndef UI_ACCESSIBILITY_PLATFORM_AURA_WINDOW_PROPERTIES_H_
#define UI_ACCESSIBILITY_PLATFORM_AURA_WINDOW_PROPERTIES_H_
+#include <string>
+
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_export.h"
-#include "ui/accessibility/ax_tree_id_registry.h"
#include "ui/aura/window.h"
namespace ui {
-AX_EXPORT extern const aura::WindowProperty<AXTreeIDRegistry::AXTreeID>* const
- kChildAXTreeID;
+// Value is a serialized |ui::AXTreeID| because code in //ui/aura/mus needs
+// to serialize the window property, but //ui/aura cannot depend on
+// //ui/accessibility and hence cannot know about the type ui::AXTreeID.
+// TODO(dmazzoni): Convert from string to base::UnguessableToken.
+AX_EXPORT extern const aura::WindowProperty<std::string*>* const kChildAXTreeID;
AX_EXPORT extern const aura::WindowProperty<ax::mojom::Role>* const
kAXRoleOverride;
diff --git a/chromium/ui/accessibility/platform/ax_platform_atk_hyperlink.cc b/chromium/ui/accessibility/platform/ax_platform_atk_hyperlink.cc
index c13f6dbdf5d..c3d8f32a69d 100644
--- a/chromium/ui/accessibility/platform/ax_platform_atk_hyperlink.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_atk_hyperlink.cc
@@ -10,23 +10,28 @@
namespace ui {
-static gpointer ax_platform_atk_hyperlink_parent_class = nullptr;
+struct _AXPlatformAtkHyperlinkPrivate {
+ AXPlatformNodeAuraLinux* platform_node = nullptr;
+ base::Optional<int> end_index;
+ base::Optional<int> start_index;
+};
+
+static gpointer kAXPlatformAtkHyperlinkParentClass = nullptr;
static AXPlatformNodeAuraLinux* ToAXPlatformNodeAuraLinux(
AXPlatformAtkHyperlink* atk_hyperlink) {
if (!atk_hyperlink)
return nullptr;
-
- return atk_hyperlink->m_object;
+ return atk_hyperlink->priv->platform_node;
}
-static void ax_platform_atk_hyperlink_finalize(GObject* atk_hyperlink) {
- G_OBJECT_CLASS(ax_platform_atk_hyperlink_parent_class)
- ->finalize(atk_hyperlink);
+static void AXPlatformAtkHyperlinkFinalize(GObject* self) {
+ AX_PLATFORM_ATK_HYPERLINK(self)->priv->~AXPlatformAtkHyperlinkPrivate();
+ G_OBJECT_CLASS(kAXPlatformAtkHyperlinkParentClass)->finalize(self);
}
-static gchar* ax_platform_atk_hyperlink_get_uri(AtkHyperlink* atk_hyperlink,
- gint index) {
+static gchar* AXPlatformAtkHyperlinkGetUri(AtkHyperlink* atk_hyperlink,
+ gint index) {
AXPlatformNodeAuraLinux* obj =
ToAXPlatformNodeAuraLinux(AX_PLATFORM_ATK_HYPERLINK(atk_hyperlink));
if (!obj)
@@ -39,9 +44,8 @@ static gchar* ax_platform_atk_hyperlink_get_uri(AtkHyperlink* atk_hyperlink,
obj->GetStringAttribute(ax::mojom::StringAttribute::kUrl).c_str());
}
-static AtkObject* ax_platform_atk_hyperlink_get_object(
- AtkHyperlink* atk_hyperlink,
- gint index) {
+static AtkObject* AXPlatformAtkHyperlinkGetObject(AtkHyperlink* atk_hyperlink,
+ gint index) {
AXPlatformNodeAuraLinux* obj =
ToAXPlatformNodeAuraLinux(AX_PLATFORM_ATK_HYPERLINK(atk_hyperlink));
if (!obj)
@@ -53,45 +57,57 @@ static AtkObject* ax_platform_atk_hyperlink_get_object(
return ATK_OBJECT(obj->GetNativeViewAccessible());
}
-static gint ax_platform_atk_hyperlink_get_n_anchors(
- AtkHyperlink* atk_hyperlink) {
+static gint AXPlatformAtkHyperlinkGetNAnchors(AtkHyperlink* atk_hyperlink) {
AXPlatformNodeAuraLinux* obj =
ToAXPlatformNodeAuraLinux(AX_PLATFORM_ATK_HYPERLINK(atk_hyperlink));
return obj ? 1 : 0;
}
-static gboolean ax_platform_atk_hyperlink_is_valid(
- AtkHyperlink* atk_hyperlink) {
+static gboolean AXPlatformAtkHyperlinkIsValid(AtkHyperlink* atk_hyperlink) {
AXPlatformNodeAuraLinux* obj =
ToAXPlatformNodeAuraLinux(AX_PLATFORM_ATK_HYPERLINK(atk_hyperlink));
return obj ? TRUE : FALSE;
}
-static gboolean ax_platform_atk_hyperlink_is_selected_link(
+static gboolean AXPlatformAtkHyperlinkIsSelectedLink(
AtkHyperlink* atk_hyperlink) {
AXPlatformNodeAuraLinux* obj =
ToAXPlatformNodeAuraLinux(AX_PLATFORM_ATK_HYPERLINK(atk_hyperlink));
-
if (!obj)
return false;
return obj->GetDelegate()->GetFocus() == obj->GetNativeViewAccessible();
}
-static void ax_platform_atk_hyperlink_class_init(AtkHyperlinkClass* klass) {
- GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
- ax_platform_atk_hyperlink_parent_class = g_type_class_peek_parent(klass);
+static int AXPlatformAtkHyperlinkGetStartIndex(AtkHyperlink* atk_hyperlink) {
+ g_return_val_if_fail(IS_AX_PLATFORM_ATK_HYPERLINK(atk_hyperlink), 0);
+ AXPlatformAtkHyperlink* link = AX_PLATFORM_ATK_HYPERLINK(atk_hyperlink);
+ return link->priv->start_index ? *link->priv->start_index : 0;
+}
- gobject_class->finalize = ax_platform_atk_hyperlink_finalize;
- klass->get_uri = ax_platform_atk_hyperlink_get_uri;
- klass->get_object = ax_platform_atk_hyperlink_get_object;
- klass->is_valid = ax_platform_atk_hyperlink_is_valid;
- klass->get_n_anchors = ax_platform_atk_hyperlink_get_n_anchors;
- klass->is_selected_link = ax_platform_atk_hyperlink_is_selected_link;
- // TODO(jose.dapena) implement get_start_index and get_end_index methods
- // that should provide the range of the link in the embedding text.
+static int AXPlatformAtkHyperlinkGetEndIndex(AtkHyperlink* atk_hyperlink) {
+ g_return_val_if_fail(IS_AX_PLATFORM_ATK_HYPERLINK(atk_hyperlink), 0);
+ AXPlatformAtkHyperlink* link = AX_PLATFORM_ATK_HYPERLINK(atk_hyperlink);
+ return link->priv->end_index ? *link->priv->end_index : 0;
+}
+
+static void AXPlatformAtkHyperlinkClassInit(AtkHyperlinkClass* klass) {
+ GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
+ kAXPlatformAtkHyperlinkParentClass = g_type_class_peek_parent(klass);
+
+ g_type_class_add_private(gobject_class,
+ sizeof(AXPlatformAtkHyperlinkPrivate));
+
+ gobject_class->finalize = AXPlatformAtkHyperlinkFinalize;
+ klass->get_uri = AXPlatformAtkHyperlinkGetUri;
+ klass->get_object = AXPlatformAtkHyperlinkGetObject;
+ klass->is_valid = AXPlatformAtkHyperlinkIsValid;
+ klass->get_n_anchors = AXPlatformAtkHyperlinkGetNAnchors;
+ klass->is_selected_link = AXPlatformAtkHyperlinkIsSelectedLink;
+ klass->get_start_index = AXPlatformAtkHyperlinkGetStartIndex;
+ klass->get_end_index = AXPlatformAtkHyperlinkGetEndIndex;
}
//
@@ -208,10 +224,27 @@ static void atk_action_interface_init(AtkActionIface* iface) {
iface->get_localized_name = ax_platform_atk_hyperlink_get_localized_name;
}
-void ax_platform_atk_hyperlink_set_object(AXPlatformAtkHyperlink* atk_hyperlink,
- AXPlatformNodeAuraLinux* obj) {
+void ax_platform_atk_hyperlink_set_object(
+ AXPlatformAtkHyperlink* atk_hyperlink,
+ AXPlatformNodeAuraLinux* platform_node) {
g_return_if_fail(AX_PLATFORM_ATK_HYPERLINK(atk_hyperlink));
- atk_hyperlink->m_object = obj;
+ atk_hyperlink->priv->platform_node = platform_node;
+}
+
+void ax_platform_atk_hyperlink_set_indices(
+ AXPlatformAtkHyperlink* atk_hyperlink,
+ int start_index,
+ int end_index) {
+ atk_hyperlink->priv->start_index = start_index;
+ atk_hyperlink->priv->end_index = end_index;
+}
+
+static void AXPlatformAtkHyperlinkInit(AXPlatformAtkHyperlink* self, gpointer) {
+ AXPlatformAtkHyperlinkPrivate* priv =
+ G_TYPE_INSTANCE_GET_PRIVATE(self, ax_platform_atk_hyperlink_get_type(),
+ AXPlatformAtkHyperlinkPrivate);
+ self->priv = priv;
+ new (priv) AXPlatformAtkHyperlinkPrivate();
}
GType ax_platform_atk_hyperlink_get_type() {
@@ -224,12 +257,12 @@ GType ax_platform_atk_hyperlink_get_type() {
sizeof(AXPlatformAtkHyperlinkClass),
(GBaseInitFunc) nullptr,
(GBaseFinalizeFunc) nullptr,
- (GClassInitFunc)ax_platform_atk_hyperlink_class_init,
+ (GClassInitFunc)AXPlatformAtkHyperlinkClassInit,
(GClassFinalizeFunc) nullptr,
nullptr, /* class data */
sizeof(AXPlatformAtkHyperlink), /* instance size */
0, /* nb preallocs */
- (GInstanceInitFunc) nullptr,
+ (GInstanceInitFunc)AXPlatformAtkHyperlinkInit,
nullptr /* value table */
};
diff --git a/chromium/ui/accessibility/platform/ax_platform_atk_hyperlink.h b/chromium/ui/accessibility/platform/ax_platform_atk_hyperlink.h
index 9704f8b5553..733d418ec20 100644
--- a/chromium/ui/accessibility/platform/ax_platform_atk_hyperlink.h
+++ b/chromium/ui/accessibility/platform/ax_platform_atk_hyperlink.h
@@ -30,10 +30,13 @@ G_BEGIN_DECLS
typedef struct _AXPlatformAtkHyperlink AXPlatformAtkHyperlink;
typedef struct _AXPlatformAtkHyperlinkClass AXPlatformAtkHyperlinkClass;
+typedef struct _AXPlatformAtkHyperlinkPrivate AXPlatformAtkHyperlinkPrivate;
struct _AXPlatformAtkHyperlink {
AtkHyperlink parent;
- AXPlatformNodeAuraLinux* m_object;
+
+ /*< private >*/
+ AXPlatformAtkHyperlinkPrivate* priv;
};
struct _AXPlatformAtkHyperlinkClass {
@@ -43,6 +46,10 @@ struct _AXPlatformAtkHyperlinkClass {
GType ax_platform_atk_hyperlink_get_type(void) G_GNUC_CONST;
void ax_platform_atk_hyperlink_set_object(AXPlatformAtkHyperlink* hyperlink,
AXPlatformNodeAuraLinux* obj);
+void ax_platform_atk_hyperlink_set_indices(
+ AXPlatformAtkHyperlink* atk_hyperlink,
+ int start_index,
+ int end_index);
G_END_DECLS
diff --git a/chromium/ui/accessibility/platform/ax_platform_node.h b/chromium/ui/accessibility/platform/ax_platform_node.h
index 9430ddbb50a..278107bc458 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node.h
+++ b/chromium/ui/accessibility/platform/ax_platform_node.h
@@ -11,8 +11,8 @@
#include "build/build_config.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_export.h"
+#include "ui/accessibility/ax_mode.h"
#include "ui/accessibility/ax_mode_observer.h"
-#include "ui/accessibility/ax_modes.h"
#include "ui/gfx/native_widget_types.h"
namespace ui {
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_auralinux.cc b/chromium/ui/accessibility/platform/ax_platform_node_auralinux.cc
index 949ca8bb3a5..c61d9ea4e11 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_auralinux.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -15,6 +15,7 @@
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/accessibility/ax_action_data.h"
+#include "ui/accessibility/ax_mode_observer.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/ax_text_utils.h"
#include "ui/accessibility/ax_tree_data.h"
@@ -23,6 +24,8 @@
#include "ui/accessibility/platform/ax_platform_node_delegate.h"
#include "ui/gfx/geometry/rect_conversions.h"
+namespace ui {
+
//
// ax_platform_node_auralinux AtkObject definition and implementation.
//
@@ -201,7 +204,7 @@ constexpr AtkRole kAtkFootnoteRole = ATK_ROLE_LIST_ITEM;
struct _AXPlatformNodeAuraLinuxObject {
AtkObject parent;
- ui::AXPlatformNodeAuraLinux* m_object;
+ AXPlatformNodeAuraLinux* m_object;
};
struct _AXPlatformNodeAuraLinuxClass {
@@ -210,9 +213,9 @@ struct _AXPlatformNodeAuraLinuxClass {
GType ax_platform_node_auralinux_get_type();
-static gpointer ax_platform_node_auralinux_parent_class = nullptr;
+static gpointer kAXPlatformNodeAuraLinuxParentClass = nullptr;
-static ui::AXPlatformNodeAuraLinux* ToAXPlatformNodeAuraLinux(
+static AXPlatformNodeAuraLinux* ToAXPlatformNodeAuraLinux(
AXPlatformNodeAuraLinuxObject* atk_object) {
if (!atk_object)
return nullptr;
@@ -220,7 +223,7 @@ static ui::AXPlatformNodeAuraLinux* ToAXPlatformNodeAuraLinux(
return atk_object->m_object;
}
-static ui::AXPlatformNodeAuraLinux* AtkObjectToAXPlatformNodeAuraLinux(
+static AXPlatformNodeAuraLinux* AtkObjectToAXPlatformNodeAuraLinux(
AtkObject* atk_object) {
if (!atk_object)
return nullptr;
@@ -231,9 +234,8 @@ static ui::AXPlatformNodeAuraLinux* AtkObjectToAXPlatformNodeAuraLinux(
return nullptr;
}
-static const gchar* ax_platform_node_auralinux_get_name(AtkObject* atk_object) {
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+static const gchar* AXPlatformNodeAuraLinuxGetName(AtkObject* atk_object) {
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return nullptr;
@@ -245,10 +247,9 @@ static const gchar* ax_platform_node_auralinux_get_name(AtkObject* atk_object) {
return obj->GetStringAttribute(ax::mojom::StringAttribute::kName).c_str();
}
-static const gchar* ax_platform_node_auralinux_get_description(
+static const gchar* AXPlatformNodeAuraLinuxGetDescription(
AtkObject* atk_object) {
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return nullptr;
@@ -256,10 +257,8 @@ static const gchar* ax_platform_node_auralinux_get_description(
.c_str();
}
-static gint ax_platform_node_auralinux_get_index_in_parent(
- AtkObject* atk_object) {
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+static gint AXPlatformNodeAuraLinuxGetIndexInParent(AtkObject* atk_object) {
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return -1;
@@ -267,28 +266,25 @@ static gint ax_platform_node_auralinux_get_index_in_parent(
return obj->GetIndexInParent();
}
-static AtkObject* ax_platform_node_auralinux_get_parent(AtkObject* atk_object) {
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+static AtkObject* AXPlatformNodeAuraLinuxGetParent(AtkObject* atk_object) {
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return nullptr;
return obj->GetParent();
}
-static gint ax_platform_node_auralinux_get_n_children(AtkObject* atk_object) {
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+static gint AXPlatformNodeAuraLinuxGetNChildren(AtkObject* atk_object) {
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return 0;
return obj->GetChildCount();
}
-static AtkObject* ax_platform_node_auralinux_ref_child(
- AtkObject* atk_object, gint index) {
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+static AtkObject* AXPlatformNodeAuraLinuxRefChild(AtkObject* atk_object,
+ gint index) {
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return nullptr;
@@ -298,13 +294,12 @@ static AtkObject* ax_platform_node_auralinux_ref_child(
return result;
}
-static AtkRelationSet* ax_platform_node_auralinux_ref_relation_set(
+static AtkRelationSet* AXPlatformNodeAuraLinuxRefRelationSet(
AtkObject* atk_object) {
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
AtkRelationSet* atk_relation_set =
- ATK_OBJECT_CLASS(ax_platform_node_auralinux_parent_class)->
- ref_relation_set(atk_object);
+ ATK_OBJECT_CLASS(kAXPlatformNodeAuraLinuxParentClass)
+ ->ref_relation_set(atk_object);
if (!obj)
return atk_relation_set;
@@ -313,33 +308,28 @@ static AtkRelationSet* ax_platform_node_auralinux_ref_relation_set(
return atk_relation_set;
}
-static AtkAttributeSet* ax_platform_node_auralinux_get_attributes(
+static AtkAttributeSet* AXPlatformNodeAuraLinuxGetAttributes(
AtkObject* atk_object) {
-
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return nullptr;
return obj->GetAtkAttributes();
}
-static AtkRole ax_platform_node_auralinux_get_role(AtkObject* atk_object) {
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+static AtkRole AXPlatformNodeAuraLinuxGetRole(AtkObject* atk_object) {
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return ATK_ROLE_INVALID;
return obj->GetAtkRole();
}
-static AtkStateSet* ax_platform_node_auralinux_ref_state_set(
- AtkObject* atk_object) {
+static AtkStateSet* AXPlatformNodeAuraLinuxRefStateSet(AtkObject* atk_object) {
AtkStateSet* atk_state_set =
- ATK_OBJECT_CLASS(ax_platform_node_auralinux_parent_class)->
- ref_state_set(atk_object);
+ ATK_OBJECT_CLASS(kAXPlatformNodeAuraLinuxParentClass)
+ ->ref_state_set(atk_object);
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj) {
atk_state_set_add_state(atk_state_set, ATK_STATE_DEFUNCT);
} else {
@@ -368,10 +358,12 @@ static gfx::Point FindAtkObjectParentCoords(AtkObject* atk_object) {
return FindAtkObjectParentCoords(atk_object);
}
-static void ax_platform_node_auralinux_get_extents(AtkComponent* atk_component,
- gint* x, gint* y,
- gint* width, gint* height,
- AtkCoordType coord_type) {
+static void AXPlatformNodeAuraLinuxGetExtents(AtkComponent* atk_component,
+ gint* x,
+ gint* y,
+ gint* width,
+ gint* height,
+ AtkCoordType coord_type) {
g_return_if_fail(ATK_IS_COMPONENT(atk_component));
if (x)
@@ -384,17 +376,17 @@ static void ax_platform_node_auralinux_get_extents(AtkComponent* atk_component,
*height = 0;
AtkObject* atk_object = ATK_OBJECT(atk_component);
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return;
obj->GetExtents(x, y, width, height, coord_type);
}
-static void ax_platform_node_auralinux_get_position(AtkComponent* atk_component,
- gint* x, gint* y,
- AtkCoordType coord_type) {
+static void AXPlatformNodeAuraLinuxGetPosition(AtkComponent* atk_component,
+ gint* x,
+ gint* y,
+ AtkCoordType coord_type) {
g_return_if_fail(ATK_IS_COMPONENT(atk_component));
if (x)
@@ -403,16 +395,16 @@ static void ax_platform_node_auralinux_get_position(AtkComponent* atk_component,
*y = 0;
AtkObject* atk_object = ATK_OBJECT(atk_component);
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return;
obj->GetPosition(x, y, coord_type);
}
-static void ax_platform_node_auralinux_get_size(AtkComponent* atk_component,
- gint* width, gint* height) {
+static void AXPlatformNodeAuraLinuxGetSize(AtkComponent* atk_component,
+ gint* width,
+ gint* height) {
g_return_if_fail(ATK_IS_COMPONENT(atk_component));
if (width)
@@ -421,23 +413,21 @@ static void ax_platform_node_auralinux_get_size(AtkComponent* atk_component,
*height = 0;
AtkObject* atk_object = ATK_OBJECT(atk_component);
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return;
obj->GetSize(width, height);
}
-static AtkObject* ax_platform_node_auralinux_ref_accessible_at_point(
+static AtkObject* AXPlatformNodeAuraLinuxRefAccessibleAtPoint(
AtkComponent* atk_component,
gint x,
gint y,
AtkCoordType coord_type) {
g_return_val_if_fail(ATK_IS_COMPONENT(atk_component), nullptr);
AtkObject* atk_object = ATK_OBJECT(atk_component);
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return nullptr;
@@ -447,93 +437,83 @@ static AtkObject* ax_platform_node_auralinux_ref_accessible_at_point(
return result;
}
-static gboolean ax_platform_node_auralinux_grab_focus(
- AtkComponent* atk_component) {
+static gboolean AXPlatformNodeAuraLinuxGrabFocus(AtkComponent* atk_component) {
g_return_val_if_fail(ATK_IS_COMPONENT(atk_component), FALSE);
AtkObject* atk_object = ATK_OBJECT(atk_component);
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return FALSE;
return obj->GrabFocus();
}
-void ax_component_interface_base_init(AtkComponentIface* iface) {
- iface->get_extents = ax_platform_node_auralinux_get_extents;
- iface->get_position = ax_platform_node_auralinux_get_position;
- iface->get_size = ax_platform_node_auralinux_get_size;
- iface->ref_accessible_at_point =
- ax_platform_node_auralinux_ref_accessible_at_point;
- iface->grab_focus = ax_platform_node_auralinux_grab_focus;
+void AXComponentInterfaceBaseInit(AtkComponentIface* iface) {
+ iface->get_extents = AXPlatformNodeAuraLinuxGetExtents;
+ iface->get_position = AXPlatformNodeAuraLinuxGetPosition;
+ iface->get_size = AXPlatformNodeAuraLinuxGetSize;
+ iface->ref_accessible_at_point = AXPlatformNodeAuraLinuxRefAccessibleAtPoint;
+ iface->grab_focus = AXPlatformNodeAuraLinuxGrabFocus;
}
static const GInterfaceInfo ComponentInfo = {
- reinterpret_cast<GInterfaceInitFunc>(ax_component_interface_base_init), 0, 0
-};
+ reinterpret_cast<GInterfaceInitFunc>(AXComponentInterfaceBaseInit), 0, 0};
//
// AtkAction interface
//
-static gboolean ax_platform_node_auralinux_do_action(AtkAction* atk_action,
- gint index) {
+static gboolean AXPlatformNodeAuraLinuxDoAction(AtkAction* atk_action,
+ gint index) {
g_return_val_if_fail(ATK_IS_ACTION(atk_action), FALSE);
g_return_val_if_fail(!index, FALSE);
AtkObject* atk_object = ATK_OBJECT(atk_action);
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return FALSE;
return obj->DoDefaultAction();
}
-static gint ax_platform_node_auralinux_get_n_actions(AtkAction* atk_action) {
+static gint AXPlatformNodeAuraLinuxGetNActions(AtkAction* atk_action) {
g_return_val_if_fail(ATK_IS_ACTION(atk_action), 0);
AtkObject* atk_object = ATK_OBJECT(atk_action);
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return 0;
return 1;
}
-static const gchar* ax_platform_node_auralinux_get_action_description(
- AtkAction*,
- gint) {
+static const gchar* AXPlatformNodeAuraLinuxGetActionDescription(AtkAction*,
+ gint) {
// Not implemented. Right now Orca does not provide this and
// Chromium is not providing a string for the action description.
return nullptr;
}
-static const gchar* ax_platform_node_auralinux_get_action_name(
- AtkAction* atk_action,
- gint index) {
+static const gchar* AXPlatformNodeAuraLinuxGetActionName(AtkAction* atk_action,
+ gint index) {
g_return_val_if_fail(ATK_IS_ACTION(atk_action), nullptr);
g_return_val_if_fail(!index, nullptr);
AtkObject* atk_object = ATK_OBJECT(atk_action);
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return nullptr;
return obj->GetDefaultActionName();
}
-static const gchar* ax_platform_node_auralinux_get_action_keybinding(
+static const gchar* AXPlatformNodeAuraLinuxGetActionKeybinding(
AtkAction* atk_action,
gint index) {
g_return_val_if_fail(ATK_IS_ACTION(atk_action), nullptr);
g_return_val_if_fail(!index, nullptr);
AtkObject* atk_object = ATK_OBJECT(atk_action);
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return nullptr;
@@ -541,85 +521,79 @@ static const gchar* ax_platform_node_auralinux_get_action_keybinding(
.c_str();
}
-void ax_action_interface_base_init(AtkActionIface* iface) {
- iface->do_action = ax_platform_node_auralinux_do_action;
- iface->get_n_actions = ax_platform_node_auralinux_get_n_actions;
- iface->get_description = ax_platform_node_auralinux_get_action_description;
- iface->get_name = ax_platform_node_auralinux_get_action_name;
- iface->get_keybinding = ax_platform_node_auralinux_get_action_keybinding;
+void AXActionInterfaceBaseInit(AtkActionIface* iface) {
+ iface->do_action = AXPlatformNodeAuraLinuxDoAction;
+ iface->get_n_actions = AXPlatformNodeAuraLinuxGetNActions;
+ iface->get_description = AXPlatformNodeAuraLinuxGetActionDescription;
+ iface->get_name = AXPlatformNodeAuraLinuxGetActionName;
+ iface->get_keybinding = AXPlatformNodeAuraLinuxGetActionKeybinding;
}
static const GInterfaceInfo ActionInfo = {
- reinterpret_cast<GInterfaceInitFunc>(ax_action_interface_base_init),
- nullptr, nullptr};
+ reinterpret_cast<GInterfaceInitFunc>(AXActionInterfaceBaseInit), nullptr,
+ nullptr};
// AtkDocument interface.
-static const gchar* ax_platform_node_auralinux_get_document_attribute_value(
+static const gchar* AXPlatformNodeAuraLinuGetDocumentAttributeValue(
AtkDocument* atk_doc,
const gchar* attribute) {
g_return_val_if_fail(ATK_IS_DOCUMENT(atk_doc), nullptr);
AtkObject* atk_object = ATK_OBJECT(atk_doc);
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return nullptr;
return obj->GetDocumentAttributeValue(attribute);
}
-static AtkAttributeSet* ax_platform_node_auralinux_get_document_attributes(
+static AtkAttributeSet* AXPlatformNodeAuraLinuxGetDocumentAttributes(
AtkDocument* atk_doc) {
g_return_val_if_fail(ATK_IS_DOCUMENT(atk_doc), 0);
AtkObject* atk_object = ATK_OBJECT(atk_doc);
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return nullptr;
return obj->GetDocumentAttributes();
}
-void ax_document_interface_base_init(AtkDocumentIface* iface) {
+void AXDocumentInterfaceBaseInit(AtkDocumentIface* iface) {
iface->get_document_attribute_value =
- ax_platform_node_auralinux_get_document_attribute_value;
- iface->get_document_attributes =
- ax_platform_node_auralinux_get_document_attributes;
+ AXPlatformNodeAuraLinuGetDocumentAttributeValue;
+ iface->get_document_attributes = AXPlatformNodeAuraLinuxGetDocumentAttributes;
}
static const GInterfaceInfo DocumentInfo = {
- reinterpret_cast<GInterfaceInitFunc>(ax_document_interface_base_init),
- nullptr, nullptr};
+ reinterpret_cast<GInterfaceInitFunc>(AXDocumentInterfaceBaseInit), nullptr,
+ nullptr};
//
// AtkImage interface.
//
-static void ax_platform_node_auralinux_get_image_position(
- AtkImage* atk_img,
- gint* x,
- gint* y,
- AtkCoordType coord_type) {
+static void AXPlatformNodeGetImagePosition(AtkImage* atk_img,
+ gint* x,
+ gint* y,
+ AtkCoordType coord_type) {
g_return_if_fail(ATK_IMAGE(atk_img));
AtkObject* atk_object = ATK_OBJECT(atk_img);
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return;
obj->GetPosition(x, y, coord_type);
}
-static const gchar* ax_platform_node_auralinux_get_image_description(
+static const gchar* AXPlatformNodeAuraLinuxGetImageDescription(
AtkImage* atk_img) {
g_return_val_if_fail(ATK_IMAGE(atk_img), nullptr);
AtkObject* atk_object = ATK_OBJECT(atk_img);
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return nullptr;
@@ -627,42 +601,39 @@ static const gchar* ax_platform_node_auralinux_get_image_description(
.c_str();
}
-static void ax_platform_node_auralinux_get_image_size(AtkImage* atk_img,
- gint* width,
- gint* height) {
+static void AXPlatformNodeAuraLinuxGetImageSize(AtkImage* atk_img,
+ gint* width,
+ gint* height) {
g_return_if_fail(ATK_IMAGE(atk_img));
AtkObject* atk_object = ATK_OBJECT(atk_img);
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return;
obj->GetSize(width, height);
}
-void ax_image_interface_base_init(AtkImageIface* iface) {
- iface->get_image_position = ax_platform_node_auralinux_get_image_position;
- iface->get_image_description =
- ax_platform_node_auralinux_get_image_description;
- iface->get_image_size = ax_platform_node_auralinux_get_image_size;
+void AXImageInterfaceBaseInit(AtkImageIface* iface) {
+ iface->get_image_position = AXPlatformNodeGetImagePosition;
+ iface->get_image_description = AXPlatformNodeAuraLinuxGetImageDescription;
+ iface->get_image_size = AXPlatformNodeAuraLinuxGetImageSize;
}
static const GInterfaceInfo ImageInfo = {
- reinterpret_cast<GInterfaceInitFunc>(ax_image_interface_base_init), nullptr,
+ reinterpret_cast<GInterfaceInitFunc>(AXImageInterfaceBaseInit), nullptr,
nullptr};
//
// AtkValue interface
//
-static void ax_platform_node_auralinux_get_current_value(AtkValue* atk_value,
- GValue* value) {
+static void AXPlatformNodeAuraLinuxGetCurrentValue(AtkValue* atk_value,
+ GValue* value) {
g_return_if_fail(ATK_VALUE(atk_value));
AtkObject* atk_object = ATK_OBJECT(atk_value);
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return;
@@ -670,13 +641,12 @@ static void ax_platform_node_auralinux_get_current_value(AtkValue* atk_value,
value);
}
-static void ax_platform_node_auralinux_get_minimum_value(AtkValue* atk_value,
- GValue* value) {
+static void AXPlatformNodeAuraLinuxGetMinimumValue(AtkValue* atk_value,
+ GValue* value) {
g_return_if_fail(ATK_VALUE(atk_value));
AtkObject* atk_object = ATK_OBJECT(atk_value);
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return;
@@ -684,13 +654,12 @@ static void ax_platform_node_auralinux_get_minimum_value(AtkValue* atk_value,
value);
}
-static void ax_platform_node_auralinux_get_maximum_value(AtkValue* atk_value,
- GValue* value) {
+static void AXPlatformNodeAuraLinuxGetMaximumValue(AtkValue* atk_value,
+ GValue* value) {
g_return_if_fail(ATK_VALUE(atk_value));
AtkObject* atk_object = ATK_OBJECT(atk_value);
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return;
@@ -698,14 +667,12 @@ static void ax_platform_node_auralinux_get_maximum_value(AtkValue* atk_value,
value);
}
-static void ax_platform_node_auralinux_get_minimum_increment(
- AtkValue* atk_value,
- GValue* value) {
+static void AXPlatformNodeAuraLinuxGetMinimumIncrement(AtkValue* atk_value,
+ GValue* value) {
g_return_if_fail(ATK_VALUE(atk_value));
AtkObject* atk_object = ATK_OBJECT(atk_value);
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return;
@@ -713,29 +680,27 @@ static void ax_platform_node_auralinux_get_minimum_increment(
value);
}
-static void ax_value_interface_base_init(AtkValueIface* iface) {
- iface->get_current_value = ax_platform_node_auralinux_get_current_value;
- iface->get_maximum_value = ax_platform_node_auralinux_get_maximum_value;
- iface->get_minimum_value = ax_platform_node_auralinux_get_minimum_value;
- iface->get_minimum_increment =
- ax_platform_node_auralinux_get_minimum_increment;
+static void AXValueInterfaceBaseInit(AtkValueIface* iface) {
+ iface->get_current_value = AXPlatformNodeAuraLinuxGetCurrentValue;
+ iface->get_maximum_value = AXPlatformNodeAuraLinuxGetMaximumValue;
+ iface->get_minimum_value = AXPlatformNodeAuraLinuxGetMinimumValue;
+ iface->get_minimum_increment = AXPlatformNodeAuraLinuxGetMinimumIncrement;
}
static const GInterfaceInfo ValueInfo = {
- reinterpret_cast<GInterfaceInitFunc>(ax_value_interface_base_init), nullptr,
+ reinterpret_cast<GInterfaceInitFunc>(AXValueInterfaceBaseInit), nullptr,
nullptr};
//
// AtkHyperlinkImpl interface.
//
-static AtkHyperlink* ax_platform_node_auralinux_get_hyperlink(
+static AtkHyperlink* AXPlatformNodeAuraLinuxGetHyperlink(
AtkHyperlinkImpl* atk_hyperlink_impl) {
g_return_val_if_fail(ATK_HYPERLINK_IMPL(atk_hyperlink_impl), 0);
AtkObject* atk_object = ATK_OBJECT(atk_hyperlink_impl);
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return 0;
@@ -745,24 +710,85 @@ static AtkHyperlink* ax_platform_node_auralinux_get_hyperlink(
return atk_hyperlink;
}
-void ax_hyperlink_impl_interface_base_init(AtkHyperlinkImplIface* iface) {
- iface->get_hyperlink = ax_platform_node_auralinux_get_hyperlink;
+void AXHyperlinkImplInterfaceBaseInit(AtkHyperlinkImplIface* iface) {
+ iface->get_hyperlink = AXPlatformNodeAuraLinuxGetHyperlink;
}
static const GInterfaceInfo HyperlinkImplInfo = {
- reinterpret_cast<GInterfaceInitFunc>(ax_hyperlink_impl_interface_base_init),
+ reinterpret_cast<GInterfaceInitFunc>(AXHyperlinkImplInterfaceBaseInit),
nullptr, nullptr};
//
+// AtkHypertext interface.
+//
+
+static AtkHyperlink* AXPlatformNodeAuraLinuxHypertextGetLink(
+ AtkHypertext* hypertext,
+ int index) {
+ g_return_val_if_fail(ATK_HYPERTEXT(hypertext), 0);
+ auto* obj = AtkObjectToAXPlatformNodeAuraLinux(ATK_OBJECT(hypertext));
+ if (!obj)
+ return nullptr;
+
+ const AXHypertext& ax_hypertext = obj->GetHypertext();
+ if (index > static_cast<int>(ax_hypertext.hyperlinks.size()) || index < 0)
+ return nullptr;
+
+ int32_t id = ax_hypertext.hyperlinks[index];
+ auto* link = AXPlatformNodeAuraLinux::GetFromUniqueId(id);
+ if (!link)
+ return nullptr;
+
+ AtkHyperlink* atk_hyperlink = link->GetAtkHyperlink();
+ for (const auto& key_value : ax_hypertext.hyperlink_offset_to_index) {
+ if (key_value.second == index) {
+ ax_platform_atk_hyperlink_set_indices(
+ AX_PLATFORM_ATK_HYPERLINK(atk_hyperlink), key_value.first,
+ key_value.first + 1);
+ }
+ }
+
+ return atk_hyperlink;
+}
+
+static int AXPlatformNodeAuraLinuxGetNLinks(AtkHypertext* hypertext) {
+ g_return_val_if_fail(ATK_HYPERTEXT(hypertext), 0);
+ AXPlatformNodeAuraLinux* obj =
+ AtkObjectToAXPlatformNodeAuraLinux(ATK_OBJECT(hypertext));
+ return obj ? obj->GetHypertext().hyperlinks.size() : 0;
+}
+
+static int AXPlatformNodeAuraLinuxGetLinkIndex(AtkHypertext* hypertext,
+ int char_index) {
+ g_return_val_if_fail(ATK_HYPERTEXT(hypertext), 0);
+ AXPlatformNodeAuraLinux* obj =
+ AtkObjectToAXPlatformNodeAuraLinux(ATK_OBJECT(hypertext));
+
+ auto it = obj->GetHypertext().hyperlink_offset_to_index.find(char_index);
+ if (it == obj->GetHypertext().hyperlink_offset_to_index.end())
+ return -1;
+ return it->second;
+}
+
+void AXHypertextInterfaceBaseInit(AtkHypertextIface* iface) {
+ iface->get_link = AXPlatformNodeAuraLinuxHypertextGetLink;
+ iface->get_n_links = AXPlatformNodeAuraLinuxGetNLinks;
+ iface->get_link_index = AXPlatformNodeAuraLinuxGetLinkIndex;
+}
+
+static const GInterfaceInfo HypertextInfo = {
+ reinterpret_cast<GInterfaceInitFunc>(AXHypertextInterfaceBaseInit), nullptr,
+ nullptr};
+
+//
// AtkText interface.
//
-static gchar* ax_platform_node_auralinux_get_text(AtkText* atk_text,
- gint start_offset,
- gint end_offset) {
+static gchar* AXPlatformNodeAuraLinuxGetText(AtkText* atk_text,
+ gint start_offset,
+ gint end_offset) {
AtkObject* atk_object = ATK_OBJECT(atk_text);
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return nullptr;
@@ -773,10 +799,9 @@ static gchar* ax_platform_node_auralinux_get_text(AtkText* atk_text,
return g_utf8_substring(text.c_str(), start_offset, end_offset);
}
-static gint ax_platform_node_auralinux_get_character_count(AtkText* atk_text) {
+static gint AXPlatformNodeAuraLinuxGetCharacterCount(AtkText* atk_text) {
AtkObject* atk_object = ATK_OBJECT(atk_text);
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return 0;
@@ -784,7 +809,7 @@ static gint ax_platform_node_auralinux_get_character_count(AtkText* atk_text) {
return g_utf8_strlen(text.c_str(), -1);
}
-static AtkAttributeSet* ax_platform_node_auralinux_get_run_attributes(
+static AtkAttributeSet* AXPlatformNodeAuraLinuxGetRunAttributes(
AtkText* atk_text,
gint offset,
gint* start_offset,
@@ -793,25 +818,146 @@ static AtkAttributeSet* ax_platform_node_auralinux_get_run_attributes(
*end_offset = -1;
AtkObject* atk_object = ATK_OBJECT(atk_text);
- ui::AXPlatformNodeAuraLinux* obj =
- AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
if (!obj)
return nullptr;
*start_offset = 0;
- *end_offset = ax_platform_node_auralinux_get_character_count(atk_text);
+ *end_offset = AXPlatformNodeAuraLinuxGetCharacterCount(atk_text);
return nullptr;
}
-static void ax_text_interface_base_init(AtkTextIface* iface) {
- iface->get_text = ax_platform_node_auralinux_get_text;
- iface->get_run_attributes = ax_platform_node_auralinux_get_run_attributes;
- iface->get_character_count = ax_platform_node_auralinux_get_character_count;
+static gunichar AXPlatformNodeAuraLinuxGetCharacterAtOffset(AtkText* atk_text,
+ int offset) {
+ AtkObject* atk_object = ATK_OBJECT(atk_text);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ if (!obj)
+ return 0;
+
+ std::string text = obj->GetTextForATK();
+ size_t limited_offset = std::max(0L, std::min(g_utf8_strlen(text.c_str(), -1),
+ static_cast<glong>(offset)));
+
+ // According to the C++ documentation, the pointer returned by c_str() should
+ // be valid as long as any non-const operations are not performed on the
+ // std::string in question.
+ return g_utf8_get_char(
+ g_utf8_offset_to_pointer(text.c_str(), limited_offset));
+}
+
+// This function returns a single character as a UTF-8 encoded C string because
+// the character may be encoded into more than one byte.
+static char* AXPlatformNodeAuraLinuxGetCharacter(AtkText* atk_text,
+ int offset,
+ int* start_offset,
+ int* end_offset) {
+ *start_offset = -1;
+ *end_offset = -1;
+
+ AtkObject* atk_object = ATK_OBJECT(atk_text);
+ AXPlatformNodeAuraLinux* obj = AtkObjectToAXPlatformNodeAuraLinux(atk_object);
+ if (!obj)
+ return nullptr;
+
+ std::string text = obj->GetTextForATK();
+ int text_length = static_cast<int>(g_utf8_strlen(text.c_str(), -1));
+ *start_offset = std::max(0, std::min(text_length, offset));
+ *end_offset = std::max(0, std::min(text_length, *start_offset + 1));
+
+ return g_utf8_substring(text.c_str(), *start_offset, *end_offset);
+}
+
+static char* AXPlatformNodeAuraLinuxGetTextAtOffset(
+ AtkText* atk_text,
+ int offset,
+ AtkTextBoundary boundary_type,
+ int* start_offset,
+ int* end_offset) {
+ *start_offset = -1;
+ *end_offset = -1;
+
+ if (boundary_type != ATK_TEXT_BOUNDARY_CHAR) {
+ NOTIMPLEMENTED();
+ return nullptr;
+ }
+
+ return AXPlatformNodeAuraLinuxGetCharacter(atk_text, offset, start_offset,
+ end_offset);
+}
+
+static char* AXPlatformNodeAuraLinuxGetTextAfterOffset(
+ AtkText* atk_text,
+ int offset,
+ AtkTextBoundary boundary_type,
+ int* start_offset,
+ int* end_offset) {
+ *start_offset = -1;
+ *end_offset = -1;
+
+ if (boundary_type != ATK_TEXT_BOUNDARY_CHAR) {
+ NOTIMPLEMENTED();
+ return nullptr;
+ }
+
+ return AXPlatformNodeAuraLinuxGetCharacter(atk_text, offset + 1, start_offset,
+ end_offset);
+}
+
+static char* AXPlatformNodeAuraLinuxGetTextBeforeOffset(
+ AtkText* atk_text,
+ int offset,
+ AtkTextBoundary boundary_type,
+ int* start_offset,
+ int* end_offset) {
+ *start_offset = -1;
+ *end_offset = -1;
+
+ if (boundary_type != ATK_TEXT_BOUNDARY_CHAR) {
+ NOTIMPLEMENTED();
+ return nullptr;
+ }
+
+ return AXPlatformNodeAuraLinuxGetCharacter(atk_text, offset - 1, start_offset,
+ end_offset);
+}
+
+#if ATK_CHECK_VERSION(2, 10, 0)
+static char* AXPlatformNodeAuraLinuxGetStringAtOffset(
+ AtkText* atk_text,
+ int offset,
+ AtkTextGranularity granularity,
+ int* start_offset,
+ int* end_offset) {
+ *start_offset = -1;
+ *end_offset = -1;
+
+ if (granularity != ATK_TEXT_GRANULARITY_CHAR) {
+ NOTIMPLEMENTED();
+ return nullptr;
+ }
+
+ return AXPlatformNodeAuraLinuxGetCharacter(atk_text, offset, start_offset,
+ end_offset);
+}
+#endif
+
+static void AXTextInterfaceBaseInit(AtkTextIface* iface) {
+ iface->get_text = AXPlatformNodeAuraLinuxGetText;
+ iface->get_run_attributes = AXPlatformNodeAuraLinuxGetRunAttributes;
+ iface->get_character_count = AXPlatformNodeAuraLinuxGetCharacterCount;
+ iface->get_character_at_offset = AXPlatformNodeAuraLinuxGetCharacterAtOffset;
+ iface->get_text_after_offset = AXPlatformNodeAuraLinuxGetTextAfterOffset;
+ iface->get_text_before_offset = AXPlatformNodeAuraLinuxGetTextBeforeOffset;
+ iface->get_text_at_offset = AXPlatformNodeAuraLinuxGetTextAtOffset;
+
+#if ATK_CHECK_VERSION(2, 10, 0)
+ iface->get_string_at_offset = AXPlatformNodeAuraLinuxGetStringAtOffset;
+#endif
}
static const GInterfaceInfo TextInfo = {
- reinterpret_cast<GInterfaceInitFunc>(ax_text_interface_base_init), nullptr,
+ reinterpret_cast<GInterfaceInitFunc>(AXTextInterfaceBaseInit), nullptr,
nullptr};
//
@@ -819,41 +965,40 @@ static const GInterfaceInfo TextInfo = {
// of the Atk* interfaces.
//
-static void ax_platform_node_auralinux_init(AtkObject* atk_object,
- gpointer data) {
- if (ATK_OBJECT_CLASS(ax_platform_node_auralinux_parent_class)->initialize) {
- ATK_OBJECT_CLASS(ax_platform_node_auralinux_parent_class)->initialize(
- atk_object, data);
+static void AXPlatformNodeAuraLinuxInit(AtkObject* atk_object, gpointer data) {
+ if (ATK_OBJECT_CLASS(kAXPlatformNodeAuraLinuxParentClass)->initialize) {
+ ATK_OBJECT_CLASS(kAXPlatformNodeAuraLinuxParentClass)
+ ->initialize(atk_object, data);
}
AX_PLATFORM_NODE_AURALINUX(atk_object)->m_object =
- reinterpret_cast<ui::AXPlatformNodeAuraLinux*>(data);
+ reinterpret_cast<AXPlatformNodeAuraLinux*>(data);
}
-static void ax_platform_node_auralinux_finalize(GObject* atk_object) {
- G_OBJECT_CLASS(ax_platform_node_auralinux_parent_class)->finalize(atk_object);
+static void AXPlatformNodeAuraLinuxFinalize(GObject* atk_object) {
+ G_OBJECT_CLASS(kAXPlatformNodeAuraLinuxParentClass)->finalize(atk_object);
}
-static void ax_platform_node_auralinux_class_init(AtkObjectClass* klass) {
+static void AXPlatformNodeAuraLinuxClassInit(AtkObjectClass* klass) {
GObjectClass* gobject_class = G_OBJECT_CLASS(klass);
- ax_platform_node_auralinux_parent_class = g_type_class_peek_parent(klass);
-
- gobject_class->finalize = ax_platform_node_auralinux_finalize;
- klass->initialize = ax_platform_node_auralinux_init;
- klass->get_name = ax_platform_node_auralinux_get_name;
- klass->get_description = ax_platform_node_auralinux_get_description;
- klass->get_parent = ax_platform_node_auralinux_get_parent;
- klass->get_n_children = ax_platform_node_auralinux_get_n_children;
- klass->ref_child = ax_platform_node_auralinux_ref_child;
- klass->get_role = ax_platform_node_auralinux_get_role;
- klass->ref_state_set = ax_platform_node_auralinux_ref_state_set;
- klass->get_index_in_parent = ax_platform_node_auralinux_get_index_in_parent;
- klass->ref_relation_set = ax_platform_node_auralinux_ref_relation_set;
- klass->get_attributes = ax_platform_node_auralinux_get_attributes;
+ kAXPlatformNodeAuraLinuxParentClass = g_type_class_peek_parent(klass);
+
+ gobject_class->finalize = AXPlatformNodeAuraLinuxFinalize;
+ klass->initialize = AXPlatformNodeAuraLinuxInit;
+ klass->get_name = AXPlatformNodeAuraLinuxGetName;
+ klass->get_description = AXPlatformNodeAuraLinuxGetDescription;
+ klass->get_parent = AXPlatformNodeAuraLinuxGetParent;
+ klass->get_n_children = AXPlatformNodeAuraLinuxGetNChildren;
+ klass->ref_child = AXPlatformNodeAuraLinuxRefChild;
+ klass->get_role = AXPlatformNodeAuraLinuxGetRole;
+ klass->ref_state_set = AXPlatformNodeAuraLinuxRefStateSet;
+ klass->get_index_in_parent = AXPlatformNodeAuraLinuxGetIndexInParent;
+ klass->ref_relation_set = AXPlatformNodeAuraLinuxRefRelationSet;
+ klass->get_attributes = AXPlatformNodeAuraLinuxGetAttributes;
}
GType ax_platform_node_auralinux_get_type() {
- ui::AXPlatformNodeAuraLinux::EnsureGTypeInit();
+ AXPlatformNodeAuraLinux::EnsureGTypeInit();
static volatile gsize type_volatile = 0;
if (g_once_init_enter(&type_volatile)) {
@@ -861,7 +1006,7 @@ GType ax_platform_node_auralinux_get_type() {
sizeof(AXPlatformNodeAuraLinuxClass),
(GBaseInitFunc) nullptr,
(GBaseFinalizeFunc) nullptr,
- (GClassInitFunc)ax_platform_node_auralinux_class_init,
+ (GClassInitFunc)AXPlatformNodeAuraLinuxClassInit,
(GClassFinalizeFunc) nullptr,
nullptr, /* class data */
sizeof(AXPlatformNodeAuraLinuxObject), /* instance size */
@@ -878,8 +1023,7 @@ GType ax_platform_node_auralinux_get_type() {
return type_volatile;
}
-void ax_platform_node_auralinux_detach(
- AXPlatformNodeAuraLinuxObject* atk_object) {
+void AXPlatformNodeAuraLinuxDetach(AXPlatformNodeAuraLinuxObject* atk_object) {
if (atk_object->m_object) {
atk_object_notify_state_change(ATK_OBJECT(atk_object), ATK_STATE_DEFUNCT,
TRUE);
@@ -889,8 +1033,6 @@ void ax_platform_node_auralinux_detach(
G_END_DECLS
-namespace ui {
-
void AXPlatformNodeAuraLinux::EnsureGTypeInit() {
#if !GLIB_CHECK_VERSION(2, 36, 0)
static bool first_time = true;
@@ -910,6 +1052,12 @@ const char* AXPlatformNodeAuraLinux::GetUniqueAccessibilityGTypeName(
return name;
}
+static bool IsRoleWithValueInterface(AtkRole role) {
+ return role == ATK_ROLE_SCROLL_BAR || role == ATK_ROLE_SLIDER ||
+ role == ATK_ROLE_PROGRESS_BAR || role == ATK_ROLE_SEPARATOR ||
+ role == ATK_ROLE_SPIN_BUTTON;
+}
+
int AXPlatformNodeAuraLinux::GetGTypeInterfaceMask() {
int interface_mask = 0;
@@ -925,11 +1073,12 @@ int AXPlatformNodeAuraLinux::GetGTypeInterfaceMask() {
// as well.
interface_mask |= 1 << ATK_TEXT_INTERFACE;
+ if (!IsPlainTextField() && !IsChildOfLeaf())
+ interface_mask |= 1 << ATK_HYPERTEXT_INTERFACE;
+
// Value Interface
- int role = GetAtkRole();
- if (role == ATK_ROLE_SCROLL_BAR || role == ATK_ROLE_SLIDER ||
- role == ATK_ROLE_PROGRESS_BAR || role == ATK_ROLE_SEPARATOR ||
- role == ATK_ROLE_SPIN_BUTTON) {
+ AtkRole role = GetAtkRole();
+ if (IsRoleWithValueInterface(role)) {
interface_mask |= 1 << ATK_VALUE_INTERFACE;
}
@@ -982,6 +1131,8 @@ GType AXPlatformNodeAuraLinux::GetAccessibilityGType() {
if (interface_mask_ & (1 << ATK_HYPERLINK_INTERFACE))
g_type_add_interface_static(type, ATK_TYPE_HYPERLINK_IMPL,
&HyperlinkImplInfo);
+ if (interface_mask_ & (1 << ATK_HYPERTEXT_INTERFACE))
+ g_type_add_interface_static(type, ATK_TYPE_HYPERTEXT, &HypertextInfo);
if (interface_mask_ & (1 << ATK_TEXT_INTERFACE))
g_type_add_interface_static(type, ATK_TYPE_TEXT, &TextInfo);
@@ -1009,7 +1160,7 @@ void AXPlatformNodeAuraLinux::DestroyAtkObjects() {
if (atk_object_) {
if (atk_object_ == current_focused_)
current_focused_ = nullptr;
- ax_platform_node_auralinux_detach(AX_PLATFORM_NODE_AURALINUX(atk_object_));
+ AXPlatformNodeAuraLinuxDetach(AX_PLATFORM_NODE_AURALINUX(atk_object_));
g_object_unref(atk_object_);
atk_object_ = nullptr;
}
@@ -1028,6 +1179,22 @@ AXPlatformNode* AXPlatformNode::FromNativeViewAccessible(
return AtkObjectToAXPlatformNodeAuraLinux(accessible);
}
+using UniqueIdMap = base::hash_map<int32_t, AXPlatformNodeAuraLinux*>;
+// Map from each AXPlatformNode's unique id to its instance.
+base::LazyInstance<UniqueIdMap>::Leaky g_unique_id_map =
+ LAZY_INSTANCE_INITIALIZER;
+
+// static
+AXPlatformNodeAuraLinux* AXPlatformNodeAuraLinux::GetFromUniqueId(
+ int32_t unique_id) {
+ UniqueIdMap* unique_ids = g_unique_id_map.Pointer();
+ auto iter = unique_ids->find(unique_id);
+ if (iter != unique_ids->end())
+ return iter->second;
+
+ return nullptr;
+}
+
//
// AXPlatformNodeAuraLinux implementation.
//
@@ -1434,7 +1601,8 @@ void AXPlatformNodeAuraLinux::GetAtkState(AtkStateSet* atk_state_set) {
atk_state_set_add_state(atk_state_set, ATK_STATE_EXPANDABLE);
atk_state_set_add_state(atk_state_set, ATK_STATE_EXPANDED);
}
- if (data.HasState(ax::mojom::State::kFocusable))
+ if (data.HasState(ax::mojom::State::kFocusable) ||
+ SelectionAndFocusAreTheSame())
atk_state_set_add_state(atk_state_set, ATK_STATE_FOCUSABLE);
if (data.HasState(ax::mojom::State::kHorizontal))
atk_state_set_add_state(atk_state_set, ATK_STATE_HORIZONTAL);
@@ -1456,8 +1624,10 @@ void AXPlatformNodeAuraLinux::GetAtkState(AtkStateSet* atk_state_set) {
static_cast<int32_t>(ax::mojom::InvalidState::kFalse))
atk_state_set_add_state(atk_state_set, ATK_STATE_INVALID_ENTRY);
#if defined(ATK_216)
- if (data.HasIntAttribute(ax::mojom::IntAttribute::kCheckedState))
+ if (data.HasIntAttribute(ax::mojom::IntAttribute::kCheckedState) &&
+ data.role != ax::mojom::Role::kToggleButton) {
atk_state_set_add_state(atk_state_set, ATK_STATE_CHECKABLE);
+ }
if (data.HasIntAttribute(ax::mojom::IntAttribute::kHasPopup))
atk_state_set_add_state(atk_state_set, ATK_STATE_HAS_POPUP);
#endif
@@ -1465,10 +1635,11 @@ void AXPlatformNodeAuraLinux::GetAtkState(AtkStateSet* atk_state_set) {
atk_state_set_add_state(atk_state_set, ATK_STATE_BUSY);
if (data.GetBoolAttribute(ax::mojom::BoolAttribute::kModal))
atk_state_set_add_state(atk_state_set, ATK_STATE_MODAL);
- if (data.GetBoolAttribute(ax::mojom::BoolAttribute::kSelected)) {
+ if (data.HasBoolAttribute(ax::mojom::BoolAttribute::kSelected))
atk_state_set_add_state(atk_state_set, ATK_STATE_SELECTABLE);
+ if (data.GetBoolAttribute(ax::mojom::BoolAttribute::kSelected))
atk_state_set_add_state(atk_state_set, ATK_STATE_SELECTED);
- }
+
if (IsPlainTextField() || IsRichTextField()) {
atk_state_set_add_state(atk_state_set, ATK_STATE_SELECTABLE_TEXT);
if (data.HasState(ax::mojom::State::kMultiline))
@@ -1486,18 +1657,9 @@ void AXPlatformNodeAuraLinux::GetAtkState(AtkStateSet* atk_state_set) {
// Checked state
const auto checked_state = GetData().GetCheckedState();
- switch (checked_state) {
- case ax::mojom::CheckedState::kMixed:
- atk_state_set_add_state(atk_state_set, ATK_STATE_INDETERMINATE);
- break;
- case ax::mojom::CheckedState::kTrue:
- atk_state_set_add_state(atk_state_set,
- data.role == ax::mojom::Role::kToggleButton
- ? ATK_STATE_PRESSED
- : ATK_STATE_CHECKED);
- break;
- default:
- break;
+ if (checked_state == ax::mojom::CheckedState::kTrue ||
+ checked_state == ax::mojom::CheckedState::kMixed) {
+ atk_state_set_add_state(atk_state_set, GetAtkStateTypeForCheckableNode());
}
switch (GetData().GetRestriction()) {
@@ -1523,13 +1685,18 @@ void AXPlatformNodeAuraLinux::GetAtkRelations(
}
AXPlatformNodeAuraLinux::AXPlatformNodeAuraLinux()
- : interface_mask_(0), atk_object_(nullptr), atk_hyperlink_(nullptr) {}
+ : interface_mask_(0),
+ atk_object_(nullptr),
+ atk_hyperlink_(nullptr),
+ weak_factory_(this) {}
AXPlatformNodeAuraLinux::~AXPlatformNodeAuraLinux() {
DestroyAtkObjects();
}
void AXPlatformNodeAuraLinux::Destroy() {
+ g_unique_id_map.Get().erase(GetUniqueId());
+
DestroyAtkObjects();
AXPlatformNodeBase::Destroy();
}
@@ -1537,6 +1704,7 @@ void AXPlatformNodeAuraLinux::Destroy() {
void AXPlatformNodeAuraLinux::Init(AXPlatformNodeDelegate* delegate) {
// Initialize ATK.
AXPlatformNodeBase::Init(delegate);
+ g_unique_id_map.Get()[GetUniqueId()] = this;
DataChanged();
}
@@ -1590,6 +1758,21 @@ gfx::NativeViewAccessible AXPlatformNodeAuraLinux::GetNativeViewAccessible() {
return atk_object_;
}
+void AXPlatformNodeAuraLinux::OnCheckedStateChanged() {
+ DCHECK(atk_object_);
+
+ atk_object_notify_state_change(
+ ATK_OBJECT(atk_object_), GetAtkStateTypeForCheckableNode(),
+ GetData().GetCheckedState() != ax::mojom::CheckedState::kFalse);
+}
+
+void AXPlatformNodeAuraLinux::OnExpandedStateChanged(bool is_expanded) {
+ DCHECK(atk_object_);
+
+ atk_object_notify_state_change(ATK_OBJECT(atk_object_), ATK_STATE_EXPANDED,
+ is_expanded);
+}
+
AtkObject* AXPlatformNodeAuraLinux::current_focused_ = nullptr;
void AXPlatformNodeAuraLinux::OnFocused() {
@@ -1610,13 +1793,93 @@ void AXPlatformNodeAuraLinux::OnFocused() {
true);
}
+base::WeakPtr<AXPlatformNodeAuraLinux>
+ AXPlatformNodeAuraLinux::current_selected_ = nullptr;
+
+void AXPlatformNodeAuraLinux::OnSelected() {
+ if (current_selected_ && !current_selected_->GetData().GetBoolAttribute(
+ ax::mojom::BoolAttribute::kSelected)) {
+ atk_object_notify_state_change(ATK_OBJECT(current_selected_->atk_object_),
+ ATK_STATE_SELECTED, false);
+ }
+
+ current_selected_ = weak_factory_.GetWeakPtr();
+ if (ATK_IS_OBJECT(atk_object_)) {
+ atk_object_notify_state_change(ATK_OBJECT(atk_object_), ATK_STATE_SELECTED,
+ true);
+ }
+
+ if (SelectionAndFocusAreTheSame())
+ OnFocused();
+}
+
+bool AXPlatformNodeAuraLinux::SelectionAndFocusAreTheSame() {
+ if (AXPlatformNodeBase* container = GetSelectionContainer()) {
+ ax::mojom::Role role = container->GetData().role;
+ if (role == ax::mojom::Role::kMenuBar || role == ax::mojom::Role::kMenu)
+ return true;
+ if (role == ax::mojom::Role::kListBox &&
+ !container->GetData().HasState(ax::mojom::State::kMultiselectable)) {
+ return container->GetDelegate()->GetFocus() ==
+ container->GetNativeViewAccessible();
+ }
+ }
+
+ // TODO(accessibility): GetSelectionContainer returns nullptr when the current
+ // object is a descendant of a select element with a size of 1. Intentional?
+ // For now, handle that scenario here.
+ //
+ // If the selection is changing on a collapsed select element, focus remains
+ // on the select element and not the newly-selected descendant.
+ if (AXPlatformNodeBase* parent = FromNativeViewAccessible(GetParent())) {
+ if (parent->GetData().role == ax::mojom::Role::kMenuListPopup)
+ return !parent->GetData().HasState(ax::mojom::State::kInvisible);
+ }
+
+ return false;
+}
+
+void AXPlatformNodeAuraLinux::OnValueChanged() {
+ DCHECK(atk_object_);
+
+ if (!IsRoleWithValueInterface(GetAtkRole()))
+ return;
+
+ float float_val;
+ if (!GetFloatAttribute(ax::mojom::FloatAttribute::kValueForRange, &float_val))
+ return;
+
+ AtkPropertyValues property_values;
+ property_values.property_name = "accessible-value";
+
+ property_values.new_value = G_VALUE_INIT;
+ g_value_init(&property_values.new_value, G_TYPE_DOUBLE);
+ g_value_set_double(&property_values.new_value,
+ static_cast<double>(float_val));
+ g_signal_emit_by_name(G_OBJECT(atk_object_),
+ "property-change::accessible-value", &property_values,
+ nullptr);
+}
+
void AXPlatformNodeAuraLinux::NotifyAccessibilityEvent(
ax::mojom::Event event_type) {
switch (event_type) {
+ case ax::mojom::Event::kCheckedStateChanged:
+ OnCheckedStateChanged();
+ break;
+ case ax::mojom::Event::kExpandedChanged:
+ OnExpandedStateChanged(GetData().HasState(ax::mojom::State::kExpanded));
+ break;
case ax::mojom::Event::kFocus:
case ax::mojom::Event::kFocusContext:
OnFocused();
break;
+ case ax::mojom::Event::kSelection:
+ OnSelected();
+ break;
+ case ax::mojom::Event::kValueChanged:
+ OnValueChanged();
+ break;
default:
break;
}
@@ -1626,6 +1889,10 @@ void AXPlatformNodeAuraLinux::UpdateHypertext() {
hypertext_ = ComputeHypertext();
}
+const AXHypertext& AXPlatformNodeAuraLinux::GetHypertext() {
+ return hypertext_;
+}
+
int AXPlatformNodeAuraLinux::GetIndexInParent() {
if (!GetParent())
return -1;
@@ -1710,7 +1977,7 @@ const gchar* AXPlatformNodeAuraLinux::GetDefaultActionName() {
if (!GetIntAttribute(ax::mojom::IntAttribute::kDefaultActionVerb, &action))
return nullptr;
- base::string16 action_verb = ui::ActionVerbToUnlocalizedString(
+ base::string16 action_verb = ActionVerbToUnlocalizedString(
static_cast<ax::mojom::DefaultActionVerb>(action));
ATK_AURALINUX_RETURN_STRING(base::UTF16ToUTF8(action_verb));
@@ -1722,6 +1989,14 @@ AtkAttributeSet* AXPlatformNodeAuraLinux::GetAtkAttributes() {
return attribute_list;
}
+AtkStateType AXPlatformNodeAuraLinux::GetAtkStateTypeForCheckableNode() {
+ if (GetData().GetCheckedState() == ax::mojom::CheckedState::kMixed)
+ return ATK_STATE_INDETERMINATE;
+ if (GetData().role == ax::mojom::Role::kToggleButton)
+ return ATK_STATE_PRESSED;
+ return ATK_STATE_CHECKED;
+}
+
// AtkDocumentHelpers
const gchar* AXPlatformNodeAuraLinux::GetDocumentAttributeValue(
@@ -1770,9 +2045,6 @@ AtkAttributeSet* AXPlatformNodeAuraLinux::GetDocumentAttributes() const {
//
AtkHyperlink* AXPlatformNodeAuraLinux::GetAtkHyperlink() {
- DCHECK(ATK_HYPERLINK_IMPL(atk_object_));
- g_return_val_if_fail(ATK_HYPERLINK_IMPL(atk_object_), 0);
-
if (!atk_hyperlink_) {
atk_hyperlink_ =
ATK_HYPERLINK(g_object_new(AX_PLATFORM_ATK_HYPERLINK_TYPE, 0));
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_auralinux.h b/chromium/ui/accessibility/platform/ax_platform_node_auralinux.h
index 6ed9b01cedf..48fd256d64b 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_auralinux.h
+++ b/chromium/ui/accessibility/platform/ax_platform_node_auralinux.h
@@ -27,24 +27,24 @@
namespace ui {
// Implements accessibility on Aura Linux using ATK.
-class AXPlatformNodeAuraLinux : public AXPlatformNodeBase {
+class AX_EXPORT AXPlatformNodeAuraLinux : public AXPlatformNodeBase {
public:
AXPlatformNodeAuraLinux();
~AXPlatformNodeAuraLinux() override;
// Set or get the root-level Application object that's the parent of all
// top-level windows.
- AX_EXPORT static void SetApplication(AXPlatformNode* application);
+ static void SetApplication(AXPlatformNode* application);
static AXPlatformNode* application() { return application_; }
static void EnsureGTypeInit();
// Do asynchronous static initialization.
- AX_EXPORT static void StaticInitialize();
+ static void StaticInitialize();
- AX_EXPORT void DataChanged();
+ void DataChanged();
void Destroy() override;
- AX_EXPORT void AddAccessibilityTreeProperties(base::DictionaryValue* dict);
+ void AddAccessibilityTreeProperties(base::DictionaryValue* dict);
AtkRole GetAtkRole();
void GetAtkState(AtkStateSet* state_set);
@@ -65,6 +65,8 @@ class AXPlatformNodeAuraLinux : public AXPlatformNodeBase {
gint* x, gint* y, gint* width, gint* height,
AtkCoordType coord_type);
+ static AXPlatformNodeAuraLinux* GetFromUniqueId(int32_t unique_id);
+
// AtkDocument helpers
const gchar* GetDocumentAttributeValue(const gchar* attribute) const;
AtkAttributeSet* GetDocumentAttributes() const;
@@ -76,7 +78,13 @@ class AXPlatformNodeAuraLinux : public AXPlatformNodeBase {
void GetFloatAttributeInGValue(ax::mojom::FloatAttribute attr, GValue* value);
// Event helpers
+ void OnCheckedStateChanged();
+ void OnExpandedStateChanged(bool is_expanded);
void OnFocused();
+ void OnSelected();
+ void OnValueChanged();
+
+ bool SelectionAndFocusAreTheSame();
// AXPlatformNode overrides.
gfx::NativeViewAccessible GetNativeViewAccessible() override;
@@ -88,7 +96,8 @@ class AXPlatformNodeAuraLinux : public AXPlatformNodeBase {
std::string GetTextForATK();
- AX_EXPORT void UpdateHypertext();
+ void UpdateHypertext();
+ const AXHypertext& GetHypertext();
protected:
AXHypertext hypertext_;
@@ -117,6 +126,9 @@ class AXPlatformNodeAuraLinux : public AXPlatformNodeBase {
AtkObject* CreateAtkObject();
void DestroyAtkObjects();
+ // The AtkStateType for a checkable node can vary depending on the role.
+ AtkStateType GetAtkStateTypeForCheckableNode();
+
// Keep information of latest AtkInterfaces mask to refresh atk object
// interfaces accordingly if needed.
int interface_mask_;
@@ -133,6 +145,13 @@ class AXPlatformNodeAuraLinux : public AXPlatformNodeBase {
// to emit the ATK_STATE_FOCUSED change to false.
static AtkObject* current_focused_;
+ // The last object which was selected. Tracking this is required because
+ // widgets in the browser UI only emit notifications upon becoming selected,
+ // but clients also expect notifications when items become unselected.
+ static base::WeakPtr<AXPlatformNodeAuraLinux> current_selected_;
+
+ base::WeakPtrFactory<AXPlatformNodeAuraLinux> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(AXPlatformNodeAuraLinux);
};
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_auralinux_unittest.cc b/chromium/ui/accessibility/platform/ax_platform_node_auralinux_unittest.cc
index 228bd0156ce..21f086f22e0 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_auralinux_unittest.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_auralinux_unittest.cc
@@ -857,4 +857,90 @@ TEST_F(AXPlatformNodeAuraLinuxTest, TestAtkHyperlink) {
g_object_unref(root_obj);
}
+//
+// AtkText interface
+//
+//
+TEST_F(AXPlatformNodeAuraLinuxTest, TestAtkTextCharacterGranularity) {
+ AXNodeData root;
+ root.id = 1;
+ root.role = ax::mojom::Role::kTextField;
+ root.AddStringAttribute(ax::mojom::StringAttribute::kValue,
+ "A decently long string \xE2\x98\xBA with an emoji.");
+ Init(root);
+
+ AtkObject* root_obj(GetRootAtkObject());
+ ASSERT_TRUE(ATK_IS_OBJECT(root_obj));
+ g_object_ref(root_obj);
+
+ ASSERT_TRUE(ATK_IS_TEXT(root_obj));
+ AtkText* atk_text = ATK_TEXT(root_obj);
+
+ EXPECT_EQ(static_cast<gunichar>('d'),
+ atk_text_get_character_at_offset(atk_text, 2));
+ EXPECT_EQ(static_cast<gunichar>('A'),
+ atk_text_get_character_at_offset(atk_text, -1));
+ EXPECT_EQ(0u, atk_text_get_character_at_offset(atk_text, 42342));
+ EXPECT_EQ(0x263Au, atk_text_get_character_at_offset(atk_text, 23));
+ EXPECT_EQ(static_cast<gunichar>(' '),
+ atk_text_get_character_at_offset(atk_text, 24));
+
+ auto verify_text = [&](const char* expected_text, char* text,
+ int expected_start, int expected_end, int start,
+ int end) {
+ EXPECT_STREQ(expected_text, text);
+ EXPECT_EQ(start, expected_start);
+ EXPECT_EQ(end, expected_end);
+ g_free(text);
+ };
+
+ auto verify_text_at_offset = [&](const char* expected_text, int offset,
+ int expected_start, int expected_end) {
+ int start = 0, end = 0;
+ char* text = atk_text_get_text_at_offset(
+ atk_text, offset, ATK_TEXT_BOUNDARY_CHAR, &start, &end);
+ verify_text(expected_text, text, expected_start, expected_end, start, end);
+ };
+
+ verify_text_at_offset("d", 2, 2, 3);
+ verify_text_at_offset("A", -1, 0, 1);
+ verify_text_at_offset("", 42342, 39, 39);
+ verify_text_at_offset("\xE2\x98\xBA", 23, 23, 24);
+ verify_text_at_offset(" ", 24, 24, 25);
+
+ auto verify_text_after_offset = [&](const char* expected_text, int offset,
+ int expected_start, int expected_end) {
+ int start = 0, end = 0;
+ char* text = atk_text_get_text_after_offset(
+ atk_text, offset, ATK_TEXT_BOUNDARY_CHAR, &start, &end);
+ verify_text(expected_text, text, expected_start, expected_end, start, end);
+ };
+
+ verify_text_after_offset("d", 1, 2, 3);
+ verify_text_after_offset("", 42342, 39, 39);
+ verify_text_after_offset("\xE2\x98\xBA", 22, 23, 24);
+ verify_text_after_offset(" ", 23, 24, 25);
+
+ // This boundary condition is enforced by ATK for some reason.
+ verify_text_after_offset(nullptr, -1, 0, 0);
+
+ auto verify_text_before_offset = [&](const char* expected_text, int offset,
+ int expected_start, int expected_end) {
+ int start = 0, end = 0;
+ char* text = atk_text_get_text_before_offset(
+ atk_text, offset, ATK_TEXT_BOUNDARY_CHAR, &start, &end);
+ verify_text(expected_text, text, expected_start, expected_end, start, end);
+ };
+
+ verify_text_before_offset("d", 3, 2, 3);
+ verify_text_before_offset("", 42342, 39, 39);
+ verify_text_before_offset("\xE2\x98\xBA", 24, 23, 24);
+ verify_text_before_offset(" ", 25, 24, 25);
+
+ // This boundary condition is enforced by ATK for some reason.
+ verify_text_after_offset(nullptr, -1, 0, 0);
+
+ g_object_unref(root_obj);
+}
+
} // namespace ui
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_base.cc b/chromium/ui/accessibility/platform/ax_platform_node_base.cc
index cae47b1fc8e..e4a10976f4f 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_base.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_base.cc
@@ -8,6 +8,7 @@
#include <utility>
#include <vector>
+#include "base/no_destructor.h"
#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
@@ -27,10 +28,10 @@ void AXPlatformNodeBase::Init(AXPlatformNodeDelegate* delegate) {
}
const AXNodeData& AXPlatformNodeBase::GetData() const {
- CR_DEFINE_STATIC_LOCAL(AXNodeData, empty_data, ());
+ static base::NoDestructor<AXNodeData> empty_data;
if (delegate_)
return delegate_->GetData();
- return empty_data;
+ return *empty_data;
}
gfx::NativeViewAccessible AXPlatformNodeBase::GetParent() {
@@ -189,9 +190,9 @@ bool AXPlatformNodeBase::HasStringAttribute(
const std::string& AXPlatformNodeBase::GetStringAttribute(
ax::mojom::StringAttribute attribute) const {
- CR_DEFINE_STATIC_LOCAL(std::string, empty_data, ());
+ static base::NoDestructor<std::string> empty_data;
if (!delegate_)
- return empty_data;
+ return *empty_data;
return GetData().GetStringAttribute(attribute);
}
@@ -227,9 +228,9 @@ bool AXPlatformNodeBase::HasIntListAttribute(
const std::vector<int32_t>& AXPlatformNodeBase::GetIntListAttribute(
ax::mojom::IntListAttribute attribute) const {
- CR_DEFINE_STATIC_LOCAL(std::vector<int32_t>, empty_data, ());
+ static base::NoDestructor<std::vector<int32_t>> empty_data;
if (!delegate_)
- return empty_data;
+ return *empty_data;
return GetData().GetIntListAttribute(attribute);
}
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 41d04774945..f5a77c4e1dd 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_delegate_base.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_delegate_base.cc
@@ -4,20 +4,20 @@
#include "ui/accessibility/platform/ax_platform_node_delegate_base.h"
-#include "base/macros.h"
+#include "base/no_destructor.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/ax_tree_data.h"
namespace ui {
const AXNodeData& AXPlatformNodeDelegateBase::GetData() const {
- CR_DEFINE_STATIC_LOCAL(AXNodeData, empty_data, ());
- return empty_data;
+ static base::NoDestructor<AXNodeData> empty_data;
+ return *empty_data;
}
const AXTreeData& AXPlatformNodeDelegateBase::GetTreeData() const {
- CR_DEFINE_STATIC_LOCAL(AXTreeData, empty_data, ());
- return empty_data;
+ static base::NoDestructor<AXTreeData> empty_data;
+ return *empty_data;
}
gfx::NativeWindow AXPlatformNodeDelegateBase::GetTopLevelWidget() {
@@ -131,8 +131,8 @@ std::set<int32_t> AXPlatformNodeDelegateBase::GetReverseRelations(
}
const AXUniqueId& AXPlatformNodeDelegateBase::GetUniqueId() const {
- CR_DEFINE_STATIC_LOCAL(AXUniqueId, dummy_unique_id, ());
- return dummy_unique_id;
+ static base::NoDestructor<AXUniqueId> dummy_unique_id;
+ return *dummy_unique_id;
}
} // namespace ui
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_mac.mm b/chromium/ui/accessibility/platform/ax_platform_node_mac.mm
index 1bf96b4b9a6..dc041e0b6ee 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_mac.mm
+++ b/chromium/ui/accessibility/platform/ax_platform_node_mac.mm
@@ -8,6 +8,7 @@
#include <stddef.h>
#include "base/macros.h"
+#include "base/no_destructor.h"
#include "base/strings/sys_string_conversions.h"
#include "ui/accessibility/ax_action_data.h"
#include "ui/accessibility/ax_node_data.h"
@@ -259,6 +260,8 @@ RoleMap BuildSubroleMap() {
EventMap BuildEventMap() {
const EventMap::value_type events[] = {
+ {ax::mojom::Event::kCheckedStateChanged,
+ NSAccessibilityValueChangedNotification},
{ax::mojom::Event::kFocus,
NSAccessibilityFocusedUIElementChangedNotification},
{ax::mojom::Event::kFocusContext,
@@ -287,8 +290,8 @@ ActionList BuildActionList() {
}
const ActionList& GetActionList() {
- CR_DEFINE_STATIC_LOCAL(const ActionList, action_map, (BuildActionList()));
- return action_map;
+ static const base::NoDestructor<ActionList> action_map(BuildActionList());
+ return *action_map;
}
void PostAnnouncementNotification(NSString* announcement) {
@@ -335,21 +338,21 @@ bool AlsoUseShowMenuActionForDefaultAction(const ui::AXNodeData& data) {
@synthesize node = node_;
+ (NSString*)nativeRoleFromAXRole:(ax::mojom::Role)role {
- CR_DEFINE_STATIC_LOCAL(const RoleMap, role_map, (BuildRoleMap()));
- RoleMap::const_iterator it = role_map.find(role);
- return it != role_map.end() ? it->second : NSAccessibilityUnknownRole;
+ static const base::NoDestructor<RoleMap> role_map(BuildRoleMap());
+ RoleMap::const_iterator it = role_map->find(role);
+ return it != role_map->end() ? it->second : NSAccessibilityUnknownRole;
}
+ (NSString*)nativeSubroleFromAXRole:(ax::mojom::Role)role {
- CR_DEFINE_STATIC_LOCAL(const RoleMap, subrole_map, (BuildSubroleMap()));
- RoleMap::const_iterator it = subrole_map.find(role);
- return it != subrole_map.end() ? it->second : nil;
+ static const base::NoDestructor<RoleMap> subrole_map(BuildSubroleMap());
+ RoleMap::const_iterator it = subrole_map->find(role);
+ return it != subrole_map->end() ? it->second : nil;
}
+ (NSString*)nativeNotificationFromAXEvent:(ax::mojom::Event)event {
- CR_DEFINE_STATIC_LOCAL(const EventMap, event_map, (BuildEventMap()));
- EventMap::const_iterator it = event_map.find(event);
- return it != event_map.end() ? it->second : nil;
+ static const base::NoDestructor<EventMap> event_map(BuildEventMap());
+ EventMap::const_iterator it = event_map->find(event);
+ return it != event_map->end() ? it->second : nil;
}
- (instancetype)initWithNode:(ui::AXPlatformNodeBase*)node {
@@ -560,6 +563,10 @@ bool AlsoUseShowMenuActionForDefaultAction(const ui::AXNodeData& data) {
[axAttributes addObjectsFromArray:@[ NSAccessibilitySelectedAttribute ]];
}
+ if (ui::IsMenuItem(node_->GetData().role)) {
+ [axAttributes addObjectsFromArray:@[ @"AXMenuItemMarkChar" ]];
+ }
+
return axAttributes.autorelease();
}
@@ -759,6 +766,13 @@ bool AlsoUseShowMenuActionForDefaultAction(const ui::AXNodeData& data) {
if (ui::IsNameExposedInAXValueForRole(role))
return [self getStringAttribute:ax::mojom::StringAttribute::kName];
+ if (node_->HasIntAttribute(ax::mojom::IntAttribute::kCheckedState)) {
+ // Mixed checkbox state not currently supported in views, but could be.
+ // See browser_accessibility_cocoa.mm for details.
+ const auto checkedState = static_cast<ax::mojom::CheckedState>(
+ node_->GetIntAttribute(ax::mojom::IntAttribute::kCheckedState));
+ return checkedState == ax::mojom::CheckedState::kTrue ? @1 : @0;
+ }
return [self getStringAttribute:ax::mojom::StringAttribute::kValue];
}
@@ -825,6 +839,19 @@ bool AlsoUseShowMenuActionForDefaultAction(const ui::AXNodeData& data) {
return [self getStringAttribute:ax::mojom::StringAttribute::kPlaceholder];
}
+- (NSString*)AXMenuItemMarkChar {
+ if (!ui::IsMenuItem(node_->GetData().role))
+ return nil;
+
+ const auto checkedState = static_cast<ax::mojom::CheckedState>(
+ node_->GetIntAttribute(ax::mojom::IntAttribute::kCheckedState));
+ if (checkedState == ax::mojom::CheckedState::kTrue) {
+ return @"\xE2\x9C\x93"; // UTF-8 for unicode 0x2713, "check mark"
+ }
+
+ return @"";
+}
+
// Text-specific attributes.
- (NSString*)AXSelectedText {
@@ -976,7 +1003,7 @@ void AXPlatformNodeMac::NotifyAccessibilityEvent(ax::mojom::Event event_type) {
break;
case ax::mojom::Event::kSelection:
// On Mac, map menu item selection to a focus event.
- if (GetData().role == ax::mojom::Role::kMenuItem) {
+ if (ui::IsMenuItem(GetData().role)) {
NotifyMacEvent(native_node_, ax::mojom::Event::kFocus);
return;
}
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_test_helper.cc b/chromium/ui/accessibility/platform/ax_platform_node_test_helper.cc
new file mode 100644
index 00000000000..2dd8e81c10b
--- /dev/null
+++ b/chromium/ui/accessibility/platform/ax_platform_node_test_helper.cc
@@ -0,0 +1,47 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/accessibility/platform/ax_platform_node_test_helper.h"
+
+#include "ui/accessibility/ax_node_data.h"
+
+namespace ui {
+
+// static
+int AXPlatformNodeTestHelper::GetTreeSize(AXPlatformNode* ax_node) {
+ if (!ax_node)
+ return 0;
+ int count = 1;
+ AXPlatformNodeDelegate* delegate = ax_node->GetDelegate();
+ for (int i = 0; i < delegate->GetChildCount(); ++i) {
+ AXPlatformNode* child_node =
+ AXPlatformNode::FromNativeViewAccessible(delegate->ChildAtIndex(i));
+ count += GetTreeSize(child_node);
+ }
+ return count;
+}
+
+// static
+AXPlatformNode* AXPlatformNodeTestHelper::FindChildByName(
+ AXPlatformNode* ax_node,
+ const std::string& name) {
+ if (!ax_node)
+ return nullptr;
+
+ AXPlatformNodeDelegate* delegate = ax_node->GetDelegate();
+ if (delegate->GetData().GetStringAttribute(
+ ax::mojom::StringAttribute::kName) == name)
+ return ax_node;
+
+ for (int i = 0; i < delegate->GetChildCount(); ++i) {
+ AXPlatformNode* result_from_child = FindChildByName(
+ AXPlatformNode::FromNativeViewAccessible(delegate->ChildAtIndex(i)),
+ name);
+ if (result_from_child)
+ return result_from_child;
+ }
+ return nullptr;
+}
+
+} // namespace ui
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_test_helper.h b/chromium/ui/accessibility/platform/ax_platform_node_test_helper.h
new file mode 100644
index 00000000000..14994ea4c25
--- /dev/null
+++ b/chromium/ui/accessibility/platform/ax_platform_node_test_helper.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_ACCESSIBILITY_PLATFORM_AX_PLATFORM_NODE_TEST_HELPER_H_
+#define UI_ACCESSIBILITY_PLATFORM_AX_PLATFORM_NODE_TEST_HELPER_H_
+
+#include "ui/accessibility/platform/ax_platform_node.h"
+#include "ui/accessibility/platform/ax_platform_node_delegate.h"
+
+namespace ui {
+
+class AX_EXPORT AXPlatformNodeTestHelper {
+ public:
+ static int GetTreeSize(AXPlatformNode* ax_node);
+ static AXPlatformNode* FindChildByName(AXPlatformNode* ax_node,
+ const std::string& name);
+};
+
+} // namespace ui
+
+#endif // UI_ACCESSIBILITY_PLATFORM_AX_PLATFORM_NODE_TEST_HELPER_H_
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_win.cc b/chromium/ui/accessibility/platform/ax_platform_node_win.cc
index 65069458fa8..15faebdb9ff 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_win.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_win.cc
@@ -1367,16 +1367,15 @@ IFACEMETHODIMP AXPlatformNodeWin::scrollToPoint(
COM_OBJECT_VALIDATE();
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_SCROLL_TO_POINT);
+ // Convert to screen-relative coordinates if necessary.
gfx::Point scroll_to(x, y);
- if (coordinate_type == IA2_COORDTYPE_SCREEN_RELATIVE) {
- scroll_to -= delegate_->GetUnclippedScreenBoundsRect().OffsetFromOrigin();
- } else if (coordinate_type == IA2_COORDTYPE_PARENT_RELATIVE) {
+ if (coordinate_type == IA2_COORDTYPE_PARENT_RELATIVE) {
if (GetParent()) {
AXPlatformNodeBase* base = FromNativeViewAccessible(GetParent());
scroll_to +=
base->delegate_->GetUnclippedScreenBoundsRect().OffsetFromOrigin();
}
- } else {
+ } else if (coordinate_type != IA2_COORDTYPE_SCREEN_RELATIVE) {
return E_INVALIDARG;
}
@@ -5559,8 +5558,7 @@ int AXPlatformNodeWin::MSAAState() {
// In focused single selection UI menus and listboxes, mirror item selection
// to focus. This helps NVDA read the selected option as it changes.
- if ((data.role == ax::mojom::Role::kListBoxOption ||
- data.role == ax::mojom::Role::kMenuItem) &&
+ if ((data.role == ax::mojom::Role::kListBoxOption || IsMenuItem(data.role)) &&
data.GetBoolAttribute(ax::mojom::BoolAttribute::kSelected)) {
AXPlatformNodeBase* container = FromNativeViewAccessible(GetParent());
if (container && container->GetParent() == focus) {
@@ -5600,6 +5598,7 @@ int AXPlatformNodeWin::MSAAEvent(ax::mojom::Event event) {
switch (event) {
case ax::mojom::Event::kAlert:
return EVENT_SYSTEM_ALERT;
+ case ax::mojom::Event::kCheckedStateChanged:
case ax::mojom::Event::kExpandedChanged:
return EVENT_OBJECT_STATECHANGE;
case ax::mojom::Event::kFocus:
diff --git a/chromium/ui/accessibility/platform/ax_system_caret_win.cc b/chromium/ui/accessibility/platform/ax_system_caret_win.cc
index bd475d53d84..dd91704c713 100644
--- a/chromium/ui/accessibility/platform/ax_system_caret_win.cc
+++ b/chromium/ui/accessibility/platform/ax_system_caret_win.cc
@@ -24,6 +24,7 @@ AXSystemCaretWin::AXSystemCaretWin(gfx::AcceleratedWidget event_target)
data_.role = ax::mojom::Role::kCaret;
// |get_accState| should return 0 which means that the caret is visible.
data_.state = 0;
+ data_.AddState(ax::mojom::State::kInvisible);
// According to MSDN, "Edit" should be the name of the caret object.
data_.SetName(L"Edit");
data_.offset_container_id = -1;
@@ -54,13 +55,43 @@ Microsoft::WRL::ComPtr<IAccessible> AXSystemCaretWin::GetCaret() const {
void AXSystemCaretWin::MoveCaretTo(const gfx::Rect& bounds) {
if (bounds.IsEmpty())
return;
- data_.location = gfx::RectF(bounds);
- if (event_target_) {
+
+ // If the caret has non-empty bounds, assume it has been made visible.
+ bool newly_visible = false;
+ if (data_.HasState(ax::mojom::State::kInvisible)) {
+ newly_visible = true;
+ data_.RemoveState(ax::mojom::State::kInvisible);
+ }
+
+ if (!event_target_)
+ return;
+
+ if (newly_visible) {
+ ::NotifyWinEvent(EVENT_OBJECT_SHOW, event_target_, OBJID_CARET,
+ -caret_->GetUniqueId());
+ }
+
+ gfx::RectF new_location(bounds);
+ // Avoid redundant caret move events (if the location stays the same), but
+ // always fire when it's made visible again.
+ if (data_.location != new_location || newly_visible) {
+ data_.location = new_location;
::NotifyWinEvent(EVENT_OBJECT_LOCATIONCHANGE, event_target_, OBJID_CARET,
-caret_->GetUniqueId());
}
}
+void AXSystemCaretWin::Hide() {
+ if (!data_.HasState(ax::mojom::State::kInvisible)) {
+ data_.AddState(ax::mojom::State::kInvisible);
+ data_.location.set_width(0);
+ if (event_target_) {
+ ::NotifyWinEvent(EVENT_OBJECT_HIDE, event_target_, OBJID_CARET,
+ -caret_->GetUniqueId());
+ }
+ }
+}
+
const AXNodeData& AXSystemCaretWin::GetData() const {
return data_;
}
diff --git a/chromium/ui/accessibility/platform/ax_system_caret_win.h b/chromium/ui/accessibility/platform/ax_system_caret_win.h
index 03f4bf9dc0a..a4d2392410f 100644
--- a/chromium/ui/accessibility/platform/ax_system_caret_win.h
+++ b/chromium/ui/accessibility/platform/ax_system_caret_win.h
@@ -31,6 +31,7 @@ class AX_EXPORT AXSystemCaretWin : private AXPlatformNodeDelegateBase {
Microsoft::WRL::ComPtr<IAccessible> GetCaret() const;
void MoveCaretTo(const gfx::Rect& bounds);
+ void Hide();
private:
// |AXPlatformNodeDelegate| members.
diff --git a/chromium/ui/android/BUILD.gn b/chromium/ui/android/BUILD.gn
index db4b8a8ad9e..b641523e27c 100644
--- a/chromium/ui/android/BUILD.gn
+++ b/chromium/ui/android/BUILD.gn
@@ -233,6 +233,7 @@ java_group("ui_java") {
android_library("ui_utils_java") {
java_files = [
"java/src/org/chromium/ui/ContactsPickerListener.java",
+ "java/src/org/chromium/ui/KeyboardVisibilityDelegate.java",
"java/src/org/chromium/ui/PhotoPickerListener.java",
"java/src/org/chromium/ui/UiUtils.java",
]
@@ -245,6 +246,7 @@ android_library("ui_full_java") {
java_files = [
"java/src/org/chromium/ui/AsyncViewStub.java",
"java/src/org/chromium/ui/AsyncViewProvider.java",
+ "java/src/org/chromium/ui/DeferredViewStubInflationProvider.java",
"java/src/org/chromium/ui/DropdownAdapter.java",
"java/src/org/chromium/ui/DropdownDividerDrawable.java",
"java/src/org/chromium/ui/DropdownItem.java",
@@ -255,6 +257,7 @@ android_library("ui_full_java") {
"java/src/org/chromium/ui/DropdownPopupWindowInterface.java",
"java/src/org/chromium/ui/HorizontalListDividerDrawable.java",
"java/src/org/chromium/ui/OverscrollRefreshHandler.java",
+ "java/src/org/chromium/ui/ViewProvider.java",
"java/src/org/chromium/ui/VSyncMonitor.java",
"java/src/org/chromium/ui/base/ActivityAndroidPermissionDelegate.java",
"java/src/org/chromium/ui/base/ActivityWindowAndroid.java",
@@ -307,6 +310,7 @@ android_library("ui_full_java") {
"java/src/org/chromium/ui/widget/AnchoredPopupWindow.java",
"java/src/org/chromium/ui/widget/ButtonCompat.java",
"java/src/org/chromium/ui/widget/CheckableImageView.java",
+ "java/src/org/chromium/ui/widget/ChromeBulletSpan.java",
"java/src/org/chromium/ui/widget/OptimizedFrameLayout.java",
"java/src/org/chromium/ui/widget/RectProvider.java",
"java/src/org/chromium/ui/widget/RoundedCornerImageView.java",
@@ -320,8 +324,8 @@ android_library("ui_full_java") {
":ui_java_resources",
":ui_utils_java",
"//base:base_java",
- "//third_party/android_tools:android_support_annotations_java",
- "//third_party/android_tools:android_support_v7_appcompat_java",
+ "//third_party/android_deps:android_support_annotations_java",
+ "//third_party/android_deps:android_support_v7_appcompat_java",
]
srcjar_deps = [
":java_enums_srcjar",
diff --git a/chromium/ui/android/delegated_frame_host_android.cc b/chromium/ui/android/delegated_frame_host_android.cc
index b28774aaf98..ec85b8eedbe 100644
--- a/chromium/ui/android/delegated_frame_host_android.cc
+++ b/chromium/ui/android/delegated_frame_host_android.cc
@@ -94,7 +94,6 @@ void DelegatedFrameHostAndroid::SubmitCompositorFrame(
viz::RenderPass* root_pass = frame.render_pass_list.back().get();
const bool has_transparent_background = root_pass->has_transparent_background;
- const float active_device_scale_factor = frame.device_scale_factor();
const gfx::Size pending_surface_size_in_pixels = frame.size_in_pixels();
// Reset |content_layer_| only if surface-sync is not used. When surface-sync
// is turned on, |content_layer_| is updated with the appropriate states (see
@@ -113,7 +112,6 @@ void DelegatedFrameHostAndroid::SubmitCompositorFrame(
if (!content_layer_) {
active_local_surface_id_ = local_surface_id;
pending_local_surface_id_ = active_local_surface_id_;
- active_device_scale_factor_ = active_device_scale_factor;
pending_surface_size_in_pixels_ = pending_surface_size_in_pixels;
has_transparent_background_ = has_transparent_background;
content_layer_ = CreateSurfaceLayer(
@@ -150,6 +148,8 @@ void DelegatedFrameHostAndroid::CopyFromCompositingSurface(
const gfx::Rect& src_subrect,
const gfx::Size& output_size,
base::OnceCallback<void(const SkBitmap&)> callback) {
+ DCHECK(CanCopyFromCompositingSurface());
+
std::unique_ptr<viz::CopyOutputRequest> request =
std::make_unique<viz::CopyOutputRequest>(
viz::CopyOutputRequest::ResultFormat::RGBA_BITMAP,
@@ -165,41 +165,48 @@ void DelegatedFrameHostAndroid::CopyFromCompositingSurface(
if (!output_size.IsEmpty())
request->set_result_selection(gfx::Rect(output_size));
- // If there is enough information to populate the copy output request fields,
- // then process it now. Otherwise, wait until the information becomes
- // available.
- if (CanCopyFromCompositingSurface() &&
- active_local_surface_id_ == pending_local_surface_id_) {
- ProcessCopyOutputRequest(std::move(request));
- } else {
- pending_first_frame_requests_.push_back(std::move(request));
+ if (!request->has_area())
+ request->set_area(gfx::Rect(pending_surface_size_in_pixels_));
+
+ if (request->has_result_selection()) {
+ const gfx::Rect& area = request->area();
+ const gfx::Rect& result_selection = request->result_selection();
+ if (area.IsEmpty() || result_selection.IsEmpty()) {
+ // Viz would normally return an empty result for an empty selection.
+ // However, this guard here is still necessary to protect against setting
+ // an illegal scaling ratio.
+ return;
+ }
+ request->SetScaleRatio(
+ gfx::Vector2d(area.width(), area.height()),
+ gfx::Vector2d(result_selection.width(), result_selection.height()));
}
+
+ host_frame_sink_manager_->RequestCopyOfOutput(
+ viz::SurfaceId(frame_sink_id_, pending_local_surface_id_),
+ std::move(request));
}
bool DelegatedFrameHostAndroid::CanCopyFromCompositingSurface() const {
- return content_layer_ && content_layer_->fallback_surface_id() &&
- content_layer_->fallback_surface_id()->is_valid() &&
- view_->GetWindowAndroid() &&
+ return pending_local_surface_id_.is_valid() && view_->GetWindowAndroid() &&
view_->GetWindowAndroid()->GetCompositor();
}
void DelegatedFrameHostAndroid::EvictDelegatedFrame() {
if (!content_layer_)
return;
- viz::SurfaceId surface_id;
- if (content_layer_->fallback_surface_id()) {
- surface_id = *content_layer_->fallback_surface_id();
- content_layer_->SetFallbackSurfaceId(viz::SurfaceId());
- }
content_layer_->SetPrimarySurfaceId(viz::SurfaceId(),
cc::DeadlinePolicy::UseDefaultDeadline());
if (!enable_surface_synchronization_) {
content_layer_->RemoveFromParent();
content_layer_ = nullptr;
}
- if (!surface_id.is_valid())
+ if (!HasSavedFrame())
return;
- std::vector<viz::SurfaceId> surface_ids = {surface_id};
+ std::vector<viz::SurfaceId> surface_ids = {
+ viz::SurfaceId(frame_sink_id_, active_local_surface_id_)};
+ // Reset information about the active surface because it will get destroyed.
+ active_local_surface_id_ = viz::LocalSurfaceId();
host_frame_sink_manager_->EvictSurfaces(surface_ids);
frame_evictor_->DiscardedFrame();
}
@@ -207,6 +214,16 @@ void DelegatedFrameHostAndroid::EvictDelegatedFrame() {
void DelegatedFrameHostAndroid::ResetFallbackToFirstNavigationSurface() {
if (!content_layer_)
return;
+ // Don't update the fallback if it's already newer than the first id after
+ // navigation.
+ if (content_layer_->fallback_surface_id() &&
+ content_layer_->fallback_surface_id()->frame_sink_id() ==
+ frame_sink_id_ &&
+ content_layer_->fallback_surface_id()
+ ->local_surface_id()
+ .IsSameOrNewerThan(first_local_surface_id_after_navigation_)) {
+ return;
+ }
content_layer_->SetFallbackSurfaceId(
viz::SurfaceId(frame_sink_id_, first_local_surface_id_after_navigation_));
}
@@ -296,16 +313,18 @@ void DelegatedFrameHostAndroid::EmbedSurface(
viz::SurfaceId current_primary_surface_id =
content_layer_->primary_surface_id();
+ viz::SurfaceId new_primary_surface_id(frame_sink_id_,
+ pending_local_surface_id_);
if (!frame_evictor_->visible()) {
- // If the tab is resized while hidden, reset the fallback so that the next
+ // If the tab is resized while hidden, advance the fallback so that the next
// time user switches back to it the page is blank. This is preferred to
// showing contents of old size. Don't call EvictDelegatedFrame to avoid
// races when dragging tabs across displays. See https://crbug.com/813157.
if (pending_surface_size_in_pixels_ != content_layer_->bounds() &&
content_layer_->fallback_surface_id() &&
content_layer_->fallback_surface_id()->is_valid()) {
- content_layer_->SetFallbackSurfaceId(viz::SurfaceId());
+ content_layer_->SetFallbackSurfaceId(new_primary_surface_id);
}
// Don't update the SurfaceLayer when invisible to avoid blocking on
// renderers that do not submit CompositorFrames. Next time the renderer
@@ -329,9 +348,8 @@ void DelegatedFrameHostAndroid::EmbedSurface(
deadline_policy = cc::DeadlinePolicy::UseSpecifiedDeadline(0u);
}
}
- viz::SurfaceId primary_surface_id(frame_sink_id_,
- pending_local_surface_id_);
- content_layer_->SetPrimarySurfaceId(primary_surface_id, deadline_policy);
+ content_layer_->SetPrimarySurfaceId(new_primary_surface_id,
+ deadline_policy);
content_layer_->SetBounds(new_pending_size_in_pixels);
}
}
@@ -397,31 +415,13 @@ void DelegatedFrameHostAndroid::OnFirstSurfaceActivation(
if (!enable_surface_synchronization_)
return;
- // If there's no primary surface, then we don't wish to display content at
- // this time (e.g. the view is hidden) and so we don't need a fallback
- // surface either. Since we won't use the fallback surface, we drop the
- // temporary reference here to save resources.
- if (!content_layer_->primary_surface_id().is_valid()) {
- host_frame_sink_manager_->DropTemporaryReference(surface_info.id());
- return;
- }
-
- content_layer_->SetFallbackSurfaceId(surface_info.id());
active_local_surface_id_ = surface_info.id().local_surface_id();
- active_device_scale_factor_ = surface_info.device_scale_factor();
// TODO(fsamuel): "SwappedFrame" is a bad name. Also, this method doesn't
// really need to take in visiblity. FrameEvictor already has the latest
// visibility state.
frame_evictor_->SwappedFrame(frame_evictor_->visible());
// Note: the frame may have been evicted immediately.
-
- if (!pending_first_frame_requests_.empty()) {
- DCHECK(CanCopyFromCompositingSurface());
- for (auto& request : pending_first_frame_requests_)
- ProcessCopyOutputRequest(std::move(request));
- pending_first_frame_requests_.clear();
- }
}
void DelegatedFrameHostAndroid::OnFrameTokenChanged(uint32_t frame_token) {
@@ -441,34 +441,12 @@ void DelegatedFrameHostAndroid::CreateCompositorFrameSinkSupport() {
this, frame_sink_id_, is_root, needs_sync_points);
}
-void DelegatedFrameHostAndroid::ProcessCopyOutputRequest(
- std::unique_ptr<viz::CopyOutputRequest> request) {
- if (!request->has_area())
- request->set_area(gfx::Rect(pending_surface_size_in_pixels_));
-
- if (request->has_result_selection()) {
- const gfx::Rect& area = request->area();
- const gfx::Rect& result_selection = request->result_selection();
- if (area.IsEmpty() || result_selection.IsEmpty()) {
- // Viz would normally return an empty result for an empty selection.
- // However, this guard here is still necessary to protect against setting
- // an illegal scaling ratio.
- return;
- }
- request->SetScaleRatio(
- gfx::Vector2d(area.width(), area.height()),
- gfx::Vector2d(result_selection.width(), result_selection.height()));
- }
-
- host_frame_sink_manager_->RequestCopyOfOutput(
- viz::SurfaceId(frame_sink_id_, pending_local_surface_id_),
- std::move(request));
+viz::SurfaceId DelegatedFrameHostAndroid::SurfaceId() const {
+ return viz::SurfaceId(frame_sink_id_, active_local_surface_id_);
}
-viz::SurfaceId DelegatedFrameHostAndroid::SurfaceId() const {
- return content_layer_ && content_layer_->fallback_surface_id()
- ? *content_layer_->fallback_surface_id()
- : viz::SurfaceId();
+bool DelegatedFrameHostAndroid::HasPrimarySurface() const {
+ return content_layer_ && content_layer_->primary_surface_id().is_valid();
}
bool DelegatedFrameHostAndroid::HasFallbackSurface() const {
@@ -478,27 +456,41 @@ bool DelegatedFrameHostAndroid::HasFallbackSurface() const {
void DelegatedFrameHostAndroid::TakeFallbackContentFrom(
DelegatedFrameHostAndroid* other) {
- if (HasFallbackSurface() || !other->HasFallbackSurface())
+ if (HasFallbackSurface() || !other->HasPrimarySurface())
return;
- if (!enable_surface_synchronization_) {
- if (content_layer_) {
- content_layer_->SetPrimarySurfaceId(
- *other->content_layer_->fallback_surface_id(),
- cc::DeadlinePolicy::UseDefaultDeadline());
+ if (enable_surface_synchronization_) {
+ const viz::SurfaceId& other_primary =
+ other->content_layer_->primary_surface_id();
+ const base::Optional<viz::SurfaceId>& other_fallback =
+ other->content_layer_->fallback_surface_id();
+ viz::SurfaceId desired_fallback;
+ if (!other->HasFallbackSurface() ||
+ !other_primary.IsSameOrNewerThan(*other_fallback)) {
+ desired_fallback = other_primary.ToSmallestId();
} else {
- const auto& surface_id = other->SurfaceId();
- active_local_surface_id_ = surface_id.local_surface_id();
- pending_local_surface_id_ = active_local_surface_id_;
- active_device_scale_factor_ = other->active_device_scale_factor_;
- pending_surface_size_in_pixels_ = other->pending_surface_size_in_pixels_;
- has_transparent_background_ = other->has_transparent_background_;
- content_layer_ = CreateSurfaceLayer(
- surface_id, surface_id, other->content_layer_->bounds(),
- cc::DeadlinePolicy::UseDefaultDeadline(),
- other->content_layer_->contents_opaque());
- view_->GetLayer()->AddChild(content_layer_);
+ desired_fallback = *other_fallback;
}
+ content_layer_->SetFallbackSurfaceId(
+ other->content_layer_->primary_surface_id().ToSmallestId());
+ return;
+ }
+
+ if (content_layer_) {
+ content_layer_->SetPrimarySurfaceId(
+ *other->content_layer_->fallback_surface_id(),
+ cc::DeadlinePolicy::UseDefaultDeadline());
+ } else {
+ const auto& surface_id = other->SurfaceId();
+ active_local_surface_id_ = surface_id.local_surface_id();
+ pending_local_surface_id_ = active_local_surface_id_;
+ pending_surface_size_in_pixels_ = other->pending_surface_size_in_pixels_;
+ has_transparent_background_ = other->has_transparent_background_;
+ content_layer_ = CreateSurfaceLayer(
+ surface_id, surface_id, other->content_layer_->bounds(),
+ cc::DeadlinePolicy::UseDefaultDeadline(),
+ other->content_layer_->contents_opaque());
+ view_->GetLayer()->AddChild(content_layer_);
}
content_layer_->SetFallbackSurfaceId(
*other->content_layer_->fallback_surface_id());
@@ -509,7 +501,6 @@ void DelegatedFrameHostAndroid::DidNavigate() {
return;
first_local_surface_id_after_navigation_ = pending_local_surface_id_;
- received_frame_after_navigation_ = false;
}
} // namespace ui
diff --git a/chromium/ui/android/delegated_frame_host_android.h b/chromium/ui/android/delegated_frame_host_android.h
index 13a83cfebae..eef5417b4eb 100644
--- a/chromium/ui/android/delegated_frame_host_android.h
+++ b/chromium/ui/android/delegated_frame_host_android.h
@@ -134,6 +134,7 @@ class UI_ANDROID_EXPORT DelegatedFrameHostAndroid
// Returns the ID for the current Surface. Returns an invalid ID if no
// surface exists (!HasDelegatedContent()).
viz::SurfaceId SurfaceId() const;
+ bool HasPrimarySurface() const;
bool HasFallbackSurface() const;
void TakeFallbackContentFrom(DelegatedFrameHostAndroid* other);
@@ -201,16 +202,10 @@ class UI_ANDROID_EXPORT DelegatedFrameHostAndroid
// Whether we've received a frame from the renderer since navigating.
// Only used when surface synchronization is on.
viz::LocalSurfaceId first_local_surface_id_after_navigation_;
- bool received_frame_after_navigation_ = false;
-
- std::vector<std::unique_ptr<viz::CopyOutputRequest>>
- pending_first_frame_requests_;
// The surface id that was most recently activated by
// OnFirstSurfaceActivation.
viz::LocalSurfaceId active_local_surface_id_;
- // The scale factor of the above surface.
- float active_device_scale_factor_ = 0.f;
// The local surface id as of the most recent call to
// EmbedSurface. This is the surface that we expect future frames to
diff --git a/chromium/ui/android/delegated_frame_host_android_unittest.cc b/chromium/ui/android/delegated_frame_host_android_unittest.cc
index 013ebd2205b..9248c71eb4d 100644
--- a/chromium/ui/android/delegated_frame_host_android_unittest.cc
+++ b/chromium/ui/android/delegated_frame_host_android_unittest.cc
@@ -8,6 +8,7 @@
#include "cc/layers/layer.h"
#include "cc/layers/solid_color_layer.h"
#include "cc/layers/surface_layer.h"
+#include "cc/trees/layer_tree_host.h"
#include "components/viz/common/hit_test/hit_test_region_list.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
#include "components/viz/host/host_frame_sink_manager.h"
@@ -69,18 +70,13 @@ class MockWindowAndroidCompositor : public WindowAndroidCompositor {
}
};
-class MockCompositorLockManagerClient : public ui::CompositorLockManagerClient {
- public:
- MOCK_METHOD1(OnCompositorLockStateChanged, void(bool));
-};
-
class DelegatedFrameHostAndroidTest : public testing::Test {
public:
DelegatedFrameHostAndroidTest()
: frame_sink_manager_impl_(&shared_bitmap_manager_),
frame_sink_id_(1, 1),
task_runner_(new base::TestMockTimeTaskRunner()),
- lock_manager_(task_runner_, &lock_manager_client_) {
+ lock_manager_(task_runner_) {
host_frame_sink_manager_.SetLocalManager(&frame_sink_manager_impl_);
frame_sink_manager_impl_.SetLocalClient(&host_frame_sink_manager_);
}
@@ -98,9 +94,12 @@ class DelegatedFrameHostAndroidTest : public testing::Test {
ui::CompositorLock* GetLock(CompositorLockClient* client,
base::TimeDelta time_delta) {
- return lock_manager_.GetCompositorLock(client, time_delta).release();
+ return lock_manager_.GetCompositorLock(client, time_delta, nullptr)
+ .release();
}
+ bool IsLocked() const { return lock_manager_.IsLocked(); }
+
void SubmitCompositorFrame(const gfx::Size& frame_size = gfx::Size(10, 10)) {
viz::CompositorFrame frame =
viz::CompositorFrameBuilder()
@@ -115,13 +114,11 @@ class DelegatedFrameHostAndroidTest : public testing::Test {
.WillOnce(Return(true));
EXPECT_CALL(compositor_, DoGetCompositorLock(frame_host_.get(), _))
.WillOnce(Invoke(this, &DelegatedFrameHostAndroidTest::GetLock));
- EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(true))
- .Times(1);
frame_host_->AttachToCompositor(&compositor_);
+ EXPECT_TRUE(IsLocked());
- EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(false))
- .Times(1);
SubmitCompositorFrame(frame_size);
+ EXPECT_FALSE(IsLocked());
}
protected:
@@ -134,7 +131,6 @@ class DelegatedFrameHostAndroidTest : public testing::Test {
viz::FrameSinkId frame_sink_id_;
viz::ParentLocalSurfaceIdAllocator allocator_;
std::unique_ptr<DelegatedFrameHostAndroid> frame_host_;
- MockCompositorLockManagerClient lock_manager_client_;
scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
CompositorLockManager lock_manager_;
};
@@ -192,14 +188,12 @@ TEST_F(DelegatedFrameHostAndroidTest, CompositorLockDuringFirstFrame) {
EXPECT_CALL(compositor_, IsDrawingFirstVisibleFrame()).WillOnce(Return(true));
EXPECT_CALL(compositor_, DoGetCompositorLock(frame_host_.get(), _))
.WillOnce(Invoke(this, &DelegatedFrameHostAndroidTest::GetLock));
- EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(true))
- .Times(1);
frame_host_->AttachToCompositor(&compositor_);
+ EXPECT_TRUE(IsLocked());
// Lock should be released when we submit a compositor frame.
- EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(false))
- .Times(1);
SubmitCompositorFrame();
+ EXPECT_FALSE(IsLocked());
}
TEST_F(DelegatedFrameHostAndroidTest, CompositorLockDuringLaterFrame) {
@@ -226,14 +220,12 @@ TEST_F(DelegatedFrameHostAndroidTest, CompositorLockReleasedWithDetach) {
EXPECT_CALL(compositor_, IsDrawingFirstVisibleFrame()).WillOnce(Return(true));
EXPECT_CALL(compositor_, DoGetCompositorLock(frame_host_.get(), _))
.WillOnce(Invoke(this, &DelegatedFrameHostAndroidTest::GetLock));
- EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(true))
- .Times(1);
frame_host_->AttachToCompositor(&compositor_);
+ EXPECT_TRUE(IsLocked());
// Lock should be released when we detach.
- EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(false))
- .Times(1);
frame_host_->DetachFromCompositor();
+ EXPECT_FALSE(IsLocked());
}
TEST_F(DelegatedFrameHostAndroidTest, ResizeLockBasic) {
@@ -246,19 +238,16 @@ TEST_F(DelegatedFrameHostAndroidTest, ResizeLockBasic) {
// Tell the frame host to resize, it should take a lock.
EXPECT_CALL(compositor_, DoGetCompositorLock(frame_host_.get(), _))
.WillOnce(Invoke(this, &DelegatedFrameHostAndroidTest::GetLock));
- EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(true))
- .Times(1);
frame_host_->PixelSizeWillChange(gfx::Size(50, 50));
+ EXPECT_TRUE(IsLocked());
// Submit a frame of the wrong size, nothing should change.
- EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(false))
- .Times(0);
SubmitCompositorFrame(gfx::Size(20, 20));
+ EXPECT_TRUE(IsLocked());
// Submit a frame with the right size, the lock should release.
- EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(false))
- .Times(1);
SubmitCompositorFrame(gfx::Size(50, 50));
+ EXPECT_FALSE(IsLocked());
}
TEST_F(DelegatedFrameHostAndroidTest, ResizeLockNotTakenIfNoSizeChange) {
@@ -269,9 +258,8 @@ TEST_F(DelegatedFrameHostAndroidTest, ResizeLockNotTakenIfNoSizeChange) {
SetUpValidFrame(gfx::Size(10, 10));
// Tell the frame host to resize to the existing size, nothing should happen.
- EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(true))
- .Times(0);
frame_host_->PixelSizeWillChange(gfx::Size(10, 10));
+ EXPECT_FALSE(IsLocked());
}
TEST_F(DelegatedFrameHostAndroidTest, ResizeLockReleasedWithDetach) {
@@ -284,14 +272,12 @@ TEST_F(DelegatedFrameHostAndroidTest, ResizeLockReleasedWithDetach) {
// Tell the frame host to resize, it should take a lock.
EXPECT_CALL(compositor_, DoGetCompositorLock(frame_host_.get(), _))
.WillOnce(Invoke(this, &DelegatedFrameHostAndroidTest::GetLock));
- EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(true))
- .Times(1);
frame_host_->PixelSizeWillChange(gfx::Size(50, 50));
+ EXPECT_TRUE(IsLocked());
// Lock should be released when we detach.
- EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(false))
- .Times(1);
frame_host_->DetachFromCompositor();
+ EXPECT_FALSE(IsLocked());
}
TEST_F(DelegatedFrameHostAndroidTest, TestBothCompositorLocks) {
@@ -303,21 +289,18 @@ TEST_F(DelegatedFrameHostAndroidTest, TestBothCompositorLocks) {
EXPECT_CALL(compositor_, IsDrawingFirstVisibleFrame()).WillOnce(Return(true));
EXPECT_CALL(compositor_, DoGetCompositorLock(frame_host_.get(), _))
.WillOnce(Invoke(this, &DelegatedFrameHostAndroidTest::GetLock));
- EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(true))
- .Times(1);
frame_host_->AttachToCompositor(&compositor_);
+ EXPECT_TRUE(IsLocked());
// Tell the frame host to resize, it should take a second lock.
EXPECT_CALL(compositor_, DoGetCompositorLock(frame_host_.get(), _))
.WillOnce(Invoke(this, &DelegatedFrameHostAndroidTest::GetLock));
- EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(true))
- .Times(0);
frame_host_->PixelSizeWillChange(gfx::Size(50, 50));
+ EXPECT_TRUE(IsLocked());
// Submit a compositor frame of the right size, both locks should release.
- EXPECT_CALL(lock_manager_client_, OnCompositorLockStateChanged(false))
- .Times(1);
SubmitCompositorFrame(gfx::Size(50, 50));
+ EXPECT_FALSE(IsLocked());
}
} // namespace
diff --git a/chromium/ui/android/display_android_manager.cc b/chromium/ui/android/display_android_manager.cc
index b7c04d5e362..7352daa7127 100644
--- a/chromium/ui/android/display_android_manager.cc
+++ b/chromium/ui/android/display_android_manager.cc
@@ -89,7 +89,7 @@ void DisplayAndroidManager::UpdateDisplay(
display::Display display(sdkDisplayId, bounds_in_dip);
if (!Display::HasForceDeviceScaleFactor())
display.set_device_scale_factor(dipScale);
- if (!Display::HasForceColorProfile()) {
+ if (!Display::HasForceDisplayColorProfile()) {
// TODO(ccameron): Use CreateDisplayP3D65 if isWideColorGamut is true, once
// the feature is ready to use.
display.set_color_space(gfx::ColorSpace::CreateSRGB());
diff --git a/chromium/ui/android/junit/src/org/chromium/ui/AsyncViewProviderTest.java b/chromium/ui/android/junit/src/org/chromium/ui/AsyncViewProviderTest.java
new file mode 100644
index 00000000000..37e04ef6b85
--- /dev/null
+++ b/chromium/ui/android/junit/src/org/chromium/ui/AsyncViewProviderTest.java
@@ -0,0 +1,131 @@
+// 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.
+
+package org.chromium.ui;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+import static org.junit.Assert.assertTrue;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.ImageView;
+import android.widget.LinearLayout;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowLooper;
+
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.ui.shadows.ShadowAsyncLayoutInflater;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Tests logic in the AsyncViewProvider class.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, shadows = {ShadowAsyncLayoutInflater.class})
+public class AsyncViewProviderTest {
+ private LinearLayout mRoot;
+ private AsyncViewStub mAsyncViewStub;
+ private AsyncViewProvider<View> mAsyncViewProvider;
+ private final AtomicInteger mEventCount = new AtomicInteger();
+ private static final int MAIN_LAYOUT_RESOURCE_ID = org.chromium.test.ui.R.layout.main_view;
+ private static final int INFLATE_LAYOUT_RESOURCE_ID =
+ org.chromium.test.ui.R.layout.inflated_view;
+ private static final int STUB_ID = org.chromium.test.ui.R.id.view_stub;
+ private static final int INFLATED_VIEW_ID = org.chromium.test.ui.R.id.inflated_view;
+ private static final int PREINFLATED_VIEW_ID = org.chromium.test.ui.R.id.pre_inflated_view;
+
+ @Before
+ public void setUp() {
+ mRoot = (LinearLayout) LayoutInflater.from(RuntimeEnvironment.application)
+ .inflate(MAIN_LAYOUT_RESOURCE_ID, null);
+ mAsyncViewStub = mRoot.findViewById(STUB_ID);
+ mAsyncViewStub.setLayoutResource(INFLATE_LAYOUT_RESOURCE_ID);
+ mAsyncViewStub.setShouldInflateOnBackgroundThread(true);
+ mAsyncViewProvider = AsyncViewProvider.of(mAsyncViewStub, INFLATED_VIEW_ID);
+ mAsyncViewStub.setId(STUB_ID);
+ mEventCount.set(0);
+ }
+
+ @Test
+ public void testCreatesUnloadedProviderIfNotInflated() {
+ AsyncViewProvider provider = AsyncViewProvider.of(mAsyncViewStub, INFLATED_VIEW_ID);
+ assertNull(provider.get());
+ }
+
+ @Test
+ public void testCreatesLoadedProviderIfInflated() {
+ mAsyncViewStub.inflate();
+ ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
+ AsyncViewProvider provider = AsyncViewProvider.of(mAsyncViewStub, INFLATED_VIEW_ID);
+ assertNotNull(provider.get());
+ }
+
+ @Test
+ public void testCreatesUnloadedProviderUsingResourceIds() {
+ AsyncViewProvider provider = AsyncViewProvider.of(mRoot, STUB_ID, INFLATED_VIEW_ID);
+ assertNull(provider.get());
+ }
+
+ @Test
+ public void testCreatesLoadedProviderUsingResourceIds() {
+ mAsyncViewStub.inflate();
+ ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
+ AsyncViewProvider provider = AsyncViewProvider.of(mRoot, STUB_ID, INFLATED_VIEW_ID);
+ assertNotNull(provider.get());
+ }
+
+ @Test
+ public void testCreatesLoadedProviderUsingResourceIdsWithoutAsyncViewStub() {
+ AsyncViewProvider provider = AsyncViewProvider.of(mRoot, 0, PREINFLATED_VIEW_ID);
+ assertNotNull(provider.get());
+ assertTrue(provider.get() instanceof ImageView);
+ }
+
+ @Test
+ public void testRunsCallbackImmediatelyIfLoaded() {
+ mAsyncViewStub.inflate();
+ ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
+ AsyncViewProvider<View> provider = AsyncViewProvider.of(mAsyncViewStub, INFLATED_VIEW_ID);
+ assertEquals(mEventCount.get(), 0);
+ provider.whenLoaded((View v) -> { mEventCount.incrementAndGet(); });
+ assertEquals(mEventCount.get(), 1);
+ provider.whenLoaded((View v) -> { mEventCount.incrementAndGet(); });
+ assertEquals(mEventCount.get(), 2);
+ }
+
+ @Test
+ public void testCallsListenersOnUiThread() {
+ mAsyncViewProvider.whenLoaded((View v) -> {
+ assertTrue(ThreadUtils.runningOnUiThread());
+ mEventCount.incrementAndGet();
+ });
+ mAsyncViewStub.inflate();
+ ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
+ // ensure callback gets called.
+ assertEquals(mEventCount.get(), 1);
+ }
+
+ @Test
+ public void testCallsListenersInOrder() {
+ mAsyncViewProvider.whenLoaded(
+ (View v) -> { assertEquals(mEventCount.incrementAndGet(), 1); });
+ mAsyncViewProvider.whenLoaded(
+ (View v) -> { assertEquals(mEventCount.incrementAndGet(), 2); });
+ mAsyncViewProvider.whenLoaded(
+ (View v) -> { assertEquals(mEventCount.decrementAndGet(), 1); });
+ assertEquals(mEventCount.get(), 0);
+ mAsyncViewStub.inflate();
+ ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
+ assertEquals(mEventCount.get(), 1);
+ }
+} \ No newline at end of file
diff --git a/chromium/ui/android/junit/src/org/chromium/ui/AsyncViewStubTest.java b/chromium/ui/android/junit/src/org/chromium/ui/AsyncViewStubTest.java
new file mode 100644
index 00000000000..4c3e9d83b1f
--- /dev/null
+++ b/chromium/ui/android/junit/src/org/chromium/ui/AsyncViewStubTest.java
@@ -0,0 +1,75 @@
+// 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.
+
+package org.chromium.ui;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertTrue;
+
+import android.view.LayoutInflater;
+import android.view.View;
+import android.widget.LinearLayout;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowLooper;
+
+import org.chromium.base.ThreadUtils;
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.ui.shadows.ShadowAsyncLayoutInflater;
+
+import java.util.concurrent.atomic.AtomicInteger;
+
+/**
+ * Tests logic in the AsyncViewStub class.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, shadows = {ShadowAsyncLayoutInflater.class})
+public class AsyncViewStubTest {
+ private AsyncViewStub mAsyncViewStub;
+ private final AtomicInteger mEventCount = new AtomicInteger();
+ private static final int MAIN_LAYOUT_RESOURCE_ID = org.chromium.test.ui.R.layout.main_view;
+ private static final int INFLATE_LAYOUT_RESOURCE_ID =
+ org.chromium.test.ui.R.layout.inflated_view;
+ private static final int STUB_ID = org.chromium.test.ui.R.id.view_stub;
+
+ @Before
+ public void setUp() {
+ LinearLayout mainView = (LinearLayout) LayoutInflater.from(RuntimeEnvironment.application)
+ .inflate(MAIN_LAYOUT_RESOURCE_ID, null);
+ mAsyncViewStub = mainView.findViewById(STUB_ID);
+ mAsyncViewStub.setLayoutResource(INFLATE_LAYOUT_RESOURCE_ID);
+ mAsyncViewStub.setShouldInflateOnBackgroundThread(true);
+ mEventCount.set(0);
+ }
+
+ @Test
+ public void testCallsListenersOnUiThread() {
+ mAsyncViewStub.addOnInflateListener((View v) -> {
+ assertTrue(ThreadUtils.runningOnUiThread());
+ mEventCount.incrementAndGet();
+ });
+ mAsyncViewStub.inflate();
+ ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
+ // ensure callback gets called.
+ assertEquals(mEventCount.get(), 1);
+ }
+
+ @Test
+ public void testCallsListenersInOrder() {
+ mAsyncViewStub.addOnInflateListener(
+ (View v) -> { assertEquals(mEventCount.incrementAndGet(), 1); });
+ mAsyncViewStub.addOnInflateListener(
+ (View v) -> { assertEquals(mEventCount.incrementAndGet(), 2); });
+ mAsyncViewStub.addOnInflateListener(
+ (View v) -> { assertEquals(mEventCount.decrementAndGet(), 1); });
+ assertEquals(mEventCount.get(), 0);
+ mAsyncViewStub.inflate();
+ ShadowLooper.runUiThreadTasksIncludingDelayedTasks();
+ assertEquals(mEventCount.get(), 1);
+ }
+} \ No newline at end of file
diff --git a/chromium/ui/android/junit/src/org/chromium/ui/base/ClipboardTest.java b/chromium/ui/android/junit/src/org/chromium/ui/base/ClipboardTest.java
new file mode 100644
index 00000000000..30099db7bd8
--- /dev/null
+++ b/chromium/ui/android/junit/src/org/chromium/ui/base/ClipboardTest.java
@@ -0,0 +1,56 @@
+// 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.
+
+package org.chromium.ui.base;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertNotNull;
+import static org.junit.Assert.assertNull;
+
+import android.content.ClipData;
+import android.content.Intent;
+import android.text.SpannableString;
+import android.text.style.RelativeSizeSpan;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+
+/**
+ * Tests logic in the Clipboard class.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class ClipboardTest {
+ private static final String PLAIN_TEXT = "plain";
+ private static final String HTML_TEXT = "<span style=\"color: red;\">HTML</span>";
+
+ @Test
+ public void testClipDataToHtmlText() {
+ Clipboard clipboard = Clipboard.getInstance();
+
+ // HTML text
+ ClipData html = ClipData.newHtmlText("html", PLAIN_TEXT, HTML_TEXT);
+ assertEquals(HTML_TEXT, clipboard.clipDataToHtmlText(html));
+
+ // Plain text without span
+ ClipData plainTextNoSpan = ClipData.newPlainText("plain", PLAIN_TEXT);
+ assertNull(clipboard.clipDataToHtmlText(plainTextNoSpan));
+
+ // Plain text with span
+ SpannableString spanned = new SpannableString(PLAIN_TEXT);
+ spanned.setSpan(new RelativeSizeSpan(2f), 0, 5, 0);
+ ClipData plainTextSpan = ClipData.newPlainText("plain", spanned);
+ assertNotNull(clipboard.clipDataToHtmlText(plainTextSpan));
+
+ // Intent
+ Intent intent = new Intent(Intent.ACTION_GET_CONTENT);
+ intent.addCategory(Intent.CATEGORY_OPENABLE);
+ intent.setType("*/*");
+ ClipData intentClip = ClipData.newIntent("intent", intent);
+ assertNull(clipboard.clipDataToHtmlText(intentClip));
+ }
+}
diff --git a/chromium/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java b/chromium/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java
new file mode 100644
index 00000000000..ebcc7d363f7
--- /dev/null
+++ b/chromium/ui/android/junit/src/org/chromium/ui/base/SelectFileDialogTest.java
@@ -0,0 +1,147 @@
+// 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.
+
+package org.chromium.ui.base;
+
+import static org.junit.Assert.assertEquals;
+
+import android.net.Uri;
+import android.webkit.MimeTypeMap;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.Shadows;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadows.ShadowMimeTypeMap;
+
+import org.chromium.base.ContextUtils;
+import org.chromium.base.test.BaseRobolectricTestRunner;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+
+/**
+ * Tests logic in the SelectFileDialog class.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class SelectFileDialogTest {
+ /**
+ * Returns the determined scope for the accepted |fileTypes|.
+ */
+ private int scopeForFileTypes(String... fileTypes) {
+ SelectFileDialog instance = SelectFileDialog.create((long) 0 /* nativeSelectFileDialog */);
+ instance.setFileTypesForTests(new ArrayList<String>(Arrays.asList(fileTypes)));
+
+ return instance.determineSelectFileDialogScope();
+ }
+
+ @Test
+ public void testDetermineSelectFileDialogScope() {
+ assertEquals(SelectFileDialog.SELECT_FILE_DIALOG_SCOPE_GENERIC, scopeForFileTypes());
+ assertEquals(SelectFileDialog.SELECT_FILE_DIALOG_SCOPE_GENERIC, scopeForFileTypes("*/*"));
+ assertEquals(
+ SelectFileDialog.SELECT_FILE_DIALOG_SCOPE_GENERIC, scopeForFileTypes("text/plain"));
+
+ assertEquals(
+ SelectFileDialog.SELECT_FILE_DIALOG_SCOPE_IMAGES, scopeForFileTypes("image/*"));
+ assertEquals(
+ SelectFileDialog.SELECT_FILE_DIALOG_SCOPE_IMAGES, scopeForFileTypes("image/png"));
+ assertEquals(SelectFileDialog.SELECT_FILE_DIALOG_SCOPE_GENERIC,
+ scopeForFileTypes("image/*", "test/plain"));
+
+ assertEquals(
+ SelectFileDialog.SELECT_FILE_DIALOG_SCOPE_VIDEOS, scopeForFileTypes("video/*"));
+ assertEquals(
+ SelectFileDialog.SELECT_FILE_DIALOG_SCOPE_VIDEOS, scopeForFileTypes("video/ogg"));
+ assertEquals(SelectFileDialog.SELECT_FILE_DIALOG_SCOPE_GENERIC,
+ scopeForFileTypes("video/*", "test/plain"));
+ assertEquals(SelectFileDialog.SELECT_FILE_DIALOG_SCOPE_IMAGES,
+ scopeForFileTypes("image/x-png", "image/gif", "image/jpeg"));
+ assertEquals(SelectFileDialog.SELECT_FILE_DIALOG_SCOPE_GENERIC,
+ scopeForFileTypes("image/x-png", "image/gif", "image/jpeg", "text/plain"));
+
+ // Test image extensions only.
+ assertEquals(SelectFileDialog.SELECT_FILE_DIALOG_SCOPE_IMAGES,
+ scopeForFileTypes(".jpg", ".jpeg", ".png", ".gif", ".apng", ".tiff", ".tif", ".bmp",
+ ".pdf", ".xcf", ".webp"));
+ // Test image extensions mixed with image MIME types.
+ assertEquals(SelectFileDialog.SELECT_FILE_DIALOG_SCOPE_IMAGES,
+ scopeForFileTypes(".JPG", ".jpeg", "image/gif", "image/jpeg"));
+ // Image extensions mixed with image MIME types and other.
+ assertEquals(SelectFileDialog.SELECT_FILE_DIALOG_SCOPE_GENERIC,
+ scopeForFileTypes(".jpg", "image/gif", "text/plain"));
+ // Video extensions only.
+ assertEquals(SelectFileDialog.SELECT_FILE_DIALOG_SCOPE_VIDEOS,
+ scopeForFileTypes(".asf", ".avhcd", ".avi", ".flv", ".mov", ".mp4", ".mpeg", ".mpg",
+ ".swf", ".wmv", ".webm", ".mkv", ".divx"));
+ // Video extensions and video MIME types.
+ assertEquals(SelectFileDialog.SELECT_FILE_DIALOG_SCOPE_VIDEOS,
+ scopeForFileTypes(".avi", ".mp4", "video/ogg"));
+ // Video extensions and video MIME types and other.
+ assertEquals(SelectFileDialog.SELECT_FILE_DIALOG_SCOPE_GENERIC,
+ scopeForFileTypes(".avi", ".mp4", "video/ogg", "text/plain"));
+
+ // Non-image, non-video extension only.
+ assertEquals(SelectFileDialog.SELECT_FILE_DIALOG_SCOPE_GENERIC, scopeForFileTypes(".doc"));
+
+ assertEquals(SelectFileDialog.SELECT_FILE_DIALOG_SCOPE_IMAGES_AND_VIDEOS,
+ scopeForFileTypes("video/*", "image/*"));
+ assertEquals(SelectFileDialog.SELECT_FILE_DIALOG_SCOPE_IMAGES_AND_VIDEOS,
+ scopeForFileTypes("image/jpeg", "video/ogg"));
+ assertEquals(SelectFileDialog.SELECT_FILE_DIALOG_SCOPE_GENERIC,
+ scopeForFileTypes("video/*", "image/*", "text/plain"));
+ }
+
+ @Test
+ public void testPhotoPickerLaunchAndMimeTypes() throws Throwable {
+ ShadowMimeTypeMap shadowMimeTypeMap = Shadows.shadowOf(MimeTypeMap.getSingleton());
+ shadowMimeTypeMap.addExtensionMimeTypMapping("jpg", "image/jpeg");
+ shadowMimeTypeMap.addExtensionMimeTypMapping("gif", "image/gif");
+ shadowMimeTypeMap.addExtensionMimeTypMapping("txt", "text/plain");
+ shadowMimeTypeMap.addExtensionMimeTypMapping("mpg", "audio/mpeg");
+
+ assertEquals("", SelectFileDialog.ensureMimeType(""));
+ assertEquals("image/jpeg", SelectFileDialog.ensureMimeType(".jpg"));
+ assertEquals("image/jpeg", SelectFileDialog.ensureMimeType("image/jpeg"));
+ // Unknown extension, expect default response:
+ assertEquals("application/octet-stream", SelectFileDialog.ensureMimeType(".flv"));
+
+ assertEquals(null, SelectFileDialog.convertToImageMimeTypes(new ArrayList<>()));
+ assertEquals(null, SelectFileDialog.convertToImageMimeTypes(Arrays.asList("")));
+ assertEquals(null, SelectFileDialog.convertToImageMimeTypes(Arrays.asList("foo/bar")));
+ assertEquals(Arrays.asList("image/jpeg"),
+ SelectFileDialog.convertToImageMimeTypes(Arrays.asList(".jpg")));
+ assertEquals(Arrays.asList("image/jpeg"),
+ SelectFileDialog.convertToImageMimeTypes(Arrays.asList("image/jpeg")));
+ assertEquals(Arrays.asList("image/jpeg"),
+ SelectFileDialog.convertToImageMimeTypes(Arrays.asList(".jpg", "image/jpeg")));
+ assertEquals(Arrays.asList("image/gif", "image/jpeg"),
+ SelectFileDialog.convertToImageMimeTypes(Arrays.asList(".gif", "image/jpeg")));
+
+ // Returns null because generic picker is required (due to addition of .txt file).
+ assertEquals(null,
+ SelectFileDialog.convertToImageMimeTypes(
+ Arrays.asList(".txt", ".jpg", "image/jpeg")));
+ // Returns null because video file is included.
+ assertEquals(null,
+ SelectFileDialog.convertToImageMimeTypes(
+ Arrays.asList(".jpg", "image/jpeg", ".mpg")));
+ }
+
+ @Test
+ public void testMultipleFileSelectorWithFileUris() throws Throwable {
+ SelectFileDialog selectFileDialog = new SelectFileDialog(0);
+ Uri[] filePathArray = new Uri[] {
+ Uri.parse("file:///storage/emulated/0/DCIM/Camera/IMG_0.jpg"),
+ Uri.parse("file:///storage/emulated/0/DCIM/Camera/IMG_1.jpg")};
+ SelectFileDialog.GetDisplayNameTask task = selectFileDialog.new GetDisplayNameTask(
+ ContextUtils.getApplicationContext(), true, filePathArray);
+ task.doInBackground();
+ assertEquals(task.mFilePaths[0].toString(),
+ "///storage/emulated/0/DCIM/Camera/IMG_0.jpg");
+ assertEquals(task.mFilePaths[1].toString(),
+ "///storage/emulated/0/DCIM/Camera/IMG_1.jpg");
+ }
+}
diff --git a/chromium/ui/android/junit/src/org/chromium/ui/drawable/StateListDrawableBuilderTest.java b/chromium/ui/android/junit/src/org/chromium/ui/drawable/StateListDrawableBuilderTest.java
new file mode 100644
index 00000000000..48911eb6a5e
--- /dev/null
+++ b/chromium/ui/android/junit/src/org/chromium/ui/drawable/StateListDrawableBuilderTest.java
@@ -0,0 +1,62 @@
+// 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.
+
+package org.chromium.ui.drawable;
+
+import static org.junit.Assert.assertEquals;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.graphics.drawable.AnimatedStateListDrawable;
+import android.graphics.drawable.StateListDrawable;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+import org.robolectric.shadow.api.Shadow;
+import org.robolectric.shadows.ShadowStateListDrawable;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.ui.shadows.ShadowAnimatedStateListDrawable;
+import org.chromium.ui.shadows.ShadowAppCompatResources;
+
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE,
+ shadows = {ShadowAppCompatResources.class, ShadowAnimatedStateListDrawable.class})
+public class StateListDrawableBuilderTest {
+ private static final int[] CHECKED_STATE = new int[] {android.R.attr.state_checked};
+ private static final int[] WILDCARD_STATE = new int[0];
+ private static final int CHECKED_DRAWABLE = 34567;
+ private static final int DEFAULT_DRAWABLE = 45678;
+
+ @Test
+ @Config(sdk = 18)
+ public void testPreL() {
+ StateListDrawableBuilder b = new StateListDrawableBuilder(RuntimeEnvironment.application);
+ b.addState(CHECKED_DRAWABLE, android.R.attr.state_checked);
+ b.addState(DEFAULT_DRAWABLE, WILDCARD_STATE);
+ StateListDrawable result = b.build();
+ assertEquals(result.getClass(), StateListDrawable.class);
+ ShadowStateListDrawable drawable = shadowOf(result);
+ assertEquals(CHECKED_DRAWABLE,
+ shadowOf(drawable.getDrawableForState(CHECKED_STATE)).getCreatedFromResId());
+ assertEquals(DEFAULT_DRAWABLE,
+ shadowOf(drawable.getDrawableForState(WILDCARD_STATE)).getCreatedFromResId());
+ }
+
+ @Test
+ @Config(sdk = 21)
+ public void testPostL() {
+ StateListDrawableBuilder b = new StateListDrawableBuilder(RuntimeEnvironment.application);
+ b.addState(CHECKED_DRAWABLE, android.R.attr.state_checked);
+ b.addState(DEFAULT_DRAWABLE, WILDCARD_STATE);
+ StateListDrawable result = b.build();
+ assertEquals(result.getClass(), AnimatedStateListDrawable.class);
+ ShadowAnimatedStateListDrawable drawable = Shadow.extract(result);
+ assertEquals(CHECKED_DRAWABLE,
+ shadowOf(drawable.getDrawableForState(CHECKED_STATE)).getCreatedFromResId());
+ assertEquals(DEFAULT_DRAWABLE,
+ shadowOf(drawable.getDrawableForState(WILDCARD_STATE)).getCreatedFromResId());
+ }
+}
diff --git a/chromium/ui/android/junit/src/org/chromium/ui/shadows/ShadowAnimatedStateListDrawable.java b/chromium/ui/android/junit/src/org/chromium/ui/shadows/ShadowAnimatedStateListDrawable.java
new file mode 100644
index 00000000000..94120e582ce
--- /dev/null
+++ b/chromium/ui/android/junit/src/org/chromium/ui/shadows/ShadowAnimatedStateListDrawable.java
@@ -0,0 +1,18 @@
+// 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.
+
+package org.chromium.ui.shadows;
+
+import android.graphics.drawable.AnimatedStateListDrawable;
+import android.graphics.drawable.Drawable;
+
+import org.robolectric.annotation.Implements;
+import org.robolectric.shadows.ShadowStateListDrawable;
+
+@Implements(AnimatedStateListDrawable.class)
+public class ShadowAnimatedStateListDrawable extends ShadowStateListDrawable {
+ public void addState(int[] stateSet, Drawable drawable, int stateId) {
+ addState(stateSet, drawable);
+ }
+}
diff --git a/chromium/ui/android/junit/src/org/chromium/ui/shadows/ShadowAppCompatResources.java b/chromium/ui/android/junit/src/org/chromium/ui/shadows/ShadowAppCompatResources.java
new file mode 100644
index 00000000000..036ed79a38e
--- /dev/null
+++ b/chromium/ui/android/junit/src/org/chromium/ui/shadows/ShadowAppCompatResources.java
@@ -0,0 +1,25 @@
+// 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.
+
+package org.chromium.ui.shadows;
+
+import android.content.Context;
+import android.graphics.drawable.Drawable;
+import android.support.annotation.DrawableRes;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v7.content.res.AppCompatResources;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+import org.robolectric.shadows.ShadowDrawable;
+
+@Implements(AppCompatResources.class)
+public class ShadowAppCompatResources {
+ @Implementation
+ @Nullable
+ public static Drawable getDrawable(@NonNull Context context, @DrawableRes int resId) {
+ return ShadowDrawable.createFromResourceId(resId);
+ }
+}
diff --git a/chromium/ui/android/junit/src/org/chromium/ui/shadows/ShadowAppCompatResourcesTest.java b/chromium/ui/android/junit/src/org/chromium/ui/shadows/ShadowAppCompatResourcesTest.java
new file mode 100644
index 00000000000..c9d359dfb77
--- /dev/null
+++ b/chromium/ui/android/junit/src/org/chromium/ui/shadows/ShadowAppCompatResourcesTest.java
@@ -0,0 +1,32 @@
+// 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.
+
+package org.chromium.ui.shadows;
+
+import static org.junit.Assert.assertEquals;
+import static org.robolectric.Shadows.shadowOf;
+
+import android.graphics.drawable.Drawable;
+import android.support.v7.content.res.AppCompatResources;
+
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.RuntimeEnvironment;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+
+/** Tests logic in the ShadowAppCompatResources class. */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE, shadows = {ShadowAppCompatResources.class})
+public class ShadowAppCompatResourcesTest {
+ private static final int DRAWABLE_RES_ID = 34567;
+
+ @Test
+ public void testShadowAppCompatResources() {
+ Drawable drawable =
+ AppCompatResources.getDrawable(RuntimeEnvironment.application, DRAWABLE_RES_ID);
+ assertEquals(DRAWABLE_RES_ID, shadowOf(drawable).getCreatedFromResId());
+ }
+}
diff --git a/chromium/ui/android/junit/src/org/chromium/ui/shadows/ShadowAsyncLayoutInflater.java b/chromium/ui/android/junit/src/org/chromium/ui/shadows/ShadowAsyncLayoutInflater.java
new file mode 100644
index 00000000000..0eb84725327
--- /dev/null
+++ b/chromium/ui/android/junit/src/org/chromium/ui/shadows/ShadowAsyncLayoutInflater.java
@@ -0,0 +1,33 @@
+// 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.
+
+package org.chromium.ui.shadows;
+
+import android.support.annotation.LayoutRes;
+import android.support.annotation.NonNull;
+import android.support.annotation.Nullable;
+import android.support.v4.view.AsyncLayoutInflater;
+import android.view.LayoutInflater;
+import android.view.View;
+import android.view.ViewGroup;
+
+import org.robolectric.annotation.Implementation;
+import org.robolectric.annotation.Implements;
+
+import org.chromium.base.ThreadUtils;
+
+/**
+ * Shadow implementation of AsyncLayoutInflater that inflates on the UI thread then posts the
+ * callback on the UI thread delayed.
+ */
+@Implements(AsyncLayoutInflater.class)
+public class ShadowAsyncLayoutInflater {
+ @Implementation
+ public void inflate(@LayoutRes int resid, @Nullable ViewGroup parent,
+ @NonNull AsyncLayoutInflater.OnInflateFinishedListener callback) {
+ View inflatedView = LayoutInflater.from(parent.getContext()).inflate(resid, parent, false);
+ ThreadUtils.postOnUiThreadDelayed(
+ () -> callback.onInflateFinished(inflatedView, inflatedView.getId(), parent), 500);
+ }
+} \ No newline at end of file
diff --git a/chromium/ui/android/junit/src/org/chromium/ui/text/SpanApplierTest.java b/chromium/ui/android/junit/src/org/chromium/ui/text/SpanApplierTest.java
new file mode 100644
index 00000000000..7b8fc7ace75
--- /dev/null
+++ b/chromium/ui/android/junit/src/org/chromium/ui/text/SpanApplierTest.java
@@ -0,0 +1,179 @@
+// 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.
+
+package org.chromium.ui.text;
+
+import android.text.SpannableString;
+import android.text.style.BulletSpan;
+import android.text.style.QuoteSpan;
+import android.text.style.ScaleXSpan;
+
+import org.junit.Assert;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+import org.chromium.ui.text.SpanApplier.SpanInfo;
+
+/**
+ * Tests public methods in SpanApplier.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public class SpanApplierTest {
+ @Test
+ public void testApplySpan() {
+ String input = "Lorem ipsum <span>dolor</span> sit amet.";
+ String output = "Lorem ipsum dolor sit amet.";
+ SpanInfo span = new SpanInfo("<span>", "</span>", new QuoteSpan());
+
+ SpannableString expectedOutput = new SpannableString(output);
+ expectedOutput.setSpan(span.mSpan, 12, 17, 0);
+ SpannableString actualOutput = SpanApplier.applySpans(input, span);
+
+ assertSpannableStringEquality(expectedOutput, actualOutput);
+ }
+
+ @Test
+ public void testApplyMultipleSpans() {
+ String input = "Lorem <link>ipsum</link> dolor sit amet, "
+ + "<cons>consectetur adipiscing</cons> <elit>elit. Proin<endElit> consectetur.";
+ String output = "Lorem ipsum dolor sit amet, "
+ + "consectetur adipiscing elit. Proin consectetur.";
+ SpanInfo linkSpan = new SpanInfo("<link>", "</link>", new QuoteSpan());
+ SpanInfo consSpan = new SpanInfo("<cons>", "</cons>", new BulletSpan());
+ SpanInfo elitSpan = new SpanInfo("<elit>", "<endElit>", new ScaleXSpan(1));
+
+ SpannableString expectedOutput = new SpannableString(output);
+ expectedOutput.setSpan(linkSpan.mSpan, 6, 11, 0);
+ expectedOutput.setSpan(consSpan.mSpan, 28, 50, 0);
+ expectedOutput.setSpan(elitSpan.mSpan, 51, 62, 0);
+ SpannableString actualOutput = SpanApplier.applySpans(input, elitSpan, consSpan, linkSpan);
+
+ assertSpannableStringEquality(expectedOutput, actualOutput);
+ }
+
+ @Test
+ public void testEndTagMissingInInput() {
+ String input = "Lorem ipsum <span>dolor</> sit amet.";
+ SpanInfo span = new SpanInfo("<span>", "</span>", new QuoteSpan());
+
+ try {
+ SpanApplier.applySpans(input, span);
+ Assert.fail("Expected IllegalArgumentException to be thrown.");
+ } catch (IllegalArgumentException e) {
+ // success
+ }
+ }
+
+ @Test
+ public void testStartTagMissingInInput() {
+ String input = "Lorem ipsum <>dolor</span> sit amet.";
+ SpanInfo span = new SpanInfo("<span>", "</span>", new QuoteSpan());
+
+ try {
+ SpanApplier.applySpans(input, span);
+ Assert.fail("Expected IllegalArgumentException to be thrown.");
+ } catch (IllegalArgumentException e) {
+ // success
+ }
+ }
+
+ @Test
+ public void testNestedTagsInInput() {
+ String input = "Lorem ipsum <span>dolor<span2> sit </span2> </span> amet.";
+ SpanInfo span = new SpanInfo("<span>", "</span>", new QuoteSpan());
+ SpanInfo span2 = new SpanInfo("<span2>", "</span2>", new QuoteSpan());
+
+ try {
+ SpanApplier.applySpans(input, span, span2);
+ Assert.fail("Expected IllegalArgumentException to be thrown.");
+ } catch (IllegalArgumentException e) {
+ // success
+ }
+ }
+
+ @Test
+ public void testDuplicateTagsInInput() {
+ String input = "Lorem ipsum <span>dolor</span> <span>sit </span> amet.";
+ SpanInfo span = new SpanInfo("<span>", "</span>", new QuoteSpan());
+ SpanInfo span2 = new SpanInfo("<span>", "</span>", new QuoteSpan());
+
+ try {
+ SpanApplier.applySpans(input, span, span2);
+ Assert.fail("Expected IllegalArgumentException to be thrown.");
+ } catch (IllegalArgumentException e) {
+ // success
+ }
+ }
+
+ @Test
+ public void testNullSpan() {
+ String input = "Lorem <link>ipsum</link> dolor <span>sit</span> amet.";
+ SpanInfo linkSpan = new SpanInfo("<link>", "</link>", new QuoteSpan());
+ SpanInfo nullSpan = new SpanInfo("<span>", "</span>", null);
+
+ String output = "Lorem ipsum dolor sit amet.";
+ SpannableString expectedOutput = new SpannableString(output);
+ expectedOutput.setSpan(linkSpan.mSpan, 6, 11, 0);
+ SpannableString actualOutput = SpanApplier.applySpans(input, linkSpan, nullSpan);
+
+ assertSpannableStringEquality(expectedOutput, actualOutput);
+ }
+
+ /*
+ * Tests the attributes of two SpannableStrings and asserts expected equality.
+ *
+ * Prior to KitKat, there was no equals method for SpannableString, so we have to
+ * manually check that the objects are the same.
+ */
+ private void assertSpannableStringEquality(
+ SpannableString expected, SpannableString actual) {
+ if (!areSpannableStringsEqual(expected, actual)) {
+ Assert.fail("Expected string is " + getSpannableStringDescription(expected)
+ + " Actual string is " + getSpannableStringDescription(actual));
+ }
+ }
+
+ private boolean areSpannableStringsEqual(SpannableString expected, SpannableString actual) {
+ Object[] expectedSpans = expected.getSpans(0, expected.length(), Object.class);
+ Object[] actualSpans = actual.getSpans(0, actual.length(), Object.class);
+
+ if (!expected.toString().equals(actual.toString())
+ || expectedSpans.length != actualSpans.length) {
+ return false;
+ }
+
+ for (int i = 0; i < expectedSpans.length; i++) {
+ Object expectedSpan = expectedSpans[i];
+ Object actualSpan = actualSpans[i];
+ if (expectedSpan != actualSpan
+ || expected.getSpanStart(expectedSpan) != actual.getSpanStart(actualSpan)
+ || expected.getSpanEnd(expectedSpan) != actual.getSpanEnd(actualSpan)) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ private String getSpannableStringDescription(SpannableString spannableString) {
+ Object[] spans = spannableString.getSpans(0, spannableString.length(), Object.class);
+ StringBuilder description = new StringBuilder();
+ description.append("\"" + spannableString + "\"" + " with spans: ");
+ for (int i = 0; i < spans.length; i++) {
+ Object span = spans[i];
+ description.append(span.getClass().getName()
+ + " from " + spannableString.getSpanStart(span)
+ + " to " + spannableString.getSpanEnd(span));
+ if (i != spans.length - 1) {
+ description.append(", ");
+ }
+ }
+
+ description.append('.');
+ return description.toString();
+ }
+}
diff --git a/chromium/ui/android/junit/src/org/chromium/ui/widget/AnchoredPopupWindowTest.java b/chromium/ui/android/junit/src/org/chromium/ui/widget/AnchoredPopupWindowTest.java
new file mode 100644
index 00000000000..ce165e48bb9
--- /dev/null
+++ b/chromium/ui/android/junit/src/org/chromium/ui/widget/AnchoredPopupWindowTest.java
@@ -0,0 +1,202 @@
+// 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.
+
+package org.chromium.ui.widget;
+
+import static org.junit.Assert.assertEquals;
+import static org.junit.Assert.assertFalse;
+import static org.junit.Assert.assertTrue;
+
+import android.graphics.Rect;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.robolectric.annotation.Config;
+
+import org.chromium.base.test.BaseRobolectricTestRunner;
+
+/**
+ * Unit tests for the static positioning methods in {@link AnchoredPopupWindow}.
+ */
+@RunWith(BaseRobolectricTestRunner.class)
+@Config(manifest = Config.NONE)
+public final class AnchoredPopupWindowTest {
+ private Rect mWindowRect;
+ int mPopupWidth;
+ int mPopupHeight;
+
+ @Before
+ public void setUp() {
+ mWindowRect = new Rect(0, 0, 600, 1000);
+ mPopupWidth = 150;
+ mPopupHeight = 300;
+ }
+
+ @Test
+ public void testGetPopupPosition_BelowRight() {
+ Rect anchorRect = new Rect(10, 10, 20, 20);
+
+ int spaceLeftOfAnchor =
+ AnchoredPopupWindow.getSpaceLeftOfAnchor(anchorRect, mWindowRect, false);
+ int spaceRightOfAnchor =
+ AnchoredPopupWindow.getSpaceRightOfAnchor(anchorRect, mWindowRect, false);
+ boolean positionToLeft = AnchoredPopupWindow.shouldPositionLeftOfAnchor(
+ spaceLeftOfAnchor, spaceRightOfAnchor, mPopupWidth, false, false);
+
+ assertEquals("Space left of anchor incorrect.", 10, spaceLeftOfAnchor);
+ assertEquals("Space right of anchor incorrect.", 580, spaceRightOfAnchor);
+ assertFalse("positionToLeft incorrect.", positionToLeft);
+
+ int x = AnchoredPopupWindow.getPopupX(anchorRect, mWindowRect, mPopupWidth, 0, false,
+ AnchoredPopupWindow.HORIZONTAL_ORIENTATION_MAX_AVAILABLE_SPACE, false);
+ int y = AnchoredPopupWindow.getPopupY(anchorRect, mPopupHeight, false, true);
+
+ assertEquals("Wrong x position.", 20, x);
+ assertEquals("Wrong y position.", 20, y);
+ }
+
+ @Test
+ public void testGetPopupPosition_BelowRight_Overlap() {
+ Rect anchorRect = new Rect(10, 10, 20, 20);
+
+ int spaceLeftOfAnchor =
+ AnchoredPopupWindow.getSpaceLeftOfAnchor(anchorRect, mWindowRect, true);
+ int spaceRightOfAnchor =
+ AnchoredPopupWindow.getSpaceRightOfAnchor(anchorRect, mWindowRect, true);
+ boolean positionToLeft = AnchoredPopupWindow.shouldPositionLeftOfAnchor(
+ spaceLeftOfAnchor, spaceRightOfAnchor, mPopupWidth, false, false);
+
+ assertEquals("Space left of anchor incorrect.", 20, spaceLeftOfAnchor);
+ assertEquals("Space right of anchor incorrect.", 590, spaceRightOfAnchor);
+ assertFalse("positionToLeft incorrect.", positionToLeft);
+
+ int x = AnchoredPopupWindow.getPopupX(anchorRect, mWindowRect, mPopupWidth, 0, true,
+ AnchoredPopupWindow.HORIZONTAL_ORIENTATION_MAX_AVAILABLE_SPACE, false);
+ int y = AnchoredPopupWindow.getPopupY(anchorRect, mPopupHeight, true, true);
+
+ assertEquals("Wrong x position.", 10, x);
+ assertEquals("Wrong y position.", 10, y);
+ }
+
+ @Test
+ public void testGetPopupPosition_BelowCenter() {
+ Rect anchorRect = new Rect(295, 10, 305, 20);
+ int x = AnchoredPopupWindow.getPopupX(anchorRect, mWindowRect, mPopupWidth, 0, false,
+ AnchoredPopupWindow.HORIZONTAL_ORIENTATION_CENTER, false);
+ int y = AnchoredPopupWindow.getPopupY(anchorRect, mPopupHeight, false, true);
+
+ assertEquals("Wrong x position.", 225, x);
+ assertEquals("Wrong y position.", 20, y);
+ }
+
+ @Test
+ public void getPopupPosition_AboveLeft() {
+ Rect anchorRect = new Rect(400, 800, 410, 820);
+
+ int spaceLeftOfAnchor =
+ AnchoredPopupWindow.getSpaceLeftOfAnchor(anchorRect, mWindowRect, false);
+ int spaceRightOfAnchor =
+ AnchoredPopupWindow.getSpaceRightOfAnchor(anchorRect, mWindowRect, false);
+ boolean positionToLeft = AnchoredPopupWindow.shouldPositionLeftOfAnchor(
+ spaceLeftOfAnchor, spaceRightOfAnchor, mPopupWidth, false, false);
+
+ assertEquals("Space left of anchor incorrect.", 400, spaceLeftOfAnchor);
+ assertEquals("Space right of anchor incorrect.", 190, spaceRightOfAnchor);
+ assertTrue("positionToLeft incorrect.", positionToLeft);
+
+ int x = AnchoredPopupWindow.getPopupX(anchorRect, mWindowRect, mPopupWidth, 0, false,
+ AnchoredPopupWindow.HORIZONTAL_ORIENTATION_MAX_AVAILABLE_SPACE, positionToLeft);
+ int y = AnchoredPopupWindow.getPopupY(anchorRect, mPopupHeight, false, false);
+
+ assertEquals("Wrong x position.", 250, x);
+ assertEquals("Wrong y position.", 500, y);
+ }
+
+ @Test
+ public void testGetPopupPosition_AboveLeft_Overlap() {
+ Rect anchorRect = new Rect(400, 800, 410, 820);
+
+ int spaceLeftOfAnchor =
+ AnchoredPopupWindow.getSpaceLeftOfAnchor(anchorRect, mWindowRect, true);
+ int spaceRightOfAnchor =
+ AnchoredPopupWindow.getSpaceRightOfAnchor(anchorRect, mWindowRect, true);
+ boolean positionToLeft = AnchoredPopupWindow.shouldPositionLeftOfAnchor(
+ spaceLeftOfAnchor, spaceRightOfAnchor, mPopupWidth, false, false);
+
+ assertEquals("Space left of anchor incorrect.", 410, spaceLeftOfAnchor);
+ assertEquals("Space right of anchor incorrect.", 200, spaceRightOfAnchor);
+ assertTrue("positionToLeft incorrect.", positionToLeft);
+
+ int x = AnchoredPopupWindow.getPopupX(anchorRect, mWindowRect, mPopupWidth, 0, true,
+ AnchoredPopupWindow.HORIZONTAL_ORIENTATION_MAX_AVAILABLE_SPACE, true);
+ int y = AnchoredPopupWindow.getPopupY(anchorRect, mPopupHeight, true, false);
+
+ assertEquals("Wrong x position.", 260, x);
+ assertEquals("Wrong y position.", 520, y);
+ }
+
+ @Test
+ public void testGetPopupPosition_ClampedLeftEdge() {
+ Rect anchorRect = new Rect(10, 10, 20, 20);
+ int x = AnchoredPopupWindow.getPopupX(anchorRect, mWindowRect, mPopupWidth, 20, false,
+ AnchoredPopupWindow.HORIZONTAL_ORIENTATION_MAX_AVAILABLE_SPACE, true);
+
+ assertEquals("Wrong x position.", 20, x);
+ }
+
+ @Test
+ public void testGetPopupPosition_ClampedRightEdge() {
+ Rect anchorRect = new Rect(590, 800, 600, 820);
+ int x = AnchoredPopupWindow.getPopupX(anchorRect, mWindowRect, mPopupWidth, 20, false,
+ AnchoredPopupWindow.HORIZONTAL_ORIENTATION_MAX_AVAILABLE_SPACE, true);
+
+ assertEquals("Wrong x position.", 430, x);
+ }
+
+ @Test
+ public void testShouldPositionLeftOfAnchor() {
+ Rect anchorRect = new Rect(300, 10, 310, 20);
+ int spaceLeftOfAnchor =
+ AnchoredPopupWindow.getSpaceLeftOfAnchor(anchorRect, mWindowRect, false);
+ int spaceRightOfAnchor =
+ AnchoredPopupWindow.getSpaceRightOfAnchor(anchorRect, mWindowRect, false);
+ boolean positionToLeft = AnchoredPopupWindow.shouldPositionLeftOfAnchor(
+ spaceLeftOfAnchor, spaceRightOfAnchor, mPopupWidth, false, false);
+
+ assertEquals("Space left of anchor incorrect.", 300, spaceLeftOfAnchor);
+ assertEquals("Space right of anchor incorrect.", 290, spaceRightOfAnchor);
+ assertTrue("Should be positioned to the left.", positionToLeft);
+
+ anchorRect = new Rect(250, 10, 260, 20);
+ spaceLeftOfAnchor =
+ AnchoredPopupWindow.getSpaceLeftOfAnchor(anchorRect, mWindowRect, false);
+ spaceRightOfAnchor =
+ AnchoredPopupWindow.getSpaceRightOfAnchor(anchorRect, mWindowRect, false);
+ positionToLeft = AnchoredPopupWindow.shouldPositionLeftOfAnchor(
+ spaceLeftOfAnchor, spaceRightOfAnchor, mPopupWidth, true, true);
+
+ // There is more space to the right, but the popup will still fit to the left and should
+ // be positioned to the left.
+ assertEquals("Space left of anchor incorrect.", 250, spaceLeftOfAnchor);
+ assertEquals("Space right of anchor incorrect.", 340, spaceRightOfAnchor);
+ assertTrue("Should still be positioned to the left.", positionToLeft);
+ }
+
+ @Test
+ public void testGetMaxContentWidth() {
+ int maxWidth = AnchoredPopupWindow.getMaxContentWidth(300, 600, 10, 10);
+ assertEquals("Max width should be based on desired width.", 290, maxWidth);
+
+ maxWidth = AnchoredPopupWindow.getMaxContentWidth(300, 300, 10, 10);
+ assertEquals("Max width should be based on root view width.", 270, maxWidth);
+
+ maxWidth = AnchoredPopupWindow.getMaxContentWidth(0, 600, 10, 10);
+ assertEquals("Max width should be based on root view width when desired with is 0.", 570,
+ maxWidth);
+
+ maxWidth = AnchoredPopupWindow.getMaxContentWidth(300, 300, 10, 300);
+ assertEquals("Max width should be clamped at 0.", 0, maxWidth);
+ }
+}
diff --git a/chromium/ui/aura/BUILD.gn b/chromium/ui/aura/BUILD.gn
index c97d5dda9cf..cba785ad544 100644
--- a/chromium/ui/aura/BUILD.gn
+++ b/chromium/ui/aura/BUILD.gn
@@ -47,6 +47,7 @@ jumbo_component("aura") {
"mus/focus_synchronizer.h",
"mus/focus_synchronizer_delegate.h",
"mus/focus_synchronizer_observer.h",
+ "mus/gesture_synchronizer.h",
"mus/in_flight_change.h",
"mus/input_method_mus.h",
"mus/input_method_mus_delegate.h",
@@ -118,6 +119,7 @@ jumbo_component("aura") {
"mus/drag_drop_controller_mus.cc",
"mus/embed_root.cc",
"mus/focus_synchronizer.cc",
+ "mus/gesture_synchronizer.cc",
"mus/in_flight_change.cc",
"mus/input_method_mus.cc",
"mus/mus_context_factory.cc",
@@ -250,6 +252,8 @@ jumbo_static_library("test_support") {
"test/mus/test_window_tree_client_delegate.h",
"test/mus/test_window_tree_client_setup.cc",
"test/mus/test_window_tree_client_setup.h",
+ "test/mus/window_port_mus_test_helper.cc",
+ "test/mus/window_port_mus_test_helper.h",
"test/mus/window_tree_client_private.cc",
"test/mus/window_tree_client_private.h",
"test/test_cursor_client.cc",
@@ -370,6 +374,7 @@ test("aura_unittests") {
"mouse_location_manager_unittest.cc",
"mus/drag_drop_controller_mus_unittest.cc",
"mus/focus_synchronizer_unittest.cc",
+ "mus/gesture_synchronizer_unittest.cc",
"mus/input_method_mus_unittest.cc",
"mus/os_exchange_data_provider_mus_unittest.cc",
"mus/property_converter_unittest.cc",
diff --git a/chromium/ui/aura/client/aura_constants.cc b/chromium/ui/aura/client/aura_constants.cc
index c0b3bf9c200..1ed7c6e50d9 100644
--- a/chromium/ui/aura/client/aura_constants.cc
+++ b/chromium/ui/aura/client/aura_constants.cc
@@ -24,8 +24,6 @@ DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, void*)
DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, SkColor)
DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, int32_t)
DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, int64_t)
-DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT,
- aura::client::WindowEmbedType)
DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, aura::client::FocusClient*)
DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, aura::Window*)
@@ -54,9 +52,6 @@ DEFINE_UI_CLASS_PROPERTY_KEY(Window*, kHostWindowKey, nullptr);
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kImmersiveFullscreenKey, false);
DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::Size, kMinimumSize, nullptr);
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kMirroringEnabledKey, false);
-DEFINE_UI_CLASS_PROPERTY_KEY(WindowEmbedType,
- kEmbedType,
- WindowEmbedType::NONE);
DEFINE_UI_CLASS_PROPERTY_KEY(Window*, kChildModalParentKey, nullptr);
DEFINE_UI_CLASS_PROPERTY_KEY(ui::ModalType, kModalKey, ui::MODAL_TYPE_NONE);
DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(std::string, kNameKey, nullptr);
@@ -68,6 +63,7 @@ DEFINE_UI_CLASS_PROPERTY_KEY(
DEFINE_UI_CLASS_PROPERTY_KEY(int32_t,
kResizeBehaviorKey,
ws::mojom::kResizeBehaviorCanResize);
+DEFINE_UI_CLASS_PROPERTY_KEY(int, kResizeHandleInset, 0);
DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::Rect, kRestoreBoundsKey, nullptr);
DEFINE_UI_CLASS_PROPERTY_KEY(
ui::WindowShowState, kShowStateKey, ui::SHOW_STATE_DEFAULT);
diff --git a/chromium/ui/aura/client/aura_constants.h b/chromium/ui/aura/client/aura_constants.h
index a184412827a..65dc33a5477 100644
--- a/chromium/ui/aura/client/aura_constants.h
+++ b/chromium/ui/aura/client/aura_constants.h
@@ -23,11 +23,6 @@ namespace aura {
namespace client {
class FocusClient;
-enum class WindowEmbedType {
- NONE,
- EMBED_IN_OWNER,
-};
-
// Alphabetical sort.
// A property key to store whether accessibility focus falls back to widget or
@@ -124,6 +119,12 @@ AURA_EXPORT extern const WindowProperty<ui::WindowShowState>* const
// ws::mojom::kResizeBehavior values.
AURA_EXPORT extern const WindowProperty<int32_t>* const kResizeBehaviorKey;
+// Reserves a number of dip around the window (i.e. inset from its exterior
+// border) for event routing back to the top level window. This is used for
+// routing events to toplevel window resize handles. It should only be respected
+// for restored windows (maximized and fullscreen can't be drag-resized).
+AURA_EXPORT extern const WindowProperty<int>* const kResizeHandleInset;
+
// A property key to store the restore bounds in screen coordinates for a
// window.
AURA_EXPORT extern const WindowProperty<gfx::Rect*>* const kRestoreBoundsKey;
@@ -149,9 +150,6 @@ AURA_EXPORT extern const WindowProperty<int>* const kTopViewInset;
// A property key to store the window icon, typically 16x16 for title bars.
AURA_EXPORT extern const WindowProperty<gfx::ImageSkia*>* const kWindowIconKey;
-// Indicates the type of embedding within the given window.
-AURA_EXPORT extern const WindowProperty<WindowEmbedType>* const kEmbedType;
-
// The corner radius of a window in DIPs. Currently only used for shadows.
// Default is -1, meaning "unspecified". 0 Ensures corners are square.
AURA_EXPORT extern const WindowProperty<int>* const kWindowCornerRadiusKey;
diff --git a/chromium/ui/aura/env.cc b/chromium/ui/aura/env.cc
index 07ff6f5bf18..bbd91404c0f 100644
--- a/chromium/ui/aura/env.cc
+++ b/chromium/ui/aura/env.cc
@@ -6,6 +6,7 @@
#include "base/command_line.h"
#include "base/lazy_instance.h"
+#include "base/memory/ptr_util.h"
#include "services/ws/public/mojom/window_tree.mojom.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/env_input_state_controller.h"
@@ -20,6 +21,7 @@
#include "ui/aura/mus/window_tree_client.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher_observer.h"
+#include "ui/aura/window_occlusion_tracker.h"
#include "ui/aura/window_port_for_shutdown.h"
#include "ui/base/ui_base_features.h"
#include "ui/events/event_target_iterator.h"
@@ -113,19 +115,8 @@ std::unique_ptr<WindowPort> Env::CreateWindowPort(Window* window) {
return std::make_unique<WindowPortForShutdown>();
DCHECK(window_tree_client_);
- WindowMusType window_mus_type;
- switch (window->GetProperty(aura::client::kEmbedType)) {
- case aura::client::WindowEmbedType::NONE:
- window_mus_type = WindowMusType::LOCAL;
- break;
- case aura::client::WindowEmbedType::EMBED_IN_OWNER:
- window_mus_type = WindowMusType::EMBED_IN_OWNER;
- break;
- default:
- NOTREACHED();
- }
- // Use LOCAL as all other cases are created by WindowTreeClient explicitly.
- return std::make_unique<WindowPortMus>(window_tree_client_, window_mus_type);
+ return std::make_unique<WindowPortMus>(window_tree_client_,
+ WindowMusType::LOCAL);
}
void Env::AddObserver(EnvObserver* observer) {
@@ -196,6 +187,17 @@ void Env::ScheduleEmbed(
window_tree_client_->ScheduleEmbed(std::move(client), std::move(callback));
}
+WindowOcclusionTracker* Env::GetWindowOcclusionTracker() {
+ // TODO(https://crbug.com/867150): DCHECK to ensure LOCAL aura after mus
+ // code path is wired up.
+ if (!window_occlusion_tracker_) {
+ // Use base::WrapUnique + new because of the constructor is private.
+ window_occlusion_tracker_ = base::WrapUnique(new WindowOcclusionTracker());
+ }
+
+ return window_occlusion_tracker_.get();
+}
+
////////////////////////////////////////////////////////////////////////////////
// Env, private:
diff --git a/chromium/ui/aura/env.h b/chromium/ui/aura/env.h
index f8fb629389f..3738281bedd 100644
--- a/chromium/ui/aura/env.h
+++ b/chromium/ui/aura/env.h
@@ -59,6 +59,7 @@ class MouseLocationManager;
class MusMouseLocationUpdater;
class Window;
class WindowEventDispatcherObserver;
+class WindowOcclusionTracker;
class WindowPort;
class WindowTreeClient;
class WindowTreeHost;
@@ -191,6 +192,9 @@ class AURA_EXPORT Env : public ui::EventTarget,
mojo::InterfacePtr<ws::mojom::WindowTreeClient> client,
base::OnceCallback<void(const base::UnguessableToken&)> callback);
+ // Get WindowOcclusionTracker instance. Create it if it is not yet created.
+ WindowOcclusionTracker* GetWindowOcclusionTracker();
+
private:
friend class test::EnvTestHelper;
friend class test::EnvWindowTreeClientSetter;
@@ -285,6 +289,9 @@ class AURA_EXPORT Env : public ui::EventTarget,
// Only created if CreateMouseLocationManager() was called.
std::unique_ptr<MouseLocationManager> mouse_location_manager_;
+ // Lazily created for LOCAL aura.
+ std::unique_ptr<WindowOcclusionTracker> window_occlusion_tracker_;
+
DISALLOW_COPY_AND_ASSIGN(Env);
};
diff --git a/chromium/ui/aura/event_injector.cc b/chromium/ui/aura/event_injector.cc
index fd2a7423c05..f67d1fe5721 100644
--- a/chromium/ui/aura/event_injector.cc
+++ b/chromium/ui/aura/event_injector.cc
@@ -13,24 +13,6 @@
#include "ui/events/event.h"
#include "ui/events/event_sink.h"
-namespace {
-std::unique_ptr<ui::Event> MapEvent(const ui::Event& event) {
- if (event.IsScrollEvent()) {
- return std::make_unique<ui::PointerEvent>(
- ui::MouseWheelEvent(*event.AsScrollEvent()));
- }
-
- if (event.IsMouseEvent())
- return std::make_unique<ui::PointerEvent>(*event.AsMouseEvent());
-
- if (event.IsTouchEvent())
- return std::make_unique<ui::PointerEvent>(*event.AsTouchEvent());
-
- return ui::Event::Clone(event);
-}
-
-} // namespace
-
namespace aura {
EventInjector::EventInjector() {}
@@ -60,7 +42,8 @@ ui::EventDispatchDetails EventInjector::Inject(WindowTreeHost* host,
env->window_tree_client_->connector()->BindInterface(
ws::mojom::kServiceName, &event_injector_);
}
- event_injector_->InjectEventNoAck(host->GetDisplayId(), MapEvent(*event));
+ event_injector_->InjectEventNoAck(host->GetDisplayId(),
+ ui::Event::Clone(*event));
return ui::EventDispatchDetails();
}
diff --git a/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc b/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc
index 86b08db290d..ee72e003826 100644
--- a/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc
+++ b/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc
@@ -4705,8 +4705,7 @@ TEST_F(GestureRecognizerTest, TransferEventsToRoutesAckCorrectly) {
// Transfer event sequence from previous window to the new window.
aura::Env::GetInstance()->gesture_recognizer()->TransferEventsTo(
- window_1.get(), window_2.get(),
- ui::GestureRecognizer::ShouldCancelTouches::DontCancel);
+ window_1.get(), window_2.get(), ui::TransferTouchesBehavior::kDontCancel);
delegate_1->Reset();
delegate_1->ReceivedAck();
diff --git a/chromium/ui/aura/hit_test_data_provider_aura_unittest.cc b/chromium/ui/aura/hit_test_data_provider_aura_unittest.cc
index b120625ed1a..79f73481cad 100644
--- a/chromium/ui/aura/hit_test_data_provider_aura_unittest.cc
+++ b/chromium/ui/aura/hit_test_data_provider_aura_unittest.cc
@@ -8,6 +8,7 @@
#include "components/viz/common/hit_test/hit_test_region_list.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/test/aura_test_base.h"
+#include "ui/aura/test/mus/window_port_mus_test_helper.h"
#include "ui/aura/window.h"
#include "ui/aura/window_targeter.h"
#include "ui/gfx/geometry/rect.h"
@@ -28,15 +29,15 @@ namespace {
// | ---------- |
// | hit hit |
// ----------------------
-class TestHoleWindowTargeter : public aura::WindowTargeter {
+class TestHoleWindowTargeter : public WindowTargeter {
public:
TestHoleWindowTargeter() = default;
~TestHoleWindowTargeter() override {}
private:
- // aura::WindowTargeter:
- std::unique_ptr<aura::WindowTargeter::HitTestRects> GetExtraHitTestShapeRects(
- aura::Window* target) const override {
+ // WindowTargeter:
+ std::unique_ptr<WindowTargeter::HitTestRects> GetExtraHitTestShapeRects(
+ Window* target) const override {
gfx::Rect bounds = target->bounds();
int x0 = 0;
int x1 = bounds.width() / 3;
@@ -46,7 +47,7 @@ class TestHoleWindowTargeter : public aura::WindowTargeter {
int y1 = bounds.height() / 3;
int y2 = bounds.height() - bounds.height() / 3;
int y3 = bounds.height();
- auto shape_rects = std::make_unique<aura::WindowTargeter::HitTestRects>();
+ auto shape_rects = std::make_unique<WindowTargeter::HitTestRects>();
shape_rects->emplace_back(x0, y0, bounds.width(), y1 - y0);
shape_rects->emplace_back(x0, y1, x1 - x0, y2 - y1);
shape_rects->emplace_back(x2, y1, x3 - x2, y2 - y1);
@@ -73,23 +74,17 @@ class HitTestDataProviderAuraTest : public test::AuraTestBaseMus {
test::AuraTestBaseMus::SetUp();
root_ = std::make_unique<Window>(nullptr);
- root_->SetProperty(aura::client::kEmbedType,
- aura::client::WindowEmbedType::EMBED_IN_OWNER);
root_->Init(ui::LAYER_NOT_DRAWN);
root_->SetEventTargeter(std::make_unique<WindowTargeter>());
root_->SetBounds(gfx::Rect(0, 0, 300, 200));
root_->Show();
window2_ = new Window(nullptr);
- window2_->SetProperty(aura::client::kEmbedType,
- aura::client::WindowEmbedType::EMBED_IN_OWNER);
window2_->Init(ui::LAYER_TEXTURED);
window2_->SetBounds(gfx::Rect(20, 30, 40, 60));
window2_->Show();
window3_ = new Window(nullptr);
- window3_->SetProperty(aura::client::kEmbedType,
- aura::client::WindowEmbedType::EMBED_IN_OWNER);
window3_->Init(ui::LAYER_TEXTURED);
window3_->SetEventTargeter(std::make_unique<WindowTargeter>());
window3_->SetBounds(gfx::Rect(50, 60, 100, 40));
@@ -175,10 +170,14 @@ TEST_F(HitTestDataProviderAuraTest, Stacking) {
TEST_F(HitTestDataProviderAuraTest, CustomTargeter) {
constexpr int kMouseInset = -5;
constexpr int kTouchInset = -10;
- auto targeter = std::make_unique<aura::WindowTargeter>();
+ auto targeter = std::make_unique<WindowTargeter>();
targeter->SetInsets(gfx::Insets(kMouseInset), gfx::Insets(kTouchInset));
window3()->SetEventTargeter(std::move(targeter));
+ targeter = std::make_unique<WindowTargeter>();
+ targeter->SetInsets(gfx::Insets(kMouseInset), gfx::Insets(kTouchInset));
+ window4()->SetEventTargeter(std::move(targeter));
+
window2()->SetEmbedFrameSinkId(viz::FrameSinkId(1, 2));
const base::Optional<viz::HitTestRegionList> hit_test_data =
hit_test_data_provider()->GetHitTestData(compositor_frame_);
diff --git a/chromium/ui/aura/local/window_port_local.cc b/chromium/ui/aura/local/window_port_local.cc
index 56c7db037cc..454a3dea5b2 100644
--- a/chromium/ui/aura/local/window_port_local.cc
+++ b/chromium/ui/aura/local/window_port_local.cc
@@ -9,6 +9,7 @@
#include "components/viz/client/local_surface_id_provider.h"
#include "components/viz/common/features.h"
#include "components/viz/host/host_frame_sink_manager.h"
+#include "services/ws/public/mojom/window_tree_constants.mojom.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/env.h"
#include "ui/aura/hit_test_data_provider_aura.h"
@@ -19,7 +20,9 @@
#include "ui/display/screen.h"
namespace aura {
+
namespace {
+static const char* kExo = "Exo";
class ScopedCursorHider {
public:
@@ -63,7 +66,9 @@ class ScopedCursorHider {
} // namespace
WindowPortLocal::WindowPortLocal(Window* window)
- : window_(window), weak_factory_(this) {}
+ : WindowPort(WindowPort::Type::kLocal),
+ window_(window),
+ weak_factory_(this) {}
WindowPortLocal::~WindowPortLocal() {
if (frame_sink_id_.is_valid()) {
@@ -156,10 +161,16 @@ WindowPortLocal::CreateLayerTreeFrameSink() {
params.pipes.compositor_frame_sink_info = std::move(sink_info);
params.pipes.client_request = std::move(client_request);
params.enable_surface_synchronization = true;
+ params.client_name = kExo;
if (features::IsVizHitTestingDrawQuadEnabled()) {
+ bool root_accepts_events =
+ (window_->event_targeting_policy() ==
+ ws::mojom::EventTargetingPolicy::TARGET_ONLY) ||
+ (window_->event_targeting_policy() ==
+ ws::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS);
params.hit_test_data_provider =
std::make_unique<viz::HitTestDataProviderDrawQuad>(
- true /* should_ask_for_child_region */);
+ true /* should_ask_for_child_region */, root_accepts_events);
} else {
params.hit_test_data_provider =
std::make_unique<HitTestDataProviderAura>(window_);
diff --git a/chromium/ui/aura/mus/client_surface_embedder.cc b/chromium/ui/aura/mus/client_surface_embedder.cc
index 21913636c50..340eef15b1f 100644
--- a/chromium/ui/aura/mus/client_surface_embedder.cc
+++ b/chromium/ui/aura/mus/client_surface_embedder.cc
@@ -43,6 +43,10 @@ void ClientSurfaceEmbedder::SetPrimarySurfaceId(
false /* stretch_content_to_fill_bounds */);
}
+bool ClientSurfaceEmbedder::HasPrimarySurfaceId() const {
+ return surface_layer_owner_->layer()->GetPrimarySurfaceId() != nullptr;
+}
+
void ClientSurfaceEmbedder::SetFallbackSurfaceInfo(
const viz::SurfaceInfo& surface_info) {
fallback_surface_info_ = surface_info;
@@ -50,6 +54,16 @@ void ClientSurfaceEmbedder::SetFallbackSurfaceInfo(
UpdateSizeAndGutters();
}
+void ClientSurfaceEmbedder::SetClientAreaInsets(
+ const gfx::Insets& client_area_insets) {
+ if (client_area_insets_ == client_area_insets)
+ return;
+
+ client_area_insets_ = client_area_insets;
+ if (inject_gutter_)
+ UpdateSizeAndGutters();
+}
+
void ClientSurfaceEmbedder::UpdateSizeAndGutters() {
surface_layer_owner_->layer()->SetBounds(gfx::Rect(window_->bounds().size()));
if (!inject_gutter_)
diff --git a/chromium/ui/aura/mus/client_surface_embedder.h b/chromium/ui/aura/mus/client_surface_embedder.h
index cec86d00c37..bcf1ce1bace 100644
--- a/chromium/ui/aura/mus/client_surface_embedder.h
+++ b/chromium/ui/aura/mus/client_surface_embedder.h
@@ -37,10 +37,15 @@ class AURA_EXPORT ClientSurfaceEmbedder {
// on the provided |surface_id|.
void SetPrimarySurfaceId(const viz::SurfaceId& surface_id);
+ bool HasPrimarySurfaceId() const;
+
// Sets the fallback SurfaceInfo of the surface layer. The clip layer is not
// updated.
void SetFallbackSurfaceInfo(const viz::SurfaceInfo& surface_info);
+ void SetClientAreaInsets(const gfx::Insets& client_area_insets);
+ const gfx::Insets& client_area_insets() const { return client_area_insets_; }
+
// Update the surface layer size and the right and bottom gutter layers for
// the current window size.
void UpdateSizeAndGutters();
diff --git a/chromium/ui/aura/mus/embed_root.cc b/chromium/ui/aura/mus/embed_root.cc
index 372988eaa30..32fa6b55747 100644
--- a/chromium/ui/aura/mus/embed_root.cc
+++ b/chromium/ui/aura/mus/embed_root.cc
@@ -123,6 +123,7 @@ void EmbedRoot::OnEmbed(std::unique_ptr<WindowTreeHost> window_tree_host) {
focus_client_ =
std::make_unique<EmbeddedFocusClient>(window_tree_host->window());
window_tree_host_ = std::move(window_tree_host);
+ window_tree_host_->Show();
delegate_->OnEmbed(window());
}
diff --git a/chromium/ui/aura/mus/gesture_synchronizer.cc b/chromium/ui/aura/mus/gesture_synchronizer.cc
new file mode 100644
index 00000000000..ce216f54f35
--- /dev/null
+++ b/chromium/ui/aura/mus/gesture_synchronizer.cc
@@ -0,0 +1,55 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/aura/mus/gesture_synchronizer.h"
+
+#include "services/ws/public/mojom/window_tree.mojom.h"
+#include "ui/aura/env.h"
+#include "ui/aura/mus/window_mus.h"
+#include "ui/aura/window.h"
+#include "ui/events/gestures/gesture_recognizer.h"
+
+namespace aura {
+
+GestureSynchronizer::GestureSynchronizer(ws::mojom::WindowTree* window_tree)
+ : window_tree_(window_tree) {
+ Env::GetInstance()->gesture_recognizer()->AddObserver(this);
+}
+
+GestureSynchronizer::~GestureSynchronizer() {
+ Env::GetInstance()->gesture_recognizer()->RemoveObserver(this);
+}
+
+void GestureSynchronizer::OnActiveTouchesCanceledExcept(
+ ui::GestureConsumer* not_cancelled) {
+ ws::Id not_cancelled_window_id = kInvalidServerId;
+ if (not_cancelled) {
+ WindowMus* not_cancelled_window =
+ WindowMus::Get(static_cast<Window*>(not_cancelled));
+ not_cancelled_window_id = not_cancelled_window->server_id();
+ }
+ window_tree_->CancelActiveTouchesExcept(not_cancelled_window_id);
+}
+
+void GestureSynchronizer::OnEventsTransferred(
+ ui::GestureConsumer* current_consumer,
+ ui::GestureConsumer* new_consumer,
+ ui::TransferTouchesBehavior transfer_touches_behavior) {
+ WindowMus* current_window =
+ WindowMus::Get(static_cast<Window*>(current_consumer));
+ WindowMus* new_window = WindowMus::Get(static_cast<Window*>(new_consumer));
+ DCHECK(current_window);
+ DCHECK(new_window);
+ window_tree_->TransferGestureEventsTo(
+ current_window->server_id(), new_window->server_id(),
+ transfer_touches_behavior == ui::TransferTouchesBehavior::kCancel);
+}
+
+void GestureSynchronizer::OnActiveTouchesCanceled(
+ ui::GestureConsumer* consumer) {
+ WindowMus* window = WindowMus::Get(static_cast<Window*>(consumer));
+ window_tree_->CancelActiveTouches(window->server_id());
+}
+
+} // namespace aura
diff --git a/chromium/ui/aura/mus/gesture_synchronizer.h b/chromium/ui/aura/mus/gesture_synchronizer.h
new file mode 100644
index 00000000000..66ab563d33f
--- /dev/null
+++ b/chromium/ui/aura/mus/gesture_synchronizer.h
@@ -0,0 +1,45 @@
+// 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_AURA_MUS_GESTURE_SYNCHRONIZER_H_
+#define UI_AURA_MUS_GESTURE_SYNCHRONIZER_H_
+
+#include "base/macros.h"
+#include "ui/events/gestures/gesture_recognizer_observer.h"
+
+namespace ws {
+namespace mojom {
+
+class WindowTree;
+
+} // namespace mojom
+} // namespace ws
+
+namespace aura {
+
+// GestureSynchronizer is responsible for keeping GestureRecognizer's state
+// synchronized between aura and the mus server.
+class GestureSynchronizer : public ui::GestureRecognizerObserver {
+ public:
+ explicit GestureSynchronizer(ws::mojom::WindowTree* window_tree);
+ ~GestureSynchronizer() override;
+
+ private:
+ // ui::GestureRecognizerObserver:
+ void OnActiveTouchesCanceledExcept(
+ ui::GestureConsumer* not_cancelled) override;
+ void OnEventsTransferred(
+ ui::GestureConsumer* current_consumer,
+ ui::GestureConsumer* new_consumer,
+ ui::TransferTouchesBehavior transfer_touches_behavior) override;
+ void OnActiveTouchesCanceled(ui::GestureConsumer* consumer) override;
+
+ ws::mojom::WindowTree* window_tree_;
+
+ DISALLOW_COPY_AND_ASSIGN(GestureSynchronizer);
+};
+
+} // namespace aura
+
+#endif // UI_AURA_MUS_GESTURE_SYNCHRONIZER_H_
diff --git a/chromium/ui/aura/mus/gesture_synchronizer_unittest.cc b/chromium/ui/aura/mus/gesture_synchronizer_unittest.cc
new file mode 100644
index 00000000000..cd1e7e0dee8
--- /dev/null
+++ b/chromium/ui/aura/mus/gesture_synchronizer_unittest.cc
@@ -0,0 +1,90 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/aura/mus/gesture_synchronizer.h"
+
+#include <memory>
+
+#include "ui/aura/env.h"
+#include "ui/aura/mus/window_mus.h"
+#include "ui/aura/mus/window_tree_host_mus.h"
+#include "ui/aura/mus/window_tree_host_mus_init_params.h"
+#include "ui/aura/test/aura_mus_test_base.h"
+#include "ui/aura/test/mus/test_window_tree.h"
+
+namespace aura {
+
+class GestureSynchronizerTest : public test::AuraMusClientTestBase {
+ public:
+ GestureSynchronizerTest() = default;
+ ~GestureSynchronizerTest() override = default;
+
+ void SetUp() override {
+ test::AuraMusClientTestBase::SetUp();
+
+ window_tree_host_ = std::make_unique<WindowTreeHostMus>(
+ CreateInitParamsForTopLevel(window_tree_client_impl()));
+ window_tree_host_->InitHost();
+ window_tree_host_->Show();
+ }
+
+ protected:
+ ui::GestureRecognizer* gesture_recognizer() {
+ return Env::GetInstance()->gesture_recognizer();
+ }
+
+ std::unique_ptr<Window> NewWindow() {
+ auto window = std::make_unique<Window>(nullptr);
+ window->Init(ui::LAYER_NOT_DRAWN);
+ window_tree_host_->window()->AddChild(window.get());
+ window->Show();
+ return window;
+ }
+
+ private:
+ std::unique_ptr<WindowTreeHostMus> window_tree_host_;
+
+ DISALLOW_COPY_AND_ASSIGN(GestureSynchronizerTest);
+};
+
+TEST_F(GestureSynchronizerTest, CancelActiveTouchesExcept) {
+ std::unique_ptr<Window> window = NewWindow();
+ gesture_recognizer()->CancelActiveTouchesExcept(window.get());
+ EXPECT_EQ(window_tree()->last_not_cancelled_window_id(),
+ WindowMus::Get(window.get())->server_id());
+}
+
+TEST_F(GestureSynchronizerTest, CancelActiveTouchesExceptForNullptr) {
+ gesture_recognizer()->CancelActiveTouchesExcept(nullptr);
+ EXPECT_EQ(window_tree()->last_not_cancelled_window_id(), kInvalidServerId);
+}
+
+TEST_F(GestureSynchronizerTest, CancelActiveTouches) {
+ std::unique_ptr<Window> window = NewWindow();
+ gesture_recognizer()->CancelActiveTouches(window.get());
+ EXPECT_EQ(window_tree()->last_cancelled_window_id(),
+ WindowMus::Get(window.get())->server_id());
+}
+
+TEST_F(GestureSynchronizerTest, TransferGestureEventsTo) {
+ std::unique_ptr<Window> window1 = NewWindow();
+ std::unique_ptr<Window> window2 = NewWindow();
+ gesture_recognizer()->TransferEventsTo(window1.get(), window2.get(),
+ ui::TransferTouchesBehavior::kCancel);
+ EXPECT_EQ(window_tree()->last_transfer_current(),
+ WindowMus::Get(window1.get())->server_id());
+ EXPECT_EQ(window_tree()->last_transfer_new(),
+ WindowMus::Get(window2.get())->server_id());
+ EXPECT_TRUE(window_tree()->last_transfer_should_cancel());
+
+ gesture_recognizer()->TransferEventsTo(
+ window2.get(), window1.get(), ui::TransferTouchesBehavior::kDontCancel);
+ EXPECT_EQ(window_tree()->last_transfer_current(),
+ WindowMus::Get(window2.get())->server_id());
+ EXPECT_EQ(window_tree()->last_transfer_new(),
+ WindowMus::Get(window1.get())->server_id());
+ EXPECT_FALSE(window_tree()->last_transfer_should_cancel());
+}
+
+} // namespace aura
diff --git a/chromium/ui/aura/mus/input_method_mus.cc b/chromium/ui/aura/mus/input_method_mus.cc
index f840416fe0f..cf1328a6e05 100644
--- a/chromium/ui/aura/mus/input_method_mus.cc
+++ b/chromium/ui/aura/mus/input_method_mus.cc
@@ -19,6 +19,21 @@
using ws::mojom::EventResult;
namespace aura {
+namespace {
+
+void CallEventResultCallback(InputMethodMus::EventResultCallback ack_callback,
+ bool handled) {
+ // |ack_callback| can be null if the standard form of DispatchKeyEvent() is
+ // called instead of the version which provides a callback. In mus+ash we
+ // use the version with callback, but some unittests use the standard form.
+ if (!ack_callback)
+ return;
+
+ std::move(ack_callback)
+ .Run(handled ? EventResult::HANDLED : EventResult::UNHANDLED);
+}
+
+} // namespace
////////////////////////////////////////////////////////////////////////////////
// InputMethodMus, public:
@@ -34,7 +49,7 @@ InputMethodMus::~InputMethodMus() {
// Mus won't dispatch the next key event until the existing one is acked. We
// may have KeyEvents sent to IME and awaiting the result, we need to ack
// them otherwise mus won't process the next event until it times out.
- AckPendingCallbacksUnhandled();
+ AckPendingCallbacks();
}
void InputMethodMus::Init(service_manager::Connector* connector) {
@@ -50,13 +65,9 @@ ui::EventDispatchDetails InputMethodMus::DispatchKeyEvent(
// If no text input client, do nothing.
if (!GetTextInputClient()) {
- ui::EventDispatchDetails dispatch_details = DispatchKeyEventPostIME(event);
- if (ack_callback) {
- std::move(ack_callback)
- .Run(event->handled() ? EventResult::HANDLED
- : EventResult::UNHANDLED);
- }
- return dispatch_details;
+ return DispatchKeyEventPostIME(
+ event,
+ base::BindOnce(&CallEventResultCallback, std::move(ack_callback)));
}
return SendKeyEventToInputMethod(*event, std::move(ack_callback));
@@ -136,7 +147,8 @@ ui::EventDispatchDetails InputMethodMus::SendKeyEventToInputMethod(
// This code path is hit in tests that don't connect to the server.
DCHECK(!ack_callback);
std::unique_ptr<ui::Event> event_clone = ui::Event::Clone(event);
- return DispatchKeyEventPostIME(event_clone->AsKeyEvent());
+ return DispatchKeyEventPostIME(event_clone->AsKeyEvent(),
+ base::NullCallback());
}
// IME driver will notify us whether it handled the event or not by calling
@@ -160,7 +172,7 @@ void InputMethodMus::OnDidChangeFocusedClient(
// We are about to close the pipe with pending callbacks. Closing the pipe
// results in none of the callbacks being run. We have to run the callbacks
// else mus won't process the next event immediately.
- AckPendingCallbacksUnhandled();
+ AckPendingCallbacks();
if (!focused) {
input_method_ = nullptr;
@@ -200,10 +212,10 @@ void InputMethodMus::UpdateTextInputType() {
}
}
-void InputMethodMus::AckPendingCallbacksUnhandled() {
+void InputMethodMus::AckPendingCallbacks() {
for (auto& callback : pending_callbacks_) {
if (callback)
- std::move(callback).Run(EventResult::UNHANDLED);
+ std::move(callback).Run(EventResult::HANDLED);
}
pending_callbacks_.clear();
}
@@ -216,14 +228,7 @@ void InputMethodMus::ProcessKeyEventCallback(
DCHECK(!pending_callbacks_.empty());
EventResultCallback ack_callback = std::move(pending_callbacks_.front());
pending_callbacks_.pop_front();
-
- // |ack_callback| can be null if the standard form of DispatchKeyEvent() is
- // called instead of the version which provides a callback. In mus+ash we
- // use the version with callback, but some unittests use the standard form.
- if (ack_callback) {
- std::move(ack_callback)
- .Run(handled ? EventResult::HANDLED : EventResult::UNHANDLED);
- }
+ CallEventResultCallback(std::move(ack_callback), handled);
}
} // namespace aura
diff --git a/chromium/ui/aura/mus/input_method_mus.h b/chromium/ui/aura/mus/input_method_mus.h
index d47ed317001..d54bf4357cc 100644
--- a/chromium/ui/aura/mus/input_method_mus.h
+++ b/chromium/ui/aura/mus/input_method_mus.h
@@ -64,10 +64,13 @@ class AURA_EXPORT InputMethodMus : public ui::InputMethodBase {
void UpdateTextInputType();
- // Runs all pending callbacks with UNHANDLED. This is called during shutdown,
+ // Runs all pending callbacks with HANDLED. This is called during shutdown,
// or any time |input_method_ptr_| is reset to ensure we don't leave mus
- // waiting for an ack.
- void AckPendingCallbacksUnhandled();
+ // waiting for an ack. We ack HANDLED because the input method can be reset
+ // due to focus changes in response to shortcuts (e.g. Ctrl-T opening a tab)
+ // and we don't want the window manager to try to process the accelerators.
+ // https://crbug.com/874098
+ void AckPendingCallbacks();
// Called when the server responds to our request to process an event.
void ProcessKeyEventCallback(
diff --git a/chromium/ui/aura/mus/input_method_mus_unittest.cc b/chromium/ui/aura/mus/input_method_mus_unittest.cc
index eaa79232a93..b70f26395ba 100644
--- a/chromium/ui/aura/mus/input_method_mus_unittest.cc
+++ b/chromium/ui/aura/mus/input_method_mus_unittest.cc
@@ -21,12 +21,22 @@ class TestInputMethodDelegate : public ui::internal::InputMethodDelegate {
TestInputMethodDelegate() {}
~TestInputMethodDelegate() override {}
+ bool was_dispatch_key_event_post_ime_called() const {
+ return was_dispatch_key_event_post_ime_called_;
+ }
+
// ui::internal::InputMethodDelegate:
- ui::EventDispatchDetails DispatchKeyEventPostIME(ui::KeyEvent* key) override {
+ ui::EventDispatchDetails DispatchKeyEventPostIME(
+ ui::KeyEvent* key,
+ base::OnceCallback<void(bool)> ack_callback) override {
+ was_dispatch_key_event_post_ime_called_ = true;
+ CallDispatchKeyEventPostIMEAck(key, std::move(ack_callback));
return ui::EventDispatchDetails();
}
private:
+ bool was_dispatch_key_event_post_ime_called_ = false;
+
DISALLOW_COPY_AND_ASSIGN(TestInputMethodDelegate);
};
@@ -94,23 +104,28 @@ using InputMethodMusTest = test::AuraTestBaseMus;
namespace {
// Used in closure supplied to processing the event.
-void RunFunctionWithEventResult(bool* was_run, ws::mojom::EventResult result) {
+void RunFunctionWithEventResult(bool* was_run,
+ ws::mojom::EventResult* result_out,
+ ws::mojom::EventResult result) {
*was_run = true;
+ *result_out = result;
}
} // namespace
TEST_F(InputMethodMusTest, PendingCallbackRunFromDestruction) {
bool was_event_result_callback_run = false;
- // Create an InputMethodMus and foward an event to it.
+ ws::mojom::EventResult event_result = ws::mojom::EventResult::UNHANDLED;
+ // Create an InputMethodMus and forward an event to it.
{
TestInputMethodDelegate input_method_delegate;
InputMethodMus input_method_mus(&input_method_delegate, nullptr);
TestInputMethod test_input_method;
InputMethodMusTestApi::SetInputMethod(&input_method_mus,
&test_input_method);
- EventResultCallback callback = base::BindOnce(
- &RunFunctionWithEventResult, &was_event_result_callback_run);
+ EventResultCallback callback =
+ base::BindOnce(&RunFunctionWithEventResult,
+ &was_event_result_callback_run, &event_result);
ui::EventDispatchDetails details =
InputMethodMusTestApi::CallSendKeyEventToInputMethod(
@@ -136,14 +151,16 @@ TEST_F(InputMethodMusTest, PendingCallbackRunFromDestruction) {
TEST_F(InputMethodMusTest, PendingCallbackRunFromOnDidChangeFocusedClient) {
bool was_event_result_callback_run = false;
+ ws::mojom::EventResult event_result = ws::mojom::EventResult::UNHANDLED;
ui::DummyTextInputClient test_input_client;
- // Create an InputMethodMus and foward an event to it.
+ // Create an InputMethodMus and forward an event to it.
TestInputMethodDelegate input_method_delegate;
InputMethodMus input_method_mus(&input_method_delegate, nullptr);
TestInputMethod test_input_method;
InputMethodMusTestApi::SetInputMethod(&input_method_mus, &test_input_method);
- EventResultCallback callback = base::BindOnce(&RunFunctionWithEventResult,
- &was_event_result_callback_run);
+ EventResultCallback callback =
+ base::BindOnce(&RunFunctionWithEventResult,
+ &was_event_result_callback_run, &event_result);
ui::EventDispatchDetails details =
InputMethodMusTestApi::CallSendKeyEventToInputMethod(
&input_method_mus,
@@ -159,18 +176,21 @@ TEST_F(InputMethodMusTest, PendingCallbackRunFromOnDidChangeFocusedClient) {
&input_method_mus, nullptr, &test_input_client);
// Changing the focused client should trigger running the callback.
EXPECT_TRUE(was_event_result_callback_run);
+ EXPECT_EQ(ws::mojom::EventResult::HANDLED, event_result);
}
TEST_F(InputMethodMusTest,
PendingCallbackRunFromOnDidChangeFocusedClientToNull) {
bool was_event_result_callback_run = false;
- // Create an InputMethodMus and foward an event to it.
+ ws::mojom::EventResult event_result = ws::mojom::EventResult::UNHANDLED;
+ // Create an InputMethodMus and forward an event to it.
TestInputMethodDelegate input_method_delegate;
InputMethodMus input_method_mus(&input_method_delegate, nullptr);
TestInputMethod test_input_method;
InputMethodMusTestApi::SetInputMethod(&input_method_mus, &test_input_method);
- EventResultCallback callback = base::BindOnce(&RunFunctionWithEventResult,
- &was_event_result_callback_run);
+ EventResultCallback callback =
+ base::BindOnce(&RunFunctionWithEventResult,
+ &was_event_result_callback_run, &event_result);
ui::EventDispatchDetails details =
InputMethodMusTestApi::CallSendKeyEventToInputMethod(
&input_method_mus,
@@ -186,6 +206,7 @@ TEST_F(InputMethodMusTest,
nullptr, nullptr);
// Changing the focused client should trigger running the callback.
EXPECT_TRUE(was_event_result_callback_run);
+ EXPECT_EQ(ws::mojom::EventResult::HANDLED, event_result);
}
// See description of ChangeTextInputTypeWhileProcessingCallback for details.
@@ -205,9 +226,12 @@ class TestInputMethodDelegate2 : public ui::internal::InputMethodDelegate {
}
// ui::internal::InputMethodDelegate:
- ui::EventDispatchDetails DispatchKeyEventPostIME(ui::KeyEvent* key) override {
+ ui::EventDispatchDetails DispatchKeyEventPostIME(
+ ui::KeyEvent* key,
+ base::OnceCallback<void(bool)> ack_callback) override {
was_dispatch_key_event_post_ime_called_ = true;
input_method_mus_->SetFocusedTextInputClient(text_input_client_);
+ CallDispatchKeyEventPostIMEAck(key, std::move(ack_callback));
return ui::EventDispatchDetails();
}
@@ -224,16 +248,18 @@ class TestInputMethodDelegate2 : public ui::internal::InputMethodDelegate {
// scenario and the callback is correctly called.
TEST_F(InputMethodMusTest, ChangeTextInputTypeWhileProcessingCallback) {
bool was_event_result_callback_run = false;
+ ws::mojom::EventResult event_result = ws::mojom::EventResult::UNHANDLED;
ui::DummyTextInputClient test_input_client;
- // Create an InputMethodMus and foward an event to it.
+ // Create an InputMethodMus and forward an event to it.
TestInputMethodDelegate2 input_method_delegate;
InputMethodMus input_method_mus(&input_method_delegate, nullptr);
input_method_delegate.SetInputMethodAndClient(&input_method_mus,
&test_input_client);
TestInputMethod test_input_method;
InputMethodMusTestApi::SetInputMethod(&input_method_mus, &test_input_method);
- EventResultCallback callback = base::BindOnce(&RunFunctionWithEventResult,
- &was_event_result_callback_run);
+ EventResultCallback callback =
+ base::BindOnce(&RunFunctionWithEventResult,
+ &was_event_result_callback_run, &event_result);
const ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, 0);
ui::EventDispatchDetails details =
InputMethodMusTestApi::CallSendKeyEventToInputMethod(
@@ -243,10 +269,13 @@ TEST_F(InputMethodMusTest, ChangeTextInputTypeWhileProcessingCallback) {
ASSERT_EQ(1u, test_input_method.process_key_event_callbacks()->size());
// Callback should not have been run yet.
EXPECT_FALSE(was_event_result_callback_run);
- std::move((*test_input_method.process_key_event_callbacks())[0]).Run(false);
+ const bool handled = true;
+ std::move((*test_input_method.process_key_event_callbacks())[0]).Run(handled);
// Callback should have been run.
EXPECT_TRUE(was_event_result_callback_run);
+ EXPECT_EQ(ws::mojom::EventResult::HANDLED, event_result);
+ EXPECT_FALSE(input_method_delegate.was_dispatch_key_event_post_ime_called());
}
// Calling OnTextInputTypeChanged from unfocused client should
@@ -317,4 +346,37 @@ TEST_F(InputMethodMusTest, ShowVirtualKeyboardIfEnabled) {
EXPECT_TRUE(test_input_method.was_show_virtual_keyboard_if_enabled_called());
}
+TEST_F(InputMethodMusTest, AckUnhandledCallsDispatchKeyEventPostUnhandled) {
+ bool was_event_result_callback_run = false;
+ ws::mojom::EventResult event_result = ws::mojom::EventResult::UNHANDLED;
+ // Create an InputMethodMus and forward an event to it.
+ TestInputMethodDelegate input_method_delegate;
+ InputMethodMus input_method_mus(&input_method_delegate, nullptr);
+ TestInputMethod test_input_method;
+ InputMethodMusTestApi::SetInputMethod(&input_method_mus, &test_input_method);
+ EventResultCallback callback =
+ base::BindOnce(&RunFunctionWithEventResult,
+ &was_event_result_callback_run, &event_result);
+ const ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_RETURN, 0);
+ ignore_result(InputMethodMusTestApi::CallSendKeyEventToInputMethod(
+ &input_method_mus, key_event, std::move(callback)));
+ // The event should have been queued.
+ ASSERT_EQ(1u, test_input_method.process_key_event_callbacks()->size());
+ // Callback should not have been run yet.
+ EXPECT_FALSE(was_event_result_callback_run);
+ const bool handled = false;
+ std::move((*test_input_method.process_key_event_callbacks())[0]).Run(handled);
+ test_input_method.process_key_event_callbacks()->clear();
+
+ // Callback should have been run.
+ EXPECT_TRUE(was_event_result_callback_run);
+ EXPECT_EQ(ws::mojom::EventResult::UNHANDLED, event_result);
+
+ // DispatchKeyEventPostIME() should not have beeen called. In production
+ // the following calls result:
+ // InputMethodChromeOS -> RemoteTextInputClient -> TextInputClientImpl ->
+ // InputMethodMus's delegate.
+ EXPECT_FALSE(input_method_delegate.was_dispatch_key_event_post_ime_called());
+}
+
} // namespace aura
diff --git a/chromium/ui/aura/mus/mus_mouse_location_updater.cc b/chromium/ui/aura/mus/mus_mouse_location_updater.cc
index 32aa588cb61..ce61eab444f 100644
--- a/chromium/ui/aura/mus/mus_mouse_location_updater.cc
+++ b/chromium/ui/aura/mus/mus_mouse_location_updater.cc
@@ -38,27 +38,17 @@ MusMouseLocationUpdater::~MusMouseLocationUpdater() {
}
void MusMouseLocationUpdater::OnEventProcessingStarted(const ui::Event& event) {
- if (!IsMouseEventWithLocation(event) ||
- Env::GetInstance()->always_use_last_mouse_location_) {
+ Env* env = Env::GetInstance();
+ if (!IsMouseEventWithLocation(event) || env->always_use_last_mouse_location_)
return;
- }
is_processing_trigger_event_ = true;
- gfx::Point location_in_screen = event.AsMouseEvent()->root_location();
// event.target() may not exist in some tests.
- if (event.target()) {
- aura::Window* root_window =
- static_cast<aura::Window*>(event.target())->GetRootWindow();
- auto* screen_position_client =
- aura::client::GetScreenPositionClient(root_window);
- // screen_position_client may not exist in tests.
- if (screen_position_client) {
- screen_position_client->ConvertPointToScreen(root_window,
- &location_in_screen);
- }
- }
- Env::GetInstance()->SetLastMouseLocation(location_in_screen);
- Env::GetInstance()->get_last_mouse_location_from_mus_ = false;
+ const gfx::Point screen_location =
+ event.target() ? event.target()->GetScreenLocation(*event.AsMouseEvent())
+ : event.AsMouseEvent()->root_location();
+ env->SetLastMouseLocation(screen_location);
+ env->get_last_mouse_location_from_mus_ = false;
}
void MusMouseLocationUpdater::OnEventProcessingFinished() {
diff --git a/chromium/ui/aura/mus/mus_types.h b/chromium/ui/aura/mus/mus_types.h
index 4f406261d73..3a58e55eeb9 100644
--- a/chromium/ui/aura/mus/mus_types.h
+++ b/chromium/ui/aura/mus/mus_types.h
@@ -20,17 +20,9 @@ enum class WindowMusType {
// The window is an embed root in the embedded client. That is, the client
// received this window by way of another client calling Embed(). In other
// words, this is the embedded side of an embedding.
- // NOTE: in the client that called Embed() the window type is LOCAL (or
- // EMBED_IN_OWNER).
- // TODO(sky): ensure when Embed() is called type is always set to
- // EMBED_IN_OWNER, and if the embedding is removed it goes back to LOCAL.
- // https://crbug.com/834487
+ // NOTE: in the client that called Embed() the window type is LOCAL.
EMBED,
- // Embed() was called on the window by the local client. In other words, this
- // is the embedder side of an embedding.
- EMBED_IN_OWNER,
-
// The window was created by requesting a top level
// (WindowTree::NewTopLevel()).
TOP_LEVEL,
diff --git a/chromium/ui/aura/mus/os_exchange_data_provider_mus.cc b/chromium/ui/aura/mus/os_exchange_data_provider_mus.cc
index 9e41787ea96..f8e327cd09b 100644
--- a/chromium/ui/aura/mus/os_exchange_data_provider_mus.cc
+++ b/chromium/ui/aura/mus/os_exchange_data_provider_mus.cc
@@ -113,8 +113,7 @@ void OSExchangeDataProviderMus::SetFilename(const base::FilePath& path) {
void OSExchangeDataProviderMus::SetFilenames(
const std::vector<ui::FileInfo>& file_names) {
std::vector<std::string> paths;
- for (std::vector<ui::FileInfo>::const_iterator it = file_names.begin();
- it != file_names.end(); ++it) {
+ for (auto it = file_names.begin(); it != file_names.end(); ++it) {
std::string url_spec = net::FilePathToFileURL(it->path).spec();
if (!url_spec.empty())
paths.push_back(url_spec);
diff --git a/chromium/ui/aura/mus/property_converter.cc b/chromium/ui/aura/mus/property_converter.cc
index 51cd00e1d81..0d0e345318e 100644
--- a/chromium/ui/aura/mus/property_converter.cc
+++ b/chromium/ui/aura/mus/property_converter.cc
@@ -4,6 +4,7 @@
#include "ui/aura/mus/property_converter.h"
+#include "base/time/time.h"
#include "base/unguessable_token.h"
#include "mojo/public/cpp/bindings/type_converter.h"
#include "services/ws/public/cpp/property_type_converters.h"
@@ -108,10 +109,58 @@ PropertyConverter::PropertyConverter() {
client::kAnimationsDisabledKey,
ws::mojom::WindowManager::kAnimationsDisabled_Property,
CreateAcceptAnyValueCallback());
+ RegisterWindowPtrProperty(
+ client::kChildModalParentKey,
+ ws::mojom::WindowManager::kChildModalParent_Property);
}
PropertyConverter::~PropertyConverter() {}
+const void* PropertyConverter::GetPropertyKeyFromTransportName(
+ const std::string& transport_name) {
+ for (const auto& primitive_property : primitive_properties_) {
+ if (primitive_property.second.transport_name == transport_name)
+ return primitive_property.first;
+ }
+
+ for (const auto& image_property : image_properties_) {
+ if (image_property.second == transport_name)
+ return image_property.first->name;
+ }
+
+ for (const auto& rect_property : rect_properties_) {
+ if (rect_property.second == transport_name)
+ return rect_property.first->name;
+ }
+
+ for (const auto& size_property : size_properties_) {
+ if (size_property.second == transport_name)
+ return size_property.first->name;
+ }
+
+ for (const auto& string_property : string_properties_) {
+ if (string_property.second == transport_name)
+ return string_property.first->name;
+ }
+
+ for (const auto& string16_property : string16_properties_) {
+ if (string16_property.second == transport_name)
+ return string16_property.first->name;
+ }
+
+ for (const auto& unguessable_token_property : unguessable_token_properties_) {
+ if (unguessable_token_property.second == transport_name)
+ return unguessable_token_property.first->name;
+ }
+
+ for (const auto& window_ptr_property : window_ptr_properties_) {
+ if (window_ptr_property.second == transport_name)
+ return window_ptr_property.first->name;
+ }
+
+ return nullptr;
+}
+
bool PropertyConverter::IsTransportNameRegistered(
const std::string& name) const {
return transport_names_.count(name) > 0;
@@ -131,7 +180,7 @@ bool PropertyConverter::ConvertPropertyForTransport(
const gfx::ImageSkia* value = window->GetProperty(image_key);
if (value) {
// TODO(crbug.com/667566): Support additional scales or gfx::Image[Skia].
- SkBitmap bitmap = value->GetRepresentation(1.f).sk_bitmap();
+ SkBitmap bitmap = value->GetRepresentation(1.f).GetBitmap();
*transport_value = std::make_unique<std::vector<uint8_t>>(
mojo::ConvertTo<std::vector<uint8_t>>(bitmap));
} else {
@@ -171,6 +220,14 @@ bool PropertyConverter::ConvertPropertyForTransport(
return true;
}
+ // window_ptr_properties_ aren't processed here since Window* values aren't
+ // transferrable. A post processing step in WindowTree and WindowTreeClient
+ // takes care of the conversion.
+ if (IsWindowPtrPropertyRegistered(
+ static_cast<const WindowProperty<Window*>*>(key))) {
+ return true;
+ }
+
// Handle primitive property types generically.
DCHECK_GT(primitive_properties_.count(key), 0u);
PrimitiveType default_value = primitive_properties_[key].default_value;
@@ -210,6 +267,10 @@ std::string PropertyConverter::GetTransportNameForPropertyKey(const void* key) {
if (unguessable_token_properties_.count(unguessable_token_key) > 0)
return unguessable_token_properties_[unguessable_token_key];
+ auto* window_ptr_key = static_cast<const WindowProperty<Window*>*>(key);
+ if (window_ptr_properties_.count(window_ptr_key) > 0)
+ return window_ptr_properties_[window_ptr_key];
+
return std::string();
}
@@ -307,6 +368,20 @@ void PropertyConverter::SetPropertyFromTransportValue(
}
}
+ // window_ptr_properties_ aren't processed here since Window* values aren't
+ // transferrable. A post processing step in WindowTree and WindowTreeClient
+ // takes care of the conversion.
+ for (const auto& window_ptr_property : window_ptr_properties_) {
+ if (window_ptr_property.second == transport_name) {
+ LOG(ERROR) << transport_name << " is a registered window property but "
+ << "should not be processed here.";
+ return;
+ }
+ }
+
+ // WARNING: Adding a new map, be sure and update
+ // GetPropertyKeyFromTransportName() as well.
+
DVLOG(2) << "Unknown mus property name: " << transport_name;
}
@@ -379,6 +454,15 @@ void PropertyConverter::RegisterString16Property(
transport_names_.insert(transport_name);
}
+void PropertyConverter::RegisterTimeDeltaProperty(
+ const WindowProperty<base::TimeDelta>* property,
+ const char* transport_name) {
+ // TimeDelta is internally handled (by class_property) as a primitive
+ // value (int64_t) . See ClassPropertyCaster<base::TimeDelta> for details.
+ RegisterPrimitiveProperty(property, transport_name,
+ CreateAcceptAnyValueCallback());
+}
+
void PropertyConverter::RegisterUnguessableTokenProperty(
const WindowProperty<base::UnguessableToken*>* property,
const char* transport_name) {
@@ -388,6 +472,29 @@ void PropertyConverter::RegisterUnguessableTokenProperty(
transport_names_.insert(transport_name);
}
+void PropertyConverter::RegisterWindowPtrProperty(
+ const WindowProperty<Window*>* property,
+ const char* transport_name) {
+ DCHECK(!IsTransportNameRegistered(transport_name))
+ << "Property already registered: " << transport_name;
+ window_ptr_properties_[property] = transport_name;
+ transport_names_.insert(transport_name);
+}
+
+const WindowProperty<Window*>* PropertyConverter::GetWindowPtrProperty(
+ const std::string& transport_name) const {
+ for (const auto& iter : window_ptr_properties_) {
+ if (transport_name == iter.second)
+ return iter.first;
+ }
+ return nullptr;
+}
+
+bool PropertyConverter::IsWindowPtrPropertyRegistered(
+ const WindowProperty<Window*>* property) const {
+ return window_ptr_properties_.find(property) != window_ptr_properties_.end();
+}
+
base::flat_map<std::string, std::vector<uint8_t>>
PropertyConverter::GetTransportProperties(Window* window) {
base::flat_map<std::string, std::vector<uint8_t>> properties;
diff --git a/chromium/ui/aura/mus/property_converter.h b/chromium/ui/aura/mus/property_converter.h
index 8d13b2021cd..82650db1321 100644
--- a/chromium/ui/aura/mus/property_converter.h
+++ b/chromium/ui/aura/mus/property_converter.h
@@ -18,6 +18,7 @@
#include "ui/aura/window.h"
namespace base {
+class TimeDelta;
class UnguessableToken;
}
@@ -45,6 +46,10 @@ class AURA_EXPORT PropertyConverter {
// accept any value.
static base::RepeatingCallback<bool(int64_t)> CreateAcceptAnyValueCallback();
+ // Returns the key for the window property registered against the specified
+ // transport name.
+ const void* GetPropertyKeyFromTransportName(const std::string& name);
+
// Returns true if RegisterProperty() has been called with the specified
// transport name.
bool IsTransportNameRegistered(const std::string& name) const;
@@ -111,9 +116,23 @@ class AURA_EXPORT PropertyConverter {
const char* transport_name);
void RegisterString16Property(const WindowProperty<base::string16*>* property,
const char* transport_name);
+ void RegisterTimeDeltaProperty(
+ const WindowProperty<base::TimeDelta>* property,
+ const char* transport_name);
void RegisterUnguessableTokenProperty(
const WindowProperty<base::UnguessableToken*>* property,
const char* transport_name);
+ void RegisterWindowPtrProperty(const WindowProperty<Window*>* property,
+ const char* transport_name);
+
+ // Returns the window property key of Window* value which is registered with
+ // the transport_name. If the name is not registered or registered with a
+ // different type, returns nullptr.
+ const WindowProperty<Window*>* GetWindowPtrProperty(
+ const std::string& transport_name) const;
+
+ bool IsWindowPtrPropertyRegistered(
+ const WindowProperty<Window*>* property) const;
// Get a flat map of the window's registered properties, to use for transport.
base::flat_map<std::string, std::vector<uint8_t>> GetTransportProperties(
@@ -151,6 +170,7 @@ class AURA_EXPORT PropertyConverter {
string16_properties_;
std::map<const WindowProperty<base::UnguessableToken*>*, const char*>
unguessable_token_properties_;
+ std::map<const WindowProperty<Window*>*, const char*> window_ptr_properties_;
// Set of transport names supplied to RegisterProperty().
std::set<std::string> transport_names_;
diff --git a/chromium/ui/aura/mus/property_converter_unittest.cc b/chromium/ui/aura/mus/property_converter_unittest.cc
index 50838071d5f..2d0382cf08f 100644
--- a/chromium/ui/aura/mus/property_converter_unittest.cc
+++ b/chromium/ui/aura/mus/property_converter_unittest.cc
@@ -43,6 +43,10 @@ DEFINE_UI_CLASS_PROPERTY_KEY(int16_t, kTestPropertyKey7, 1);
DEFINE_UI_CLASS_PROPERTY_KEY(int32_t, kTestPropertyKey8, -1);
DEFINE_UI_CLASS_PROPERTY_KEY(int64_t, kTestPropertyKey9, 777);
+DEFINE_UI_CLASS_PROPERTY_KEY(base::TimeDelta,
+ kTestTimeDeltaKey,
+ base::TimeDelta());
+
DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::ImageSkia,
kTestImageSkiaPropertyKey,
nullptr);
@@ -53,6 +57,9 @@ DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(
DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(base::string16, kTestString16PropertyKey,
nullptr);
+DEFINE_UI_CLASS_PROPERTY_KEY(Window*, kTestWindowPtrPropertyKey, nullptr);
+DEFINE_UI_CLASS_PROPERTY_KEY(Window*, kTestWindowPtrUnregisteredKey, nullptr);
+
const char kTestPropertyServerKey0[] = "test-property-server0";
const char kTestPropertyServerKey1[] = "test-property-server1";
const char kTestPropertyServerKey2[] = "test-property-server2";
@@ -69,6 +76,10 @@ const char kTestRectPropertyServerKey[] = "test-rect-property-server";
const char kTestSizePropertyServerKey[] = "test-size-property-server";
const char kTestStringPropertyServerKey[] = "test-string-property-server";
const char kTestString16PropertyServerKey[] = "test-string16-property-server";
+const char kTestTimeDeltaPropertyServerKey[] =
+ "test-time-delta-property-server";
+const char kTestWindowPtrPropertyServerKey[] =
+ "test-window-ptr-property-server";
// Test registration, naming and value conversion for primitive property types.
template <typename T>
@@ -369,4 +380,84 @@ TEST_F(PropertyConverterTest, String16Property) {
EXPECT_EQ(value_2, *window->GetProperty(kTestString16PropertyKey));
}
+TEST_F(PropertyConverterTest, TimeDeltaProperty) {
+ PropertyConverter property_converter;
+ property_converter.RegisterTimeDeltaProperty(kTestTimeDeltaKey,
+ kTestTimeDeltaPropertyServerKey);
+ EXPECT_EQ(
+ kTestTimeDeltaPropertyServerKey,
+ property_converter.GetTransportNameForPropertyKey(kTestTimeDeltaKey));
+ EXPECT_TRUE(property_converter.IsTransportNameRegistered(
+ kTestTimeDeltaPropertyServerKey));
+
+ std::unique_ptr<Window> window(CreateNormalWindow(1, root_window(), nullptr));
+ const base::TimeDelta time_delta =
+ base::TimeDelta::FromMilliseconds(123456789);
+ window->SetProperty(kTestTimeDeltaKey, time_delta);
+
+ std::string transport_name_out;
+ std::unique_ptr<std::vector<uint8_t>> transport_value_out;
+ EXPECT_TRUE(property_converter.ConvertPropertyForTransport(
+ window.get(), kTestTimeDeltaKey, &transport_name_out,
+ &transport_value_out));
+ EXPECT_EQ(kTestTimeDeltaPropertyServerKey, transport_name_out);
+ const int64_t storage_value_1 = time_delta.InMicroseconds();
+ std::vector<uint8_t> transport_value =
+ mojo::ConvertTo<std::vector<uint8_t>>(storage_value_1);
+ EXPECT_EQ(transport_value, *transport_value_out.get());
+
+ int64_t decoded_value_1 = 0;
+ EXPECT_TRUE(property_converter.GetPropertyValueFromTransportValue(
+ kTestTimeDeltaPropertyServerKey, *transport_value_out, &decoded_value_1));
+ EXPECT_EQ(time_delta.InMicroseconds(), decoded_value_1);
+
+ window->SetProperty(kTestTimeDeltaKey, base::TimeDelta());
+ property_converter.SetPropertyFromTransportValue(
+ window.get(), kTestTimeDeltaPropertyServerKey, &transport_value);
+ EXPECT_EQ(time_delta, window->GetProperty(kTestTimeDeltaKey));
+}
+
+TEST_F(PropertyConverterTest, WindowPtrProperty) {
+ PropertyConverter property_converter;
+ property_converter.RegisterString16Property(kTestString16PropertyKey,
+ kTestString16PropertyServerKey);
+ property_converter.RegisterWindowPtrProperty(kTestWindowPtrPropertyKey,
+ kTestWindowPtrPropertyServerKey);
+ EXPECT_EQ(kTestWindowPtrPropertyServerKey,
+ property_converter.GetTransportNameForPropertyKey(
+ kTestWindowPtrPropertyKey));
+ EXPECT_TRUE(property_converter.IsTransportNameRegistered(
+ kTestWindowPtrPropertyServerKey));
+
+ EXPECT_TRUE(property_converter.IsWindowPtrPropertyRegistered(
+ kTestWindowPtrPropertyKey));
+ EXPECT_EQ(kTestWindowPtrPropertyKey, property_converter.GetWindowPtrProperty(
+ kTestWindowPtrPropertyServerKey));
+ EXPECT_FALSE(property_converter.IsWindowPtrPropertyRegistered(
+ kTestWindowPtrUnregisteredKey));
+ EXPECT_FALSE(
+ property_converter.GetWindowPtrProperty(kTestString16PropertyServerKey));
+
+ std::unique_ptr<Window> window1(
+ CreateNormalWindow(1, root_window(), nullptr));
+ std::unique_ptr<Window> window2(
+ CreateNormalWindow(2, root_window(), nullptr));
+ window1->SetProperty(kTestWindowPtrPropertyKey, window2.get());
+
+ std::string transport_name_out;
+ std::unique_ptr<std::vector<uint8_t>> transport_value_out;
+ EXPECT_TRUE(property_converter.ConvertPropertyForTransport(
+ window1.get(), kTestWindowPtrPropertyKey, &transport_name_out,
+ &transport_value_out));
+ EXPECT_EQ(kTestWindowPtrPropertyServerKey, transport_name_out);
+ EXPECT_FALSE(transport_value_out);
+
+ window1->ClearProperty(kTestWindowPtrPropertyKey);
+ std::vector<uint8_t> transport_value = mojo::ConvertTo<std::vector<uint8_t>>(
+ reinterpret_cast<uint64_t>(window2.get()));
+ property_converter.SetPropertyFromTransportValue(
+ window1.get(), kTestWindowPtrPropertyServerKey, &transport_value);
+ EXPECT_FALSE(window1->GetProperty(kTestWindowPtrPropertyKey));
+}
+
} // namespace aura
diff --git a/chromium/ui/aura/mus/text_input_client_impl.cc b/chromium/ui/aura/mus/text_input_client_impl.cc
index 0ce8eb10c23..29121c53a7e 100644
--- a/chromium/ui/aura/mus/text_input_client_impl.cc
+++ b/chromium/ui/aura/mus/text_input_client_impl.cc
@@ -52,9 +52,8 @@ void TextInputClientImpl::DispatchKeyEventPostIME(
std::unique_ptr<ui::Event> event,
DispatchKeyEventPostIMECallback callback) {
if (delegate_) {
- delegate_->DispatchKeyEventPostIME(event->AsKeyEvent());
- if (callback && !callback.is_null())
- std::move(callback).Run(event->stopped_propagation());
+ delegate_->DispatchKeyEventPostIME(event->AsKeyEvent(),
+ std::move(callback));
}
}
diff --git a/chromium/ui/aura/mus/window_mus.h b/chromium/ui/aura/mus/window_mus.h
index bac124e8b37..3ee4b65d25a 100644
--- a/chromium/ui/aura/mus/window_mus.h
+++ b/chromium/ui/aura/mus/window_mus.h
@@ -28,7 +28,6 @@ enum class OrderDirection;
namespace viz {
class FrameSinkId;
class LocalSurfaceId;
-class SurfaceInfo;
}
namespace aura {
@@ -95,7 +94,6 @@ class AURA_EXPORT WindowMus {
const viz::FrameSinkId& frame_sink_id) = 0;
virtual const viz::LocalSurfaceId& GetOrAllocateLocalSurfaceId(
const gfx::Size& new_size) = 0;
- virtual void SetFallbackSurfaceInfo(const viz::SurfaceInfo& surface_info) = 0;
// The window was deleted on the server side. DestroyFromServer() should
// result in deleting |this|.
virtual void DestroyFromServer() = 0;
diff --git a/chromium/ui/aura/mus/window_port_mus.cc b/chromium/ui/aura/mus/window_port_mus.cc
index 9db986531be..2eb6ad5647c 100644
--- a/chromium/ui/aura/mus/window_port_mus.cc
+++ b/chromium/ui/aura/mus/window_port_mus.cc
@@ -4,13 +4,15 @@
#include "ui/aura/mus/window_port_mus.h"
+#include "base/auto_reset.h"
#include "cc/mojo_embedder/async_layer_tree_frame_sink.h"
+#include "components/viz/client/hit_test_data_provider_draw_quad.h"
#include "components/viz/client/local_surface_id_provider.h"
#include "components/viz/host/host_frame_sink_manager.h"
+#include "services/ws/public/mojom/window_tree_constants.mojom.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/transient_window_client.h"
#include "ui/aura/env.h"
-#include "ui/aura/hit_test_data_provider_aura.h"
#include "ui/aura/mus/client_surface_embedder.h"
#include "ui/aura/mus/property_converter.h"
#include "ui/aura/mus/window_tree_client.h"
@@ -27,6 +29,10 @@
namespace aura {
+namespace {
+static const char* kMus = "Mus";
+} // namespace
+
WindowPortMus::WindowMusChangeDataImpl::WindowMusChangeDataImpl() = default;
WindowPortMus::WindowMusChangeDataImpl::~WindowMusChangeDataImpl() = default;
@@ -38,7 +44,8 @@ WindowMus* WindowMus::Get(Window* window) {
WindowPortMus::WindowPortMus(WindowTreeClient* client,
WindowMusType window_mus_type)
- : WindowMus(window_mus_type),
+ : WindowPort(WindowPort::Type::kMus),
+ WindowMus(window_mus_type),
window_tree_client_(client),
weak_ptr_factory_(this) {}
@@ -56,7 +63,10 @@ WindowPortMus::~WindowPortMus() {
// static
WindowPortMus* WindowPortMus::Get(Window* window) {
- return static_cast<WindowPortMus*>(WindowPort::Get(window));
+ WindowPort* port = WindowPort::Get(window);
+ return port && port->type() == WindowPort::Type::kMus
+ ? static_cast<WindowPortMus*>(port)
+ : nullptr;
}
void WindowPortMus::SetTextInputState(ui::mojom::TextInputStatePtr state) {
@@ -85,23 +95,36 @@ void WindowPortMus::SetCanAcceptDrops(bool can_accept_drops) {
window_tree_client_->SetCanAcceptDrops(this, can_accept_drops);
}
-void WindowPortMus::SetHitTestMask(const base::Optional<gfx::Rect>& mask) {
- window_tree_client_->SetHitTestMask(this, mask);
+void WindowPortMus::SetHitTestInsets(const gfx::Insets& mouse,
+ const gfx::Insets& touch) {
+ window_tree_client_->SetHitTestInsets(this, mouse, touch);
}
void WindowPortMus::Embed(ws::mojom::WindowTreeClientPtr client,
uint32_t flags,
ws::mojom::WindowTree::EmbedCallback callback) {
- window_tree_client_->Embed(window_, std::move(client), flags,
- std::move(callback));
+ if (!PrepareForEmbed()) {
+ std::move(callback).Run(false);
+ return;
+ }
+ window_tree_client_->tree_->Embed(
+ server_id(), std::move(client), flags,
+ base::BindOnce(&WindowPortMus::OnEmbedAck, weak_ptr_factory_.GetWeakPtr(),
+ std::move(callback)));
}
void WindowPortMus::EmbedUsingToken(
const base::UnguessableToken& token,
uint32_t flags,
ws::mojom::WindowTree::EmbedCallback callback) {
- window_tree_client_->EmbedUsingToken(window_, token, flags,
- std::move(callback));
+ if (!PrepareForEmbed()) {
+ std::move(callback).Run(false);
+ return;
+ }
+ window_tree_client_->tree_->EmbedUsingToken(
+ server_id(), token, flags,
+ base::BindOnce(&WindowPortMus::OnEmbedAck, weak_ptr_factory_.GetWeakPtr(),
+ std::move(callback)));
}
std::unique_ptr<cc::mojo_embedder::AsyncLayerTreeFrameSink>
@@ -119,11 +142,18 @@ WindowPortMus::RequestLayerTreeFrameSink(
params.gpu_memory_buffer_manager = gpu_memory_buffer_manager;
params.pipes.compositor_frame_sink_info = std::move(sink_info);
params.pipes.client_request = std::move(client_request);
+ bool root_accepts_events =
+ (window_->event_targeting_policy() ==
+ ws::mojom::EventTargetingPolicy::TARGET_ONLY) ||
+ (window_->event_targeting_policy() ==
+ ws::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS);
params.hit_test_data_provider =
- std::make_unique<HitTestDataProviderAura>(window_);
+ std::make_unique<viz::HitTestDataProviderDrawQuad>(
+ true /* should_ask_for_child_region */, root_accepts_events);
params.local_surface_id_provider =
std::make_unique<viz::DefaultLocalSurfaceIdProvider>();
params.enable_surface_synchronization = true;
+ params.client_name = kMus;
auto layer_tree_frame_sink =
std::make_unique<cc::mojo_embedder::AsyncLayerTreeFrameSink>(
@@ -213,6 +243,43 @@ WindowPortMus::ServerChanges::iterator WindowPortMus::FindChangeByTypeAndData(
return iter;
}
+bool WindowPortMus::PrepareForEmbed() {
+ // Window::Init() must be called before Embed() (otherwise the server hasn't
+ // been told about the window).
+ DCHECK(window_->layer());
+
+ // The window server removes all children before embedding. In other words,
+ // it's generally an error to Embed() with existing children. So, fail early.
+ if (!window_->children().empty())
+ return false;
+
+ // Can only embed in windows created by this client.
+ if (window_mus_type() != WindowMusType::LOCAL)
+ return false;
+
+ // Don't allow an embed when one exists. This could be handled, if the
+ // callback was converted to OnChangeCompleted(). To attempt to handle it
+ // without routing the callback over the WindowTreeClient pipe would result
+ // in problemcs because of ordering. The ordering problem is because there is
+ // the Embed() request, the callback, and OnEmbeddedAppDisconnected() (which
+ // originates from the server side).
+ if (has_embedding_)
+ return false;
+
+ has_embedding_ = true;
+ return true;
+}
+
+// static
+void WindowPortMus::OnEmbedAck(
+ base::WeakPtr<WindowPortMus> window,
+ ws::mojom::WindowTree::EmbedCallback real_callback,
+ bool result) {
+ if (window && !result)
+ window->has_embedding_ = false;
+ std::move(real_callback).Run(window && result);
+}
+
PropertyConverter* WindowPortMus::GetPropertyConverter() {
return window_tree_client_->delegate_->GetPropertyConverter();
}
@@ -305,9 +372,12 @@ void WindowPortMus::SetPropertyFromServer(
void WindowPortMus::SetFrameSinkIdFromServer(
const viz::FrameSinkId& frame_sink_id) {
- DCHECK(window_mus_type() == WindowMusType::EMBED_IN_OWNER);
- window_->SetEmbedFrameSinkId(frame_sink_id);
- UpdatePrimarySurfaceId();
+ embed_frame_sink_id_ = frame_sink_id;
+ window_->SetEmbedFrameSinkId(embed_frame_sink_id_);
+ // We may not have allocated a LocalSurfaceId. Call OnWindowMusBoundsChanged()
+ // to trigger updating the LocalSurfaceId *and* notifying the server.
+ window_tree_client_->OnWindowMusBoundsChanged(this, window_->bounds(),
+ window_->bounds());
}
const viz::LocalSurfaceId& WindowPortMus::GetOrAllocateLocalSurfaceId(
@@ -331,25 +401,6 @@ const viz::LocalSurfaceId& WindowPortMus::GetOrAllocateLocalSurfaceId(
return local_surface_id_;
}
-void WindowPortMus::SetFallbackSurfaceInfo(
- const viz::SurfaceInfo& surface_info) {
- if (!window_->IsEmbeddingClient()) {
- // |primary_surface_id_| shold not be valid, since we didn't know the
- // |window_->frame_sink_id()|.
- DCHECK(!primary_surface_id_.is_valid());
- window_->SetEmbedFrameSinkId(surface_info.id().frame_sink_id());
- UpdatePrimarySurfaceId();
- }
-
- // The frame sink id should never be changed.
- DCHECK_EQ(surface_info.id().frame_sink_id(), window_->GetFrameSinkId());
-
- fallback_surface_info_ = surface_info;
- UpdateClientSurfaceEmbedder();
- if (window_->delegate())
- window_->delegate()->OnFirstSurfaceActivation(fallback_surface_info_);
-}
-
void WindowPortMus::DestroyFromServer() {
std::unique_ptr<ScopedServerChange> remove_from_parent_change;
if (window_->parent()) {
@@ -408,6 +459,8 @@ WindowPortMus::ChangeSource WindowPortMus::OnTransientChildRemoved(
void WindowPortMus::AllocateLocalSurfaceId() {
local_surface_id_ = parent_local_surface_id_allocator_.GenerateId();
UpdatePrimarySurfaceId();
+ if (local_layer_tree_frame_sink_)
+ local_layer_tree_frame_sink_->SetLocalSurfaceId(local_surface_id_);
}
bool WindowPortMus::IsLocalSurfaceIdAllocationSuppressed() const {
@@ -426,6 +479,12 @@ void WindowPortMus::UpdateLocalSurfaceIdFromEmbeddedClient(
embedded_client_local_surface_id);
local_surface_id_ =
parent_local_surface_id_allocator_.GetCurrentLocalSurfaceId();
+ UpdatePrimarySurfaceId();
+
+ // OnWindowMusBoundsChanged() triggers notifying the server of the new
+ // LocalSurfaceId.
+ window_tree_client_->OnWindowMusBoundsChanged(this, window_->bounds(),
+ window_->bounds());
}
const viz::LocalSurfaceId& WindowPortMus::GetLocalSurfaceId() {
@@ -459,6 +518,7 @@ void WindowPortMus::PrepareForDestroy() {
}
void WindowPortMus::NotifyEmbeddedAppDisconnected() {
+ has_embedding_ = false;
for (WindowObserver& observer : *GetObservers(window_))
observer.OnEmbeddedAppDisconnected(window_);
}
@@ -575,20 +635,18 @@ WindowPortMus::CreateLayerTreeFrameSink() {
DCHECK_EQ(window_mus_type(), WindowMusType::LOCAL);
DCHECK(!local_layer_tree_frame_sink_);
- std::unique_ptr<cc::LayerTreeFrameSink> frame_sink;
auto client_layer_tree_frame_sink = RequestLayerTreeFrameSink(
- nullptr,
- aura::Env::GetInstance()->context_factory()->GetGpuMemoryBufferManager());
+ nullptr, window_->env()->context_factory()->GetGpuMemoryBufferManager());
local_layer_tree_frame_sink_ = client_layer_tree_frame_sink->GetWeakPtr();
- frame_sink = std::move(client_layer_tree_frame_sink);
- window_->SetEmbedFrameSinkId(GenerateFrameSinkIdFromServerId());
+ embed_frame_sink_id_ = GenerateFrameSinkIdFromServerId();
+ window_->SetEmbedFrameSinkId(embed_frame_sink_id_);
gfx::Size size_in_pixel =
gfx::ConvertSizeToPixel(GetDeviceScaleFactor(), window_->bounds().size());
// Make sure |local_surface_id_| and |last_surface_size_in_pixels_| are
// correct for the new created |local_layer_tree_frame_sink_|.
GetOrAllocateLocalSurfaceId(size_in_pixel);
- return frame_sink;
+ return client_layer_tree_frame_sink;
}
void WindowPortMus::OnEventTargetingPolicyChanged() {
@@ -599,25 +657,30 @@ bool WindowPortMus::ShouldRestackTransientChildren() {
return should_restack_transient_children_;
}
+void WindowPortMus::RegisterFrameSinkId(const viz::FrameSinkId& frame_sink_id) {
+ if (frame_sink_id == embed_frame_sink_id_)
+ return;
+
+ window_tree_client_->RegisterFrameSinkId(this, frame_sink_id);
+}
+
+void WindowPortMus::UnregisterFrameSinkId(
+ const viz::FrameSinkId& frame_sink_id) {
+ if (frame_sink_id == embed_frame_sink_id_)
+ return;
+
+ window_tree_client_->UnregisterFrameSinkId(this);
+}
+
void WindowPortMus::UpdatePrimarySurfaceId() {
- if (window_mus_type() != WindowMusType::EMBED_IN_OWNER &&
- window_mus_type() != WindowMusType::LOCAL) {
+ if (window_mus_type() != WindowMusType::LOCAL)
return;
- }
if (!window_->IsEmbeddingClient() || !local_surface_id_.is_valid())
return;
primary_surface_id_ =
viz::SurfaceId(window_->GetFrameSinkId(), local_surface_id_);
- UpdateClientSurfaceEmbedder();
-}
-
-void WindowPortMus::UpdateClientSurfaceEmbedder() {
- if (window_mus_type() != WindowMusType::EMBED_IN_OWNER &&
- window_mus_type() != WindowMusType::LOCAL) {
- return;
- }
if (!client_surface_embedder_) {
client_surface_embedder_ = std::make_unique<ClientSurfaceEmbedder>(
@@ -625,7 +688,7 @@ void WindowPortMus::UpdateClientSurfaceEmbedder() {
}
client_surface_embedder_->SetPrimarySurfaceId(primary_surface_id_);
- client_surface_embedder_->SetFallbackSurfaceInfo(fallback_surface_info_);
+ client_surface_embedder_->UpdateSizeAndGutters();
}
} // namespace aura
diff --git a/chromium/ui/aura/mus/window_port_mus.h b/chromium/ui/aura/mus/window_port_mus.h
index e6ec469c098..428b05a2732 100644
--- a/chromium/ui/aura/mus/window_port_mus.h
+++ b/chromium/ui/aura/mus/window_port_mus.h
@@ -45,7 +45,6 @@ namespace aura {
class ClientSurfaceEmbedder;
class PropertyConverter;
class Window;
-class WindowPortMusTest;
class WindowTreeClient;
class WindowTreeClientPrivate;
class WindowTreeHostMus;
@@ -87,7 +86,7 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus {
void SetCanAcceptDrops(bool can_accept_drops);
// See description in mojom for details on this.
- void SetHitTestMask(const base::Optional<gfx::Rect>& mask);
+ void SetHitTestInsets(const gfx::Insets& mouse, const gfx::Insets& touch);
// Embeds a new client in this Window. See WindowTreeClient::Embed() for
// details on arguments.
@@ -106,7 +105,7 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus {
viz::FrameSinkId GenerateFrameSinkIdFromServerId() const;
private:
- friend class WindowPortMusTest;
+ friend class WindowPortMusTestHelper;
friend class WindowTreeClient;
friend class WindowTreeClientPrivate;
friend class WindowTreeHostMus;
@@ -116,7 +115,7 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus {
// Changes to the underlying Window originating from the server must be done
// in such a way that the same change is not applied back to the server. To
- // accomplish this every changes from the server is associated with at least
+ // accomplish this every change from the server is associated with at least
// one ServerChange. If the underlying Window ends up calling back to this
// class and the change is expected then the change is ignored and not sent to
// the server. For example, here's the flow when the server changes the
@@ -221,6 +220,16 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus {
ServerChanges::iterator FindChangeByTypeAndData(const ServerChangeType type,
const ServerChangeData& data);
+ // Called to setup state necessary for an embedding. Returns false if an
+ // embedding is not allowed in this window.
+ bool PrepareForEmbed();
+
+ // Called from OnEmbed() with the result of the embedding. |real_callback| is
+ // the callback supplied to the embed call.
+ static void OnEmbedAck(base::WeakPtr<WindowPortMus> window,
+ ws::mojom::WindowTree::EmbedCallback real_callback,
+ bool result);
+
PropertyConverter* GetPropertyConverter();
// WindowMus:
@@ -245,7 +254,6 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus {
const gfx::Size& surface_size_in_pixels) override;
void UpdateLocalSurfaceIdFromEmbeddedClient(
const viz::LocalSurfaceId& embedded_client_local_surface_id) override;
- void SetFallbackSurfaceInfo(const viz::SurfaceInfo& surface_info) override;
void DestroyFromServer() override;
void AddTransientChildFromServer(WindowMus* child) override;
void RemoveTransientChildFromServer(WindowMus* child) override;
@@ -285,9 +293,10 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus {
const viz::LocalSurfaceId& GetLocalSurfaceId() override;
void OnEventTargetingPolicyChanged() override;
bool ShouldRestackTransientChildren() override;
+ void RegisterFrameSinkId(const viz::FrameSinkId& frame_sink_id) override;
+ void UnregisterFrameSinkId(const viz::FrameSinkId& frame_sink_id) override;
void UpdatePrimarySurfaceId();
- void UpdateClientSurfaceEmbedder();
WindowTreeClient* window_tree_client_;
@@ -300,7 +309,6 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus {
ServerChanges server_changes_;
viz::SurfaceId primary_surface_id_;
- viz::SurfaceInfo fallback_surface_info_;
viz::LocalSurfaceId local_surface_id_;
// TODO(sad, fsamuel): For 'mash' mode, where the embedder is responsible for
@@ -311,9 +319,15 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus {
ui::CursorData cursor_;
+ // Set if this class calls SetEmbedFrameSinkId() on the associated window.
+ viz::FrameSinkId embed_frame_sink_id_;
+
// See description in single place that changes the value for details.
bool should_restack_transient_children_ = true;
+ // True if this window has an embedding.
+ bool has_embedding_ = false;
+
// When a frame sink is created
// for a local aura::Window, we need keep a weak ptr of it, so we can update
// the local surface id when necessary.
diff --git a/chromium/ui/aura/mus/window_port_mus_unittest.cc b/chromium/ui/aura/mus/window_port_mus_unittest.cc
index 0e05b5886d5..fe616b2dc28 100644
--- a/chromium/ui/aura/mus/window_port_mus_unittest.cc
+++ b/chromium/ui/aura/mus/window_port_mus_unittest.cc
@@ -7,26 +7,16 @@
#include "cc/mojo_embedder/async_layer_tree_frame_sink.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/mus/client_surface_embedder.h"
+#include "ui/aura/test/aura_mus_test_base.h"
#include "ui/aura/test/aura_test_base.h"
+#include "ui/aura/test/mus/test_window_tree.h"
+#include "ui/aura/test/mus/window_port_mus_test_helper.h"
#include "ui/aura/window.h"
#include "ui/base/ui_base_features.h"
namespace aura {
-class WindowPortMusTest : public test::AuraTestBase {
- public:
- WindowPortMusTest() { EnableMusWithTestWindowTree(); }
-
- ~WindowPortMusTest() override = default;
-
- base::WeakPtr<cc::LayerTreeFrameSink> GetFrameSinkFor(Window* window) {
- auto* window_mus = WindowPortMus::Get(window);
- return window_mus->local_layer_tree_frame_sink_;
- }
-
- private:
- DISALLOW_COPY_AND_ASSIGN(WindowPortMusTest);
-};
+using WindowPortMusTest = test::AuraMusClientTestBase;
// TODO(sadrul): https://crbug.com/842361.
TEST_F(WindowPortMusTest,
@@ -45,7 +35,7 @@ TEST_F(WindowPortMusTest,
window.CreateLayerTreeFrameSink());
EXPECT_TRUE(frame_sink.get());
- auto mus_frame_sink = GetFrameSinkFor(&window);
+ auto mus_frame_sink = WindowPortMusTestHelper(&window).GetFrameSink();
ASSERT_TRUE(mus_frame_sink);
auto frame_sink_local_surface_id =
static_cast<cc::mojo_embedder::AsyncLayerTreeFrameSink*>(
@@ -71,4 +61,46 @@ TEST_F(WindowPortMusTest, ClientSurfaceEmbedderUpdatesLayer) {
EXPECT_EQ(local_surface_id, primary_surface_id.local_surface_id());
}
+TEST_F(WindowPortMusTest,
+ UpdateLocalSurfaceIdFromEmbeddedClientUpdateClientSurfaceEmbedder) {
+ Window window(nullptr);
+ window.Init(ui::LAYER_NOT_DRAWN);
+ window.set_owned_by_parent(false);
+ window.SetBounds(gfx::Rect(300, 300));
+ // Simulate an embedding.
+ window.SetEmbedFrameSinkId(viz::FrameSinkId(0, 1));
+ root_window()->AddChild(&window);
+
+ // AckAllChanges() so that can verify a bounds change happens from
+ // UpdateLocalSurfaceIdFromEmbeddedClient().
+ window_tree()->AckAllChanges();
+
+ // Update the LocalSurfaceId.
+ viz::LocalSurfaceId current_id = window.GetSurfaceId().local_surface_id();
+ ASSERT_TRUE(current_id.is_valid());
+ viz::ParentLocalSurfaceIdAllocator* parent_allocator =
+ WindowPortMusTestHelper(&window).GetParentLocalSurfaceIdAllocator();
+ parent_allocator->Reset(current_id);
+ viz::LocalSurfaceId updated_id = parent_allocator->GenerateId();
+ ASSERT_TRUE(updated_id.is_valid());
+ EXPECT_NE(updated_id, current_id);
+ window.UpdateLocalSurfaceIdFromEmbeddedClient(updated_id);
+
+ // Updating the LocalSurfaceId should propagate to the ClientSurfaceEmbedder.
+ auto* window_mus = WindowPortMus::Get(&window);
+ ASSERT_TRUE(window_mus);
+ ASSERT_TRUE(window_mus->client_surface_embedder());
+ EXPECT_EQ(updated_id, window_mus->client_surface_embedder()
+ ->GetPrimarySurfaceIdForTesting()
+ .local_surface_id());
+
+ // The server is notified of a bounds change, so that it sees the new
+ // LocalSurfaceId.
+ ASSERT_EQ(1u,
+ window_tree()->GetChangeCountForType(WindowTreeChangeType::BOUNDS));
+ ASSERT_TRUE(window_tree()->last_local_surface_id());
+ EXPECT_EQ(window_mus->server_id(), window_tree()->window_id());
+ EXPECT_EQ(updated_id, *(window_tree()->last_local_surface_id()));
+}
+
} // namespace aura
diff --git a/chromium/ui/aura/mus/window_tree_client.cc b/chromium/ui/aura/mus/window_tree_client.cc
index 517bd131eaf..f28829be913 100644
--- a/chromium/ui/aura/mus/window_tree_client.cc
+++ b/chromium/ui/aura/mus/window_tree_client.cc
@@ -38,6 +38,7 @@
#include "ui/aura/mus/embed_root.h"
#include "ui/aura/mus/embed_root_delegate.h"
#include "ui/aura/mus/focus_synchronizer.h"
+#include "ui/aura/mus/gesture_synchronizer.h"
#include "ui/aura/mus/in_flight_change.h"
#include "ui/aura/mus/input_method_mus.h"
#include "ui/aura/mus/mus_context_factory.h"
@@ -121,32 +122,7 @@ WindowTreeHostMus* GetWindowTreeHostMus(WindowMus* window) {
}
bool IsInternalProperty(const void* key) {
- return key == client::kModalKey || key == client::kChildModalParentKey;
-}
-
-// Create and return a MouseEvent or TouchEvent from |event| if |event| is a
-// PointerEvent, otherwise return the copy of |event|.
-std::unique_ptr<ui::Event> MapEvent(const ui::Event& event) {
- if (event.IsPointerEvent()) {
- const ui::PointerEvent& pointer_event = *event.AsPointerEvent();
- // Use a switch statement in case more pointer types are added.
- switch (pointer_event.pointer_details().pointer_type) {
- case ui::EventPointerType::POINTER_TYPE_MOUSE:
- if (event.type() == ui::ET_POINTER_WHEEL_CHANGED)
- return std::make_unique<ui::MouseWheelEvent>(pointer_event);
- return std::make_unique<ui::MouseEvent>(pointer_event);
- case ui::EventPointerType::POINTER_TYPE_TOUCH:
- case ui::EventPointerType::POINTER_TYPE_PEN:
- return std::make_unique<ui::TouchEvent>(pointer_event);
- case ui::EventPointerType::POINTER_TYPE_ERASER:
- NOTIMPLEMENTED();
- break;
- case ui::EventPointerType::POINTER_TYPE_UNKNOWN:
- NOTREACHED();
- break;
- }
- }
- return ui::Event::Clone(event);
+ return key == client::kModalKey;
}
} // namespace
@@ -273,31 +249,26 @@ void WindowTreeClient::SetImeVisibility(WindowMus* window,
tree_->SetImeVisibility(window->server_id(), visible, std::move(state));
}
-void WindowTreeClient::SetHitTestMask(
- WindowMus* window,
- const base::Optional<gfx::Rect>& mask_rect) {
+void WindowTreeClient::SetHitTestInsets(WindowMus* window,
+ const gfx::Insets& mouse,
+ const gfx::Insets& touch) {
DCHECK(tree_);
- tree_->SetHitTestMask(window->server_id(), mask_rect);
+ tree_->SetHitTestInsets(window->server_id(), mouse, touch);
}
-void WindowTreeClient::Embed(Window* window,
- ws::mojom::WindowTreeClientPtr client,
- uint32_t flags,
- ws::mojom::WindowTree::EmbedCallback callback) {
- DCHECK(tree_);
- // Window::Init() must be called before Embed() (otherwise the server hasn't
- // been told about the window).
- DCHECK(window->layer());
- if (!window->children().empty()) {
- // The window server removes all children before embedding. In other words,
- // it's generally an error to Embed() with existing children. So, fail
- // early.
- std::move(callback).Run(false);
- return;
- }
+void WindowTreeClient::RegisterFrameSinkId(
+ WindowMus* window,
+ const viz::FrameSinkId& frame_sink_id) {
+ tree_->AttachFrameSinkId(window->server_id(), frame_sink_id);
+
+ // Call OnWindowMusBoundsChanged() to force allocation of a LocalSurfaceId as
+ // well as notifying the server of the LocalSurfaceId.
+ const gfx::Rect bounds = window->GetWindow()->bounds();
+ OnWindowMusBoundsChanged(window, bounds, bounds);
+}
- tree_->Embed(WindowMus::Get(window)->server_id(), std::move(client), flags,
- std::move(callback));
+void WindowTreeClient::UnregisterFrameSinkId(WindowMus* window) {
+ tree_->UnattachFrameSinkId(window->server_id());
}
void WindowTreeClient::ScheduleEmbed(
@@ -306,27 +277,6 @@ void WindowTreeClient::ScheduleEmbed(
tree_->ScheduleEmbed(std::move(client), std::move(callback));
}
-void WindowTreeClient::EmbedUsingToken(
- Window* window,
- const base::UnguessableToken& token,
- uint32_t flags,
- ws::mojom::WindowTree::EmbedCallback callback) {
- DCHECK(tree_);
- // Window::Init() must be called before Embed() (otherwise the server hasn't
- // been told about the window).
- DCHECK(window->layer());
- if (!window->children().empty()) {
- // The window server removes all children before embedding. In other words,
- // it's generally an error to Embed() with existing children. So, fail
- // early.
- std::move(callback).Run(false);
- return;
- }
-
- tree_->EmbedUsingToken(WindowMus::Get(window)->server_id(), token, flags,
- std::move(callback));
-}
-
void WindowTreeClient::AttachCompositorFrameSink(
ws::Id window_id,
viz::mojom::CompositorFrameSinkRequest compositor_frame_sink,
@@ -413,7 +363,9 @@ WindowMus* WindowTreeClient::GetWindowByServerId(ws::Id id) {
bool WindowTreeClient::IsWindowKnown(aura::Window* window) {
WindowMus* window_mus = WindowMus::Get(window);
- return windows_.count(window_mus->server_id()) > 0;
+ // NOTE: this function explicitly checks for a null WindowMus as it may be
+ // called from global observers that may see other types.
+ return window_mus && windows_.count(window_mus->server_id()) > 0;
}
InFlightChange* WindowTreeClient::GetOldestInFlightChangeMatching(
@@ -584,6 +536,7 @@ void WindowTreeClient::WindowTreeConnectionEstablished(
drag_drop_controller_ = std::make_unique<DragDropControllerMus>(this, tree_);
capture_synchronizer_ = std::make_unique<CaptureSynchronizer>(this, tree_);
focus_synchronizer_ = std::make_unique<FocusSynchronizer>(this, tree_);
+ gesture_synchronizer_ = std::make_unique<GestureSynchronizer>(tree_);
}
void WindowTreeClient::OnConnectionLost() {
@@ -601,18 +554,6 @@ bool WindowTreeClient::HandleInternalPropertyChanged(WindowMus* window,
window->GetWindow()->GetProperty(client::kModalKey));
return true;
}
- if (key == client::kChildModalParentKey) {
- const uint32_t change_id =
- ScheduleInFlightChange(std::make_unique<CrashInFlightChange>(
- window, ChangeType::CHILD_MODAL_PARENT));
- Window* child_modal_parent =
- window->GetWindow()->GetProperty(client::kChildModalParentKey);
- tree_->SetChildModalParent(
- change_id, window->server_id(),
- child_modal_parent ? WindowMus::Get(child_modal_parent)->server_id()
- : kInvalidServerId);
- return true;
- }
return false;
}
@@ -736,16 +677,17 @@ void WindowTreeClient::ScheduleInFlightBoundsChange(
ScheduleInFlightChange(std::make_unique<InFlightBoundsChange>(
this, window, old_bounds, window->GetLocalSurfaceId()));
base::Optional<viz::LocalSurfaceId> local_surface_id;
- if (window->window_mus_type() == WindowMusType::EMBED_IN_OWNER ||
+ if (window->GetWindow()->IsEmbeddingClient() ||
window->HasLocalLayerTreeFrameSink()) {
// Do not use ConvertRectToPixel, enclosing rects cause problems.
const gfx::Size size = gfx::ScaleToCeiledSize(
new_bounds.size(), window->GetDeviceScaleFactor());
local_surface_id = window->GetOrAllocateLocalSurfaceId(size);
// |window_tree_host| may be null if this is called during creation of
- // the window associated with the WindowTreeHostMus.
+ // the window associated with the WindowTreeHostMus, or if there is an
+ // embedding.
WindowTreeHost* window_tree_host = window->GetWindow()->GetHost();
- if (window_tree_host)
+ if (window_tree_host && window_tree_host->window() == window->GetWindow())
window_tree_host->compositor()->OnChildResizing();
}
tree_->SetWindowBounds(change_id, window->server_id(), new_bounds,
@@ -904,13 +846,24 @@ void WindowTreeClient::OnWindowMusPropertyChanged(
WindowPortPropertyDataMus* data_mus =
static_cast<WindowPortPropertyDataMus*>(data.get());
+ PropertyConverter* property_converter = delegate_->GetPropertyConverter();
std::string transport_name;
std::unique_ptr<std::vector<uint8_t>> transport_value;
- if (!delegate_->GetPropertyConverter()->ConvertPropertyForTransport(
+ if (!property_converter->ConvertPropertyForTransport(
window->GetWindow(), key, &transport_name, &transport_value)) {
return;
}
DCHECK_EQ(transport_name, data_mus->transport_name);
+ const auto* window_ptr_key = static_cast<const WindowProperty<Window*>*>(key);
+ if (property_converter->IsWindowPtrPropertyRegistered(window_ptr_key)) {
+ DCHECK(!transport_value);
+ Window* value = window->GetWindow()->GetProperty(window_ptr_key);
+ WindowMus* window_mus = WindowMus::Get(value);
+ if (window_mus) {
+ transport_value = std::make_unique<std::vector<uint8_t>>(
+ mojo::ConvertTo<std::vector<uint8_t>>(window_mus->server_id()));
+ }
+ }
base::Optional<std::vector<uint8_t>> transport_value_mojo;
if (transport_value)
@@ -1273,6 +1226,14 @@ void WindowTreeClient::OnWindowOpacityChanged(ws::Id window_id,
window->SetOpacityFromServer(new_opacity);
}
+void WindowTreeClient::OnWindowDisplayChanged(ws::Id window_id,
+ int64_t display_id) {
+ WindowMus* window = GetWindowByServerId(window_id);
+ if (!window)
+ return;
+ GetWindowTreeHostMus(window->GetWindow())->set_display_id(display_id);
+}
+
void WindowTreeClient::OnWindowParentDrawnStateChanged(ws::Id window_id,
bool drawn) {
// TODO: route to WindowTreeHost.
@@ -1311,10 +1272,22 @@ void WindowTreeClient::OnWindowInputEvent(uint32_t event_id,
DCHECK(event);
WindowMus* window = GetWindowByServerId(window_id); // May be null.
+ DCHECK(!event->IsPointerEvent());
+
if (matches_pointer_watcher && has_pointer_watcher_) {
- DCHECK(event->IsPointerEvent());
- std::unique_ptr<ui::Event> event_in_dip(ui::Event::Clone(*event));
- NotifyPointerEventObserved(event_in_dip->AsPointerEvent(), display_id,
+ // TODO(sky): remove this once PointerWatcher doesn't need PointerEvent.
+ // https://crbug.com/865781
+ std::unique_ptr<ui::Event> pointer_event;
+ if (event->IsMouseEvent()) {
+ pointer_event =
+ std::make_unique<ui::PointerEvent>(*event->AsMouseEvent());
+ } else if (event->IsTouchEvent()) {
+ pointer_event =
+ std::make_unique<ui::PointerEvent>(*event->AsTouchEvent());
+ } else {
+ NOTREACHED();
+ }
+ NotifyPointerEventObserved(pointer_event->AsPointerEvent(), display_id,
window);
}
@@ -1323,13 +1296,10 @@ void WindowTreeClient::OnWindowInputEvent(uint32_t event_id,
if (!window || !window->GetWindow()->GetHost()) {
EnvInputStateController* env_controller =
Env::GetInstance()->env_controller();
- std::unique_ptr<ui::Event> mapped_event = MapEvent(*event.get());
- if (mapped_event->IsMouseEvent()) {
- env_controller->UpdateStateForMouseEvent(nullptr,
- *mapped_event->AsMouseEvent());
- } else if (mapped_event->IsTouchEvent()) {
- env_controller->UpdateStateForTouchEvent(*mapped_event->AsTouchEvent());
- }
+ if (event->IsMouseEvent())
+ env_controller->UpdateStateForMouseEvent(nullptr, *event->AsMouseEvent());
+ else if (event->IsTouchEvent())
+ env_controller->UpdateStateForTouchEvent(*event->AsTouchEvent());
tree_->OnWindowInputEventAck(event_id, ws::mojom::EventResult::UNHANDLED);
return;
}
@@ -1343,10 +1313,6 @@ void WindowTreeClient::OnWindowInputEvent(uint32_t event_id,
}
}
- // TODO(moshayedi): crbug.com/617222. No need to convert to ui::MouseEvent or
- // ui::TouchEvent once we have proper support for pointer events.
- std::unique_ptr<ui::Event> mapped_event = MapEvent(*event.get());
- ui::Event* event_to_dispatch = mapped_event.get();
// |ack_handler| may use |event_to_dispatch| from its destructor, so it needs
// to be destroyed after |event_to_dispatch| is destroyed.
EventAckHandler ack_handler(CreateEventResultCallback(event_id));
@@ -1354,12 +1320,12 @@ void WindowTreeClient::OnWindowInputEvent(uint32_t event_id,
if (!event->IsKeyEvent()) {
// Set |window| as the target, except for key events. Key events go to the
// focused window, which may have changed by the time we process the event.
- ui::Event::DispatcherApi(event_to_dispatch).set_target(window->GetWindow());
+ ui::Event::DispatcherApi(event.get()).set_target(window->GetWindow());
}
- GetWindowTreeHostMus(window)->SendEventToSink(event_to_dispatch);
+ GetWindowTreeHostMus(window)->SendEventToSink(event.get());
- ack_handler.set_handled(event_to_dispatch->handled());
+ ack_handler.set_handled(event->handled());
}
void WindowTreeClient::OnPointerEventObserved(std::unique_ptr<ui::Event> event,
@@ -1397,21 +1363,6 @@ void WindowTreeClient::OnWindowCursorChanged(ws::Id window_id,
window->SetCursorFromServer(cursor);
}
-void WindowTreeClient::OnWindowSurfaceChanged(
- ws::Id window_id,
- const viz::SurfaceInfo& surface_info) {
- WindowMus* window = GetWindowByServerId(window_id);
- if (!window)
- return;
-
- // If the parent is informed of a child's surface then that surface ID is
- // guaranteed to be available in the display compositor so we set it as the
- // fallback. If surface synchronization is enabled, the primary SurfaceInfo
- // is created by the embedder, and the LocalSurfaceId is allocated by the
- // embedder.
- window->SetFallbackSurfaceInfo(surface_info);
-}
-
void WindowTreeClient::OnDragDropStart(
const base::flat_map<std::string, std::vector<uint8_t>>& mime_data) {
drag_drop_controller_->OnDragDropStart(mojo::FlatMapToMap(mime_data));
@@ -1605,13 +1556,6 @@ void WindowTreeClient::OnWindowTreeHostStackAtTop(
tree_->StackAtTop(change_id, window->server_id());
}
-void WindowTreeClient::OnWindowTreeHostPerformWmAction(
- WindowTreeHostMus* window_tree_host,
- const std::string& action) {
- WindowMus* window = WindowMus::Get(window_tree_host->window());
- tree_->PerformWmAction(window->server_id(), action);
-}
-
void WindowTreeClient::OnWindowTreeHostPerformWindowMove(
WindowTreeHostMus* window_tree_host,
ws::mojom::MoveLoopSource source,
diff --git a/chromium/ui/aura/mus/window_tree_client.h b/chromium/ui/aura/mus/window_tree_client.h
index f4d0931ed3e..9183c781309 100644
--- a/chromium/ui/aura/mus/window_tree_client.h
+++ b/chromium/ui/aura/mus/window_tree_client.h
@@ -61,6 +61,7 @@ class DragDropControllerMus;
class EmbedRoot;
class EmbedRootDelegate;
class FocusSynchronizer;
+class GestureSynchronizer;
class InFlightBoundsChange;
class InFlightChange;
class InFlightFocusChange;
@@ -136,20 +137,14 @@ class AURA_EXPORT WindowTreeClient
void SetImeVisibility(WindowMus* window,
bool visible,
ui::mojom::TextInputStatePtr state);
- void SetHitTestMask(WindowMus* window, const base::Optional<gfx::Rect>& rect);
-
- // Embeds a new client in |window|. |flags| is a bitmask of the values defined
- // by kEmbedFlag*; 0 gives default behavior. |callback| is called to indicate
- // whether the embedding succeeded or failed and may be called immediately if
- // the embedding is known to fail.
- void Embed(Window* window,
- ws::mojom::WindowTreeClientPtr client,
- uint32_t flags,
- ws::mojom::WindowTree::EmbedCallback callback);
- void EmbedUsingToken(Window* window,
- const base::UnguessableToken& token,
- uint32_t flags,
- ws::mojom::WindowTree::EmbedCallback callback);
+ void SetHitTestInsets(WindowMus* window,
+ const gfx::Insets& mouse,
+ const gfx::Insets& touch);
+
+ // See WindowPort for details on these.
+ void RegisterFrameSinkId(WindowMus* window,
+ const viz::FrameSinkId& child_frame_sink_id);
+ void UnregisterFrameSinkId(WindowMus* window);
// Schedules an embed of a client. See
// ws::mojom::WindowTreeClient::ScheduleEmbed() for details.
@@ -177,6 +172,17 @@ class AURA_EXPORT WindowTreeClient
ws::mojom::MoveLoopSource source,
aura::Window* initial_target);
+ // See mojom for details.
+ template <typename Interface>
+ mojo::AssociatedInterfacePtr<Interface> BindWindowManagerInterface() {
+ ws::mojom::WindowManagerAssociatedPtr interface_ptr;
+ tree_->BindWindowManagerInterface(Interface::Name_,
+ mojo::MakeRequest(&interface_ptr));
+ return mojo::AssociatedInterfacePtr<Interface>(
+ mojo::AssociatedInterfacePtrInfo<Interface>(
+ interface_ptr.PassInterface().PassHandle(), Interface::Version_));
+ }
+
// Returns true if the specified window was created by this client.
bool WasCreatedByThisClient(const WindowMus* window) const;
@@ -403,6 +409,7 @@ class AURA_EXPORT WindowTreeClient
void OnWindowOpacityChanged(ws::Id window_id,
float old_opacity,
float new_opacity) override;
+ void OnWindowDisplayChanged(ws::Id window_id, int64_t display_id) override;
void OnWindowParentDrawnStateChanged(ws::Id window_id, bool drawn) override;
void OnWindowSharedPropertyChanged(
ws::Id window_id,
@@ -418,8 +425,6 @@ class AURA_EXPORT WindowTreeClient
int64_t display_id) override;
void OnWindowFocused(ws::Id focused_window_id) override;
void OnWindowCursorChanged(ws::Id window_id, ui::CursorData cursor) override;
- void OnWindowSurfaceChanged(ws::Id window_id,
- const viz::SurfaceInfo& surface_info) override;
void OnDragDropStart(const base::flat_map<std::string, std::vector<uint8_t>>&
mime_data) override;
void OnDragEnter(ws::Id window_id,
@@ -469,8 +474,6 @@ class AURA_EXPORT WindowTreeClient
void OnWindowTreeHostStackAbove(WindowTreeHostMus* window_tree_host,
Window* window) override;
void OnWindowTreeHostStackAtTop(WindowTreeHostMus* window_tree_host) override;
- void OnWindowTreeHostPerformWmAction(WindowTreeHostMus* window_tree_host,
- const std::string& action) override;
void OnWindowTreeHostPerformWindowMove(
WindowTreeHostMus* window_tree_host,
ws::mojom::MoveLoopSource mus_source,
@@ -526,6 +529,8 @@ class AURA_EXPORT WindowTreeClient
std::unique_ptr<FocusSynchronizer> focus_synchronizer_;
+ std::unique_ptr<GestureSynchronizer> gesture_synchronizer_;
+
mojo::Binding<ws::mojom::WindowTreeClient> binding_;
ws::mojom::WindowTreePtr tree_ptr_;
// Typically this is the value contained in |tree_ptr_|, but tests may
diff --git a/chromium/ui/aura/mus/window_tree_client_unittest.cc b/chromium/ui/aura/mus/window_tree_client_unittest.cc
index e8c841cb632..2ca4cce0c21 100644
--- a/chromium/ui/aura/mus/window_tree_client_unittest.cc
+++ b/chromium/ui/aura/mus/window_tree_client_unittest.cc
@@ -39,6 +39,7 @@
#include "ui/aura/mus/window_tree_host_mus_init_params.h"
#include "ui/aura/test/aura_mus_test_base.h"
#include "ui/aura/test/mus/test_window_tree.h"
+#include "ui/aura/test/mus/window_port_mus_test_helper.h"
#include "ui/aura/test/mus/window_tree_client_private.h"
#include "ui/aura/test/test_screen.h"
#include "ui/aura/test/test_window_delegate.h"
@@ -68,10 +69,12 @@ namespace {
DEFINE_UI_CLASS_PROPERTY_KEY(uint8_t, kTestPropertyKey1, 0);
DEFINE_UI_CLASS_PROPERTY_KEY(uint16_t, kTestPropertyKey2, 0);
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kTestPropertyKey3, false);
+DEFINE_UI_CLASS_PROPERTY_KEY(Window*, kTestPropertyKey4, nullptr);
const char kTestPropertyServerKey1[] = "test-property-server1";
const char kTestPropertyServerKey2[] = "test-property-server2";
const char kTestPropertyServerKey3[] = "test-property-server3";
+const char kTestPropertyServerKey4[] = "test-property-server4";
ws::Id server_id(Window* window) {
return window ? WindowMus::Get(window)->server_id() : 0;
@@ -113,6 +116,8 @@ void RegisterTestProperties(PropertyConverter* converter) {
converter->RegisterPrimitiveProperty(
kTestPropertyKey3, kTestPropertyServerKey3,
PropertyConverter::CreateAcceptAnyValueCallback());
+ converter->RegisterWindowPtrProperty(kTestPropertyKey4,
+ kTestPropertyServerKey4);
}
// Convert a primitive aura property value to a mus transport value.
@@ -269,11 +274,8 @@ TEST_F(WindowTreeClientTest, SetBoundsFailed) {
// reverted if the server replied that the change failed.
TEST_F(WindowTreeClientTest, SetBoundsFailedLocalSurfaceId) {
Window window(nullptr);
- // TOP_LEVEL_IN_WM and EMBED_IN_OWNER windows allocate viz::LocalSurfaceIds
- // when their sizes change.
- window.SetProperty(aura::client::kEmbedType,
- aura::client::WindowEmbedType::EMBED_IN_OWNER);
window.Init(ui::LAYER_NOT_DRAWN);
+ WindowPortMusTestHelper(&window).SimulateEmbedding();
const gfx::Rect original_bounds(window.bounds());
const gfx::Rect new_bounds(gfx::Rect(0, 0, 100, 100));
@@ -295,111 +297,29 @@ INSTANTIATE_TEST_CASE_P(/* no prefix */,
WindowTreeClientTestSurfaceSync,
::testing::Bool());
-namespace {
-
-class FirstSurfaceActivationWindowDelegate : public test::TestWindowDelegate {
- public:
- FirstSurfaceActivationWindowDelegate() = default;
- ~FirstSurfaceActivationWindowDelegate() override = default;
-
- const viz::SurfaceInfo& last_surface_info() const {
- return last_surface_info_;
- }
-
- void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override {
- last_surface_info_ = surface_info;
- }
-
- private:
- viz::SurfaceInfo last_surface_info_;
-
- DISALLOW_COPY_AND_ASSIGN(FirstSurfaceActivationWindowDelegate);
-};
-
-} // namespace
-
-// Verifies that a ClientSurfaceEmbedder is created for a window once it has
-// a bounds, and a valid FrameSinkId.
-TEST_P(WindowTreeClientTestSurfaceSync, ClientSurfaceEmbedderOnValidEmbedding) {
- FirstSurfaceActivationWindowDelegate delegate;
- Window window(&delegate);
- // EMBED_IN_OWNER windows allocate viz::LocalSurfaceIds when their sizes
- // change.
- window.SetProperty(aura::client::kEmbedType,
- aura::client::WindowEmbedType::EMBED_IN_OWNER);
+// Verifies that windows with an embedding create a ClientSurfaceEmbedder.
+TEST_P(WindowTreeClientTestSurfaceSync, ClientSurfaceEmbedderCreated) {
+ Window window(nullptr);
window.Init(ui::LAYER_NOT_DRAWN);
+ WindowPortMusTestHelper(&window).SimulateEmbedding();
// The window will allocate a viz::LocalSurfaceId once it has a bounds.
- WindowMus* window_mus = WindowMus::Get(&window);
- ASSERT_NE(nullptr, window_mus);
- EXPECT_FALSE(window_mus->GetLocalSurfaceId().is_valid());
- gfx::Rect new_bounds(gfx::Rect(0, 0, 100, 100));
- ASSERT_NE(new_bounds, window.bounds());
- window.SetBounds(new_bounds);
- EXPECT_EQ(new_bounds, window.bounds());
- EXPECT_TRUE(window_mus->GetLocalSurfaceId().is_valid());
-
- // An ClientSurfaceEmbedder isn't created UNTIL the window has a bounds and
- // a valid FrameSinkId.
WindowPortMus* window_port_mus = WindowPortMus::Get(&window);
ASSERT_NE(nullptr, window_port_mus);
+ EXPECT_FALSE(WindowMus::Get(&window)->GetLocalSurfaceId().is_valid());
+ // A ClientSurfaceEmbedder is only created once there is bounds and a
+ // FrameSinkId.
EXPECT_EQ(nullptr, window_port_mus->client_surface_embedder());
-
- // Now that the window has a valid FrameSinkId, it can embed the client in a
- // CompositorFrame.
- window_tree_client()->OnFrameSinkIdAllocated(server_id(&window),
- viz::FrameSinkId(1, 1));
- ClientSurfaceEmbedder* client_surface_embedder =
- window_port_mus->client_surface_embedder();
- ASSERT_NE(nullptr, client_surface_embedder);
- EXPECT_FALSE(delegate.last_surface_info().is_valid());
-
- // When a SurfaceInfo arrives from the window server, we use it as the
- // fallback SurfaceInfo. Here we issue the primary SurfaceId back to the
- // client lib. This should cause the gutter to go away, eliminating overdraw.
- window_tree_client()->OnWindowSurfaceChanged(
- server_id(&window),
- viz::SurfaceInfo(window_port_mus->PrimarySurfaceIdForTesting(), 1.0f,
- gfx::Size(100, 100)));
- EXPECT_TRUE(delegate.last_surface_info().is_valid());
- EXPECT_EQ(delegate.last_surface_info().id(),
- window_port_mus->PrimarySurfaceIdForTesting());
-}
-
-// Verifies that EMBED_IN_OWNER windows do not gutter.
-TEST_P(WindowTreeClientTestSurfaceSync, NoEmbedInOwnerGutter) {
- FirstSurfaceActivationWindowDelegate delegate;
- Window window(&delegate);
- // TOP_LEVEL_IN_WM and EMBED_IN_OWNER windows allocate viz::LocalSurfaceIds
- // when their sizes change.
- window.SetProperty(aura::client::kEmbedType,
- aura::client::WindowEmbedType::EMBED_IN_OWNER);
- window.Init(ui::LAYER_NOT_DRAWN);
-
- // The window will allocate a viz::LocalSurfaceId once it has a bounds.
- WindowMus* window_mus = WindowMus::Get(&window);
- ASSERT_NE(nullptr, window_mus);
- EXPECT_FALSE(window_mus->GetLocalSurfaceId().is_valid());
gfx::Rect new_bounds(gfx::Rect(0, 0, 100, 100));
ASSERT_NE(new_bounds, window.bounds());
window.SetBounds(new_bounds);
EXPECT_EQ(new_bounds, window.bounds());
- EXPECT_TRUE(window_mus->GetLocalSurfaceId().is_valid());
+ EXPECT_TRUE(WindowMus::Get(&window)->GetLocalSurfaceId().is_valid());
- // An ClientSurfaceEmbedder isn't created UNTIL the window has a bounds and
- // a valid FrameSinkId.
- WindowPortMus* window_port_mus = WindowPortMus::Get(&window);
- ASSERT_NE(nullptr, window_port_mus);
- EXPECT_EQ(nullptr, window_port_mus->client_surface_embedder());
-
- // Now that the window has a valid FrameSinkId, it can embed the client in a
- // CompositorFrame.
- window_tree_client()->OnFrameSinkIdAllocated(server_id(&window),
- viz::FrameSinkId(1, 1));
+ // Once the bounds have been set, the ClientSurfaceEmbedder should be created.
ClientSurfaceEmbedder* client_surface_embedder =
window_port_mus->client_surface_embedder();
ASSERT_NE(nullptr, client_surface_embedder);
- EXPECT_FALSE(delegate.last_surface_info().is_valid());
EXPECT_EQ(nullptr, client_surface_embedder->BottomGutterForTesting());
EXPECT_EQ(nullptr, client_surface_embedder->RightGutterForTesting());
@@ -410,11 +330,8 @@ TEST_P(WindowTreeClientTestSurfaceSync, NoEmbedInOwnerGutter) {
TEST_P(WindowTreeClientTestSurfaceSync, SetBoundsLocalSurfaceIdChanges) {
ASSERT_EQ(base::nullopt, window_tree()->last_local_surface_id());
Window window(nullptr);
- // TOP_LEVEL_IN_WM and EMBED_IN_OWNER windows allocate viz::LocalSurfaceIds
- // when their sizes change.
- window.SetProperty(aura::client::kEmbedType,
- aura::client::WindowEmbedType::EMBED_IN_OWNER);
window.Init(ui::LAYER_NOT_DRAWN);
+ WindowPortMusTestHelper(&window).SimulateEmbedding();
// Resize the window and verify that we've allocated a viz::LocalSurfaceId.
const gfx::Rect new_bounds(0, 0, 100, 100);
@@ -800,6 +717,26 @@ TEST_F(WindowTreeClientTest, SetStringProperty) {
EXPECT_EQ(example, *root_window()->GetProperty(client::kNameKey));
}
+TEST_F(WindowTreeClientTest, SetWindowPointerProperty) {
+ PropertyConverter* property_converter = GetPropertyConverter();
+ RegisterTestProperties(property_converter);
+
+ Window window(nullptr);
+ window.Init(ui::LAYER_NOT_DRAWN);
+ window.Show();
+ root_window()->SetProperty(kTestPropertyKey4, &window);
+ base::Optional<std::vector<uint8_t>> value =
+ window_tree()->GetLastPropertyValue();
+ ASSERT_TRUE(value.has_value());
+ EXPECT_EQ(WindowMus::Get(&window)->server_id(),
+ mojo::ConvertTo<ws::Id>(*value));
+ window_tree()->AckAllChanges();
+
+ root_window()->ClearProperty(kTestPropertyKey4);
+ value = window_tree()->GetLastPropertyValue();
+ EXPECT_FALSE(value.has_value());
+}
+
// Verifies visible is reverted if the server replied that the change failed.
TEST_F(WindowTreeClientTest, SetVisibleFailed) {
const bool original_visible = root_window()->TargetVisibility();
@@ -1010,13 +947,13 @@ TEST_F(WindowTreeClientTest, InputEventPointerEvent) {
const gfx::Point event_location(2, 3);
const uint32_t event_id = 1;
window_delegate.set_event_id(event_id);
- ui::PointerEvent pointer_event(
- ui::ET_POINTER_MOVED, event_location, gfx::Point(), ui::EF_NONE, 0,
- ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE, 0),
- base::TimeTicks());
+ ui::MouseEvent mouse_event(
+ ui::ET_MOUSE_MOVED, event_location, event_location, ui::EventTimeForNow(),
+ ui::EF_NONE, ui::EF_NONE,
+ ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE, 0));
window_tree_client()->OnWindowInputEvent(event_id, server_id(&child),
window_tree_host.display_id(),
- ui::Event::Clone(pointer_event), 0);
+ ui::Event::Clone(mouse_event), 0);
EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
EXPECT_EQ(ws::mojom::EventResult::HANDLED,
window_tree()->GetEventResult(event_id));
@@ -1046,13 +983,13 @@ TEST_F(WindowTreeClientTest, InputEventPen) {
const gfx::Point event_location(2, 3);
const uint32_t event_id = 1;
window_delegate.set_event_id(event_id);
- ui::PointerEvent pointer_event(
- ui::ET_POINTER_DOWN, event_location, gfx::Point(), ui::EF_NONE, 0,
- ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_PEN, 0),
- ui::EventTimeForNow());
+ ui::MouseEvent mouse_event(
+ ui::ET_MOUSE_PRESSED, event_location, event_location,
+ ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE,
+ ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_PEN, 0));
window_tree_client()->OnWindowInputEvent(event_id, server_id(&child),
window_tree_host.display_id(),
- ui::Event::Clone(pointer_event), 0);
+ ui::Event::Clone(mouse_event), 0);
// Pen event was handled.
EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
@@ -1346,14 +1283,13 @@ TEST_F(WindowTreeClientTest, InputMouseEventNoWindow) {
const gfx::Point event_location(2, 3);
uint32_t event_id = 1;
window_delegate.set_event_id(event_id);
- ui::PointerEvent pointer_event_down(
- ui::ET_POINTER_DOWN, event_location, event_location,
- ui::EF_LEFT_MOUSE_BUTTON, 0,
- ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE, 0),
- ui::EventTimeForNow());
+ ui::MouseEvent mouse_event_down(
+ ui::ET_MOUSE_PRESSED, event_location, event_location,
+ ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, 0,
+ ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE, 0));
window_tree_client()->OnWindowInputEvent(
event_id, server_id(&child), window_tree_host.display_id(),
- ui::Event::Clone(pointer_event_down), 0);
+ ui::Event::Clone(mouse_event_down), 0);
EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
EXPECT_EQ(ws::mojom::EventResult::HANDLED,
window_tree()->GetEventResult(event_id));
@@ -1366,14 +1302,13 @@ TEST_F(WindowTreeClientTest, InputMouseEventNoWindow) {
const gfx::Point event_location1(4, 5);
event_id = 2;
window_delegate.set_event_id(event_id);
- ui::PointerEvent pointer_event_up(
- ui::ET_POINTER_UP, event_location1, event_location,
- ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON,
- ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE, 0),
- ui::EventTimeForNow());
- window_tree_client()->OnWindowInputEvent(
- event_id, kInvalidServerId, window_tree_host.display_id(),
- ui::Event::Clone(pointer_event_up), 0);
+ ui::MouseEvent mouse_event_up(
+ ui::ET_MOUSE_RELEASED, event_location1, event_location,
+ ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON,
+ ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE, 0));
+ window_tree_client()->OnWindowInputEvent(event_id, kInvalidServerId,
+ window_tree_host.display_id(),
+ ui::Event::Clone(mouse_event_up), 0);
EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
// WindowTreeClient::OnWindowInputEvent cannot find a target window with
// kInvalidServerId but should use the event to update event states kept in
@@ -1410,13 +1345,12 @@ TEST_F(WindowTreeClientTest, InputTouchEventNoWindow) {
const gfx::Point event_location(2, 3);
uint32_t event_id = 1;
window_delegate.set_event_id(event_id);
- ui::PointerEvent pointer_event_down(
- ui::ET_POINTER_DOWN, event_location, gfx::Point(), 0, 0,
- ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0),
- ui::EventTimeForNow());
+ ui::TouchEvent touch_event_down(
+ ui::ET_TOUCH_PRESSED, event_location, ui::EventTimeForNow(),
+ ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
window_tree_client()->OnWindowInputEvent(
event_id, server_id(&child), window_tree_host.display_id(),
- ui::Event::Clone(pointer_event_down), 0);
+ ui::Event::Clone(touch_event_down), 0);
EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
EXPECT_EQ(ws::mojom::EventResult::HANDLED,
window_tree()->GetEventResult(event_id));
@@ -1426,13 +1360,12 @@ TEST_F(WindowTreeClientTest, InputTouchEventNoWindow) {
event_id = 2;
window_delegate.set_event_id(event_id);
- ui::PointerEvent pointer_event_up(
- ui::ET_POINTER_UP, event_location, gfx::Point(), 0, 0,
- ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0),
- ui::EventTimeForNow());
- window_tree_client()->OnWindowInputEvent(
- event_id, kInvalidServerId, window_tree_host.display_id(),
- ui::Event::Clone(pointer_event_up), 0);
+ ui::TouchEvent touch_event_up(
+ ui::ET_TOUCH_RELEASED, event_location, ui::EventTimeForNow(),
+ ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
+ window_tree_client()->OnWindowInputEvent(event_id, kInvalidServerId,
+ window_tree_host.display_id(),
+ ui::Event::Clone(touch_event_up), 0);
EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
// WindowTreeClient::OnWindowInputEvent cannot find a target window with
// kInvalidServerId but should use the event to update event states kept in
@@ -1543,12 +1476,12 @@ TEST_F(WindowTreeClientPointerObserverTest,
window_tree_client_impl()->StartPointerWatcher(false /* want_moves */);
// Simulate the server dispatching an event that also matched the observer.
- std::unique_ptr<ui::PointerEvent> pointer_event_down(new ui::PointerEvent(
- ui::ET_POINTER_DOWN, gfx::Point(), gfx::Point(), ui::EF_CONTROL_DOWN, 0,
+ ui::TouchEvent touch_event_down(
+ ui::ET_TOUCH_PRESSED, gfx::Point(), ui::EventTimeForNow(),
ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1),
- base::TimeTicks::Now()));
- window_tree_client()->OnWindowInputEvent(1, server_id(top_level), 0,
- std::move(pointer_event_down), true);
+ ui::EF_CONTROL_DOWN);
+ window_tree_client()->OnWindowInputEvent(
+ 1, server_id(top_level), 0, ui::Event::Clone(touch_event_down), true);
// Delegate sensed the event.
const ui::Event* last_event = last_event_observed();
diff --git a/chromium/ui/aura/mus/window_tree_host_mus.cc b/chromium/ui/aura/mus/window_tree_host_mus.cc
index 4714427d756..47ff9645626 100644
--- a/chromium/ui/aura/mus/window_tree_host_mus.cc
+++ b/chromium/ui/aura/mus/window_tree_host_mus.cc
@@ -146,10 +146,6 @@ void WindowTreeHostMus::StackAtTop() {
delegate_->OnWindowTreeHostStackAtTop(this);
}
-void WindowTreeHostMus::PerformWmAction(const std::string& action) {
- delegate_->OnWindowTreeHostPerformWmAction(this, action);
-}
-
void WindowTreeHostMus::PerformWindowMove(
ws::mojom::MoveLoopSource mus_source,
const gfx::Point& cursor_location,
diff --git a/chromium/ui/aura/mus/window_tree_host_mus.h b/chromium/ui/aura/mus/window_tree_host_mus.h
index c023265a716..eaafd008187 100644
--- a/chromium/ui/aura/mus/window_tree_host_mus.h
+++ b/chromium/ui/aura/mus/window_tree_host_mus.h
@@ -68,9 +68,6 @@ class AURA_EXPORT WindowTreeHostMus : public WindowTreeHostPlatform,
// windows which we might not own.
void StackAtTop();
- // Requests that the window manager perform |action| on the window.
- void PerformWmAction(const std::string& action);
-
// Tells the window manager to take control of moving the window. Returns
// true if the move wasn't canceled.
void PerformWindowMove(ws::mojom::MoveLoopSource mus_source,
diff --git a/chromium/ui/aura/mus/window_tree_host_mus_delegate.h b/chromium/ui/aura/mus/window_tree_host_mus_delegate.h
index 636d7018f35..0c17643cca5 100644
--- a/chromium/ui/aura/mus/window_tree_host_mus_delegate.h
+++ b/chromium/ui/aura/mus/window_tree_host_mus_delegate.h
@@ -54,11 +54,6 @@ class AURA_EXPORT WindowTreeHostMusDelegate {
virtual void OnWindowTreeHostStackAtTop(
WindowTreeHostMus* window_tree_host) = 0;
- // Called to signal to the window manager to take an action.
- virtual void OnWindowTreeHostPerformWmAction(
- WindowTreeHostMus* window_tree_host,
- const std::string& action) = 0;
-
// Called to start a move loop, where the window manager will take over
// moving a window during a drag.
virtual void OnWindowTreeHostPerformWindowMove(
diff --git a/chromium/ui/aura/mus/window_tree_host_mus_unittest.cc b/chromium/ui/aura/mus/window_tree_host_mus_unittest.cc
index 39a7302ed1d..90c5bc823a2 100644
--- a/chromium/ui/aura/mus/window_tree_host_mus_unittest.cc
+++ b/chromium/ui/aura/mus/window_tree_host_mus_unittest.cc
@@ -23,30 +23,4 @@ TEST_F(WindowTreeHostMusTest, UpdateClientArea) {
EXPECT_EQ(new_insets, window_tree()->last_client_area());
}
-TEST_F(WindowTreeHostMusTest, SetHitTestMask) {
- std::unique_ptr<WindowTreeHostMus> window_tree_host_mus =
- std::make_unique<WindowTreeHostMus>(
- CreateInitParamsForTopLevel(window_tree_client_impl()));
-
- EXPECT_FALSE(window_tree()->last_hit_test_mask().has_value());
- gfx::Rect mask(10, 10, 10, 10);
- WindowPortMus::Get(window_tree_host_mus->window())->SetHitTestMask(mask);
- ASSERT_TRUE(window_tree()->last_hit_test_mask().has_value());
- EXPECT_EQ(mask, window_tree()->last_hit_test_mask());
-
- WindowPortMus::Get(window_tree_host_mus->window())
- ->SetHitTestMask(base::nullopt);
- ASSERT_FALSE(window_tree()->last_hit_test_mask().has_value());
-}
-
-TEST_F(WindowTreeHostMusTest, PerformWmAction) {
- std::unique_ptr<WindowTreeHostMus> window_tree_host_mus =
- std::make_unique<WindowTreeHostMus>(
- CreateInitParamsForTopLevel(window_tree_client_impl()));
-
- const std::string test_action("test-action");
- window_tree_host_mus->PerformWmAction(test_action);
- EXPECT_EQ(test_action, window_tree()->last_wm_action());
-}
-
} // namespace aura
diff --git a/chromium/ui/aura/screen_ozone.h b/chromium/ui/aura/screen_ozone.h
index 132ea591702..7c26999f515 100644
--- a/chromium/ui/aura/screen_ozone.h
+++ b/chromium/ui/aura/screen_ozone.h
@@ -5,6 +5,8 @@
#ifndef UI_AURA_SCREEN_OZONE_H_
#define UI_AURA_SCREEN_OZONE_H_
+#include <memory>
+
#include "base/macros.h"
#include "ui/aura/aura_export.h"
#include "ui/display/screen.h"
diff --git a/chromium/ui/aura/test/ui_controls_factory_ozone.cc b/chromium/ui/aura/test/ui_controls_factory_ozone.cc
index 8538cfb0893..24ef109d467 100644
--- a/chromium/ui/aura/test/ui_controls_factory_ozone.cc
+++ b/chromium/ui/aura/test/ui_controls_factory_ozone.cc
@@ -6,12 +6,12 @@
#include "base/location.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/optional.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/ws/public/mojom/constants.mojom.h"
#include "services/ws/public/mojom/event_injector.mojom.h"
-#include "ui/aura/client/screen_position_client.h"
#include "ui/aura/env.h"
#include "ui/aura/mus/window_tree_client.h"
#include "ui/aura/test/aura_test_utils.h"
@@ -19,6 +19,8 @@
#include "ui/aura/test/ui_controls_factory_aura.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/test/ui_controls_aura.h"
+#include "ui/display/display.h"
+#include "ui/display/screen.h"
#include "ui/events/event_utils.h"
#include "ui/events/test/events_test_utils.h"
@@ -122,16 +124,19 @@ class UIControlsOzone : public ui_controls::UIControlsAura {
bool SendMouseMoveNotifyWhenDone(long screen_x,
long screen_y,
base::OnceClosure closure) override {
- gfx::Point root_location(screen_x, screen_y);
- aura::client::ScreenPositionClient* screen_position_client =
- aura::client::GetScreenPositionClient(host_->window());
- if (screen_position_client) {
- screen_position_client->ConvertPointFromScreen(host_->window(),
- &root_location);
+ // The location needs to be in display's coordinate.
+ gfx::Point display_location(screen_x, screen_y);
+ display::Display display;
+ if (!display::Screen::GetScreen()->GetDisplayWithDisplayId(
+ host_->GetDisplayId(), &display)) {
+ LOG(ERROR) << "Failed to see the display for " << host_->GetDisplayId();
+ return false;
}
+ display_location -= display.bounds().OffsetFromOrigin();
- gfx::Point host_location = root_location;
+ gfx::Point host_location = display_location;
host_->ConvertDIPToPixels(&host_location);
+ last_mouse_location_ = host_location;
ui::EventType event_type;
@@ -155,16 +160,24 @@ class UIControlsOzone : public ui_controls::UIControlsAura {
int button_state,
base::OnceClosure closure,
int accelerator_state) override {
- gfx::Point root_location = host_->window()->env()->last_mouse_location();
- aura::client::ScreenPositionClient* screen_position_client =
- aura::client::GetScreenPositionClient(host_->window());
- if (screen_position_client) {
- screen_position_client->ConvertPointFromScreen(host_->window(),
- &root_location);
- }
+ gfx::Point host_location;
+ if (last_mouse_location_.has_value()) {
+ host_location = last_mouse_location_.value();
+ } else {
+ // The location needs to be in display's coordinate.
+ gfx::Point display_location =
+ host_->window()->env()->last_mouse_location();
+ display::Display display;
+ if (!display::Screen::GetScreen()->GetDisplayWithDisplayId(
+ host_->GetDisplayId(), &display)) {
+ LOG(ERROR) << "Failed to see the display for " << host_->GetDisplayId();
+ return false;
+ }
+ display_location -= display.bounds().OffsetFromOrigin();
- gfx::Point host_location = root_location;
- host_->ConvertDIPToPixels(&host_location);
+ host_location = display_location;
+ host_->ConvertDIPToPixels(&host_location);
+ }
int changed_button_flag = 0;
@@ -219,18 +232,8 @@ class UIControlsOzone : public ui_controls::UIControlsAura {
private:
void SendEventToSink(ui::Event* event, base::OnceClosure closure) {
if (host_->window()->env()->mode() == aura::Env::Mode::MUS) {
- std::unique_ptr<ui::Event> event_to_send;
- if (event->IsMouseEvent()) {
- // WindowService expects MouseEvents as PointerEvents.
- // See http://crbug.com/617222.
- event_to_send =
- std::make_unique<ui::PointerEvent>(*event->AsMouseEvent());
- } else {
- event_to_send = ui::Event::Clone(*event);
- }
-
GetEventInjector()->InjectEvent(
- host_->GetDisplayId(), std::move(event_to_send),
+ host_->GetDisplayId(), ui::Event::Clone(*event),
base::BindOnce(&OnWindowServiceProcessedEvent, std::move(closure)));
return;
}
@@ -311,6 +314,11 @@ class UIControlsOzone : public ui_controls::UIControlsAura {
WindowTreeHost* host_;
ws::mojom::EventInjectorPtr event_injector_;
+ // The mouse location for the last SendMouseEventsNotifyWhenDone call. This is
+ // used rather than Env::last_mouse_location() as Env::last_mouse_location()
+ // is updated asynchronously with mus.
+ base::Optional<gfx::Point> last_mouse_location_;
+
// Mask of the mouse buttons currently down. This is static as it needs to
// track the state globally for all displays. A UIControlsOzone instance is
// created for each display host.
diff --git a/chromium/ui/aura/window.cc b/chromium/ui/aura/window.cc
index 3ebec72c8db..18829840094 100644
--- a/chromium/ui/aura/window.cc
+++ b/chromium/ui/aura/window.cc
@@ -92,7 +92,7 @@ Window::Window(WindowDelegate* delegate,
}
Window::~Window() {
- WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking;
+ WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_);
if (layer()->owner() == this)
layer()->CompleteAllAnimations();
@@ -160,7 +160,7 @@ Window::~Window() {
}
void Window::Init(ui::LayerType layer_type) {
- WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking;
+ WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_);
if (!port_owner_) {
port_owner_ = env_->CreateWindowPort(this);
@@ -285,7 +285,7 @@ gfx::Rect Window::GetBoundsInScreen() const {
}
void Window::SetTransform(const gfx::Transform& transform) {
- WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking;
+ WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_);
for (WindowObserver& observer : observers_)
observer.OnWindowTargetTransformChanging(this, transform);
layer()->SetTransform(transform);
@@ -308,7 +308,11 @@ void Window::SetLayoutManager(LayoutManager* layout_manager) {
std::unique_ptr<WindowTargeter> Window::SetEventTargeter(
std::unique_ptr<WindowTargeter> targeter) {
std::unique_ptr<WindowTargeter> old_targeter = std::move(targeter_);
+ if (old_targeter)
+ old_targeter->OnInstalled(nullptr);
targeter_ = std::move(targeter);
+ if (targeter_)
+ targeter_->OnInstalled(this);
return old_targeter;
}
@@ -369,7 +373,7 @@ void Window::StackChildBelow(Window* child, Window* target) {
}
void Window::AddChild(Window* child) {
- WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking;
+ WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_);
DCHECK(layer()) << "Parent has not been Init()ed yet.";
DCHECK(child->layer()) << "Child has not been Init()ed yt.";
@@ -411,7 +415,7 @@ void Window::AddChild(Window* child) {
}
void Window::RemoveChild(Window* child) {
- WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking;
+ WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_);
WindowObserver::HierarchyChangeParams params;
params.target = child;
@@ -547,6 +551,20 @@ bool Window::HasObserver(const WindowObserver* observer) const {
}
void Window::SetEventTargetingPolicy(ws::mojom::EventTargetingPolicy policy) {
+#if DCHECK_IS_ON()
+ const bool old_window_accepts_events =
+ (event_targeting_policy_ ==
+ ws::mojom::EventTargetingPolicy::TARGET_ONLY) ||
+ (event_targeting_policy_ ==
+ ws::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS);
+ const bool new_window_accepts_events =
+ (policy == ws::mojom::EventTargetingPolicy::TARGET_ONLY) ||
+ (policy == ws::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS);
+ if (new_window_accepts_events != old_window_accepts_events) {
+ DCHECK(!created_layer_tree_frame_sink_);
+ }
+#endif
+
if (event_targeting_policy_ == policy)
return;
@@ -833,7 +851,7 @@ void Window::SetVisible(bool visible) {
if (visible == layer()->GetTargetVisibility())
return; // No change.
- WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking;
+ WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_);
for (WindowObserver& observer : observers_)
observer.OnWindowVisibilityChanging(this, visible);
@@ -886,7 +904,7 @@ void Window::RemoveChildImpl(Window* child, Window* new_parent) {
if (child->OwnsLayer())
layer()->Remove(child->layer());
child->parent_ = NULL;
- Windows::iterator i = std::find(children_.begin(), children_.end(), child);
+ auto i = std::find(children_.begin(), children_.end(), child);
DCHECK(i != children_.end());
children_.erase(i);
child->OnParentChanged();
@@ -908,7 +926,7 @@ void Window::StackChildRelativeTo(Window* child,
DCHECK_EQ(this, child->parent());
DCHECK_EQ(this, target->parent());
- WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking;
+ WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_);
client::WindowStackingClient* stacking_client =
client::GetWindowStackingClient();
@@ -1074,9 +1092,7 @@ bool Window::CleanupGestureState() {
bool state_modified = false;
state_modified |= env_->gesture_recognizer()->CancelActiveTouches(this);
state_modified |= env_->gesture_recognizer()->CleanupStateForConsumer(this);
- for (Window::Windows::iterator iter = children_.begin();
- iter != children_.end();
- ++iter) {
+ for (auto iter = children_.begin(); iter != children_.end(); ++iter) {
state_modified |= (*iter)->CleanupGestureState();
}
return state_modified;
@@ -1087,6 +1103,7 @@ std::unique_ptr<cc::LayerTreeFrameSink> Window::CreateLayerTreeFrameSink() {
DCHECK(frame_sink_id_.is_valid());
DCHECK(embeds_external_client_);
DCHECK(GetLocalSurfaceId().is_valid());
+ created_layer_tree_frame_sink_ = true;
return sink;
}
@@ -1133,6 +1150,8 @@ const viz::FrameSinkId& Window::GetFrameSinkId() const {
}
void Window::SetEmbedFrameSinkId(const viz::FrameSinkId& frame_sink_id) {
+ UnregisterFrameSinkId();
+
DCHECK(frame_sink_id.is_valid());
frame_sink_id_ = frame_sink_id;
embeds_external_client_ = true;
@@ -1143,6 +1162,10 @@ bool Window::IsEmbeddingClient() const {
return embeds_external_client_;
}
+void Window::TrackOcclusionState() {
+ env_->GetWindowOcclusionTracker()->Track(this);
+}
+
bool Window::RequiresDoubleTapGestureEvents() const {
return delegate_ && delegate_->RequiresDoubleTapGestureEvents();
}
@@ -1160,7 +1183,7 @@ void Window::OnPaintLayer(const ui::PaintContext& context) {
void Window::OnLayerBoundsChanged(const gfx::Rect& old_bounds,
ui::PropertyChangeReason reason) {
- WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking;
+ WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_);
bounds_ = layer()->bounds();
@@ -1177,13 +1200,13 @@ void Window::OnLayerBoundsChanged(const gfx::Rect& old_bounds,
}
void Window::OnLayerOpacityChanged(ui::PropertyChangeReason reason) {
- WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking;
+ WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_);
for (WindowObserver& observer : observers_)
observer.OnWindowOpacitySet(this, reason);
}
void Window::OnLayerAlphaShapeChanged() {
- WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking;
+ WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_);
for (WindowObserver& observer : observers_)
observer.OnWindowAlphaShapeSet(this);
}
@@ -1191,7 +1214,7 @@ void Window::OnLayerAlphaShapeChanged() {
void Window::OnLayerTransformed(const gfx::Transform& old_transform,
ui::PropertyChangeReason reason) {
port_->OnDidChangeTransform(old_transform, layer()->transform());
- WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking;
+ WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_);
for (WindowObserver& observer : observers_)
observer.OnWindowTransformed(this, reason);
}
@@ -1246,8 +1269,18 @@ void Window::ConvertEventToTarget(ui::EventTarget* target,
static_cast<Window*>(target));
}
+gfx::PointF Window::GetScreenLocationF(const ui::LocatedEvent& event) const {
+ DCHECK_EQ(this, event.target());
+ gfx::PointF screen_location(event.root_location_f());
+ const Window* root = GetRootWindow();
+ auto* screen_position_client = aura::client::GetScreenPositionClient(root);
+ if (screen_position_client)
+ screen_position_client->ConvertPointToScreen(root, &screen_location);
+ return screen_location;
+}
+
std::unique_ptr<ui::Layer> Window::RecreateLayer() {
- WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion_tracking;
+ WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(env_);
ui::LayerAnimator* const animator = layer()->GetAnimator();
const bool was_animating_opacity =
@@ -1307,6 +1340,7 @@ void Window::RegisterFrameSinkId() {
if (auto* compositor = layer()->GetCompositor()) {
compositor->AddChildFrameSink(frame_sink_id_);
registered_frame_sink_id_ = true;
+ port_->RegisterFrameSinkId(frame_sink_id_);
}
}
@@ -1314,6 +1348,7 @@ void Window::UnregisterFrameSinkId() {
if (!registered_frame_sink_id_)
return;
registered_frame_sink_id_ = false;
+ port_->UnregisterFrameSinkId(frame_sink_id_);
if (auto* compositor = layer()->GetCompositor())
compositor->RemoveChildFrameSink(frame_sink_id_);
}
diff --git a/chromium/ui/aura/window.h b/chromium/ui/aura/window.h
index 18a6a3601e6..6175dcd10ba 100644
--- a/chromium/ui/aura/window.h
+++ b/chromium/ui/aura/window.h
@@ -95,8 +95,8 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
STACK_BELOW
};
enum class OcclusionState {
- // The window's occlusion state isn't tracked
- // (WindowOcclusionTracker::Track) or hasn't been computed yet.
+ // The window's occlusion state isn't tracked (Window::TrackOcclusionState)
+ // or hasn't been computed yet.
UNKNOWN,
// The window or one of its descendants IsVisible() [1] and:
// - Its bounds aren't completely covered by fully opaque windows [2], or,
@@ -194,9 +194,9 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// whether Show() without a Hide() has been invoked.
bool TargetVisibility() const { return visible_; }
// Returns the occlusion state of this window. Is UNKNOWN if the occlusion
- // state of this window isn't tracked (WindowOcclusionTracker::Track) or
+ // state of this window isn't tracked (Window::TrackOcclusionState) or
// hasn't been computed yet. Is stale if called within the scope of a
- // WindowOcclusionTracker::ScopedPauseOcclusionTracking.
+ // WindowOcclusionTracker::ScopedPause.
OcclusionState occlusion_state() const { return occlusion_state_; }
// Returns the window's bounds in root window's coordinates.
@@ -221,6 +221,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
std::unique_ptr<WindowTargeter> SetEventTargeter(
std::unique_ptr<WindowTargeter> targeter);
WindowTargeter* targeter() { return targeter_.get(); }
+ const WindowTargeter* targeter() const { return targeter_.get(); }
// Changes the bounds of the window. If present, the window's parent's
// LayoutManager may adjust the bounds.
@@ -430,6 +431,9 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// Returns whether this window is embedding another client.
bool IsEmbeddingClient() const;
+ // Starts occlusion state tracking.
+ void TrackOcclusionState();
+
Env* env() { return env_; }
const Env* env() const { return env_; }
@@ -558,6 +562,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
ui::EventTargeter* GetEventTargeter() override;
void ConvertEventToTarget(ui::EventTarget* target,
ui::LocatedEvent* event) override;
+ gfx::PointF GetScreenLocationF(const ui::LocatedEvent& event) const override;
// Updates the layer name based on the window's name and id.
void UpdateLayerName();
@@ -572,6 +577,8 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
bool registered_frame_sink_id_ = false;
bool disable_frame_sink_id_registration_ = false;
+ bool created_layer_tree_frame_sink_ = false;
+
// Window owns its corresponding WindowPort, but the ref is held as a raw
// pointer in |port_| so that it can still be accessed during destruction.
// This is important as deleting the WindowPort may result in trying to lookup
diff --git a/chromium/ui/aura/window_delegate.h b/chromium/ui/aura/window_delegate.h
index fae8ea9c7ee..7911cb92df7 100644
--- a/chromium/ui/aura/window_delegate.h
+++ b/chromium/ui/aura/window_delegate.h
@@ -24,10 +24,6 @@ namespace ui {
class PaintContext;
}
-namespace viz {
-class SurfaceInfo;
-}
-
namespace aura {
// Delegate interface for aura::Window.
@@ -106,10 +102,6 @@ class AURA_EXPORT WindowDelegate : public ui::EventHandler {
// above returns true.
virtual void GetHitTestMask(gfx::Path* mask) const = 0;
- // Called when a child submits a CompositorFrame to a surface with the given
- // |surface_info| for the first time.
- virtual void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) {}
-
// Returns whether the window wants to receive and handle double tap gesture
// events. Defaults to false.
virtual bool RequiresDoubleTapGestureEvents() const;
diff --git a/chromium/ui/aura/window_event_dispatcher.cc b/chromium/ui/aura/window_event_dispatcher.cc
index b5ce6203d1a..f6ea825d7e2 100644
--- a/chromium/ui/aura/window_event_dispatcher.cc
+++ b/chromium/ui/aura/window_event_dispatcher.cc
@@ -836,15 +836,19 @@ ui::EventDispatchDetails WindowEventDispatcher::DispatchHeldEvents() {
}
if (held_move_event_) {
+ // |held_move_event_| should be cleared here. Some event handler can
+ // create its own run loop on an event (e.g. WindowMove loop for
+ // tab-dragging), which means the other move events need to be processed
+ // before this OnEventFromSource() finishes. See also b/119260190.
+ std::unique_ptr<ui::LocatedEvent> event = std::move(held_move_event_);
+
// If a mouse move has been synthesized, the target location is suspect,
// so drop the held mouse event.
- if (held_move_event_->IsTouchEvent() ||
- (held_move_event_->IsMouseEvent() && !synthesize_mouse_move_)) {
- dispatching_held_event_ = held_move_event_.get();
- dispatch_details = OnEventFromSource(held_move_event_.get());
+ if (event->IsTouchEvent() ||
+ (event->IsMouseEvent() && !synthesize_mouse_move_)) {
+ dispatching_held_event_ = event.get();
+ dispatch_details = OnEventFromSource(event.get());
}
- if (!dispatch_details.dispatcher_destroyed)
- held_move_event_.reset();
}
if (!dispatch_details.dispatcher_destroyed) {
diff --git a/chromium/ui/aura/window_event_dispatcher.h b/chromium/ui/aura/window_event_dispatcher.h
index 5a9e099cf7a..c66b2a1d2a7 100644
--- a/chromium/ui/aura/window_event_dispatcher.h
+++ b/chromium/ui/aura/window_event_dispatcher.h
@@ -64,6 +64,8 @@ class AURA_EXPORT WindowEventDispatcher : public ui::EventProcessor,
WindowEventDispatcher(WindowTreeHost* host, bool are_events_in_pixels);
~WindowEventDispatcher() override;
+ bool are_events_in_pixels() const { return are_events_in_pixels_; }
+
// Stops dispatching/synthesizing mouse events.
void Shutdown();
diff --git a/chromium/ui/aura/window_event_dispatcher_unittest.cc b/chromium/ui/aura/window_event_dispatcher_unittest.cc
index 27deae028d1..fc0967392b9 100644
--- a/chromium/ui/aura/window_event_dispatcher_unittest.cc
+++ b/chromium/ui/aura/window_event_dispatcher_unittest.cc
@@ -14,6 +14,7 @@
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
+#include "base/test/bind_test_util.h"
#include "base/test/metrics/histogram_tester.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
@@ -1010,9 +1011,6 @@ class HoldPointerOnScrollHandler : public ui::test::TestEventHandler {
// Tests that touch-move events don't contribute to an in-progress scroll
// gesture if touch-move events are being held by the dispatcher.
TEST_P(WindowEventDispatcherTest, TouchMovesHeldOnScroll) {
- // TODO(sky): fails with mus. https://crbug.com/866502
- if (GetParam() == Env::Mode::MUS)
- return;
EventFilterRecorder recorder;
root_window()->AddPreTargetHandler(&recorder);
test::TestWindowDelegate delegate;
@@ -2179,6 +2177,77 @@ TEST_P(WindowEventDispatcherTest, CaptureWindowDestroyed) {
EXPECT_EQ(NULL, capture_window_tracker.capture_window());
}
+namespace {
+
+class RunLoopHandler : public ui::EventHandler {
+ public:
+ explicit RunLoopHandler(aura::Window* target)
+ : run_loop_(base::RunLoop::Type::kNestableTasksAllowed), target_(target) {
+ target_->AddPreTargetHandler(this);
+ }
+ ~RunLoopHandler() override { target_->RemovePreTargetHandler(this); }
+ int num_scroll_updates() const { return num_scroll_updates_; }
+
+ private:
+ // ui::EventHandler:
+ void OnGestureEvent(ui::GestureEvent* event) override {
+ if (event->type() != ui::ET_GESTURE_SCROLL_UPDATE)
+ return;
+ num_scroll_updates_++;
+ if (running_) {
+ run_loop_.QuitWhenIdle();
+ } else {
+ running_ = true;
+ run_loop_.Run();
+ }
+ }
+
+ base::RunLoop run_loop_;
+ bool running_ = false;
+ int num_scroll_updates_ = 0;
+
+ aura::Window* target_;
+
+ DISALLOW_COPY_AND_ASSIGN(RunLoopHandler);
+};
+
+} // namespace
+
+TEST_P(WindowEventDispatcherTest, HeldTouchMoveWithRunLoop) {
+ RunLoopHandler handler(root_window());
+
+ host()->dispatcher()->HoldPointerMoves();
+
+ gfx::Point point = root_window()->GetBoundsInScreen().CenterPoint();
+ ui::TouchEvent ev0(ui::ET_TOUCH_PRESSED, point, ui::EventTimeForNow(),
+ ui::PointerDetails());
+ DispatchEventUsingWindowDispatcher(&ev0);
+
+ point.Offset(10, 10);
+ ui::TouchEvent ev1(ui::ET_TOUCH_MOVED, point, ui::EventTimeForNow(),
+ ui::PointerDetails());
+ DispatchEventUsingWindowDispatcher(&ev1);
+ // The move event is held, so SCROLL_UPDATE does not happen yet.
+ EXPECT_EQ(0, handler.num_scroll_updates());
+
+ // ReleasePointerMoves() will post DispatchHeldEvent() asynchronously.
+ host()->dispatcher()->ReleasePointerMoves();
+ point.Offset(10, 10);
+ // Schedule another move event which should cause another SCROLL_UPDATE and
+ // quit the run_loop within the handler.
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindLambdaForTesting([&]() {
+ ui::TouchEvent ev2(ui::ET_TOUCH_MOVED, point, base::TimeTicks::Now(),
+ ui::PointerDetails());
+ DispatchEventUsingWindowDispatcher(&ev2);
+ }));
+ // Wait for both DispatchHeldEvent() and dispatch of |ev2|.
+ base::RunLoop(base::RunLoop::Type::kNestableTasksAllowed).RunUntilIdle();
+
+ // Makes sure that the run_loop ran and then ended.
+ EXPECT_EQ(2, handler.num_scroll_updates());
+}
+
class ExitMessageLoopOnMousePress : public ui::test::TestEventHandler {
public:
ExitMessageLoopOnMousePress() {}
@@ -2282,7 +2351,9 @@ class WindowEventDispatcherTestInHighDPI : public WindowEventDispatcherTest {
};
TEST_P(WindowEventDispatcherTestInHighDPI, EventLocationTransform) {
- // TODO(sky): fails with mus. https://crbug.com/866502
+ // This test is only applicable to LOCAL mode as it's setting a device scale
+ // factor and expecting events to be transformed while routing the event
+ // directly through host(). In MUS mode the window-service does the scaling.
if (GetParam() == Env::Mode::MUS)
return;
@@ -2322,9 +2393,12 @@ TEST_P(WindowEventDispatcherTestInHighDPI, EventLocationTransform) {
}
TEST_P(WindowEventDispatcherTestInHighDPI, TouchMovesHeldOnScroll) {
- // TODO(sky): fails with mus. https://crbug.com/866502
+ // This test is only applicable to LOCAL mode as it's setting a device scale
+ // factor and expecting events to be transformed while routing the event
+ // directly through host(). In MUS mode the window-service does the scaling.
if (GetParam() == Env::Mode::MUS)
return;
+
EventFilterRecorder recorder;
root_window()->AddPreTargetHandler(&recorder);
test::TestWindowDelegate delegate;
@@ -2394,9 +2468,12 @@ class TriggerNestedLoopOnRightMousePress : public ui::test::TestEventHandler {
// correctly.
TEST_P(WindowEventDispatcherTestInHighDPI,
EventsTransformedInRepostedEventTriggeredNestedLoop) {
- // TODO(sky): fails with mus. https://crbug.com/866502
+ // This test is only applicable to LOCAL mode as it's setting a device scale
+ // factor and expecting events to be transformed while routing the event
+ // directly through host(). In MUS mode the window-service does the scaling.
if (GetParam() == Env::Mode::MUS)
return;
+
std::unique_ptr<Window> window(CreateNormalWindow(1, root_window(), NULL));
// Make sure the window is visible.
RunAllPendingInMessageLoop();
@@ -2851,7 +2928,9 @@ TEST_P(WindowEventDispatcherTest, TouchMovesMarkedWhenCausingScroll) {
// cursor's position in root coordinates has changed (e.g. when the displays's
// scale factor changed). Test that hover effects are properly updated.
TEST_P(WindowEventDispatcherTest, OnCursorMovedToRootLocationUpdatesHover) {
- // TODO(sky): fails with mus. https://crbug.com/866502
+ // This test is only applicable to LOCAL mode as it's setting a device scale
+ // factor and expecting events to be transformed while routing the event
+ // directly through host(). In MUS mode the window-service does the scaling.
if (GetParam() == Env::Mode::MUS)
return;
diff --git a/chromium/ui/aura/window_occlusion_tracker.cc b/chromium/ui/aura/window_occlusion_tracker.cc
index 89f7a5b412f..16a1d228990 100644
--- a/chromium/ui/aura/window_occlusion_tracker.cc
+++ b/chromium/ui/aura/window_occlusion_tracker.cc
@@ -9,6 +9,7 @@
#include "base/stl_util.h"
#include "third_party/skia/include/core/SkRect.h"
#include "third_party/skia/include/core/SkRegion.h"
+#include "ui/aura/env.h"
#include "ui/aura/window_tracker.h"
#include "ui/gfx/geometry/safe_integer_conversions.h"
#include "ui/gfx/transform.h"
@@ -32,10 +33,6 @@ constexpr ui::LayerAnimationElement::AnimatableProperties
// RenderWidgetHostViewAura. https://crbug.com/827268
constexpr int kMaxRecomputeOcclusion = 3;
-WindowOcclusionTracker* g_tracker = nullptr;
-
-int g_num_pause_occlusion_tracking = 0;
-
bool WindowOrParentHasShape(Window* window) {
if (window->layer()->alpha_shape())
return true;
@@ -112,46 +109,36 @@ bool OcclusionStatesMatch(
} // namespace
-WindowOcclusionTracker::ScopedPauseOcclusionTracking::
- ScopedPauseOcclusionTracking() {
- ++g_num_pause_occlusion_tracking;
+WindowOcclusionTracker::ScopedPause::ScopedPause(Env* env)
+ : tracker_(env->GetWindowOcclusionTracker()) {
+ ++tracker_->num_pause_occlusion_tracking_;
}
-WindowOcclusionTracker::ScopedPauseOcclusionTracking::
- ~ScopedPauseOcclusionTracking() {
- --g_num_pause_occlusion_tracking;
- DCHECK_GE(g_num_pause_occlusion_tracking, 0);
- if (g_tracker)
- g_tracker->MaybeComputeOcclusion();
+WindowOcclusionTracker::ScopedPause::~ScopedPause() {
+ --tracker_->num_pause_occlusion_tracking_;
+ DCHECK_GE(tracker_->num_pause_occlusion_tracking_, 0);
+ tracker_->MaybeComputeOcclusion();
}
void WindowOcclusionTracker::Track(Window* window) {
DCHECK(window);
DCHECK(window != window->GetRootWindow());
- if (!g_tracker)
- g_tracker = new WindowOcclusionTracker();
-
- auto insert_result = g_tracker->tracked_windows_.insert(
- {window, Window::OcclusionState::UNKNOWN});
+ auto insert_result =
+ tracked_windows_.insert({window, Window::OcclusionState::UNKNOWN});
DCHECK(insert_result.second);
- if (!window->HasObserver(g_tracker))
- window->AddObserver(g_tracker);
+ if (!window_observer_.IsObserving(window))
+ window_observer_.Add(window);
if (window->GetRootWindow())
- g_tracker->TrackedWindowAddedToRoot(window);
+ TrackedWindowAddedToRoot(window);
}
WindowOcclusionTracker::WindowOcclusionTracker() = default;
WindowOcclusionTracker::~WindowOcclusionTracker() = default;
-WindowOcclusionTracker* WindowOcclusionTracker::GetInstance() {
- DCHECK(g_tracker);
- return g_tracker;
-}
-
void WindowOcclusionTracker::MaybeComputeOcclusion() {
- if (g_num_pause_occlusion_tracking ||
+ if (num_pause_occlusion_tracking_ ||
num_times_occlusion_recomputed_in_current_step_ != 0) {
return;
}
@@ -459,9 +446,10 @@ void WindowOcclusionTracker::TrackedWindowRemovedFromRoot(Window* window) {
void WindowOcclusionTracker::RemoveObserverFromWindowAndDescendants(
Window* window) {
if (WindowIsTracked(window)) {
- DCHECK(window->HasObserver(this));
+ DCHECK(window_observer_.IsObserving(window));
} else {
- window->RemoveObserver(this);
+ if (window_observer_.IsObserving(window))
+ window_observer_.Remove(window);
window->layer()->GetAnimator()->RemoveObserver(this);
animated_windows_.erase(window);
}
@@ -470,10 +458,12 @@ void WindowOcclusionTracker::RemoveObserverFromWindowAndDescendants(
}
void WindowOcclusionTracker::AddObserverToWindowAndDescendants(Window* window) {
- if (WindowIsTracked(window))
- DCHECK(window->HasObserver(this));
- else
- window->AddObserver(this);
+ if (WindowIsTracked(window)) {
+ DCHECK(window_observer_.IsObserving(window));
+ } else {
+ DCHECK(!window_observer_.IsObserving(window));
+ window_observer_.Add(window);
+ }
for (Window* child_window : window->children())
AddObserverToWindowAndDescendants(child_window);
}
@@ -498,7 +488,7 @@ void WindowOcclusionTracker::OnWindowHierarchyChanged(
Window* const window = params.target;
Window* const root_window = window->GetRootWindow();
if (root_window && base::ContainsKey(root_windows_, root_window) &&
- !window->HasObserver(this)) {
+ !window_observer_.IsObserving(window)) {
AddObserverToWindowAndDescendants(window);
}
}
@@ -582,6 +572,7 @@ void WindowOcclusionTracker::OnWindowStackingChanged(Window* window) {
void WindowOcclusionTracker::OnWindowDestroyed(Window* window) {
DCHECK(!window->GetRootWindow() || (window == window->GetRootWindow()));
tracked_windows_.erase(window);
+ window_observer_.Remove(window);
// Animations should be completed or aborted before a window is destroyed.
DCHECK(!window->layer()->GetAnimator()->IsAnimatingOnePropertyOf(
kSkipWindowWhenPropertiesAnimated));
diff --git a/chromium/ui/aura/window_occlusion_tracker.h b/chromium/ui/aura/window_occlusion_tracker.h
index 2e6d557b31b..2b546a5a8b6 100644
--- a/chromium/ui/aura/window_occlusion_tracker.h
+++ b/chromium/ui/aura/window_occlusion_tracker.h
@@ -5,9 +5,12 @@
#ifndef UI_AURA_WINDOW_OCCLUSION_TRACKER_H_
#define UI_AURA_WINDOW_OCCLUSION_TRACKER_H_
+#include <memory>
+
#include "base/containers/flat_map.h"
#include "base/containers/flat_set.h"
#include "base/macros.h"
+#include "base/scoped_observer.h"
#include "ui/aura/aura_export.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
@@ -26,10 +29,12 @@ namespace test {
class WindowOcclusionTrackerTestApi;
}
+class Env;
+
// Notifies tracked Windows when their occlusion state change.
//
// To start tracking the occlusion state of a Window, call
-// WindowOcclusionTracker::Track().
+// aura::Window::TrackOcclusionState()
//
// A Window is occluded if its bounds and transform are not animated and one of
// these conditions is true:
@@ -43,22 +48,25 @@ class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver,
public:
// Prevents window occlusion state computations within its scope. If an event
// that could cause window occlusion states to change occurs within the scope
- // of a ScopedPauseOcclusionTracking, window occlusion state computations are
- // delayed until all ScopedPauseOcclusionTracking objects have been destroyed.
- class AURA_EXPORT ScopedPauseOcclusionTracking {
+ // of a ScopedPause, window occlusion state computations are delayed until all
+ // ScopedPause objects have been destroyed.
+ class AURA_EXPORT ScopedPause {
public:
- ScopedPauseOcclusionTracking();
- ~ScopedPauseOcclusionTracking();
+ explicit ScopedPause(Env* env);
+ ~ScopedPause();
private:
- DISALLOW_COPY_AND_ASSIGN(ScopedPauseOcclusionTracking);
+ WindowOcclusionTracker* const tracker_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedPause);
};
// Start tracking the occlusion state of |window|.
- static void Track(Window* window);
+ void Track(Window* window);
private:
friend class test::WindowOcclusionTrackerTestApi;
+ friend class Env;
+ friend std::unique_ptr<WindowOcclusionTracker>::deleter_type;
struct RootWindowState {
// Number of Windows whose occlusion state is tracked under this root
@@ -72,11 +80,8 @@ class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver,
WindowOcclusionTracker();
~WindowOcclusionTracker() override;
- static WindowOcclusionTracker* GetInstance();
-
// Recomputes the occlusion state of tracked windows under roots marked as
- // dirty in |root_windows_| if there are no active
- // ScopedPauseOcclusionTracking instance.
+ // dirty in |root_windows_| if there are no active ScopedPause instance.
void MaybeComputeOcclusion();
// Recomputes the occlusion state of |window| and its descendants.
@@ -211,6 +216,12 @@ class AURA_EXPORT WindowOcclusionTracker : public ui::LayerAnimationObserver,
// recomputed occlusion states. Always 0 when not in MaybeComputeOcclusion().
int num_times_occlusion_recomputed_in_current_step_ = 0;
+ // Counter of the current occlusion tracking pause.
+ int num_pause_occlusion_tracking_ = 0;
+
+ // Tracks the observed windows.
+ ScopedObserver<Window, WindowObserver> window_observer_{this};
+
DISALLOW_COPY_AND_ASSIGN(WindowOcclusionTracker);
};
diff --git a/chromium/ui/aura/window_occlusion_tracker_unittest.cc b/chromium/ui/aura/window_occlusion_tracker_unittest.cc
index 27caa0959a2..ee9247f9d99 100644
--- a/chromium/ui/aura/window_occlusion_tracker_unittest.cc
+++ b/chromium/ui/aura/window_occlusion_tracker_unittest.cc
@@ -76,7 +76,7 @@ class WindowOcclusionTrackerTest : public test::AuraTestBase {
window->Show();
parent = parent ? parent : root_window();
parent->AddChild(window);
- WindowOcclusionTracker::Track(window);
+ window->TrackOcclusionState();
return window;
}
@@ -958,9 +958,8 @@ TEST_F(WindowOcclusionTrackerTest, ResizeChildFromObserver) {
}
// Verify that the bounds of windows are changed multiple times within the scope
-// of a ScopedPauseOcclusionTracking, occlusion states are updated once at the
-// end of the scope.
-TEST_F(WindowOcclusionTrackerTest, ScopedPauseOcclusionTracking) {
+// of a ScopedPause, occlusion states are updated once at the end of the scope.
+TEST_F(WindowOcclusionTrackerTest, ScopedPause) {
// Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE);
@@ -977,8 +976,8 @@ TEST_F(WindowOcclusionTrackerTest, ScopedPauseOcclusionTracking) {
// Change bounds multiple times. At the end of the scope, expect window a to
// be occluded.
{
- WindowOcclusionTracker::ScopedPauseOcclusionTracking
- pause_occlusion_tracking;
+ WindowOcclusionTracker::ScopedPause pause_occlusion_tracking(
+ root_window()->env());
window_b->SetBounds(window_a->bounds());
window_a->SetBounds(gfx::Rect(0, 10, 5, 5));
window_b->SetBounds(window_a->bounds());
@@ -988,8 +987,8 @@ TEST_F(WindowOcclusionTrackerTest, ScopedPauseOcclusionTracking) {
EXPECT_FALSE(delegate_a->is_expecting_call());
}
-// Same as the previous test, but with nested ScopedPauseOcclusionTracking.
-TEST_F(WindowOcclusionTrackerTest, NestedScopedPauseOcclusionTracking) {
+// Same as the previous test, but with nested ScopedPause.
+TEST_F(WindowOcclusionTrackerTest, NestedScopedPause) {
// Create window a. Expect it to be non-occluded.
MockWindowDelegate* delegate_a = new MockWindowDelegate();
delegate_a->set_expectation(Window::OcclusionState::VISIBLE);
@@ -1006,22 +1005,22 @@ TEST_F(WindowOcclusionTrackerTest, NestedScopedPauseOcclusionTracking) {
// Change bounds multiple times. At the end of the scope, expect window a to
// be occluded.
{
- WindowOcclusionTracker::ScopedPauseOcclusionTracking
- pause_occlusion_tracking_a;
+ WindowOcclusionTracker::ScopedPause pause_occlusion_tracking_a(
+ root_window()->env());
{
- WindowOcclusionTracker::ScopedPauseOcclusionTracking
- pause_occlusion_tracking_b;
+ WindowOcclusionTracker::ScopedPause pause_occlusion_tracking_b(
+ root_window()->env());
window_b->SetBounds(window_a->bounds());
}
{
- WindowOcclusionTracker::ScopedPauseOcclusionTracking
- pause_occlusion_tracking_c;
+ WindowOcclusionTracker::ScopedPause pause_occlusion_tracking_c(
+ root_window()->env());
window_a->SetBounds(gfx::Rect(0, 10, 5, 5));
}
{
- WindowOcclusionTracker::ScopedPauseOcclusionTracking
- pause_occlusion_tracking_d;
+ WindowOcclusionTracker::ScopedPause pause_occlusion_tracking_d(
+ root_window()->env());
window_b->SetBounds(window_a->bounds());
}
@@ -1451,7 +1450,7 @@ class WindowDelegateChangingWindowVisibility : public MockWindowDelegate {
// Verify that if a window changes its visibility every time it is notified that
// its occlusion state changed, a DCHECK occurs.
TEST_F(WindowOcclusionTrackerTest, OcclusionStatesDontBecomeStable) {
- test::WindowOcclusionTrackerTestApi test_api;
+ test::WindowOcclusionTrackerTestApi test_api(root_window()->env());
// Create 2 superposed tracked windows.
MockWindowDelegate* delegate_a = new MockWindowDelegate();
@@ -1651,7 +1650,7 @@ class WindowDelegateAddingAndHidingChild : public MockWindowDelegate {
// to be recomputed.
TEST_F(WindowOcclusionTrackerTest,
HideWindowWithHiddenParentOnOcclusionChange) {
- test::WindowOcclusionTrackerTestApi test_api;
+ test::WindowOcclusionTrackerTestApi test_api(root_window()->env());
auto* delegate_a = new WindowDelegateAddingAndHidingChild(this);
delegate_a->set_expectation(Window::OcclusionState::VISIBLE);
diff --git a/chromium/ui/aura/window_port.cc b/chromium/ui/aura/window_port.cc
index a710f70587b..2c3b71651ba 100644
--- a/chromium/ui/aura/window_port.cc
+++ b/chromium/ui/aura/window_port.cc
@@ -8,6 +8,8 @@
namespace aura {
+WindowPort::WindowPort(Type type) : type_(type) {}
+
// static
WindowPort* WindowPort::Get(Window* window) {
return window ? window->port_ : nullptr;
diff --git a/chromium/ui/aura/window_port.h b/chromium/ui/aura/window_port.h
index 99f07292d6f..8e058542b48 100644
--- a/chromium/ui/aura/window_port.h
+++ b/chromium/ui/aura/window_port.h
@@ -40,8 +40,22 @@ class WindowObserver;
// Env::CreateWindowPort() is used to create the WindowPort.
class AURA_EXPORT WindowPort {
public:
+ // Corresponds to the concrete implementation of this interface.
+ enum class Type {
+ // WindowPortLocal.
+ kLocal,
+
+ // WindowPortMus.
+ kMus,
+
+ // WindowPortForShutdown.
+ kShutdown,
+ };
+
virtual ~WindowPort() {}
+ Type type() const { return type_; }
+
// Called from Window::Init().
virtual void OnPreInit(Window* window) = 0;
@@ -116,13 +130,23 @@ class AURA_EXPORT WindowPort {
// See description of function with same name in transient_window_client.
virtual bool ShouldRestackTransientChildren() = 0;
+ // Called to register/unregister an embedded FramesSinkId. This is only called
+ // if SetEmbedFrameSinkId() is called on the associated Window.
+ virtual void RegisterFrameSinkId(const viz::FrameSinkId& frame_sink_id) {}
+ virtual void UnregisterFrameSinkId(const viz::FrameSinkId& frame_sink_id) {}
+
protected:
+ explicit WindowPort(Type type);
+
// Returns the WindowPort associated with a Window.
static WindowPort* Get(Window* window);
// Returns the ObserverList of a Window.
static base::ObserverList<WindowObserver, true>::Unchecked* GetObservers(
Window* window);
+
+ private:
+ const Type type_;
};
} // namespace aura
diff --git a/chromium/ui/aura/window_port_for_shutdown.cc b/chromium/ui/aura/window_port_for_shutdown.cc
index 998764cceed..a30583c51cd 100644
--- a/chromium/ui/aura/window_port_for_shutdown.cc
+++ b/chromium/ui/aura/window_port_for_shutdown.cc
@@ -9,7 +9,8 @@
namespace aura {
-WindowPortForShutdown::WindowPortForShutdown() {}
+WindowPortForShutdown::WindowPortForShutdown()
+ : WindowPort(WindowPort::Type::kShutdown) {}
WindowPortForShutdown::~WindowPortForShutdown() {}
diff --git a/chromium/ui/aura/window_targeter.cc b/chromium/ui/aura/window_targeter.cc
index 9555a1d7373..19a77c27a51 100644
--- a/chromium/ui/aura/window_targeter.cc
+++ b/chromium/ui/aura/window_targeter.cc
@@ -10,6 +10,8 @@
#include "ui/aura/client/focus_client.h"
#include "ui/aura/client/screen_position_client.h"
#include "ui/aura/env.h"
+#include "ui/aura/mus/window_port_mus.h"
+#include "ui/aura/mus/window_tree_client.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
#include "ui/aura/window_event_dispatcher.h"
@@ -20,6 +22,14 @@
#include "ui/events/event_target_iterator.h"
namespace aura {
+namespace {
+
+bool AreInsetsEmptyOrPositive(const gfx::Insets& insets) {
+ return insets.left() >= 0 && insets.right() >= 0 && insets.top() >= 0 &&
+ insets.bottom() >= 0;
+}
+
+} // namespace
WindowTargeter::WindowTargeter() {}
WindowTargeter::~WindowTargeter() {}
@@ -60,11 +70,9 @@ void WindowTargeter::SetInsets(const gfx::Insets& mouse_extend,
if (mouse_extend_ == mouse_extend && touch_extend_ == touch_extend)
return;
- const gfx::Insets last_mouse_extend_ = mouse_extend_;
- const gfx::Insets last_touch_extend_ = touch_extend_;
mouse_extend_ = mouse_extend;
touch_extend_ = touch_extend;
- OnSetInsets(last_mouse_extend_, last_touch_extend_);
+ UpdateMusIfNecessary();
}
Window* WindowTargeter::GetPriorityTargetInRootWindow(
@@ -125,10 +133,12 @@ Window* WindowTargeter::FindTargetInRootWindow(Window* root_window,
if (consumer)
return static_cast<Window*>(consumer);
+#if defined(OS_CHROMEOS)
// If the initial touch is outside the window's display, target the root.
// This is used for bezel gesture events (eg. swiping in from screen edge).
display::Display display =
display::Screen::GetScreen()->GetDisplayNearestWindow(root_window);
+ // The window target may be null, so use the root's ScreenPositionClient.
gfx::Point screen_location = event.root_location();
if (client::GetScreenPositionClient(root_window)) {
client::GetScreenPositionClient(root_window)
@@ -136,6 +146,12 @@ Window* WindowTargeter::FindTargetInRootWindow(Window* root_window,
}
if (!display.bounds().Contains(screen_location))
return root_window;
+#else
+ // If the initial touch is outside the root window, target the root.
+ // TODO: this code is likely not necessarily and will be removed.
+ if (!root_window->bounds().Contains(event.location()))
+ return root_window;
+#endif
}
return nullptr;
@@ -189,6 +205,11 @@ ui::EventTarget* WindowTargeter::FindNextBestTarget(
return nullptr;
}
+void WindowTargeter::OnInstalled(Window* window) {
+ window_ = window;
+ UpdateMusIfNecessary();
+}
+
Window* WindowTargeter::FindTargetForLocatedEvent(Window* window,
ui::LocatedEvent* event) {
if (!window->parent()) {
@@ -278,12 +299,34 @@ bool WindowTargeter::EventLocationInsideBounds(
return false;
}
-bool WindowTargeter::ShouldUseExtendedBounds(const aura::Window* window) const {
- return true;
+bool WindowTargeter::ShouldUseExtendedBounds(const aura::Window* w) const {
+ // window() is null when this is used as the default targeter (by
+ // WindowEventDispatcher). Insets should never be set in this case, so the
+ // return should not matter.
+ if (!window()) {
+ DCHECK(mouse_extend_.IsEmpty());
+ DCHECK(touch_extend_.IsEmpty());
+ return false;
+ }
+
+ // Insets should only apply to the window. Subclasses may enforce other
+ // policies.
+ return window() == w;
}
-void WindowTargeter::OnSetInsets(const gfx::Insets& last_mouse_extend,
- const gfx::Insets& last_touch_extend) {}
+// TODO: this function should go away once https://crbug.com/879308 is fixed.
+void WindowTargeter::UpdateMusIfNecessary() {
+ if (!window_ || window_->env()->mode() != Env::Mode::MUS)
+ return;
+
+ // Negative insets are used solely to extend the hit-test region of child
+ // windows, which is not needed by code using MUS (negative insets are only
+ // used in the server).
+ if (AreInsetsEmptyOrPositive(mouse_extend_) &&
+ AreInsetsEmptyOrPositive(touch_extend_)) {
+ WindowPortMus::Get(window_)->SetHitTestInsets(mouse_extend_, touch_extend_);
+ }
+}
Window* WindowTargeter::FindTargetForKeyEvent(Window* window,
const ui::KeyEvent& key) {
diff --git a/chromium/ui/aura/window_targeter.h b/chromium/ui/aura/window_targeter.h
index 5f38c4828f8..3d251b8a37e 100644
--- a/chromium/ui/aura/window_targeter.h
+++ b/chromium/ui/aura/window_targeter.h
@@ -88,6 +88,12 @@ class AURA_EXPORT WindowTargeter : public ui::EventTargeter {
ui::Event* event) override;
protected:
+ aura::Window* window() { return window_; }
+ const aura::Window* window() const { return window_; }
+
+ // This is called by Window when the targeter is set on a window.
+ virtual void OnInstalled(Window* window);
+
// Same as FindTargetForEvent(), but used for positional events. The location
// etc. of |event| are in |window|'s coordinate system. When finding the
// target for the event, the targeter can mutate the |event| (e.g. change the
@@ -114,22 +120,26 @@ class AURA_EXPORT WindowTargeter : public ui::EventTargeter {
// Returns true if the hit testing (GetHitTestRects()) should use the
// extended bounds.
- virtual bool ShouldUseExtendedBounds(const aura::Window* window) const;
-
- // Called after the hit-test area has been extended with SetInsets(). The
- // supplied insets are the values before the call to SetInsets().
- virtual void OnSetInsets(const gfx::Insets& last_mouse_extend,
- const gfx::Insets& last_touch_extend);
+ virtual bool ShouldUseExtendedBounds(const aura::Window* w) const;
const gfx::Insets& mouse_extend() const { return mouse_extend_; }
const gfx::Insets& touch_extend() const { return touch_extend_; }
private:
+ // To call OnInstalled().
+ friend class Window;
+
+ void UpdateMusIfNecessary();
+
Window* FindTargetForKeyEvent(Window* root_window, const ui::KeyEvent& event);
Window* FindTargetForNonKeyEvent(Window* root_window, ui::Event* event);
Window* FindTargetForLocatedEventRecursively(Window* root_window,
ui::LocatedEvent* event);
+ // The Window this WindowTargeter is installed on. Null if not attached to a
+ // Window.
+ aura::Window* window_ = nullptr;
+
gfx::Insets mouse_extend_;
gfx::Insets touch_extend_;
diff --git a/chromium/ui/aura/window_targeter_unittest.cc b/chromium/ui/aura/window_targeter_unittest.cc
index daeb8529d05..1085c08c32c 100644
--- a/chromium/ui/aura/window_targeter_unittest.cc
+++ b/chromium/ui/aura/window_targeter_unittest.cc
@@ -8,7 +8,9 @@
#include "base/macros.h"
#include "ui/aura/scoped_window_targeter.h"
+#include "ui/aura/test/aura_mus_test_base.h"
#include "ui/aura/test/aura_test_base.h"
+#include "ui/aura/test/mus/test_window_tree.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/window.h"
#include "ui/display/display.h"
@@ -332,4 +334,33 @@ INSTANTIATE_TEST_CASE_P(/* no prefix */,
WindowTargeterTest,
::testing::Values(Env::Mode::LOCAL, Env::Mode::MUS));
+using WindowTargeterMus = aura::test::AuraMusClientTestBase;
+
+TEST_F(WindowTargeterMus, SetInsets) {
+ aura::Window window(nullptr);
+ window.Init(ui::LAYER_NOT_DRAWN);
+ std::unique_ptr<WindowTargeter> window_targeter_ptr =
+ std::make_unique<WindowTargeter>();
+ WindowTargeter* window_targeter = window_targeter_ptr.get();
+ window.SetEventTargeter(std::move(window_targeter_ptr));
+ const gfx::Insets insets1(1, 2, 3, 4);
+ const gfx::Insets insets2(11, 12, 13, 14);
+ window_targeter->SetInsets(insets1, insets2);
+ EXPECT_EQ(insets1, window_tree()->last_mouse_hit_test_insets());
+ EXPECT_EQ(insets2, window_tree()->last_touch_hit_test_insets());
+}
+
+TEST_F(WindowTargeterMus, SetInsetsBeforeInstall) {
+ aura::Window window(nullptr);
+ window.Init(ui::LAYER_NOT_DRAWN);
+ std::unique_ptr<WindowTargeter> window_targeter =
+ std::make_unique<WindowTargeter>();
+ const gfx::Insets insets1(1, 2, 3, 4);
+ const gfx::Insets insets2(11, 12, 13, 14);
+ window_targeter->SetInsets(insets1, insets2);
+ window.SetEventTargeter(std::move(window_targeter));
+ EXPECT_EQ(insets1, window_tree()->last_mouse_hit_test_insets());
+ EXPECT_EQ(insets2, window_tree()->last_touch_hit_test_insets());
+}
+
} // namespace aura
diff --git a/chromium/ui/aura/window_tree_host.cc b/chromium/ui/aura/window_tree_host.cc
index 4c3ea6cb9d1..eb205785534 100644
--- a/chromium/ui/aura/window_tree_host.cc
+++ b/chromium/ui/aura/window_tree_host.cc
@@ -243,7 +243,8 @@ void WindowTreeHost::SetSharedInputMethod(ui::InputMethod* input_method) {
}
ui::EventDispatchDetails WindowTreeHost::DispatchKeyEventPostIME(
- ui::KeyEvent* event) {
+ ui::KeyEvent* event,
+ base::OnceCallback<void(bool)> ack_callback) {
// If dispatch to IME is already disabled we shouldn't reach here.
DCHECK(!dispatcher_->should_skip_ime());
dispatcher_->set_skip_ime(true);
@@ -252,6 +253,7 @@ ui::EventDispatchDetails WindowTreeHost::DispatchKeyEventPostIME(
event_sink()->OnEventFromSource(event);
if (!dispatch_details.dispatcher_destroyed)
dispatcher_->set_skip_ime(false);
+ CallDispatchKeyEventPostIMEAck(event, std::move(ack_callback));
return dispatch_details;
}
@@ -300,6 +302,11 @@ WindowTreeHost::WindowTreeHost(std::unique_ptr<Window> window)
display::Screen::GetScreen()->AddObserver(this);
}
+void WindowTreeHost::IntializeDeviceScaleFactor(float device_scale_factor) {
+ DCHECK(!compositor_->root_layer()) << "Only call this before InitHost()";
+ device_scale_factor_ = device_scale_factor;
+}
+
void WindowTreeHost::DestroyCompositor() {
if (compositor_) {
compositor_->RemoveObserver(this);
@@ -442,10 +449,6 @@ ui::EventSink* WindowTreeHost::GetEventSink() {
return dispatcher_.get();
}
-void WindowTreeHost::OnDisplayAdded(const display::Display& new_display) {}
-
-void WindowTreeHost::OnDisplayRemoved(const display::Display& old_display) {}
-
void WindowTreeHost::OnDisplayMetricsChanged(const display::Display& display,
uint32_t metrics) {
if (metrics & DisplayObserver::DISPLAY_METRIC_COLOR_SPACE) {
diff --git a/chromium/ui/aura/window_tree_host.h b/chromium/ui/aura/window_tree_host.h
index d600ca4869e..8eec7d205ea 100644
--- a/chromium/ui/aura/window_tree_host.h
+++ b/chromium/ui/aura/window_tree_host.h
@@ -45,12 +45,13 @@ struct PlatformWindowInitProperties;
}
namespace aura {
-class ScopedKeyboardHook;
namespace test {
class WindowTreeHostTestApi;
}
+class Env;
+class ScopedKeyboardHook;
class WindowEventDispatcher;
class WindowTreeHostObserver;
@@ -64,9 +65,11 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate,
public:
~WindowTreeHost() override;
- // Creates a new WindowTreeHost with the specified |properties|.
+ // Creates a new WindowTreeHost with the specified |properties| and an
+ // optional |env|. If |env| is null, the default Env::GetInstance() is used.
static std::unique_ptr<WindowTreeHost> Create(
- ui::PlatformWindowInitProperties properties);
+ ui::PlatformWindowInitProperties properties,
+ Env* env = nullptr);
// Returns the WindowTreeHost for the specified accelerated widget, or NULL
// if there is none associated.
@@ -168,7 +171,9 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate,
void SetSharedInputMethod(ui::InputMethod* input_method);
// Overridden from ui::internal::InputMethodDelegate:
- ui::EventDispatchDetails DispatchKeyEventPostIME(ui::KeyEvent* event) final;
+ ui::EventDispatchDetails DispatchKeyEventPostIME(
+ ui::KeyEvent* event,
+ base::OnceCallback<void(bool)> ack_callback) final;
// Returns the id of the display. Default implementation queries Screen.
virtual int64_t GetDisplayId();
@@ -224,6 +229,10 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate,
explicit WindowTreeHost(std::unique_ptr<Window> window = nullptr);
+ // Set the cached display device scale factor. This should only be called
+ // during subclass initialization, when the value is needed before InitHost().
+ void IntializeDeviceScaleFactor(float device_scale_factor);
+
void DestroyCompositor();
void DestroyDispatcher();
@@ -273,8 +282,6 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate,
ui::EventSink* GetEventSink() override;
// display::DisplayObserver implementation.
- void OnDisplayAdded(const display::Display& new_display) override;
- void OnDisplayRemoved(const display::Display& old_display) override;
void OnDisplayMetricsChanged(const display::Display& display,
uint32_t metrics) override;
diff --git a/chromium/ui/aura/window_tree_host_platform.cc b/chromium/ui/aura/window_tree_host_platform.cc
index 76865a51750..c16bbb1477a 100644
--- a/chromium/ui/aura/window_tree_host_platform.cc
+++ b/chromium/ui/aura/window_tree_host_platform.cc
@@ -10,6 +10,7 @@
#include "base/run_loop.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
+#include "ui/aura/client/cursor_client.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
@@ -42,11 +43,12 @@ namespace aura {
// static
std::unique_ptr<WindowTreeHost> WindowTreeHost::Create(
- ui::PlatformWindowInitProperties properties) {
+ ui::PlatformWindowInitProperties properties,
+ Env* env) {
return std::make_unique<WindowTreeHostPlatform>(
std::move(properties),
std::make_unique<aura::Window>(nullptr, client::WINDOW_TYPE_UNKNOWN,
- Env::GetInstance()));
+ env ? env : Env::GetInstance()));
}
WindowTreeHostPlatform::WindowTreeHostPlatform(
@@ -215,8 +217,23 @@ void WindowTreeHostPlatform::OnDamageRect(const gfx::Rect& damage_rect) {
void WindowTreeHostPlatform::DispatchEvent(ui::Event* event) {
TRACE_EVENT0("input", "WindowTreeHostPlatform::DispatchEvent");
ui::EventDispatchDetails details = SendEventToSink(event);
- if (details.dispatcher_destroyed)
+ if (details.dispatcher_destroyed) {
event->SetHandled();
+ return;
+ }
+
+ // Reset the cursor on ET_MOUSE_EXITED, so that when the mouse re-enters the
+ // window, the cursor is updated correctly.
+ if (event->type() == ui::ET_MOUSE_EXITED) {
+ client::CursorClient* cursor_client = client::GetCursorClient(window());
+ if (cursor_client) {
+ // The cursor-change needs to happen through the CursorClient so that
+ // other external states are updated correctly, instead of just changing
+ // |current_cursor_| here.
+ cursor_client->SetCursor(ui::CursorType::kNone);
+ DCHECK_EQ(ui::CursorType::kNone, current_cursor_.native_type());
+ }
+ }
}
void WindowTreeHostPlatform::OnCloseRequest() {
diff --git a/chromium/ui/aura/window_tree_host_platform.h b/chromium/ui/aura/window_tree_host_platform.h
index 5ea1727398f..91fde9bcf2a 100644
--- a/chromium/ui/aura/window_tree_host_platform.h
+++ b/chromium/ui/aura/window_tree_host_platform.h
@@ -84,6 +84,9 @@ class AURA_EXPORT WindowTreeHostPlatform : public WindowTreeHost,
bool IsKeyLocked(ui::DomCode dom_code) override;
base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override;
+ // This function is only for test purpose.
+ gfx::NativeCursor* GetCursorNative() { return &current_cursor_; }
+
private:
gfx::AcceleratedWidget widget_;
std::unique_ptr<ui::PlatformWindow> platform_window_;
diff --git a/chromium/ui/aura/window_tree_host_unittest.cc b/chromium/ui/aura/window_tree_host_unittest.cc
index 8207d3ba42d..6d40482c6d6 100644
--- a/chromium/ui/aura/window_tree_host_unittest.cc
+++ b/chromium/ui/aura/window_tree_host_unittest.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "ui/aura/test/aura_test_base.h"
+#include "ui/aura/test/test_cursor_client.h"
#include "ui/aura/test/test_screen.h"
#include "ui/aura/test/window_event_dispatcher_test_api.h"
#include "ui/aura/window.h"
@@ -10,6 +11,7 @@
#include "ui/base/ime/input_method.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/test/draw_waiter_for_test.h"
+#include "ui/events/base_event_utils.h"
#include "ui/events/event_rewriter.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/platform_window/stub/stub_window.h"
@@ -141,12 +143,51 @@ class TestWindowTreeHost : public WindowTreeHostPlatform {
CreateCompositor();
}
+ ui::CursorType GetCursorType() { return GetCursorNative()->native_type(); }
+ void DispatchEventForTest(ui::Event* event) { DispatchEvent(event); }
+
private:
DISALLOW_COPY_AND_ASSIGN(TestWindowTreeHost);
};
+class TestCursorClient : public test::TestCursorClient {
+ public:
+ explicit TestCursorClient(aura::Window* root_window)
+ : test::TestCursorClient(root_window) {
+ window_ = root_window;
+ }
+ ~TestCursorClient() override {}
+
+ // Overridden from test::TestCursorClient:
+ void SetCursor(gfx::NativeCursor cursor) override {
+ WindowTreeHost* host = window_->GetHost();
+ if (host)
+ host->SetCursor(cursor);
+ }
+
+ private:
+ aura::Window* window_;
+ DISALLOW_COPY_AND_ASSIGN(TestCursorClient);
+};
+
TEST_F(WindowTreeHostTest, LostCaptureDuringTearDown) {
TestWindowTreeHost host;
}
+// Tests if the cursor type is reset after ET_MOUSE_EXITED event.
+TEST_F(WindowTreeHostTest, ResetCursorOnExit) {
+ TestWindowTreeHost host;
+ aura::TestCursorClient cursor_client(host.window());
+
+ // Set the cursor with the specific type to check if it's reset after
+ // ET_MOUSE_EXITED event.
+ host.SetCursorNative(ui::CursorType::kCross);
+
+ ui::MouseEvent exit_event(ui::ET_MOUSE_EXITED, gfx::Point(), gfx::Point(),
+ ui::EventTimeForNow(), 0, 0);
+
+ host.DispatchEventForTest(&exit_event);
+ EXPECT_EQ(host.GetCursorType(), ui::CursorType::kNone);
+}
+
} // namespace aura
diff --git a/chromium/ui/aura/window_unittest.cc b/chromium/ui/aura/window_unittest.cc
index a61fc13a4de..7edb1e5aced 100644
--- a/chromium/ui/aura/window_unittest.cc
+++ b/chromium/ui/aura/window_unittest.cc
@@ -1638,9 +1638,13 @@ TEST_P(WindowTest, Transform) {
}
TEST_P(WindowTest, TransformGesture) {
- // TODO(sky): fails with mus. https://crbug.com/866502
+ // This test is only applicable to LOCAL mode as it's setting a transform on
+ // host() and expecting events to be transformed while routing the event
+ // directly through host(). In MUS mode the window-service does the
+ // transformation.
if (GetParam() == Env::Mode::MUS)
return;
+
gfx::Size size = host()->GetBoundsInPixels().size();
std::unique_ptr<GestureTrackPositionDelegate> delegate(
diff --git a/chromium/ui/base/BUILD.gn b/chromium/ui/base/BUILD.gn
index 07d7594628f..1e2170ec644 100644
--- a/chromium/ui/base/BUILD.gn
+++ b/chromium/ui/base/BUILD.gn
@@ -4,6 +4,7 @@
import("//build/buildflag_header.gni")
import("//build/config/compiler/compiler.gni")
+import("//build/config/jumbo.gni")
import("//build/config/linux/pangocairo/pangocairo.gni")
import("//build/config/sanitizers/sanitizers.gni")
import("//build/config/ui.gni")
@@ -27,7 +28,7 @@ build_ime = !is_ios
#
# Introduce a standalone target that can build on both 'host' and 'target'
# toolchains that just builds the support to load datapacks. The dependencies
-# should be kept minimal to have to build too many targets with multiple
+# should be kept minimal to not have to build too many targets with multiple
# toolchains.
component("ui_data_pack") {
sources = [
@@ -45,8 +46,11 @@ component("ui_data_pack") {
defines = [ "UI_DATA_PACK_IMPLEMENTATION" ]
- # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
- configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
+ configs += [
+ # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+ "//build/config/compiler:no_size_t_to_int_warning",
+ "//build/config/compiler:wexit_time_destructors",
+ ]
}
buildflag_header("ui_features") {
@@ -57,12 +61,11 @@ buildflag_header("ui_features") {
"ENABLE_MUS=$enable_mus",
"USE_ATK=$use_atk",
"USE_XKBCOMMON=$use_xkbcommon",
- "MAC_VIEWS_BROWSER=$mac_views_browser",
"HAS_NATIVE_ACCESSIBILITY=$has_native_accessibility",
]
}
-component("base") {
+jumbo_component("base") {
output_name = "ui_base"
sources = [
@@ -88,9 +91,6 @@ component("base") {
"clipboard/clipboard_win.cc",
"clipboard/clipboard_win.h",
"clipboard/custom_data_helper_mac.mm",
- "cocoa/a11y_util.h",
- "cocoa/a11y_util.mm",
- "cocoa/accessibility_hostable.h",
"cocoa/animation_utils.h",
"cocoa/appkit_utils.h",
"cocoa/appkit_utils.mm",
@@ -102,20 +102,8 @@ component("base") {
"cocoa/command_dispatcher.mm",
"cocoa/constrained_window/constrained_window_animation.h",
"cocoa/constrained_window/constrained_window_animation.mm",
- "cocoa/controls/blue_label_button.h",
- "cocoa/controls/blue_label_button.mm",
"cocoa/controls/button_utils.h",
"cocoa/controls/button_utils.mm",
- "cocoa/controls/hover_image_menu_button.h",
- "cocoa/controls/hover_image_menu_button.mm",
- "cocoa/controls/hover_image_menu_button_cell.h",
- "cocoa/controls/hover_image_menu_button_cell.mm",
- "cocoa/controls/hyperlink_button_cell.h",
- "cocoa/controls/hyperlink_button_cell.mm",
- "cocoa/controls/hyperlink_text_view.h",
- "cocoa/controls/hyperlink_text_view.mm",
- "cocoa/controls/imageview_utils.h",
- "cocoa/controls/imageview_utils.mm",
"cocoa/controls/textfield_utils.h",
"cocoa/controls/textfield_utils.mm",
"cocoa/defaults_utils.h",
@@ -136,22 +124,16 @@ component("base") {
"cocoa/menu_controller.mm",
"cocoa/nib_loading.h",
"cocoa/nib_loading.mm",
- "cocoa/nsgraphics_context_additions.h",
- "cocoa/nsgraphics_context_additions.mm",
- "cocoa/nsview_additions.h",
- "cocoa/nsview_additions.mm",
+ "cocoa/ns_view_ids.h",
+ "cocoa/ns_view_ids.mm",
"cocoa/quartz_util.h",
"cocoa/quartz_util.mm",
"cocoa/remote_layer_api.h",
"cocoa/remote_layer_api.mm",
- "cocoa/scoped_cg_context_smooth_fonts.h",
- "cocoa/scoped_cg_context_smooth_fonts.mm",
"cocoa/secure_password_input.h",
"cocoa/secure_password_input.mm",
"cocoa/text_services_context_menu.cc",
"cocoa/text_services_context_menu.h",
- "cocoa/three_part_image.h",
- "cocoa/three_part_image.mm",
"cocoa/tool_tip_base_view.h",
"cocoa/tool_tip_base_view.mm",
"cocoa/touch_bar_forward_declarations.h",
@@ -163,8 +145,7 @@ component("base") {
"cocoa/underlay_opengl_hosting_window.h",
"cocoa/underlay_opengl_hosting_window.mm",
"cocoa/user_interface_item_command_handler.h",
- "cocoa/view_description.h",
- "cocoa/view_description.mm",
+ "cocoa/views_hostable.h",
"cocoa/weak_ptr_nsobject.h",
"cocoa/weak_ptr_nsobject.mm",
"cocoa/window_size_constants.h",
@@ -178,7 +159,6 @@ component("base") {
"cursor/cursor_type.h",
"cursor/cursor_win.cc",
"default_style.h",
- "default_theme_provider_mac.mm",
"device_form_factor.h",
"device_form_factor_android.cc",
"device_form_factor_desktop.cc",
@@ -223,6 +203,7 @@ component("base") {
"layout.h",
"material_design/material_design_controller.cc",
"material_design/material_design_controller.h",
+ "material_design/material_design_controller_observer.h",
"models/button_menu_item_model.cc",
"models/button_menu_item_model.h",
"models/combobox_model.cc",
@@ -344,7 +325,6 @@ component("base") {
"accelerators/accelerator_history.h",
"accelerators/accelerator_manager.cc",
"accelerators/accelerator_manager.h",
- "accelerators/accelerator_manager_delegate.h",
"base_window.cc",
"base_window.h",
"clipboard/clipboard.cc",
@@ -422,8 +402,11 @@ component("base") {
]
}
- # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
- configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
+ configs += [
+ # TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
+ "//build/config/compiler:no_size_t_to_int_warning",
+ "//build/config/compiler:wexit_time_destructors",
+ ]
defines = [ "UI_BASE_IMPLEMENTATION" ]
@@ -682,7 +665,7 @@ component("base") {
}
}
-static_library("test_support") {
+jumbo_static_library("test_support") {
testonly = true
sources = [
"test/material_design_controller_test_api.cc",
@@ -820,7 +803,6 @@ test("ui_base_unittests") {
"clipboard/clipboard_util_mac_unittest.mm",
"l10n/l10n_util_mac_unittest.mm",
"l10n/l10n_util_unittest.cc",
- "l10n/l10n_util_win_unittest.cc",
"l10n/time_format_unittest.cc",
"layout_unittest.cc",
"material_design/material_design_controller_unittest.cc",
@@ -873,17 +855,10 @@ test("ui_base_unittests") {
"cocoa/bubble_closer_unittest.mm",
"cocoa/cocoa_base_utils_unittest.mm",
"cocoa/constrained_window/constrained_window_animation_unittest.mm",
- "cocoa/controls/blue_label_button_unittest.mm",
- "cocoa/controls/hover_image_menu_button_unittest.mm",
- "cocoa/controls/hyperlink_button_cell_unittest.mm",
- "cocoa/controls/hyperlink_text_view_unittest.mm",
"cocoa/focus_tracker_unittest.mm",
"cocoa/hover_button_unittest.mm",
"cocoa/hover_image_button_unittest.mm",
"cocoa/menu_controller_unittest.mm",
- "cocoa/nsgraphics_context_additions_unittest.mm",
- "cocoa/nsview_additions_unittest.mm",
- "cocoa/three_part_image_unittest.mm",
"cocoa/touch_bar_util_unittest.mm",
"cocoa/tracking_area_unittest.mm",
"cocoa/weak_ptr_nsobject_unittest.mm",
@@ -912,7 +887,7 @@ test("ui_base_unittests") {
"ime/win/tsf_text_store_unittest.cc",
]
if (is_linux && use_aura && !is_chromeos) {
- if (use_x11) {
+ if (use_x11 || use_ozone) {
sources += [ "ime/input_method_auralinux_unittest.cc" ]
} else {
sources += [ "ime/input_method_minimal_unittest.cc" ]
diff --git a/chromium/ui/base/accelerators/accelerator.cc b/chromium/ui/base/accelerators/accelerator.cc
index d2f31e0add2..d56e87be04c 100644
--- a/chromium/ui/base/accelerators/accelerator.cc
+++ b/chromium/ui/base/accelerators/accelerator.cc
@@ -239,6 +239,8 @@ base::string16 Accelerator::ApplyLongFormModifiers(
shortcut = ApplyModifierToAcceleratorString(shortcut, IDS_APP_COMMAND_KEY);
#elif defined(OS_CHROMEOS)
shortcut = ApplyModifierToAcceleratorString(shortcut, IDS_APP_SEARCH_KEY);
+#elif defined(OS_WIN)
+ shortcut = ApplyModifierToAcceleratorString(shortcut, IDS_APP_WINDOWS_KEY);
#else
NOTREACHED();
#endif
diff --git a/chromium/ui/base/accelerators/accelerator.h b/chromium/ui/base/accelerators/accelerator.h
index 1ea2afeca16..f5304b8e1ae 100644
--- a/chromium/ui/base/accelerators/accelerator.h
+++ b/chromium/ui/base/accelerators/accelerator.h
@@ -38,6 +38,11 @@ class UI_BASE_EXPORT Accelerator {
};
Accelerator();
+ // |modifiers| consists of ui::EventFlags bitwise-or-ed together,
+ // for example:
+ // Accelerator(ui::VKEY_Z, ui::EF_SHIFT_DOWN | ui::EF_CONTROL_DOWN)
+ // would correspond to the shortcut "ctrl + shift + z".
+ //
// NOTE: this constructor strips out non key related flags.
Accelerator(KeyboardCode key_code,
int modifiers,
diff --git a/chromium/ui/base/accelerators/accelerator_history.h b/chromium/ui/base/accelerators/accelerator_history.h
index bc944cc9a6b..331389ae6b8 100644
--- a/chromium/ui/base/accelerators/accelerator_history.h
+++ b/chromium/ui/base/accelerators/accelerator_history.h
@@ -31,6 +31,10 @@ class UI_BASE_EXPORT AcceleratorHistory {
return previous_accelerator_;
}
+ const std::set<KeyboardCode>& currently_pressed_keys() const {
+ return currently_pressed_keys_;
+ }
+
// Stores the given |accelerator| only if it's different than the currently
// stored one.
void StoreCurrentAccelerator(const Accelerator& accelerator);
diff --git a/chromium/ui/base/accelerators/accelerator_manager.cc b/chromium/ui/base/accelerators/accelerator_manager.cc
index b604c019ccc..919326f1a9d 100644
--- a/chromium/ui/base/accelerators/accelerator_manager.cc
+++ b/chromium/ui/base/accelerators/accelerator_manager.cc
@@ -8,15 +8,12 @@
#include "base/logging.h"
#include "base/stl_util.h"
-#include "ui/base/accelerators/accelerator_manager_delegate.h"
namespace ui {
-AcceleratorManager::AcceleratorManager(AcceleratorManagerDelegate* delegate)
- : delegate_(delegate) {}
+AcceleratorManager::AcceleratorManager() = default;
-AcceleratorManager::~AcceleratorManager() {
-}
+AcceleratorManager::~AcceleratorManager() = default;
void AcceleratorManager::Register(
const std::vector<ui::Accelerator>& accelerators,
@@ -24,14 +21,10 @@ void AcceleratorManager::Register(
AcceleratorTarget* target) {
DCHECK(target);
- // Accelerators which haven't already been registered with any target.
- std::vector<ui::Accelerator> new_accelerators;
-
for (const ui::Accelerator& accelerator : accelerators) {
AcceleratorTargetList& targets = accelerators_[accelerator].second;
DCHECK(!base::ContainsValue(targets, target))
<< "Registering the same target multiple times";
- const bool is_first_target_for_accelerator = targets.empty();
// All priority accelerators go to the front of the line.
if (priority == kHighPriority) {
@@ -50,16 +43,12 @@ void AcceleratorManager::Register(
else
targets.insert(++targets.begin(), target);
}
- if (is_first_target_for_accelerator)
- new_accelerators.push_back(accelerator);
}
- if (delegate_ && !new_accelerators.empty())
- delegate_->OnAcceleratorsRegistered(new_accelerators);
}
void AcceleratorManager::Unregister(const Accelerator& accelerator,
AcceleratorTarget* target) {
- AcceleratorMap::iterator map_iter = accelerators_.find(accelerator);
+ auto map_iter = accelerators_.find(accelerator);
if (map_iter == accelerators_.end()) {
NOTREACHED() << "Unregistering non-existing accelerator";
return;
@@ -69,7 +58,7 @@ void AcceleratorManager::Unregister(const Accelerator& accelerator,
}
void AcceleratorManager::UnregisterAll(AcceleratorTarget* target) {
- for (AcceleratorMap::iterator map_iter = accelerators_.begin();
+ for (auto map_iter = accelerators_.begin();
map_iter != accelerators_.end();) {
AcceleratorTargetList* targets = &map_iter->second.second;
if (!base::ContainsValue(*targets, target)) {
@@ -83,20 +72,19 @@ void AcceleratorManager::UnregisterAll(AcceleratorTarget* target) {
}
bool AcceleratorManager::IsRegistered(const Accelerator& accelerator) const {
- AcceleratorMap::const_iterator map_iter = accelerators_.find(accelerator);
+ auto map_iter = accelerators_.find(accelerator);
return map_iter != accelerators_.end() && !map_iter->second.second.empty();
}
bool AcceleratorManager::Process(const Accelerator& accelerator) {
- AcceleratorMap::iterator map_iter = accelerators_.find(accelerator);
+ auto map_iter = accelerators_.find(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 (AcceleratorTargetList::iterator iter = targets.begin();
- iter != targets.end(); ++iter) {
+ for (auto iter = targets.begin(); iter != targets.end(); ++iter) {
if ((*iter)->CanHandleAccelerators() &&
(*iter)->AcceleratorPressed(accelerator)) {
return true;
@@ -108,7 +96,7 @@ bool AcceleratorManager::Process(const Accelerator& accelerator) {
bool AcceleratorManager::HasPriorityHandler(
const Accelerator& accelerator) const {
- AcceleratorMap::const_iterator map_iter = accelerators_.find(accelerator);
+ auto map_iter = accelerators_.find(accelerator);
if (map_iter == accelerators_.end() || map_iter->second.second.empty())
return false;
@@ -124,8 +112,7 @@ bool AcceleratorManager::HasPriorityHandler(
void AcceleratorManager::UnregisterImpl(AcceleratorMap::iterator map_iter,
AcceleratorTarget* target) {
AcceleratorTargetList* targets = &map_iter->second.second;
- AcceleratorTargetList::iterator target_iter =
- std::find(targets->begin(), targets->end(), target);
+ auto target_iter = std::find(targets->begin(), targets->end(), target);
if (target_iter == targets->end()) {
NOTREACHED() << "Unregistering accelerator for wrong target";
return;
@@ -139,10 +126,7 @@ void AcceleratorManager::UnregisterImpl(AcceleratorMap::iterator map_iter,
targets->remove(target);
if (!targets->empty())
return;
- const ui::Accelerator accelerator = map_iter->first;
accelerators_.erase(map_iter);
- if (delegate_)
- delegate_->OnAcceleratorUnregistered(accelerator);
}
} // namespace ui
diff --git a/chromium/ui/base/accelerators/accelerator_manager.h b/chromium/ui/base/accelerators/accelerator_manager.h
index 621454eb9ed..9eeec5ce99e 100644
--- a/chromium/ui/base/accelerators/accelerator_manager.h
+++ b/chromium/ui/base/accelerators/accelerator_manager.h
@@ -17,8 +17,6 @@
namespace ui {
-class AcceleratorManagerDelegate;
-
// AcceleratorManger handles processing of accelerators. A delegate may be
// supplied which is notified as unique accelerators are added and removed.
class UI_BASE_EXPORT AcceleratorManager {
@@ -28,7 +26,7 @@ class UI_BASE_EXPORT AcceleratorManager {
kHighPriority,
};
- explicit AcceleratorManager(AcceleratorManagerDelegate* = nullptr);
+ AcceleratorManager();
~AcceleratorManager();
// Register keyboard accelerators for the specified target. If multiple
@@ -93,7 +91,6 @@ class UI_BASE_EXPORT AcceleratorManager {
void UnregisterImpl(AcceleratorMap::iterator map_iter,
AcceleratorTarget* target);
- AcceleratorManagerDelegate* delegate_;
AcceleratorMap accelerators_;
DISALLOW_COPY_AND_ASSIGN(AcceleratorManager);
diff --git a/chromium/ui/base/accelerators/accelerator_manager_delegate.h b/chromium/ui/base/accelerators/accelerator_manager_delegate.h
deleted file mode 100644
index 7056be18941..00000000000
--- a/chromium/ui/base/accelerators/accelerator_manager_delegate.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2016 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_MANAGER_DELEGATE_H_
-#define UI_BASE_ACCELERATORS_ACCELERATOR_MANAGER_DELEGATE_H_
-
-#include "ui/base/ui_base_export.h"
-
-namespace ui {
-
-class Accelerator;
-
-// TODO: this should no longer be necessary, remove. https://crbug.com/842365
-class UI_BASE_EXPORT AcceleratorManagerDelegate {
- public:
- // Called when new accelerators are registered. This is only called with
- // newly registered accelerators. For example, if Register() is
- // called with A and B, then OnAcceleratorsRegistered() is called with A and
- // B. If Register() is subsequently called with A and C, then
- // OnAcceleratorsRegistered() is only called with C, as A was already
- // registered.
- virtual void OnAcceleratorsRegistered(
- const std::vector<ui::Accelerator>& accelerators) = 0;
-
- // Called when there no more targets are registered for |accelerator|.
- virtual void OnAcceleratorUnregistered(const Accelerator& accelerator) = 0;
-
- protected:
- virtual ~AcceleratorManagerDelegate() {}
-};
-
-} // namespace ui
-
-#endif // UI_BASE_ACCELERATORS_ACCELERATOR_MANAGER_DELEGATE_H_
diff --git a/chromium/ui/base/accelerators/accelerator_manager_unittest.cc b/chromium/ui/base/accelerators/accelerator_manager_unittest.cc
index 7ef855296d7..4711295de00 100644
--- a/chromium/ui/base/accelerators/accelerator_manager_unittest.cc
+++ b/chromium/ui/base/accelerators/accelerator_manager_unittest.cc
@@ -4,19 +4,14 @@
#include "ui/base/accelerators/accelerator_manager.h"
-#include <map>
-
-#include "base/compiler_specific.h"
#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/base/accelerators/accelerator_manager_delegate.h"
#include "ui/base/accelerators/test_accelerator_target.h"
#include "ui/events/event_constants.h"
#include "ui/events/keycodes/keyboard_codes.h"
namespace ui {
namespace test {
-
namespace {
Accelerator GetAccelerator(KeyboardCode code, int mask) {
@@ -38,81 +33,24 @@ int BuildAcceleratorModifier(int id) {
return result;
}
-// AcceleratorManagerDelegate implementation that records calls to interface
-// using the following format.
-// . OnAcceleratorsRegistered() -> A list of "'Register ' + <id>" separated by
-// whitespaces.
-// . OnAcceleratorUnregistered() -> 'Unregister' + id
-// where the id is specified using SetIdForAccelerator().
-class TestAcceleratorManagerDelegate : public AcceleratorManagerDelegate {
- public:
- TestAcceleratorManagerDelegate() {}
- ~TestAcceleratorManagerDelegate() override {}
-
- void SetIdForAccelerator(const Accelerator& accelerator,
- const std::string& id) {
- accelerator_to_id_[accelerator] = id;
- }
-
- std::string GetAndClearCommands() {
- std::string commands;
- std::swap(commands, commands_);
- return commands;
- }
-
- // AcceleratorManagerDelegate:
- void OnAcceleratorsRegistered(
- const std::vector<Accelerator>& accelerators) override {
- for (const Accelerator& accelerator : accelerators) {
- if (!commands_.empty())
- commands_ += " ";
- commands_ += "Register " + accelerator_to_id_[accelerator];
- }
- }
- void OnAcceleratorUnregistered(const Accelerator& accelerator) override {
- if (!commands_.empty())
- commands_ += " ";
- commands_ += "Unregister " + accelerator_to_id_[accelerator];
- }
-
- private:
- std::map<Accelerator, std::string> accelerator_to_id_;
- std::string commands_;
-
- DISALLOW_COPY_AND_ASSIGN(TestAcceleratorManagerDelegate);
-};
-
-} // namespace
-
class AcceleratorManagerTest : public testing::Test {
public:
- AcceleratorManagerTest() : manager_(&delegate_) {}
- ~AcceleratorManagerTest() override {}
+ AcceleratorManagerTest() = default;
+ ~AcceleratorManagerTest() override = default;
protected:
- TestAcceleratorManagerDelegate delegate_;
AcceleratorManager manager_;
};
TEST_F(AcceleratorManagerTest, Register) {
TestAcceleratorTarget target;
const Accelerator accelerator_a(VKEY_A, EF_NONE);
- delegate_.SetIdForAccelerator(accelerator_a, "a");
-
const Accelerator accelerator_b(VKEY_B, EF_NONE);
- delegate_.SetIdForAccelerator(accelerator_b, "b");
-
const Accelerator accelerator_c(VKEY_C, EF_NONE);
- delegate_.SetIdForAccelerator(accelerator_c, "c");
-
const Accelerator accelerator_d(VKEY_D, EF_NONE);
- delegate_.SetIdForAccelerator(accelerator_d, "d");
-
manager_.Register(
{accelerator_a, accelerator_b, accelerator_c, accelerator_d},
AcceleratorManager::kNormalPriority, &target);
- EXPECT_EQ("Register a Register b Register c Register d",
- delegate_.GetAndClearCommands());
// The registered accelerators are processed.
EXPECT_TRUE(manager_.Process(accelerator_a));
@@ -124,16 +62,12 @@ TEST_F(AcceleratorManagerTest, Register) {
TEST_F(AcceleratorManagerTest, RegisterMultipleTarget) {
const Accelerator accelerator_a(VKEY_A, EF_NONE);
- delegate_.SetIdForAccelerator(accelerator_a, "a");
TestAcceleratorTarget target1;
manager_.Register({accelerator_a}, AcceleratorManager::kNormalPriority,
&target1);
- EXPECT_EQ("Register a", delegate_.GetAndClearCommands());
TestAcceleratorTarget target2;
manager_.Register({accelerator_a}, AcceleratorManager::kNormalPriority,
&target2);
- // Registering the same command shouldn't notify the delegate.
- EXPECT_TRUE(delegate_.GetAndClearCommands().empty());
// If multiple targets are registered with the same accelerator, the target
// registered later processes the accelerator.
@@ -144,51 +78,37 @@ TEST_F(AcceleratorManagerTest, RegisterMultipleTarget) {
TEST_F(AcceleratorManagerTest, Unregister) {
const Accelerator accelerator_a(VKEY_A, EF_NONE);
- delegate_.SetIdForAccelerator(accelerator_a, "a");
TestAcceleratorTarget target;
const Accelerator accelerator_b(VKEY_B, EF_NONE);
- delegate_.SetIdForAccelerator(accelerator_b, "b");
manager_.Register({accelerator_a, accelerator_b},
AcceleratorManager::kNormalPriority, &target);
- EXPECT_EQ("Register a Register b", delegate_.GetAndClearCommands());
// Unregistering a different accelerator does not affect the other
// accelerator.
manager_.Unregister(accelerator_b, &target);
- EXPECT_EQ("Unregister b", delegate_.GetAndClearCommands());
EXPECT_TRUE(manager_.Process(accelerator_a));
EXPECT_EQ(1, target.accelerator_count());
// The unregistered accelerator is no longer processed.
target.ResetCounts();
manager_.Unregister(accelerator_a, &target);
- EXPECT_EQ("Unregister a", delegate_.GetAndClearCommands());
EXPECT_FALSE(manager_.Process(accelerator_a));
EXPECT_EQ(0, target.accelerator_count());
}
TEST_F(AcceleratorManagerTest, UnregisterAll) {
const Accelerator accelerator_a(VKEY_A, EF_NONE);
- delegate_.SetIdForAccelerator(accelerator_a, "a");
TestAcceleratorTarget target1;
const Accelerator accelerator_b(VKEY_B, EF_NONE);
- delegate_.SetIdForAccelerator(accelerator_b, "b");
manager_.Register({accelerator_a, accelerator_b},
AcceleratorManager::kNormalPriority, &target1);
+
const Accelerator accelerator_c(VKEY_C, EF_NONE);
- delegate_.SetIdForAccelerator(accelerator_c, "c");
TestAcceleratorTarget target2;
manager_.Register({accelerator_c}, AcceleratorManager::kNormalPriority,
&target2);
- EXPECT_EQ("Register a Register b Register c",
- delegate_.GetAndClearCommands());
+
manager_.UnregisterAll(&target1);
- {
- const std::string commands = delegate_.GetAndClearCommands();
- // Ordering is not guaranteed.
- EXPECT_TRUE(commands == "Unregister a Unregister b" ||
- commands == "Unregister b Unregister a");
- }
// All the accelerators registered for |target1| are no longer processed.
EXPECT_FALSE(manager_.Process(accelerator_a));
@@ -242,21 +162,6 @@ TEST_F(AcceleratorManagerTest, Process) {
}
}
-// Verifies delegate is notifed correctly when unregistering and registering
-// with the same accelerator.
-TEST_F(AcceleratorManagerTest, Reregister) {
- const Accelerator accelerator_a(VKEY_A, EF_NONE);
- TestAcceleratorTarget target;
- delegate_.SetIdForAccelerator(accelerator_a, "a");
- manager_.Register({accelerator_a}, AcceleratorManager::kNormalPriority,
- &target);
- EXPECT_EQ("Register a", delegate_.GetAndClearCommands());
- manager_.UnregisterAll(&target);
- EXPECT_EQ("Unregister a", delegate_.GetAndClearCommands());
- manager_.Register({accelerator_a}, AcceleratorManager::kNormalPriority,
- &target);
- EXPECT_EQ("Register a", delegate_.GetAndClearCommands());
-}
-
+} // namespace
} // namespace test
} // namespace ui
diff --git a/chromium/ui/base/class_property.cc b/chromium/ui/base/class_property.cc
index 8b13aa1426e..01941edfd31 100644
--- a/chromium/ui/base/class_property.cc
+++ b/chromium/ui/base/class_property.cc
@@ -54,7 +54,7 @@ void PropertyHandler::ClearProperties() {
int64_t PropertyHandler::GetPropertyInternal(const void* key,
int64_t default_value) const {
- std::map<const void*, Value>::const_iterator iter = prop_map_.find(key);
+ auto iter = prop_map_.find(key);
if (iter == prop_map_.end())
return default_value;
return iter->second.value;
diff --git a/chromium/ui/base/clipboard/clipboard.cc b/chromium/ui/base/clipboard/clipboard.cc
index 6697be9cd4c..38665261399 100644
--- a/chromium/ui/base/clipboard/clipboard.cc
+++ b/chromium/ui/base/clipboard/clipboard.cc
@@ -80,7 +80,7 @@ void Clipboard::DestroyClipboardForCurrentThread() {
ClipboardMap* clipboard_map = clipboard_map_.Pointer();
base::PlatformThreadId id = base::PlatformThread::CurrentId();
- ClipboardMap::iterator it = clipboard_map->find(id);
+ auto it = clipboard_map->find(id);
if (it != clipboard_map->end())
clipboard_map->erase(it);
}
diff --git a/chromium/ui/base/clipboard/clipboard.h b/chromium/ui/base/clipboard/clipboard.h
index 94236adca28..d76a66d657b 100644
--- a/chromium/ui/base/clipboard/clipboard.h
+++ b/chromium/ui/base/clipboard/clipboard.h
@@ -16,6 +16,7 @@
#include "base/containers/flat_map.h"
#include "base/lazy_instance.h"
#include "base/macros.h"
+#include "base/no_destructor.h"
#include "base/process/process.h"
#include "base/strings/string16.h"
#include "base/synchronization/lock.h"
@@ -82,6 +83,7 @@ class UI_BASE_EXPORT Clipboard : public base::ThreadChecker {
bool Equals(const FormatType& other) const;
private:
+ friend class base::NoDestructor<FormatType>;
friend class Clipboard;
// Platform-specific glue used internally by the Clipboard class. Each
diff --git a/chromium/ui/base/clipboard/clipboard_android.cc b/chromium/ui/base/clipboard/clipboard_android.cc
index 0cb4357b64b..c1fada750f6 100644
--- a/chromium/ui/base/clipboard/clipboard_android.cc
+++ b/chromium/ui/base/clipboard/clipboard_android.cc
@@ -11,6 +11,7 @@
#include "base/android/scoped_java_ref.h"
#include "base/callback.h"
#include "base/lazy_instance.h"
+#include "base/no_destructor.h"
#include "base/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/synchronization/lock.h"
@@ -269,56 +270,56 @@ Clipboard::FormatType Clipboard::GetFormatType(
// static
const Clipboard::FormatType& Clipboard::GetUrlWFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kURLFormat));
- return type;
+ static base::NoDestructor<FormatType> type(kURLFormat);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetPlainTextFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kPlainTextFormat));
- return type;
+ static base::NoDestructor<FormatType> type(kPlainTextFormat);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetPlainTextWFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kPlainTextFormat));
- return type;
+ static base::NoDestructor<FormatType> type(kPlainTextFormat);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetWebKitSmartPasteFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kWebKitSmartPasteFormat));
- return type;
+ static base::NoDestructor<FormatType> type(kWebKitSmartPasteFormat);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetHtmlFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kHTMLFormat));
- return type;
+ static base::NoDestructor<FormatType> type(kHTMLFormat);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetRtfFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kRTFFormat));
- return type;
+ static base::NoDestructor<FormatType> type(kRTFFormat);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetBitmapFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kBitmapFormat));
- return type;
+ static base::NoDestructor<FormatType> type(kBitmapFormat);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetWebCustomDataFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebCustomData));
- return type;
+ static base::NoDestructor<FormatType> type(kMimeTypeWebCustomData);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypePepperCustomData));
- return type;
+ static base::NoDestructor<FormatType> type(kMimeTypePepperCustomData);
+ return *type;
}
// Clipboard factory method.
diff --git a/chromium/ui/base/clipboard/clipboard_aura.cc b/chromium/ui/base/clipboard/clipboard_aura.cc
index 9e08f7a1f9c..f185182cb36 100644
--- a/chromium/ui/base/clipboard/clipboard_aura.cc
+++ b/chromium/ui/base/clipboard/clipboard_aura.cc
@@ -15,6 +15,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.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_monitor.h"
@@ -453,8 +454,8 @@ Clipboard::FormatType Clipboard::GetFormatType(
// static
const Clipboard::FormatType& Clipboard::GetUrlFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeURIList));
- return type;
+ static base::NoDestructor<FormatType> type(kMimeTypeURIList);
+ return *type;
}
// static
@@ -464,14 +465,14 @@ const Clipboard::FormatType& Clipboard::GetUrlWFormatType() {
// static
const Clipboard::FormatType& Clipboard::GetMozUrlFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeMozillaURL));
- return type;
+ static base::NoDestructor<FormatType> type(kMimeTypeMozillaURL);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetPlainTextFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeText));
- return type;
+ static base::NoDestructor<FormatType> type(kMimeTypeText);
+ return *type;
}
// static
@@ -481,8 +482,8 @@ const Clipboard::FormatType& Clipboard::GetPlainTextWFormatType() {
// static
const Clipboard::FormatType& Clipboard::GetFilenameFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeFilename));
- return type;
+ static base::NoDestructor<FormatType> type(kMimeTypeFilename);
+ return *type;
}
// static
@@ -492,38 +493,38 @@ const Clipboard::FormatType& Clipboard::GetFilenameWFormatType() {
// static
const Clipboard::FormatType& Clipboard::GetHtmlFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeHTML));
- return type;
+ static base::NoDestructor<FormatType> type(kMimeTypeHTML);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetRtfFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeRTF));
- return type;
+ static base::NoDestructor<FormatType> type(kMimeTypeRTF);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetBitmapFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeBitmap));
- return type;
+ static base::NoDestructor<FormatType> type(kMimeTypeBitmap);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetWebKitSmartPasteFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebkitSmartPaste));
- return type;
+ static base::NoDestructor<FormatType> type(kMimeTypeWebkitSmartPaste);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetWebCustomDataFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebCustomData));
- return type;
+ static base::NoDestructor<FormatType> type(kMimeTypeWebCustomData);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypePepperCustomData));
- return type;
+ static base::NoDestructor<FormatType> type(kMimeTypePepperCustomData);
+ return *type;
}
// Clipboard factory method.
diff --git a/chromium/ui/base/clipboard/clipboard_aurax11.cc b/chromium/ui/base/clipboard/clipboard_aurax11.cc
index d071d155a65..4e767fcd9d9 100644
--- a/chromium/ui/base/clipboard/clipboard_aurax11.cc
+++ b/chromium/ui/base/clipboard/clipboard_aurax11.cc
@@ -17,6 +17,7 @@
#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/stl_util.h"
#include "base/strings/utf_string_conversions.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -378,9 +379,8 @@ SelectionData ClipboardAuraX11::AuraX11Details::RequestAndWaitForTypes(
// with the X server.
const SelectionFormatMap& format_map = LookupStorageForAtom(selection_name);
- for (std::vector< ::Atom>::const_iterator it = types.begin();
- it != types.end(); ++it) {
- SelectionFormatMap::const_iterator format_map_it = format_map.find(*it);
+ for (auto it = types.begin(); it != types.end(); ++it) {
+ auto format_map_it = format_map.find(*it);
if (format_map_it != format_map.end())
return SelectionData(format_map_it->first, format_map_it->second);
}
@@ -405,8 +405,7 @@ TargetList ClipboardAuraX11::AuraX11Details::WaitAndGetTargetsList(
// We can local fastpath and return the list of local targets.
const SelectionFormatMap& format_map = LookupStorageForAtom(selection_name);
- for (SelectionFormatMap::const_iterator it = format_map.begin();
- it != format_map.end(); ++it) {
+ for (auto it = format_map.begin(); it != format_map.end(); ++it) {
out.push_back(it->first);
}
} else {
@@ -557,8 +556,8 @@ Clipboard::FormatType Clipboard::GetFormatType(
// static
const Clipboard::FormatType& Clipboard::GetUrlFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeURIList));
- return type;
+ static base::NoDestructor<FormatType> type(kMimeTypeURIList);
+ return *type;
}
// static
@@ -568,14 +567,14 @@ const Clipboard::FormatType& Clipboard::GetUrlWFormatType() {
// static
const Clipboard::FormatType& Clipboard::GetMozUrlFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeMozillaURL));
- return type;
+ static base::NoDestructor<FormatType> type(kMimeTypeMozillaURL);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetPlainTextFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeText));
- return type;
+ static base::NoDestructor<FormatType> type(kMimeTypeText);
+ return *type;
}
// static
@@ -585,8 +584,8 @@ const Clipboard::FormatType& Clipboard::GetPlainTextWFormatType() {
// static
const Clipboard::FormatType& Clipboard::GetFilenameFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeFilename));
- return type;
+ static base::NoDestructor<FormatType> type(kMimeTypeFilename);
+ return *type;
}
// static
@@ -596,38 +595,38 @@ const Clipboard::FormatType& Clipboard::GetFilenameWFormatType() {
// static
const Clipboard::FormatType& Clipboard::GetHtmlFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeHTML));
- return type;
+ static base::NoDestructor<FormatType> type(kMimeTypeHTML);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetRtfFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeRTF));
- return type;
+ static base::NoDestructor<FormatType> type(kMimeTypeRTF);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetBitmapFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypePNG));
- return type;
+ static base::NoDestructor<FormatType> type(kMimeTypePNG);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetWebKitSmartPasteFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebkitSmartPaste));
- return type;
+ static base::NoDestructor<FormatType> type(kMimeTypeWebkitSmartPaste);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetWebCustomDataFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebCustomData));
- return type;
+ static base::NoDestructor<FormatType> type(kMimeTypeWebCustomData);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypePepperCustomData));
- return type;
+ static base::NoDestructor<FormatType> type(kMimeTypePepperCustomData);
+ return *type;
}
///////////////////////////////////////////////////////////////////////////////
@@ -813,14 +812,13 @@ void ClipboardAuraX11::WriteObjects(ClipboardType type,
DCHECK(IsSupportedClipboardType(type));
aurax11_details_->CreateNewClipboardData();
- for (ObjectMap::const_iterator iter = objects.begin(); iter != objects.end();
- ++iter) {
+ for (auto iter = objects.begin(); iter != objects.end(); ++iter) {
DispatchObject(static_cast<ObjectType>(iter->first), iter->second);
}
aurax11_details_->TakeOwnershipOfSelection(type);
if (type == CLIPBOARD_TYPE_COPY_PASTE) {
- ObjectMap::const_iterator text_iter = objects.find(CBF_TEXT);
+ auto text_iter = objects.find(CBF_TEXT);
if (text_iter != objects.end()) {
aurax11_details_->CreateNewClipboardData();
const ObjectMapParams& params_vector = text_iter->second;
diff --git a/chromium/ui/base/clipboard/clipboard_mac.mm b/chromium/ui/base/clipboard/clipboard_mac.mm
index 845c1a3427b..e9abab846ec 100644
--- a/chromium/ui/base/clipboard/clipboard_mac.mm
+++ b/chromium/ui/base/clipboard/clipboard_mac.mm
@@ -14,6 +14,7 @@
#include "base/mac/mac_util.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/mac/scoped_nsobject.h"
+#include "base/no_destructor.h"
#include "base/stl_util.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
@@ -99,8 +100,8 @@ Clipboard::FormatType Clipboard::GetFormatType(
// static
const Clipboard::FormatType& Clipboard::GetUrlFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (NSURLPboardType));
- return type;
+ static base::NoDestructor<FormatType> type(NSURLPboardType);
+ return *type;
}
// static
@@ -110,8 +111,8 @@ const Clipboard::FormatType& Clipboard::GetUrlWFormatType() {
// static
const Clipboard::FormatType& Clipboard::GetPlainTextFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (NSPasteboardTypeString));
- return type;
+ static base::NoDestructor<FormatType> type(NSPasteboardTypeString);
+ return *type;
}
// static
@@ -121,8 +122,8 @@ const Clipboard::FormatType& Clipboard::GetPlainTextWFormatType() {
// static
const Clipboard::FormatType& Clipboard::GetFilenameFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (NSFilenamesPboardType));
- return type;
+ static base::NoDestructor<FormatType> type(NSFilenamesPboardType);
+ return *type;
}
// static
@@ -132,38 +133,38 @@ const Clipboard::FormatType& Clipboard::GetFilenameWFormatType() {
// static
const Clipboard::FormatType& Clipboard::GetHtmlFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (NSHTMLPboardType));
- return type;
+ static base::NoDestructor<FormatType> type(NSHTMLPboardType);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetRtfFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (NSRTFPboardType));
- return type;
+ static base::NoDestructor<FormatType> type(NSRTFPboardType);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetBitmapFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (NSTIFFPboardType));
- return type;
+ static base::NoDestructor<FormatType> type(NSTIFFPboardType);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetWebKitSmartPasteFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kWebSmartPastePboardType));
- return type;
+ static base::NoDestructor<FormatType> type(kWebSmartPastePboardType);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetWebCustomDataFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kWebCustomDataPboardType));
- return type;
+ static base::NoDestructor<FormatType> type(kWebCustomDataPboardType);
+ return *type;
}
// static
const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kPepperCustomDataPboardType));
- return type;
+ static base::NoDestructor<FormatType> type(kPepperCustomDataPboardType);
+ return *type;
}
// Clipboard factory method.
diff --git a/chromium/ui/base/clipboard/clipboard_util_mac.h b/chromium/ui/base/clipboard/clipboard_util_mac.h
index 1c4ff0ad99d..31c459b1b08 100644
--- a/chromium/ui/base/clipboard/clipboard_util_mac.h
+++ b/chromium/ui/base/clipboard/clipboard_util_mac.h
@@ -9,10 +9,15 @@
#include "base/mac/scoped_nsobject.h"
#include "base/memory/ref_counted.h"
+#include "ui/base/clipboard/clipboard_types.h"
#include "ui/base/ui_base_export.h"
namespace ui {
+// A publicly-used UTI for the name of a URL. It really should be in a system
+// header but isn't.
+UI_BASE_EXPORT extern NSString* const kUTTypeURLName;
+
class UI_BASE_EXPORT UniquePasteboard
: public base::RefCounted<UniquePasteboard> {
public:
@@ -64,6 +69,9 @@ class UI_BASE_EXPORT ClipboardUtil {
static bool URLsAndTitlesFromPasteboard(NSPasteboard* pboard,
NSArray** urls,
NSArray** titles);
+
+ // Gets the NSPasteboard specified from the clipboard type.
+ static NSPasteboard* PasteboardFromType(ui::ClipboardType type);
};
}
diff --git a/chromium/ui/base/clipboard/clipboard_util_mac.mm b/chromium/ui/base/clipboard/clipboard_util_mac.mm
index 0db36b8f58a..b7bf6229dda 100644
--- a/chromium/ui/base/clipboard/clipboard_util_mac.mm
+++ b/chromium/ui/base/clipboard/clipboard_util_mac.mm
@@ -10,10 +10,10 @@
namespace ui {
+NSString* const kUTTypeURLName = @"public.url-name";
+
namespace {
NSString* const kWebURLsWithTitlesPboardType = @"WebURLsWithTitlesPboardType";
-NSString* const kPublicUrl = @"public.url";
-NSString* const kPublicUrlName = @"public.url-name";
// It's much more convenient to return an NSString than a
// base::ScopedCFTypeRef<CFStringRef>, since the methods on NSPasteboardItem
@@ -75,8 +75,8 @@ base::scoped_nsobject<NSPasteboardItem> ClipboardUtil::PasteboardItemFromUrl(
}
[item setString:urlString forType:NSPasteboardTypeString];
- [item setString:urlString forType:kPublicUrl];
- [item setString:title forType:kPublicUrlName];
+ [item setString:urlString forType:base::mac::CFToNSCast(kUTTypeURL)];
+ [item setString:title forType:kUTTypeURLName];
return item;
}
@@ -104,12 +104,12 @@ base::scoped_nsobject<NSPasteboardItem> ClipboardUtil::PasteboardItemFromString(
//static
NSString* ClipboardUtil::GetTitleFromPasteboardURL(NSPasteboard* pboard) {
- return [pboard stringForType:kPublicUrlName];
+ return [pboard stringForType:kUTTypeURLName];
}
//static
NSString* ClipboardUtil::GetURLFromPasteboardURL(NSPasteboard* pboard) {
- return [pboard stringForType:kPublicUrl];
+ return [pboard stringForType:base::mac::CFToNSCast(kUTTypeURL)];
}
// static
@@ -177,4 +177,22 @@ bool ClipboardUtil::URLsAndTitlesFromPasteboard(NSPasteboard* pboard,
return true;
}
+// static
+NSPasteboard* ClipboardUtil::PasteboardFromType(ui::ClipboardType type) {
+ NSString* type_string = nil;
+ switch (type) {
+ case ui::CLIPBOARD_TYPE_COPY_PASTE:
+ type_string = NSGeneralPboard;
+ break;
+ case ui::CLIPBOARD_TYPE_DRAG:
+ type_string = NSDragPboard;
+ break;
+ case ui::CLIPBOARD_TYPE_SELECTION:
+ NOTREACHED();
+ break;
+ }
+
+ return [NSPasteboard pasteboardWithName:type_string];
+}
+
} // namespace ui
diff --git a/chromium/ui/base/cocoa/a11y_util.h b/chromium/ui/base/cocoa/a11y_util.h
deleted file mode 100644
index a304b77c647..00000000000
--- a/chromium/ui/base/cocoa/a11y_util.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright 2016 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_BASE_COCOA_A11Y_UTIL_H
-#define UI_BASE_COCOA_A11Y_UTIL_H
-
-#import <Cocoa/Cocoa.h>
-
-#include "ui/base/ui_base_export.h"
-
-namespace ui {
-namespace a11y_util {
-
-// Hides the given |view| from the accessibility order for Voice Over. This
-// should be used when the view provides no additional information with
-// voice over (i.e., an icon next to a written description of the icon).
-UI_BASE_EXPORT void HideImageFromAccessibilityOrder(NSImageView* view);
-
-// Ask VoiceOver to play a sound for |object|, generally a view or window
-// (undocumented). Built-in apps seem to use this to indicate that something
-// interesting has happened, like a failed download or available completions.
-UI_BASE_EXPORT void PlayElementUpdatedSound(id source);
-
-} // namespace a11y_util
-} // namespace ui
-
-#endif // UI_BASE_COCOA_A11Y_UTIL_H
diff --git a/chromium/ui/base/cocoa/a11y_util.mm b/chromium/ui/base/cocoa/a11y_util.mm
deleted file mode 100644
index e6a27ad26c3..00000000000
--- a/chromium/ui/base/cocoa/a11y_util.mm
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2016 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 "ui/base/cocoa/a11y_util.h"
-
-namespace ui {
-namespace a11y_util {
-
-void HideImageFromAccessibilityOrder(NSImageView* view) {
- // This is the minimum change necessary to get VoiceOver to skip the image
- // (instead of reading the word "image"). Accessibility mechanisms in OSX
- // change once in a while, so this may be fragile.
- [[view cell] accessibilitySetOverrideValue:@""
- forAttribute:NSAccessibilityRoleAttribute];
-}
-
-void PlayElementUpdatedSound(id source) {
- NSAccessibilityPostNotificationWithUserInfo(
- source, @"AXPlaySound",
- @{@"AXSoundIdentifier" : @"AXElementUpdatedSound"});
-}
-
-} // namespace a11y_util
-} // namespace ui
diff --git a/chromium/ui/base/cocoa/accessibility_hostable.h b/chromium/ui/base/cocoa/accessibility_hostable.h
deleted file mode 100644
index 63a4a2424b2..00000000000
--- a/chromium/ui/base/cocoa/accessibility_hostable.h
+++ /dev/null
@@ -1,25 +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_BASE_COCOA_ACCESSIBILITY_HOSTABLE_H_
-#define UI_BASE_COCOA_ACCESSIBILITY_HOSTABLE_H_
-
-#import <objc/objc.h>
-
-// An object that can be hosted in another accessibility hierarchy.
-// This allows for stitching together heterogenous accessibility
-// hierarchies, for example the AXPlatformNodeCocoa-based views
-// toolkit hierarchy and the BrowserAccessibilityCocoa-based
-// web content hierarchy.
-@protocol AccessibilityHostable
-
-// Sets |accessibilityParent| as the object returned when the
-// receiver is queried for its accessibility parent.
-// TODO(lgrey/ellyjones): Remove this in favor of setAccessibilityParent:
-// when we switch to the new accessibility API.
-- (void)setAccessibilityParentElement:(id)accessibilityParent;
-
-@end
-
-#endif // UI_BASE_COCOA_ACCESSIBILITY_HOSTABLE_H_
diff --git a/chromium/ui/base/cocoa/appkit_utils.h b/chromium/ui/base/cocoa/appkit_utils.h
index 8f900e9326b..14f6c55070e 100644
--- a/chromium/ui/base/cocoa/appkit_utils.h
+++ b/chromium/ui/base/cocoa/appkit_utils.h
@@ -11,37 +11,6 @@
namespace ui {
-struct NinePartImageIds {
- int top_left;
- int top;
- int top_right;
- int left;
- int center;
- int right;
- int bottom_left;
- int bottom;
- int bottom_right;
-};
-
-// A macro to define arrays of IDR constants used with DrawNinePartImage.
-#define IMAGE_GRID(x) { x ## _TOP_LEFT, x ## _TOP, x ## _TOP_RIGHT, \
- x ## _LEFT, x ## _CENTER, x ## _RIGHT, \
- x ## _BOTTOM_LEFT, x ## _BOTTOM, x ## _BOTTOM_RIGHT, }
-
-// Utility method to draw a nine part image using image ids.
-UI_BASE_EXPORT void DrawNinePartImage(NSRect frame,
- const NinePartImageIds& image_ids,
- NSCompositingOperation operation,
- CGFloat alpha,
- BOOL flipped);
-
-// Minimizes or zooms the window, or does nothing, depending on OS version and
-// system configuration.
-// |window| is the receiver of the double click.
-// |sender| is the object that sends the action, if one is sent.
-UI_BASE_EXPORT void WindowTitlebarReceivedDoubleClick(NSWindow* window,
- id sender);
-
// Whether a force-click event on the touchpad should invoke Quick Look.
UI_BASE_EXPORT bool ForceClickInvokesQuickLook();
diff --git a/chromium/ui/base/cocoa/appkit_utils.mm b/chromium/ui/base/cocoa/appkit_utils.mm
index 6c3e7e2d9cb..c82a222e096 100644
--- a/chromium/ui/base/cocoa/appkit_utils.mm
+++ b/chromium/ui/base/cocoa/appkit_utils.mm
@@ -25,86 +25,10 @@ enum class ForceTouchAction {
QUICK_LOOK = 1, // Set to "Force Click with one finger".
};
-// Gets an NSImage given an image id.
-NSImage* GetImage(int image_id) {
- return ui::ResourceBundle::GetSharedInstance()
- .GetNativeImageNamed(image_id)
- .ToNSImage();
-}
-
-// The action to take when the user double-clicks in the window title bar.
-DoubleClickAction WindowTitleBarDoubleClickAction() {
- // El Capitan introduced a Dock preference to configure the window title bar
- // double-click action (Minimize, Maximize, or nothing).
- if (base::mac::IsAtLeastOS10_11()) {
- NSString* doubleClickAction = [[NSUserDefaults standardUserDefaults]
- objectForKey:@"AppleActionOnDoubleClick"];
-
- if ([doubleClickAction isEqualToString:@"Minimize"]) {
- return DoubleClickAction::MINIMIZE;
- } else if ([doubleClickAction isEqualToString:@"Maximize"]) {
- return DoubleClickAction::MAXIMIZE;
- }
-
- return DoubleClickAction::NONE;
- }
-
- // Determine minimize using an undocumented method in Cocoa. If we're
- // running on an earlier version of the OS that doesn't implement it,
- // just default to the minimize action.
- BOOL methodImplemented =
- [NSWindow respondsToSelector:@selector(_shouldMiniaturizeOnDoubleClick)];
- if (!methodImplemented ||
- [NSWindow performSelector:@selector(_shouldMiniaturizeOnDoubleClick)]) {
- return DoubleClickAction::MINIMIZE;
- }
-
- // At this point _shouldMiniaturizeOnDoubleClick has returned |NO|. On
- // Yosemite, that means a double-click should Maximize the window, and on
- // all prior OSes a double-click should do nothing.
- return base::mac::IsOS10_10() ? DoubleClickAction::MAXIMIZE
- : DoubleClickAction::NONE;
-}
-
} // namespace
namespace ui {
-void DrawNinePartImage(NSRect frame,
- const NinePartImageIds& image_ids,
- NSCompositingOperation operation,
- CGFloat alpha,
- BOOL flipped) {
- NSDrawNinePartImage(frame,
- GetImage(image_ids.top_left),
- GetImage(image_ids.top),
- GetImage(image_ids.top_right),
- GetImage(image_ids.left),
- GetImage(image_ids.center),
- GetImage(image_ids.right),
- GetImage(image_ids.bottom_left),
- GetImage(image_ids.bottom),
- GetImage(image_ids.bottom_right),
- operation,
- alpha,
- flipped);
-}
-
-void WindowTitlebarReceivedDoubleClick(NSWindow* window, id sender) {
- switch (WindowTitleBarDoubleClickAction()) {
- case DoubleClickAction::MINIMIZE:
- [window performMiniaturize:sender];
- break;
-
- case DoubleClickAction::MAXIMIZE:
- [window performZoom:sender];
- break;
-
- case DoubleClickAction::NONE:
- break;
- }
-}
-
bool ForceClickInvokesQuickLook() {
return [[NSUserDefaults standardUserDefaults]
integerForKey:@"com.apple.trackpad.forceClick"] ==
diff --git a/chromium/ui/base/cocoa/constrained_window/constrained_window_animation.mm b/chromium/ui/base/cocoa/constrained_window/constrained_window_animation.mm
index e467e0c85d4..b681b77ca68 100644
--- a/chromium/ui/base/cocoa/constrained_window/constrained_window_animation.mm
+++ b/chromium/ui/base/cocoa/constrained_window/constrained_window_animation.mm
@@ -5,6 +5,7 @@
#import "ui/base/cocoa/constrained_window/constrained_window_animation.h"
#include <stdint.h>
+#include <stdlib.h>
#include "base/files/file_path.h"
#include "base/location.h"
@@ -189,6 +190,15 @@ void UpdateWindowShowHideAnimationState(NSWindow* window, CGFloat value) {
SetWindowWarp(window, y_offset, scale, perspective_offset);
}
+bool AreWindowServerEffectsDisabled() {
+ // If the CHROME_HEADLESS env variable is set, this code is running in a
+ // test environment. The custom constrained window animations may be
+ // causing the WindowServer to crash (https://crbug.com/828031), so use the
+ // simple animations.
+ static bool is_headless = getenv("CHROME_HEADLESS") != nullptr;
+ return is_headless;
+}
+
} // namespace
@interface ConstrainedWindowAnimationBase ()
@@ -256,14 +266,26 @@ void UpdateWindowShowHideAnimationState(NSWindow* window, CGFloat value) {
@implementation ConstrainedWindowAnimationShow
- (void)setWindowStateForStart {
+ if (AreWindowServerEffectsDisabled()) {
+ [window_ setAlphaValue:0.0];
+ return;
+ }
SetWindowAlpha(window_, 0.0);
}
- (void)setWindowStateForValue:(float)value {
+ if (AreWindowServerEffectsDisabled()) {
+ [window_ setAlphaValue:value];
+ return;
+ }
UpdateWindowShowHideAnimationState(window_, value);
}
- (void)setWindowStateForEnd {
+ if (AreWindowServerEffectsDisabled()) {
+ [window_ setAlphaValue:1.0];
+ return;
+ }
SetWindowAlpha(window_, 1.0);
ClearWindowWarp(window_);
}
@@ -273,10 +295,18 @@ void UpdateWindowShowHideAnimationState(NSWindow* window, CGFloat value) {
@implementation ConstrainedWindowAnimationHide
- (void)setWindowStateForValue:(float)value {
+ if (AreWindowServerEffectsDisabled()) {
+ [window_ setAlphaValue:1.0 - value];
+ return;
+ }
UpdateWindowShowHideAnimationState(window_, 1.0 - value);
}
- (void)setWindowStateForEnd {
+ if (AreWindowServerEffectsDisabled()) {
+ [window_ setAlphaValue:0.0];
+ return;
+ }
SetWindowAlpha(window_, 0.0);
ClearWindowWarp(window_);
}
@@ -287,6 +317,9 @@ void UpdateWindowShowHideAnimationState(NSWindow* window, CGFloat value) {
// Sets the window scale based on the animation progress.
- (void)setWindowStateForValue:(float)value {
+ if (AreWindowServerEffectsDisabled())
+ return;
+
KeyFrame frames[] = {
{0.00, 1.0}, {0.40, 1.02}, {0.60, 1.02}, {1.00, 1.0},
};
@@ -306,6 +339,11 @@ void UpdateWindowShowHideAnimationState(NSWindow* window, CGFloat value) {
}
- (void)setWindowStateForEnd {
+ if (AreWindowServerEffectsDisabled()) {
+ NSBeep();
+ return;
+ }
+
SetWindowScale(window_, 1.0);
}
diff --git a/chromium/ui/base/cocoa/controls/blue_label_button.h b/chromium/ui/base/cocoa/controls/blue_label_button.h
deleted file mode 100644
index 0712131a791..00000000000
--- a/chromium/ui/base/cocoa/controls/blue_label_button.h
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_BASE_COCOA_CONTROLS_BLUE_LABEL_BUTTON_H_
-#define UI_BASE_COCOA_CONTROLS_BLUE_LABEL_BUTTON_H_
-
-#import <Cocoa/Cocoa.h>
-
-#import "ui/base/cocoa/hover_button.h"
-#include "ui/base/ui_base_export.h"
-
-// A rectangular blue NSButton that reacts to hover, focus and lit states. It
-// can contain an arbitrary single-line text label, and will be sized to fit the
-// font height and label width.
-UI_BASE_EXPORT
-@interface BlueLabelButton : HoverButtonCocoa
-@end
-
-#endif // UI_BASE_COCOA_CONTROLS_BLUE_LABEL_BUTTON_H_
diff --git a/chromium/ui/base/cocoa/controls/blue_label_button.mm b/chromium/ui/base/cocoa/controls/blue_label_button.mm
deleted file mode 100644
index 5a620175889..00000000000
--- a/chromium/ui/base/cocoa/controls/blue_label_button.mm
+++ /dev/null
@@ -1,152 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ui/base/cocoa/controls/blue_label_button.h"
-
-#include "base/mac/foundation_util.h"
-#include "skia/ext/skia_utils_mac.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "ui/base/cocoa/scoped_cg_context_smooth_fonts.h"
-#include "ui/base/resource/resource_bundle.h"
-#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
-
-const CGFloat kCornerRadius = 2;
-
-const CGFloat kTopBottomTextPadding = 7;
-const CGFloat kLeftRightTextPadding = 15;
-const SkColor kTextShadowColor = SkColorSetRGB(0x53, 0x8c, 0xea);
-
-const SkColor kShadowColor = SkColorSetRGB(0xe9, 0xe9, 0xe9);
-const SkColor kDefaultColor = SkColorSetRGB(0x5a, 0x97, 0xff);
-const SkColor kHoverColor = SkColorSetRGB(0x55, 0x8f, 0xf3);
-const SkColor kPressedColor = SkColorSetRGB(0x42, 0x79, 0xd8);
-
-const SkColor kInnerRingColor = SkColorSetRGB(0x64, 0x9e, 0xff);
-const SkColor kFocusInnerRingColor = SkColorSetRGB(0xad, 0xcc, 0xff);
-const SkColor kPressInnerRingColor = SkColorSetRGB(0x3f, 0x73, 0xcd);
-
-const SkColor kOuterRingColor = SkColorSetRGB(0x2b, 0x67, 0xce);
-const SkColor kPressOuterRingColor = SkColorSetRGB(0x23, 0x52, 0xa2);
-
-const int kFontSizeDelta = ui::ResourceBundle::kSmallFontDelta;
-
-@interface BlueLabelButtonCell : NSButtonCell
-
-+ (NSAttributedString*)generateAttributedString:(NSString*)buttonText;
-
-@end
-
-@implementation BlueLabelButton
-
-+ (Class)cellClass {
- return [BlueLabelButtonCell class];
-}
-
-- (id)initWithFrame:(NSRect)frameRect {
- if ((self = [super initWithFrame:frameRect])) {
- [self setBezelStyle:NSSmallSquareBezelStyle];
- }
- return self;
-}
-
-@end
-
-@implementation BlueLabelButtonCell
-
-+ (NSAttributedString*)generateAttributedString:(NSString*)buttonText {
- ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
- NSFont* buttonFont = rb.GetFontWithDelta(kFontSizeDelta).GetNativeFont();
- base::scoped_nsobject<NSMutableParagraphStyle> buttonTextParagraphStyle(
- [[NSMutableParagraphStyle alloc] init]);
- [buttonTextParagraphStyle setAlignment:NSCenterTextAlignment];
-
- base::scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
- [shadow setShadowOffset:NSMakeSize(0, -1)];
- [shadow setShadowBlurRadius:0];
- [shadow setShadowColor:skia::SkColorToSRGBNSColor(kTextShadowColor)];
-
- NSDictionary* buttonTextAttributes = @{
- NSParagraphStyleAttributeName : buttonTextParagraphStyle,
- NSFontAttributeName : buttonFont,
- NSForegroundColorAttributeName : [NSColor whiteColor],
- NSShadowAttributeName : shadow.get()
- };
- base::scoped_nsobject<NSAttributedString> attributedButtonText(
- [[NSAttributedString alloc] initWithString:buttonText
- attributes:buttonTextAttributes]);
- return attributedButtonText.autorelease();
-}
-
-- (NSSize)cellSize {
- NSAttributedString* attributedTitle =
- [[self class] generateAttributedString:[self title]];
- NSSize textSize = [attributedTitle size];
-
- // Add 1 to maintain identical height w/ previous drawing code.
- textSize.height += 2 * kTopBottomTextPadding + 1;
- textSize.width += 2 * kLeftRightTextPadding;
- return textSize;
-}
-
-- (NSRect)drawTitle:(NSAttributedString*)title
- withFrame:(NSRect)frame
- inView:(NSView*)controlView {
- // Fuzz factor to adjust for the drop shadow. Based on visual inspection.
- frame.origin.y -= 1;
-
- ui::ScopedCGContextSmoothFonts fontSmoothing;
- NSAttributedString* attributedTitle =
- [[self class] generateAttributedString:[self title]];
- [attributedTitle drawInRect:frame];
- return frame;
-}
-
-- (void)drawBezelWithFrame:(NSRect)frame
- inView:(NSView*)controlView {
- NSColor* centerColor;
- NSColor* innerColor;
- NSColor* outerColor;
- CloseButtonHoverState hoverState =
- [base::mac::ObjCCastStrict<HoverButtonCocoa>(controlView) hoverState];
- // Leave a sliver of height 1 for the button drop shadow.
- frame.size.height -= 1;
-
- if (hoverState == kHoverStateMouseDown && [self isHighlighted]) {
- centerColor = skia::SkColorToSRGBNSColor(kPressedColor);
- innerColor = skia::SkColorToSRGBNSColor(kPressInnerRingColor);
- outerColor = skia::SkColorToSRGBNSColor(kPressOuterRingColor);
- } else {
- centerColor = hoverState == kHoverStateMouseOver ?
- skia::SkColorToSRGBNSColor(kHoverColor) :
- skia::SkColorToSRGBNSColor(kDefaultColor);
- innerColor = [self showsFirstResponder] ?
- skia::SkColorToSRGBNSColor(kFocusInnerRingColor) :
- skia::SkColorToSRGBNSColor(kInnerRingColor);
- outerColor = skia::SkColorToSRGBNSColor(kOuterRingColor);
- }
- {
- gfx::ScopedNSGraphicsContextSaveGState context;
- base::scoped_nsobject<NSShadow> shadow([[NSShadow alloc] init]);
- [shadow setShadowOffset:NSMakeSize(0, -1)];
- [shadow setShadowBlurRadius:1.0];
- [shadow setShadowColor:skia::SkColorToSRGBNSColor(kShadowColor)];
- [shadow set];
- [outerColor set];
-
- [[NSBezierPath bezierPathWithRoundedRect:frame
- xRadius:kCornerRadius
- yRadius:kCornerRadius] fill];
- }
-
- [innerColor set];
- [[NSBezierPath bezierPathWithRoundedRect:NSInsetRect(frame, 1, 1)
- xRadius:kCornerRadius
- yRadius:kCornerRadius] fill];
- [centerColor set];
- [[NSBezierPath bezierPathWithRoundedRect:NSInsetRect(frame, 2, 2)
- xRadius:kCornerRadius
- yRadius:kCornerRadius] fill];
-}
-
-@end
diff --git a/chromium/ui/base/cocoa/controls/blue_label_button_unittest.mm b/chromium/ui/base/cocoa/controls/blue_label_button_unittest.mm
deleted file mode 100644
index 33200cb11e6..00000000000
--- a/chromium/ui/base/cocoa/controls/blue_label_button_unittest.mm
+++ /dev/null
@@ -1,40 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ui/base/cocoa/controls/blue_label_button.h"
-
-#include "base/mac/scoped_nsobject.h"
-#include "base/macros.h"
-#import "testing/gtest_mac.h"
-#import "ui/base/test/cocoa_helper.h"
-
-namespace ui {
-namespace test {
-
-class BlueLabelButtonTest : public ui::CocoaTest {
- public:
- BlueLabelButtonTest() {}
-
- // ui::CocoaTest override:
- void SetUp() override;
-
- protected:
- base::scoped_nsobject<BlueLabelButton> blue_label_button_;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(BlueLabelButtonTest);
-};
-
-void BlueLabelButtonTest::SetUp() {
- blue_label_button_.reset([[BlueLabelButton alloc] initWithFrame:NSZeroRect]);
- [blue_label_button_ setTitle:@"Test Title"];
- [blue_label_button_ sizeToFit];
- ui::CocoaTest::SetUp();
- [[test_window() contentView] addSubview:blue_label_button_];
-}
-
-TEST_VIEW(BlueLabelButtonTest, blue_label_button_);
-
-} // namespace test
-} // namespace ui
diff --git a/chromium/ui/base/cocoa/controls/button_utils.h b/chromium/ui/base/cocoa/controls/button_utils.h
index 8759436e803..740c914140a 100644
--- a/chromium/ui/base/cocoa/controls/button_utils.h
+++ b/chromium/ui/base/cocoa/controls/button_utils.h
@@ -22,9 +22,6 @@ UI_BASE_EXPORT
+ (NSButton*)checkboxWithTitle:(NSString*)title;
-+ (NSButton*)linkWithTitle:(NSString*)title
- action:(SEL)action
- target:(id)target;
@end
#endif // UI_BASE_COCOA_CONTROLS_BUTTON_UTILS_H_
diff --git a/chromium/ui/base/cocoa/controls/button_utils.mm b/chromium/ui/base/cocoa/controls/button_utils.mm
index 51a3b44609b..0a74df2d7da 100644
--- a/chromium/ui/base/cocoa/controls/button_utils.mm
+++ b/chromium/ui/base/cocoa/controls/button_utils.mm
@@ -4,8 +4,6 @@
#import "ui/base/cocoa/controls/button_utils.h"
-#import "ui/base/cocoa/controls/hyperlink_button_cell.h"
-
@implementation ButtonUtils
+ (NSButton*)buttonWithTitle:(NSString*)title
@@ -31,18 +29,4 @@
return button;
}
-+ (NSButton*)linkWithTitle:(NSString*)title
- action:(SEL)action
- target:(id)target {
- NSButton* button = [[[NSButton alloc] initWithFrame:NSZeroRect] autorelease];
- // The cell has to be replaced before doing any of the other setup, or it will
- // not get the new configuration.
- [button setCell:[[[HyperlinkButtonCell alloc] init] autorelease]];
- [button setAction:action];
- [button setFont:[NSFont systemFontOfSize:[NSFont systemFontSize]]];
- [button setTarget:target];
- [button setTitle:title];
- return button;
-}
-
@end
diff --git a/chromium/ui/base/cocoa/controls/hover_image_menu_button.h b/chromium/ui/base/cocoa/controls/hover_image_menu_button.h
deleted file mode 100644
index 86914192e02..00000000000
--- a/chromium/ui/base/cocoa/controls/hover_image_menu_button.h
+++ /dev/null
@@ -1,29 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_BASE_COCOA_CONTROLS_HOVER_IMAGE_MENU_BUTTON_H_
-#define UI_BASE_COCOA_CONTROLS_HOVER_IMAGE_MENU_BUTTON_H_
-
-#import <Cocoa/Cocoa.h>
-
-#import "ui/base/cocoa/tracking_area.h"
-#include "ui/base/ui_base_export.h"
-
-@class HoverImageMenuButtonCell;
-
-// An NSPopUpButton that additionally tracks mouseover state and calls
-// [[self cell] setHovered:flag] when the hover state changes. Uses
-// HoverImageMenuButtonCell as the default cellClass. Note that the menu item at
-// index 0 is ignored and client code should populate it with a dummy item.
-UI_BASE_EXPORT
-@interface HoverImageMenuButton : NSPopUpButton {
- @private
- ui::ScopedCrTrackingArea trackingArea_;
-}
-
-- (HoverImageMenuButtonCell*)hoverImageMenuButtonCell;
-
-@end
-
-#endif // UI_BASE_COCOA_CONTROLS_HOVER_IMAGE_MENU_BUTTON_H_
diff --git a/chromium/ui/base/cocoa/controls/hover_image_menu_button.mm b/chromium/ui/base/cocoa/controls/hover_image_menu_button.mm
deleted file mode 100644
index 85a311885bd..00000000000
--- a/chromium/ui/base/cocoa/controls/hover_image_menu_button.mm
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ui/base/cocoa/controls/hover_image_menu_button.h"
-
-#include "base/mac/foundation_util.h"
-#import "ui/base/cocoa/controls/hover_image_menu_button_cell.h"
-
-@implementation HoverImageMenuButton
-
-+ (Class)cellClass {
- return [HoverImageMenuButtonCell class];
-}
-
-- (id)initWithFrame:(NSRect)frameRect
- pullsDown:(BOOL)flag {
- if ((self = [super initWithFrame:frameRect
- pullsDown:flag])) {
- trackingArea_.reset(
- [[CrTrackingArea alloc] initWithRect:NSZeroRect
- options:NSTrackingInVisibleRect |
- NSTrackingMouseEnteredAndExited |
- NSTrackingActiveInKeyWindow
- owner:self
- userInfo:nil]);
- [self addTrackingArea:trackingArea_.get()];
- }
- return self;
-}
-
-- (HoverImageMenuButtonCell*)hoverImageMenuButtonCell {
- return base::mac::ObjCCastStrict<HoverImageMenuButtonCell>([self cell]);
-}
-
-- (void)mouseEntered:(NSEvent*)theEvent {
- [[self cell] setHovered:YES];
-}
-
-- (void)mouseExited:(NSEvent*)theEvent {
- [[self cell] setHovered:NO];
-}
-
-@end
diff --git a/chromium/ui/base/cocoa/controls/hover_image_menu_button_cell.h b/chromium/ui/base/cocoa/controls/hover_image_menu_button_cell.h
deleted file mode 100644
index 249a74d78e4..00000000000
--- a/chromium/ui/base/cocoa/controls/hover_image_menu_button_cell.h
+++ /dev/null
@@ -1,35 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_BASE_COCOA_CONTROLS_HOVER_IMAGE_MENU_BUTTON_CELL_H_
-#define UI_BASE_COCOA_CONTROLS_HOVER_IMAGE_MENU_BUTTON_CELL_H_
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/mac/scoped_nsobject.h"
-#include "ui/base/ui_base_export.h"
-
-// A custom NSPopUpButtonCell that permits a hover image, and draws only an
-// image in its frame; no border, bezel or drop-down arrow. Use setDefaultImage:
-// to set the default image, setAlternateImage: to set the button shown while
-// the menu is active, and setHoverImage: for the mouseover hover image.
-UI_BASE_EXPORT
-@interface HoverImageMenuButtonCell : NSPopUpButtonCell {
- @private
- base::scoped_nsobject<NSImage> hoverImage_;
- BOOL hovered_;
-}
-
-@property(retain, nonatomic) NSImage* hoverImage;
-@property(assign, nonatomic, getter=isHovered) BOOL hovered;
-
-// Return the image that would be drawn based on the current state flags.
-- (NSImage*)imageToDraw;
-
-// Set the default image to show on the menu button.
-- (void)setDefaultImage:(NSImage*)defaultImage;
-
-@end
-
-#endif // UI_BASE_COCOA_CONTROLS_HOVER_IMAGE_MENU_BUTTON_CELL_H_
diff --git a/chromium/ui/base/cocoa/controls/hover_image_menu_button_cell.mm b/chromium/ui/base/cocoa/controls/hover_image_menu_button_cell.mm
deleted file mode 100644
index 10e93fb0b27..00000000000
--- a/chromium/ui/base/cocoa/controls/hover_image_menu_button_cell.mm
+++ /dev/null
@@ -1,69 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ui/base/cocoa/controls/hover_image_menu_button_cell.h"
-
-@implementation HoverImageMenuButtonCell
-
-@synthesize hovered = hovered_;
-
-- (id)initTextCell:(NSString*)stringValue
- pullsDown:(BOOL)pullDown {
- if ((self = [super initTextCell:stringValue
- pullsDown:pullDown])) {
- [self setUsesItemFromMenu:NO];
- }
- return self;
-}
-
-- (void)setHoverImage:(NSImage*)newImage {
- if ([hoverImage_ isEqual:newImage])
- return;
-
- hoverImage_.reset([newImage retain]);
- if (hovered_)
- [[self controlView] setNeedsDisplay:YES];
-}
-
-- (NSImage*)hoverImage {
- return hoverImage_;
-}
-
-- (void)setHovered:(BOOL)hovered {
- if (hovered_ == hovered)
- return;
-
- hovered_ = hovered;
- [[self controlView] setNeedsDisplay:YES];
-}
-
-- (NSImage*)imageToDraw {
- if ([self isHighlighted] && [self alternateImage])
- return [self alternateImage];
-
- if ([self isHovered] && [self hoverImage])
- return [self hoverImage];
-
- // Note that NSPopUpButtonCell updates the cell image when the [self menuItem]
- // changes.
- return [self image];
-}
-
-- (void)setDefaultImage:(NSImage*)defaultImage {
- base::scoped_nsobject<NSMenuItem> buttonMenuItem([[NSMenuItem alloc] init]);
- [buttonMenuItem setImage:defaultImage];
- [self setMenuItem:buttonMenuItem];
-}
-
-- (void)drawWithFrame:(NSRect)cellFrame
- inView:(NSView*)controlView {
- [[self imageToDraw] drawInRect:cellFrame
- fromRect:NSZeroRect
- operation:NSCompositeSourceOver
- fraction:1.0
- respectFlipped:YES
- hints:nil];
-}
-
-@end
diff --git a/chromium/ui/base/cocoa/controls/hover_image_menu_button_unittest.mm b/chromium/ui/base/cocoa/controls/hover_image_menu_button_unittest.mm
deleted file mode 100644
index ea6bd91f18a..00000000000
--- a/chromium/ui/base/cocoa/controls/hover_image_menu_button_unittest.mm
+++ /dev/null
@@ -1,175 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ui/base/cocoa/controls/hover_image_menu_button.h"
-
-#include "base/mac/foundation_util.h"
-#include "base/macros.h"
-#import "testing/gtest_mac.h"
-#import "ui/base/cocoa/controls/hover_image_menu_button_cell.h"
-#import "ui/base/test/cocoa_helper.h"
-#include "ui/events/test/cocoa_test_event_utils.h"
-
-namespace ui {
-
-namespace {
-
-// Test initialization and display of the NSPopUpButton that shows the drop-
-// down menu. Don't try to show the menu, since it will block the thread.
-class HoverImageMenuButtonTest : public CocoaTest {
- public:
- HoverImageMenuButtonTest() {}
-
- // CocoaTest override:
- void SetUp() override;
-
- protected:
- base::scoped_nsobject<HoverImageMenuButton> menu_button_;
- base::scoped_nsobject<NSImage> normal_;
- base::scoped_nsobject<NSImage> pressed_;
- base::scoped_nsobject<NSImage> hovered_;
-
- DISALLOW_COPY_AND_ASSIGN(HoverImageMenuButtonTest);
-};
-
-void HoverImageMenuButtonTest::SetUp() {
- menu_button_.reset(
- [[HoverImageMenuButton alloc] initWithFrame:NSMakeRect(0, 0, 50, 30)
- pullsDown:YES]);
-
- normal_.reset([base::mac::ObjCCastStrict<NSImage>(
- [NSImage imageNamed:NSImageNameStatusAvailable]) retain]);
- pressed_.reset([base::mac::ObjCCastStrict<NSImage>(
- [NSImage imageNamed:NSImageNameStatusUnavailable]) retain]);
- hovered_.reset([base::mac::ObjCCastStrict<NSImage>(
- [NSImage imageNamed:NSImageNameStatusPartiallyAvailable]) retain]);
- [[menu_button_ hoverImageMenuButtonCell] setDefaultImage:normal_];
- [[menu_button_ hoverImageMenuButtonCell] setAlternateImage:pressed_];
- [[menu_button_ hoverImageMenuButtonCell] setHoverImage:hovered_];
-
- CocoaTest::SetUp();
- [[test_window() contentView] addSubview:menu_button_];
-}
-
-} // namespace
-
-TEST_VIEW(HoverImageMenuButtonTest, menu_button_);
-
-// Tests that the correct image is chosen, depending on the cell's state flags.
-TEST_F(HoverImageMenuButtonTest, CheckImagesForState) {
- EXPECT_FALSE([[menu_button_ cell] isHovered]);
- EXPECT_FALSE([[menu_button_ cell] isHighlighted]);
- EXPECT_NSEQ(normal_, [[menu_button_ cell] imageToDraw]);
- [menu_button_ display];
-
- [[menu_button_ cell] setHovered:YES];
- EXPECT_TRUE([[menu_button_ cell] isHovered]);
- EXPECT_FALSE([[menu_button_ cell] isHighlighted]);
- EXPECT_NSEQ(hovered_, [[menu_button_ cell] imageToDraw]);
- [menu_button_ display];
-
- // Highlighted takes precendece over hover.
- [[menu_button_ cell] setHighlighted:YES];
- EXPECT_TRUE([[menu_button_ cell] isHovered]);
- EXPECT_TRUE([[menu_button_ cell] isHighlighted]);
- EXPECT_NSEQ(pressed_, [[menu_button_ cell] imageToDraw]);
- [menu_button_ display];
-
- [[menu_button_ cell] setHovered:NO];
- EXPECT_FALSE([[menu_button_ cell] isHovered]);
- EXPECT_TRUE([[menu_button_ cell] isHighlighted]);
- EXPECT_NSEQ(pressed_, [[menu_button_ cell] imageToDraw]);
- [menu_button_ display];
-
- [[menu_button_ cell] setHighlighted:NO];
- EXPECT_FALSE([[menu_button_ cell] isHovered]);
- EXPECT_FALSE([[menu_button_ cell] isHighlighted]);
- EXPECT_NSEQ(normal_, [[menu_button_ cell] imageToDraw]);
- [menu_button_ display];
-}
-
-// Tests that calling the various setXImage functions calls setNeedsDisplay.
-TEST_F(HoverImageMenuButtonTest, NewImageCausesDisplay) {
- [menu_button_ display];
- EXPECT_FALSE([menu_button_ needsDisplay]);
-
- // Uses setDefaultImage rather than setImage to ensure the image goes into the
- // NSPopUpButtonCell's menuItem. It is then accessible using [NSCell image].
- EXPECT_NSEQ(normal_, [[menu_button_ cell] image]);
- [[menu_button_ cell] setDefaultImage:pressed_];
- EXPECT_NSEQ(pressed_, [[menu_button_ cell] image]);
- EXPECT_TRUE([menu_button_ needsDisplay]);
- [menu_button_ display];
- EXPECT_FALSE([menu_button_ needsDisplay]);
-
- // Highlighting the cell requires a redisplay.
- [[menu_button_ cell] setHighlighted:YES];
- EXPECT_TRUE([menu_button_ needsDisplay]);
- [menu_button_ display];
- EXPECT_FALSE([menu_button_ needsDisplay]);
-
- // setAlternateImage comes from NSButtonCell. Ensure the added setHover*
- // behaviour matches.
- [[menu_button_ cell] setAlternateImage:normal_];
- EXPECT_TRUE([menu_button_ needsDisplay]);
- [menu_button_ display];
- EXPECT_FALSE([menu_button_ needsDisplay]);
-
- // Setting the same image should not cause a redisplay.
- [[menu_button_ cell] setAlternateImage:normal_];
- EXPECT_FALSE([menu_button_ needsDisplay]);
-
- // Unhighlighting requires a redisplay.
- [[menu_button_ cell] setHighlighted:NO];
- EXPECT_TRUE([menu_button_ needsDisplay]);
- [menu_button_ display];
- EXPECT_FALSE([menu_button_ needsDisplay]);
-
- // Changing hover state requires a redisplay.
- [[menu_button_ cell] setHovered:YES];
- EXPECT_TRUE([menu_button_ needsDisplay]);
- [menu_button_ display];
- EXPECT_FALSE([menu_button_ needsDisplay]);
-
- // setHoverImage comes directly from storage in HoverImageMenuButtonCell.
- [[menu_button_ cell] setHoverImage:normal_];
- EXPECT_TRUE([menu_button_ needsDisplay]);
- [menu_button_ display];
- EXPECT_FALSE([menu_button_ needsDisplay]);
-
- // Setting the same image should not cause a redisplay.
- [[menu_button_ cell] setHoverImage:normal_];
- EXPECT_FALSE([menu_button_ needsDisplay]);
-
- // Unhover requires a redisplay.
- [[menu_button_ cell] setHovered:NO];
- EXPECT_TRUE([menu_button_ needsDisplay]);
- [menu_button_ display];
- EXPECT_FALSE([menu_button_ needsDisplay]);
-
- // Changing the image while not hovered should not require a redisplay.
- [[menu_button_ cell] setHoverImage:pressed_];
- EXPECT_FALSE([menu_button_ needsDisplay]);
-}
-
-// Test that the mouse enter and exit is properly handled, to set hover state.
-TEST_F(HoverImageMenuButtonTest, SimulateMouseEnterExit) {
- [menu_button_ display];
- EXPECT_FALSE([menu_button_ needsDisplay]);
- EXPECT_NSEQ(normal_, [[menu_button_ cell] imageToDraw]);
-
- [menu_button_ mouseEntered:cocoa_test_event_utils::EnterEvent()];
- EXPECT_TRUE([menu_button_ needsDisplay]);
- EXPECT_NSEQ(hovered_, [[menu_button_ cell] imageToDraw]);
- [menu_button_ display];
- EXPECT_FALSE([menu_button_ needsDisplay]);
-
- [menu_button_ mouseExited:cocoa_test_event_utils::ExitEvent()];
- EXPECT_TRUE([menu_button_ needsDisplay]);
- EXPECT_NSEQ(normal_, [[menu_button_ cell] imageToDraw]);
- [menu_button_ display];
- EXPECT_FALSE([menu_button_ needsDisplay]);
-}
-
-} // namespace ui
diff --git a/chromium/ui/base/cocoa/controls/hyperlink_button_cell.h b/chromium/ui/base/cocoa/controls/hyperlink_button_cell.h
deleted file mode 100644
index f8753e48660..00000000000
--- a/chromium/ui/base/cocoa/controls/hyperlink_button_cell.h
+++ /dev/null
@@ -1,58 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_BASE_COCOA_CONTROLS_HYPERLINK_BUTTON_CELL_H_
-#define UI_BASE_COCOA_CONTROLS_HYPERLINK_BUTTON_CELL_H_
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/mac/scoped_nsobject.h"
-#include "ui/base/ui_base_export.h"
-
-// A HyperlinkButtonCell is used to create an NSButton that looks and acts
-// like a hyperlink. The default styling is to look like blue (#3367D6) text
-// with no underline and to have the pointingHand cursor on mouse over.
-//
-// To use in Interface Builder:
-// 1. Drag out an NSButton.
-// 2. Double click on the button so you have the cell component selected.
-// 3. In the Identity panel of the inspector, set the custom class to this.
-// 4. In the Attributes panel, change the Bezel to Square.
-// 5. In the Size panel, set the Height to 16.
-//
-// Use this if all of your text is a link. If you need text that contains
-// embedded links but also regular text, use HyperlinkTextView.
-
-namespace hyperlink_button_cell {
-
-enum class UI_BASE_EXPORT UnderlineBehavior {
- ALWAYS,
- NEVER,
- ON_HOVER,
-};
-
-} // namespace hyperlink_button_cell
-
-UI_BASE_EXPORT
-@interface HyperlinkButtonCell : NSButtonCell {
- base::scoped_nsobject<NSColor> textColor_;
- hyperlink_button_cell::UnderlineBehavior underlineBehavior_;
- BOOL mouseIsInside_;
-}
-@property(nonatomic, retain) NSColor* textColor;
-@property(nonatomic, assign) hyperlink_button_cell::UnderlineBehavior
- underlineBehavior;
-
-+ (NSColor*)defaultTextColor;
-
-// Helper function to create a button with HyperLinkButtonCell as its cell.
-+ (NSButton*)buttonWithString:(NSString*)string;
-
-@end
-
-@interface HyperlinkButtonCell (ExposedForTesting)
-- (NSDictionary*)linkAttributes;
-@end
-
-#endif // UI_BASE_COCOA_CONTROLS_HYPERLINK_BUTTON_CELL_H_
diff --git a/chromium/ui/base/cocoa/controls/hyperlink_button_cell.mm b/chromium/ui/base/cocoa/controls/hyperlink_button_cell.mm
deleted file mode 100644
index 754be72f613..00000000000
--- a/chromium/ui/base/cocoa/controls/hyperlink_button_cell.mm
+++ /dev/null
@@ -1,167 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ui/base/cocoa/controls/hyperlink_button_cell.h"
-
-using hyperlink_button_cell::UnderlineBehavior;
-
-@interface HyperlinkButtonCell ()
-- (void)customizeButtonCell;
-@end
-
-@implementation HyperlinkButtonCell
-
-@dynamic textColor;
-@synthesize underlineBehavior = underlineBehavior_;
-
-+ (NSColor*)defaultTextColor {
- // Equates to rgb(51, 103, 214) or #3367D6.
- return [NSColor colorWithCalibratedRed:51.0/255.0
- green:103.0/255.0
- blue:214.0/255.0
- alpha:1.0];
-}
-
-+ (NSButton*)buttonWithString:(NSString*)string {
- NSButton* button = [[[NSButton alloc] initWithFrame:NSZeroRect] autorelease];
- base::scoped_nsobject<HyperlinkButtonCell> cell(
- [[HyperlinkButtonCell alloc] initTextCell:string]);
- [cell setAlignment:NSLeftTextAlignment];
- [button setCell:cell.get()];
- [button setBezelStyle:NSRegularSquareBezelStyle];
- return button;
-}
-
-// Designated initializer.
-- (id)init {
- if ((self = [super init])) {
- [self customizeButtonCell];
- }
- return self;
-}
-
-// Initializer called when the cell is loaded from the NIB.
-- (id)initWithCoder:(NSCoder*)aDecoder {
- if ((self = [super initWithCoder:aDecoder])) {
- [self customizeButtonCell];
- }
- return self;
-}
-
-// Initializer for code-based creation.
-- (id)initTextCell:(NSString*)title {
- if ((self = [super initTextCell:title])) {
- [self customizeButtonCell];
- }
- return self;
-}
-
-- (id)copyWithZone:(NSZone*)zone {
- NSColor* color = textColor_.release();
- HyperlinkButtonCell* cell = [super copyWithZone:zone];
- cell->textColor_.reset([color copy]);
- textColor_.reset(color);
- return cell;
-}
-
-// Because an NSButtonCell has multiple initializers, this method performs the
-// common cell customization code.
-- (void)customizeButtonCell {
- [self setBordered:NO];
- [self setTextColor:[HyperlinkButtonCell defaultTextColor]];
- [self setUnderlineBehavior:UnderlineBehavior::NEVER];
-
- CGFloat fontSize = [NSFont systemFontSizeForControlSize:[self controlSize]];
- NSFont* font = [NSFont controlContentFontOfSize:fontSize];
- [self setFont:font];
-
- // Do not change button appearance when we are pushed.
- [self setHighlightsBy:NSNoCellMask];
-
- // We need to set this so that we can override |-mouseEntered:| and
- // |-mouseExited:| to change the cursor style on hover states.
- [self setShowsBorderOnlyWhileMouseInside:YES];
-}
-
-- (void)setControlSize:(NSControlSize)size {
- [super setControlSize:size];
- [self customizeButtonCell]; // recompute |font|.
-}
-
-// Creates the NSDictionary of attributes for the attributed string.
-- (NSDictionary*)linkAttributes {
- NSUInteger underlineMask = NSUnderlineStyleNone;
- if (underlineBehavior_ == UnderlineBehavior::ALWAYS ||
- (mouseIsInside_ && [self isEnabled] &&
- underlineBehavior_ == UnderlineBehavior::ON_HOVER)) {
- underlineMask = NSUnderlinePatternSolid | NSUnderlineStyleSingle;
- }
-
- base::scoped_nsobject<NSMutableParagraphStyle> paragraphStyle(
- [[NSParagraphStyle defaultParagraphStyle] mutableCopy]);
- [paragraphStyle setAlignment:[self alignment]];
- [paragraphStyle setLineBreakMode:[self lineBreakMode]];
-
- return [NSDictionary dictionaryWithObjectsAndKeys:
- [self textColor], NSForegroundColorAttributeName,
- [NSNumber numberWithInt:underlineMask], NSUnderlineStyleAttributeName,
- [self font], NSFontAttributeName,
- [NSCursor pointingHandCursor], NSCursorAttributeName,
- paragraphStyle.get(), NSParagraphStyleAttributeName,
- nil
- ];
-}
-
-// Override the drawing for the cell so that the custom style attributes
-// can always be applied and so that ellipses will appear when appropriate.
-- (NSRect)drawTitle:(NSAttributedString*)title
- withFrame:(NSRect)frame
- inView:(NSView*)controlView {
- NSDictionary* linkAttributes = [self linkAttributes];
- NSString* plainTitle = [title string];
- [plainTitle drawWithRect:frame
- options:(NSStringDrawingUsesLineFragmentOrigin |
- NSStringDrawingTruncatesLastVisibleLine)
- attributes:linkAttributes];
- return frame;
-}
-
-// Override the default behavior to draw the border. Instead, change the cursor.
-- (void)mouseEntered:(NSEvent*)event {
- mouseIsInside_ = YES;
- if ([self isEnabled])
- [[NSCursor pointingHandCursor] push];
- else
- [[NSCursor currentCursor] push];
- if (underlineBehavior_ == UnderlineBehavior::ON_HOVER)
- [[self controlView] setNeedsDisplay:YES];
-}
-
-- (void)mouseExited:(NSEvent*)event {
- mouseIsInside_ = NO;
- [NSCursor pop];
- if (underlineBehavior_ == UnderlineBehavior::ON_HOVER)
- [[self controlView] setNeedsDisplay:YES];
-}
-
-// Setters and getters.
-- (NSColor*)textColor {
- if ([self isEnabled])
- return textColor_.get();
- else
- return [NSColor disabledControlTextColor];
-}
-
-- (void)setTextColor:(NSColor*)color {
- textColor_.reset([color retain]);
-}
-
-// Override so that |-sizeToFit| works better with this type of cell.
-- (NSSize)cellSize {
- NSSize size = [super cellSize];
- size.width += 2;
- return size;
-}
-
-@end
diff --git a/chromium/ui/base/cocoa/controls/hyperlink_button_cell_unittest.mm b/chromium/ui/base/cocoa/controls/hyperlink_button_cell_unittest.mm
deleted file mode 100644
index 2caf8a6690f..00000000000
--- a/chromium/ui/base/cocoa/controls/hyperlink_button_cell_unittest.mm
+++ /dev/null
@@ -1,143 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ui/base/cocoa/controls/hyperlink_button_cell.h"
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/mac/foundation_util.h"
-#include "base/mac/scoped_nsobject.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#import "testing/gtest_mac.h"
-#include "testing/platform_test.h"
-#import "ui/base/test/cocoa_helper.h"
-#include "ui/events/test/cocoa_test_event_utils.h"
-
-namespace ui {
-
-namespace {
-
-class HyperlinkButtonCellTest : public CocoaTest {
- public:
- HyperlinkButtonCellTest() {
- NSRect frame = NSMakeRect(0, 0, 50, 30);
- base::scoped_nsobject<NSButton> view(
- [[NSButton alloc] initWithFrame:frame]);
- view_ = view.get();
- base::scoped_nsobject<HyperlinkButtonCell> cell(
- [[HyperlinkButtonCell alloc] initTextCell:@"Testing"]);
- cell_ = cell.get();
- [view_ setCell:cell_];
- [[test_window() contentView] addSubview:view_];
- }
-
- void TestCellCustomization(HyperlinkButtonCell* cell) {
- EXPECT_FALSE([cell isBordered]);
- EXPECT_EQ(NSNoCellMask, [cell_ highlightsBy]);
- EXPECT_TRUE([cell showsBorderOnlyWhileMouseInside]);
- EXPECT_TRUE([cell textColor]);
- }
-
- protected:
- bool HasUnderlineAttribute(NSDictionary* attributes) {
- NSNumber* number = base::mac::ObjCCastStrict<NSNumber>(
- [attributes objectForKey:NSUnderlineStyleAttributeName]);
- return [number unsignedIntegerValue] != 0;
- }
-
- NSButton* view_;
- HyperlinkButtonCell* cell_;
-};
-
-TEST_VIEW(HyperlinkButtonCellTest, view_)
-
-// Tests the three designated intializers.
-TEST_F(HyperlinkButtonCellTest, Initializers) {
- TestCellCustomization(cell_); // |-initTextFrame:|
- base::scoped_nsobject<HyperlinkButtonCell> cell(
- [[HyperlinkButtonCell alloc] init]);
- TestCellCustomization(cell.get());
-
- // Need to create a dummy archiver to test |-initWithCoder:|.
- NSData* emptyData = [NSKeyedArchiver archivedDataWithRootObject:@""];
- NSCoder* coder =
- [[[NSKeyedUnarchiver alloc] initForReadingWithData:emptyData] autorelease];
- cell.reset([[HyperlinkButtonCell alloc] initWithCoder:coder]);
- TestCellCustomization(cell);
-}
-
-// Test set color.
-TEST_F(HyperlinkButtonCellTest, SetTextColor) {
- NSColor* textColor = [NSColor redColor];
- EXPECT_NE(textColor, [cell_ textColor]);
- [cell_ setTextColor:textColor];
- EXPECT_EQ(textColor, [cell_ textColor]);
-}
-
-// Test mouse events.
-TEST_F(HyperlinkButtonCellTest, MouseHover) {
- [[NSCursor disappearingItemCursor] push]; // Set a known state.
- [cell_ mouseEntered:cocoa_test_event_utils::EnterEvent()];
- EXPECT_EQ([NSCursor pointingHandCursor], [NSCursor currentCursor]);
- [cell_ mouseExited:cocoa_test_event_utils::ExitEvent()];
- EXPECT_EQ([NSCursor disappearingItemCursor], [NSCursor currentCursor]);
- [NSCursor pop];
-}
-
-// Test mouse events when button is disabled. {
-TEST_F(HyperlinkButtonCellTest, MouseHoverWhenDisabled) {
- [cell_ setEnabled:NO];
-
- [[NSCursor disappearingItemCursor] push]; // Set a known state.
- [cell_ mouseEntered:cocoa_test_event_utils::EnterEvent()];
- EXPECT_EQ([NSCursor disappearingItemCursor], [NSCursor currentCursor]);
-
- [cell_ mouseExited:cocoa_test_event_utils::ExitEvent()];
- EXPECT_EQ([NSCursor disappearingItemCursor], [NSCursor currentCursor]);
- [NSCursor pop];
- [NSCursor pop];
-}
-
-// Test underline on hover.
-TEST_F(HyperlinkButtonCellTest, UnderlineOnHover) {
- // Default is for no underline.
- EXPECT_FALSE(HasUnderlineAttribute([cell_ linkAttributes]));
- [cell_ mouseEntered:cocoa_test_event_utils::EnterEvent()];
- EXPECT_FALSE(HasUnderlineAttribute([cell_ linkAttributes]));
- [cell_ mouseExited:cocoa_test_event_utils::ExitEvent()];
- EXPECT_FALSE(HasUnderlineAttribute([cell_ linkAttributes]));
-
- // Setting behavior to ALWAYS will result in always having an underline.
- [cell_ setUnderlineBehavior:hyperlink_button_cell::UnderlineBehavior::ALWAYS];
- EXPECT_TRUE(HasUnderlineAttribute([cell_ linkAttributes]));
- [cell_ mouseEntered:cocoa_test_event_utils::EnterEvent()];
- EXPECT_TRUE(HasUnderlineAttribute([cell_ linkAttributes]));
- [cell_ mouseExited:cocoa_test_event_utils::ExitEvent()];
- EXPECT_TRUE(HasUnderlineAttribute([cell_ linkAttributes]));
-
- // Setting behavior to ON_HOVER will result in only underlining when the
- // mouse is hovering over the link.
- [cell_ setUnderlineBehavior:
- hyperlink_button_cell::UnderlineBehavior::ON_HOVER];
- EXPECT_FALSE(HasUnderlineAttribute([cell_ linkAttributes]));
- [cell_ mouseEntered:cocoa_test_event_utils::EnterEvent()];
- EXPECT_TRUE(HasUnderlineAttribute([cell_ linkAttributes]));
- [cell_ mouseExited:cocoa_test_event_utils::ExitEvent()];
- EXPECT_FALSE(HasUnderlineAttribute([cell_ linkAttributes]));
-}
-
-TEST_F(HyperlinkButtonCellTest, Copy) {
- base::scoped_nsobject<HyperlinkButtonCell> cell1([[HyperlinkButtonCell alloc]
- initTextCell:@"Cell"]);
- [cell1 setTextColor:[NSColor redColor]];
-
- base::scoped_nsobject<HyperlinkButtonCell> cell2([cell1 copy]);
- EXPECT_NSEQ([cell1 textColor], [cell2 textColor]);
- [cell1 setTextColor:[NSColor purpleColor]];
- [cell2 setTextColor:[NSColor greenColor]];
-}
-
-} // namespace
-
-} // namespace ui
diff --git a/chromium/ui/base/cocoa/controls/hyperlink_text_view.h b/chromium/ui/base/cocoa/controls/hyperlink_text_view.h
deleted file mode 100644
index 0a0cb4406bd..00000000000
--- a/chromium/ui/base/cocoa/controls/hyperlink_text_view.h
+++ /dev/null
@@ -1,39 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import <Cocoa/Cocoa.h>
-
-#include "ui/base/ui_base_export.h"
-
-@class NSColor;
-
-// HyperlinkTextView is an NSTextView subclass for unselectable, linkable text.
-// This subclass doesn't show the text caret or IBeamCursor, whereas the base
-// class NSTextView displays both with full keyboard accessibility enabled.
-UI_BASE_EXPORT
-@interface HyperlinkTextView : NSTextView {
- @private
- BOOL refusesFirstResponder_;
- BOOL drawsBackgroundUsingSuperview_;
- BOOL isValidLink_;
-}
-
-@property(nonatomic, assign) BOOL drawsBackgroundUsingSuperview;
-
-// Set the |message| displayed by the HyperlinkTextView, using |font| and
-// |messageColor|.
-- (void)setMessage:(NSString*)message
- withFont:(NSFont*)font
- messageColor:(NSColor*)messageColor;
-
-// Marks a |range| within the given message as a link. Pass nil as the url to
-// create a link that can neither be copied nor dragged.
-- (void)addLinkRange:(NSRange)range
- withURL:(NSString*)url
- linkColor:(NSColor*)linkColor;
-
-// This is NO (by default) if the view rejects first responder status.
-- (void)setRefusesFirstResponder:(BOOL)refusesFirstResponder;
-
-@end
diff --git a/chromium/ui/base/cocoa/controls/hyperlink_text_view.mm b/chromium/ui/base/cocoa/controls/hyperlink_text_view.mm
deleted file mode 100644
index 86204e99e57..00000000000
--- a/chromium/ui/base/cocoa/controls/hyperlink_text_view.mm
+++ /dev/null
@@ -1,179 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ui/base/cocoa/controls/hyperlink_text_view.h"
-
-#include "base/logging.h"
-#include "base/mac/scoped_nsobject.h"
-#include "ui/base/cocoa/nsview_additions.h"
-
-// The baseline shift for text in the NSTextView.
-const float kTextBaselineShift = -1.0;
-
-@interface HyperlinkTextView(Private)
-// Initialize the NSTextView properties for this subclass.
-- (void)configureTextView;
-
-// Change the current IBeamCursor to an arrowCursor.
-- (void)fixupCursor;
-@end
-
-@implementation HyperlinkTextView
-
-@synthesize drawsBackgroundUsingSuperview = drawsBackgroundUsingSuperview_;
-
-- (id)initWithCoder:(NSCoder*)decoder {
- if ((self = [super initWithCoder:decoder]))
- [self configureTextView];
- return self;
-}
-
-- (id)initWithFrame:(NSRect)frameRect {
- if ((self = [super initWithFrame:frameRect]))
- [self configureTextView];
- return self;
-}
-
-- (BOOL)acceptsFirstResponder {
- return !refusesFirstResponder_;
-}
-
-- (void)drawViewBackgroundInRect:(NSRect)rect {
- if (drawsBackgroundUsingSuperview_)
- [self cr_drawUsingAncestor:[self superview] inRect:rect];
- else
- [super drawViewBackgroundInRect:rect];
-}
-
-// Never draw the insertion point (otherwise, it shows up without any user
-// action if full keyboard accessibility is enabled).
-- (BOOL)shouldDrawInsertionPoint {
- return NO;
-}
-
-- (NSRange)selectionRangeForProposedRange:(NSRange)proposedSelRange
- granularity:(NSSelectionGranularity)granularity {
- // Return a range of length 0 to prevent text selection. Note that the start
- // of the range (the first argument) is treated as the position of the
- // subsequent click so it must not be 0. If it is, links that begin at a
- // non-zero position in the text will not function correctly when they are
- // clicked in such a way as to look like a possible text selection.
- return NSMakeRange(proposedSelRange.location, 0);
-}
-
-// Convince NSTextView to not show an I-Beam cursor when the cursor is over the
-// text view but not over actual text.
-//
-// http://www.mail-archive.com/cocoa-dev@lists.apple.com/msg10791.html
-// "NSTextView sets the cursor over itself dynamically, based on considerations
-// including the text under the cursor. It does so in -mouseEntered:,
-// -mouseMoved:, and -cursorUpdate:, so those would be points to consider
-// overriding."
-- (void)mouseMoved:(NSEvent*)e {
- [super mouseMoved:e];
- [self fixupCursor];
-}
-
-- (void)mouseEntered:(NSEvent*)e {
- [super mouseEntered:e];
- [self fixupCursor];
-}
-
-- (void)cursorUpdate:(NSEvent*)e {
- [super cursorUpdate:e];
- [self fixupCursor];
-}
-
-- (void)configureTextView {
- [self setEditable:NO];
- [self setDrawsBackground:NO];
- [self setHorizontallyResizable:NO];
- [self setVerticallyResizable:NO];
-
- // When text is rendered, linkTextAttributes override anything set via
- // addAttributes for text that has NSLinkAttributeName. Set to nil to allow
- // custom attributes to take precedence.
- [self setLinkTextAttributes:nil];
- [self setDisplaysLinkToolTips:NO];
-
- refusesFirstResponder_ = NO;
- drawsBackgroundUsingSuperview_ = NO;
- isValidLink_ = NO;
-}
-
-- (void)fixupCursor {
- if ([[NSCursor currentCursor] isEqual:[NSCursor IBeamCursor]])
- [[NSCursor arrowCursor] set];
-}
-
-// Only allow contextual menus (which allow copying of the link URL) if the link
-// is a valid one.
-- (NSMenu*)menuForEvent:(NSEvent*)e {
- if (isValidLink_)
- return [super menuForEvent:e];
-
- return nil;
-}
-
-// Only allow dragging of valid links.
-- (BOOL)dragSelectionWithEvent:(NSEvent*)event
- offset:(NSSize)mouseOffset
- slideBack:(BOOL)slideBack {
- if (isValidLink_) {
- return [super dragSelectionWithEvent:event
- offset:mouseOffset
- slideBack:slideBack];
- }
-
- return NO;
-}
-
-- (void)setMessage:(NSString*)message
- withFont:(NSFont*)font
- messageColor:(NSColor*)messageColor {
- // Create an attributes dictionary for the message and link.
- NSDictionary* attributes = @{
- NSForegroundColorAttributeName : messageColor,
- NSCursorAttributeName : [NSCursor arrowCursor],
- NSFontAttributeName : font,
- NSBaselineOffsetAttributeName : @(kTextBaselineShift)
- };
-
- // Create the attributed string for the message.
- base::scoped_nsobject<NSAttributedString> attributedMessage(
- [[NSMutableAttributedString alloc] initWithString:message
- attributes:attributes]);
-
- // Update the text view with the new text.
- [[self textStorage] setAttributedString:attributedMessage];
-}
-
-- (void)addLinkRange:(NSRange)range
- withURL:(NSString*)url
- linkColor:(NSColor*)linkColor {
- // If a URL is provided, make sure it is a valid one.
- if (url) {
- DCHECK_GT([url length], 0u);
- DCHECK([NSURL URLWithString:url]);
- isValidLink_ = YES;
- } else {
- url = @"";
- isValidLink_ = NO;
- }
- NSDictionary* attributes = @{
- NSForegroundColorAttributeName : linkColor,
- NSUnderlineStyleAttributeName : @(YES),
- NSCursorAttributeName : [NSCursor pointingHandCursor],
- NSLinkAttributeName : url,
- NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle)
- };
-
- [[self textStorage] addAttributes:attributes range:range];
-}
-
-- (void)setRefusesFirstResponder:(BOOL)refusesFirstResponder {
- refusesFirstResponder_ = refusesFirstResponder;
-}
-
-@end
diff --git a/chromium/ui/base/cocoa/controls/hyperlink_text_view_unittest.mm b/chromium/ui/base/cocoa/controls/hyperlink_text_view_unittest.mm
deleted file mode 100644
index d4fbd072453..00000000000
--- a/chromium/ui/base/cocoa/controls/hyperlink_text_view_unittest.mm
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ui/base/cocoa/controls/hyperlink_text_view.h"
-
-#include "base/mac/scoped_nsobject.h"
-#include "testing/gtest_mac.h"
-#import "ui/base/test/cocoa_helper.h"
-
-namespace {
-
-class HyperlinkTextViewTest : public ui::CocoaTest {
- public:
- HyperlinkTextViewTest() {
- NSRect frame = NSMakeRect(0, 0, 50, 50);
- base::scoped_nsobject<HyperlinkTextView> view(
- [[HyperlinkTextView alloc] initWithFrame:frame]);
- view_ = view.get();
- [[test_window() contentView] addSubview:view_];
- }
-
- NSFont* GetDefaultFont() {
- return [NSFont labelFontOfSize:
- [NSFont systemFontSizeForControlSize:NSRegularControlSize]];
- }
-
- NSDictionary* GetDefaultTextAttributes() {
- const float kTextBaselineShift = -1.0;
- return @{
- NSForegroundColorAttributeName : [NSColor blackColor],
- NSCursorAttributeName : [NSCursor arrowCursor],
- NSFontAttributeName : GetDefaultFont(),
- NSBaselineOffsetAttributeName : @(kTextBaselineShift)
- };
- }
-
- NSMutableDictionary* GetDefaultLinkAttributes() {
- if (!linkAttributes_.get()) {
- linkAttributes_.reset(
- [[NSMutableDictionary dictionaryWithDictionary:
- GetDefaultTextAttributes()] retain]);
- [linkAttributes_ addEntriesFromDictionary:@{
- NSForegroundColorAttributeName : [NSColor blueColor],
- NSUnderlineStyleAttributeName : @(YES),
- NSCursorAttributeName : [NSCursor pointingHandCursor],
- NSUnderlineStyleAttributeName : @(NSUnderlineStyleSingle),
- NSLinkAttributeName : @""
- }];
- }
- return [NSMutableDictionary dictionaryWithDictionary:linkAttributes_];
- }
-
- HyperlinkTextView* view_;
-
- private:
- base::scoped_nsobject<NSMutableDictionary> linkAttributes_;
-};
-
-TEST_VIEW(HyperlinkTextViewTest, view_);
-
-TEST_F(HyperlinkTextViewTest, TestSelectionRange) {
- NSRange actualRange;
-
- // The length of the selection range should be 0.
- actualRange = [view_ selectionRangeForProposedRange:NSMakeRange(0, 20)
- granularity:NSSelectByCharacter];
- EXPECT_TRUE(NSEqualRanges(NSMakeRange(0, 0), actualRange));
-
- // While the location should always match the location of the proposed range.
- actualRange = [view_ selectionRangeForProposedRange:NSMakeRange(50, 100)
- granularity:NSSelectByCharacter];
- EXPECT_TRUE(NSEqualRanges(NSMakeRange(50, 0), actualRange));
-}
-
-TEST_F(HyperlinkTextViewTest, TestViewConfiguration) {
- EXPECT_FALSE([view_ isEditable]);
- EXPECT_FALSE([view_ drawsBackground]);
- EXPECT_FALSE([view_ isHorizontallyResizable]);
- EXPECT_FALSE([view_ isVerticallyResizable]);
-}
-
-TEST_F(HyperlinkTextViewTest, TestSetMessage) {
- // Verifies setMessage sets text and attributes properly.
- NSString* message = @"Test message";
- [view_ setMessage:message
- withFont:GetDefaultFont()
- messageColor:[NSColor blackColor]];
- EXPECT_NSEQ(@"Test message", [[view_ textStorage] string]);
-
- NSDictionary* attributes;
- NSRange rangeLimit = NSMakeRange(0, [message length]);
- NSRange range;
- attributes = [[view_ textStorage] attributesAtIndex:0
- longestEffectiveRange:&range
- inRange:rangeLimit];
- EXPECT_EQ(0U, range.location);
- EXPECT_EQ([message length], range.length);
- EXPECT_NSEQ(GetDefaultTextAttributes(), attributes);
-}
-
-TEST_F(HyperlinkTextViewTest, TestAddLinkRange) {
- NSString* message = @"One Two Three Four";
- [view_ setMessage:message
- withFont:GetDefaultFont()
- messageColor:[NSColor blackColor]];
-
- NSColor* blue = [NSColor blueColor];
- [view_ addLinkRange:NSMakeRange(4,3) withURL:@"http://2" linkColor:blue];
- [view_ addLinkRange:NSMakeRange(14,4) withURL:@"http://4" linkColor:blue];
-
- NSDictionary* attributes;
- NSRange rangeLimit = NSMakeRange(0, [message length]);
- NSRange range;
- attributes = [[view_ textStorage] attributesAtIndex:0
- longestEffectiveRange:&range
- inRange:rangeLimit];
- EXPECT_EQ(0U, range.location);
- EXPECT_EQ(4U, range.length);
- EXPECT_NSEQ(GetDefaultTextAttributes(), attributes);
-
- NSMutableDictionary* linkAttributes = GetDefaultLinkAttributes();
- [linkAttributes setObject:@"http://2" forKey:NSLinkAttributeName];
- attributes = [[view_ textStorage] attributesAtIndex:4
- longestEffectiveRange:&range
- inRange:rangeLimit];
- EXPECT_EQ(4U, range.location);
- EXPECT_EQ(3U, range.length);
- EXPECT_NSEQ(linkAttributes, attributes);
-
- attributes = [[view_ textStorage] attributesAtIndex:7
- longestEffectiveRange:&range
- inRange:rangeLimit];
- EXPECT_EQ(7U, range.location);
- EXPECT_EQ(7U, range.length);
- EXPECT_NSEQ(GetDefaultTextAttributes(), attributes);
-
- [linkAttributes setObject:@"http://4" forKey:NSLinkAttributeName];
- attributes = [[view_ textStorage] attributesAtIndex:14
- longestEffectiveRange:&range
- inRange:rangeLimit];
- EXPECT_EQ(14U, range.location);
- EXPECT_EQ(4U, range.length);
- EXPECT_NSEQ(linkAttributes, attributes);
-}
-
-TEST_F(HyperlinkTextViewTest, FirstResponderBehavior) {
- // By default, accept.
- EXPECT_TRUE([view_ acceptsFirstResponder]);
-
- [view_ setRefusesFirstResponder:YES];
- EXPECT_FALSE([view_ acceptsFirstResponder]);
-}
-
-} // namespace
diff --git a/chromium/ui/base/cocoa/controls/imageview_utils.h b/chromium/ui/base/cocoa/controls/imageview_utils.h
deleted file mode 100644
index b0e35705310..00000000000
--- a/chromium/ui/base/cocoa/controls/imageview_utils.h
+++ /dev/null
@@ -1,23 +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.
-
-#ifndef UI_BASE_COCOA_CONTROLS_IMAGEVIEW_UTILS_H_
-#define UI_BASE_COCOA_CONTROLS_IMAGEVIEW_UTILS_H_
-
-#include "ui/base/ui_base_export.h"
-
-#include <Cocoa/Cocoa.h>
-
-UI_BASE_EXPORT
-@interface ImageViewUtils : NSObject
-
-// These methods are a polyfill for convenience constructors that exist on
-// NSImageView in macOS 10.12+.
-// TODO(ellyjones): once we target only 10.12+, delete these and migrate
-// callers over to NSImageView directly.
-+ (NSImageView*)imageViewWithImage:(NSImage*)image;
-
-@end
-
-#endif // UI_BASE_COCOA_CONTROLS_IMAGEVIEW_UTILS_H_
diff --git a/chromium/ui/base/cocoa/controls/imageview_utils.mm b/chromium/ui/base/cocoa/controls/imageview_utils.mm
deleted file mode 100644
index a12d2b4c88f..00000000000
--- a/chromium/ui/base/cocoa/controls/imageview_utils.mm
+++ /dev/null
@@ -1,15 +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.
-
-#import "ui/base/cocoa/controls/imageview_utils.h"
-
-@implementation ImageViewUtils
-
-+ (NSImageView*)imageViewWithImage:(NSImage*)image {
- NSImageView* imageView = [[[NSImageView alloc] init] autorelease];
- [imageView setImage:image];
- return imageView;
-}
-
-@end
diff --git a/chromium/ui/base/cocoa/menu_controller.h b/chromium/ui/base/cocoa/menu_controller.h
index 95cf7fcaad7..56cdd4a63a7 100644
--- a/chromium/ui/base/cocoa/menu_controller.h
+++ b/chromium/ui/base/cocoa/menu_controller.h
@@ -15,9 +15,6 @@ namespace ui {
class MenuModel;
}
-UI_BASE_EXPORT extern NSString* const kMenuControllerMenuWillOpenNotification;
-UI_BASE_EXPORT extern NSString* const kMenuControllerMenuDidCloseNotification;
-
// A controller for the cross-platform menu model. The menu that's created
// has the tag and represented object set for each menu item. The object is a
// NSValue holding a pointer to the model for that level of the menu (to
@@ -25,12 +22,10 @@ UI_BASE_EXPORT extern NSString* const kMenuControllerMenuDidCloseNotification;
// that particular item. It is important that the model outlives this object
// as it only maintains weak references.
UI_BASE_EXPORT
-@interface MenuControllerCocoa : NSObject<NSMenuDelegate> {
- @protected
- ui::MenuModel* model_; // Weak.
- base::scoped_nsobject<NSMenu> menu_;
-}
+@interface MenuControllerCocoa
+ : NSObject<NSMenuDelegate, NSUserInterfaceValidations>
+// The Model passed in to -initWithModel:.
@property(nonatomic, assign) ui::MenuModel* model;
// Whether to activate selected menu items via a posted task. This may allow the
@@ -41,7 +36,7 @@ UI_BASE_EXPORT
// Note that changing this will have no effect if you use
// |-initWithModel:useWithPopUpButtonCell:| or after the first call to |-menu|.
-@property(nonatomic) BOOL useWithPopUpButtonCell;
+@property(nonatomic, assign) BOOL useWithPopUpButtonCell;
+ (base::string16)elideMenuTitle:(const base::string16&)title
toWidth:(int)width;
@@ -69,35 +64,6 @@ UI_BASE_EXPORT
// Whether the menu is currently open.
- (BOOL)isMenuOpen;
-// NSMenuDelegate methods this class implements. Subclasses should call super
-// if extending the behavior.
-- (void)menuWillOpen:(NSMenu*)menu;
-- (void)menuDidClose:(NSMenu*)menu;
-
-@end
-
-// Protected methods that subclassers can override and/or invoke.
-@interface MenuControllerCocoa (Protected)
-
-// Called before the menu is to be displayed to update the state (enabled,
-// radio, etc) of each item in the menu. Also will update the title if the item
-// is marked as "dynamic".
-- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item;
-
-// Adds the item at |index| in |model| as an NSMenuItem at |index| of |menu|.
-// Associates a submenu if the MenuModel::ItemType is TYPE_SUBMENU.
-- (void)addItemToMenu:(NSMenu*)menu
- atIndex:(NSInteger)index
- fromModel:(ui::MenuModel*)model;
-
-// Creates a NSMenu from the given model. If the model has submenus, this can
-// be invoked recursively.
-- (NSMenu*)menuFromModel:(ui::MenuModel*)model;
-
-// Returns the maximum width for the menu item. Returns -1 to indicate that
-// there's no maximum width.
-- (int)maxWidthForMenuModel:(ui::MenuModel*)model
- modelIndex:(int)modelIndex;
@end
#endif // UI_BASE_COCOA_MENU_CONTROLLER_H_
diff --git a/chromium/ui/base/cocoa/menu_controller.mm b/chromium/ui/base/cocoa/menu_controller.mm
index 089448f28e2..7462cfc934f 100644
--- a/chromium/ui/base/cocoa/menu_controller.mm
+++ b/chromium/ui/base/cocoa/menu_controller.mm
@@ -45,13 +45,23 @@ bool MenuHasVisibleItems(const ui::MenuModel* model) {
} // namespace
-NSString* const kMenuControllerMenuWillOpenNotification =
- @"MenuControllerMenuWillOpen";
-NSString* const kMenuControllerMenuDidCloseNotification =
- @"MenuControllerMenuDidClose";
-
// Internal methods.
@interface MenuControllerCocoa ()
+// Called before the menu is to be displayed to update the state (enabled,
+// radio, etc) of each item in the menu. Also will update the title if the item
+// is marked as "dynamic".
+- (BOOL)validateUserInterfaceItem:(id<NSValidatedUserInterfaceItem>)item;
+
+// Adds the item at |index| in |model| as an NSMenuItem at |index| of |menu|.
+// Associates a submenu if the MenuModel::ItemType is TYPE_SUBMENU.
+- (void)addItemToMenu:(NSMenu*)menu
+ atIndex:(NSInteger)index
+ fromModel:(ui::MenuModel*)model;
+
+// Creates a NSMenu from the given model. If the model has submenus, this can
+// be invoked recursively.
+- (NSMenu*)menuFromModel:(ui::MenuModel*)model;
+
// Adds a separator item at the given index. As the separator doesn't need
// anything from the model, this method doesn't need the model index as the
// other method below does.
@@ -74,6 +84,8 @@ NSString* const kMenuControllerMenuDidCloseNotification =
@end
@implementation MenuControllerCocoa {
+ ui::MenuModel* model_; // Weak.
+ base::scoped_nsobject<NSMenu> menu_;
BOOL useWithPopUpButtonCell_; // If YES, 0th item is blank
BOOL isMenuOpen_;
BOOL postItemSelectedAsTask_;
@@ -139,11 +151,6 @@ NSString* const kMenuControllerMenuDidCloseNotification =
return menu;
}
-- (int)maxWidthForMenuModel:(ui::MenuModel*)model
- modelIndex:(int)modelIndex {
- return -1;
-}
-
- (void)addSeparatorToMenu:(NSMenu*)menu
atIndex:(int)index {
NSMenuItem* separator = [NSMenuItem separatorItem];
@@ -153,12 +160,7 @@ NSString* const kMenuControllerMenuDidCloseNotification =
- (void)addItemToMenu:(NSMenu*)menu
atIndex:(NSInteger)index
fromModel:(ui::MenuModel*)model {
- base::string16 label16 = model->GetLabelAt(index);
- int maxWidth = [self maxWidthForMenuModel:model modelIndex:index];
- if (maxWidth != -1)
- label16 = [MenuControllerCocoa elideMenuTitle:label16 toWidth:maxWidth];
-
- NSString* label = l10n_util::FixUpWindowsStyleLabel(label16);
+ NSString* label = l10n_util::FixUpWindowsStyleLabel(model->GetLabelAt(index));
base::scoped_nsobject<NSMenuItem> item([[ResponsiveNSMenuItem alloc]
initWithTitle:label
action:@selector(itemSelected:)
@@ -335,16 +337,10 @@ NSString* const kMenuControllerMenuDidCloseNotification =
- (void)menuWillOpen:(NSMenu*)menu {
isMenuOpen_ = YES;
- [[NSNotificationCenter defaultCenter]
- postNotificationName:kMenuControllerMenuWillOpenNotification
- object:self];
model_->MenuWillShow(); // Note: |model_| may trigger -[self dealloc].
}
- (void)menuDidClose:(NSMenu*)menu {
- [[NSNotificationCenter defaultCenter]
- postNotificationName:kMenuControllerMenuDidCloseNotification
- object:self];
if (isMenuOpen_) {
isMenuOpen_ = NO;
model_->MenuWillClose(); // Note: |model_| may trigger -[self dealloc].
diff --git a/chromium/ui/base/cocoa/ns_view_ids.h b/chromium/ui/base/cocoa/ns_view_ids.h
new file mode 100644
index 00000000000..749fdd14dc0
--- /dev/null
+++ b/chromium/ui/base/cocoa/ns_view_ids.h
@@ -0,0 +1,49 @@
+// 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_BASE_COCOA_NS_VIEW_IDS_H_
+#define UI_BASE_COCOA_NS_VIEW_IDS_H_
+
+#include <stdint.h>
+
+#include "base/macros.h"
+#include "ui/base/ui_base_export.h"
+
+@class NSView;
+
+namespace ui {
+
+// A class used to manage NSViews across processes.
+// - NSViews that may be instantiated in another process are assigned an id in
+// the browser process.
+// - Instantiating a ScopedNSViewIdMapping in the process where the NSView is
+// created will make NSViewIds::GetNSView return the specified NSView.
+// - This mechanism is used by mojo methods to refer to NSViews across
+// interfaces (in particular, to specify parent NSViews).
+class UI_BASE_EXPORT NSViewIds {
+ public:
+ // Get a new id to use with a new NSView. This is to only be called in the
+ // browser process.
+ static uint64_t GetNewId();
+
+ // Return an NSView given its id. This is to be called in an app shim process.
+ static NSView* GetNSView(uint64_t ns_view_id);
+};
+
+// A scoped mapping from |ns_view_id| to |view|. While this object exists,
+// NSViewIds::GetNSView will return |view| when queried with |ns_view_id|. This
+// is to be instantiated in the app shim process.
+class UI_BASE_EXPORT ScopedNSViewIdMapping {
+ public:
+ ScopedNSViewIdMapping(uint64_t ns_view_id, NSView* view);
+ ~ScopedNSViewIdMapping();
+
+ private:
+ const uint64_t ns_view_id_;
+ DISALLOW_COPY_AND_ASSIGN(ScopedNSViewIdMapping);
+};
+
+} // namespace ui
+
+#endif // UI_BASE_COCOA_NS_VIEW_IDS_H_
diff --git a/chromium/ui/base/cocoa/ns_view_ids.mm b/chromium/ui/base/cocoa/ns_view_ids.mm
new file mode 100644
index 00000000000..3af9ba81e47
--- /dev/null
+++ b/chromium/ui/base/cocoa/ns_view_ids.mm
@@ -0,0 +1,49 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/cocoa/ns_view_ids.h"
+
+#import <Cocoa/Cocoa.h>
+#include <map>
+#include <utility>
+
+#include "base/logging.h"
+#include "base/no_destructor.h"
+
+namespace ui {
+
+std::map<uint64_t, NSView*>& GetNSViewIdMap() {
+ static base::NoDestructor<std::map<uint64_t, NSView*>> instance;
+ return *instance;
+}
+
+// static
+uint64_t NSViewIds::GetNewId() {
+ static uint64_t next_id = 1;
+ return next_id++;
+}
+
+// static
+NSView* NSViewIds::GetNSView(uint64_t ns_view_id) {
+ auto& view_map = GetNSViewIdMap();
+ auto found = view_map.find(ns_view_id);
+ if (found == view_map.end())
+ return nil;
+ return found->second;
+}
+
+ScopedNSViewIdMapping::ScopedNSViewIdMapping(uint64_t ns_view_id, NSView* view)
+ : ns_view_id_(ns_view_id) {
+ auto result = GetNSViewIdMap().insert(std::make_pair(ns_view_id, view));
+ DCHECK(result.second);
+}
+
+ScopedNSViewIdMapping::~ScopedNSViewIdMapping() {
+ auto& view_map = GetNSViewIdMap();
+ auto found = view_map.find(ns_view_id_);
+ DCHECK(found != view_map.end());
+ view_map.erase(found);
+}
+
+} // namespace ui
diff --git a/chromium/ui/base/cocoa/nsgraphics_context_additions.h b/chromium/ui/base/cocoa/nsgraphics_context_additions.h
deleted file mode 100644
index 7a373ef67c0..00000000000
--- a/chromium/ui/base/cocoa/nsgraphics_context_additions.h
+++ /dev/null
@@ -1,23 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_BASE_COCOA_NSGRAPHICS_CONTEXT_ADDITIONS_H_
-#define UI_BASE_COCOA_NSGRAPHICS_CONTEXT_ADDITIONS_H_
-
-#import <Cocoa/Cocoa.h>
-
-@interface NSGraphicsContext (CrAdditions)
-
-// When a view is not layer backed the pattern phase is relative to the origin
-// of the window's content view. With a layer backed view the pattern phase is
-// relative to the origin of the view.
-//
-// For layer backed view this method offsets the pattern phase to match the
-// behavior of non layer backed views.
-- (void)cr_setPatternPhase:(NSPoint)phase
- forView:(NSView*)view;
-
-@end
-
-#endif // UI_BASE_COCOA_NSGRAPHICS_CONTEXT_ADDITIONS_H_
diff --git a/chromium/ui/base/cocoa/nsgraphics_context_additions.mm b/chromium/ui/base/cocoa/nsgraphics_context_additions.mm
deleted file mode 100644
index c29a76227ee..00000000000
--- a/chromium/ui/base/cocoa/nsgraphics_context_additions.mm
+++ /dev/null
@@ -1,42 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ui/base/cocoa/nsgraphics_context_additions.h"
-
-#include "base/logging.h"
-
-@implementation NSGraphicsContext (CrAdditions)
-
-- (void)cr_setPatternPhase:(NSPoint)phase
- forView:(NSView*)view {
- // TODO(sdy): Remove once we no longer add the tab background view to
- // [[window contentView] superview] *or* no longer make the content view
- // smaller than the window while exiting fullscreen. These two things
- // together can result in the tab background view being drawn while it's
- // outside of contentView, with a pattern phase that assumes it's inside.
- NSView* contentView = [[view window] contentView];
- if (![view isDescendantOf:contentView]) {
- NSView* frameView = [contentView superview];
- DCHECK([view isDescendantOf:frameView]);
- // Convert phase into an offset from the top left corner of contentView so
- // that it will be aligned correctly at the end of the transition.
- phase.x += NSMinX([frameView frame]) - NSMinX([contentView frame]);
- phase.y += NSMaxY([frameView frame]) - NSMaxY([contentView frame]);
- }
-
- NSView* ancestorWithLayer = view;
- while (ancestorWithLayer && ![ancestorWithLayer layer])
- ancestorWithLayer = [ancestorWithLayer superview];
- if (ancestorWithLayer) {
- NSPoint bottomLeft = NSZeroPoint;
- if ([ancestorWithLayer isFlipped])
- bottomLeft.y = NSMaxY([ancestorWithLayer bounds]);
- NSPoint offset = [ancestorWithLayer convertPoint:bottomLeft toView:nil];
- phase.x -= offset.x;
- phase.y -= offset.y;
- }
- [self setPatternPhase:phase];
-}
-
-@end
diff --git a/chromium/ui/base/cocoa/nsgraphics_context_additions_unittest.mm b/chromium/ui/base/cocoa/nsgraphics_context_additions_unittest.mm
deleted file mode 100644
index 632add77e27..00000000000
--- a/chromium/ui/base/cocoa/nsgraphics_context_additions_unittest.mm
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ui/base/cocoa/nsgraphics_context_additions.h"
-
-#include "base/mac/scoped_nsobject.h"
-#import "ui/base/test/cocoa_helper.h"
-
-typedef ui::CocoaTest NSGraphicsContextCrAdditionsTest;
-
-TEST_F(NSGraphicsContextCrAdditionsTest, PatternPhase) {
- NSRect frame = NSMakeRect(50, 50, 100, 100);
- base::scoped_nsobject<NSView> view([[NSView alloc] initWithFrame:frame]);
- [[test_window() contentView] addSubview:view];
-
- [view lockFocus];
- NSGraphicsContext* context = [NSGraphicsContext currentContext];
-
- [context cr_setPatternPhase:NSZeroPoint forView:view];
- EXPECT_EQ(0, [context patternPhase].y);
-
- [view setWantsLayer:YES];
- [context cr_setPatternPhase:NSZeroPoint forView:view];
- EXPECT_EQ(-NSMinY(frame), [context patternPhase].y);
-
- [view unlockFocus];
-}
diff --git a/chromium/ui/base/cocoa/nsview_additions.h b/chromium/ui/base/cocoa/nsview_additions.h
deleted file mode 100644
index 836a21a261b..00000000000
--- a/chromium/ui/base/cocoa/nsview_additions.h
+++ /dev/null
@@ -1,57 +0,0 @@
-// Copyright (c) 2011 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_BASE_COCOA_NSVIEW_ADDITIONS_H_
-#define UI_BASE_COCOA_NSVIEW_ADDITIONS_H_
-
-#import <Cocoa/Cocoa.h>
-
-@interface NSView (ChromeAdditions)
-
-// Returns the line width that will generate a 1 pixel wide line.
-- (CGFloat)cr_lineWidth;
-
-// Checks if the mouse is currently in this view.
-- (BOOL)cr_isMouseInView;
-
-// Returns YES if this view is below |otherView|.
-- (BOOL)cr_isBelowView:(NSView*)otherView;
-
-// Returns YES if this view is aobve |otherView|.
-- (BOOL)cr_isAboveView:(NSView*)otherView;
-
-// Ensures that the z-order of |subview| is correct relative to |otherView|.
-- (void)cr_ensureSubview:(NSView*)subview
- isPositioned:(NSWindowOrderingMode)place
- relativeTo:(NSView *)otherView;
-
-// Return best color for keyboard focus ring.
-- (NSColor*)cr_keyboardFocusIndicatorColor;
-
-// Invoke |block| on this view and all descendants.
-- (void)cr_recursivelyInvokeBlock:(void (^)(id view))block;
-
-// Set needsDisplay for this view and all descendants.
-- (void)cr_recursivelySetNeedsDisplay:(BOOL)flag;
-
-// Draw using ancestorView's drawRect function into this view's rect. Do any
-// required translating or flipping to transform between the two coordinate
-// systems, and optionally clip to the ancestor view's bounds.
-- (void)cr_drawUsingAncestor:(NSView*)ancestorView inRect:(NSRect)dirtyRect
- clippedToAncestorBounds:(BOOL)clipToAncestorBounds;
-
-// Same as cr_drawUsingAncestor:inRect:clippedToAncestorBounds: except always
-// clips to the ancestor view's bounds.
-- (void)cr_drawUsingAncestor:(NSView*)ancestorView inRect:(NSRect)dirtyRect;
-
-// Used by ancestorView in the above draw call, to look up the child view that
-// it is actually drawing to.
-- (NSView*)cr_viewBeingDrawnTo;
-
-// Set a view's accessibilityLabel in a way that's compatible with 10.9.
-- (void)cr_setAccessibilityLabel:(NSString*)label;
-
-@end
-
-#endif // UI_BASE_COCOA_NSVIEW_ADDITIONS_H_
diff --git a/chromium/ui/base/cocoa/nsview_additions.mm b/chromium/ui/base/cocoa/nsview_additions.mm
deleted file mode 100644
index 4f37d9e3989..00000000000
--- a/chromium/ui/base/cocoa/nsview_additions.mm
+++ /dev/null
@@ -1,126 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/mac/sdk_forward_declarations.h"
-#import "ui/base/cocoa/nsview_additions.h"
-#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
-
-#include "base/logging.h"
-
-@implementation NSView (ChromeAdditions)
-
-- (CGFloat)cr_lineWidth {
- // All shipping retina macs run at least 10.7.
- if (![self respondsToSelector:@selector(convertSizeFromBacking:)])
- return 1;
- return [self convertSizeFromBacking:NSMakeSize(1, 1)].width;
-}
-
-- (BOOL)cr_isMouseInView {
- NSPoint mouseLoc = [[self window] mouseLocationOutsideOfEventStream];
- mouseLoc = [[self superview] convertPoint:mouseLoc fromView:nil];
- return [self hitTest:mouseLoc] == self;
-}
-
-- (BOOL)cr_isBelowView:(NSView*)otherView {
- NSArray* subviews = [[self superview] subviews];
-
- NSUInteger selfIndex = [subviews indexOfObject:self];
- DCHECK(NSNotFound != selfIndex);
-
- NSUInteger otherIndex = [subviews indexOfObject:otherView];
- DCHECK(NSNotFound != otherIndex);
-
- return selfIndex < otherIndex;
-}
-
-- (BOOL)cr_isAboveView:(NSView*)otherView {
- return ![self cr_isBelowView:otherView];
-}
-
-- (void)cr_ensureSubview:(NSView*)subview
- isPositioned:(NSWindowOrderingMode)place
- relativeTo:(NSView *)otherView {
- DCHECK(place == NSWindowAbove || place == NSWindowBelow);
- BOOL isAbove = place == NSWindowAbove;
- if ([[subview superview] isEqual:self] &&
- [subview cr_isAboveView:otherView] == isAbove) {
- return;
- }
-
- [subview removeFromSuperview];
- [self addSubview:subview
- positioned:place
- relativeTo:otherView];
-}
-
-- (NSColor*)cr_keyboardFocusIndicatorColor {
- return [[NSColor keyboardFocusIndicatorColor]
- colorWithAlphaComponent:0.5 / [self cr_lineWidth]];
-}
-
-- (void)cr_recursivelyInvokeBlock:(void (^)(id view))block {
- block(self);
- for (NSView* subview in [self subviews])
- [subview cr_recursivelyInvokeBlock:block];
-}
-
-- (void)cr_recursivelySetNeedsDisplay:(BOOL)flag {
- [self setNeedsDisplay:YES];
- for (NSView* child in [self subviews])
- [child cr_recursivelySetNeedsDisplay:flag];
-}
-
-static NSView* g_ancestorBeingDrawnFrom = nil;
-static NSView* g_childBeingDrawnTo = nil;
-
-- (void)cr_drawUsingAncestor:(NSView*)ancestorView inRect:(NSRect)dirtyRect
- clippedToAncestorBounds:(BOOL)clipToAncestorBounds {
- gfx::ScopedNSGraphicsContextSaveGState scopedGSState;
- NSRect frame = [self convertRect:[self bounds] toView:ancestorView];
- NSAffineTransform* transform = [NSAffineTransform transform];
- if ([self isFlipped] == [ancestorView isFlipped]) {
- [transform translateXBy:-NSMinX(frame) yBy:-NSMinY(frame)];
- } else {
- [transform translateXBy:-NSMinX(frame) yBy:NSMaxY(frame)];
- [transform scaleXBy:1.0 yBy:-1.0];
- }
- [transform concat];
-
- // This can be made robust to recursive calls, but is as of yet unneeded.
- DCHECK(!g_ancestorBeingDrawnFrom && !g_childBeingDrawnTo);
- g_ancestorBeingDrawnFrom = ancestorView;
- g_childBeingDrawnTo = self;
- NSRect drawRect = [self convertRect:dirtyRect toView:ancestorView];
- if (clipToAncestorBounds) {
- drawRect = NSIntersectionRect([ancestorView bounds], drawRect);
- }
- [ancestorView drawRect:drawRect];
- g_childBeingDrawnTo = nil;
- g_ancestorBeingDrawnFrom = nil;
-}
-
-- (void)cr_drawUsingAncestor:(NSView*)ancestorView inRect:(NSRect)dirtyRect {
- [self cr_drawUsingAncestor:ancestorView
- inRect:dirtyRect
- clippedToAncestorBounds:YES];
-}
-
-- (NSView*)cr_viewBeingDrawnTo {
- if (!g_ancestorBeingDrawnFrom)
- return self;
- DCHECK(g_ancestorBeingDrawnFrom == self);
- return g_childBeingDrawnTo;
-}
-
-- (void)cr_setAccessibilityLabel:(NSString*)label {
- if (@available(macOS 10.10, *)) {
- self.accessibilityLabel = label;
- } else {
- [self accessibilitySetOverrideValue:label
- forAttribute:NSAccessibilityDescriptionAttribute];
- }
-}
-
-@end
diff --git a/chromium/ui/base/cocoa/nsview_additions_unittest.mm b/chromium/ui/base/cocoa/nsview_additions_unittest.mm
deleted file mode 100644
index 9d1f66f6633..00000000000
--- a/chromium/ui/base/cocoa/nsview_additions_unittest.mm
+++ /dev/null
@@ -1,106 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ui/base/cocoa/nsview_additions.h"
-
-#include "base/mac/scoped_nsobject.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#import "testing/gtest_mac.h"
-#import "ui/base/test/cocoa_helper.h"
-
-typedef ui::CocoaTest NSViewChromeAdditionsTest;
-
-@interface ParentView : NSView {
- @private
- int removeCount_;
- int addCount_;
-}
-
-@property(readonly, nonatomic) int removeCount;
-@property(readonly, nonatomic) int addCount;
-
-@end
-
-@implementation ParentView
-
-@synthesize removeCount = removeCount_;
-@synthesize addCount = addCount_;
-
-- (void)willRemoveSubview:(NSView*)view {
- ++removeCount_;
-}
-
-- (void)didAddSubview:(NSView*)view {
- ++addCount_;
-}
-
-@end
-
-TEST_F(NSViewChromeAdditionsTest, BelowAboveView) {
- base::scoped_nsobject<NSView> parent(
- [[NSView alloc] initWithFrame:NSZeroRect]);
- base::scoped_nsobject<NSView> child1(
- [[NSView alloc] initWithFrame:NSZeroRect]);
- base::scoped_nsobject<NSView> child2(
- [[NSView alloc] initWithFrame:NSZeroRect]);
-
- [parent addSubview:child1];
- [parent addSubview:child2];
- EXPECT_TRUE([child1 cr_isBelowView:child2]);
- EXPECT_FALSE([child1 cr_isAboveView:child2]);
- EXPECT_FALSE([child2 cr_isBelowView:child1]);
- EXPECT_TRUE([child2 cr_isAboveView:child1]);
-
- [child1 removeFromSuperview];
- [child2 removeFromSuperview];
- [parent addSubview:child2];
- [parent addSubview:child1];
- EXPECT_FALSE([child1 cr_isBelowView:child2]);
- EXPECT_TRUE([child1 cr_isAboveView:child2]);
- EXPECT_TRUE([child2 cr_isBelowView:child1]);
- EXPECT_FALSE([child2 cr_isAboveView:child1]);
-}
-
-TEST_F(NSViewChromeAdditionsTest, EnsurePosition) {
- base::scoped_nsobject<NSView> parent(
- [[NSView alloc] initWithFrame:NSZeroRect]);
- base::scoped_nsobject<NSView> child1(
- [[NSView alloc] initWithFrame:NSZeroRect]);
- base::scoped_nsobject<NSView> child2(
- [[NSView alloc] initWithFrame:NSZeroRect]);
-
- [parent addSubview:child1];
- [parent cr_ensureSubview:child2
- isPositioned:NSWindowAbove
- relativeTo:child1];
- EXPECT_NSEQ([[parent subviews] objectAtIndex:0], child1);
- EXPECT_NSEQ([[parent subviews] objectAtIndex:1], child2);
-
- [child2 removeFromSuperview];
- [parent cr_ensureSubview:child2
- isPositioned:NSWindowBelow
- relativeTo:child1];
- EXPECT_NSEQ([[parent subviews] objectAtIndex:0], child2);
- EXPECT_NSEQ([[parent subviews] objectAtIndex:1], child1);
-}
-
-// Verify that no view is removed or added when no change is needed.
-TEST_F(NSViewChromeAdditionsTest, EnsurePositionNoChange) {
- base::scoped_nsobject<ParentView> parent(
- [[ParentView alloc] initWithFrame:NSZeroRect]);
- base::scoped_nsobject<NSView> child1(
- [[NSView alloc] initWithFrame:NSZeroRect]);
- base::scoped_nsobject<NSView> child2(
- [[NSView alloc] initWithFrame:NSZeroRect]);
- [parent addSubview:child1];
- [parent addSubview:child2];
-
- EXPECT_EQ(0, [parent removeCount]);
- EXPECT_EQ(2, [parent addCount]);
- [parent cr_ensureSubview:child2
- isPositioned:NSWindowAbove
- relativeTo:child1];
- EXPECT_EQ(0, [parent removeCount]);
- EXPECT_EQ(2, [parent addCount]);
-}
diff --git a/chromium/ui/base/cocoa/scoped_cg_context_smooth_fonts.h b/chromium/ui/base/cocoa/scoped_cg_context_smooth_fonts.h
deleted file mode 100644
index f080d78e199..00000000000
--- a/chromium/ui/base/cocoa/scoped_cg_context_smooth_fonts.h
+++ /dev/null
@@ -1,34 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_BASE_COCOA_SCOPED_CG_CONTEXT_SMOOTH_FONTS_H_
-#define UI_BASE_COCOA_SCOPED_CG_CONTEXT_SMOOTH_FONTS_H_
-
-#include "base/macros.h"
-#include "ui/base/ui_base_export.h"
-#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
-
-namespace ui {
-
-// Ensures LCD font smoothing is enabled before drawing text. This allows Cocoa
-// drawing code to override a decision made by AppKit to disable font smoothing.
-// E.g. this occurs when a view is layer-backed or, since 10.8, when a view
-// returns NO from -[NSView isOpaque]. For this to look nice, there must be an
-// opaque background already drawn in the graphics context at the location of
-// the text (but it doesn't need to fill the view bounds, which is required when
-// -[NSView isOpaque] returns YES).
-class UI_BASE_EXPORT ScopedCGContextSmoothFonts {
- public:
- ScopedCGContextSmoothFonts();
- ~ScopedCGContextSmoothFonts();
-
- private:
- gfx::ScopedNSGraphicsContextSaveGState save_state_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedCGContextSmoothFonts);
-};
-
-} // namespace ui
-
-#endif // UI_BASE_COCOA_SCOPED_CG_CONTEXT_SMOOTH_FONTS_H_
diff --git a/chromium/ui/base/cocoa/scoped_cg_context_smooth_fonts.mm b/chromium/ui/base/cocoa/scoped_cg_context_smooth_fonts.mm
deleted file mode 100644
index 1129a19abc8..00000000000
--- a/chromium/ui/base/cocoa/scoped_cg_context_smooth_fonts.mm
+++ /dev/null
@@ -1,20 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/base/cocoa/scoped_cg_context_smooth_fonts.h"
-
-#import <AppKit/AppKit.h>
-
-namespace ui {
-
-ScopedCGContextSmoothFonts::ScopedCGContextSmoothFonts() {
- NSGraphicsContext* context = [NSGraphicsContext currentContext];
- CGContextRef cg_context = static_cast<CGContextRef>([context graphicsPort]);
- CGContextSetShouldSmoothFonts(cg_context, true);
-}
-
-ScopedCGContextSmoothFonts::~ScopedCGContextSmoothFonts() {
-}
-
-} // namespace ui
diff --git a/chromium/ui/base/cocoa/three_part_image.h b/chromium/ui/base/cocoa/three_part_image.h
deleted file mode 100644
index 72da5ca918a..00000000000
--- a/chromium/ui/base/cocoa/three_part_image.h
+++ /dev/null
@@ -1,54 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_BASE_COCOA_THREE_PART_IMAGE_H_
-#define UI_BASE_COCOA_THREE_PART_IMAGE_H_
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/mac/scoped_nsobject.h"
-#include "base/macros.h"
-#include "ui/base/ui_base_export.h"
-
-namespace ui {
-
-// A wrapper around NSDrawThreePartImage that caches the images.
-// The middle image is optional.
-// Vertical orientation is not currently supported.
-class UI_BASE_EXPORT ThreePartImage {
- public:
- // Create a ThreePartImage from existing NSImages. Specify nil for |middle| if
- // there is no middle image.
- ThreePartImage(NSImage* left, NSImage* middle, NSImage* right);
- ~ThreePartImage();
-
- // Returns the image rects if drawn in |bounds|.
- NSRect GetLeftRect(NSRect bounds) const;
- NSRect GetMiddleRect(NSRect bounds) const;
- NSRect GetRightRect(NSRect bounds) const;
-
- // Draws the three part image inside |rect|.
- void DrawInRect(NSRect rect, NSCompositingOperation op, CGFloat alpha) const;
-
- // Returns YES if |point| is in a non-transparent part of the images.
- // Returns YES if |point| is inside the middle rect and there is no middle
- // image.
- BOOL HitTest(NSPoint point, NSRect bounds) const;
-
- private:
- // Returns YES if |point| is in a non-transparent part of |image|.
- BOOL HitTestImage(NSPoint point, NSImage* image, NSRect imageRect) const;
-
- base::scoped_nsobject<NSImage> leftImage_;
- base::scoped_nsobject<NSImage> middleImage_;
- base::scoped_nsobject<NSImage> rightImage_;
- NSSize leftSize_;
- NSSize rightSize_;
-
- DISALLOW_COPY_AND_ASSIGN(ThreePartImage);
-};
-
-} // namespace ui
-
-#endif // UI_BASE_COCOA_THREE_PART_IMAGE_H_
diff --git a/chromium/ui/base/cocoa/three_part_image.mm b/chromium/ui/base/cocoa/three_part_image.mm
deleted file mode 100644
index 18ec2ddbfd0..00000000000
--- a/chromium/ui/base/cocoa/three_part_image.mm
+++ /dev/null
@@ -1,82 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/base/cocoa/three_part_image.h"
-
-#include "base/logging.h"
-#include "ui/base/resource/resource_bundle.h"
-
-namespace ui {
-
-ThreePartImage::ThreePartImage(NSImage* left, NSImage* middle, NSImage* right) {
- DCHECK(left);
- DCHECK(right);
- leftImage_.reset([left retain]);
- rightImage_.reset([right retain]);
- leftSize_ = [leftImage_ size];
- rightSize_ = [rightImage_ size];
-
- if (middle) {
- middleImage_.reset([middle retain]);
- }
-}
-
-ThreePartImage::~ThreePartImage() {
-}
-
-NSRect ThreePartImage::GetLeftRect(NSRect bounds) const {
- NSRect left, right;
- NSDivideRect(bounds, &left, &right, leftSize_.width, NSMinXEdge);
- return left;
-}
-
-NSRect ThreePartImage::GetMiddleRect(NSRect bounds) const {
- NSRect left, middle, right;
- NSDivideRect(bounds, &left, &middle, leftSize_.width, NSMinXEdge);
- NSDivideRect(middle, &right, &middle, rightSize_.width, NSMaxXEdge);
- return middle;
-}
-
-NSRect ThreePartImage::GetRightRect(NSRect bounds) const {
- NSRect left, right;
- NSDivideRect(bounds, &right, &left, rightSize_.width, NSMaxXEdge);
- return right;
-}
-
-void ThreePartImage::DrawInRect(NSRect rect,
- NSCompositingOperation op,
- CGFloat alpha) const {
- rect.size.height = leftSize_.height;
- NSDrawThreePartImage(rect, leftImage_, middleImage_, rightImage_,
- NO, op, alpha, NO);
-}
-
-BOOL ThreePartImage::HitTest(NSPoint point, NSRect bounds) const {
- NSRect middleRect = GetMiddleRect(bounds);
- if (NSPointInRect(point, middleRect))
- return middleImage_ ? HitTestImage(point, middleImage_, middleRect) : YES;
-
- NSRect leftRect = GetLeftRect(bounds);
- if (NSPointInRect(point, leftRect))
- return HitTestImage(point, leftImage_, leftRect);
-
- NSRect rightRect = GetRightRect(bounds);
- if (NSPointInRect(point, rightRect))
- return HitTestImage(point, rightImage_, rightRect);
-
- return NO;
-}
-
-BOOL ThreePartImage::HitTestImage(NSPoint point,
- NSImage* image,
- NSRect imageRect) const {
- NSRect pointRect = NSMakeRect(point.x, point.y, 1, 1);
- return [image hitTestRect:pointRect
- withImageDestinationRect:imageRect
- context:nil
- hints:nil
- flipped:NO];
-}
-
-} // namespace ui
diff --git a/chromium/ui/base/cocoa/three_part_image_unittest.mm b/chromium/ui/base/cocoa/three_part_image_unittest.mm
deleted file mode 100644
index 223d5e6f235..00000000000
--- a/chromium/ui/base/cocoa/three_part_image_unittest.mm
+++ /dev/null
@@ -1,84 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/base/cocoa/three_part_image.h"
-
-#include <memory>
-
-#include "testing/gtest_mac.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "third_party/skia/include/core/SkRect.h"
-#include "ui/base/resource/resource_bundle.h"
-#import "ui/base/test/cocoa_helper.h"
-#include "ui/gfx/image/image.h"
-#include "ui/gfx/image/image_unittest_util.h"
-
-namespace ui {
-namespace test {
-
-TEST(ThreePartImageTest, GetRects) {
- const int kHeight = 11;
- const int kLeftWidth = 3;
- const int kMiddleWidth = 5;
- const int kRightWidth = 7;
- base::scoped_nsobject<NSImage> leftImage(
- gfx::test::CreateImage(kLeftWidth, kHeight).CopyNSImage());
- base::scoped_nsobject<NSImage> middleImage(
- gfx::test::CreateImage(kMiddleWidth, kHeight).CopyNSImage());
- base::scoped_nsobject<NSImage> rightImage(
- gfx::test::CreateImage(kRightWidth, kHeight).CopyNSImage());
- ThreePartImage image(leftImage, middleImage, rightImage);
- NSRect bounds =
- NSMakeRect(0, 0, kLeftWidth + kMiddleWidth + kRightWidth, kHeight);
- EXPECT_NSRECT_EQ(NSMakeRect(0, 0, kLeftWidth, kHeight),
- image.GetLeftRect(bounds));
- EXPECT_NSRECT_EQ(NSMakeRect(kLeftWidth, 0, kMiddleWidth, kHeight),
- image.GetMiddleRect(bounds));
- EXPECT_NSRECT_EQ(
- NSMakeRect(kLeftWidth + kMiddleWidth, 0, kRightWidth, kHeight),
- image.GetRightRect(bounds));
-
- ThreePartImage image2(leftImage, nullptr, rightImage);
- EXPECT_NSRECT_EQ(NSMakeRect(0, 0, kLeftWidth, kHeight),
- image.GetLeftRect(bounds));
- EXPECT_NSRECT_EQ(NSMakeRect(kLeftWidth, 0, kMiddleWidth, kHeight),
- image.GetMiddleRect(bounds));
- EXPECT_NSRECT_EQ(
- NSMakeRect(kLeftWidth + kMiddleWidth, 0, kRightWidth, kHeight),
- image.GetRightRect(bounds));
-}
-
-TEST(ThreePartImageTest, HitTest) {
- // Create a bitmap with transparent top and bottom.
- const int size = 128;
- const int corner_size = 8;
- SkBitmap bitmap = gfx::test::CreateBitmap(size, size);
- // Clear top and bottom.
- bitmap.erase(SK_ColorTRANSPARENT, SkIRect::MakeXYWH(0, 0, size, corner_size));
- bitmap.erase(SK_ColorTRANSPARENT,
- SkIRect::MakeXYWH(0, size - corner_size, size, corner_size));
- gfx::Image part_image = gfx::Image::CreateFrom1xBitmap(bitmap);
-
- // Create a three-part image.
- base::scoped_nsobject<NSImage> ns_image(part_image.CopyNSImage());
- ThreePartImage image(ns_image, nullptr, ns_image);
- NSRect bounds = NSMakeRect(0, 0, 4 * size, size);
-
- // The middle of the left and right parts are hits.
- EXPECT_TRUE(image.HitTest(NSMakePoint(size / 2, size / 2), bounds));
- EXPECT_TRUE(image.HitTest(NSMakePoint(7 * size / 2, size / 2), bounds));
-
- // No middle image means the middle rect is a hit.
- EXPECT_TRUE(image.HitTest(NSMakePoint(2 * size, size / 2), bounds));
-
- // The corners are transparent.
- EXPECT_FALSE(image.HitTest(NSMakePoint(0, 0), bounds));
- EXPECT_FALSE(image.HitTest(NSMakePoint(0, size - 1), bounds));
- EXPECT_FALSE(image.HitTest(NSMakePoint(4 * size - 1, 0), bounds));
- EXPECT_FALSE(image.HitTest(NSMakePoint(4 * size - 1, size - 1), bounds));
-}
-
-} // namespace test
-} // namespace ui
diff --git a/chromium/ui/base/cocoa/view_description.h b/chromium/ui/base/cocoa/view_description.h
deleted file mode 100644
index 727ad15db0a..00000000000
--- a/chromium/ui/base/cocoa/view_description.h
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_BASE_COCOA_VIEW_DESCRIPTION_H_
-#define UI_BASE_COCOA_VIEW_DESCRIPTION_H_
-
-#import <Cocoa/Cocoa.h>
-
-#if !NDEBUG
-
-@interface NSView (CrDebugging)
-
-// Returns a description of all the subviews and each's frame for debugging.
-- (NSString*)cr_recursiveDescription;
-
-@end
-
-#endif // !NDEBUG
-
-#endif // UI_BASE_COCOA_VIEW_DESCRIPTION_H_
diff --git a/chromium/ui/base/cocoa/view_description.mm b/chromium/ui/base/cocoa/view_description.mm
deleted file mode 100644
index 1734f8817be..00000000000
--- a/chromium/ui/base/cocoa/view_description.mm
+++ /dev/null
@@ -1,31 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ui/base/cocoa/view_description.h"
-
-#if !NDEBUG
-
-@implementation NSView (CrDebugging)
-
-- (NSString*)cr_recursiveDescriptionWithPrefix:(NSString*)prefix {
- NSString* description =
- [NSString stringWithFormat:@"%@ <%@ %p, frame=%@, hidden=%d>\n",
- prefix, [self class], self, NSStringFromRect([self frame]),
- [self isHidden]];
- prefix = [prefix stringByAppendingString:@"--"];
-
- for (NSView* subview in [self subviews]) {
- description = [description stringByAppendingString:
- [subview cr_recursiveDescriptionWithPrefix:prefix]];
- }
- return description;
-}
-
-- (NSString*)cr_recursiveDescription {
- return [self cr_recursiveDescriptionWithPrefix:@""];
-}
-
-@end
-
-#endif // !NDEBUG
diff --git a/chromium/ui/base/cocoa/views_hostable.h b/chromium/ui/base/cocoa/views_hostable.h
new file mode 100644
index 00000000000..68c5cc56f19
--- /dev/null
+++ b/chromium/ui/base/cocoa/views_hostable.h
@@ -0,0 +1,78 @@
+// 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_BASE_COCOA_VIEWS_HOSTABLE_H_
+#define UI_BASE_COCOA_VIEWS_HOSTABLE_H_
+
+#import <objc/objc.h>
+
+#include "ui/base/ui_base_export.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace ui {
+
+class Layer;
+
+// Interface that it used to stitch a content::WebContentsView into a
+// views::View.
+class ViewsHostableView {
+ public:
+ // Host interface through which the WebContentsView may indicate that its C++
+ // object is destroying.
+ class Host {
+ public:
+ // Query the ui::Layer of the host.
+ virtual ui::Layer* GetUiLayer() const = 0;
+
+ // Return the id for the process in which the host NSView exists. Used to
+ // migrate the content::WebContentsView and content::RenderWidgetHostview
+ // to that process.
+ virtual uint64_t GetViewsFactoryHostId() const = 0;
+
+ // The id for the views::View's NSView. Used to add the
+ // content::WebContentsView's NSView as a child view.
+ virtual uint64_t GetNSViewId() const = 0;
+
+ // Query the parent accessibility element of the host.
+ virtual id GetAccessibilityElement() const = 0;
+
+ // Called when the hostable view will be destroyed.
+ virtual void OnHostableViewDestroying() = 0;
+ };
+
+ // Called when the content::WebContentsView's NSView is added as a subview of
+ // the views::View's NSView (note that these are the browser-side NSViews).
+ // This is responsible for:
+ // - Adding the WebContentsView's ui::Layer to the parent's ui::Layer tree.
+ // - Stitching together the accessibility tree between the views::View and
+ // the WebContentsView.
+ // - Stitching together any app-shim-side NSViews.
+ virtual void OnViewsHostableAttached(Host* host) = 0;
+
+ // Called when the WebContentsView's NSView has been removed from the
+ // views::View's NSView. This is responsible for un-doing all of the actions
+ // taken when attaching.
+ virtual void OnViewsHostableDetached() = 0;
+
+ // Called when the WebContentsView's NSView is to be shown or resized.
+ virtual void OnViewsHostableShow(const gfx::Rect& bounds_in_window) = 0;
+
+ // Called when the WebContentsView's NSView is to be hidden.
+ virtual void OnViewsHostableHide() = 0;
+
+ // Called when the WebContentsView's NSView is to be made a first responder.
+ virtual void OnViewsHostableMakeFirstResponder() = 0;
+};
+
+} // namespace ui
+
+// The protocol through which an NSView indicates support for the
+// ViewsHostableView interface.
+@protocol ViewsHostable
+
+- (ui::ViewsHostableView*)viewsHostableView;
+
+@end
+
+#endif // UI_BASE_COCOA_VIEWS_HOSTABLE_H_
diff --git a/chromium/ui/base/cursor/cursor_util.cc b/chromium/ui/base/cursor/cursor_util.cc
index 5a672aa921a..3735bf69664 100644
--- a/chromium/ui/base/cursor/cursor_util.cc
+++ b/chromium/ui/base/cursor/cursor_util.cc
@@ -108,7 +108,7 @@ void GetImageCursorBitmap(int resource_id,
const gfx::ImageSkiaRep& image_rep = image->GetRepresentation(scale);
// TODO(oshima): The cursor should use resource scale factor when
// fractional scale factor is enabled. crbug.com/372212
- (*bitmap) = image_rep.sk_bitmap();
+ (*bitmap) = image_rep.GetBitmap();
ScaleAndRotateCursorBitmapAndHotpoint(
scale / image_rep.scale(), rotation, bitmap, hotspot);
// |image_rep| is owned by the resource bundle. So we do not need to free it.
@@ -123,7 +123,7 @@ void GetAnimatedCursorBitmaps(int resource_id,
const gfx::ImageSkia* image =
ResourceBundle::GetSharedInstance().GetImageSkiaNamed(resource_id);
const gfx::ImageSkiaRep& image_rep = image->GetRepresentation(scale);
- SkBitmap bitmap = image_rep.sk_bitmap();
+ SkBitmap bitmap = image_rep.GetBitmap();
int frame_width = bitmap.height();
int frame_height = frame_width;
int total_width = bitmap.width();
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 809a927ca4f..a64e32e9185 100644
--- a/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.cc
+++ b/chromium/ui/base/cursor/ozone/bitmap_cursor_factory_ozone.cc
@@ -22,6 +22,10 @@ PlatformCursor ToPlatformCursor(BitmapCursorOzone* cursor) {
scoped_refptr<BitmapCursorOzone> CreateDefaultBitmapCursor(CursorType type) {
Cursor cursor(type);
+ // Ozone must honor the lowest possible scale value, which is 1.0f. Otherwise,
+ // it can happen that cursor chooses wrong hotspots if max scaling value is
+ // set to 200p, for example.
+ cursor.set_device_scale_factor(1.0f);
SkBitmap bitmap = cursor.GetBitmap();
gfx::Point hotspot = cursor.GetHotspot();
if (!bitmap.isNull())
diff --git a/chromium/ui/base/default_theme_provider.h b/chromium/ui/base/default_theme_provider.h
index 1f976131f47..c5bf36835b6 100644
--- a/chromium/ui/base/default_theme_provider.h
+++ b/chromium/ui/base/default_theme_provider.h
@@ -9,7 +9,6 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
-#include "build/build_config.h"
#include "ui/base/theme_provider.h"
#include "ui/base/ui_base_export.h"
@@ -31,17 +30,6 @@ class UI_BASE_EXPORT DefaultThemeProvider : public ThemeProvider {
base::RefCountedMemory* GetRawData(int id, ui::ScaleFactor scale_factor)
const override;
-#if defined(OS_MACOSX)
- bool UsingSystemTheme() const override;
- bool InIncognitoMode() const override;
- NSImage* GetNSImageNamed(int id) const override;
- NSColor* GetNSImageColorNamed(int id) const override;
- NSColor* GetNSColor(int id) const override;
- NSColor* GetNSColorTint(int id) const override;
- NSGradient* GetNSGradient(int id) const override;
- bool ShouldIncreaseContrast() const override;
-#endif
-
private:
DISALLOW_COPY_AND_ASSIGN(DefaultThemeProvider);
};
diff --git a/chromium/ui/base/default_theme_provider_mac.mm b/chromium/ui/base/default_theme_provider_mac.mm
deleted file mode 100644
index 21db59a98bf..00000000000
--- a/chromium/ui/base/default_theme_provider_mac.mm
+++ /dev/null
@@ -1,47 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/base/default_theme_provider.h"
-
-#import <Cocoa/Cocoa.h>
-
-#include "ui/base/resource/resource_bundle.h"
-
-namespace ui {
-
-bool DefaultThemeProvider::UsingSystemTheme() const {
- return true;
-}
-
-bool DefaultThemeProvider::InIncognitoMode() const {
- return false;
-}
-
-NSImage* DefaultThemeProvider::GetNSImageNamed(int id) const {
- return ResourceBundle::GetSharedInstance().
- GetNativeImageNamed(id).ToNSImage();
-}
-
-NSColor* DefaultThemeProvider::GetNSImageColorNamed(int id) const {
- NSImage* image = GetNSImageNamed(id);
- return [NSColor colorWithPatternImage:image];
-}
-
-NSColor* DefaultThemeProvider::GetNSColor(int id) const {
- return [NSColor redColor];
-}
-
-NSColor* DefaultThemeProvider::GetNSColorTint(int id) const {
- return [NSColor redColor];
-}
-
-NSGradient* DefaultThemeProvider::GetNSGradient(int id) const {
- return nil;
-}
-
-bool DefaultThemeProvider::ShouldIncreaseContrast() const {
- return false;
-}
-
-} // namespace ui
diff --git a/chromium/ui/base/dragdrop/file_info.cc b/chromium/ui/base/dragdrop/file_info.cc
index e5b894a020f..e0f63dc582a 100644
--- a/chromium/ui/base/dragdrop/file_info.cc
+++ b/chromium/ui/base/dragdrop/file_info.cc
@@ -14,4 +14,8 @@ FileInfo::FileInfo(const base::FilePath& path,
FileInfo::~FileInfo() {}
+bool FileInfo::operator==(const FileInfo& other) const {
+ return path == other.path && display_name == other.display_name;
+}
+
} // namespace ui
diff --git a/chromium/ui/base/dragdrop/file_info.h b/chromium/ui/base/dragdrop/file_info.h
index 6e4f456147a..4c8bd3cb131 100644
--- a/chromium/ui/base/dragdrop/file_info.h
+++ b/chromium/ui/base/dragdrop/file_info.h
@@ -15,6 +15,7 @@ struct UI_BASE_EXPORT FileInfo {
FileInfo();
FileInfo(const base::FilePath& path, const base::FilePath& display_name);
~FileInfo();
+ bool operator==(const FileInfo& other) const;
base::FilePath path;
base::FilePath display_name; // Optional.
diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_aurax11.cc b/chromium/ui/base/dragdrop/os_exchange_data_provider_aurax11.cc
index 1a6e9a1c789..6666737fd2d 100644
--- a/chromium/ui/base/dragdrop/os_exchange_data_provider_aurax11.cc
+++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_aurax11.cc
@@ -173,9 +173,7 @@ void OSExchangeDataProviderAuraX11::SetFilename(const base::FilePath& path) {
void OSExchangeDataProviderAuraX11::SetFilenames(
const std::vector<FileInfo>& filenames) {
std::vector<std::string> paths;
- for (std::vector<FileInfo>::const_iterator it = filenames.begin();
- it != filenames.end();
- ++it) {
+ for (auto it = filenames.begin(); it != filenames.end(); ++it) {
std::string url_spec = net::FilePathToFileURL(it->path).spec();
if (!url_spec.empty())
paths.push_back(url_spec);
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 7ee25905b85..edc52f42540 100644
--- a/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.h
+++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.h
@@ -57,6 +57,9 @@ class UI_BASE_EXPORT OSExchangeDataProviderMac
// Returns the data for the specified type in the pasteboard.
NSData* GetNSDataForType(NSString* type) const;
+ // Gets the underlying pasteboard.
+ NSPasteboard* GetPasteboard() const;
+
// Returns the union of SupportedPasteboardTypes() and the types in the
// current pasteboard.
NSArray* GetAvailableTypes() const;
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 334bc9cad88..c55c78ca720 100644
--- a/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.mm
+++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_mac.mm
@@ -15,6 +15,7 @@
#import "ui/base/clipboard/clipboard_util_mac.h"
#include "ui/base/clipboard/custom_data_helper.h"
#import "ui/base/dragdrop/cocoa_dnd_util.h"
+#include "ui/base/dragdrop/file_info.h"
#include "url/gurl.h"
namespace ui {
@@ -64,7 +65,16 @@ void OSExchangeDataProviderMac::SetFilename(const base::FilePath& path) {
void OSExchangeDataProviderMac::SetFilenames(
const std::vector<FileInfo>& filenames) {
- NOTIMPLEMENTED();
+ if (filenames.empty())
+ return;
+
+ NSMutableArray* paths = [NSMutableArray arrayWithCapacity:filenames.size()];
+
+ for (const auto& filename : filenames) {
+ NSString* path = base::SysUTF8ToNSString(filename.path.value());
+ [paths addObject:path];
+ }
+ [pasteboard_->get() setPropertyList:paths forType:NSFilenamesPboardType];
}
void OSExchangeDataProviderMac::SetPickledData(
@@ -137,8 +147,16 @@ bool OSExchangeDataProviderMac::GetFilename(base::FilePath* path) const {
bool OSExchangeDataProviderMac::GetFilenames(
std::vector<FileInfo>* filenames) const {
- NOTIMPLEMENTED();
- return false;
+ NSArray* paths =
+ [pasteboard_->get() propertyListForType:NSFilenamesPboardType];
+ if ([paths count] == 0)
+ return false;
+
+ for (NSString* path in paths)
+ filenames->push_back(
+ {base::FilePath(base::SysNSStringToUTF8(path)), base::FilePath()});
+
+ return true;
}
bool OSExchangeDataProviderMac::GetPickledData(
@@ -194,6 +212,10 @@ NSData* OSExchangeDataProviderMac::GetNSDataForType(NSString* type) const {
return [pasteboard_->get() dataForType:type];
}
+NSPasteboard* OSExchangeDataProviderMac::GetPasteboard() const {
+ return pasteboard_->get();
+}
+
NSArray* OSExchangeDataProviderMac::GetAvailableTypes() const {
NSSet* supportedTypes = [NSSet setWithArray:SupportedPasteboardTypes()];
NSMutableSet* availableTypes =
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 2aa2920a069..7f7270b6319 100644
--- a/chromium/ui/base/dragdrop/os_exchange_data_provider_win.cc
+++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_win.cc
@@ -18,6 +18,7 @@
#include "base/i18n/file_util_icu.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/no_destructor.h"
#include "base/pickle.h"
#include "base/strings/utf_string_conversions.h"
#include "base/win/scoped_hdc.h"
@@ -38,11 +39,9 @@
namespace ui {
static const Clipboard::FormatType& GetRendererTaintFormatType() {
- CR_DEFINE_STATIC_LOCAL(
- Clipboard::FormatType,
- format,
- (ui::Clipboard::GetFormatType("chromium/x-renderer-taint")));
- return format;
+ static base::NoDestructor<Clipboard::FormatType> format(
+ ui::Clipboard::GetFormatType("chromium/x-renderer-taint"));
+ return *format;
}
// Creates a new STGMEDIUM object to hold the specified text. The caller
@@ -57,8 +56,9 @@ static void GetInternetShortcutFileContents(const GURL& url, std::string* data);
static void CreateValidFileNameFromTitle(const GURL& url,
const base::string16& title,
base::string16* validated);
-// Creates a new STGMEDIUM object to hold a file.
-static STGMEDIUM* GetStorageForFileName(const base::FilePath& path);
+// Creates a new STGMEDIUM object to hold files.
+static STGMEDIUM* GetStorageForFileNames(
+ const std::vector<FileInfo>& filenames);
static STGMEDIUM* GetIDListStorageForFileName(const base::FilePath& path);
// Creates a File Descriptor for the creation of a file to the given URL and
// returns a handle to it.
@@ -346,7 +346,7 @@ void OSExchangeDataProviderWin::SetURL(const GURL& url,
Clipboard::GetUrlFormatType().ToFormatEtc(), storage));
// TODO(beng): add CF_HTML.
- // http://code.google.com/p/chromium/issues/detail?id=6767
+ // http://code.google.com/p/chromium/issues/detail?id=6767GetIDListStorageForFileName
// Also add text representations (these should be last since they're the
// least preferable).
@@ -354,11 +354,9 @@ void OSExchangeDataProviderWin::SetURL(const GURL& url,
}
void OSExchangeDataProviderWin::SetFilename(const base::FilePath& path) {
- STGMEDIUM* storage = GetStorageForFileName(path);
- data_->contents_.push_back(std::make_unique<DataObjectImpl::StoredDataInfo>(
- Clipboard::GetCFHDropFormatType().ToFormatEtc(), storage));
+ SetFilenames({FileInfo(path, base::FilePath())});
- storage = GetIDListStorageForFileName(path);
+ STGMEDIUM* storage = GetIDListStorageForFileName(path);
if (!storage)
return;
data_->contents_.push_back(std::make_unique<DataObjectImpl::StoredDataInfo>(
@@ -367,11 +365,12 @@ void OSExchangeDataProviderWin::SetFilename(const base::FilePath& path) {
void OSExchangeDataProviderWin::SetFilenames(
const std::vector<FileInfo>& filenames) {
- for (size_t i = 0; i < filenames.size(); ++i) {
- STGMEDIUM* storage = GetStorageForFileName(filenames[i].path);
- data_->contents_.push_back(std::make_unique<DataObjectImpl::StoredDataInfo>(
- Clipboard::GetCFHDropFormatType().ToFormatEtc(), storage));
- }
+ STGMEDIUM* storage = GetStorageForFileNames(filenames);
+ if (!storage)
+ return;
+
+ data_->contents_.push_back(std::make_unique<DataObjectImpl::StoredDataInfo>(
+ Clipboard::GetCFHDropFormatType().ToFormatEtc(), storage));
}
void OSExchangeDataProviderWin::SetPickledData(
@@ -537,7 +536,7 @@ void OSExchangeDataProviderWin::SetDownloadFileInfo(
// think we always synthesize one in WebContentsDragWin.
STGMEDIUM* storage = NULL;
if (!download.filename.empty())
- storage = GetStorageForFileName(download.filename);
+ GetStorageForFileNames({FileInfo(download.filename, base::FilePath())});
// Add CF_HDROP.
auto info = std::make_unique<DataObjectImpl::StoredDataInfo>(
@@ -752,8 +751,12 @@ void DataObjectImpl::OnDownloadCompleted(const base::FilePath& file_path) {
}
// Update the storage.
- (*iter)->owns_medium = true;
- (*iter)->medium = GetStorageForFileName(file_path);
+ STGMEDIUM* storage =
+ GetStorageForFileNames({FileInfo(file_path, base::FilePath())});
+ if (storage) {
+ (*iter)->owns_medium = true;
+ (*iter)->medium = storage;
+ }
break;
}
@@ -1003,26 +1006,52 @@ static void CreateValidFileNameFromTitle(const GURL& url,
*validated += extension;
}
-static STGMEDIUM* GetStorageForFileName(const base::FilePath& path) {
- const size_t kDropSize = sizeof(DROPFILES);
- const size_t kTotalBytes =
- kDropSize + (path.value().length() + 2) * sizeof(wchar_t);
- HANDLE hdata = GlobalAlloc(GMEM_MOVEABLE, kTotalBytes);
+static STGMEDIUM* GetStorageForFileNames(
+ const std::vector<FileInfo>& filenames) {
+ // CF_HDROP clipboard format consists of DROPFILES structure, a series of file
+ // names including the terminating null character and the additional null
+ // character at the tail to terminate the array.
+ // For example,
+ //| DROPFILES | FILENAME 1 | NULL | ... | FILENAME n | NULL | NULL |
+ // For more details, please refer to
+ // https://docs.microsoft.com/ko-kr/windows/desktop/shell/clipboard#cf_hdrop
+
+ if (filenames.empty())
+ return nullptr;
+
+ const size_t kDropFilesHeaderSizeInBytes = sizeof(DROPFILES);
+ size_t total_bytes = kDropFilesHeaderSizeInBytes;
+ for (const auto& filename : filenames) {
+ // Allocate memory of the filename's length including the null
+ // character.
+ total_bytes += (filename.path.value().length() + 1) * sizeof(wchar_t);
+ }
+ // |data| needs to be terminated by an additional null character.
+ total_bytes += sizeof(wchar_t);
+
+ // GHND combines GMEM_MOVEABLE and GMEM_ZEROINIT, and GMEM_ZEROINIT
+ // initializes memory contents to zero.
+ HANDLE hdata = GlobalAlloc(GHND, total_bytes);
base::win::ScopedHGlobal<DROPFILES*> locked_mem(hdata);
DROPFILES* drop_files = locked_mem.get();
drop_files->pFiles = sizeof(DROPFILES);
drop_files->fWide = TRUE;
+
wchar_t* data = reinterpret_cast<wchar_t*>(
- reinterpret_cast<BYTE*>(drop_files) + kDropSize);
- const size_t copy_size = (path.value().length() + 1) * sizeof(wchar_t);
- memcpy(data, path.value().c_str(), copy_size);
- data[path.value().length() + 1] = L'\0'; // Double NULL
+ reinterpret_cast<BYTE*>(drop_files) + kDropFilesHeaderSizeInBytes);
+
+ size_t next_filename_offset = 0;
+ for (const auto& filename : filenames) {
+ wcscpy(data + next_filename_offset, filename.path.value().c_str());
+ // Skip the terminating null character of the filename.
+ next_filename_offset += filename.path.value().length() + 1;
+ }
STGMEDIUM* storage = new STGMEDIUM;
storage->tymed = TYMED_HGLOBAL;
storage->hGlobal = hdata;
- storage->pUnkForRelease = NULL;
+ storage->pUnkForRelease = nullptr;
return storage;
}
diff --git a/chromium/ui/base/dragdrop/os_exchange_data_unittest.cc b/chromium/ui/base/dragdrop/os_exchange_data_unittest.cc
index 62d98d1b77a..9291ca57f51 100644
--- a/chromium/ui/base/dragdrop/os_exchange_data_unittest.cc
+++ b/chromium/ui/base/dragdrop/os_exchange_data_unittest.cc
@@ -12,6 +12,7 @@
#include "net/base/filename_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "testing/platform_test.h"
+#include "ui/base/dragdrop/file_info.h"
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/events/platform/platform_event_source.h"
#include "url/gurl.h"
@@ -164,6 +165,30 @@ TEST_F(OSExchangeDataTest, TestPickledData) {
EXPECT_EQ(2, value);
}
+TEST_F(OSExchangeDataTest, TestFilenames) {
+#if defined(OS_WIN)
+ const std::vector<FileInfo> kTestFilenames = {
+ {base::FilePath(FILE_PATH_LITERAL("C:\\tmp\\test_file1")),
+ base::FilePath()},
+ {base::FilePath(FILE_PATH_LITERAL("C:\\tmp\\test_file2")),
+ base::FilePath()},
+ };
+#else
+ const std::vector<FileInfo> kTestFilenames = {
+ {base::FilePath(FILE_PATH_LITERAL("/tmp/test_file1")), base::FilePath()},
+ {base::FilePath(FILE_PATH_LITERAL("/tmp/test_file2")), base::FilePath()},
+ };
+#endif
+ OSExchangeData data;
+ data.SetFilenames(kTestFilenames);
+
+ OSExchangeData copy(data.provider().Clone());
+ std::vector<FileInfo> dropped_filenames;
+
+ EXPECT_TRUE(copy.GetFilenames(&dropped_filenames));
+ EXPECT_EQ(kTestFilenames, dropped_filenames);
+}
+
#if defined(USE_AURA)
TEST_F(OSExchangeDataTest, TestHTML) {
OSExchangeData data;
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 536c4d37d7d..09bf9b0d6a3 100644
--- a/chromium/ui/base/dragdrop/os_exchange_data_win_unittest.cc
+++ b/chromium/ui/base/dragdrop/os_exchange_data_win_unittest.cc
@@ -11,6 +11,7 @@
#include "base/win/scoped_hglobal.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/clipboard/clipboard.h"
+#include "ui/base/dragdrop/file_info.h"
#include "ui/base/dragdrop/os_exchange_data_provider_win.h"
#include "url/gurl.h"
diff --git a/chromium/ui/base/ime/BUILD.gn b/chromium/ui/base/ime/BUILD.gn
index f143cd4db17..df6079261fd 100644
--- a/chromium/ui/base/ime/BUILD.gn
+++ b/chromium/ui/base/ime/BUILD.gn
@@ -4,6 +4,7 @@
import("//build/config/jumbo.gni")
import("//build/config/linux/pangocairo/pangocairo.gni")
+import("//build/config/jumbo.gni")
import("//build/config/ui.gni")
import("//testing/test.gni")
@@ -15,56 +16,48 @@ source_set("text_input_types") {
]
}
-jumbo_component("ime") {
- output_name = "ui_base_ime"
+jumbo_component("ime_types") {
+ output_name = "ui_base_ime_types"
sources = [
"candidate_window.cc",
"candidate_window.h",
- "chromeos/character_composer.cc",
- "chromeos/character_composer.h",
- "chromeos/component_extension_ime_manager.cc",
- "chromeos/component_extension_ime_manager.h",
- "chromeos/extension_ime_util.cc",
- "chromeos/extension_ime_util.h",
- "chromeos/fake_ime_keyboard.cc",
- "chromeos/fake_ime_keyboard.h",
- "chromeos/fake_input_method_delegate.cc",
- "chromeos/fake_input_method_delegate.h",
- "chromeos/ime_candidate_window_handler_interface.h",
- "chromeos/ime_keyboard.cc",
- "chromeos/ime_keyboard.h",
- "chromeos/ime_keymap.cc",
- "chromeos/ime_keymap.h",
- "chromeos/input_method_delegate.h",
- "chromeos/input_method_descriptor.cc",
- "chromeos/input_method_descriptor.h",
- "chromeos/input_method_manager.cc",
- "chromeos/input_method_manager.h",
- "chromeos/input_method_util.cc",
- "chromeos/input_method_util.h",
- "chromeos/mock_component_extension_ime_manager.cc",
- "chromeos/mock_component_extension_ime_manager.h",
- "chromeos/mock_component_extension_ime_manager_delegate.cc",
- "chromeos/mock_component_extension_ime_manager_delegate.h",
- "chromeos/mock_ime_candidate_window_handler.cc",
- "chromeos/mock_ime_candidate_window_handler.h",
- "chromeos/mock_ime_engine_handler.cc",
- "chromeos/mock_ime_engine_handler.h",
"composition_text.cc",
"composition_text.h",
- "ime_bridge.cc",
- "ime_bridge.h",
- "ime_engine_handler_interface.h",
- "ime_input_context_handler_interface.h",
"ime_text_span.cc",
"ime_text_span.h",
"infolist_entry.cc",
"infolist_entry.h",
+ "ui_base_ime_types_export.h",
+ ]
+
+ defines = [ "UI_BASE_IME_TYPES_IMPLEMENTATION" ]
+
+ deps = [
+ "//base",
+ "//ui/gfx/range",
+ ]
+
+ public_deps = [
+ ":text_input_types",
+ "//skia",
+ ]
+}
+
+jumbo_component("ime") {
+ output_name = "ui_base_ime"
+ sources = [
+ "constants.cc",
+ "constants.h",
+ "ime_bridge.cc",
+ "ime_bridge.h",
+ "ime_engine_handler_interface.h",
+ "ime_input_context_handler_interface.h",
"input_method.h",
"input_method_base.cc",
"input_method_base.h",
"input_method_chromeos.cc",
"input_method_chromeos.h",
+ "input_method_delegate.cc",
"input_method_delegate.h",
"input_method_factory.cc",
"input_method_factory.h",
@@ -79,13 +72,6 @@ jumbo_component("ime") {
"input_method_minimal.cc",
"input_method_minimal.h",
"input_method_observer.h",
- "linux/fake_input_method_context.cc",
- "linux/fake_input_method_context.h",
- "linux/fake_input_method_context_factory.cc",
- "linux/fake_input_method_context_factory.h",
- "linux/linux_input_method_context.h",
- "linux/linux_input_method_context_factory.cc",
- "linux/linux_input_method_context_factory.h",
"mock_ime_input_context_handler.cc",
"mock_ime_input_context_handler.h",
"mock_input_method.cc",
@@ -110,6 +96,41 @@ jumbo_component("ime") {
"win/tsf_text_store.h",
]
+ if (is_chromeos) {
+ sources += [
+ "chromeos/character_composer.cc",
+ "chromeos/character_composer.h",
+ "chromeos/component_extension_ime_manager.cc",
+ "chromeos/component_extension_ime_manager.h",
+ "chromeos/extension_ime_util.cc",
+ "chromeos/extension_ime_util.h",
+ "chromeos/fake_ime_keyboard.cc",
+ "chromeos/fake_ime_keyboard.h",
+ "chromeos/fake_input_method_delegate.cc",
+ "chromeos/fake_input_method_delegate.h",
+ "chromeos/ime_candidate_window_handler_interface.h",
+ "chromeos/ime_keyboard.cc",
+ "chromeos/ime_keyboard.h",
+ "chromeos/ime_keymap.cc",
+ "chromeos/ime_keymap.h",
+ "chromeos/input_method_delegate.h",
+ "chromeos/input_method_descriptor.cc",
+ "chromeos/input_method_descriptor.h",
+ "chromeos/input_method_manager.cc",
+ "chromeos/input_method_manager.h",
+ "chromeos/input_method_util.cc",
+ "chromeos/input_method_util.h",
+ "chromeos/mock_component_extension_ime_manager.cc",
+ "chromeos/mock_component_extension_ime_manager.h",
+ "chromeos/mock_component_extension_ime_manager_delegate.cc",
+ "chromeos/mock_component_extension_ime_manager_delegate.h",
+ "chromeos/mock_ime_candidate_window_handler.cc",
+ "chromeos/mock_ime_candidate_window_handler.h",
+ "chromeos/mock_ime_engine_handler.cc",
+ "chromeos/mock_ime_engine_handler.h",
+ ]
+ }
+
# TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
configs += [ "//build/config/compiler:no_size_t_to_int_warning" ]
@@ -132,8 +153,7 @@ jumbo_component("ime") {
]
public_deps = [
- ":text_input_types",
- "//skia",
+ ":ime_types",
]
if (is_desktop_linux) {
@@ -143,6 +163,10 @@ jumbo_component("ime") {
]
}
+ if (is_linux) {
+ public_deps += [ "//ui/base/ime/linux" ]
+ }
+
if (!is_chromeos && is_linux) {
sources += [
"linux/text_edit_command_auralinux.cc",
@@ -211,4 +235,19 @@ jumbo_component("ime") {
if (is_mac) {
libs = [ "AppKit.framework" ]
}
+
+ if (is_fuchsia) {
+ sources += [
+ "fuchsia/input_method_keyboard_controller_fuchsia.cc",
+ "fuchsia/input_method_keyboard_controller_fuchsia.h",
+ "input_method_fuchsia.cc",
+ "input_method_fuchsia.h",
+ ]
+
+ deps += [
+ "//third_party/fuchsia-sdk/sdk:input",
+ "//ui/events",
+ "//ui/events:dom_keycode_converter",
+ ]
+ }
}
diff --git a/chromium/ui/base/ime/candidate_window.h b/chromium/ui/base/ime/candidate_window.h
index f27bfe29b70..60b8f68e409 100644
--- a/chromium/ui/base/ime/candidate_window.h
+++ b/chromium/ui/base/ime/candidate_window.h
@@ -13,19 +13,19 @@
#include "base/macros.h"
#include "ui/base/ime/infolist_entry.h"
-#include "ui/base/ime/ui_base_ime_export.h"
+#include "ui/base/ime/ui_base_ime_types_export.h"
namespace ui {
// CandidateWindow represents the structure of candidates generated from IME.
-class UI_BASE_IME_EXPORT CandidateWindow {
+class UI_BASE_IME_TYPES_EXPORT CandidateWindow {
public:
enum Orientation {
HORIZONTAL = 0,
VERTICAL = 1,
};
- struct UI_BASE_IME_EXPORT CandidateWindowProperty {
+ struct UI_BASE_IME_TYPES_EXPORT CandidateWindowProperty {
CandidateWindowProperty();
virtual ~CandidateWindowProperty();
int page_size;
@@ -41,7 +41,7 @@ class UI_BASE_IME_EXPORT CandidateWindow {
};
// Represents a candidate entry.
- struct UI_BASE_IME_EXPORT Entry {
+ struct UI_BASE_IME_TYPES_EXPORT Entry {
Entry();
Entry(const Entry& other);
virtual ~Entry();
diff --git a/chromium/ui/base/ime/composition_text.h b/chromium/ui/base/ime/composition_text.h
index 272535ba3e6..6d05f15bce5 100644
--- a/chromium/ui/base/ime/composition_text.h
+++ b/chromium/ui/base/ime/composition_text.h
@@ -9,13 +9,13 @@
#include "base/strings/string16.h"
#include "ui/base/ime/ime_text_span.h"
-#include "ui/base/ime/ui_base_ime_export.h"
+#include "ui/base/ime/ui_base_ime_types_export.h"
#include "ui/gfx/range/range.h"
namespace ui {
// A struct represents the status of an ongoing composition text.
-struct UI_BASE_IME_EXPORT CompositionText {
+struct UI_BASE_IME_TYPES_EXPORT CompositionText {
CompositionText();
CompositionText(const CompositionText& other);
~CompositionText();
diff --git a/chromium/ui/base/ime/constants.cc b/chromium/ui/base/ime/constants.cc
new file mode 100644
index 00000000000..e9556078fc3
--- /dev/null
+++ b/chromium/ui/base/ime/constants.cc
@@ -0,0 +1,11 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/ime/constants.h"
+
+namespace ui {
+
+const char kPropertyFromVK[] = "from_vk";
+
+} // namespace ui
diff --git a/chromium/ui/base/ime/constants.h b/chromium/ui/base/ime/constants.h
new file mode 100644
index 00000000000..f5e812a7b44
--- /dev/null
+++ b/chromium/ui/base/ime/constants.h
@@ -0,0 +1,21 @@
+// 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_BASE_IME_CONSTANTS_H_
+#define UI_BASE_IME_CONSTANTS_H_
+
+#include "ui/base/ime/ui_base_ime_export.h"
+
+namespace ui {
+
+// The name of the property that is attach to the key event and indicates
+// whether it was from the virtual keyboard.
+// This is used where the key event is simulated by the virtual keyboard
+// (e.g. IME extension API) as well as the input field implementation (e.g.
+// Textfield).
+UI_BASE_IME_EXPORT extern const char kPropertyFromVK[];
+
+} // namespace ui
+
+#endif // UI_BASE_IME_CONSTANTS_H_
diff --git a/chromium/ui/base/ime/fuchsia/input_method_keyboard_controller_fuchsia.cc b/chromium/ui/base/ime/fuchsia/input_method_keyboard_controller_fuchsia.cc
new file mode 100644
index 00000000000..b2f5b9fd580
--- /dev/null
+++ b/chromium/ui/base/ime/fuchsia/input_method_keyboard_controller_fuchsia.cc
@@ -0,0 +1,96 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/ime/fuchsia/input_method_keyboard_controller_fuchsia.h"
+
+#include <utility>
+
+#include "base/fuchsia/component_context.h"
+#include "base/logging.h"
+#include "ui/base/ime/text_input_client.h"
+#include "ui/events/base_event_utils.h"
+#include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/events/keycodes/dom/keycode_converter.h"
+
+namespace ui {
+
+InputMethodKeyboardControllerFuchsia::InputMethodKeyboardControllerFuchsia(
+ InputMethodFuchsia* input_method)
+ : event_converter_(input_method),
+ ime_client_binding_(this),
+ ime_service_(base::fuchsia::ComponentContext::GetDefault()
+ ->ConnectToService<fuchsia::ui::input::ImeService>()),
+ ime_visibility_(
+ base::fuchsia::ComponentContext::GetDefault()
+ ->ConnectToService<fuchsia::ui::input::ImeVisibilityService>()),
+ input_method_(input_method) {
+ DCHECK(ime_service_);
+ DCHECK(input_method_);
+
+ ime_service_.set_error_handler([this]() {
+ LOG(ERROR) << "Lost connection to IME service.";
+ ime_.Unbind();
+ ime_client_binding_.Unbind();
+ });
+
+ ime_visibility_.events().OnKeyboardVisibilityChanged = [this](bool visible) {
+ keyboard_visible_ = visible;
+ };
+}
+
+InputMethodKeyboardControllerFuchsia::~InputMethodKeyboardControllerFuchsia() =
+ default;
+
+bool InputMethodKeyboardControllerFuchsia::DisplayVirtualKeyboard() {
+ if (!ime_) {
+ // TODO(crbug.com/876934): Instantiate the IME with details about the
+ // current composition.
+ 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());
+ }
+
+ if (!keyboard_visible_) {
+ ime_service_->ShowKeyboard();
+ }
+
+ return true;
+}
+
+void InputMethodKeyboardControllerFuchsia::DismissVirtualKeyboard() {
+ if (keyboard_visible_) {
+ ime_service_->HideKeyboard();
+ }
+}
+
+void InputMethodKeyboardControllerFuchsia::AddObserver(
+ InputMethodKeyboardControllerObserver* observer) {}
+
+void InputMethodKeyboardControllerFuchsia::RemoveObserver(
+ InputMethodKeyboardControllerObserver* observer) {}
+
+bool InputMethodKeyboardControllerFuchsia::IsKeyboardVisible() {
+ return keyboard_visible_;
+}
+
+void InputMethodKeyboardControllerFuchsia::DidUpdateState(
+ fuchsia::ui::input::TextInputState state,
+ std::unique_ptr<fuchsia::ui::input::InputEvent> input_event) {
+ if (input_event->is_keyboard())
+ event_converter_.ProcessEvent(*input_event);
+}
+
+void InputMethodKeyboardControllerFuchsia::OnAction(
+ fuchsia::ui::input::InputMethodAction action) {
+ // 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());
+ input_method_->DispatchKeyEvent(&key_event);
+}
+
+} // namespace ui
diff --git a/chromium/ui/base/ime/fuchsia/input_method_keyboard_controller_fuchsia.h b/chromium/ui/base/ime/fuchsia/input_method_keyboard_controller_fuchsia.h
new file mode 100644
index 00000000000..01b53ea2704
--- /dev/null
+++ b/chromium/ui/base/ime/fuchsia/input_method_keyboard_controller_fuchsia.h
@@ -0,0 +1,59 @@
+// 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_BASE_IME_FUCHSIA_INPUT_METHOD_KEYBOARD_CONTROLLER_FUCHSIA_H_
+#define UI_BASE_IME_FUCHSIA_INPUT_METHOD_KEYBOARD_CONTROLLER_FUCHSIA_H_
+
+#include <fuchsia/ui/input/cpp/fidl.h>
+#include <lib/fidl/cpp/binding.h>
+#include <memory>
+
+#include "base/macros.h"
+#include "ui/base/ime/input_method_fuchsia.h"
+#include "ui/base/ime/input_method_keyboard_controller.h"
+#include "ui/base/ime/ui_base_ime_export.h"
+#include "ui/events/fuchsia/input_event_dispatcher.h"
+
+namespace ui {
+
+// Handles input events from the Fuchsia on-screen keyboard.
+class UI_BASE_IME_EXPORT InputMethodKeyboardControllerFuchsia
+ : public InputMethodKeyboardController,
+ public fuchsia::ui::input::InputMethodEditorClient {
+ public:
+ // |input_method|: Pointer to the parent InputMethod which owns |this|.
+ explicit InputMethodKeyboardControllerFuchsia(
+ InputMethodFuchsia* input_method);
+ ~InputMethodKeyboardControllerFuchsia() override;
+
+ // InputMethodKeyboardController implementation.
+ bool DisplayVirtualKeyboard() override;
+ void DismissVirtualKeyboard() override;
+ void AddObserver(InputMethodKeyboardControllerObserver* observer) override;
+ void RemoveObserver(InputMethodKeyboardControllerObserver* observer) override;
+ bool IsKeyboardVisible() override;
+
+ private:
+ // InputMethodEditorClient implementation.
+ void DidUpdateState(
+ fuchsia::ui::input::TextInputState state,
+ std::unique_ptr<fuchsia::ui::input::InputEvent> input_event) override;
+ void OnAction(fuchsia::ui::input::InputMethodAction action) override;
+
+ bool keyboard_visible_ = false;
+ InputEventDispatcher event_converter_;
+ fidl::Binding<fuchsia::ui::input::InputMethodEditorClient>
+ ime_client_binding_;
+ fuchsia::ui::input::ImeServicePtr ime_service_;
+ fuchsia::ui::input::InputMethodEditorPtr ime_;
+ fuchsia::ui::input::ImeVisibilityServicePtr ime_visibility_;
+
+ InputMethodFuchsia* input_method_;
+
+ DISALLOW_COPY_AND_ASSIGN(InputMethodKeyboardControllerFuchsia);
+};
+
+} // namespace ui
+
+#endif // UI_BASE_IME_FUCHSIA_INPUT_METHOD_KEYBOARD_CONTROLLER_FUCHSIA_H_
diff --git a/chromium/ui/base/ime/ime_text_span.h b/chromium/ui/base/ime/ime_text_span.h
index e47064a1a63..52011f3c067 100644
--- a/chromium/ui/base/ime/ime_text_span.h
+++ b/chromium/ui/base/ime/ime_text_span.h
@@ -11,14 +11,14 @@
#include <vector>
#include "third_party/skia/include/core/SkColor.h"
-#include "ui/base/ime/ui_base_ime_export.h"
+#include "ui/base/ime/ui_base_ime_types_export.h"
namespace ui {
// Intentionally keep sync with blink::WebImeTextSpan defined in:
// third_party/WebKit/public/web/WebImeTextSpan.h
-struct UI_BASE_IME_EXPORT ImeTextSpan {
+struct UI_BASE_IME_TYPES_EXPORT ImeTextSpan {
enum class Type {
// Creates a composition marker.
kComposition,
diff --git a/chromium/ui/base/ime/infolist_entry.h b/chromium/ui/base/ime/infolist_entry.h
index a19d8541077..1e16e5e938f 100644
--- a/chromium/ui/base/ime/infolist_entry.h
+++ b/chromium/ui/base/ime/infolist_entry.h
@@ -6,12 +6,12 @@
#define UI_BASE_IME_INFOLIST_ENTRY_H_
#include "base/strings/string16.h"
-#include "ui/base/ime/ui_base_ime_export.h"
+#include "ui/base/ime/ui_base_ime_types_export.h"
namespace ui {
// The data model of infolist window.
-struct UI_BASE_IME_EXPORT InfolistEntry {
+struct UI_BASE_IME_TYPES_EXPORT InfolistEntry {
base::string16 title;
base::string16 body;
bool highlighted;
diff --git a/chromium/ui/base/ime/input_method_auralinux.cc b/chromium/ui/base/ime/input_method_auralinux.cc
index 699792009be..f7343b30c07 100644
--- a/chromium/ui/base/ime/input_method_auralinux.cc
+++ b/chromium/ui/base/ime/input_method_auralinux.cc
@@ -6,6 +6,7 @@
#include "base/auto_reset.h"
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/environment.h"
#include "ui/base/ime/ime_bridge.h"
#include "ui/base/ime/ime_engine_handler_interface.h"
@@ -52,11 +53,12 @@ ui::EventDispatchDetails InputMethodAuraLinux::DispatchKeyEvent(
// If no text input client, do nothing.
if (!GetTextInputClient())
- return DispatchKeyEventPostIME(event);
+ return DispatchKeyEventPostIME(event, base::NullCallback());
if (!event->HasNativeEvent() && sending_key_event()) {
// Faked key events that are sent from input.ime.sendKeyEvents.
- ui::EventDispatchDetails details = DispatchKeyEventPostIME(event);
+ ui::EventDispatchDetails details =
+ DispatchKeyEventPostIME(event, base::NullCallback());
if (details.dispatcher_destroyed || details.target_destroyed ||
event->stopped_propagation()) {
return details;
@@ -135,7 +137,7 @@ ui::EventDispatchDetails InputMethodAuraLinux::ProcessKeyEventDone(
ui::EventDispatchDetails details;
if (event->type() == ui::ET_KEY_PRESSED && filtered) {
if (NeedInsertChar())
- details = DispatchKeyEventPostIME(event);
+ details = DispatchKeyEventPostIME(event, base::NullCallback());
else if (HasInputMethodResult())
details = SendFakeProcessKeyEvent(event);
if (details.dispatcher_destroyed)
@@ -194,7 +196,7 @@ ui::EventDispatchDetails InputMethodAuraLinux::ProcessKeyEventDone(
composition_ = CompositionText();
if (!filtered) {
- details = DispatchKeyEventPostIME(event);
+ details = DispatchKeyEventPostIME(event, base::NullCallback());
if (details.dispatcher_destroyed) {
if (should_stop_propagation)
event->StopPropagation();
@@ -275,6 +277,14 @@ void InputMethodAuraLinux::OnCaretBoundsChanged(const TextInputClient* client) {
NotifyTextInputCaretBoundsChanged(client);
context_->SetCursorLocation(GetTextInputClient()->GetCaretBounds());
+ gfx::Range text_range, selection_range;
+ base::string16 text;
+ if (client->GetTextRange(&text_range) &&
+ client->GetTextFromRange(text_range, &text) &&
+ client->GetSelectionRange(&selection_range)) {
+ context_->SetSurroundingText(text, selection_range);
+ }
+
if (!IsTextInputTypeNone() && text_input_type_ != TEXT_INPUT_TYPE_PASSWORD &&
GetEngine())
GetEngine()->SetCompositionBounds(GetCompositionBounds(client));
@@ -307,13 +317,6 @@ void InputMethodAuraLinux::ResetContext() {
context_->Reset();
context_simple_->Reset();
- // Some input methods may not honour the reset call. Focusing out/in the
- // |context_| to make sure it gets reset correctly.
- if (text_input_type_ != TEXT_INPUT_TYPE_NONE) {
- context_->Blur();
- context_->Focus();
- }
-
composition_ = CompositionText();
result_text_.clear();
is_sync_mode_ = false;
@@ -353,6 +356,14 @@ void InputMethodAuraLinux::OnCommit(const base::string16& text) {
}
}
+void InputMethodAuraLinux::OnDeleteSurroundingText(int32_t index,
+ uint32_t length) {
+ if (GetTextInputClient() && composition_.text.empty()) {
+ uint32_t before = index >= 0 ? 0U : static_cast<uint32_t>(-1 * index);
+ GetTextInputClient()->ExtendSelectionAndDelete(before, length - before);
+ }
+}
+
void InputMethodAuraLinux::OnPreeditChanged(
const CompositionText& composition_text) {
if (IgnoringNonKeyInput() || IsTextInputTypeNone())
@@ -432,7 +443,8 @@ bool InputMethodAuraLinux::NeedInsertChar() const {
ui::EventDispatchDetails InputMethodAuraLinux::SendFakeProcessKeyEvent(
ui::KeyEvent* event) const {
KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_PROCESSKEY, event->flags());
- ui::EventDispatchDetails details = DispatchKeyEventPostIME(&key_event);
+ ui::EventDispatchDetails details =
+ DispatchKeyEventPostIME(&key_event, base::NullCallback());
if (key_event.stopped_propagation())
event->StopPropagation();
return details;
diff --git a/chromium/ui/base/ime/input_method_auralinux.h b/chromium/ui/base/ime/input_method_auralinux.h
index ef4985b95c6..8963ab945ad 100644
--- a/chromium/ui/base/ime/input_method_auralinux.h
+++ b/chromium/ui/base/ime/input_method_auralinux.h
@@ -35,6 +35,7 @@ class UI_BASE_IME_EXPORT InputMethodAuraLinux
// Overriden from ui::LinuxInputMethodContextDelegate
void OnCommit(const base::string16& text) override;
+ void OnDeleteSurroundingText(int32_t index, uint32_t length) override;
void OnPreeditChanged(const CompositionText& composition_text) override;
void OnPreeditEnd() override;
void OnPreeditStart() override {}
diff --git a/chromium/ui/base/ime/input_method_auralinux_unittest.cc b/chromium/ui/base/ime/input_method_auralinux_unittest.cc
index 7424f5f5024..2496391504e 100644
--- a/chromium/ui/base/ime/input_method_auralinux_unittest.cc
+++ b/chromium/ui/base/ime/input_method_auralinux_unittest.cc
@@ -125,6 +125,19 @@ class LinuxInputMethodContextForTesting : public LinuxInputMethodContext {
cursor_position_ = rect;
}
+ void SetSurroundingText(const base::string16& text,
+ const gfx::Range& selection_range) override {
+ TestResult::GetInstance()->RecordAction(
+ base::ASCIIToUTF16("surroundingtext:") + text);
+
+ std::stringstream rs;
+ rs << "selectionrangestart:" << selection_range.start();
+ std::stringstream re;
+ re << "selectionrangeend:" << selection_range.end();
+ TestResult::GetInstance()->RecordAction(base::ASCIIToUTF16(rs.str()));
+ TestResult::GetInstance()->RecordAction(base::ASCIIToUTF16(re.str()));
+ };
+
private:
LinuxInputMethodContextDelegate* delegate_;
std::vector<base::string16> actions_;
@@ -158,7 +171,8 @@ class InputMethodDelegateForTesting : public internal::InputMethodDelegate {
~InputMethodDelegateForTesting() override {}
ui::EventDispatchDetails DispatchKeyEventPostIME(
- ui::KeyEvent* key_event) override {
+ ui::KeyEvent* key_event,
+ base::OnceCallback<void(bool)> ack_callback) override {
std::string action;
switch (key_event->type()) {
case ET_KEY_PRESSED:
@@ -174,6 +188,7 @@ class InputMethodDelegateForTesting : public internal::InputMethodDelegate {
ss << key_event->key_code();
action += std::string(ss.str());
TestResult::GetInstance()->RecordAction(base::ASCIIToUTF16(action));
+ CallDispatchKeyEventPostIMEAck(key_event, std::move(ack_callback));
return ui::EventDispatchDetails();
}
@@ -187,6 +202,9 @@ class TextInputClientForTesting : public DummyTextInputClient {
: DummyTextInputClient(text_input_type){};
base::string16 composition_text;
+ gfx::Range text_range;
+ gfx::Range selection_range;
+ base::string16 surrounding_text;
protected:
void SetCompositionText(const CompositionText& composition) override {
@@ -229,6 +247,22 @@ class TextInputClientForTesting : public DummyTextInputClient {
TestResult::GetInstance()->RecordAction(base::ASCIIToUTF16("keypress:") +
base::ASCIIToUTF16(ss.str()));
}
+
+ bool GetTextRange(gfx::Range* range) const override {
+ *range = text_range;
+ return true;
+ }
+ bool GetSelectionRange(gfx::Range* range) const override {
+ *range = selection_range;
+ return true;
+ }
+ bool GetTextFromRange(const gfx::Range& range,
+ base::string16* text) const override {
+ if (surrounding_text.empty())
+ return false;
+ *text = surrounding_text.substr(range.GetMin(), range.length());
+ return true;
+ }
};
class InputMethodAuraLinuxTest : public testing::Test {
@@ -760,5 +794,59 @@ TEST_F(InputMethodAuraLinuxTest, ReleaseKeyTest) {
test_result_->Verify();
}
+TEST_F(InputMethodAuraLinuxTest, SurroundingText_NoSelectionTest) {
+ std::unique_ptr<TextInputClientForTesting> client(
+ new TextInputClientForTesting(TEXT_INPUT_TYPE_TEXT));
+ input_method_auralinux_->SetFocusedTextInputClient(client.get());
+ input_method_auralinux_->OnTextInputTypeChanged(client.get());
+
+ client->surrounding_text = base::ASCIIToUTF16("abcdef");
+ client->text_range = gfx::Range(0, 6);
+ client->selection_range = gfx::Range(3, 3);
+
+ input_method_auralinux_->OnCaretBoundsChanged(client.get());
+
+ test_result_->ExpectAction("surroundingtext:abcdef");
+ test_result_->ExpectAction("selectionrangestart:3");
+ test_result_->ExpectAction("selectionrangeend:3");
+ test_result_->Verify();
+}
+
+TEST_F(InputMethodAuraLinuxTest, SurroundingText_SelectionTest) {
+ std::unique_ptr<TextInputClientForTesting> client(
+ new TextInputClientForTesting(TEXT_INPUT_TYPE_TEXT));
+ input_method_auralinux_->SetFocusedTextInputClient(client.get());
+ input_method_auralinux_->OnTextInputTypeChanged(client.get());
+
+ client->surrounding_text = base::ASCIIToUTF16("abcdef");
+ client->text_range = gfx::Range(0, 6);
+ client->selection_range = gfx::Range(2, 5);
+
+ input_method_auralinux_->OnCaretBoundsChanged(client.get());
+
+ test_result_->ExpectAction("surroundingtext:abcdef");
+ test_result_->ExpectAction("selectionrangestart:2");
+ test_result_->ExpectAction("selectionrangeend:5");
+ test_result_->Verify();
+}
+
+TEST_F(InputMethodAuraLinuxTest, SurroundingText_PartialText) {
+ std::unique_ptr<TextInputClientForTesting> client(
+ new TextInputClientForTesting(TEXT_INPUT_TYPE_TEXT));
+ input_method_auralinux_->SetFocusedTextInputClient(client.get());
+ input_method_auralinux_->OnTextInputTypeChanged(client.get());
+
+ client->surrounding_text = base::ASCIIToUTF16("abcdefghij");
+ client->text_range = gfx::Range(5, 10);
+ client->selection_range = gfx::Range(7, 9);
+
+ input_method_auralinux_->OnCaretBoundsChanged(client.get());
+
+ test_result_->ExpectAction("surroundingtext:fghij");
+ test_result_->ExpectAction("selectionrangestart:7");
+ test_result_->ExpectAction("selectionrangeend:9");
+ test_result_->Verify();
+}
+
} // namespace
} // namespace ui
diff --git a/chromium/ui/base/ime/input_method_base.cc b/chromium/ui/base/ime/input_method_base.cc
index df1e94c65b7..76f14cac5af 100644
--- a/chromium/ui/base/ime/input_method_base.cc
+++ b/chromium/ui/base/ime/input_method_base.cc
@@ -5,6 +5,7 @@
#include "ui/base/ime/input_method_base.h"
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/logging.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
@@ -129,7 +130,8 @@ bool InputMethodBase::GetClientShouldDoLearning() {
void InputMethodBase::ShowVirtualKeyboardIfEnabled() {
for (InputMethodObserver& observer : observer_list_)
observer.OnShowVirtualKeyboardIfEnabled();
- GetInputMethodKeyboardController()->DisplayVirtualKeyboard();
+ if (auto* keyboard = GetInputMethodKeyboardController())
+ keyboard->DisplayVirtualKeyboard();
}
void InputMethodBase::AddObserver(InputMethodObserver* observer) {
@@ -142,11 +144,6 @@ void InputMethodBase::RemoveObserver(InputMethodObserver* observer) {
InputMethodKeyboardController*
InputMethodBase::GetInputMethodKeyboardController() {
- if (!keyboard_controller_) {
- NOTIMPLEMENTED() << "Using InputMethodKeyboardControllerStub";
- keyboard_controller_ =
- std::make_unique<InputMethodKeyboardControllerStub>();
- }
return keyboard_controller_.get();
}
@@ -165,23 +162,10 @@ void InputMethodBase::OnInputMethodChanged() const {
}
ui::EventDispatchDetails InputMethodBase::DispatchKeyEventPostIME(
- ui::KeyEvent* event) const {
- ui::EventDispatchDetails details;
- if (delegate_)
- details = delegate_->DispatchKeyEventPostIME(event);
- return details;
-}
-
-ui::EventDispatchDetails InputMethodBase::DispatchKeyEventPostIME(
ui::KeyEvent* event,
base::OnceCallback<void(bool)> ack_callback) const {
- if (delegate_) {
- ui::EventDispatchDetails details =
- delegate_->DispatchKeyEventPostIME(event);
- if (ack_callback)
- std::move(ack_callback).Run(event->stopped_propagation());
- return details;
- }
+ if (delegate_)
+ return delegate_->DispatchKeyEventPostIME(event, std::move(ack_callback));
if (ack_callback)
std::move(ack_callback).Run(false);
@@ -235,7 +219,7 @@ std::vector<gfx::Rect> InputMethodBase::GetCompositionBounds(
bool InputMethodBase::SendFakeProcessKeyEvent(bool pressed) const {
KeyEvent evt(pressed ? ET_KEY_PRESSED : ET_KEY_RELEASED,
pressed ? VKEY_PROCESSKEY : VKEY_UNKNOWN, EF_IME_FABRICATED_KEY);
- ignore_result(DispatchKeyEventPostIME(&evt));
+ ignore_result(DispatchKeyEventPostIME(&evt, base::NullCallback()));
return evt.stopped_propagation();
}
diff --git a/chromium/ui/base/ime/input_method_base.h b/chromium/ui/base/ime/input_method_base.h
index 31fa2742395..afd0342cc42 100644
--- a/chromium/ui/base/ime/input_method_base.h
+++ b/chromium/ui/base/ime/input_method_base.h
@@ -106,11 +106,6 @@ class UI_BASE_IME_EXPORT InputMethodBase
// input type is not TEXT_INPUT_TYPE_NONE.
void OnInputMethodChanged() const;
- // Convenience method to call delegate_->DispatchKeyEventPostIME().
- // Returns true if the event was processed
- ui::EventDispatchDetails DispatchKeyEventPostIME(ui::KeyEvent* event) const
- WARN_UNUSED_RESULT;
-
virtual ui::EventDispatchDetails DispatchKeyEventPostIME(
ui::KeyEvent* event,
base::OnceCallback<void(bool)> ack_callback) const WARN_UNUSED_RESULT;
diff --git a/chromium/ui/base/ime/input_method_chromeos.cc b/chromium/ui/base/ime/input_method_chromeos.cc
index 3478bcd0c76..918bd6eca9a 100644
--- a/chromium/ui/base/ime/input_method_chromeos.cc
+++ b/chromium/ui/base/ime/input_method_chromeos.cc
@@ -474,7 +474,7 @@ void InputMethodChromeOS::PostProcessUnfilteredKeyPressEvent(
if (stopped_propagation) {
ResetContext();
if (ack_callback)
- std::move(ack_callback).Run(false);
+ std::move(ack_callback).Run(true); // true matches |stopped_propagation|.
return;
}
diff --git a/chromium/ui/base/ime/input_method_chromeos_unittest.cc b/chromium/ui/base/ime/input_method_chromeos_unittest.cc
index 6be9f339ffb..5b4a72a861f 100644
--- a/chromium/ui/base/ime/input_method_chromeos_unittest.cc
+++ b/chromium/ui/base/ime/input_method_chromeos_unittest.cc
@@ -237,10 +237,12 @@ class InputMethodChromeOSTest : public internal::InputMethodDelegate,
// Overridden from ui::internal::InputMethodDelegate:
ui::EventDispatchDetails DispatchKeyEventPostIME(
- ui::KeyEvent* event) override {
+ ui::KeyEvent* event,
+ base::OnceCallback<void(bool)> ack_callback) override {
dispatched_key_event_ = *event;
if (stop_propagation_post_ime_)
event->StopPropagation();
+ CallDispatchKeyEventPostIMEAck(event, std::move(ack_callback));
return ui::EventDispatchDetails();
}
diff --git a/chromium/ui/base/ime/input_method_delegate.cc b/chromium/ui/base/ime/input_method_delegate.cc
new file mode 100644
index 00000000000..f2578a51479
--- /dev/null
+++ b/chromium/ui/base/ime/input_method_delegate.cc
@@ -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.
+
+#include "ui/base/ime/input_method_delegate.h"
+
+#include "base/callback.h"
+#include "ui/events/event.h"
+
+namespace ui {
+namespace internal {
+
+// static
+void InputMethodDelegate::CallDispatchKeyEventPostIMEAck(
+ KeyEvent* key_event,
+ base::OnceCallback<void(bool)> ack_callback) {
+ if (ack_callback)
+ std::move(ack_callback).Run(key_event->stopped_propagation());
+}
+
+} // namespace internal
+} // namespace ui
diff --git a/chromium/ui/base/ime/input_method_delegate.h b/chromium/ui/base/ime/input_method_delegate.h
index 7bfa01a242a..4bfae0343ab 100644
--- a/chromium/ui/base/ime/input_method_delegate.h
+++ b/chromium/ui/base/ime/input_method_delegate.h
@@ -5,13 +5,15 @@
#ifndef UI_BASE_IME_INPUT_METHOD_DELEGATE_H_
#define UI_BASE_IME_INPUT_METHOD_DELEGATE_H_
+#include "base/callback_forward.h"
#include "ui/base/ime/ui_base_ime_export.h"
-#include "ui/events/event_dispatcher.h"
namespace ui {
class KeyEvent;
+struct EventDispatchDetails;
+
namespace internal {
// An interface implemented by the object that handles events sent back from an
@@ -20,10 +22,19 @@ class UI_BASE_IME_EXPORT InputMethodDelegate {
public:
virtual ~InputMethodDelegate() {}
- // Dispatch a key event already processed by the input method.
- // Returns true if the event was processed.
- virtual ui::EventDispatchDetails DispatchKeyEventPostIME(
- ui::KeyEvent* key_event) = 0;
+ // Dispatch a key event already processed by the input method. Returns the
+ // status of processing, as well as running the callback |ack_callback| with
+ // the result of processing. |ack_callback| may be run asynchronously (if the
+ // delegate does processing async). |ack_callback| may not be null.
+ // Subclasses can use CallDispatchKeyEventPostIMEAck() to run the callback.
+ virtual EventDispatchDetails DispatchKeyEventPostIME(
+ KeyEvent* key_event,
+ base::OnceCallback<void(bool)> ack_callback) = 0;
+
+ protected:
+ static void CallDispatchKeyEventPostIMEAck(
+ KeyEvent* key_event,
+ base::OnceCallback<void(bool)> ack_callback);
};
} // namespace internal
diff --git a/chromium/ui/base/ime/input_method_factory.cc b/chromium/ui/base/ime/input_method_factory.cc
index 45546b353fa..2cd9b7911a3 100644
--- a/chromium/ui/base/ime/input_method_factory.cc
+++ b/chromium/ui/base/ime/input_method_factory.cc
@@ -18,7 +18,9 @@
#include "ui/base/ime/input_method_win_tsf.h"
#elif defined(OS_MACOSX)
#include "ui/base/ime/input_method_mac.h"
-#elif defined(USE_AURA) && defined(USE_X11)
+#elif defined(OS_FUCHSIA)
+#include "ui/base/ime/input_method_fuchsia.h"
+#elif defined(USE_AURA) && (defined(USE_X11) || defined(USE_OZONE))
#include "ui/base/ime/input_method_auralinux.h"
#else
#include "ui/base/ime/input_method_minimal.h"
@@ -62,7 +64,9 @@ std::unique_ptr<InputMethod> CreateInputMethod(
return std::make_unique<InputMethodWinImm32>(delegate, widget);
#elif defined(OS_MACOSX)
return std::make_unique<InputMethodMac>(delegate);
-#elif defined(USE_AURA) && defined(USE_X11)
+#elif defined(OS_FUCHSIA)
+ return std::make_unique<InputMethodFuchsia>(delegate);
+#elif defined(USE_AURA) && (defined(USE_X11) || defined(USE_OZONE))
return std::make_unique<InputMethodAuraLinux>(delegate);
#else
return std::make_unique<InputMethodMinimal>(delegate);
diff --git a/chromium/ui/base/ime/input_method_fuchsia.cc b/chromium/ui/base/ime/input_method_fuchsia.cc
new file mode 100644
index 00000000000..83f18d4df01
--- /dev/null
+++ b/chromium/ui/base/ime/input_method_fuchsia.cc
@@ -0,0 +1,66 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/ime/input_method_fuchsia.h"
+
+#include <fuchsia/ui/input/cpp/fidl.h>
+#include <memory>
+#include <utility>
+
+#include "base/bind_helpers.h"
+#include "base/fuchsia/component_context.h"
+#include "ui/base/ime/fuchsia/input_method_keyboard_controller_fuchsia.h"
+#include "ui/base/ime/text_input_client.h"
+
+namespace ui {
+
+InputMethodFuchsia::InputMethodFuchsia(internal::InputMethodDelegate* delegate)
+ : InputMethodBase(delegate) {
+ virtual_keyboard_controller_ =
+ std::make_unique<InputMethodKeyboardControllerFuchsia>(this);
+}
+
+InputMethodFuchsia::~InputMethodFuchsia() {}
+
+InputMethodKeyboardController*
+InputMethodFuchsia::GetInputMethodKeyboardController() {
+ return virtual_keyboard_controller_.get();
+}
+
+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);
+
+ // If no text input client, do nothing.
+ if (!GetTextInputClient())
+ return DispatchKeyEventPostIME(event, base::NullCallback());
+
+ // Insert the character.
+ ui::EventDispatchDetails dispatch_details =
+ DispatchKeyEventPostIME(event, base::NullCallback());
+ if (!event->stopped_propagation() && !dispatch_details.dispatcher_destroyed &&
+ event->type() == ET_KEY_PRESSED && GetTextInputClient()) {
+ const uint16_t ch = event->GetCharacter();
+ if (ch) {
+ GetTextInputClient()->InsertChar(*event);
+ event->StopPropagation();
+ }
+ }
+ return dispatch_details;
+}
+
+void InputMethodFuchsia::OnCaretBoundsChanged(const TextInputClient* client) {}
+
+void InputMethodFuchsia::CancelComposition(const TextInputClient* client) {}
+
+bool InputMethodFuchsia::IsCandidatePopupOpen() const {
+ return false;
+}
+
+} // namespace ui
diff --git a/chromium/ui/base/ime/input_method_fuchsia.h b/chromium/ui/base/ime/input_method_fuchsia.h
new file mode 100644
index 00000000000..0c72098c283
--- /dev/null
+++ b/chromium/ui/base/ime/input_method_fuchsia.h
@@ -0,0 +1,49 @@
+// 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_BASE_IME_INPUT_METHOD_FUCHSIA_H_
+#define UI_BASE_IME_INPUT_METHOD_FUCHSIA_H_
+
+#include <fuchsia/ui/input/cpp/fidl.h>
+#include <memory>
+
+#include "base/macros.h"
+#include "ui/base/ime/input_method_base.h"
+#include "ui/base/ime/input_method_delegate.h"
+#include "ui/base/ime/ui_base_ime_export.h"
+#include "ui/events/fuchsia/input_event_dispatcher_delegate.h"
+#include "ui/gfx/native_widget_types.h"
+
+namespace ui {
+
+class InputMethodKeyboardControllerFuchsia;
+
+// Hnadles input from physical keyboards and the IME service.
+class UI_BASE_IME_EXPORT InputMethodFuchsia
+ : public InputMethodBase,
+ public InputEventDispatcherDelegate {
+ public:
+ explicit InputMethodFuchsia(internal::InputMethodDelegate* delegate);
+ ~InputMethodFuchsia() override;
+
+ // InputMethodBase interface implementation.
+ InputMethodKeyboardController* GetInputMethodKeyboardController() override;
+ ui::EventDispatchDetails DispatchKeyEvent(ui::KeyEvent* event) override;
+ void OnCaretBoundsChanged(const TextInputClient* client) override;
+ void CancelComposition(const TextInputClient* client) override;
+ bool IsCandidatePopupOpen() const override;
+
+ private:
+ // InputEventDispatcherDelegate interface implementation.
+ void DispatchEvent(ui::Event* event) override;
+
+ std::unique_ptr<InputMethodKeyboardControllerFuchsia>
+ virtual_keyboard_controller_;
+
+ DISALLOW_COPY_AND_ASSIGN(InputMethodFuchsia);
+};
+
+} // namespace ui
+
+#endif // UI_BASE_IME_INPUT_METHOD_FUCHSIA_H_
diff --git a/chromium/ui/base/ime/input_method_mac.mm b/chromium/ui/base/ime/input_method_mac.mm
index e42a251afe1..f23bce99cbc 100644
--- a/chromium/ui/base/ime/input_method_mac.mm
+++ b/chromium/ui/base/ime/input_method_mac.mm
@@ -6,6 +6,8 @@
#import <Cocoa/Cocoa.h>
+#include "base/bind_helpers.h"
+
namespace ui {
InputMethodMac::InputMethodMac(internal::InputMethodDelegate* delegate)
@@ -16,7 +18,7 @@ InputMethodMac::~InputMethodMac() {
ui::EventDispatchDetails InputMethodMac::DispatchKeyEvent(ui::KeyEvent* event) {
// This is used on Mac only to dispatch events post-IME.
- return DispatchKeyEventPostIME(event);
+ return DispatchKeyEventPostIME(event, base::NullCallback());
}
void InputMethodMac::OnCaretBoundsChanged(const TextInputClient* client) {
diff --git a/chromium/ui/base/ime/input_method_minimal.cc b/chromium/ui/base/ime/input_method_minimal.cc
index 98b1cd0fe2b..fb008796579 100644
--- a/chromium/ui/base/ime/input_method_minimal.cc
+++ b/chromium/ui/base/ime/input_method_minimal.cc
@@ -6,6 +6,7 @@
#include <stdint.h>
+#include "base/bind_helpers.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
@@ -23,10 +24,11 @@ ui::EventDispatchDetails InputMethodMinimal::DispatchKeyEvent(
// If no text input client, do nothing.
if (!GetTextInputClient())
- return DispatchKeyEventPostIME(event);
+ return DispatchKeyEventPostIME(event, base::NullCallback());
// Insert the character.
- ui::EventDispatchDetails dispatch_details = DispatchKeyEventPostIME(event);
+ ui::EventDispatchDetails dispatch_details =
+ DispatchKeyEventPostIME(event, base::NullCallback());
if (!event->stopped_propagation() && !dispatch_details.dispatcher_destroyed &&
event->type() == ET_KEY_PRESSED && GetTextInputClient()) {
const uint16_t ch = event->GetCharacter();
diff --git a/chromium/ui/base/ime/input_method_minimal_unittest.cc b/chromium/ui/base/ime/input_method_minimal_unittest.cc
index 2b9df961250..9eadb6ab1f7 100644
--- a/chromium/ui/base/ime/input_method_minimal_unittest.cc
+++ b/chromium/ui/base/ime/input_method_minimal_unittest.cc
@@ -21,9 +21,11 @@ class InputMethodDelegateForTesting : public internal::InputMethodDelegate {
~InputMethodDelegateForTesting() override {}
ui::EventDispatchDetails DispatchKeyEventPostIME(
- ui::KeyEvent* key_event) override {
+ ui::KeyEvent* key_event,
+ base::OnceCallback<void(bool)> ack_callback) override {
if (!propagation_post_ime_)
key_event->StopPropagation();
+ CallDispatchKeyEventPostIMEAck(key_event, std::move(ack_callback));
return ui::EventDispatchDetails();
}
diff --git a/chromium/ui/base/ime/input_method_win_base.cc b/chromium/ui/base/ime/input_method_win_base.cc
index 046f0d05268..333607e76ea 100644
--- a/chromium/ui/base/ime/input_method_win_base.cc
+++ b/chromium/ui/base/ime/input_method_win_base.cc
@@ -10,6 +10,7 @@
#include "base/auto_reset.h"
#include "base/bind.h"
+#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/memory/ptr_util.h"
#include "base/win/windows_version.h"
@@ -498,7 +499,8 @@ ui::EventDispatchDetails InputMethodWinBase::ProcessUnhandledKeyEvent(
ui::KeyEvent* event,
const std::vector<MSG>* char_msgs) {
DCHECK(event);
- ui::EventDispatchDetails details = DispatchKeyEventPostIME(event);
+ ui::EventDispatchDetails details =
+ DispatchKeyEventPostIME(event, base::NullCallback());
if (details.dispatcher_destroyed || details.target_destroyed ||
event->stopped_propagation()) {
return details;
diff --git a/chromium/ui/base/ime/input_method_win_imm32.cc b/chromium/ui/base/ime/input_method_win_imm32.cc
index 162cf77e59b..723408b20bb 100644
--- a/chromium/ui/base/ime/input_method_win_imm32.cc
+++ b/chromium/ui/base/ime/input_method_win_imm32.cc
@@ -89,6 +89,7 @@ bool InputMethodWinImm32::OnUntranslatedIMEMessage(
void InputMethodWinImm32::OnTextInputTypeChanged(
const TextInputClient* client) {
+ InputMethodBase::OnTextInputTypeChanged(client);
if (!IsTextInputClientFocused(client) || !IsWindowFocused(client))
return;
imm32_manager_.CancelIME(toplevel_window_handle_);
diff --git a/chromium/ui/base/ime/input_method_win_tsf.cc b/chromium/ui/base/ime/input_method_win_tsf.cc
index 5e723f12e56..0bc1842527e 100644
--- a/chromium/ui/base/ime/input_method_win_tsf.cc
+++ b/chromium/ui/base/ime/input_method_win_tsf.cc
@@ -79,6 +79,7 @@ bool InputMethodWinTSF::OnUntranslatedIMEMessage(
}
void InputMethodWinTSF::OnTextInputTypeChanged(const TextInputClient* client) {
+ InputMethodBase::OnTextInputTypeChanged(client);
if (!IsTextInputClientFocused(client) || !IsWindowFocused(client))
return;
ui::TSFBridge::GetInstance()->CancelComposition();
diff --git a/chromium/ui/base/ime/linux/BUILD.gn b/chromium/ui/base/ime/linux/BUILD.gn
new file mode 100644
index 00000000000..bdbc26b7df1
--- /dev/null
+++ b/chromium/ui/base/ime/linux/BUILD.gn
@@ -0,0 +1,29 @@
+# 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("//build/config/jumbo.gni")
+
+jumbo_component("linux") {
+ output_name = "ui_base_ime_linux"
+ sources = [
+ "fake_input_method_context.cc",
+ "fake_input_method_context.h",
+ "fake_input_method_context_factory.cc",
+ "fake_input_method_context_factory.h",
+ "linux_input_method_context.h",
+ "linux_input_method_context_factory.cc",
+ "linux_input_method_context_factory.h",
+ "ui_base_ime_linux_export.h",
+ ]
+
+ defines = [ "UI_BASE_IME_LINUX_IMPLEMENTATION" ]
+
+ deps = [
+ "//base",
+ ]
+
+ public_deps = [
+ "//ui/base/ime:ime_types",
+ ]
+}
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 5053aa1cbc4..c6c0479897d 100644
--- a/chromium/ui/base/ime/linux/fake_input_method_context.cc
+++ b/chromium/ui/base/ime/linux/fake_input_method_context.cc
@@ -27,4 +27,9 @@ void FakeInputMethodContext::Blur() {
void FakeInputMethodContext::SetCursorLocation(const gfx::Rect& rect) {
}
+void FakeInputMethodContext::SetSurroundingText(
+ const base::string16& 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 ec9ac7e445a..0fd8fdf548a 100644
--- a/chromium/ui/base/ime/linux/fake_input_method_context.h
+++ b/chromium/ui/base/ime/linux/fake_input_method_context.h
@@ -21,6 +21,8 @@ class FakeInputMethodContext : public LinuxInputMethodContext {
void Focus() override;
void Blur() override;
void SetCursorLocation(const gfx::Rect& rect) override;
+ void SetSurroundingText(const base::string16& text,
+ const gfx::Range& selection_range) override;
private:
DISALLOW_COPY_AND_ASSIGN(FakeInputMethodContext);
diff --git a/chromium/ui/base/ime/linux/fake_input_method_context_factory.h b/chromium/ui/base/ime/linux/fake_input_method_context_factory.h
index 4d57b96f79e..12bb7661b1e 100644
--- a/chromium/ui/base/ime/linux/fake_input_method_context_factory.h
+++ b/chromium/ui/base/ime/linux/fake_input_method_context_factory.h
@@ -12,7 +12,8 @@ namespace ui {
// An implementation of LinuxInputMethodContextFactory, which creates and
// returns FakeInputMethodContext's.
-class FakeInputMethodContextFactory : public LinuxInputMethodContextFactory {
+class UI_BASE_IME_LINUX_EXPORT FakeInputMethodContextFactory
+ : public LinuxInputMethodContextFactory {
public:
FakeInputMethodContextFactory();
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 4611501d062..ca80623fbb6 100644
--- a/chromium/ui/base/ime/linux/linux_input_method_context.h
+++ b/chromium/ui/base/ime/linux/linux_input_method_context.h
@@ -6,12 +6,13 @@
#define UI_BASE_IME_LINUX_LINUX_INPUT_METHOD_CONTEXT_H_
#include "base/strings/string16.h"
+#include "ui/base/ime/linux/ui_base_ime_linux_export.h"
#include "ui/base/ime/text_input_type.h"
-#include "ui/base/ime/ui_base_ime_export.h"
namespace gfx {
class Rect;
-}
+class Range;
+} // namespace gfx
namespace ui {
@@ -20,7 +21,7 @@ class KeyEvent;
// An interface of input method context for input method frameworks on
// GNU/Linux and likes.
-class UI_BASE_IME_EXPORT LinuxInputMethodContext {
+class UI_BASE_IME_LINUX_EXPORT LinuxInputMethodContext {
public:
virtual ~LinuxInputMethodContext() {}
@@ -33,6 +34,10 @@ class UI_BASE_IME_EXPORT LinuxInputMethodContext {
// client window rect.
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,
+ const gfx::Range& selection_range) = 0;
+
// Resets the context. A client needs to call OnTextInputTypeChanged() again
// before calling DispatchKeyEvent().
virtual void Reset() = 0;
@@ -45,13 +50,16 @@ class UI_BASE_IME_EXPORT LinuxInputMethodContext {
};
// An interface of callback functions called from LinuxInputMethodContext.
-class UI_BASE_IME_EXPORT LinuxInputMethodContextDelegate {
+class UI_BASE_IME_LINUX_EXPORT LinuxInputMethodContextDelegate {
public:
virtual ~LinuxInputMethodContextDelegate() {}
// Commits the |text| to the text input client.
virtual void OnCommit(const base::string16& text) = 0;
+ // Deletes the surrounding text at |index| for given |length|.
+ virtual void OnDeleteSurroundingText(int32_t index, uint32_t length) = 0;
+
// Sets the composition text to the text input client.
virtual void OnPreeditChanged(const CompositionText& composition_text) = 0;
diff --git a/chromium/ui/base/ime/linux/linux_input_method_context_factory.h b/chromium/ui/base/ime/linux/linux_input_method_context_factory.h
index 65d873a02ae..2429067d660 100644
--- a/chromium/ui/base/ime/linux/linux_input_method_context_factory.h
+++ b/chromium/ui/base/ime/linux/linux_input_method_context_factory.h
@@ -7,7 +7,7 @@
#include <memory>
-#include "ui/base/ime/ui_base_ime_export.h"
+#include "ui/base/ime/linux/ui_base_ime_linux_export.h"
namespace ui {
@@ -17,7 +17,7 @@ class LinuxInputMethodContextDelegate;
// An interface that lets different Linux platforms override the
// CreateInputMethodContext function declared here to return native input method
// contexts.
-class UI_BASE_IME_EXPORT LinuxInputMethodContextFactory {
+class UI_BASE_IME_LINUX_EXPORT LinuxInputMethodContextFactory {
public:
// Returns the current active factory or NULL.
static const LinuxInputMethodContextFactory* instance();
diff --git a/chromium/ui/base/ime/linux/ui_base_ime_linux_export.h b/chromium/ui/base/ime/linux/ui_base_ime_linux_export.h
new file mode 100644
index 00000000000..e59f303866b
--- /dev/null
+++ b/chromium/ui/base/ime/linux/ui_base_ime_linux_export.h
@@ -0,0 +1,34 @@
+// 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_BASE_IME_LINUX_UI_BASE_IME_LINUX_EXPORT_H_
+#define UI_BASE_IME_LINUX_UI_BASE_IME_LINUX_EXPORT_H_
+
+#if defined(COMPONENT_BUILD)
+
+#if defined(WIN32)
+
+#if defined(UI_BASE_IME_LINUX_IMPLEMENTATION)
+#define UI_BASE_IME_LINUX_EXPORT __declspec(dllexport)
+#else
+#define UI_BASE_IME_LINUX_EXPORT __declspec(dllimport)
+#endif
+
+#else // !defined(WIN32)
+
+#if defined(UI_BASE_IME_LINUX_IMPLEMENTATION)
+#define UI_BASE_IME_LINUX_EXPORT __attribute__((visibility("default")))
+#else
+#define UI_BASE_IME_LINUX_EXPORT
+#endif
+
+#endif
+
+#else // !defined(COMPONENT_BUILD)
+
+#define UI_BASE_IME_LINUX_EXPORT
+
+#endif
+
+#endif // UI_BASE_IME_LINUX_UI_BASE_IME_LINUX_EXPORT_H_
diff --git a/chromium/ui/base/ime/mock_input_method.cc b/chromium/ui/base/ime/mock_input_method.cc
index 09cde9c326b..04ff47bed46 100644
--- a/chromium/ui/base/ime/mock_input_method.cc
+++ b/chromium/ui/base/ime/mock_input_method.cc
@@ -3,8 +3,10 @@
// found in the LICENSE file.
#include "ui/base/ime/mock_input_method.h"
-#include "build/build_config.h"
+#include "base/bind_helpers.h"
+#include "base/callback.h"
+#include "build/build_config.h"
#include "ui/base/ime/input_method_delegate.h"
#include "ui/events/event.h"
@@ -43,7 +45,7 @@ TextInputClient* MockInputMethod::GetTextInputClient() const {
ui::EventDispatchDetails MockInputMethod::DispatchKeyEvent(
ui::KeyEvent* event) {
- return delegate_->DispatchKeyEventPostIME(event);
+ return delegate_->DispatchKeyEventPostIME(event, base::NullCallback());
}
void MockInputMethod::OnFocus() {
diff --git a/chromium/ui/base/ime/text_input_flags.h b/chromium/ui/base/ime/text_input_flags.h
index f2d7c49ec9d..ed3c851107b 100644
--- a/chromium/ui/base/ime/text_input_flags.h
+++ b/chromium/ui/base/ime/text_input_flags.h
@@ -8,7 +8,7 @@
namespace ui {
// Intentionally keep in sync with blink::WebTextInputFlags defined in:
-// third_party/WebKit/public/platform/WebTextInputType.h
+// third_party/blink/public/platform/web_text_input_type.h
enum TextInputFlags {
TEXT_INPUT_FLAG_NONE = 0,
TEXT_INPUT_FLAG_AUTOCOMPLETE_ON = 1 << 0,
diff --git a/chromium/ui/base/ime/ui_base_ime_types_export.h b/chromium/ui/base/ime/ui_base_ime_types_export.h
new file mode 100644
index 00000000000..354a8adc3f0
--- /dev/null
+++ b/chromium/ui/base/ime/ui_base_ime_types_export.h
@@ -0,0 +1,34 @@
+// 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_BASE_IME_UI_BASE_IME_TYPES_EXPORT_H_
+#define UI_BASE_IME_UI_BASE_IME_TYPES_EXPORT_H_
+
+#if defined(COMPONENT_BUILD)
+
+#if defined(WIN32)
+
+#if defined(UI_BASE_IME_TYPES_IMPLEMENTATION)
+#define UI_BASE_IME_TYPES_EXPORT __declspec(dllexport)
+#else
+#define UI_BASE_IME_TYPES_EXPORT __declspec(dllimport)
+#endif
+
+#else // !defined(WIN32)
+
+#if defined(UI_BASE_IME_TYPES_IMPLEMENTATION)
+#define UI_BASE_IME_TYPES_EXPORT __attribute__((visibility("default")))
+#else
+#define UI_BASE_IME_TYPES_EXPORT
+#endif
+
+#endif
+
+#else // !defined(COMPONENT_BUILD)
+
+#define UI_BASE_IME_TYPES_EXPORT
+
+#endif
+
+#endif // UI_BASE_IME_UI_BASE_IME_TYPES_EXPORT_H_
diff --git a/chromium/ui/base/l10n/l10n_util.cc b/chromium/ui/base/l10n/l10n_util.cc
index 265c80edd26..506c5c68781 100644
--- a/chromium/ui/base/l10n/l10n_util.cc
+++ b/chromium/ui/base/l10n/l10n_util.cc
@@ -268,15 +268,7 @@ bool IsLocaleAvailable(const std::string& locale) {
if (!l10n_util::IsLocaleSupportedByOS(locale))
return false;
- // If the ResourceBundle is not yet initialized, return false to avoid the
- // CHECK failure in ResourceBundle::GetSharedInstance().
- if (!ui::ResourceBundle::HasSharedInstance())
- return false;
-
- // TODO(hshi): make ResourceBundle::LocaleDataPakExists() a static function
- // so that this can be invoked without initializing the global instance.
- // See crbug.com/230432: CHECK failure in GetUserDataDir().
- return ui::ResourceBundle::GetSharedInstance().LocaleDataPakExists(locale);
+ return ui::ResourceBundle::LocaleDataPakExists(locale);
}
#endif
diff --git a/chromium/ui/base/l10n/l10n_util_win.cc b/chromium/ui/base/l10n/l10n_util_win.cc
index 8acfde020ee..8b3850c2441 100644
--- a/chromium/ui/base/l10n/l10n_util_win.cc
+++ b/chromium/ui/base/l10n/l10n_util_win.cc
@@ -4,7 +4,6 @@
#include "ui/base/l10n/l10n_util_win.h"
-#include <windowsx.h>
#include <algorithm>
#include <iterator>
@@ -22,30 +21,6 @@
namespace {
-void AdjustLogFont(const base::string16& font_family,
- double font_size_scaler,
- double dpi_scale,
- LOGFONT* logfont) {
- DCHECK(font_size_scaler > 0);
- font_size_scaler = std::max(std::min(font_size_scaler, 2.0), 0.7);
- // Font metrics are computed in pixels and scale in high-DPI mode.
- // Normalized by the DPI scale factor in order to work in DIP with
- // Views/Aura. Call with dpi_scale=1 to keep the size in pixels.
- font_size_scaler /= dpi_scale;
- logfont->lfHeight = static_cast<long>(font_size_scaler *
- static_cast<double>(abs(logfont->lfHeight)) + 0.5) *
- (logfont->lfHeight > 0 ? 1 : -1);
-
- // TODO(jungshik): We may want to check the existence of the font.
- // If it's not installed, we shouldn't adjust the font.
- if (font_family != L"default") {
- int name_len = std::min(static_cast<int>(font_family.size()),
- LF_FACESIZE -1);
- memcpy(logfont->lfFaceName, font_family.data(), name_len * sizeof(WORD));
- logfont->lfFaceName[name_len] = 0;
- }
-}
-
class OverrideLocaleHolder {
public:
OverrideLocaleHolder() {}
@@ -113,44 +88,14 @@ bool NeedOverrideDefaultUIFont(base::string16* override_font_family,
if ((ui_font_family == L"default" && scaler100 == 100) ||
ui_font_family.empty())
return false;
- if (override_font_family && font_size_scaler) {
+
+ if (override_font_family && ui_font_family != L"default")
override_font_family->swap(ui_font_family);
+ if (font_size_scaler)
*font_size_scaler = scaler100 / 100.0;
- }
return true;
}
-void AdjustUIFont(LOGFONT* logfont) {
- // Use the unforced scale so the font will be normalized to the correct DIP
- // value. That way it'll appear the right size when the forced scale is
- // applied later (when coverting to pixels).
- AdjustUIFontForDIP(display::win::ScreenWin::GetSystemScaleFactor(), logfont);
-}
-
-void AdjustUIFontForDIP(float dpi_scale, LOGFONT* logfont) {
- base::string16 ui_font_family = L"default";
- double ui_font_size_scaler = 1;
- if (NeedOverrideDefaultUIFont(&ui_font_family, &ui_font_size_scaler) ||
- dpi_scale != 1) {
- AdjustLogFont(ui_font_family, ui_font_size_scaler, dpi_scale, logfont);
- }
-}
-
-void AdjustUIFontForWindow(HWND hwnd) {
- base::string16 ui_font_family;
- double ui_font_size_scaler;
- if (NeedOverrideDefaultUIFont(&ui_font_family, &ui_font_size_scaler)) {
- LOGFONT logfont;
- if (GetObject(GetWindowFont(hwnd), sizeof(logfont), &logfont)) {
- double dpi_scale = 1;
- AdjustLogFont(ui_font_family, ui_font_size_scaler, dpi_scale, &logfont);
- HFONT hfont = CreateFontIndirect(&logfont);
- if (hfont)
- SetWindowFont(hwnd, hfont, FALSE);
- }
- }
-}
-
void OverrideLocaleWithUILanguageList() {
std::vector<base::string16> ui_languages;
if (base::win::i18n::GetThreadPreferredUILanguageList(&ui_languages)) {
diff --git a/chromium/ui/base/l10n/l10n_util_win.h b/chromium/ui/base/l10n/l10n_util_win.h
index 75bfe5db03a..a245ec91764 100644
--- a/chromium/ui/base/l10n/l10n_util_win.h
+++ b/chromium/ui/base/l10n/l10n_util_win.h
@@ -44,25 +44,6 @@ UI_BASE_EXPORT bool NeedOverrideDefaultUIFont(
base::string16* override_font_family,
double* font_size_scaler);
-// If the default UI font stored in |logfont| is not suitable, its family
-// and size are replaced with those stored in the per-locale resource. The
-// font size is adjusted based on the font scale setting in the OS preferences.
-// Windows 8 supports scale factors of 1, 1.4 and 1.8.
-UI_BASE_EXPORT void AdjustUIFont(LOGFONT* logfont);
-
-// If the default UI font stored in |logfont| is not suitable, its family
-// and size are replaced with those stored in the per-locale resource. The
-// |dpi_scale| is the ratio of the OS setting for dots per inch relative to the
-// baseline of 96 DPI. This ratio is also used for converting sizes from
-// device independent pixels (DIP) to physical pixels. The font size is scaled
-// for use with Views and Aura which work in DIP.
-UI_BASE_EXPORT void AdjustUIFontForDIP(float dpi_scale, LOGFONT* logfont);
-
-// If the font for a given window (pointed to by HWND) is not suitable for the
-// UI in the current UI langauge, its family and size are replaced with those
-// stored in the per-locale resource.
-UI_BASE_EXPORT void AdjustUIFontForWindow(HWND hwnd);
-
// Allow processes to override the configured locale with the user's Windows UI
// languages. This function should generally be called once early in
// Application startup.
@@ -70,7 +51,7 @@ UI_BASE_EXPORT void OverrideLocaleWithUILanguageList();
// Retrieve the locale override, or an empty vector if the locale has not been
// or failed to be overridden.
-const std::vector<std::string>& GetLocaleOverrides();
+UI_BASE_EXPORT const std::vector<std::string>& GetLocaleOverrides();
} // namespace l10n_util
diff --git a/chromium/ui/base/l10n/l10n_util_win_unittest.cc b/chromium/ui/base/l10n/l10n_util_win_unittest.cc
deleted file mode 100644
index 3dfa8533722..00000000000
--- a/chromium/ui/base/l10n/l10n_util_win_unittest.cc
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/base/l10n/l10n_util_win.h"
-
-#include <windows.h>
-
-#include "base/command_line.h"
-#include "base/win/win_client_metrics.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "testing/platform_test.h"
-#include "ui/display/display.h"
-#include "ui/display/display_switches.h"
-#include "ui/display/win/screen_win.h"
-
-typedef PlatformTest L10nUtilWinTest;
-
-TEST_F(L10nUtilWinTest, TestDPIScaling) {
- // Baseline font for comparison.
- NONCLIENTMETRICS_XP metrics;
- base::win::GetNonClientMetrics(&metrics);
- LOGFONT lf = metrics.lfMessageFont;
- l10n_util::AdjustUIFont(&lf);
- int size = lf.lfHeight;
- float rounding = size < 0 ? -0.5f : 0.5f;
-
- // Test that font size is properly normalized for DIP. In high-DPI mode, the
- // font metrics are scaled based on the DPI scale factor. For Windows 8, 140%
- // and 180% font scaling are supported. Simulate size normalization for a DPI-
- // aware process by manually scaling up the font and checking that it returns
- // to the expected size.
- lf.lfHeight = static_cast<int>(1.4 * size + rounding);
- l10n_util::AdjustUIFontForDIP(1.4f, &lf);
- EXPECT_NEAR(size, lf.lfHeight, 1);
-
- lf.lfHeight = static_cast<int>(1.8 * size + rounding);
- l10n_util::AdjustUIFontForDIP(1.8f, &lf);
- EXPECT_NEAR(size, lf.lfHeight, 1);
-}
-
-// Test for crbug.com/675933. Since font size is a Windows metric we need to
-// normalize to DIPs based on the real device scale factor, not the forced one.
-TEST_F(L10nUtilWinTest, TestForcedScaling) {
- base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
- switches::kForceDeviceScaleFactor, "4");
- display::Display::ResetForceDeviceScaleFactorForTesting();
-
- NONCLIENTMETRICS_XP metrics;
- base::win::GetNonClientMetrics(&metrics);
- LOGFONT lf = metrics.lfMessageFont;
-
- // Set the font size to an arbitrary value and make sure it comes through
- // correctly on the other end.
- constexpr int test_font_size = 18;
- lf.lfHeight = test_font_size;
- l10n_util::AdjustUIFont(&lf);
- EXPECT_EQ(test_font_size / display::win::ScreenWin::GetSystemScaleFactor(),
- lf.lfHeight);
-}
diff --git a/chromium/ui/base/material_design/material_design_controller.cc b/chromium/ui/base/material_design/material_design_controller.cc
index caf62d06d79..d23a4df67be 100644
--- a/chromium/ui/base/material_design/material_design_controller.cc
+++ b/chromium/ui/base/material_design/material_design_controller.cc
@@ -9,10 +9,13 @@
#include "base/command_line.h"
#include "base/feature_list.h"
#include "base/logging.h"
+#include "base/no_destructor.h"
+#include "base/observer_list.h"
#include "base/strings/string_number_conversions.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "build/buildflag.h"
+#include "ui/base/material_design/material_design_controller_observer.h"
#include "ui/base/ui_base_features.h"
#include "ui/base/ui_base_switches.h"
#include "ui/base/ui_features.h"
@@ -39,19 +42,6 @@
namespace ui {
namespace {
-#if defined(OS_CHROMEOS) || defined(OS_WIN) || defined(OS_LINUX)
-
-// Whether Material Refresh should be used by default.
-// Material refresh is controlled by both --top-chrome-md and this feature.
-// --top-chrome-md should take precedence over what this feature may indicate.
-bool IsMaterialRefreshEnabled() {
- static constexpr base::Feature kMaterialRefreshEnabledFeature = {
- "MaterialRefresh", base::FEATURE_ENABLED_BY_DEFAULT};
- return base::FeatureList::IsEnabled(kMaterialRefreshEnabledFeature);
-}
-
-#endif
-
#if defined(OS_CHROMEOS)
// Whether to use touchable UI.
@@ -60,18 +50,11 @@ const base::Feature kTouchOptimizedUi = {"TouchOptimizedUi",
base::FEATURE_DISABLED_BY_DEFAULT};
MaterialDesignController::Mode GetDefaultTouchDeviceMode() {
- bool material_refresh_enabled = IsMaterialRefreshEnabled();
bool touch_optimized_ui_enabled =
base::FeatureList::IsEnabled(kTouchOptimizedUi);
- if (material_refresh_enabled) {
- return touch_optimized_ui_enabled
- ? MaterialDesignController::MATERIAL_TOUCH_REFRESH
- : MaterialDesignController::MATERIAL_REFRESH;
- }
-
return touch_optimized_ui_enabled
- ? MaterialDesignController::MATERIAL_TOUCH_OPTIMIZED
- : MaterialDesignController::MATERIAL_HYBRID;
+ ? MaterialDesignController::MATERIAL_TOUCH_REFRESH
+ : MaterialDesignController::MATERIAL_REFRESH;
}
bool HasTouchscreen() {
@@ -107,45 +90,27 @@ bool MaterialDesignController::is_mode_initialized_ = false;
MaterialDesignController::Mode MaterialDesignController::mode_ =
MaterialDesignController::MATERIAL_NORMAL;
+bool MaterialDesignController::is_refresh_dynamic_ui_ = false;
+
// static
void MaterialDesignController::Initialize() {
TRACE_EVENT0("startup", "MaterialDesignController::InitializeMode");
CHECK(!is_mode_initialized_);
+
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
const std::string switch_value =
command_line->GetSwitchValueASCII(switches::kTopChromeMD);
- bool force_material_refresh = false;
-#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_LINUX)
- force_material_refresh =
- base::FeatureList::IsEnabled(features::kExperimentalUi);
-#endif
-
if (switch_value == switches::kTopChromeMDMaterialRefresh) {
SetMode(MATERIAL_REFRESH);
} else if (switch_value ==
switches::kTopChromeMDMaterialRefreshTouchOptimized) {
SetMode(MATERIAL_TOUCH_REFRESH);
- } else if (force_material_refresh) {
- bool has_touchscreen = false;
-#if defined(OS_CHROMEOS)
- has_touchscreen = HasTouchscreen();
-#endif
- SetMode(has_touchscreen ? MATERIAL_TOUCH_REFRESH : MATERIAL_REFRESH);
- } else if (switch_value == switches::kTopChromeMDMaterial) {
- SetMode(MATERIAL_NORMAL);
- } else if (switch_value == switches::kTopChromeMDMaterialHybrid) {
- SetMode(MATERIAL_HYBRID);
- } else if (switch_value == switches::kTopChromeMDMaterialTouchOptimized) {
- SetMode(MATERIAL_TOUCH_OPTIMIZED);
- } else if (switch_value == switches::kTopChromeMDMaterialAuto) {
-#if defined(OS_WIN)
- // TODO(girard): add support for switching between modes when
- // the device switches to "tablet mode".
- if (base::win::IsTabletDevice(nullptr, ui::GetHiddenWindow()))
- SetMode(MATERIAL_HYBRID);
-#endif
- SetMode(DefaultMode());
+ } else if (switch_value == switches::kTopChromeMDMaterialRefreshDynamic) {
+ is_refresh_dynamic_ui_ = true;
+
+ // TabletModeClient's default state is in non-tablet mode.
+ SetMode(MATERIAL_REFRESH);
} else {
if (!switch_value.empty()) {
LOG(ERROR) << "Invalid value='" << switch_value
@@ -158,8 +123,7 @@ void MaterialDesignController::Initialize() {
// Ideally, there would be a more general, "initialize random stuff here"
// function into which these things and a call to this function can be placed.
// TODO(crbug.com/864544)
- if (IsRefreshUi())
- color_utils::SetDarkestColor(gfx::kGoogleGrey900);
+ color_utils::SetDarkestColor(gfx::kGoogleGrey900);
double animation_duration_scale;
if (base::StringToDouble(
@@ -182,16 +146,6 @@ bool MaterialDesignController::IsTouchOptimizedUiEnabled() {
}
// static
-bool MaterialDesignController::IsNewerMaterialUi() {
- return IsTouchOptimizedUiEnabled() || IsRefreshUi();
-}
-
-// static
-bool MaterialDesignController::IsRefreshUi() {
- return GetMode() == MATERIAL_REFRESH || GetMode() == MATERIAL_TOUCH_REFRESH;
-}
-
-// static
MaterialDesignController::Mode MaterialDesignController::DefaultMode() {
#if defined(OS_CHROMEOS)
// This is called (once) early in device startup to initialize core UI, so
@@ -199,28 +153,48 @@ MaterialDesignController::Mode MaterialDesignController::DefaultMode() {
base::ScopedAllowBlocking allow_io;
if (HasTouchscreen())
return GetDefaultTouchDeviceMode();
-
- return IsMaterialRefreshEnabled() ? MATERIAL_REFRESH : MATERIAL_NORMAL;
#endif // defined(OS_CHROMEOS)
-#if defined(OS_WIN) || defined(OS_LINUX)
- return IsMaterialRefreshEnabled() ? MATERIAL_REFRESH : MATERIAL_NORMAL;
-#elif defined(OS_MACOSX) && BUILDFLAG(MAC_VIEWS_BROWSER)
- return features::IsViewsBrowserCocoa() ? MATERIAL_NORMAL : MATERIAL_REFRESH;
-#else
- return MATERIAL_NORMAL;
-#endif
+ return MATERIAL_REFRESH;
+}
+
+// static
+void MaterialDesignController::OnTabletModeToggled(bool enabled) {
+ if (is_refresh_dynamic_ui_)
+ SetMode(enabled ? MATERIAL_TOUCH_REFRESH : MATERIAL_REFRESH);
}
// static
+MaterialDesignController* MaterialDesignController::GetInstance() {
+ static base::NoDestructor<MaterialDesignController> instance;
+ return instance.get();
+}
+
+void MaterialDesignController::AddObserver(
+ MaterialDesignControllerObserver* observer) {
+ observers_.AddObserver(observer);
+}
+
+void MaterialDesignController::RemoveObserver(
+ MaterialDesignControllerObserver* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+MaterialDesignController::MaterialDesignController() = default;
+
+// static
void MaterialDesignController::Uninitialize() {
is_mode_initialized_ = false;
}
// static
void MaterialDesignController::SetMode(MaterialDesignController::Mode mode) {
- mode_ = mode;
- is_mode_initialized_ = true;
+ if (!is_mode_initialized_ || mode_ != mode) {
+ is_mode_initialized_ = true;
+ mode_ = mode;
+ for (auto& observer : GetInstance()->observers_)
+ observer.OnMdModeChanged();
+ }
}
} // namespace ui
diff --git a/chromium/ui/base/material_design/material_design_controller.h b/chromium/ui/base/material_design/material_design_controller.h
index 4605134569e..d66f2624b43 100644
--- a/chromium/ui/base/material_design/material_design_controller.h
+++ b/chromium/ui/base/material_design/material_design_controller.h
@@ -6,10 +6,18 @@
#define UI_BASE_MATERIAL_DESIGN_MATERIAL_DESIGN_CONTROLLER_H_
#include "base/macros.h"
+#include "base/observer_list.h"
#include "ui/base/ui_base_export.h"
+namespace base {
+template <typename T>
+class NoDestructor;
+}
+
namespace ui {
+class MaterialDesignControllerObserver;
+
namespace test {
class MaterialDesignControllerTestAPI;
} // namespace test
@@ -41,31 +49,27 @@ class UI_BASE_EXPORT MaterialDesignController {
// Returns true if the touch-optimized UI material design mode is enabled.
static bool IsTouchOptimizedUiEnabled();
- // Returns true if the Material Refresh or touch-optimized UI is enabled.
- static bool IsNewerMaterialUi();
-
- // Returns true if any Material Refresh mode is enabled.
- static bool IsRefreshUi();
-
// Returns the per-platform default material design variant.
static Mode DefaultMode();
+ // Exposed for TabletModeClient on ChromeOS + ash.
+ static void OnTabletModeToggled(bool enabled);
+
static bool is_mode_initialized() { return is_mode_initialized_; }
- private:
- friend class test::MaterialDesignControllerTestAPI;
+ static MaterialDesignController* GetInstance();
- // Tracks whether |mode_| has been initialized. This is necessary to avoid
- // checking the |mode_| early in initialization before a call to Initialize().
- // Tests can use it to reset the state back to a clean state during tear down.
- static bool is_mode_initialized_;
+ void AddObserver(MaterialDesignControllerObserver* observer);
- // The current Mode to be used by the system.
- static Mode mode_;
+ void RemoveObserver(MaterialDesignControllerObserver* observer);
+
+ private:
+ friend class base::NoDestructor<MaterialDesignController>;
+ friend class test::MaterialDesignControllerTestAPI;
- // Declarations only. Do not allow construction of an object.
MaterialDesignController();
- ~MaterialDesignController();
+
+ ~MaterialDesignController() = delete;
// Resets the initialization state to uninitialized. To be used by tests to
// allow calling Initialize() more than once.
@@ -75,6 +79,20 @@ class UI_BASE_EXPORT MaterialDesignController {
// used by tests to directly set the mode.
static void SetMode(Mode mode);
+ // Tracks whether |mode_| has been initialized. This is necessary to avoid
+ // checking the |mode_| early in initialization before a call to Initialize().
+ // Tests can use it to reset the state back to a clean state during tear down.
+ static bool is_mode_initialized_;
+
+ // The current Mode to be used by the system.
+ static Mode mode_;
+
+ // Whether |mode_| should toggle between MATERIAL_REFRESH and
+ // MATERIAL_TOUCH_REFRESH depending on the tablet state.
+ static bool is_refresh_dynamic_ui_;
+
+ base::ObserverList<MaterialDesignControllerObserver> observers_;
+
DISALLOW_COPY_AND_ASSIGN(MaterialDesignController);
};
diff --git a/chromium/ui/base/material_design/material_design_controller_observer.h b/chromium/ui/base/material_design/material_design_controller_observer.h
new file mode 100644
index 00000000000..5b7eba4bbc5
--- /dev/null
+++ b/chromium/ui/base/material_design/material_design_controller_observer.h
@@ -0,0 +1,24 @@
+// 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_BASE_MATERIAL_DESIGN_MATERIAL_DESIGN_CONTROLLER_OBSERVER_H_
+#define UI_BASE_MATERIAL_DESIGN_MATERIAL_DESIGN_CONTROLLER_OBSERVER_H_
+
+#include "base/observer_list_types.h"
+#include "ui/base/ui_base_export.h"
+
+namespace ui {
+
+class UI_BASE_EXPORT MaterialDesignControllerObserver
+ : public base::CheckedObserver {
+ public:
+ virtual void OnMdModeChanged() = 0;
+
+ protected:
+ ~MaterialDesignControllerObserver() override {}
+};
+
+} // namespace ui
+
+#endif // UI_BASE_MATERIAL_DESIGN_MATERIAL_DESIGN_CONTROLLER_OBSERVER_H_
diff --git a/chromium/ui/base/material_design/material_design_controller_unittest.cc b/chromium/ui/base/material_design/material_design_controller_unittest.cc
index 6da42af5445..c5a9075033f 100644
--- a/chromium/ui/base/material_design/material_design_controller_unittest.cc
+++ b/chromium/ui/base/material_design/material_design_controller_unittest.cc
@@ -6,137 +6,180 @@
#include "base/command_line.h"
#include "base/macros.h"
+#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/base/material_design/material_design_controller.h"
+#include "ui/base/material_design/material_design_controller_observer.h"
#include "ui/base/test/material_design_controller_test_api.h"
#include "ui/base/ui_base_switches.h"
namespace ui {
+
+TEST(MaterialDesignControllerDeathTest, CrashesWithoutInitialization) {
+ ASSERT_FALSE(MaterialDesignController::is_mode_initialized());
+ EXPECT_DEATH_IF_SUPPORTED(
+ MaterialDesignController::IsTouchOptimizedUiEnabled(), "");
+}
+
namespace {
// Test fixture for the MaterialDesignController class.
class MaterialDesignControllerTest : public testing::Test {
public:
- MaterialDesignControllerTest();
- ~MaterialDesignControllerTest() override;
+ MaterialDesignControllerTest() = default;
+ ~MaterialDesignControllerTest() override = default;
protected:
// testing::Test:
- void SetUp() override;
- void TearDown() override;
- void SetCommandLineSwitch(const std::string& value_string);
+ void SetUp() override {
+ testing::Test::SetUp();
+ MaterialDesignController::Initialize();
+ }
+
+ void TearDown() override {
+ test::MaterialDesignControllerTestAPI::Uninitialize();
+ testing::Test::TearDown();
+ }
+
+ void SetCommandLineSwitch(const std::string& value_string) {
+ base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
+ switches::kTopChromeMD, value_string);
+ }
private:
DISALLOW_COPY_AND_ASSIGN(MaterialDesignControllerTest);
};
-MaterialDesignControllerTest::MaterialDesignControllerTest() {
-}
-
-MaterialDesignControllerTest::~MaterialDesignControllerTest() {
-}
-
-void MaterialDesignControllerTest::SetUp() {
- testing::Test::SetUp();
- MaterialDesignController::Initialize();
-}
+} // namespace
-void MaterialDesignControllerTest::TearDown() {
- test::MaterialDesignControllerTestAPI::Uninitialize();
- testing::Test::TearDown();
+#if !defined(OS_CHROMEOS)
+// Verify that non-touch is the default.
+TEST_F(MaterialDesignControllerTest, NoCommandLineFlagIsRefresh) {
+ ASSERT_FALSE(base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kTopChromeMD));
+ EXPECT_FALSE(MaterialDesignController::IsTouchOptimizedUiEnabled());
}
+#endif
-void MaterialDesignControllerTest::SetCommandLineSwitch(
- const std::string& value_string) {
- base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
- switches::kTopChromeMD, value_string);
-}
+namespace {
-class MaterialDesignControllerTestMaterial :
- public MaterialDesignControllerTest {
+class MaterialDesignControllerTestCommandLineRefresh
+ : public MaterialDesignControllerTest {
public:
- MaterialDesignControllerTestMaterial() {
- SetCommandLineSwitch("material");
+ MaterialDesignControllerTestCommandLineRefresh() {
+ SetCommandLineSwitch(switches::kTopChromeMDMaterialRefresh);
}
private:
- DISALLOW_COPY_AND_ASSIGN(MaterialDesignControllerTestMaterial);
+ DISALLOW_COPY_AND_ASSIGN(MaterialDesignControllerTestCommandLineRefresh);
};
-class MaterialDesignControllerTestHybrid : public MaterialDesignControllerTest {
- public:
- MaterialDesignControllerTestHybrid() {
- SetCommandLineSwitch("material-hybrid");
- }
+} // namespace
- private:
- DISALLOW_COPY_AND_ASSIGN(MaterialDesignControllerTestHybrid);
-};
+// Verify switches::kTopChromeMDMaterialRefresh maps to non-touch (the default).
+TEST_F(MaterialDesignControllerTestCommandLineRefresh, CheckApiReturns) {
+ EXPECT_FALSE(MaterialDesignController::IsTouchOptimizedUiEnabled());
+}
+
+namespace {
-class MaterialDesignControllerTestDefault :
- public MaterialDesignControllerTest {
+class MaterialDesignControllerTestCommandLineForceTouchRefresh
+ : public MaterialDesignControllerTest {
public:
- MaterialDesignControllerTestDefault() {
- SetCommandLineSwitch(std::string());
+ MaterialDesignControllerTestCommandLineForceTouchRefresh() {
+ SetCommandLineSwitch(switches::kTopChromeMDMaterialRefreshTouchOptimized);
}
private:
- DISALLOW_COPY_AND_ASSIGN(MaterialDesignControllerTestDefault);
+ DISALLOW_COPY_AND_ASSIGN(
+ MaterialDesignControllerTestCommandLineForceTouchRefresh);
};
-class MaterialDesignControllerTestInvalid :
- public MaterialDesignControllerTest {
+} // namespace
+
+// Verify switches::kTopChromeMDMaterialRefreshTouchOptimized maps to touch.
+TEST_F(MaterialDesignControllerTestCommandLineForceTouchRefresh,
+ CheckApiReturns) {
+ EXPECT_TRUE(MaterialDesignController::IsTouchOptimizedUiEnabled());
+}
+
+namespace {
+
+class TestObserver : public ui::MaterialDesignControllerObserver {
public:
- MaterialDesignControllerTestInvalid() {
- const std::string kInvalidValue = "1nvalid-valu3";
- SetCommandLineSwitch(kInvalidValue);
- }
+ TestObserver() = default;
+ ~TestObserver() override = default;
+
+ bool on_md_mode_changed_called() { return on_md_mode_changed_called_; }
private:
- DISALLOW_COPY_AND_ASSIGN(MaterialDesignControllerTestInvalid);
+ // ui::MaterialDesignControllerObserver:
+ void OnMdModeChanged() override { on_md_mode_changed_called_ = true; }
+
+ bool on_md_mode_changed_called_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(TestObserver);
};
-// Verify command line value "material" maps to Mode::MATERIAL when the compile
-// time flag is defined.
-TEST_F(MaterialDesignControllerTestMaterial,
- EnabledCommandLineValueMapsToMaterialModeWhenCompileTimeFlagEnabled) {
- EXPECT_EQ(MaterialDesignController::Mode::MATERIAL_NORMAL,
- MaterialDesignController::GetMode());
-}
+} // namespace
-// Verify command line value "material-hybrid" maps to Mode::MATERIAL_HYBRID
-// when the compile time flag is defined.
-TEST_F(
- MaterialDesignControllerTestHybrid,
- EnabledHybridCommandLineValueMapsToMaterialHybridModeWhenCompileTimeFlagEnabled) {
- EXPECT_EQ(MaterialDesignController::Mode::MATERIAL_HYBRID,
- MaterialDesignController::GetMode());
-}
+TEST(MaterialDesignControllerObserver, InitializationOnMdModeChanged) {
+ // Verifies that the MaterialDesignControllerObserver gets called back when
+ // the mode changes at startup.
+ TestObserver observer;
+ ASSERT_FALSE(observer.on_md_mode_changed_called());
+ MaterialDesignController::GetInstance()->AddObserver(&observer);
-// Verify command line value "" maps to the default mode when the compile time
-// flag is defined.
-TEST_F(
- MaterialDesignControllerTestDefault,
- DisabledCommandLineValueMapsToNonMaterialModeWhenCompileTimeFlagEnabled) {
- EXPECT_EQ(MaterialDesignController::DefaultMode(),
- MaterialDesignController::GetMode());
-}
+ // Trigger a mode change by setting it for the first time.
+ MaterialDesignController::Initialize();
-// Verify the current mode is reported as the default mode when no command line
-// flag is defined.
-TEST_F(MaterialDesignControllerTest,
- NoCommandLineValueMapsToNonMaterialModeWhenCompileTimeFlagEnabled) {
- ASSERT_FALSE(base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kTopChromeMD));
- EXPECT_EQ(MaterialDesignController::DefaultMode(),
- MaterialDesignController::GetMode());
+ EXPECT_TRUE(observer.on_md_mode_changed_called());
+
+ test::MaterialDesignControllerTestAPI::Uninitialize();
+ MaterialDesignController::GetInstance()->RemoveObserver(&observer);
}
-// Verify an invalid command line value uses the default mode.
-TEST_F(MaterialDesignControllerTestInvalid, InvalidCommandLineValue) {
- EXPECT_EQ(MaterialDesignController::DefaultMode(),
- MaterialDesignController::GetMode());
+TEST(MaterialDesignControllerObserver, TabletOnMdModeChanged) {
+ // Verifies that the MaterialDesignControllerObserver gets called back when
+ // the tablet mode toggles.
+ test::MaterialDesignControllerTestAPI::SetDynamicRefreshUi(true);
+
+ MaterialDesignController::Initialize();
+ TestObserver tablet_enabled_observer;
+ MaterialDesignController::GetInstance()->AddObserver(
+ &tablet_enabled_observer);
+ ASSERT_FALSE(tablet_enabled_observer.on_md_mode_changed_called());
+
+#if !defined(OS_CHROMEOS)
+ EXPECT_FALSE(MaterialDesignController::IsTouchOptimizedUiEnabled());
+#endif
+
+ MaterialDesignController::OnTabletModeToggled(true);
+
+ EXPECT_TRUE(MaterialDesignController::IsTouchOptimizedUiEnabled());
+
+ EXPECT_TRUE(tablet_enabled_observer.on_md_mode_changed_called());
+
+ TestObserver tablet_disabled_observer;
+ MaterialDesignController::GetInstance()->AddObserver(
+ &tablet_disabled_observer);
+ ASSERT_FALSE(tablet_disabled_observer.on_md_mode_changed_called());
+
+ MaterialDesignController::OnTabletModeToggled(false);
+
+#if !defined(OS_CHROMEOS)
+ EXPECT_FALSE(MaterialDesignController::IsTouchOptimizedUiEnabled());
+#endif
+
+ EXPECT_TRUE(tablet_disabled_observer.on_md_mode_changed_called());
+
+ test::MaterialDesignControllerTestAPI::Uninitialize();
+ MaterialDesignController::GetInstance()->RemoveObserver(
+ &tablet_disabled_observer);
+ MaterialDesignController::GetInstance()->RemoveObserver(
+ &tablet_enabled_observer);
+
+ test::MaterialDesignControllerTestAPI::SetDynamicRefreshUi(false);
}
-} // namespace
} // namespace ui
diff --git a/chromium/ui/base/models/list_selection_model.cc b/chromium/ui/base/models/list_selection_model.cc
index 1456c0f4f01..d8e23ba1340 100644
--- a/chromium/ui/base/models/list_selection_model.cc
+++ b/chromium/ui/base/models/list_selection_model.cc
@@ -76,8 +76,7 @@ bool ListSelectionModel::operator!=(const ListSelectionModel& other) const {
void ListSelectionModel::IncrementFrom(int index) {
// Shift the selection to account for a newly inserted item at |index|.
- for (SelectedIndices::iterator i = selected_indices_.begin();
- i != selected_indices_.end(); ++i) {
+ for (auto i = selected_indices_.begin(); i != selected_indices_.end(); ++i) {
IncrementFromImpl(index, &(*i));
}
IncrementFromImpl(index, &anchor_);
@@ -85,8 +84,7 @@ void ListSelectionModel::IncrementFrom(int index) {
}
void ListSelectionModel::DecrementFrom(int index) {
- for (SelectedIndices::iterator i = selected_indices_.begin();
- i != selected_indices_.end(); ) {
+ for (auto i = selected_indices_.begin(); i != selected_indices_.end();) {
if (DecrementFromImpl(index, &(*i)))
i = selected_indices_.erase(i);
else
@@ -115,8 +113,7 @@ void ListSelectionModel::AddIndexToSelection(int index) {
}
void ListSelectionModel::RemoveIndexFromSelection(int index) {
- SelectedIndices::iterator i = std::find(selected_indices_.begin(),
- selected_indices_.end(), index);
+ auto i = std::find(selected_indices_.begin(), selected_indices_.end(), index);
if (i != selected_indices_.end())
selected_indices_.erase(i);
}
diff --git a/chromium/ui/base/models/simple_menu_model.cc b/chromium/ui/base/models/simple_menu_model.cc
index 65435087568..5561c413a29 100644
--- a/chromium/ui/base/models/simple_menu_model.cc
+++ b/chromium/ui/base/models/simple_menu_model.cc
@@ -295,7 +295,7 @@ void SimpleMenuModel::Clear() {
}
int SimpleMenuModel::GetIndexOfCommandId(int command_id) const {
- for (ItemVector::const_iterator i = items_.begin(); i != items_.end(); ++i) {
+ for (auto i = items_.begin(); i != items_.end(); ++i) {
if (i->command_id == command_id)
return static_cast<int>(std::distance(items_.begin(), i));
}
@@ -306,7 +306,7 @@ int SimpleMenuModel::GetIndexOfCommandId(int command_id) const {
// SimpleMenuModel, MenuModel implementation:
bool SimpleMenuModel::HasIcons() const {
- for (ItemVector::const_iterator i = items_.begin(); i != items_.end(); ++i) {
+ for (auto i = items_.begin(); i != items_.end(); ++i) {
if (!i->icon.IsEmpty())
return true;
}
diff --git a/chromium/ui/base/mojo/clipboard_host.h b/chromium/ui/base/mojo/clipboard_host.h
index bab35e05ed9..b36e591e82a 100644
--- a/chromium/ui/base/mojo/clipboard_host.h
+++ b/chromium/ui/base/mojo/clipboard_host.h
@@ -58,7 +58,7 @@ class ClipboardHost : public mojom::ClipboardHost {
void WriteBitmap(const SkBitmap& bitmap) override;
void WriteData(const std::string& type, const std::string& data) override;
void CommitWrite(ClipboardType type) override;
-#if defined(OS_MACOSX)
+#if defined(OS_MACOSX) && !defined(OS_IOS)
void WriteStringToFindPboard(const base::string16& text) override;
#endif
diff --git a/chromium/ui/base/mojo/ui_base_types.mojom b/chromium/ui/base/mojo/ui_base_types.mojom
index e2b12c00164..82bc476b639 100644
--- a/chromium/ui/base/mojo/ui_base_types.mojom
+++ b/chromium/ui/base/mojo/ui_base_types.mojom
@@ -4,6 +4,13 @@
module ui.mojom;
+// Dialog button identifiers used to specify which buttons to show the user.
+enum DialogButton {
+ NONE,
+ OK,
+ CANCEL,
+};
+
// Specifies the type of modality applied to a window. Different modal
// treatments may be handled differently by the window manager.
enum ModalType {
diff --git a/chromium/ui/base/mojo/ui_base_types.typemap b/chromium/ui/base/mojo/ui_base_types.typemap
index a8a3b6f2643..9157ed1fa08 100644
--- a/chromium/ui/base/mojo/ui_base_types.typemap
+++ b/chromium/ui/base/mojo/ui_base_types.typemap
@@ -9,4 +9,7 @@ public_deps = [
"//ui/base",
]
traits_headers = [ "//ui/base/mojo/ui_base_types_struct_traits.h" ]
-type_mappings = [ "ui.mojom.ModalType=ui::ModalType" ]
+type_mappings = [
+ "ui.mojom.DialogButton=ui::DialogButton",
+ "ui.mojom.ModalType=ui::ModalType",
+]
diff --git a/chromium/ui/base/mojo/ui_base_types_struct_traits.h b/chromium/ui/base/mojo/ui_base_types_struct_traits.h
index 55d57df2d56..35bf814112e 100644
--- a/chromium/ui/base/mojo/ui_base_types_struct_traits.h
+++ b/chromium/ui/base/mojo/ui_base_types_struct_traits.h
@@ -12,6 +12,41 @@
namespace mojo {
template <>
+struct EnumTraits<ui::mojom::DialogButton, ui::DialogButton> {
+ static ui::mojom::DialogButton ToMojom(ui::DialogButton modal_type) {
+ switch (modal_type) {
+ case ui::DIALOG_BUTTON_NONE:
+ return ui::mojom::DialogButton::NONE;
+ case ui::DIALOG_BUTTON_OK:
+ return ui::mojom::DialogButton::OK;
+ case ui::DIALOG_BUTTON_CANCEL:
+ return ui::mojom::DialogButton::CANCEL;
+ default:
+ NOTREACHED();
+ return ui::mojom::DialogButton::NONE;
+ }
+ }
+
+ static bool FromMojom(ui::mojom::DialogButton modal_type,
+ ui::DialogButton* out) {
+ switch (modal_type) {
+ case ui::mojom::DialogButton::NONE:
+ *out = ui::DIALOG_BUTTON_NONE;
+ return true;
+ case ui::mojom::DialogButton::OK:
+ *out = ui::DIALOG_BUTTON_OK;
+ return true;
+ case ui::mojom::DialogButton::CANCEL:
+ *out = ui::DIALOG_BUTTON_CANCEL;
+ return true;
+ default:
+ NOTREACHED();
+ return false;
+ }
+ }
+};
+
+template <>
struct EnumTraits<ui::mojom::ModalType, ui::ModalType> {
static ui::mojom::ModalType ToMojom(ui::ModalType modal_type) {
switch (modal_type) {
diff --git a/chromium/ui/base/resource/resource_bundle.cc b/chromium/ui/base/resource/resource_bundle.cc
index 2a00d4e851a..d6d21eeb8ef 100644
--- a/chromium/ui/base/resource/resource_bundle.cc
+++ b/chromium/ui/base/resource/resource_bundle.cc
@@ -242,23 +242,12 @@ void ResourceBundle::LoadSecondaryLocaleDataWithPakFileRegion(
}
#if !defined(OS_ANDROID)
+// static
bool ResourceBundle::LocaleDataPakExists(const std::string& locale) {
return !GetLocaleFilePath(locale, true).empty();
}
#endif // !defined(OS_ANDROID)
-void ResourceBundle::AddDataPack(std::unique_ptr<DataPack> data_pack) {
-#if DCHECK_IS_ON()
- data_pack->CheckForDuplicateResources(data_packs_);
-#endif
-
- if (GetScaleForScaleFactor(data_pack->GetScaleFactor()) >
- GetScaleForScaleFactor(max_scale_factor_))
- max_scale_factor_ = data_pack->GetScaleFactor();
-
- data_packs_.push_back(std::move(data_pack));
-}
-
void ResourceBundle::AddDataPackFromPath(const base::FilePath& path,
ScaleFactor scale_factor) {
AddDataPackFromPathInternal(path, scale_factor, false);
@@ -300,6 +289,7 @@ void ResourceBundle::AddDataPackFromFileRegion(
}
#if !defined(OS_MACOSX)
+// static
base::FilePath ResourceBundle::GetLocaleFilePath(const std::string& app_locale,
bool test_file_exists) {
if (app_locale.empty())
@@ -328,9 +318,14 @@ base::FilePath ResourceBundle::GetLocaleFilePath(const std::string& app_locale,
#endif
}
- if (delegate_) {
- locale_file_path =
- delegate_->GetPathForLocalePack(locale_file_path, app_locale);
+ // Note: The delegate GetPathForLocalePack() override is currently only used
+ // by CastResourceDelegate, which does not call this function prior to
+ // initializing the ResourceBundle. This called earlier than that by the
+ // variations code which also has a CHECK that an inconsistent value does not
+ // get returned via VariationsService::EnsureLocaleEquals().
+ if (HasSharedInstance() && GetSharedInstance().delegate_) {
+ locale_file_path = GetSharedInstance().delegate_->GetPathForLocalePack(
+ locale_file_path, app_locale);
}
// Don't try to load empty values or values that are not absolute paths.
@@ -402,9 +397,9 @@ void ResourceBundle::OverrideLocalePakForTest(const base::FilePath& pak_path) {
}
void ResourceBundle::OverrideLocaleStringResource(
- int message_id,
+ int resource_id,
const base::string16& string) {
- overridden_locale_strings_[message_id] = string;
+ overridden_locale_strings_[resource_id] = string;
}
const base::FilePath& ResourceBundle::GetOverriddenPakPath() {
@@ -556,62 +551,16 @@ base::StringPiece ResourceBundle::GetRawDataResourceForScale(
return base::StringPiece();
}
-base::string16 ResourceBundle::GetLocalizedString(int message_id) {
- base::string16 string;
- if (delegate_ && delegate_->GetLocalizedString(message_id, &string))
- return MaybeMangleLocalizedString(string);
-
- // Ensure that ReloadLocaleResources() doesn't drop the resources while
- // we're using them.
- base::AutoLock lock_scope(*locale_resources_data_lock_);
-
- IdToStringMap::const_iterator it =
- overridden_locale_strings_.find(message_id);
- if (it != overridden_locale_strings_.end())
- return MaybeMangleLocalizedString(it->second);
-
- // If for some reason we were unable to load the resources , return an empty
- // string (better than crashing).
- if (!locale_resources_data_.get()) {
- LOG(WARNING) << "locale resources are not loaded";
- return base::string16();
- }
-
- base::StringPiece data;
- ResourceHandle::TextEncodingType encoding =
- locale_resources_data_->GetTextEncodingType();
- if (!locale_resources_data_->GetStringPiece(static_cast<uint16_t>(message_id),
- &data)) {
- if (secondary_locale_resources_data_.get() &&
- secondary_locale_resources_data_->GetStringPiece(
- static_cast<uint16_t>(message_id), &data)) {
- // Fall back on the secondary locale pak if it exists.
- encoding = secondary_locale_resources_data_->GetTextEncodingType();
- } else {
- // Fall back on the main data pack (shouldn't be any strings here except
- // in unittests).
- data = GetRawDataResource(message_id);
- if (data.empty()) {
- LOG(WARNING) << "unable to find resource: " << message_id;
- NOTREACHED();
- return base::string16();
- }
- }
- }
-
- // Strings should not be loaded from a data pack that contains binary data.
- DCHECK(encoding == ResourceHandle::UTF16 || encoding == ResourceHandle::UTF8)
- << "requested localized string from binary pack file";
-
- // Data pack encodes strings as either UTF8 or UTF16.
- base::string16 msg;
- if (encoding == ResourceHandle::UTF16) {
- msg = base::string16(reinterpret_cast<const base::char16*>(data.data()),
- data.length() / 2);
- } else if (encoding == ResourceHandle::UTF8) {
- msg = base::UTF8ToUTF16(data);
+base::string16 ResourceBundle::GetLocalizedString(int resource_id) {
+#if DCHECK_IS_ON()
+ {
+ base::AutoLock lock_scope(*locale_resources_data_lock_);
+ // Overriding locale strings isn't supported if the first string resource
+ // has already been queried.
+ can_override_locale_string_resources_ = false;
}
- return MaybeMangleLocalizedString(msg);
+#endif
+ return GetLocalizedStringImpl(resource_id);
}
base::RefCountedMemory* ResourceBundle::LoadLocalizedResourceBytes(
@@ -733,6 +682,13 @@ bool ResourceBundle::IsScaleFactorSupported(ScaleFactor scale_factor) {
return base::ContainsValue(supported_scale_factors, scale_factor);
}
+void ResourceBundle::CheckCanOverrideStringResources() {
+#if DCHECK_IS_ON()
+ base::AutoLock lock_scope(*locale_resources_data_lock_);
+ DCHECK(can_override_locale_string_resources_);
+#endif
+}
+
ResourceBundle::ResourceBundle(Delegate* delegate)
: delegate_(delegate),
locale_resources_data_lock_(new base::Lock),
@@ -750,7 +706,7 @@ ResourceBundle::~ResourceBundle() {
void ResourceBundle::InitSharedInstance(Delegate* delegate) {
DCHECK(g_shared_instance_ == NULL) << "ResourceBundle initialized twice";
g_shared_instance_ = new ResourceBundle(delegate);
- static std::vector<ScaleFactor> supported_scale_factors;
+ std::vector<ScaleFactor> supported_scale_factors;
#if defined(OS_IOS)
display::Display display = display::Screen::GetScreen()->GetPrimaryDisplay();
if (display.device_scale_factor() > 2.0) {
@@ -817,10 +773,26 @@ void ResourceBundle::AddDataPackFromPathInternal(
}
}
+void ResourceBundle::AddDataPack(std::unique_ptr<DataPack> data_pack) {
+#if DCHECK_IS_ON()
+ data_pack->CheckForDuplicateResources(data_packs_);
+#endif
+
+ if (GetScaleForScaleFactor(data_pack->GetScaleFactor()) >
+ GetScaleForScaleFactor(max_scale_factor_))
+ max_scale_factor_ = data_pack->GetScaleFactor();
+
+ data_packs_.push_back(std::move(data_pack));
+}
+
void ResourceBundle::InitDefaultFontList() {
#if defined(OS_CHROMEOS)
- std::string font_family = base::UTF16ToUTF8(
- GetLocalizedString(IDS_UI_FONT_FAMILY_CROS));
+ // InitDefaultFontList() is called earlier than overriding the locale strings.
+ // So we call the |GetLocalizedStringImpl()| which doesn't set the flag
+ // |can_override_locale_string_resources_| to false. This is okay, because the
+ // font list doesn't need to be overridden by variations.
+ std::string font_family =
+ base::UTF16ToUTF8(GetLocalizedStringImpl(IDS_UI_FONT_FAMILY_CROS));
gfx::FontList::SetDefaultFontDescription(font_family);
// TODO(yukishiino): Remove SetDefaultFontDescription() once the migration to
@@ -907,6 +879,64 @@ gfx::Image& ResourceBundle::GetEmptyImage() {
return empty_image_;
}
+base::string16 ResourceBundle::GetLocalizedStringImpl(int resource_id) {
+ base::string16 string;
+ if (delegate_ && delegate_->GetLocalizedString(resource_id, &string))
+ return MaybeMangleLocalizedString(string);
+
+ // Ensure that ReloadLocaleResources() doesn't drop the resources while
+ // we're using them.
+ base::AutoLock lock_scope(*locale_resources_data_lock_);
+
+ IdToStringMap::const_iterator it =
+ overridden_locale_strings_.find(resource_id);
+ if (it != overridden_locale_strings_.end())
+ return MaybeMangleLocalizedString(it->second);
+
+ // If for some reason we were unable to load the resources , return an empty
+ // string (better than crashing).
+ if (!locale_resources_data_.get()) {
+ LOG(WARNING) << "locale resources are not loaded";
+ return base::string16();
+ }
+
+ base::StringPiece data;
+ ResourceHandle::TextEncodingType encoding =
+ locale_resources_data_->GetTextEncodingType();
+ if (!locale_resources_data_->GetStringPiece(
+ static_cast<uint16_t>(resource_id), &data)) {
+ if (secondary_locale_resources_data_.get() &&
+ secondary_locale_resources_data_->GetStringPiece(
+ static_cast<uint16_t>(resource_id), &data)) {
+ // Fall back on the secondary locale pak if it exists.
+ encoding = secondary_locale_resources_data_->GetTextEncodingType();
+ } else {
+ // Fall back on the main data pack (shouldn't be any strings here except
+ // in unittests).
+ data = GetRawDataResource(resource_id);
+ if (data.empty()) {
+ LOG(WARNING) << "unable to find resource: " << resource_id;
+ NOTREACHED();
+ return base::string16();
+ }
+ }
+ }
+
+ // Strings should not be loaded from a data pack that contains binary data.
+ DCHECK(encoding == ResourceHandle::UTF16 || encoding == ResourceHandle::UTF8)
+ << "requested localized string from binary pack file";
+
+ // Data pack encodes strings as either UTF8 or UTF16.
+ base::string16 msg;
+ if (encoding == ResourceHandle::UTF16) {
+ msg = base::string16(reinterpret_cast<const base::char16*>(data.data()),
+ data.length() / 2);
+ } else if (encoding == ResourceHandle::UTF8) {
+ msg = base::UTF8ToUTF16(data);
+ }
+ return MaybeMangleLocalizedString(msg);
+}
+
// static
bool ResourceBundle::PNGContainsFallbackMarker(const unsigned char* buf,
size_t size) {
diff --git a/chromium/ui/base/resource/resource_bundle.h b/chromium/ui/base/resource/resource_bundle.h
index 422d84bc266..c24fcf0ba3c 100644
--- a/chromium/ui/base/resource/resource_bundle.h
+++ b/chromium/ui/base/resource/resource_bundle.h
@@ -156,11 +156,7 @@ class UI_BASE_EXPORT ResourceBundle {
const base::MemoryMappedFile::Region& region);
// Check if the .pak for the given locale exists.
- bool LocaleDataPakExists(const std::string& locale);
-
- // Inserts |data_pack| to |data_pack_| and updates |max_scale_factor_|
- // accordingly.
- void AddDataPack(std::unique_ptr<DataPack> data_pack);
+ static bool LocaleDataPakExists(const std::string& locale);
// Registers additional data pack files with this ResourceBundle. When
// looking for a DataResource, we will search these files after searching the
@@ -241,9 +237,9 @@ class UI_BASE_EXPORT ResourceBundle {
base::StringPiece GetRawDataResourceForScale(int resource_id,
ScaleFactor scale_factor) const;
- // Get a localized string given a message id. Returns an empty
- // string if the message_id is not found.
- base::string16 GetLocalizedString(int message_id);
+ // 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);
// Get a localized resource (for example, localized image logo) given a
// resource id.
@@ -276,19 +272,19 @@ class UI_BASE_EXPORT ResourceBundle {
// Overrides a localized string resource with the given string. If no delegate
// is present, the |string| will be returned when getting the localized string
- // |message_id|. If |ReloadLocaleResources| is called, all overrides are
+ // |resource_id|. If |ReloadLocaleResources| is called, all overrides are
// cleared. This is intended to be used in conjunction with field trials and
// the variations service to experiment with different UI strings. This method
// is not thread safe!
- void OverrideLocaleStringResource(int message_id,
+ void OverrideLocaleStringResource(int resource_id,
const base::string16& string);
// Returns the full pathname of the locale file to load. May return an empty
// string if no locale data files are found and |test_file_exists| is true.
// Used on Android to load the local file in the browser process and pass it
// to the sandboxed renderer process.
- base::FilePath GetLocaleFilePath(const std::string& app_locale,
- bool test_file_exists);
+ static base::FilePath GetLocaleFilePath(const std::string& app_locale,
+ bool test_file_exists);
// Returns the maximum scale factor currently loaded.
// Returns SCALE_FACTOR_100P if no resource is loaded.
@@ -297,11 +293,22 @@ class UI_BASE_EXPORT ResourceBundle {
// Returns true if |scale_factor| is supported by this platform.
static bool IsScaleFactorSupported(ScaleFactor scale_factor);
+ // Checks whether overriding locale strings is supported. This will fail with
+ // a DCHECK if the first string resource has already been queried.
+ void CheckCanOverrideStringResources();
+
// Sets whether this ResourceBundle should mangle localized strings or not.
void set_mangle_localized_strings_for_test(bool mangle) {
mangle_localized_strings_ = mangle;
}
+#if DCHECK_IS_ON()
+ // Gets whether overriding locale strings is supported.
+ bool get_can_override_locale_string_resources_for_test() {
+ return can_override_locale_string_resources_;
+ }
+#endif
+
private:
FRIEND_TEST_ALL_PREFIXES(ResourceBundleTest, DelegateGetPathForLocalePack);
FRIEND_TEST_ALL_PREFIXES(ResourceBundleTest, DelegateGetImageNamed);
@@ -341,6 +348,10 @@ class UI_BASE_EXPORT ResourceBundle {
ScaleFactor scale_factor,
bool optional);
+ // Inserts |data_pack| to |data_pack_| and updates |max_scale_factor_|
+ // accordingly.
+ void AddDataPack(std::unique_ptr<DataPack> data_pack);
+
// Try to load the locale specific strings from an external data module.
// Returns the locale that is loaded.
std::string LoadLocaleResources(const std::string& pref_locale);
@@ -404,6 +415,13 @@ class UI_BASE_EXPORT ResourceBundle {
// visible and returns the mangled string. If not, returns |str|.
base::string16 MaybeMangleLocalizedString(const base::string16& str);
+ // 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);
+
// This pointer is guaranteed to outlive the ResourceBundle instance and may
// be NULL.
Delegate* delegate_;
@@ -436,6 +454,10 @@ class UI_BASE_EXPORT ResourceBundle {
IdToStringMap overridden_locale_strings_;
+#if DCHECK_IS_ON()
+ bool can_override_locale_string_resources_ = true;
+#endif
+
bool is_test_resources_ = false;
bool mangle_localized_strings_ = false;
diff --git a/chromium/ui/base/resource/resource_bundle_android.cc b/chromium/ui/base/resource/resource_bundle_android.cc
index 6ce54d115ad..5fdfaeae0e7 100644
--- a/chromium/ui/base/resource/resource_bundle_android.cc
+++ b/chromium/ui/base/resource/resource_bundle_android.cc
@@ -11,6 +11,7 @@
#include "base/path_service.h"
#include "jni/ResourceBundle_jni.h"
#include "ui/base/l10n/l10n_util.h"
+#include "ui/base/resource/data_pack.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/ui_base_paths.h"
@@ -91,6 +92,7 @@ void ResourceBundle::LoadCommonResources() {
}
}
+// static
bool ResourceBundle::LocaleDataPakExists(const std::string& locale) {
if (g_locale_paks_in_apk) {
return !GetPathForAndroidLocalePakWithinApk(locale).empty();
@@ -175,21 +177,6 @@ void LoadMainAndroidPackFile(const char* path_within_apk,
}
}
-std::unique_ptr<DataPack> GetDataPackFromPackFile(
- const char* path_within_apk,
- const base::FilePath& disk_file_path) {
- if (LoadFromApkOrFile(path_within_apk, &disk_file_path, &g_resources_pack_fd,
- &g_resources_pack_region)) {
- std::unique_ptr<DataPack> data_pack =
- std::make_unique<DataPack>(SCALE_FACTOR_NONE);
- if (data_pack->LoadFromFileRegion(base::File(g_resources_pack_fd),
- g_resources_pack_region)) {
- return data_pack;
- }
- }
- return nullptr;
-}
-
int GetMainAndroidPackFd(base::MemoryMappedFile::Region* out_region) {
DCHECK_GE(g_resources_pack_fd, 0);
*out_region = g_resources_pack_region;
diff --git a/chromium/ui/base/resource/resource_bundle_android.h b/chromium/ui/base/resource/resource_bundle_android.h
index 2913731131f..57059b0ecbc 100644
--- a/chromium/ui/base/resource/resource_bundle_android.h
+++ b/chromium/ui/base/resource/resource_bundle_android.h
@@ -9,7 +9,6 @@
#include <string>
#include "base/files/memory_mapped_file.h"
-#include "ui/base/resource/data_pack.h"
#include "ui/base/ui_base_export.h"
namespace ui {
@@ -20,10 +19,6 @@ UI_BASE_EXPORT void LoadMainAndroidPackFile(
const char* path_within_apk,
const base::FilePath& disk_file_path);
-UI_BASE_EXPORT std::unique_ptr<DataPack> GetDataPackFromPackFile(
- const char* path_within_apk,
- const base::FilePath& disk_file_path);
-
// Returns the file descriptor and region for resources.pak.
UI_BASE_EXPORT int GetMainAndroidPackFd(
base::MemoryMappedFile::Region* out_region);
diff --git a/chromium/ui/base/resource/resource_bundle_ios.mm b/chromium/ui/base/resource/resource_bundle_ios.mm
index 74d9a97c700..02ba7fc1616 100644
--- a/chromium/ui/base/resource/resource_bundle_ios.mm
+++ b/chromium/ui/base/resource/resource_bundle_ios.mm
@@ -59,6 +59,7 @@ void ResourceBundle::LoadCommonResources() {
}
}
+// static
base::FilePath ResourceBundle::GetLocaleFilePath(const std::string& app_locale,
bool test_file_exists) {
NSString* mac_locale = base::SysUTF8ToNSString(app_locale);
@@ -74,9 +75,9 @@ base::FilePath ResourceBundle::GetLocaleFilePath(const std::string& app_locale,
base::FilePath locale_file_path =
GetResourcesPakFilePath(@"locale", mac_locale);
- if (delegate_) {
- locale_file_path =
- delegate_->GetPathForLocalePack(locale_file_path, app_locale);
+ if (HasSharedInstance() && GetSharedInstance().delegate_) {
+ locale_file_path = GetSharedInstance().delegate_->GetPathForLocalePack(
+ locale_file_path, app_locale);
}
// Don't try to load empty values or values that are not absolute paths.
diff --git a/chromium/ui/base/resource/resource_bundle_mac.mm b/chromium/ui/base/resource/resource_bundle_mac.mm
index 3cf1847860a..873989c5017 100644
--- a/chromium/ui/base/resource/resource_bundle_mac.mm
+++ b/chromium/ui/base/resource/resource_bundle_mac.mm
@@ -59,6 +59,7 @@ void ResourceBundle::LoadCommonResources() {
}
}
+// static
base::FilePath ResourceBundle::GetLocaleFilePath(const std::string& app_locale,
bool test_file_exists) {
NSString* mac_locale = base::SysUTF8ToNSString(app_locale);
@@ -74,9 +75,9 @@ base::FilePath ResourceBundle::GetLocaleFilePath(const std::string& app_locale,
base::FilePath locale_file_path =
GetResourcesPakFilePath(@"locale", mac_locale);
- if (delegate_) {
- locale_file_path =
- delegate_->GetPathForLocalePack(locale_file_path, app_locale);
+ if (HasSharedInstance() && GetSharedInstance().delegate_) {
+ locale_file_path = GetSharedInstance().delegate_->GetPathForLocalePack(
+ locale_file_path, app_locale);
}
// Don't try to load empty values or values that are not absolute paths.
diff --git a/chromium/ui/base/resource/resource_bundle_unittest.cc b/chromium/ui/base/resource/resource_bundle_unittest.cc
index 363a0e9d03d..1d61db04987 100644
--- a/chromium/ui/base/resource/resource_bundle_unittest.cc
+++ b/chromium/ui/base/resource/resource_bundle_unittest.cc
@@ -92,8 +92,7 @@ void AddCustomChunk(const base::StringPiece& custom_chunk,
bitmap_data->begin(),
bitmap_data->begin() + arraysize(kPngMagic),
kPngMagic));
- std::vector<unsigned char>::iterator ihdr_start =
- bitmap_data->begin() + arraysize(kPngMagic);
+ auto ihdr_start = bitmap_data->begin() + arraysize(kPngMagic);
char ihdr_length_data[sizeof(uint32_t)];
for (size_t i = 0; i < sizeof(uint32_t); ++i)
ihdr_length_data[i] = *(ihdr_start + i);
@@ -135,8 +134,7 @@ void CreateDataPackWithSingleBitmap(const base::FilePath& path,
class ResourceBundleTest : public testing::Test {
public:
- ResourceBundleTest() : resource_bundle_(NULL) {
- }
+ ResourceBundleTest() : resource_bundle_(nullptr) {}
~ResourceBundleTest() override {}
@@ -184,27 +182,31 @@ TEST_F(ResourceBundleTest, DelegateGetPathForResourcePack) {
#define MAYBE_DelegateGetPathForLocalePack DelegateGetPathForLocalePack
#endif
TEST_F(ResourceBundleTest, MAYBE_DelegateGetPathForLocalePack) {
+ ResourceBundle::CleanupSharedInstance();
+
MockResourceBundleDelegate delegate;
- ResourceBundle* resource_bundle = CreateResourceBundle(&delegate);
+ ResourceBundle::InitSharedInstance(&delegate);
std::string locale = "en-US";
// Cancel the load.
- EXPECT_CALL(delegate, GetPathForLocalePack(_, locale))
- .Times(2)
+ EXPECT_CALL(delegate, GetPathForLocalePack(_, _))
.WillRepeatedly(Return(base::FilePath()))
.RetiresOnSaturation();
- EXPECT_FALSE(resource_bundle->LocaleDataPakExists(locale));
- EXPECT_EQ("", resource_bundle->LoadLocaleResources(locale));
+ EXPECT_FALSE(ResourceBundle::LocaleDataPakExists(locale));
+ EXPECT_EQ("",
+ ResourceBundle::GetSharedInstance().LoadLocaleResources(locale));
// Allow the load to proceed.
- EXPECT_CALL(delegate, GetPathForLocalePack(_, locale))
- .Times(2)
+ EXPECT_CALL(delegate, GetPathForLocalePack(_, _))
.WillRepeatedly(ReturnArg<0>());
- EXPECT_TRUE(resource_bundle->LocaleDataPakExists(locale));
- EXPECT_EQ(locale, resource_bundle->LoadLocaleResources(locale));
+ EXPECT_TRUE(ResourceBundle::LocaleDataPakExists(locale));
+ EXPECT_EQ(locale,
+ ResourceBundle::GetSharedInstance().LoadLocaleResources(locale));
+
+ ResourceBundle::CleanupSharedInstance();
}
TEST_F(ResourceBundleTest, DelegateGetImageNamed) {
@@ -298,7 +300,7 @@ TEST_F(ResourceBundleTest, DelegateGetLocalizedString) {
}
TEST_F(ResourceBundleTest, OverrideStringResource) {
- ResourceBundle* resource_bundle = CreateResourceBundle(NULL);
+ ResourceBundle* resource_bundle = CreateResourceBundle(nullptr);
base::string16 data = base::ASCIIToUTF16("My test data");
int resource_id = 5;
@@ -312,6 +314,21 @@ TEST_F(ResourceBundleTest, OverrideStringResource) {
EXPECT_EQ(data, result);
}
+#if DCHECK_IS_ON()
+TEST_F(ResourceBundleTest, CanOverrideStringResources) {
+ ResourceBundle* resource_bundle = CreateResourceBundle(nullptr);
+
+ base::string16 data = base::ASCIIToUTF16("My test data");
+ int resource_id = 5;
+
+ EXPECT_TRUE(
+ resource_bundle->get_can_override_locale_string_resources_for_test());
+ resource_bundle->GetLocalizedString(resource_id);
+ EXPECT_FALSE(
+ resource_bundle->get_can_override_locale_string_resources_for_test());
+}
+#endif
+
TEST_F(ResourceBundleTest, DelegateGetLocalizedStringWithOverride) {
MockResourceBundleDelegate delegate;
ResourceBundle* resource_bundle = CreateResourceBundle(&delegate);
@@ -329,11 +346,9 @@ TEST_F(ResourceBundleTest, DelegateGetLocalizedStringWithOverride) {
}
TEST_F(ResourceBundleTest, LocaleDataPakExists) {
- ResourceBundle* resource_bundle = CreateResourceBundle(NULL);
-
// Check that ResourceBundle::LocaleDataPakExists returns the correct results.
- EXPECT_TRUE(resource_bundle->LocaleDataPakExists("en-US"));
- EXPECT_FALSE(resource_bundle->LocaleDataPakExists("not_a_real_locale"));
+ EXPECT_TRUE(ResourceBundle::LocaleDataPakExists("en-US"));
+ EXPECT_FALSE(ResourceBundle::LocaleDataPakExists("not_a_real_locale"));
}
class ResourceBundleImageTest : public ResourceBundleTest {
@@ -355,7 +370,7 @@ class ResourceBundleImageTest : public ResourceBundleTest {
EXPECT_EQ(base::WriteFile(locale_path, kEmptyPakContents, kEmptyPakSize),
static_cast<int>(kEmptyPakSize));
- ui::ResourceBundle* resource_bundle = CreateResourceBundle(NULL);
+ ui::ResourceBundle* resource_bundle = CreateResourceBundle(nullptr);
// Load the empty locale data pak.
resource_bundle->LoadTestResources(base::FilePath(), locale_path);
@@ -392,15 +407,15 @@ TEST_F(ResourceBundleImageTest, LoadDataResourceBytes) {
resource_bundle->AddDataPackFromPath(data_path, SCALE_FACTOR_100P);
const int kUnfoundResourceId = 10000;
- EXPECT_EQ(NULL, resource_bundle->LoadDataResourceBytes(
- kUnfoundResourceId));
+ EXPECT_EQ(nullptr,
+ resource_bundle->LoadDataResourceBytes(kUnfoundResourceId));
// Give a .pak file that doesn't exist so we will fail to load it.
resource_bundle->AddDataPackFromPath(
base::FilePath(FILE_PATH_LITERAL("non-existant-file.pak")),
ui::SCALE_FACTOR_NONE);
- EXPECT_EQ(NULL, resource_bundle->LoadDataResourceBytes(
- kUnfoundResourceId));
+ EXPECT_EQ(nullptr,
+ resource_bundle->LoadDataResourceBytes(kUnfoundResourceId));
}
TEST_F(ResourceBundleImageTest, GetRawDataResource) {
diff --git a/chromium/ui/base/template_expressions.cc b/chromium/ui/base/template_expressions.cc
index 9618dc7b4d7..1aec20cb5b9 100644
--- a/chromium/ui/base/template_expressions.cc
+++ b/chromium/ui/base/template_expressions.cc
@@ -93,7 +93,7 @@ std::string ReplaceTemplateExpressions(
source.substr(current_pos, key_end - current_pos).as_string();
CHECK(!key.empty());
- TemplateReplacements::const_iterator value = replacements.find(key);
+ auto value = replacements.find(key);
CHECK(value != replacements.end()) << "$i18n replacement key \"" << key
<< "\" not found";
diff --git a/chromium/ui/base/theme_provider.h b/chromium/ui/base/theme_provider.h
index 3a19618ce89..514a9ae4545 100644
--- a/chromium/ui/base/theme_provider.h
+++ b/chromium/ui/base/theme_provider.h
@@ -5,23 +5,10 @@
#ifndef UI_BASE_THEME_PROVIDER_H_
#define UI_BASE_THEME_PROVIDER_H_
-#include "build/build_config.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/layout.h"
#include "ui/base/ui_base_export.h"
-#if defined(OS_MACOSX)
-#ifdef __OBJC__
-@class NSColor;
-@class NSGradient;
-@class NSImage;
-#else
-class NSColor;
-class NSGradient;
-class NSImage;
-#endif // __OBJC__
-#endif // OS_*
-
namespace base {
class RefCountedMemory;
}
@@ -80,36 +67,6 @@ class UI_BASE_EXPORT ThemeProvider {
virtual base::RefCountedMemory* GetRawData(
int id,
ui::ScaleFactor scale_factor) const = 0;
-
-#if defined(OS_MACOSX)
- // Whether we're using the system theme (which may or may not be the
- // same as the default theme).
- // TODO(estade): this should probably just be part of ThemeService and not
- // ThemeProvider, but it's used in many places on OSX.
- virtual bool UsingSystemTheme() const = 0;
-
- // Returns whether or not theme is in Incognito mode.
- virtual bool InIncognitoMode() const = 0;
-
- // Gets the NSImage with the specified |id|.
- virtual NSImage* GetNSImageNamed(int id) const = 0;
-
- // Gets the NSImage that GetNSImageNamed (above) would return, but returns it
- // as a pattern color.
- virtual NSColor* GetNSImageColorNamed(int id) const = 0;
-
- // Gets the NSColor with the specified |id|.
- virtual NSColor* GetNSColor(int id) const = 0;
-
- // Gets the NSColor for tinting with the specified |id|.
- virtual NSColor* GetNSColorTint(int id) const = 0;
-
- // Gets the NSGradient with the specified |id|.
- virtual NSGradient* GetNSGradient(int id) const = 0;
-
- // Whether the "increase contrast" accessibility setting is enabled.
- virtual bool ShouldIncreaseContrast() const = 0;
-#endif
};
} // namespace ui
diff --git a/chromium/ui/base/touch/touch_editing_controller.h b/chromium/ui/base/touch/touch_editing_controller.h
index 513835e227a..bfa17bcdc87 100644
--- a/chromium/ui/base/touch/touch_editing_controller.h
+++ b/chromium/ui/base/touch/touch_editing_controller.h
@@ -92,13 +92,12 @@ class UI_BASE_EXPORT TouchEditingControllerDeprecated {
class UI_BASE_EXPORT TouchEditingControllerFactory {
public:
+ virtual ~TouchEditingControllerFactory() {}
+
static void SetInstance(TouchEditingControllerFactory* instance);
virtual TouchEditingControllerDeprecated* Create(TouchEditable* client_view)
= 0;
-
- protected:
- virtual ~TouchEditingControllerFactory() {}
};
} // namespace ui
diff --git a/chromium/ui/base/ui_base_features.cc b/chromium/ui/base/ui_base_features.cc
index 95139912ce8..674998b13af 100644
--- a/chromium/ui/base/ui_base_features.cc
+++ b/chromium/ui/base/ui_base_features.cc
@@ -67,7 +67,7 @@ bool IsNotificationIndicatorEnabled() {
// Enables GPU rasterization for all UI drawing (where not blacklisted).
const base::Feature kUiGpuRasterization = {"UiGpuRasterization",
-#if defined(OS_MACOSX)
+#if defined(OS_MACOSX) || defined(OS_CHROMEOS)
base::FEATURE_ENABLED_BY_DEFAULT
#else
base::FEATURE_DISABLED_BY_DEFAULT
@@ -153,20 +153,6 @@ const base::Feature kHostWindowsInAppShimProcess{
bool HostWindowsInAppShimProcess() {
return base::FeatureList::IsEnabled(kHostWindowsInAppShimProcess);
}
-
-#if BUILDFLAG(MAC_VIEWS_BROWSER)
-// Causes Views browser builds to use Views browser windows by default rather
-// than Cocoa browser windows.
-const base::Feature kViewsBrowserWindows{"ViewsBrowserWindows",
- base::FEATURE_ENABLED_BY_DEFAULT};
-
-// Returns whether a Views-capable browser build should use the Cocoa browser
-// UI.
-bool IsViewsBrowserCocoa() {
- return !base::FeatureList::IsEnabled(kViewsBrowserWindows) &&
- !base::FeatureList::IsEnabled(kExperimentalUi);
-}
-#endif // BUILDFLAG(MAC_VIEWS_BROWSER)
#endif // defined(OS_MACOSX)
const base::Feature kEnableOzoneDrmMojo = {"OzoneDrmMojo",
@@ -177,4 +163,6 @@ bool IsOzoneDrmMojo() {
IsMultiProcessMash();
}
+const base::Feature kDarkMode = {"DarkMode", base::FEATURE_DISABLED_BY_DEFAULT};
+
} // namespace features
diff --git a/chromium/ui/base/ui_base_features.h b/chromium/ui/base/ui_base_features.h
index c9799a2bda0..4a799dda3c5 100644
--- a/chromium/ui/base/ui_base_features.h
+++ b/chromium/ui/base/ui_base_features.h
@@ -68,17 +68,11 @@ UI_BASE_EXPORT bool IsMultiProcessMash();
UI_BASE_EXPORT bool IsSingleProcessMash();
#if defined(OS_MACOSX)
+UI_BASE_EXPORT extern const base::Feature kHostWindowsInAppShimProcess;
+
// Returns true if the NSWindows for apps will be created in the app's process,
// and will forward input to the browser process.
UI_BASE_EXPORT bool HostWindowsInAppShimProcess();
-
-#if BUILDFLAG(MAC_VIEWS_BROWSER)
-UI_BASE_EXPORT extern const base::Feature kViewsBrowserWindows;
-
-// Returns whether a Views-capable browser build should use the Cocoa browser
-// UI.
-UI_BASE_EXPORT bool IsViewsBrowserCocoa();
-#endif // BUILDFLAG(MAC_VIEWS_BROWSER)
#endif // defined(OS_MACOSX)
// Use mojo communication in the drm platform instead of paramtraits. Remove
@@ -88,6 +82,10 @@ UI_BASE_EXPORT bool IsViewsBrowserCocoa();
UI_BASE_EXPORT extern const base::Feature kEnableOzoneDrmMojo;
UI_BASE_EXPORT bool IsOzoneDrmMojo();
+// Whether default UI should use a dark mode color scheme, if enabled on
+// macOS Mojave/Windows 10.
+UI_BASE_EXPORT extern const base::Feature kDarkMode;
+
} // namespace features
#endif // UI_BASE_UI_BASE_FEATURES_H_
diff --git a/chromium/ui/base/ui_base_switches.cc b/chromium/ui/base/ui_base_switches.cc
index 4165ac52387..c14baff0863 100644
--- a/chromium/ui/base/ui_base_switches.cc
+++ b/chromium/ui/base/ui_base_switches.cc
@@ -48,6 +48,9 @@ const char kEnableTouchDragDrop[] = "enable-touch-drag-drop";
const char kEnableTouchableAppContextMenu[] =
"enable-touchable-app-context-menus";
+// Forces dark mode in UI for platforms that support it.
+const char kForceDarkMode[] = "force-dark-mode";
+
// Forces high-contrast mode in native UI drawing, regardless of system
// settings. Note that this has limited effect on Windows: only Aura colors will
// be switched to high contrast, not other system colors.
@@ -70,21 +73,6 @@ const char kMaterialDesignInkDropAnimationSpeedSlow[] = "slow";
// Enables top Chrome material design elements.
const char kTopChromeMD[] = "top-chrome-md";
-// Material design mode for the |kTopChromeMD| switch.
-const char kTopChromeMDMaterial[] = "material";
-
-// Auto-switching mode |kTopChromeMD| switch. This mode toggles between
-// material and material-hybrid depending on device.
-const char kTopChromeMDMaterialAuto[] = "material-auto";
-
-// Material design hybrid mode for the |kTopChromeMD| switch. Targeted for
-// mouse/touch hybrid devices.
-const char kTopChromeMDMaterialHybrid[] = "material-hybrid";
-
-// Material design mode that is more optimized for touch devices for the
-// |kTopChromeMD| switch.
-const char kTopChromeMDMaterialTouchOptimized[] = "material-touch-optimized";
-
// Material design mode that represents a refresh of the Chrome UI for the
// |kTopChromeMD| switch.
const char kTopChromeMDMaterialRefresh[] = "material-refresh";
@@ -94,6 +82,10 @@ const char kTopChromeMDMaterialRefresh[] = "material-refresh";
const char kTopChromeMDMaterialRefreshTouchOptimized[] =
"material-refresh-touch-optimized";
+// Switches between material refresh and touchable material refresh depending on
+// the tablet mode.
+const char kTopChromeMDMaterialRefreshDynamic[] = "material-refresh-dynamic";
+
// Disable partial swap which is needed for some OpenGL drivers / emulators.
const char kUIDisablePartialSwap[] = "ui-disable-partial-swap";
diff --git a/chromium/ui/base/ui_base_switches.h b/chromium/ui/base/ui_base_switches.h
index 4ddc0e56899..0c8c5957d48 100644
--- a/chromium/ui/base/ui_base_switches.h
+++ b/chromium/ui/base/ui_base_switches.h
@@ -27,6 +27,7 @@ UI_BASE_EXPORT extern const char kDisableTouchAdjustment[];
UI_BASE_EXPORT extern const char kDisableTouchDragDrop[];
UI_BASE_EXPORT extern const char kEnableTouchDragDrop[];
UI_BASE_EXPORT extern const char kEnableTouchableAppContextMenu[];
+UI_BASE_EXPORT extern const char kForceDarkMode[];
UI_BASE_EXPORT extern const char kForceHighContrast[];
UI_BASE_EXPORT extern const char kLang[];
UI_BASE_EXPORT extern const char kMaterialDesignInkDropAnimationSpeed[];
@@ -36,12 +37,9 @@ UI_BASE_EXPORT extern const char kShowOverdrawFeedback[];
UI_BASE_EXPORT extern const char kSlowDownCompositingScaleFactor[];
UI_BASE_EXPORT extern const char kTintGlCompositedContent[];
UI_BASE_EXPORT extern const char kTopChromeMD[];
-UI_BASE_EXPORT extern const char kTopChromeMDMaterial[];
-UI_BASE_EXPORT extern const char kTopChromeMDMaterialAuto[];
-UI_BASE_EXPORT extern const char kTopChromeMDMaterialHybrid[];
-UI_BASE_EXPORT extern const char kTopChromeMDMaterialTouchOptimized[];
UI_BASE_EXPORT extern const char kTopChromeMDMaterialRefresh[];
UI_BASE_EXPORT extern const char kTopChromeMDMaterialRefreshTouchOptimized[];
+UI_BASE_EXPORT extern const char kTopChromeMDMaterialRefreshDynamic[];
UI_BASE_EXPORT extern const char kUIDisablePartialSwap[];
// Test related.
diff --git a/chromium/ui/base/ui_features.gni b/chromium/ui/base/ui_features.gni
index 2691c6fbef5..6ecd398d5f1 100644
--- a/chromium/ui/base/ui_features.gni
+++ b/chromium/ui/base/ui_features.gni
@@ -8,9 +8,6 @@ declare_args() {
# Optional system library.
use_xkbcommon = false
- # Whether the entire browser uses toolkit-views on Mac instead of Cocoa.
- mac_views_browser = is_mac
-
# Whether the platform provides a native accessibility toolkit.
has_native_accessibility = use_atk || is_win || is_mac
diff --git a/chromium/ui/base/view_prop.cc b/chromium/ui/base/view_prop.cc
index 2ff403e2e31..45185f5ffbe 100644
--- a/chromium/ui/base/view_prop.cc
+++ b/chromium/ui/base/view_prop.cc
@@ -21,7 +21,7 @@ class ViewProp::Data : public base::RefCounted<ViewProp::Data> {
if (!data_set_)
data_set_ = new DataSet;
scoped_refptr<Data> new_data(new Data(view, key));
- DataSet::const_iterator i = data_set_->find(new_data.get());
+ auto i = data_set_->find(new_data.get());
if (i != data_set_->end()) {
*data = *i;
return;
@@ -58,7 +58,7 @@ class ViewProp::Data : public base::RefCounted<ViewProp::Data> {
data_(NULL) {}
~Data() {
- DataSet::iterator i = data_set_->find(this);
+ auto i = data_set_->find(this);
// Also check for equality using == as |Get| creates dummy values in order
// to look up a value.
if (i != data_set_->end() && *i == this)
diff --git a/chromium/ui/base/webui/i18n_source_stream_unittest.cc b/chromium/ui/base/webui/i18n_source_stream_unittest.cc
index 3484f649d73..5ef13bc2b53 100644
--- a/chromium/ui/base/webui/i18n_source_stream_unittest.cc
+++ b/chromium/ui/base/webui/i18n_source_stream_unittest.cc
@@ -87,7 +87,7 @@ class I18nSourceStreamTest : public ::testing::TestWithParam<I18nTestParam> {
// Helpful function to initialize the test fixture.
void Init() {
- output_buffer_ = new net::IOBuffer(output_buffer_size_);
+ output_buffer_ = base::MakeRefCounted<net::IOBuffer>(output_buffer_size_);
std::unique_ptr<net::MockSourceStream> source(new net::MockSourceStream());
source_ = source.get();
diff --git a/chromium/ui/base/x/selection_owner.cc b/chromium/ui/base/x/selection_owner.cc
index 17b750b6e9f..1804eaedee8 100644
--- a/chromium/ui/base/x/selection_owner.cc
+++ b/chromium/ui/base/x/selection_owner.cc
@@ -100,8 +100,7 @@ SelectionOwner::~SelectionOwner() {
}
void SelectionOwner::RetrieveTargets(std::vector<XAtom>* targets) {
- for (SelectionFormatMap::const_iterator it = format_map_.begin();
- it != format_map_.end(); ++it) {
+ for (auto it = format_map_.begin(); it != format_map_.end(); ++it) {
targets->push_back(it->first);
}
}
@@ -187,8 +186,7 @@ bool SelectionOwner::CanDispatchPropertyEvent(const XEvent& event) {
}
void SelectionOwner::OnPropertyEvent(const XEvent& event) {
- std::vector<IncrementalTransfer>::iterator it =
- FindIncrementalTransferForEvent(event);
+ auto it = FindIncrementalTransferForEvent(event);
if (it == incremental_transfers_.end())
return;
@@ -233,7 +231,7 @@ bool SelectionOwner::ProcessTarget(XAtom target,
}
// Try to find the data type in map.
- SelectionFormatMap::const_iterator it = format_map_.find(target);
+ auto it = format_map_.find(target);
if (it != format_map_.end()) {
if (it->second->size() > max_request_size_) {
// We must send the data back in several chunks due to a limitation in
@@ -326,10 +324,8 @@ void SelectionOwner::CompleteIncrementalTransfer(
std::vector<SelectionOwner::IncrementalTransfer>::iterator
SelectionOwner::FindIncrementalTransferForEvent(const XEvent& event) {
- for (std::vector<IncrementalTransfer>::iterator it =
- incremental_transfers_.begin();
- it != incremental_transfers_.end();
- ++it) {
+ for (auto it = incremental_transfers_.begin();
+ it != incremental_transfers_.end(); ++it) {
if (it->window == event.xproperty.window &&
it->property == event.xproperty.atom) {
return it;
diff --git a/chromium/ui/base/x/selection_requestor.cc b/chromium/ui/base/x/selection_requestor.cc
index ccd65a4d86b..8fb3bda7711 100644
--- a/chromium/ui/base/x/selection_requestor.cc
+++ b/chromium/ui/base/x/selection_requestor.cc
@@ -82,8 +82,7 @@ bool SelectionRequestor::PerformBlockingConvertSelection(
ConvertSelectionForCurrentRequest();
BlockTillSelectionNotifyForRequest(&request);
- std::vector<Request*>::iterator request_it = std::find(
- requests_.begin(), requests_.end(), &request);
+ auto request_it = std::find(requests_.begin(), requests_.end(), &request);
CHECK(request_it != requests_.end());
if (static_cast<int>(current_request_index_) >
request_it - requests_.begin()) {
@@ -116,8 +115,7 @@ void SelectionRequestor::PerformBlockingConvertSelectionWithParameter(
SelectionData SelectionRequestor::RequestAndWaitForTypes(
XAtom selection,
const std::vector<XAtom>& types) {
- for (std::vector<XAtom>::const_iterator it = types.begin();
- it != types.end(); ++it) {
+ for (auto it = types.begin(); it != types.end(); ++it) {
scoped_refptr<base::RefCountedMemory> data;
XAtom type = x11::None;
if (PerformBlockingConvertSelection(selection,
diff --git a/chromium/ui/base/x/selection_utils.cc b/chromium/ui/base/x/selection_utils.cc
index 8a413428fac..c0947ea7821 100644
--- a/chromium/ui/base/x/selection_utils.cc
+++ b/chromium/ui/base/x/selection_utils.cc
@@ -51,8 +51,7 @@ std::vector<::Atom> GetURIListAtomsFrom() {
void GetAtomIntersection(const std::vector< ::Atom>& desired,
const std::vector< ::Atom>& offered,
std::vector< ::Atom>* output) {
- for (std::vector< ::Atom>::const_iterator it = desired.begin();
- it != desired.end(); ++it) {
+ for (auto it = desired.begin(); it != desired.end(); ++it) {
if (base::ContainsValue(offered, *it))
output->push_back(*it);
}
@@ -121,9 +120,8 @@ void SelectionFormatMap::Insert(
ui::SelectionData SelectionFormatMap::GetFirstOf(
const std::vector< ::Atom>& requested_types) const {
- for (std::vector< ::Atom>::const_iterator it = requested_types.begin();
- it != requested_types.end(); ++it) {
- const_iterator data_it = data_.find(*it);
+ for (auto it = requested_types.begin(); it != requested_types.end(); ++it) {
+ auto data_it = data_.find(*it);
if (data_it != data_.end()) {
return SelectionData(data_it->first, data_it->second);
}
@@ -134,7 +132,7 @@ ui::SelectionData SelectionFormatMap::GetFirstOf(
std::vector< ::Atom> SelectionFormatMap::GetTypes() const {
std::vector< ::Atom> atoms;
- for (const_iterator it = data_.begin(); it != data_.end(); ++it)
+ for (auto it = data_.begin(); it != data_.end(); ++it)
atoms.push_back(it->first);
return atoms;
diff --git a/chromium/ui/base/x/x11_menu_list.cc b/chromium/ui/base/x/x11_menu_list.cc
index 876865b41d2..83a5522437b 100644
--- a/chromium/ui/base/x/x11_menu_list.cc
+++ b/chromium/ui/base/x/x11_menu_list.cc
@@ -34,8 +34,7 @@ void XMenuList::MaybeRegisterMenu(XID menu) {
}
void XMenuList::MaybeUnregisterMenu(XID menu) {
- std::vector<XID>::iterator iter = std::find(menus_.begin(), menus_.end(),
- menu);
+ auto iter = std::find(menus_.begin(), menus_.end(), menu);
if (iter == menus_.end())
return;
menus_.erase(iter);
diff --git a/chromium/ui/base/x/x11_util.cc b/chromium/ui/base/x/x11_util.cc
index 3b304881885..311b10e3d67 100644
--- a/chromium/ui/base/x/x11_util.cc
+++ b/chromium/ui/base/x/x11_util.cc
@@ -25,6 +25,7 @@
#include "base/memory/singleton.h"
#include "base/message_loop/message_loop_current.h"
#include "base/metrics/histogram_macros.h"
+#include "base/no_destructor.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
@@ -421,10 +422,10 @@ int CoalescePendingMotionEvents(const XEvent* xev, XEvent* last_event) {
}
void HideHostCursor() {
- CR_DEFINE_STATIC_LOCAL(XScopedCursor, invisible_cursor,
- (CreateInvisibleCursor(), gfx::GetXDisplay()));
+ static base::NoDestructor<XScopedCursor> invisible_cursor(
+ CreateInvisibleCursor(), gfx::GetXDisplay());
XDefineCursor(gfx::GetXDisplay(), DefaultRootWindow(gfx::GetXDisplay()),
- invisible_cursor.get());
+ invisible_cursor->get());
}
::Cursor CreateInvisibleCursor() {
diff --git a/chromium/ui/chromeos/BUILD.gn b/chromium/ui/chromeos/BUILD.gn
index bccdfb49937..7c4de18b330 100644
--- a/chromium/ui/chromeos/BUILD.gn
+++ b/chromium/ui/chromeos/BUILD.gn
@@ -34,6 +34,8 @@ component("chromeos") {
"//components/device_event_log",
"//components/onc",
"//mojo/public/cpp/bindings",
+ "//services/device/public/mojom",
+ "//services/service_manager/public/cpp",
"//services/ws/public/cpp",
"//services/ws/public/mojom",
"//skia",
diff --git a/chromium/ui/compositor/BUILD.gn b/chromium/ui/compositor/BUILD.gn
index e7f9be1ace3..ab830a68656 100644
--- a/chromium/ui/compositor/BUILD.gn
+++ b/chromium/ui/compositor/BUILD.gn
@@ -115,7 +115,7 @@ jumbo_component("compositor") {
}
}
-static_library("test_support") {
+jumbo_static_library("test_support") {
testonly = true
sources = [
"test/context_factories_for_test.cc",
diff --git a/chromium/ui/compositor/compositor.cc b/chromium/ui/compositor/compositor.cc
index 03ef3bf7315..8ae7efefd62 100644
--- a/chromium/ui/compositor/compositor.cc
+++ b/chromium/ui/compositor/compositor.cc
@@ -75,7 +75,7 @@ Compositor::Compositor(const viz::FrameSinkId& frame_sink_id,
force_software_compositor_(force_software_compositor),
layer_animator_collection_(this),
is_pixel_canvas_(enable_pixel_canvas),
- lock_manager_(task_runner, this),
+ lock_manager_(task_runner),
context_creation_weak_ptr_factory_(this) {
if (context_factory_private) {
auto* host_frame_sink_manager =
@@ -201,7 +201,7 @@ Compositor::Compositor(const viz::FrameSinkId& frame_sink_id,
params.settings = &settings;
params.main_task_runner = task_runner_;
params.mutator_host = animation_host_.get();
- host_ = cc::LayerTreeHost::CreateSingleThreaded(this, &params);
+ host_ = cc::LayerTreeHost::CreateSingleThreaded(this, std::move(params));
if (base::FeatureList::IsEnabled(features::kUiCompositorScrollWithLayers) &&
host_->GetInputHandler()) {
@@ -445,16 +445,6 @@ bool Compositor::GetScrollOffsetForLayer(cc::ElementId element_id,
input_handler->GetScrollOffsetForLayer(element_id, offset);
}
-void Compositor::SetAuthoritativeVSyncInterval(
- const base::TimeDelta& interval) {
- DCHECK_GT(interval.InMillisecondsF(), 0);
- refresh_rate_ =
- base::Time::kMillisecondsPerSecond / interval.InMillisecondsF();
- if (context_factory_private_)
- context_factory_private_->SetAuthoritativeVSyncInterval(this, interval);
- vsync_manager_->SetAuthoritativeVSyncInterval(interval);
-}
-
void Compositor::SetDisplayVSyncParameters(base::TimeTicks timebase,
base::TimeDelta interval) {
static bool is_frame_rate_limit_disabled =
@@ -596,8 +586,8 @@ static void SendDamagedRectsRecursive(ui::Layer* layer) {
SendDamagedRectsRecursive(child);
}
-void Compositor::UpdateLayerTreeHost(VisualStateUpdate requested_update) {
- if (!root_layer() || requested_update == VisualStateUpdate::kPrePaint)
+void Compositor::UpdateLayerTreeHost() {
+ if (!root_layer())
return;
SendDamagedRectsRecursive(root_layer());
}
@@ -661,10 +651,6 @@ void Compositor::SetLayerTreeDebugState(
host_->SetDebugState(debug_state);
}
-void Compositor::OnCompositorLockStateChanged(bool locked) {
- host_->SetDeferCommits(locked);
-}
-
void Compositor::RequestPresentationTimeForNextFrame(
PresentationTimeCallback callback) {
host_->RequestPresentationTimeForNextFrame(std::move(callback));
diff --git a/chromium/ui/compositor/compositor.h b/chromium/ui/compositor/compositor.h
index a1b6716fc79..b3905bdfa65 100644
--- a/chromium/ui/compositor/compositor.h
+++ b/chromium/ui/compositor/compositor.h
@@ -19,6 +19,7 @@
#include "base/time/time.h"
#include "build/build_config.h"
#include "cc/trees/element_id.h"
+#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_host_client.h"
#include "cc/trees/layer_tree_host_single_thread_client.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
@@ -49,7 +50,6 @@ class AnimationTimeline;
class Layer;
class LayerTreeDebugState;
class LayerTreeFrameSink;
-class LayerTreeHost;
class TaskGraphRunner;
}
@@ -151,8 +151,6 @@ class COMPOSITOR_EXPORT ContextFactoryPrivate {
const gfx::ColorSpace& blending_color_space,
const gfx::ColorSpace& output_color_space) = 0;
- virtual void SetAuthoritativeVSyncInterval(ui::Compositor* compositor,
- base::TimeDelta interval) = 0;
// Mac path for transporting vsync parameters to the display. Other platforms
// update it via the BrowserCompositorLayerTreeFrameSink directly.
virtual void SetDisplayVSyncParameters(ui::Compositor* compositor,
@@ -207,7 +205,6 @@ class COMPOSITOR_EXPORT ContextFactory {
// view hierarchy.
class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
public cc::LayerTreeHostSingleThreadClient,
- public CompositorLockManagerClient,
public viz::HostFrameSinkClient,
public ExternalBeginFrameClient {
public:
@@ -310,14 +307,6 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
gfx::ScrollOffset* offset) const;
bool ScrollLayerTo(cc::ElementId element_id, const gfx::ScrollOffset& offset);
- // The "authoritative" vsync interval, if provided, will override interval
- // reported from 3D context. This is typically the value reported by a more
- // reliable source, e.g, the platform display configuration.
- // In the particular case of ChromeOS -- this is the value queried through
- // XRandR, which is more reliable than the value queried through the 3D
- // context.
- void SetAuthoritativeVSyncInterval(const base::TimeDelta& interval);
-
// Most platforms set their vsync info via
// BrowerCompositorLayerTreeFrameSink::OnUpdateVSyncParametersFromGpu(), but
// Mac routes vsync info via the browser compositor instead through this path.
@@ -376,7 +365,8 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
CompositorLockClient* client,
base::TimeDelta timeout =
base::TimeDelta::FromMilliseconds(kCompositorLockTimeoutMs)) {
- return lock_manager_.GetCompositorLock(client, timeout);
+ return lock_manager_.GetCompositorLock(client, timeout,
+ host_->DeferCommits());
}
// Registers a callback that is run when the next frame successfully makes it
@@ -398,12 +388,9 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
void BeginMainFrame(const viz::BeginFrameArgs& args) override;
void BeginMainFrameNotExpectedSoon() override;
void BeginMainFrameNotExpectedUntil(base::TimeTicks time) override;
- void UpdateLayerTreeHost(VisualStateUpdate requested_update) override;
- void ApplyViewportDeltas(const gfx::Vector2dF& inner_delta,
- const gfx::Vector2dF& outer_delta,
- const gfx::Vector2dF& elastic_overscroll_delta,
- float page_scale,
- float top_controls_delta) override {}
+ void UpdateLayerTreeHost() override;
+ void ApplyViewportChanges(const cc::ApplyViewportChangesArgs& args) override {
+ }
void RecordWheelAndTouchScrollingCount(bool has_scrolled_by_wheel,
bool has_scrolled_by_touch) override {}
void RequestNewLayerTreeFrameSink() override;
@@ -417,6 +404,7 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
void DidPresentCompositorFrame(
uint32_t frame_token,
const gfx::PresentationFeedback& feedback) override {}
+ void RecordEndOfFrameMetrics(base::TimeTicks frame_begin_time) override {}
// cc::LayerTreeHostSingleThreadClient implementation.
void DidSubmitCompositorFrame() override;
@@ -426,9 +414,6 @@ class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
void OnFrameTokenChanged(uint32_t frame_token) override;
- // CompositorLockManagerClient implementation.
- void OnCompositorLockStateChanged(bool locked) override;
-
bool IsLocked() { return lock_manager_.IsLocked(); }
void SetOutputIsSecure(bool output_is_secure);
diff --git a/chromium/ui/compositor/compositor_lock.cc b/chromium/ui/compositor/compositor_lock.cc
index 02c609b7359..69a34775bfd 100644
--- a/chromium/ui/compositor/compositor_lock.cc
+++ b/chromium/ui/compositor/compositor_lock.cc
@@ -6,14 +6,13 @@
#include "base/bind.h"
#include "base/stl_util.h"
+#include "cc/trees/layer_tree_host.h"
namespace ui {
CompositorLockManager::CompositorLockManager(
- scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- CompositorLockManagerClient* client)
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner)
: task_runner_(std::move(task_runner)),
- client_(client),
weak_ptr_factory_(this),
lock_timeout_weak_ptr_factory_(this) {}
@@ -21,11 +20,12 @@ CompositorLockManager::~CompositorLockManager() = default;
std::unique_ptr<CompositorLock> CompositorLockManager::GetCompositorLock(
CompositorLockClient* client,
- base::TimeDelta timeout) {
+ base::TimeDelta timeout,
+ std::unique_ptr<cc::ScopedDeferCommits> scoped_defer_commits) {
// This uses the main WeakPtrFactory to break the connection from the lock to
// the CompositorLockManager when the CompositorLockManager is destroyed.
- auto lock =
- std::make_unique<CompositorLock>(client, weak_ptr_factory_.GetWeakPtr());
+ auto lock = std::make_unique<CompositorLock>(
+ client, weak_ptr_factory_.GetWeakPtr(), std::move(scoped_defer_commits));
bool was_empty = active_locks_.empty();
active_locks_.push_back(lock.get());
@@ -42,9 +42,6 @@ std::unique_ptr<CompositorLock> CompositorLockManager::GetCompositorLock(
}
}
- if (was_empty)
- client_->OnCompositorLockStateChanged(true);
-
if (should_extend_timeout) {
// The timeout task uses an independent WeakPtrFactory that is invalidated
// when all locks are ended to prevent the timeout from leaking into
@@ -61,7 +58,6 @@ std::unique_ptr<CompositorLock> CompositorLockManager::GetCompositorLock(
void CompositorLockManager::RemoveCompositorLock(CompositorLock* lock) {
base::Erase(active_locks_, lock);
if (active_locks_.empty()) {
- client_->OnCompositorLockStateChanged(false);
lock_timeout_weak_ptr_factory_.InvalidateWeakPtrs();
scheduled_timeout_ = base::TimeTicks();
}
@@ -75,16 +71,22 @@ void CompositorLockManager::TimeoutLocks() {
DCHECK(active_locks_.empty());
}
-CompositorLock::CompositorLock(CompositorLockClient* client,
- base::WeakPtr<CompositorLockManager> manager)
- : client_(client), manager_(std::move(manager)) {}
+CompositorLock::CompositorLock(
+ CompositorLockClient* client,
+ base::WeakPtr<CompositorLockManager> manager,
+ std::unique_ptr<cc::ScopedDeferCommits> scoped_defer_commits)
+ : client_(client),
+ scoped_defer_commits_(std::move(scoped_defer_commits)),
+ manager_(std::move(manager)) {}
CompositorLock::~CompositorLock() {
+ scoped_defer_commits_ = nullptr;
if (manager_)
manager_->RemoveCompositorLock(this);
}
void CompositorLock::TimeoutLock() {
+ scoped_defer_commits_ = nullptr;
manager_->RemoveCompositorLock(this);
manager_ = nullptr;
if (client_)
diff --git a/chromium/ui/compositor/compositor_lock.h b/chromium/ui/compositor/compositor_lock.h
index 370724c7ccc..2f08a190619 100644
--- a/chromium/ui/compositor/compositor_lock.h
+++ b/chromium/ui/compositor/compositor_lock.h
@@ -12,6 +12,10 @@
#include "base/single_thread_task_runner.h"
#include "ui/compositor/compositor_export.h"
+namespace cc {
+class ScopedDeferCommits;
+}
+
namespace ui {
class Compositor;
@@ -27,22 +31,12 @@ class CompositorLockClient {
virtual void CompositorLockTimedOut() = 0;
};
-// Implemented by clients which are locked by a compositor lock. Used by the
-// CompositorLockManager to notify their parent that lock state has changed.
-class CompositorLockManagerClient {
- public:
- virtual ~CompositorLockManagerClient() {}
-
- // Called when the lock state changes.
- virtual void OnCompositorLockStateChanged(bool locked) = 0;
-};
-
// A helper class used to manage compositor locks. Should be created/used by
// classes which want to provide out compositor locking.
class COMPOSITOR_EXPORT CompositorLockManager {
public:
- CompositorLockManager(scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- CompositorLockManagerClient* client);
+ CompositorLockManager(
+ scoped_refptr<base::SingleThreadTaskRunner> task_runner);
~CompositorLockManager();
// Creates a compositor lock. Returns NULL if it is not possible to lock at
@@ -50,7 +44,8 @@ class COMPOSITOR_EXPORT CompositorLockManager {
// timeout is null, then no timeout is used.
std::unique_ptr<CompositorLock> GetCompositorLock(
CompositorLockClient* client,
- base::TimeDelta timeout);
+ base::TimeDelta timeout,
+ std::unique_ptr<cc::ScopedDeferCommits> scoped_defer_commits);
void set_allow_locks_to_extend_timeout(bool allowed) {
allow_locks_to_extend_timeout_ = allowed;
@@ -71,8 +66,6 @@ class COMPOSITOR_EXPORT CompositorLockManager {
// The TaskRunner on which timeouts are run.
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
- // A client which is notified about lock state changes.
- CompositorLockManagerClient* client_ = nullptr;
// The estimated time that the locks will timeout.
base::TimeTicks scheduled_timeout_;
// If true, the |scheduled_timeout_| might be recalculated and extended.
@@ -99,8 +92,10 @@ class COMPOSITOR_EXPORT CompositorLock {
// The |client| is informed about events from the CompositorLock. The
// |delegate| is used to perform actual unlocking. If |timeout| is zero then
// no timeout is scheduled, else a timeout is scheduled on the |task_runner|.
- explicit CompositorLock(CompositorLockClient* client,
- base::WeakPtr<CompositorLockManager> manager);
+ explicit CompositorLock(
+ CompositorLockClient* client,
+ base::WeakPtr<CompositorLockManager> manager,
+ std::unique_ptr<cc::ScopedDeferCommits> scoped_defer_commits);
~CompositorLock();
private:
@@ -110,6 +105,7 @@ class COMPOSITOR_EXPORT CompositorLock {
void TimeoutLock();
CompositorLockClient* const client_;
+ std::unique_ptr<cc::ScopedDeferCommits> scoped_defer_commits_;
base::WeakPtr<CompositorLockManager> manager_;
DISALLOW_COPY_AND_ASSIGN(CompositorLock);
diff --git a/chromium/ui/compositor/compositor_lock_unittest.cc b/chromium/ui/compositor/compositor_lock_unittest.cc
index 6ca8cf842a7..4589fd63f08 100644
--- a/chromium/ui/compositor/compositor_lock_unittest.cc
+++ b/chromium/ui/compositor/compositor_lock_unittest.cc
@@ -5,6 +5,7 @@
#include <stdint.h>
#include "base/test/test_mock_time_task_runner.h"
+#include "cc/trees/layer_tree_host.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/compositor/compositor_lock.h"
@@ -16,15 +17,14 @@ namespace ui {
namespace {
// For tests that control time.
-class CompositorLockTest : public testing::Test,
- public ui::CompositorLockManagerClient {
+class CompositorLockTest : public testing::Test {
protected:
CompositorLockTest() {}
~CompositorLockTest() override {}
void SetUp() override {
task_runner_ = new base::TestMockTimeTaskRunner;
- lock_manager_ = std::make_unique<CompositorLockManager>(task_runner_, this);
+ lock_manager_ = std::make_unique<CompositorLockManager>(task_runner_);
}
base::TestMockTimeTaskRunner* task_runner() { return task_runner_.get(); }
@@ -33,11 +33,6 @@ class CompositorLockTest : public testing::Test,
void DestroyLockManager() { lock_manager_.reset(); }
- // ui::CompositorLockManagerClient implementation.
- void OnCompositorLockStateChanged(bool locked) override {
- EXPECT_EQ(locked, lock_manager_->IsLocked());
- }
-
protected:
scoped_refptr<base::TestMockTimeTaskRunner> task_runner_;
std::unique_ptr<CompositorLockManager> lock_manager_;
@@ -59,7 +54,7 @@ TEST_F(CompositorLockTest, LocksTimeOut) {
{
testing::StrictMock<MockCompositorLockClient> lock_client;
// This lock has a timeout.
- lock = lock_manager()->GetCompositorLock(&lock_client, timeout);
+ lock = lock_manager()->GetCompositorLock(&lock_client, timeout, nullptr);
EXPECT_TRUE(lock_manager()->IsLocked());
EXPECT_CALL(lock_client, CompositorLockTimedOut()).Times(1);
task_runner()->FastForwardBy(timeout);
@@ -70,7 +65,8 @@ TEST_F(CompositorLockTest, LocksTimeOut) {
{
testing::StrictMock<MockCompositorLockClient> lock_client;
// This lock has no timeout.
- lock = lock_manager()->GetCompositorLock(&lock_client, base::TimeDelta());
+ lock = lock_manager()->GetCompositorLock(&lock_client, base::TimeDelta(),
+ nullptr);
EXPECT_TRUE(lock_manager()->IsLocked());
EXPECT_CALL(lock_client, CompositorLockTimedOut()).Times(0);
task_runner()->FastForwardBy(timeout);
@@ -87,8 +83,8 @@ TEST_F(CompositorLockTest, MultipleLockClients) {
base::TimeDelta timeout = base::TimeDelta::FromMilliseconds(1);
// Both locks are grabbed from the Compositor with a separate client.
- lock1 = lock_manager()->GetCompositorLock(&lock_client1, timeout);
- lock2 = lock_manager()->GetCompositorLock(&lock_client2, timeout);
+ lock1 = lock_manager()->GetCompositorLock(&lock_client1, timeout, nullptr);
+ lock2 = lock_manager()->GetCompositorLock(&lock_client2, timeout, nullptr);
EXPECT_TRUE(lock_manager()->IsLocked());
// Both clients get notified of timeout.
EXPECT_CALL(lock_client1, CompositorLockTimedOut()).Times(1);
@@ -108,11 +104,11 @@ TEST_F(CompositorLockTest, ExtendingLifeOfLockDoesntUseDeadClient) {
// One lock is grabbed from the compositor with a client. The other
// extends its lifetime past that of the first.
- lock1 = lock_manager()->GetCompositorLock(&lock_client1, timeout);
+ lock1 = lock_manager()->GetCompositorLock(&lock_client1, timeout, nullptr);
EXPECT_TRUE(lock_manager()->IsLocked());
// This also locks the compositor and will do so past |lock1| ending.
- lock2 = lock_manager()->GetCompositorLock(&lock_client2, timeout);
+ lock2 = lock_manager()->GetCompositorLock(&lock_client2, timeout, nullptr);
// |lock1| is destroyed, so it won't timeout but |lock2| will.
lock1 = nullptr;
@@ -134,12 +130,12 @@ TEST_F(CompositorLockTest, AddingLocksDoesNotExtendTimeout) {
base::TimeDelta timeout2 = base::TimeDelta::FromMilliseconds(10);
// The first lock has a short timeout.
- lock1 = lock_manager()->GetCompositorLock(&lock_client1, timeout1);
+ lock1 = lock_manager()->GetCompositorLock(&lock_client1, timeout1, nullptr);
EXPECT_TRUE(lock_manager()->IsLocked());
// The second lock has a longer timeout, but since a lock is active,
// the first one is used for both.
- lock2 = lock_manager()->GetCompositorLock(&lock_client2, timeout2);
+ lock2 = lock_manager()->GetCompositorLock(&lock_client2, timeout2, nullptr);
EXPECT_CALL(lock_client1, CompositorLockTimedOut()).Times(1);
EXPECT_CALL(lock_client2, CompositorLockTimedOut()).Times(1);
@@ -158,13 +154,13 @@ TEST_F(CompositorLockTest, AllowAndExtendTimeout) {
base::TimeDelta timeout2 = base::TimeDelta::FromMilliseconds(10);
// The first lock has a short timeout.
- lock1 = lock_manager()->GetCompositorLock(&lock_client1, timeout1);
+ lock1 = lock_manager()->GetCompositorLock(&lock_client1, timeout1, nullptr);
EXPECT_TRUE(lock_manager()->IsLocked());
// Allow locks to extend timeout.
lock_manager()->set_allow_locks_to_extend_timeout(true);
// The second lock has a longer timeout, so the second one is used for both.
- lock2 = lock_manager()->GetCompositorLock(&lock_client2, timeout2);
+ lock2 = lock_manager()->GetCompositorLock(&lock_client2, timeout2, nullptr);
lock_manager()->set_allow_locks_to_extend_timeout(false);
EXPECT_CALL(lock_client1, CompositorLockTimedOut()).Times(0);
@@ -190,7 +186,7 @@ TEST_F(CompositorLockTest, ExtendingTimeoutStartingCreatedTime) {
base::TimeDelta timeout2 = base::TimeDelta::FromMilliseconds(10);
// The first lock has a short timeout.
- lock1 = lock_manager()->GetCompositorLock(&lock_client1, timeout1);
+ lock1 = lock_manager()->GetCompositorLock(&lock_client1, timeout1, nullptr);
EXPECT_TRUE(lock_manager()->IsLocked());
base::TimeDelta time_elapse = base::TimeDelta::FromMilliseconds(1);
@@ -201,7 +197,7 @@ TEST_F(CompositorLockTest, ExtendingTimeoutStartingCreatedTime) {
lock_manager()->set_allow_locks_to_extend_timeout(true);
// The second lock has a longer timeout, so the second one is used for both
// and start from the time second lock created.
- lock2 = lock_manager()->GetCompositorLock(&lock_client2, timeout2);
+ lock2 = lock_manager()->GetCompositorLock(&lock_client2, timeout2, nullptr);
lock_manager()->set_allow_locks_to_extend_timeout(false);
EXPECT_CALL(lock_client1, CompositorLockTimedOut()).Times(0);
@@ -227,13 +223,13 @@ TEST_F(CompositorLockTest, AllowButNotExtendTimeout) {
base::TimeDelta timeout2 = base::TimeDelta::FromMilliseconds(1);
// The first lock has a longer timeout.
- lock1 = lock_manager()->GetCompositorLock(&lock_client1, timeout1);
+ lock1 = lock_manager()->GetCompositorLock(&lock_client1, timeout1, nullptr);
EXPECT_TRUE(lock_manager()->IsLocked());
// Allow locks to extend timeout.
lock_manager()->set_allow_locks_to_extend_timeout(true);
// The second lock has a short timeout, so the first one is used for both.
- lock2 = lock_manager()->GetCompositorLock(&lock_client2, timeout2);
+ lock2 = lock_manager()->GetCompositorLock(&lock_client2, timeout2, nullptr);
lock_manager()->set_allow_locks_to_extend_timeout(false);
EXPECT_CALL(lock_client1, CompositorLockTimedOut()).Times(0);
@@ -258,7 +254,7 @@ TEST_F(CompositorLockTest, AllowingExtendDoesNotUseDeadClient) {
base::TimeDelta timeout1 = base::TimeDelta::FromMilliseconds(1);
base::TimeDelta timeout2 = base::TimeDelta::FromMilliseconds(10);
- lock1 = lock_manager()->GetCompositorLock(&lock_client1, timeout1);
+ lock1 = lock_manager()->GetCompositorLock(&lock_client1, timeout1, nullptr);
EXPECT_TRUE(lock_manager()->IsLocked());
EXPECT_CALL(lock_client1, CompositorLockTimedOut()).Times(1);
EXPECT_CALL(lock_client2, CompositorLockTimedOut()).Times(0);
@@ -269,7 +265,7 @@ TEST_F(CompositorLockTest, AllowingExtendDoesNotUseDeadClient) {
// Allow locks to extend timeout.
lock_manager()->set_allow_locks_to_extend_timeout(true);
// |lock1| is timed out already. The second lock can timeout on its own.
- lock2 = lock_manager()->GetCompositorLock(&lock_client2, timeout2);
+ lock2 = lock_manager()->GetCompositorLock(&lock_client2, timeout2, nullptr);
lock_manager()->set_allow_locks_to_extend_timeout(false);
EXPECT_TRUE(lock_manager()->IsLocked());
EXPECT_CALL(lock_client1, CompositorLockTimedOut()).Times(0);
@@ -284,7 +280,7 @@ TEST_F(CompositorLockTest, LockIsDestroyedDoesntTimeout) {
testing::StrictMock<MockCompositorLockClient> lock_client1;
std::unique_ptr<CompositorLock> lock1;
- lock1 = lock_manager()->GetCompositorLock(&lock_client1, timeout);
+ lock1 = lock_manager()->GetCompositorLock(&lock_client1, timeout, nullptr);
EXPECT_TRUE(lock_manager()->IsLocked());
// The CompositorLockClient is destroyed when |lock1| is released.
lock1 = nullptr;
@@ -305,7 +301,7 @@ TEST_F(CompositorLockTest, TimeoutEndsWhenLockEnds) {
base::TimeDelta timeout2 = base::TimeDelta::FromMilliseconds(10);
// The first lock has a short timeout.
- lock1 = lock_manager()->GetCompositorLock(&lock_client1, timeout1);
+ lock1 = lock_manager()->GetCompositorLock(&lock_client1, timeout1, nullptr);
EXPECT_TRUE(lock_manager()->IsLocked());
// But the first lock is ended before timeout.
lock1 = nullptr;
@@ -313,7 +309,7 @@ TEST_F(CompositorLockTest, TimeoutEndsWhenLockEnds) {
// The second lock has a longer timeout, and it should use that timeout,
// since the first lock is done.
- lock2 = lock_manager()->GetCompositorLock(&lock_client2, timeout2);
+ lock2 = lock_manager()->GetCompositorLock(&lock_client2, timeout2, nullptr);
EXPECT_TRUE(lock_manager()->IsLocked());
{
@@ -337,7 +333,8 @@ TEST_F(CompositorLockTest, CompositorLockOutlivesManager) {
testing::StrictMock<MockCompositorLockClient> lock_client1;
std::unique_ptr<CompositorLock> lock1;
- lock1 = lock_manager()->GetCompositorLock(&lock_client1, base::TimeDelta());
+ lock1 = lock_manager()->GetCompositorLock(&lock_client1, base::TimeDelta(),
+ nullptr);
// The compositor is destroyed before the lock.
DestroyLockManager();
// This doesn't crash.
diff --git a/chromium/ui/compositor/compositor_unittest.cc b/chromium/ui/compositor/compositor_unittest.cc
index 2abd4a84eca..c308e92d9a5 100644
--- a/chromium/ui/compositor/compositor_unittest.cc
+++ b/chromium/ui/compositor/compositor_unittest.cc
@@ -7,6 +7,7 @@
#include "base/macros.h"
#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
+#include "base/test/scoped_task_environment.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/viz/common/frame_sinks/begin_frame_args.h"
@@ -80,6 +81,12 @@ class CompositorTestWithMockedTime : public CompositorTest {
// For tests that run on a real MessageLoop with real time.
class CompositorTestWithMessageLoop : public CompositorTest {
+ public:
+ CompositorTestWithMessageLoop()
+ : scoped_task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
+ ~CompositorTestWithMessageLoop() override = default;
+
protected:
scoped_refptr<base::SingleThreadTaskRunner> CreateTaskRunner() override {
task_runner_ = base::ThreadTaskRunnerHandle::Get();
@@ -89,6 +96,7 @@ class CompositorTestWithMessageLoop : public CompositorTest {
base::SequencedTaskRunner* task_runner() { return task_runner_.get(); }
private:
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
scoped_refptr<base::SingleThreadTaskRunner> task_runner_;
};
diff --git a/chromium/ui/compositor/compositor_vsync_manager.cc b/chromium/ui/compositor/compositor_vsync_manager.cc
index 2bc25fc0275..6c537887b62 100644
--- a/chromium/ui/compositor/compositor_vsync_manager.cc
+++ b/chromium/ui/compositor/compositor_vsync_manager.cc
@@ -6,23 +6,12 @@
namespace ui {
-CompositorVSyncManager::CompositorVSyncManager()
- : authoritative_vsync_interval_(base::TimeDelta::FromSeconds(0)) {
-}
+CompositorVSyncManager::CompositorVSyncManager() = default;
CompositorVSyncManager::~CompositorVSyncManager() {}
-void CompositorVSyncManager::SetAuthoritativeVSyncInterval(
- base::TimeDelta interval) {
- authoritative_vsync_interval_ = interval;
- last_interval_ = interval;
- NotifyObservers(last_timebase_, last_interval_);
-}
-
void CompositorVSyncManager::UpdateVSyncParameters(base::TimeTicks timebase,
base::TimeDelta interval) {
- if (authoritative_vsync_interval_ != base::TimeDelta::FromSeconds(0))
- interval = authoritative_vsync_interval_;
last_timebase_ = timebase;
last_interval_ = interval;
NotifyObservers(timebase, interval);
diff --git a/chromium/ui/compositor/compositor_vsync_manager.h b/chromium/ui/compositor/compositor_vsync_manager.h
index 28769074026..3c4989bfc22 100644
--- a/chromium/ui/compositor/compositor_vsync_manager.h
+++ b/chromium/ui/compositor/compositor_vsync_manager.h
@@ -29,17 +29,8 @@ class COMPOSITOR_EXPORT CompositorVSyncManager
CompositorVSyncManager();
- // The "authoritative" vsync interval, if provided, will override |interval|
- // as reported by UpdateVSyncParameters() whenever it is called. This is
- // typically the value reported by a more reliable source, e.g. the platform
- // display configuration. In the particular case of ChromeOS -- this is the
- // value queried through XRandR, which is more reliable than the value
- // queried through the 3D context.
- void SetAuthoritativeVSyncInterval(base::TimeDelta interval);
-
// The vsync parameters consist of |timebase|, which is the platform timestamp
// of the last vsync, and |interval|, which is the interval between vsyncs.
- // |interval| may be overriden by SetAuthoritativeVSyncInterval() above.
void UpdateVSyncParameters(base::TimeTicks timebase,
base::TimeDelta interval);
@@ -57,7 +48,6 @@ class COMPOSITOR_EXPORT CompositorVSyncManager
base::TimeTicks last_timebase_;
base::TimeDelta last_interval_;
- base::TimeDelta authoritative_vsync_interval_;
DISALLOW_COPY_AND_ASSIGN(CompositorVSyncManager);
};
diff --git a/chromium/ui/compositor/host/host_context_factory_private.cc b/chromium/ui/compositor/host/host_context_factory_private.cc
index b6010d7b7c6..952525b7f82 100644
--- a/chromium/ui/compositor/host/host_context_factory_private.cc
+++ b/chromium/ui/compositor/host/host_context_factory_private.cc
@@ -4,11 +4,13 @@
#include "ui/compositor/host/host_context_factory_private.h"
+#include "base/command_line.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "cc/mojo_embedder/async_layer_tree_frame_sink.h"
#include "components/viz/client/hit_test_data_provider_draw_quad.h"
#include "components/viz/client/local_surface_id_provider.h"
+#include "components/viz/common/switches.h"
#include "components/viz/host/host_display_client.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "components/viz/host/renderer_settings_creation.h"
@@ -23,6 +25,10 @@
namespace ui {
+namespace {
+static const char* kBrowser = "Browser";
+} // namespace
+
HostContextFactoryPrivate::HostContextFactoryPrivate(
uint32_t client_id,
viz::HostFrameSinkManager* host_frame_sink_manager,
@@ -36,14 +42,14 @@ HostContextFactoryPrivate::HostContextFactoryPrivate(
HostContextFactoryPrivate::~HostContextFactoryPrivate() = default;
+void HostContextFactoryPrivate::AddCompositor(Compositor* compositor) {
+ compositor_data_map_.try_emplace(compositor);
+}
+
void HostContextFactoryPrivate::ConfigureCompositor(
- base::WeakPtr<Compositor> compositor_weak_ptr,
+ Compositor* compositor,
scoped_refptr<viz::ContextProvider> context_provider,
scoped_refptr<viz::RasterContextProvider> worker_context_provider) {
- Compositor* compositor = compositor_weak_ptr.get();
- if (!compositor)
- return;
-
bool gpu_compositing =
!is_gpu_compositing_disabled_ && !compositor->force_software_compositor();
@@ -69,13 +75,6 @@ void HostContextFactoryPrivate::ConfigureCompositor(
compositor_data.display_client->GetBoundPtr(resize_task_runner_)
.PassInterface();
-#if defined(GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW)
- gpu::SurfaceHandle surface_handle = compositor->widget();
-#else
- // TODO(kylechar): Fix this when we support macOS.
- gpu::SurfaceHandle surface_handle = gpu::kNullSurfaceHandle;
-#endif
-
// Initialize ExternalBeginFrameController client if enabled.
compositor_data.external_begin_frame_controller_client.reset();
if (compositor->external_begin_frames_enabled()) {
@@ -90,16 +89,24 @@ void HostContextFactoryPrivate::ConfigureCompositor(
}
root_params->frame_sink_id = compositor->frame_sink_id();
- root_params->widget = surface_handle;
+#if defined(GPU_SURFACE_HANDLE_IS_ACCELERATED_WINDOW)
+ root_params->widget = compositor->widget();
+#endif
root_params->gpu_compositing = gpu_compositing;
root_params->renderer_settings = renderer_settings_;
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ if (command_line->HasSwitch(switches::kDisableFrameRateLimit))
+ root_params->disable_frame_rate_limit = true;
+
// Connects the viz process end of CompositorFrameSink message pipes. The
// browser compositor may request a new CompositorFrameSink on context loss,
// which will destroy the existing CompositorFrameSink.
GetHostFrameSinkManager()->CreateRootCompositorFrameSink(
std::move(root_params));
compositor_data.display_private->Resize(compositor->size());
+ compositor_data.display_private->SetOutputIsSecure(
+ compositor_data.output_is_secure);
// Create LayerTreeFrameSink with the browser end of CompositorFrameSink.
cc::mojo_embedder::AsyncLayerTreeFrameSink::InitParams params;
@@ -113,7 +120,9 @@ void HostContextFactoryPrivate::ConfigureCompositor(
params.enable_surface_synchronization = true;
params.hit_test_data_provider =
std::make_unique<viz::HitTestDataProviderDrawQuad>(
- /*should_ask_for_child_region=*/false);
+ false /* should_ask_for_child_region */,
+ true /* root_accepts_events */);
+ params.client_name = kBrowser;
compositor->SetLayerTreeFrameSink(
std::make_unique<cc::mojo_embedder::AsyncLayerTreeFrameSink>(
std::move(context_provider), std::move(worker_context_provider),
@@ -122,8 +131,6 @@ void HostContextFactoryPrivate::ConfigureCompositor(
void HostContextFactoryPrivate::UnconfigureCompositor(Compositor* compositor) {
#if defined(OS_WIN)
- // TODO(crbug.com/791660): Make sure that GpuProcessHost::SetChildSurface()
- // doesn't crash the GPU process after parent is unregistered.
gfx::RenderingWindowManager::GetInstance()->UnregisterParent(
compositor->widget());
#endif
@@ -205,15 +212,6 @@ void HostContextFactoryPrivate::SetDisplayColorSpace(
output_color_space);
}
-void HostContextFactoryPrivate::SetAuthoritativeVSyncInterval(
- Compositor* compositor,
- base::TimeDelta interval) {
- auto iter = compositor_data_map_.find(compositor);
- if (iter == compositor_data_map_.end() || !iter->second.display_private)
- return;
- iter->second.display_private->SetAuthoritativeVSyncInterval(interval);
-}
-
void HostContextFactoryPrivate::SetDisplayVSyncParameters(
Compositor* compositor,
base::TimeTicks timebase,
@@ -239,9 +237,12 @@ void HostContextFactoryPrivate::IssueExternalBeginFrame(
void HostContextFactoryPrivate::SetOutputIsSecure(Compositor* compositor,
bool secure) {
auto iter = compositor_data_map_.find(compositor);
- if (iter == compositor_data_map_.end() || !iter->second.display_private)
+ if (iter == compositor_data_map_.end())
return;
- iter->second.display_private->SetOutputIsSecure(secure);
+ iter->second.output_is_secure = secure;
+
+ if (iter->second.display_private)
+ iter->second.display_private->SetOutputIsSecure(secure);
}
viz::FrameSinkManagerImpl* HostContextFactoryPrivate::GetFrameSinkManager() {
diff --git a/chromium/ui/compositor/host/host_context_factory_private.h b/chromium/ui/compositor/host/host_context_factory_private.h
index 76319deaa6d..69a441e9fbc 100644
--- a/chromium/ui/compositor/host/host_context_factory_private.h
+++ b/chromium/ui/compositor/host/host_context_factory_private.h
@@ -38,8 +38,13 @@ class HostContextFactoryPrivate : public ContextFactoryPrivate {
scoped_refptr<base::SingleThreadTaskRunner> resize_task_runner);
~HostContextFactoryPrivate() override;
+ // Call this when a compositor is created to ensure a data map entry exists
+ // for it, so that the data can be accessed before the compositor is
+ // configured. Could be called twice, e.g. if the GPU process crashes.
+ void AddCompositor(Compositor* compositor);
+
void ConfigureCompositor(
- base::WeakPtr<Compositor> compositor_weak_ptr,
+ Compositor* compositor,
scoped_refptr<viz::ContextProvider> context_provider,
scoped_refptr<viz::RasterContextProvider> worker_context_provider);
@@ -59,8 +64,6 @@ class HostContextFactoryPrivate : public ContextFactoryPrivate {
void SetDisplayColorSpace(Compositor* compositor,
const gfx::ColorSpace& blending_color_space,
const gfx::ColorSpace& output_color_space) override;
- void SetAuthoritativeVSyncInterval(Compositor* compositor,
- base::TimeDelta interval) override;
void SetDisplayVSyncParameters(Compositor* compositor,
base::TimeTicks timebase,
base::TimeDelta interval) override;
@@ -100,6 +103,10 @@ class HostContextFactoryPrivate : public ContextFactoryPrivate {
std::unique_ptr<ExternalBeginFrameControllerClientImpl>
external_begin_frame_controller_client;
+ // SetOutputIsSecure is called before the compositor is ready, so remember
+ // the status and apply it during configuration.
+ bool output_is_secure = false;
+
private:
DISALLOW_COPY_AND_ASSIGN(CompositorData);
};
diff --git a/chromium/ui/compositor/layer.cc b/chromium/ui/compositor/layer.cc
index 22c2dfe0125..f8f3f8cafdb 100644
--- a/chromium/ui/compositor/layer.cc
+++ b/chromium/ui/compositor/layer.cc
@@ -113,6 +113,7 @@ Layer::Layer()
device_scale_factor_(1.0f),
cache_render_surface_requests_(0),
deferred_paint_requests_(0),
+ backdrop_filter_quality_(1.0f),
trilinear_filtering_request_(0),
weak_ptr_factory_(this) {
CreateCcLayer();
@@ -141,6 +142,7 @@ Layer::Layer(LayerType type)
device_scale_factor_(1.0f),
cache_render_surface_requests_(0),
deferred_paint_requests_(0),
+ backdrop_filter_quality_(1.0f),
trilinear_filtering_request_(0),
weak_ptr_factory_(this) {
CreateCcLayer();
@@ -187,16 +189,14 @@ std::unique_ptr<Layer> Layer::Clone() const {
// cc::Layer state.
if (surface_layer_) {
- if (surface_layer_->primary_surface_id().is_valid()) {
- clone->SetShowPrimarySurface(
- surface_layer_->primary_surface_id(), frame_size_in_dip_,
- surface_layer_->background_color(),
- surface_layer_->deadline_in_frames()
- ? cc::DeadlinePolicy::UseSpecifiedDeadline(
- *surface_layer_->deadline_in_frames())
- : cc::DeadlinePolicy::UseDefaultDeadline(),
- surface_layer_->stretch_content_to_fill_bounds());
- }
+ clone->SetShowPrimarySurface(
+ surface_layer_->primary_surface_id(), frame_size_in_dip_,
+ surface_layer_->background_color(),
+ surface_layer_->deadline_in_frames()
+ ? cc::DeadlinePolicy::UseSpecifiedDeadline(
+ *surface_layer_->deadline_in_frames())
+ : cc::DeadlinePolicy::UseDefaultDeadline(),
+ surface_layer_->stretch_content_to_fill_bounds());
if (surface_layer_->fallback_surface_id())
clone->SetFallbackSurfaceId(*surface_layer_->fallback_surface_id());
} else if (type_ == LAYER_SOLID_COLOR) {
@@ -286,8 +286,7 @@ void Layer::Remove(Layer* child) {
if (compositor)
child->ResetCompositorForAnimatorsInTree(compositor);
- std::vector<Layer*>::iterator i =
- std::find(children_.begin(), children_.end(), child);
+ auto i = std::find(children_.begin(), children_.end(), child);
DCHECK(i != children_.end());
children_.erase(i);
child->parent_ = nullptr;
@@ -641,6 +640,7 @@ void Layer::SwitchToLayer(scoped_refptr<cc::Layer> new_layer) {
cc_layer_->SetContentsOpaque(fills_bounds_opaquely_);
cc_layer_->SetIsDrawable(type_ != LAYER_NOT_DRAWN);
cc_layer_->SetHideLayerAndSubtree(!visible_);
+ cc_layer_->SetBackdropFilterQuality(backdrop_filter_quality_);
cc_layer_->SetElementId(cc::ElementId(cc_layer_->id()));
SetLayerFilters();
@@ -676,6 +676,10 @@ void Layer::RemoveCacheRenderSurfaceRequest() {
cc_layer_->SetCacheRenderSurface(false);
}
+void Layer::SetBackdropFilterQuality(const float quality) {
+ backdrop_filter_quality_ = quality / GetDeviceScaleFactor();
+ cc_layer_->SetBackdropFilterQuality(backdrop_filter_quality_);
+}
void Layer::AddDeferredPaintRequest() {
++deferred_paint_requests_;
TRACE_COUNTER_ID1("ui", "DeferredPaintRequests", this,
@@ -850,7 +854,7 @@ void Layer::UpdateNinePatchLayerImage(const gfx::ImageSkia& image) {
// we don't need/want to, but we should address this in the future if it
// becomes an issue.
nine_patch_layer_->SetBitmap(
- image.GetRepresentation(device_scale_factor_).sk_bitmap());
+ image.GetRepresentation(device_scale_factor_).GetBitmap());
}
void Layer::UpdateNinePatchLayerAperture(const gfx::Rect& aperture_in_dip) {
diff --git a/chromium/ui/compositor/layer.h b/chromium/ui/compositor/layer.h
index 47c36b6dc4e..bda5eb12b82 100644
--- a/chromium/ui/compositor/layer.h
+++ b/chromium/ui/compositor/layer.h
@@ -428,6 +428,14 @@ class COMPOSITOR_EXPORT Layer : public LayerAnimationDelegate,
void AddDeferredPaintRequest();
void RemoveDeferredPaintRequest();
+ // |quality| is used as a multiplier to scale the temporary surface
+ // that might be created by the compositor to apply the backdrop filters.
+ // The filter will be applied on a surface |quality|^2 times the area of the
+ // original background.
+ // |quality| lower than one will decrease memory usage and increase
+ // performance.
+ void SetBackdropFilterQuality(const float quality);
+
bool IsPaintDeferredForTesting() const { return deferred_paint_requests_; }
// Request trilinear filtering for layer.
@@ -622,6 +630,8 @@ class COMPOSITOR_EXPORT Layer : public LayerAnimationDelegate,
// means we should paint the layer.
unsigned deferred_paint_requests_;
+ float backdrop_filter_quality_;
+
// The counter to maintain how many trilinear filtering requests we have. If
// the value > 0, means we need to perform trilinear filtering on the layer.
// If the value == 0, means we should not perform trilinear filtering on the
diff --git a/chromium/ui/compositor/layer_animation_observer.cc b/chromium/ui/compositor/layer_animation_observer.cc
index e5db5ecd5e5..2c77493b76d 100644
--- a/chromium/ui/compositor/layer_animation_observer.cc
+++ b/chromium/ui/compositor/layer_animation_observer.cc
@@ -159,8 +159,7 @@ void ImplicitAnimationObserver::UpdatePropertyAnimationStatus(
ImplicitAnimationObserver::AnimationStatus
ImplicitAnimationObserver::AnimationStatusForProperty(
LayerAnimationElement::AnimatableProperty property) const {
- PropertyAnimationStatusMap::const_iterator iter =
- property_animation_status_.find(property);
+ auto iter = property_animation_status_.find(property);
return iter == property_animation_status_.end() ? ANIMATION_STATUS_UNKNOWN :
iter->second;
}
diff --git a/chromium/ui/compositor/layer_animator.cc b/chromium/ui/compositor/layer_animator.cc
index d64ac0e6c1c..3c3efd6959c 100644
--- a/chromium/ui/compositor/layer_animator.cc
+++ b/chromium/ui/compositor/layer_animator.cc
@@ -414,7 +414,7 @@ void LayerAnimator::OnThreadedAnimationStarted(
// The call to GetRunningAnimation made above already purged deleted
// animations, so we are guaranteed that all the animations we iterate
// over now are alive.
- for (RunningAnimations::iterator iter = running_animations_.begin();
+ for (auto iter = running_animations_.begin();
iter != running_animations_.end(); ++iter) {
// Ensure that each sequence is only Started once, regardless of the
// number of sequences in the group that have threaded first elements.
@@ -541,7 +541,7 @@ LayerAnimationSequence* LayerAnimator::RemoveAnimation(
bool is_running = false;
// First remove from running animations
- for (RunningAnimations::iterator iter = running_animations_.begin();
+ for (auto iter = running_animations_.begin();
iter != running_animations_.end(); ++iter) {
if ((*iter).sequence() == sequence) {
running_animations_.erase(iter);
@@ -638,7 +638,7 @@ void LayerAnimator::ClearAnimations() {
LayerAnimator::RunningAnimation* LayerAnimator::GetRunningAnimation(
LayerAnimationElement::AnimatableProperty property) {
PurgeDeletedAnimations();
- for (RunningAnimations::iterator iter = running_animations_.begin();
+ for (auto iter = running_animations_.begin();
iter != running_animations_.end(); ++iter) {
if ((*iter).sequence()->properties() & property)
return &(*iter);
diff --git a/chromium/ui/compositor/layer_animator_collection.cc b/chromium/ui/compositor/layer_animator_collection.cc
index 54951f0c2a3..fd9873e6104 100644
--- a/chromium/ui/compositor/layer_animator_collection.cc
+++ b/chromium/ui/compositor/layer_animator_collection.cc
@@ -46,9 +46,7 @@ bool LayerAnimatorCollection::HasActiveAnimators() const {
void LayerAnimatorCollection::OnAnimationStep(base::TimeTicks now) {
last_tick_time_ = now;
std::set<scoped_refptr<LayerAnimator> > list = animators_;
- for (std::set<scoped_refptr<LayerAnimator> >::iterator iter = list.begin();
- iter != list.end();
- ++iter) {
+ for (auto iter = list.begin(); iter != list.end(); ++iter) {
// Make sure the animator is still valid.
if (animators_.count(*iter) > 0)
(*iter)->Step(now);
diff --git a/chromium/ui/compositor/layer_animator_unittest.cc b/chromium/ui/compositor/layer_animator_unittest.cc
index dc643869939..d735d2df611 100644
--- a/chromium/ui/compositor/layer_animator_unittest.cc
+++ b/chromium/ui/compositor/layer_animator_unittest.cc
@@ -10,7 +10,10 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/run_loop.h"
#include "base/strings/stringprintf.h"
+#include "base/test/scoped_mock_clock_override.h"
+#include "base/test/scoped_task_environment.h"
#include "base/time/time.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/mutator_host.h"
@@ -3250,6 +3253,8 @@ TEST(LayerAnimatorTest, AnimatorRemovedFromCollectionWhenLayerIsDestroyed) {
}
TEST(LayerAnimatorTest, LayerMovedBetweenCompositorsDuringAnimation) {
+ base::test::ScopedTaskEnvironment scoped_task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::UI);
bool enable_pixel_output = false;
ui::ContextFactory* context_factory = nullptr;
ui::ContextFactoryPrivate* context_factory_private = nullptr;
@@ -3314,6 +3319,8 @@ TEST(LayerAnimatorTest, LayerMovedBetweenCompositorsDuringAnimation) {
}
TEST(LayerAnimatorTest, ThreadedAnimationSurvivesIfLayerRemovedAdded) {
+ base::test::ScopedTaskEnvironment scoped_task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::UI);
bool enable_pixel_output = false;
ui::ContextFactory* context_factory = nullptr;
ui::ContextFactoryPrivate* context_factory_private = nullptr;
@@ -3355,6 +3362,115 @@ TEST(LayerAnimatorTest, ThreadedAnimationSurvivesIfLayerRemovedAdded) {
TerminateContextFactoryForTests();
}
+// A simple AnimationMetricsReporter class that remembers smoothness metric
+// when animation completes.
+class TestMetricsReporter : public ui::AnimationMetricsReporter {
+ public:
+ TestMetricsReporter() {}
+ ~TestMetricsReporter() override {}
+
+ bool report_called() { return report_called_; }
+ int value() const { return value_; }
+
+ protected:
+ void Report(int value) override {
+ value_ = value;
+ report_called_ = true;
+ }
+
+ private:
+ bool report_called_ = false;
+ int value_ = -1;
+
+ DISALLOW_COPY_AND_ASSIGN(TestMetricsReporter);
+};
+
+// Starts an animation and tests that incrementing compositor frame count can
+// be used to report animation smoothness metrics. This verifies that when an
+// animation is smooth (frame count matches refresh rate) that we receive a
+// smoothness value of 100.
+TEST(LayerAnimatorTest, ReportMetricsSmooth) {
+ base::ScopedMockClockOverride mock_clock_;
+ const base::TimeDelta kAnimationDuration =
+ base::TimeDelta::FromMilliseconds(100);
+
+ std::unique_ptr<Layer> root(new Layer(LAYER_SOLID_COLOR));
+ TestLayerAnimationDelegate delegate;
+ scoped_refptr<LayerAnimator> animator(CreateImplicitTestAnimator(&delegate));
+
+ std::unique_ptr<ui::LayerAnimationElement> animation_element =
+ ui::LayerAnimationElement::CreateColorElement(SK_ColorRED,
+ kAnimationDuration);
+ ui::LayerAnimationSequence* animation_sequence =
+ new ui::LayerAnimationSequence(std::move(animation_element));
+ TestMetricsReporter reporter;
+
+ animation_sequence->SetAnimationMetricsReporter(&reporter);
+ animator->StartAnimation(animation_sequence);
+ // Advances the frame count, simulating having produced 6 frames, and received
+ // an ack for each one. This implicitly simulates calling LayerAnimator::Step
+ // with an increased clock 6 times.
+ delegate.SetFrameNumber(6);
+
+ // Advancing the clock does not implicitly advance frame count. It allows the
+ // next call of LayerAnimator::Step to detect that the animation is finished,
+ // thus triggering the processing of metrics reporting.
+ mock_clock_.Advance(kAnimationDuration);
+ animator->Step(mock_clock_.NowTicks());
+
+ CHECK(reporter.report_called());
+ // With the clock being controlled, the animations should be smooth regardless
+ // of the test bots. Smoothness is based on a calculated duration of the
+ // animation when compared to the requested duration, as an integer
+ // percentage. With 100 being 100%. When the number of frames match the
+ // refresh rate, reporter should be notified of a smoothness of 100.
+ EXPECT_EQ(reporter.value(), 100);
+}
+
+// Starts an animation and tests that incrementing compositor frame count can
+// be used to report animation smoothness metrics. This verifies that when an
+// animation is not smooth (frame count doesn't match refresh rate) that we
+// receive a smoothness value that is not 100.
+TEST(LayerAnimatorTest, ReportMetricsNotSmooth) {
+ base::ScopedMockClockOverride mock_clock_;
+ const base::TimeDelta kAnimationDuration =
+ base::TimeDelta::FromMilliseconds(100);
+
+ std::unique_ptr<Layer> root(new Layer(LAYER_SOLID_COLOR));
+ TestLayerAnimationDelegate delegate;
+ scoped_refptr<LayerAnimator> animator(CreateImplicitTestAnimator(&delegate));
+
+ std::unique_ptr<ui::LayerAnimationElement> animation_element =
+ ui::LayerAnimationElement::CreateColorElement(SK_ColorRED,
+ kAnimationDuration);
+ ui::LayerAnimationSequence* animation_sequence =
+ new ui::LayerAnimationSequence(std::move(animation_element));
+ TestMetricsReporter reporter;
+
+ animation_sequence->SetAnimationMetricsReporter(&reporter);
+ animator->StartAnimation(animation_sequence);
+ // Advances the frame count, simulating having produced 1 frame, and received
+ // an ack for it. This implicitly simulates calling LayerAnimator::Step with
+ // an increased clock 1 time.
+ delegate.SetFrameNumber(1);
+
+ // Advancing the clock does not implicitly advance frame count. It allows the
+ // next call of LayerAnimator::Step to detect that the animation is finished,
+ // thus triggering the processing of metrics reporting.
+ mock_clock_.Advance(kAnimationDuration);
+ animator->Step(mock_clock_.NowTicks());
+
+ CHECK(reporter.report_called());
+ // With the clock being controlled, we have direct control of the smoothness
+ // regardless of the test bots. Smoothness is based on a calculated duration
+ // of the animation when compared to the requested duration, as an integer
+ // percentage. With 100 being 100%. With a single frame being generated over
+ // 100ms, the reporter should be notified of a smoothness matching the
+ // interval between refreshes.
+ int expected = base::Time::kMillisecondsPerSecond / delegate.GetRefreshRate();
+ EXPECT_EQ(reporter.value(), expected);
+}
+
class LayerOwnerAnimationObserver : public LayerAnimationObserver {
public:
explicit LayerOwnerAnimationObserver(LayerAnimator* animator)
diff --git a/chromium/ui/compositor/layer_unittest.cc b/chromium/ui/compositor/layer_unittest.cc
index 57951bf6f4f..190cf162069 100644
--- a/chromium/ui/compositor/layer_unittest.cc
+++ b/chromium/ui/compositor/layer_unittest.cc
@@ -20,6 +20,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/test/scoped_task_environment.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "cc/animation/animation_events.h"
@@ -129,7 +130,9 @@ class DrawFadedStringLayerDelegate : public LayerDelegate {
class LayerWithRealCompositorTest : public testing::Test {
public:
- LayerWithRealCompositorTest() {
+ LayerWithRealCompositorTest()
+ : scoped_task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::UI) {
if (base::PathService::Get(gfx::DIR_TEST_DATA, &test_data_directory_)) {
test_data_directory_ = test_data_directory_.AppendASCII("compositor");
} else {
@@ -271,6 +274,7 @@ class LayerWithRealCompositorTest : public testing::Test {
std::unique_ptr<base::RunLoop> run_loop_;
};
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
std::unique_ptr<TestCompositorHost> compositor_host_;
// The root directory for test files.
@@ -489,7 +493,9 @@ TEST_F(LayerWithRealCompositorTest, Hierarchy) {
class LayerWithDelegateTest : public testing::Test {
public:
- LayerWithDelegateTest() {}
+ LayerWithDelegateTest()
+ : scoped_task_environment_(
+ base::test::ScopedTaskEnvironment::MainThreadType::UI) {}
~LayerWithDelegateTest() override {}
// Overridden from testing::Test:
@@ -556,6 +562,7 @@ class LayerWithDelegateTest : public testing::Test {
}
private:
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
std::unique_ptr<TestCompositorHost> compositor_host_;
DISALLOW_COPY_AND_ASSIGN(LayerWithDelegateTest);
@@ -903,34 +910,22 @@ TEST_F(LayerWithDelegateTest, SurfaceLayerCloneAndMirror) {
layer->SetShowPrimarySurface(surface_id_one, gfx::Size(10, 10), SK_ColorWHITE,
cc::DeadlinePolicy::UseDefaultDeadline(), false);
EXPECT_FALSE(layer->StretchContentToFillBounds());
- EXPECT_TRUE(static_cast<cc::SurfaceLayer*>(layer->cc_layer_for_testing())
- ->surface_hit_testable());
auto clone = layer->Clone();
EXPECT_FALSE(clone->StretchContentToFillBounds());
- EXPECT_TRUE(static_cast<cc::SurfaceLayer*>(clone->cc_layer_for_testing())
- ->surface_hit_testable());
auto mirror = layer->Mirror();
EXPECT_FALSE(mirror->StretchContentToFillBounds());
- EXPECT_TRUE(static_cast<cc::SurfaceLayer*>(mirror->cc_layer_for_testing())
- ->surface_hit_testable());
local_surface_id = allocator.GenerateId();
viz::SurfaceId surface_id_two(arbitrary_frame_sink, local_surface_id);
layer->SetShowPrimarySurface(surface_id_two, gfx::Size(10, 10), SK_ColorWHITE,
cc::DeadlinePolicy::UseDefaultDeadline(), true);
EXPECT_TRUE(layer->StretchContentToFillBounds());
- EXPECT_TRUE(static_cast<cc::SurfaceLayer*>(layer->cc_layer_for_testing())
- ->surface_hit_testable());
clone = layer->Clone();
EXPECT_TRUE(clone->StretchContentToFillBounds());
- EXPECT_TRUE(static_cast<cc::SurfaceLayer*>(clone->cc_layer_for_testing())
- ->surface_hit_testable());
mirror = layer->Mirror();
EXPECT_TRUE(mirror->StretchContentToFillBounds());
- EXPECT_TRUE(static_cast<cc::SurfaceLayer*>(mirror->cc_layer_for_testing())
- ->surface_hit_testable());
}
class LayerWithNullDelegateTest : public LayerWithDelegateTest {
@@ -2675,53 +2670,6 @@ TEST_F(LayerWithRealCompositorTest, CompositorAnimationObserverTest) {
EXPECT_TRUE(animation_observer.shutdown());
}
-// A simple AnimationMetricsReporter class that remembers smoothness metric
-// when animation completes.
-class TestMetricsReporter : public ui::AnimationMetricsReporter {
- public:
- TestMetricsReporter() {}
- ~TestMetricsReporter() override {}
-
- bool report_called() { return report_called_; }
- int value() const { return value_; }
-
- protected:
- void Report(int value) override {
- value_ = value;
- report_called_ = true;
- }
-
- private:
- bool report_called_ = false;
- int value_ = -1;
-
- DISALLOW_COPY_AND_ASSIGN(TestMetricsReporter);
-};
-
-// Starts an animation and tests that incrementing compositor frame count can
-// be used to report animation smoothness metrics.
-// Flaky test crbug.com/709080
-TEST_F(LayerWithRealCompositorTest, DISABLED_ReportMetrics) {
- std::unique_ptr<Layer> root(CreateLayer(LAYER_SOLID_COLOR));
- GetCompositor()->SetRootLayer(root.get());
- LayerAnimator* animator = root->GetAnimator();
- std::unique_ptr<ui::LayerAnimationElement> animation_element =
- ui::LayerAnimationElement::CreateColorElement(
- SK_ColorRED, base::TimeDelta::FromMilliseconds(100));
- ui::LayerAnimationSequence* animation_sequence =
- new ui::LayerAnimationSequence(std::move(animation_element));
- TestMetricsReporter reporter;
- animation_sequence->SetAnimationMetricsReporter(&reporter);
- animator->StartAnimation(animation_sequence);
- while (!reporter.report_called())
- WaitForSwap();
- ResetCompositor();
- // Even though most of the time 100% smooth animations are expected, on the
- // test bots this cannot be guaranteed. Therefore simply check that some
- // value was reported.
- EXPECT_GT(reporter.value(), 0);
-}
-
TEST(LayerDebugInfoTest, LayerNameDoesNotClobber) {
Layer layer(LAYER_NOT_DRAWN);
layer.set_name("foo");
diff --git a/chromium/ui/display/BUILD.gn b/chromium/ui/display/BUILD.gn
index bd7de89cf5a..e5185ec1c71 100644
--- a/chromium/ui/display/BUILD.gn
+++ b/chromium/ui/display/BUILD.gn
@@ -2,11 +2,12 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
+import("//build/config/jumbo.gni")
import("//build/config/ui.gni")
import("//testing/test.gni")
import("//ui/display/display.gni")
-component("display") {
+jumbo_component("display") {
sources = [
"display.cc",
"display.h",
@@ -47,12 +48,17 @@ component("display") {
"win/screen_win.h",
"win/screen_win_display.cc",
"win/screen_win_display.h",
+ "win/uwp_text_scale_factor.cc",
+ "win/uwp_text_scale_factor.h",
]
+ configs += [ "//build/config/compiler:wexit_time_destructors" ]
+
defines = [ "DISPLAY_IMPLEMENTATION" ]
public_deps = [
"//ui/display/types",
+ "//ui/gfx:color_space",
"//ui/gfx:gfx",
]
@@ -101,7 +107,7 @@ component("display_manager_test_api") {
]
}
-static_library("test_support") {
+jumbo_static_library("test_support") {
testonly = true
sources = [
"test/display_matchers.cc",
diff --git a/chromium/ui/display/display.cc b/chromium/ui/display/display.cc
index 324148f8469..68a5b3a9cc2 100644
--- a/chromium/ui/display/display.cc
+++ b/chromium/ui/display/display.cc
@@ -58,6 +58,33 @@ float GetForcedDeviceScaleFactorImpl() {
int64_t internal_display_id_ = -1;
+gfx::ColorSpace ForcedColorProfileStringToColorSpace(const std::string& value) {
+ if (value == "srgb")
+ return gfx::ColorSpace::CreateSRGB();
+ if (value == "display-p3-d65")
+ return gfx::ColorSpace::CreateDisplayP3D65();
+ if (value == "scrgb-linear")
+ return gfx::ColorSpace::CreateSCRGBLinear();
+ if (value == "extended-srgb")
+ return gfx::ColorSpace::CreateExtendedSRGB();
+ if (value == "generic-rgb") {
+ return gfx::ColorSpace(gfx::ColorSpace::PrimaryID::APPLE_GENERIC_RGB,
+ gfx::ColorSpace::TransferID::GAMMA18);
+ }
+ if (value == "color-spin-gamma24") {
+ // Run this color profile through an ICC profile. The resulting color space
+ // is slightly different from the input color space, and removing the ICC
+ // profile would require rebaselineing many layout tests.
+ gfx::ColorSpace color_space(
+ gfx::ColorSpace::PrimaryID::WIDE_GAMUT_COLOR_SPIN,
+ gfx::ColorSpace::TransferID::GAMMA24);
+ return gfx::ICCProfile::FromParametricColorSpace(color_space)
+ .GetColorSpace();
+ }
+ LOG(ERROR) << "Invalid forced color profile: \"" << value << "\"";
+ return gfx::ColorSpace::CreateSRGB();
+}
+
} // namespace
bool CompareDisplayIds(int64_t id1, int64_t id2) {
@@ -103,42 +130,33 @@ void Display::SetForceDeviceScaleFactor(double dsf) {
}
// static
-gfx::ColorSpace Display::GetForcedColorProfile() {
- DCHECK(HasForceColorProfile());
+gfx::ColorSpace Display::GetForcedDisplayColorProfile() {
+ DCHECK(HasForceDisplayColorProfile());
std::string value =
base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
- switches::kForceColorProfile);
- if (value == "srgb") {
- return gfx::ColorSpace::CreateSRGB();
- } else if (value == "display-p3-d65") {
- return gfx::ColorSpace::CreateDisplayP3D65();
- } else if (value == "scrgb-linear") {
- return gfx::ColorSpace::CreateSCRGBLinear();
- } else if (value == "extended-srgb") {
- return gfx::ColorSpace::CreateExtendedSRGB();
- } else if (value == "generic-rgb") {
- return gfx::ColorSpace(gfx::ColorSpace::PrimaryID::APPLE_GENERIC_RGB,
- gfx::ColorSpace::TransferID::GAMMA18);
- } else if (value == "color-spin-gamma24") {
- // Run this color profile through an ICC profile. The resulting color space
- // is slightly different from the input color space, and removing the ICC
- // profile would require rebaselineing many layout tests.
- gfx::ColorSpace color_space(
- gfx::ColorSpace::PrimaryID::WIDE_GAMUT_COLOR_SPIN,
- gfx::ColorSpace::TransferID::GAMMA24);
- return gfx::ICCProfile::FromParametricColorSpace(color_space)
- .GetColorSpace();
- }
- LOG(ERROR) << "Invalid forced color profile";
- return gfx::ColorSpace::CreateSRGB();
+ switches::kForceDisplayColorProfile);
+ return ForcedColorProfileStringToColorSpace(value);
}
// static
-bool Display::HasForceColorProfile() {
- static bool has_force_color_profile =
- base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kForceColorProfile);
- return has_force_color_profile;
+bool Display::HasForceDisplayColorProfile() {
+ return base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kForceDisplayColorProfile);
+}
+
+// static
+gfx::ColorSpace Display::GetForcedRasterColorProfile() {
+ DCHECK(HasForceRasterColorProfile());
+ std::string value =
+ base::CommandLine::ForCurrentProcess()->GetSwitchValueASCII(
+ switches::kForceRasterColorProfile);
+ return ForcedColorProfileStringToColorSpace(value);
+}
+
+// static
+bool Display::HasForceRasterColorProfile() {
+ return base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kForceRasterColorProfile);
}
// static
@@ -196,8 +214,8 @@ Display::Display(int64_t id, const gfx::Rect& bounds)
color_space_(gfx::ColorSpace::CreateSRGB()),
color_depth_(DEFAULT_BITS_PER_PIXEL),
depth_per_component_(DEFAULT_BITS_PER_COMPONENT) {
- if (HasForceColorProfile())
- SetColorSpaceAndDepth(GetForcedColorProfile());
+ if (HasForceDisplayColorProfile())
+ SetColorSpaceAndDepth(GetForcedDisplayColorProfile());
#if defined(USE_AURA)
SetScaleAndBounds(device_scale_factor_, bounds);
#endif
diff --git a/chromium/ui/display/display.h b/chromium/ui/display/display.h
index a788c0e64e7..53f3e95c824 100644
--- a/chromium/ui/display/display.h
+++ b/chromium/ui/display/display.h
@@ -94,11 +94,19 @@ class DISPLAY_EXPORT Display final {
// Returns the forced display color profile, which is given by
// "--force-color-profile".
- static gfx::ColorSpace GetForcedColorProfile();
+ static gfx::ColorSpace GetForcedDisplayColorProfile();
// Indicates if a display color profile is being explicitly enforced from the
// command line via "--force-color-profile".
- static bool HasForceColorProfile();
+ static bool HasForceDisplayColorProfile();
+
+ // Returns the forced raster color profile, which is given by
+ // "--force-raster-color-profile".
+ static gfx::ColorSpace GetForcedRasterColorProfile();
+
+ // Indicates if a raster color profile is being explicitly enforced from the
+ // command line via "--force-raster-color-profile".
+ static bool HasForceRasterColorProfile();
// Indicates if the display color profile being forced should be ensured to
// be in use by the operating system as well.
diff --git a/chromium/ui/display/display_change_notifier.cc b/chromium/ui/display/display_change_notifier.cc
index 3a5cfd0c830..9c1e6eca641 100644
--- a/chromium/ui/display/display_change_notifier.cc
+++ b/chromium/ui/display/display_change_notifier.cc
@@ -44,7 +44,7 @@ void DisplayChangeNotifier::NotifyDisplaysChanged(
const std::vector<Display>& old_displays,
const std::vector<Display>& new_displays) {
// Display present in old_displays but not in new_displays has been removed.
- std::vector<Display>::const_iterator old_it = old_displays.begin();
+ auto old_it = old_displays.begin();
for (; old_it != old_displays.end(); ++old_it) {
if (std::find_if(new_displays.begin(), new_displays.end(),
DisplayComparator(*old_it)) == new_displays.end()) {
@@ -55,10 +55,10 @@ void DisplayChangeNotifier::NotifyDisplaysChanged(
// Display present in new_displays but not in old_displays has been added.
// Display present in both might have been modified.
- for (std::vector<Display>::const_iterator new_it = new_displays.begin();
- new_it != new_displays.end(); ++new_it) {
- std::vector<Display>::const_iterator old_it = std::find_if(
- old_displays.begin(), old_displays.end(), DisplayComparator(*new_it));
+ for (auto new_it = new_displays.begin(); new_it != new_displays.end();
+ ++new_it) {
+ auto old_it = std::find_if(old_displays.begin(), old_displays.end(),
+ DisplayComparator(*new_it));
if (old_it == old_displays.end()) {
for (DisplayObserver& observer : observer_list_)
diff --git a/chromium/ui/display/display_change_notifier.h b/chromium/ui/display/display_change_notifier.h
index 5c61896bd76..6e3c436c67d 100644
--- a/chromium/ui/display/display_change_notifier.h
+++ b/chromium/ui/display/display_change_notifier.h
@@ -32,7 +32,7 @@ class DISPLAY_EXPORT DisplayChangeNotifier {
private:
// The observers that need to be notified when a display is modified, added
// or removed.
- base::ObserverList<DisplayObserver>::Unchecked observer_list_;
+ base::ObserverList<DisplayObserver> observer_list_;
DISALLOW_COPY_AND_ASSIGN(DisplayChangeNotifier);
};
diff --git a/chromium/ui/display/display_list.h b/chromium/ui/display/display_list.h
index 91f0042594a..295dc3fb57a 100644
--- a/chromium/ui/display/display_list.h
+++ b/chromium/ui/display/display_list.h
@@ -82,9 +82,7 @@ class DISPLAY_EXPORT DisplayList {
// Removes the Display with the specified id.
void RemoveDisplay(int64_t id);
- base::ObserverList<DisplayObserver>::Unchecked* observers() {
- return &observers_;
- }
+ base::ObserverList<DisplayObserver>* observers() { return &observers_; }
private:
friend class DisplayListObserverLock;
@@ -101,7 +99,7 @@ class DISPLAY_EXPORT DisplayList {
std::vector<Display> displays_;
int primary_display_index_ = -1;
- base::ObserverList<DisplayObserver>::Unchecked observers_;
+ base::ObserverList<DisplayObserver> observers_;
int observer_suspend_lock_count_ = 0;
diff --git a/chromium/ui/display/display_observer.h b/chromium/ui/display/display_observer.h
index 568852db6af..e487ce3fe5b 100644
--- a/chromium/ui/display/display_observer.h
+++ b/chromium/ui/display/display_observer.h
@@ -7,6 +7,7 @@
#include <stdint.h>
+#include "base/observer_list_types.h"
#include "ui/display/display_export.h"
namespace display {
@@ -15,7 +16,7 @@ class Display;
// Observers for display configuration changes.
// TODO(oshima): consolidate |WorkAreaWatcherObserver| and
// |DisplaySettingsProvier|. crbug.com/122863.
-class DISPLAY_EXPORT DisplayObserver {
+class DISPLAY_EXPORT DisplayObserver : public base::CheckedObserver {
public:
enum DisplayMetric {
DISPLAY_METRIC_NONE = 0,
@@ -48,7 +49,7 @@ class DISPLAY_EXPORT DisplayObserver {
uint32_t changed_metrics);
protected:
- virtual ~DisplayObserver();
+ ~DisplayObserver() override;
};
} // namespace display
diff --git a/chromium/ui/display/display_switches.cc b/chromium/ui/display/display_switches.cc
index de1e0577e5d..40b7fa176db 100644
--- a/chromium/ui/display/display_switches.cc
+++ b/chromium/ui/display/display_switches.cc
@@ -25,7 +25,11 @@ const char kEnsureForcedColorProfile[] = "ensure-forced-color-profile";
// Force all monitors to be treated as though they have the specified color
// profile. Accepted values are "srgb" and "generic-rgb" (currently used by Mac
// layout tests) and "color-spin-gamma24" (used by layout tests).
-const char kForceColorProfile[] = "force-color-profile";
+const char kForceDisplayColorProfile[] = "force-color-profile";
+
+// Force rastering to take place in the specified color profile. Accepted values
+// are the same as for the kForceDisplayColorProfile case above.
+const char kForceRasterColorProfile[] = "force-raster-color-profile";
// Overrides the device scale factor for the browser UI and the contents.
const char kForceDeviceScaleFactor[] = "force-device-scale-factor";
diff --git a/chromium/ui/display/display_switches.h b/chromium/ui/display/display_switches.h
index da146eb5359..0079182e025 100644
--- a/chromium/ui/display/display_switches.h
+++ b/chromium/ui/display/display_switches.h
@@ -16,8 +16,9 @@ namespace switches {
DISPLAY_EXPORT extern const char kDisableMultiMirroring[];
DISPLAY_EXPORT extern const char kEnableSoftwareMirroring[];
DISPLAY_EXPORT extern const char kEnsureForcedColorProfile[];
-DISPLAY_EXPORT extern const char kForceColorProfile[];
DISPLAY_EXPORT extern const char kForceDeviceScaleFactor[];
+DISPLAY_EXPORT extern const char kForceDisplayColorProfile[];
+DISPLAY_EXPORT extern const char kForceRasterColorProfile[];
// TODO(kylechar): This overlaps with --screen-config. Unify flags and remove.
DISPLAY_EXPORT extern const char kHostWindowBounds[];
DISPLAY_EXPORT extern const char kScreenConfig[];
diff --git a/chromium/ui/display/mac/screen_mac.mm b/chromium/ui/display/mac/screen_mac.mm
index 99a12851125..ec1fc4edf55 100644
--- a/chromium/ui/display/mac/screen_mac.mm
+++ b/chromium/ui/display/mac/screen_mac.mm
@@ -93,7 +93,7 @@ Display BuildDisplayForScreen(NSScreen* screen) {
}
icc_profile.HistogramDisplay(display.id());
gfx::ColorSpace screen_color_space = icc_profile.GetColorSpace();
- if (Display::HasForceColorProfile()) {
+ if (Display::HasForceDisplayColorProfile()) {
if (Display::HasEnsureForcedColorProfile()) {
CHECK_EQ(screen_color_space, display.color_space())
<< "The display's color space does not match the color space that "
diff --git a/chromium/ui/display/manager/BUILD.gn b/chromium/ui/display/manager/BUILD.gn
index f43c0dea56d..fda805f36f3 100644
--- a/chromium/ui/display/manager/BUILD.gn
+++ b/chromium/ui/display/manager/BUILD.gn
@@ -52,6 +52,8 @@ jumbo_component("manager") {
]
}
+ configs += [ "//build/config/compiler:wexit_time_destructors" ]
+
public_deps = [
"//ui/display",
]
diff --git a/chromium/ui/display/manager/display_manager.cc b/chromium/ui/display/manager/display_manager.cc
index 06770862f57..06e2cff23c5 100644
--- a/chromium/ui/display/manager/display_manager.cc
+++ b/chromium/ui/display/manager/display_manager.cc
@@ -18,6 +18,7 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
+#include "base/no_destructor.h"
#include "base/run_loop.h"
#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
@@ -394,9 +395,9 @@ const DisplayLayout& DisplayManager::GetCurrentDisplayLayout() const {
}
DLOG(ERROR) << "DisplayLayout is requested for single display";
// On release build, just fallback to default instead of blowing up.
- static DisplayLayout layout;
- layout.primary_id = active_display_list_[0].id();
- return layout;
+ static base::NoDestructor<DisplayLayout> layout;
+ layout->primary_id = active_display_list_[0].id();
+ return *layout;
}
const DisplayLayout& DisplayManager::GetCurrentResolvedDisplayLayout() const {
@@ -714,8 +715,7 @@ void DisplayManager::RegisterDisplayRotationProperties(
bool DisplayManager::GetSelectedModeForDisplayId(
int64_t display_id,
ManagedDisplayMode* mode) const {
- std::map<int64_t, ManagedDisplayMode>::const_iterator iter =
- display_modes_.find(display_id);
+ auto iter = display_modes_.find(display_id);
if (iter == display_modes_.end())
return false;
*mode = iter->second;
@@ -741,8 +741,7 @@ bool DisplayManager::IsDisplayUIScalingEnabled() const {
}
gfx::Insets DisplayManager::GetOverscanInsets(int64_t display_id) const {
- std::map<int64_t, ManagedDisplayInfo>::const_iterator it =
- display_info_.find(display_id);
+ auto it = display_info_.find(display_id);
return (it != display_info_.end()) ? it->second.overscan_insets_in_dip()
: gfx::Insets();
}
@@ -943,7 +942,7 @@ void DisplayManager::UpdateDisplaysWith(
std::map<size_t, uint32_t> display_changes;
std::vector<size_t> added_display_indices;
- Displays::iterator curr_iter = active_display_list_.begin();
+ auto curr_iter = active_display_list_.begin();
DisplayInfoList::const_iterator new_info_iter = new_display_info_list.begin();
while (curr_iter != active_display_list_.end() ||
@@ -1068,8 +1067,8 @@ void DisplayManager::UpdateDisplaysWith(
bool notify_primary_change =
delegate_ ? old_primary.id() != screen_->GetPrimaryDisplay().id() : false;
- for (std::map<size_t, uint32_t>::iterator iter = display_changes.begin();
- iter != display_changes.end(); ++iter) {
+ for (auto iter = display_changes.begin(); iter != display_changes.end();
+ ++iter) {
uint32_t metrics = iter->second;
const Display& updated_display = active_display_list_[iter->first];
@@ -1240,8 +1239,7 @@ const ManagedDisplayInfo& DisplayManager::GetDisplayInfo(
int64_t display_id) const {
DCHECK_NE(kInvalidDisplayId, display_id);
- std::map<int64_t, ManagedDisplayInfo>::const_iterator iter =
- display_info_.find(display_id);
+ auto iter = display_info_.find(display_id);
CHECK(iter != display_info_.end()) << display_id;
return iter->second;
}
@@ -1260,8 +1258,7 @@ std::string DisplayManager::GetDisplayNameForId(int64_t id) const {
if (id == kInvalidDisplayId)
return l10n_util::GetStringUTF8(IDS_DISPLAY_NAME_UNKNOWN);
- std::map<int64_t, ManagedDisplayInfo>::const_iterator iter =
- display_info_.find(id);
+ auto iter = display_info_.find(id);
if (iter != display_info_.end() && !iter->second.name().empty())
return iter->second.name();
diff --git a/chromium/ui/display/manager/display_manager.h b/chromium/ui/display/manager/display_manager.h
index d9fc6ef7f1a..6f0d784463d 100644
--- a/chromium/ui/display/manager/display_manager.h
+++ b/chromium/ui/display/manager/display_manager.h
@@ -655,7 +655,7 @@ class DISPLAY_MANAGER_EXPORT DisplayManager
base::Closure created_mirror_window_;
- base::ObserverList<DisplayObserver>::Unchecked observers_;
+ base::ObserverList<DisplayObserver> observers_;
// Not empty if mixed mirror mode should be turned on (the specified source
// display is mirrored to the specified destination displays). Empty if mixed
diff --git a/chromium/ui/display/manager/touch_device_manager.cc b/chromium/ui/display/manager/touch_device_manager.cc
index b71cfa51475..41606b4eeb9 100644
--- a/chromium/ui/display/manager/touch_device_manager.cc
+++ b/chromium/ui/display/manager/touch_device_manager.cc
@@ -715,8 +715,10 @@ std::ostream& operator<<(std::ostream& os,
bool HasExternalTouchscreenDevice() {
for (const auto& device :
ui::InputDeviceManager::GetInstance()->GetTouchscreenDevices()) {
- if (device.type == ui::InputDeviceType::INPUT_DEVICE_EXTERNAL)
+ if (device.type == ui::InputDeviceType::INPUT_DEVICE_USB ||
+ device.type == ui::InputDeviceType::INPUT_DEVICE_BLUETOOTH) {
return true;
+ }
}
return false;
}
diff --git a/chromium/ui/display/manager/touch_device_manager_unittest.cc b/chromium/ui/display/manager/touch_device_manager_unittest.cc
index acc60f539f8..54c57f50460 100644
--- a/chromium/ui/display/manager/touch_device_manager_unittest.cc
+++ b/chromium/ui/display/manager/touch_device_manager_unittest.cc
@@ -142,7 +142,7 @@ TEST_F(TouchAssociationTest, ManyTouchscreens) {
std::vector<ui::TouchscreenDevice> devices;
for (int i = 0; i < 5; ++i) {
devices.push_back(CreateTouchscreenDevice(
- i, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(256, 256)));
+ i, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(256, 256)));
}
DisplayInfoList displays;
@@ -159,9 +159,9 @@ TEST_F(TouchAssociationTest, ManyTouchscreens) {
TEST_F(TouchAssociationTest, OneToOneMapping) {
std::vector<ui::TouchscreenDevice> devices;
devices.push_back(CreateTouchscreenDevice(
- 1, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(800, 600)));
+ 1, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(800, 600)));
devices.push_back(CreateTouchscreenDevice(
- 2, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(1024, 768)));
+ 2, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(1024, 768)));
test::ScopedSetInternalDisplayId set_internal(display_manager(),
displays_[0].id());
@@ -178,7 +178,7 @@ TEST_F(TouchAssociationTest, OneToOneMapping) {
TEST_F(TouchAssociationTest, MapToCorrectDisplaySize) {
std::vector<ui::TouchscreenDevice> devices;
devices.push_back(CreateTouchscreenDevice(
- 2, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(1024, 768)));
+ 2, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(1024, 768)));
test::ScopedSetInternalDisplayId set_internal(display_manager(),
displays_[0].id());
@@ -194,9 +194,9 @@ TEST_F(TouchAssociationTest, MapToCorrectDisplaySize) {
TEST_F(TouchAssociationTest, MapWhenSizeDiffersByOne) {
std::vector<ui::TouchscreenDevice> devices;
devices.push_back(CreateTouchscreenDevice(
- 1, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(801, 600)));
+ 1, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(801, 600)));
devices.push_back(CreateTouchscreenDevice(
- 2, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(1023, 768)));
+ 2, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(1023, 768)));
test::ScopedSetInternalDisplayId set_internal(display_manager(),
displays_[0].id());
@@ -213,9 +213,9 @@ TEST_F(TouchAssociationTest, MapWhenSizeDiffersByOne) {
TEST_F(TouchAssociationTest, MapWhenSizesDoNotMatch) {
std::vector<ui::TouchscreenDevice> devices;
devices.push_back(CreateTouchscreenDevice(
- 1, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(1022, 768)));
+ 1, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(1022, 768)));
devices.push_back(CreateTouchscreenDevice(
- 2, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(802, 600)));
+ 2, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(802, 600)));
DisplayInfoList displays;
displays.push_back(displays_[0]);
@@ -236,7 +236,7 @@ TEST_F(TouchAssociationTest, MapWhenSizesDoNotMatch) {
TEST_F(TouchAssociationTest, MapInternalTouchscreen) {
std::vector<ui::TouchscreenDevice> devices;
devices.push_back(CreateTouchscreenDevice(
- 1, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(1920, 1080)));
+ 1, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(1920, 1080)));
devices.push_back(CreateTouchscreenDevice(
2, ui::InputDeviceType::INPUT_DEVICE_INTERNAL, gfx::Size(9999, 888)));
@@ -279,7 +279,7 @@ TEST_F(TouchAssociationTest, MultipleInternalAndExternal) {
devices.push_back(CreateTouchscreenDevice(
2, ui::InputDeviceType::INPUT_DEVICE_INTERNAL, gfx::Size(1920, 1080)));
devices.push_back(CreateTouchscreenDevice(
- 3, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(1024, 768)));
+ 3, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(1024, 768)));
test::ScopedSetInternalDisplayId set_internal(display_manager(),
displays_[0].id());
@@ -298,7 +298,7 @@ TEST_F(TouchAssociationTest, MultipleInternalAndExternal) {
TEST_F(TouchAssociationTest, TestWithNoInternalDisplay) {
std::vector<ui::TouchscreenDevice> devices;
devices.push_back(CreateTouchscreenDevice(
- 1, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(1920, 1080)));
+ 1, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(1920, 1080)));
devices.push_back(CreateTouchscreenDevice(
2, ui::InputDeviceType::INPUT_DEVICE_INTERNAL, gfx::Size(9999, 888)));
@@ -315,11 +315,11 @@ TEST_F(TouchAssociationTest, TestWithNoInternalDisplay) {
TEST_F(TouchAssociationTest, MatchRemainingDevicesToInternalDisplay) {
std::vector<ui::TouchscreenDevice> devices;
devices.push_back(CreateTouchscreenDevice(
- 1, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(123, 456)));
+ 1, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(123, 456)));
devices.push_back(CreateTouchscreenDevice(
- 2, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(234, 567)));
+ 2, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(234, 567)));
devices.push_back(CreateTouchscreenDevice(
- 3, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(345, 678)));
+ 3, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(345, 678)));
test::ScopedSetInternalDisplayId set_internal(display_manager(),
displays_[0].id());
@@ -338,11 +338,11 @@ TEST_F(TouchAssociationTest,
MatchRemainingDevicesWithNoInternalDisplayPresent) {
std::vector<ui::TouchscreenDevice> devices;
devices.push_back(CreateTouchscreenDevice(
- 1, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(123, 456)));
+ 1, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(123, 456)));
devices.push_back(CreateTouchscreenDevice(
- 2, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(234, 567)));
+ 2, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(234, 567)));
devices.push_back(CreateTouchscreenDevice(
- 3, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(345, 678)));
+ 3, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(345, 678)));
touch_device_manager()->AssociateTouchscreens(&displays_, devices);
@@ -364,11 +364,11 @@ class TouchAssociationFromPrefTest : public TouchAssociationTest {
TouchDeviceManager::TouchAssociationMap touch_associations;
devices_.push_back(CreateTouchscreenDevice(
- 1, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(1920, 1080)));
+ 1, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(1920, 1080)));
devices_.push_back(CreateTouchscreenDevice(
- 2, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(1024, 768)));
+ 2, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(1024, 768)));
devices_.push_back(CreateTouchscreenDevice(
- 3, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(640, 480)));
+ 3, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(640, 480)));
devices_.push_back(CreateTouchscreenDevice(
4, ui::InputDeviceType::INPUT_DEVICE_INTERNAL, gfx::Size(800, 600)));
@@ -600,7 +600,7 @@ class TouchAssociationWithDuplicateDeviceTest : public TouchAssociationTest {
// Create a device with name |device_name_1| connected to |ports[0]|.
devices_.push_back(CreateTouchscreenDevice(
- 1, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(1920, 1080)));
+ 1, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(1920, 1080)));
devices_.back().name = device_name_1;
devices_.back().phys = ports[0];
@@ -608,7 +608,7 @@ class TouchAssociationWithDuplicateDeviceTest : public TouchAssociationTest {
int product_id = devices_.back().product_id;
devices_.push_back(CreateTouchscreenDevice(
- 2, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(1920, 1080)));
+ 2, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(1920, 1080)));
// Create another device with the same name but different port. Ensure that
// the touch device idnetifier is the same by setting the same vendor id,
@@ -619,7 +619,7 @@ class TouchAssociationWithDuplicateDeviceTest : public TouchAssociationTest {
devices_.back().product_id = product_id;
devices_.push_back(CreateTouchscreenDevice(
- 3, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(1920, 1080)));
+ 3, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(1920, 1080)));
devices_.back().name = device_name_1;
devices_.back().phys = ports[2];
devices_.back().vendor_id = vendor_id;
@@ -629,7 +629,7 @@ class TouchAssociationWithDuplicateDeviceTest : public TouchAssociationTest {
4, ui::InputDeviceType::INPUT_DEVICE_INTERNAL, gfx::Size(800, 600)));
devices_.push_back(CreateTouchscreenDevice(
- 5, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(4096, 4096)));
+ 5, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(4096, 4096)));
devices_.back().name = device_name_2;
devices_.back().phys = ports[3];
@@ -637,7 +637,7 @@ class TouchAssociationWithDuplicateDeviceTest : public TouchAssociationTest {
product_id = devices_.back().product_id;
devices_.push_back(CreateTouchscreenDevice(
- 6, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL, gfx::Size(4096, 4096)));
+ 6, ui::InputDeviceType::INPUT_DEVICE_USB, gfx::Size(4096, 4096)));
devices_.back().name = device_name_2;
devices_.back().phys = ports[4];
devices_.back().vendor_id = vendor_id;
diff --git a/chromium/ui/display/manager/touch_transform_controller_unittest.cc b/chromium/ui/display/manager/touch_transform_controller_unittest.cc
index 131bb543942..ba7cdd1d88c 100644
--- a/chromium/ui/display/manager/touch_transform_controller_unittest.cc
+++ b/chromium/ui/display/manager/touch_transform_controller_unittest.cc
@@ -41,7 +41,7 @@ ui::TouchDeviceTransform CreateTouchDeviceTransform(
ui::TouchscreenDevice CreateTouchscreenDevice(unsigned int id,
const gfx::Size& size) {
- return ui::TouchscreenDevice(id, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL,
+ return ui::TouchscreenDevice(id, ui::InputDeviceType::INPUT_DEVICE_USB,
std::string(), size, 0);
}
diff --git a/chromium/ui/display/util/BUILD.gn b/chromium/ui/display/util/BUILD.gn
index e7870883a11..ebf6b16c1c2 100644
--- a/chromium/ui/display/util/BUILD.gn
+++ b/chromium/ui/display/util/BUILD.gn
@@ -16,6 +16,8 @@ jumbo_component("util") {
"edid_parser.h",
]
+ configs += [ "//build/config/compiler:wexit_time_destructors" ]
+
defines = [ "DISPLAY_UTIL_IMPLEMENTATION" ]
deps = [
diff --git a/chromium/ui/display/util/edid_parser.h b/chromium/ui/display/util/edid_parser.h
index 5323f527da5..20516a29767 100644
--- a/chromium/ui/display/util/edid_parser.h
+++ b/chromium/ui/display/util/edid_parser.h
@@ -11,6 +11,7 @@
#include <vector>
#include "base/compiler_specific.h"
+#include "base/macros.h"
#include "base/optional.h"
#include "third_party/skia/include/core/SkColorSpace.h"
#include "ui/display/util/display_util_export.h"
diff --git a/chromium/ui/display/win/dpi.cc b/chromium/ui/display/win/dpi.cc
index 45e0aad18e4..5014d34cf12 100644
--- a/chromium/ui/display/win/dpi.cc
+++ b/chromium/ui/display/win/dpi.cc
@@ -8,6 +8,7 @@
#include "base/win/scoped_hdc.h"
#include "ui/display/display.h"
+#include "ui/display/win/uwp_text_scale_factor.h"
namespace display {
namespace win {
@@ -18,7 +19,30 @@ const float kDefaultDPI = 96.f;
float g_device_scale_factor = 0.f;
-gfx::Size GetDPI() {
+} // namespace
+
+void SetDefaultDeviceScaleFactor(float scale) {
+ DCHECK_NE(0.f, scale);
+ g_device_scale_factor = scale;
+}
+
+float GetDPIScale() {
+ if (Display::HasForceDeviceScaleFactor())
+ return Display::GetForcedDeviceScaleFactor();
+ return display::win::internal::GetUnforcedDeviceScaleFactor();
+}
+
+int GetDPIFromScalingFactor(float device_scaling_factor) {
+ return kDefaultDPI * device_scaling_factor;
+}
+
+double GetAccessibilityFontScale() {
+ return 1.0 / UwpTextScaleFactor::Instance()->GetTextScaleFactor();
+}
+
+namespace internal {
+
+int GetDefaultSystemDPI() {
static int dpi_x = 0;
static int dpi_y = 0;
static bool should_initialize = true;
@@ -31,35 +55,20 @@ gfx::Size GetDPI() {
// to all screens.
dpi_x = GetDeviceCaps(screen_dc, LOGPIXELSX);
dpi_y = GetDeviceCaps(screen_dc, LOGPIXELSY);
+ DCHECK_EQ(dpi_x, dpi_y);
}
- return gfx::Size(dpi_x, dpi_y);
-}
-
-} // namespace
-
-void SetDefaultDeviceScaleFactor(float scale) {
- DCHECK_NE(0.f, scale);
- g_device_scale_factor = scale;
-}
-
-float GetDPIScale() {
- if (Display::HasForceDeviceScaleFactor())
- return Display::GetForcedDeviceScaleFactor();
- return GetUnforcedDeviceScaleFactor();
+ return dpi_x;
}
float GetUnforcedDeviceScaleFactor() {
return g_device_scale_factor ? g_device_scale_factor
- : GetScalingFactorFromDPI(GetDPI().width());
-}
-
-int GetDPIFromScalingFactor(float device_scaling_factor) {
- return kDefaultDPI * device_scaling_factor;
+ : GetScalingFactorFromDPI(GetDefaultSystemDPI());
}
float GetScalingFactorFromDPI(int dpi) {
return static_cast<float>(dpi) / kDefaultDPI;
}
+} // namespace internal
} // namespace win
} // namespace display
diff --git a/chromium/ui/display/win/dpi.h b/chromium/ui/display/win/dpi.h
index 96c62506155..9da504e32ce 100644
--- a/chromium/ui/display/win/dpi.h
+++ b/chromium/ui/display/win/dpi.h
@@ -6,7 +6,6 @@
#define UI_DISPLAY_WIN_DPI_H_
#include "ui/display/display_export.h"
-#include "ui/gfx/geometry/size.h"
namespace display {
namespace win {
@@ -23,15 +22,36 @@ DISPLAY_EXPORT void SetDefaultDeviceScaleFactor(float scale);
// scale factor is 1.0. This does not handle per-monitor DPI.
DISPLAY_EXPORT float GetDPIScale();
-// Equivalent to GetDPIScale() but ignores the --force-device-scale-factor flag.
-float GetUnforcedDeviceScaleFactor();
-
+// Deprecated. Use win::ScreenWin::GetDPIForHWND instead.
+//
// Returns the equivalent DPI for |device_scaling_factor|.
DISPLAY_EXPORT int GetDPIFromScalingFactor(float device_scaling_factor);
+// Returns a factor to adjust a system font's height by, to adjust for
+// accessibility measures already built into the font, in order to prevent
+// applying the same scale factor twice. Value should be in the range
+// 0.0 (exclusive) to 1.0 (inclusive).
+//
+// Windows will add text scaling factor into the logical size of its default
+// system fonts (which it does *not* do for DPI scaling). Since we're scaling
+// the entire UI by a combination of text scale and DPI scale, this results in
+// double scaling. Call this function to unscale the font before using it in
+// any of our rendering code.
+DISPLAY_EXPORT double GetAccessibilityFontScale();
+
+namespace internal {
+// Note: These methods do not take accessibility adjustments into account.
+
+// Equivalent to GetDPIScale() but ignores the --force-device-scale-factor flag.
+float GetUnforcedDeviceScaleFactor();
+
// Returns the equivalent scaling factor for |dpi|.
-DISPLAY_EXPORT float GetScalingFactorFromDPI(int dpi);
+float GetScalingFactorFromDPI(int dpi);
+
+// Gets the default DPI for the system.
+int GetDefaultSystemDPI();
+} // namespace internal
} // namespace win
} // namespace display
diff --git a/chromium/ui/display/win/screen_win.cc b/chromium/ui/display/win/screen_win.cc
index d3e2267b23a..7fd3b5b4a78 100644
--- a/chromium/ui/display/win/screen_win.cc
+++ b/chromium/ui/display/win/screen_win.cc
@@ -35,32 +35,70 @@ namespace {
// resolved with Desktop Aura and WindowTreeHost.
ScreenWin* g_screen_win_instance = nullptr;
-float GetMonitorScaleFactor(HMONITOR monitor) {
+// Gets the DPI for a particular monitor, or 0 if per-monitor DPI is nuot
+// supported or can't be read.
+int GetPerMonitorDPI(HMONITOR monitor) {
+ // Most versions of Windows we will encounter are DPI-aware.
+ if (!base::win::IsProcessPerMonitorDpiAware())
+ return 0;
+
+ static auto get_dpi_for_monitor_func = []() {
+ using GetDpiForMonitorPtr = decltype(::GetDpiForMonitor)*;
+ HMODULE shcore_dll = ::LoadLibrary(L"shcore.dll");
+ if (shcore_dll) {
+ return reinterpret_cast<GetDpiForMonitorPtr>(
+ ::GetProcAddress(shcore_dll, "GetDpiForMonitor"));
+ }
+ return static_cast<GetDpiForMonitorPtr>(nullptr);
+ }();
+
+ if (!get_dpi_for_monitor_func)
+ return 0;
+
+ UINT dpi_x;
+ UINT dpi_y;
+ if (!SUCCEEDED(get_dpi_for_monitor_func(monitor, MDT_EFFECTIVE_DPI, &dpi_x,
+ &dpi_y))) {
+ return 0;
+ }
+
+ DCHECK_EQ(dpi_x, dpi_y);
+ return int{dpi_x};
+}
+
+// Gets the raw monitor scale factor.
+//
+// Respects the forced device scale factor, and will fall back to the global
+// scale factor if per-monitor DPI is not supported.
+float GetMonitorScaleFactorImpl(HMONITOR monitor, bool include_accessibility) {
DCHECK(monitor);
if (Display::HasForceDeviceScaleFactor())
return Display::GetForcedDeviceScaleFactor();
- if (base::win::IsProcessPerMonitorDpiAware()) {
- static auto get_dpi_for_monitor_func = []() {
- using GetDpiForMonitorPtr = decltype(::GetDpiForMonitor)*;
- HMODULE shcore_dll = ::LoadLibrary(L"shcore.dll");
- if (shcore_dll) {
- return reinterpret_cast<GetDpiForMonitorPtr>(
- ::GetProcAddress(shcore_dll, "GetDpiForMonitor"));
- }
- return static_cast<GetDpiForMonitorPtr>(nullptr);
- }();
+ int dpi = GetPerMonitorDPI(monitor);
+ if (!dpi)
+ return GetDPIScale();
- UINT dpi_x;
- UINT dpi_y;
- if (get_dpi_for_monitor_func &&
- SUCCEEDED(get_dpi_for_monitor_func(monitor, MDT_EFFECTIVE_DPI, &dpi_x,
- &dpi_y))) {
- DCHECK_EQ(dpi_x, dpi_y);
- return GetScalingFactorFromDPI(dpi_x);
- }
+ float scale_factor = display::win::internal::GetScalingFactorFromDPI(dpi);
+ if (include_accessibility) {
+ float text_scale_factor =
+ UwpTextScaleFactor::Instance()->GetTextScaleFactor();
+ scale_factor *= text_scale_factor;
}
- return GetDPIScale();
+ return scale_factor;
+}
+
+// Rounds a scale factor to one we can display safely in pixels without
+// smearing.
+double RoundToNearestSafeScaleFactor(float scale_factor) {
+ return std::max(1.0f, std::round(4.0f * scale_factor) * 0.25f);
+}
+
+// Returns a pixel safe monitor scale factor rounded to a pixel-safe value.
+float GetSafeMonitorScaleFactor(HMONITOR monitor,
+ bool include_accessibility = true) {
+ return RoundToNearestSafeScaleFactor(
+ GetMonitorScaleFactorImpl(monitor, include_accessibility));
}
bool GetPathInfo(HMONITOR monitor, DISPLAYCONFIG_PATH_INFO* path_info) {
@@ -153,7 +191,7 @@ Display CreateDisplayFromDisplayInfo(const DisplayInfo& display_info,
display.set_bounds(gfx::ScaleToEnclosingRect(display_info.screen_rect(),
1.0f / scale_factor));
display.set_rotation(display_info.rotation());
- if (!Display::HasForceColorProfile()) {
+ if (!Display::HasForceDisplayColorProfile()) {
if (hdr_enabled) {
display.SetColorSpaceAndDepth(
gfx::ColorSpace::CreateSCRGBLinear().GetScaledColorSpace(
@@ -254,7 +292,7 @@ BOOL CALLBACK EnumMonitorForDisplayInfoCallback(HMONITOR monitor,
reinterpret_cast<std::vector<DisplayInfo>*>(data);
DCHECK(display_infos);
display_infos->push_back(DisplayInfo(MonitorInfoFromHMONITOR(monitor),
- GetMonitorScaleFactor(monitor),
+ GetSafeMonitorScaleFactor(monitor),
GetMonitorSDRWhiteLevel(monitor)));
return TRUE;
}
@@ -294,6 +332,9 @@ ScreenWin::ScreenWin(bool initialize)
ScreenWin::~ScreenWin() {
DCHECK_EQ(g_screen_win_instance, this);
+ if (uwp_text_scale_factor_)
+ uwp_text_scale_factor_->RemoveObserver(this);
+
g_screen_win_instance = nullptr;
}
@@ -414,29 +455,36 @@ gfx::Size ScreenWin::DIPToScreenSize(HWND hwnd, const gfx::Size& dip_size) {
}
// static
-int ScreenWin::GetSystemMetricsForHwnd(HWND hwnd, int metric) {
+int ScreenWin::GetSystemMetricsForMonitor(HMONITOR monitor, int metric) {
if (!g_screen_win_instance)
return ::GetSystemMetrics(metric);
- Display primary_display(g_screen_win_instance->GetPrimaryDisplay());
-
- return GetSystemMetricsForScaleFactor(
- hwnd ? GetScaleFactorForHWND(hwnd)
- : primary_display.device_scale_factor(),
- metric);
-}
+ // We don't include fudge factors stemming from accessiblility features when
+ // dealing with system metrics associated with window elements drawn by the
+ // operating system, since we will not be doing scaling of those metrics
+ // ourselves.
+ bool include_accessibility;
+ switch (metric) {
+ case SM_CXSIZEFRAME:
+ case SM_CYSIZEFRAME:
+ case SM_CXPADDEDBORDER:
+ include_accessibility = false;
+ break;
+ default:
+ include_accessibility = true;
+ break;
+ }
-// static
-int ScreenWin::GetSystemMetricsForMonitor(HMONITOR monitor, int metric) {
- if (!g_screen_win_instance)
- return ::GetSystemMetrics(metric);
+ // We'll want to use GetSafeMonitorScaleFactor(), so if the monitor is not
+ // specified pull up the primary display's HMONITOR.
+ if (!monitor)
+ monitor = MonitorFromWindow(nullptr, MONITOR_DEFAULTTOPRIMARY);
- Display primary_display(g_screen_win_instance->GetPrimaryDisplay());
+ float scale_factor =
+ GetSafeMonitorScaleFactor(monitor, include_accessibility);
- return GetSystemMetricsForScaleFactor(
- monitor ? GetMonitorScaleFactor(monitor)
- : primary_display.device_scale_factor(),
- metric);
+ // We'll then pull up the system metrics scaled by the appropriate amount.
+ return GetSystemMetricsForScaleFactor(scale_factor, metric);
}
// static
@@ -460,8 +508,25 @@ float ScreenWin::GetScaleFactorForHWND(HWND hwnd) {
}
// static
+int ScreenWin::GetDPIForHWND(HWND hwnd) {
+ if (Display::HasForceDeviceScaleFactor())
+ return GetDPIFromScalingFactor(Display::GetForcedDeviceScaleFactor());
+
+ HMONITOR monitor = MonitorFromWindow(hwnd, MONITOR_DEFAULTTONEAREST);
+ int dpi = GetPerMonitorDPI(monitor);
+ return dpi ? dpi : display::win::internal::GetDefaultSystemDPI();
+}
+
+// static
+float ScreenWin::GetScaleFactorForDPI(int dpi) {
+ return RoundToNearestSafeScaleFactor(
+ display::win::internal::GetScalingFactorFromDPI(dpi) *
+ UwpTextScaleFactor::Instance()->GetTextScaleFactor());
+}
+
+// static
float ScreenWin::GetSystemScaleFactor() {
- return GetUnforcedDeviceScaleFactor();
+ return display::win::internal::GetUnforcedDeviceScaleFactor();
}
// static
@@ -495,6 +560,17 @@ gfx::NativeWindow ScreenWin::GetNativeWindowFromHWND(HWND hwnd) const {
return nullptr;
}
+void ScreenWin::OnUwpTextScaleFactorChanged() {
+ UpdateAllDisplaysAndNotify();
+}
+
+void ScreenWin::OnUwpTextScaleFactorCleanup(UwpTextScaleFactor* source) {
+ if (source == uwp_text_scale_factor_)
+ uwp_text_scale_factor_ = nullptr;
+
+ UwpTextScaleFactor::Observer::OnUwpTextScaleFactorCleanup(source);
+}
+
gfx::Point ScreenWin::GetCursorScreenPoint() {
POINT pt;
::GetCursorPos(&pt);
@@ -588,6 +664,12 @@ void ScreenWin::Initialize() {
base::Bind(&ScreenWin::OnWndProc, base::Unretained(this))));
UpdateFromDisplayInfos(GetDisplayInfosFromSystem());
RecordDisplayScaleFactors();
+
+ // We want to remember that we've observed a screen metrics object so that we
+ // can remove ourselves as an observer at some later point (either when the
+ // metrics object notifies us it's going away or when we are destructed).
+ uwp_text_scale_factor_ = UwpTextScaleFactor::Instance();
+ uwp_text_scale_factor_->AddObserver(this);
}
MONITORINFOEX ScreenWin::MonitorInfoFromScreenPoint(
diff --git a/chromium/ui/display/win/screen_win.h b/chromium/ui/display/win/screen_win.h
index 6a20812bf89..9a31579b8e3 100644
--- a/chromium/ui/display/win/screen_win.h
+++ b/chromium/ui/display/win/screen_win.h
@@ -15,6 +15,7 @@
#include "ui/display/display_export.h"
#include "ui/display/screen.h"
#include "ui/display/win/color_profile_reader.h"
+#include "ui/display/win/uwp_text_scale_factor.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/win/singleton_hwnd_observer.h"
@@ -33,7 +34,8 @@ class DisplayInfo;
class ScreenWinDisplay;
class DISPLAY_EXPORT ScreenWin : public Screen,
- public ColorProfileReader::Client {
+ public ColorProfileReader::Client,
+ public UwpTextScaleFactor::Observer {
public:
ScreenWin();
~ScreenWin() override;
@@ -92,15 +94,14 @@ class DISPLAY_EXPORT ScreenWin : public Screen,
// The DPI scale is performed relative to the display nearest to |hwnd|.
static gfx::Size DIPToScreenSize(HWND hwnd, const gfx::Size& dip_size);
- // Returns the result of GetSystemMetrics for |metric| scaled to |hwnd|'s DPI.
- // Use this function if you're already working with screen pixels, as this
- // helps reduce any cascading rounding errors from DIP to the |hwnd|'s DPI.
- static int GetSystemMetricsForHwnd(HWND hwnd, int metric);
-
// Returns the result of GetSystemMetrics for |metric| scaled to |monitor|'s
// DPI. Use this function if you're already working with screen pixels, as
// this helps reduce any cascading rounding errors from DIP to the |monitor|'s
// DPI.
+ //
+ // Note that metrics which correspond to elements drawn by Windows
+ // (specifically frame and resize handles) will be scaled by DPI only and not
+ // by Text Zoom or other accessibility features.
static int GetSystemMetricsForMonitor(HMONITOR monitor, int metric);
// Returns the result of GetSystemMetrics for |metric| in DIP.
@@ -108,9 +109,16 @@ class DISPLAY_EXPORT ScreenWin : public Screen,
// rounding errors towards screen pixels.
static int GetSystemMetricsInDIP(int metric);
- // Returns |hwnd|'s scale factor.
+ // Returns |hwnd|'s scale factor, including accessibility adjustments.
static float GetScaleFactorForHWND(HWND hwnd);
+ // Returns the unmodified DPI for a particular |hwnd|, without accessibility
+ // adjustments.
+ static int GetDPIForHWND(HWND hwnd);
+
+ // Converts dpi to scale factor, including accessibility adjustments.
+ static float GetScaleFactorForDPI(int dpi);
+
// Returns the system's global scale factor, ignoring the value of
// --force-device-scale-factor. Only use this if you are working with Windows
// metrics global to the system. Otherwise you should call
@@ -214,6 +222,12 @@ class DISPLAY_EXPORT ScreenWin : public Screen,
void RecordDisplayScaleFactors() const;
+ //-----------------------------------------------------------------
+ // UwpTextScaleFactor::Observer:
+
+ void OnUwpTextScaleFactorChanged() override;
+ void OnUwpTextScaleFactorCleanup(UwpTextScaleFactor* source) override;
+
// Helper implementing the DisplayObserver handling.
DisplayChangeNotifier change_notifier_;
@@ -236,6 +250,8 @@ class DISPLAY_EXPORT ScreenWin : public Screen,
// advanced color" setting.
bool hdr_enabled_ = false;
+ UwpTextScaleFactor* uwp_text_scale_factor_ = nullptr;
+
DISALLOW_COPY_AND_ASSIGN(ScreenWin);
};
diff --git a/chromium/ui/display/win/screen_win_unittest.cc b/chromium/ui/display/win/screen_win_unittest.cc
index 4cf8e183fd0..4e420cdeec3 100644
--- a/chromium/ui/display/win/screen_win_unittest.cc
+++ b/chromium/ui/display/win/screen_win_unittest.cc
@@ -329,14 +329,6 @@ TEST_F(ScreenWinTestSingleDisplay1x, DIPToScreenSize) {
EXPECT_EQ(size, ScreenWin::DIPToScreenSize(hwnd, size));
}
-TEST_F(ScreenWinTestSingleDisplay1x, GetSystemMetricsForHwnd) {
- HWND hwnd = GetFakeHwnd();
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(hwnd, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(hwnd, 42));
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(nullptr, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(nullptr, 42));
-}
-
TEST_F(ScreenWinTestSingleDisplay1x, GetSystemMetricsInDIP) {
EXPECT_EQ(31, ScreenWin::GetSystemMetricsInDIP(31));
EXPECT_EQ(42, ScreenWin::GetSystemMetricsInDIP(42));
@@ -497,14 +489,6 @@ TEST_F(ScreenWinTestSingleDisplay1_25x, DIPToScreenSize) {
ScreenWin::DIPToScreenSize(GetFakeHwnd(), gfx::Size(28, 88)));
}
-TEST_F(ScreenWinTestSingleDisplay1_25x, GetSystemMetricsForHwnd) {
- HWND hwnd = GetFakeHwnd();
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(hwnd, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(hwnd, 42));
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(nullptr, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(nullptr, 42));
-}
-
TEST_F(ScreenWinTestSingleDisplay1_25x, GetSystemMetricsInDIP) {
EXPECT_EQ(25, ScreenWin::GetSystemMetricsInDIP(31));
EXPECT_EQ(34, ScreenWin::GetSystemMetricsInDIP(42));
@@ -654,14 +638,6 @@ TEST_F(ScreenWinTestSingleDisplay1_5x, DIPToScreenSize) {
ScreenWin::DIPToScreenSize(GetFakeHwnd(), gfx::Size(28, 88)));
}
-TEST_F(ScreenWinTestSingleDisplay1_5x, GetSystemMetricsForHwnd) {
- HWND hwnd = GetFakeHwnd();
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(hwnd, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(hwnd, 42));
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(nullptr, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(nullptr, 42));
-}
-
TEST_F(ScreenWinTestSingleDisplay1_5x, GetSystemMetricsInDIP) {
EXPECT_EQ(21, ScreenWin::GetSystemMetricsInDIP(31));
EXPECT_EQ(28, ScreenWin::GetSystemMetricsInDIP(42));
@@ -811,14 +787,6 @@ TEST_F(ScreenWinTestSingleDisplay2x, DIPToScreenSize) {
ScreenWin::DIPToScreenSize(GetFakeHwnd(), gfx::Size(21, 66)));
}
-TEST_F(ScreenWinTestSingleDisplay2x, GetSystemMetricsForHwnd) {
- HWND hwnd = GetFakeHwnd();
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(hwnd, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(hwnd, 42));
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(nullptr, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(nullptr, 42));
-}
-
TEST_F(ScreenWinTestSingleDisplay2x, GetSystemMetricsInDIP) {
EXPECT_EQ(16, ScreenWin::GetSystemMetricsInDIP(31));
EXPECT_EQ(21, ScreenWin::GetSystemMetricsInDIP(42));
@@ -1036,17 +1004,6 @@ TEST_F(ScreenWinTestTwoDisplays1x, DIPToScreenSize) {
EXPECT_EQ(size, ScreenWin::DIPToScreenSize(right_hwnd, size));
}
-TEST_F(ScreenWinTestTwoDisplays1x, GetSystemMetricsForHwnd) {
- HWND left_hwnd = GetLeftFakeHwnd();
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(left_hwnd, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(left_hwnd, 42));
- HWND right_hwnd = GetRightFakeHwnd();
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(right_hwnd, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(right_hwnd, 42));
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(nullptr, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(nullptr, 42));
-}
-
TEST_F(ScreenWinTestTwoDisplays1x, GetSystemMetricsInDIP) {
EXPECT_EQ(31, ScreenWin::GetSystemMetricsInDIP(31));
EXPECT_EQ(42, ScreenWin::GetSystemMetricsInDIP(42));
@@ -1314,17 +1271,6 @@ TEST_F(ScreenWinTestTwoDisplays2x, DIPToScreenSize) {
ScreenWin::DIPToScreenSize(right_hwnd, gfx::Size(21, 66)));
}
-TEST_F(ScreenWinTestTwoDisplays2x, GetSystemMetricsForHwnd) {
- HWND left_hwnd = GetLeftFakeHwnd();
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(left_hwnd, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(left_hwnd, 42));
- HWND right_hwnd = GetRightFakeHwnd();
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(right_hwnd, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(right_hwnd, 42));
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(nullptr, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(nullptr, 42));
-}
-
TEST_F(ScreenWinTestTwoDisplays2x, GetSystemMetricsInDIP) {
EXPECT_EQ(16, ScreenWin::GetSystemMetricsInDIP(31));
EXPECT_EQ(21, ScreenWin::GetSystemMetricsInDIP(42));
@@ -1692,16 +1638,6 @@ TEST_F(ScreenWinTestManyDisplays1x, DIPToScreenSize) {
}
}
-TEST_F(ScreenWinTestManyDisplays1x, GetSystemMetricsForHwnd) {
- for (size_t i = 0; i < 5u; ++i) {
- SCOPED_TRACE(base::StringPrintf("i=%zu", i));
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(GetFakeHwnd(i), 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(GetFakeHwnd(i), 42));
- }
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(nullptr, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(nullptr, 42));
-}
-
TEST_F(ScreenWinTestManyDisplays1x, GetSystemMetricsInDIP) {
EXPECT_EQ(31, ScreenWin::GetSystemMetricsInDIP(31));
EXPECT_EQ(42, ScreenWin::GetSystemMetricsInDIP(42));
@@ -2131,16 +2067,6 @@ TEST_F(ScreenWinTestManyDisplays2x, DIPToScreenSize) {
}
}
-TEST_F(ScreenWinTestManyDisplays2x, GetSystemMetricsForHwnd) {
- for (size_t i = 0; i < 5u; ++i) {
- SCOPED_TRACE(base::StringPrintf("i=%zu", i));
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(GetFakeHwnd(i), 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(GetFakeHwnd(i), 42));
- }
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(nullptr, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(nullptr, 42));
-}
-
TEST_F(ScreenWinTestManyDisplays2x, GetSystemMetricsInDIP) {
EXPECT_EQ(16, ScreenWin::GetSystemMetricsInDIP(31));
EXPECT_EQ(21, ScreenWin::GetSystemMetricsInDIP(42));
@@ -2441,17 +2367,6 @@ TEST_F(ScreenWinTestTwoDisplays1x2x, DIPToScreenSize) {
ScreenWin::DIPToScreenSize(right_hwnd, gfx::Size(21, 66)));
}
-TEST_F(ScreenWinTestTwoDisplays1x2x, GetSystemMetricsForHwnd) {
- HWND left_hwnd = GetLeftFakeHwnd();
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(left_hwnd, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(left_hwnd, 42));
- HWND right_hwnd = GetRightFakeHwnd();
- EXPECT_EQ(62, ScreenWin::GetSystemMetricsForHwnd(right_hwnd, 31));
- EXPECT_EQ(84, ScreenWin::GetSystemMetricsForHwnd(right_hwnd, 42));
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(nullptr, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(nullptr, 42));
-}
-
TEST_F(ScreenWinTestTwoDisplays1x2x, GetSystemMetricsInDIP) {
EXPECT_EQ(31, ScreenWin::GetSystemMetricsInDIP(31));
EXPECT_EQ(42, ScreenWin::GetSystemMetricsInDIP(42));
@@ -2727,17 +2642,6 @@ TEST_F(ScreenWinTestTwoDisplays1_5x1x, DIPToScreenSize) {
ScreenWin::DIPToScreenSize(right_hwnd, gfx::Size(42, 131)));
}
-TEST_F(ScreenWinTestTwoDisplays1_5x1x, GetSystemMetricsForHwnd) {
- HWND left_hwnd = GetLeftFakeHwnd();
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(left_hwnd, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(left_hwnd, 42));
- HWND right_hwnd = GetRightFakeHwnd();
- EXPECT_EQ(21, ScreenWin::GetSystemMetricsForHwnd(right_hwnd, 31));
- EXPECT_EQ(28, ScreenWin::GetSystemMetricsForHwnd(right_hwnd, 42));
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(nullptr, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(nullptr, 42));
-}
-
TEST_F(ScreenWinTestTwoDisplays1_5x1x, GetSystemMetricsInDIP) {
EXPECT_EQ(21, ScreenWin::GetSystemMetricsInDIP(31));
EXPECT_EQ(28, ScreenWin::GetSystemMetricsInDIP(42));
@@ -3009,17 +2913,6 @@ TEST_F(ScreenWinTestTwoDisplays2x1x, DIPToScreenSize) {
ScreenWin::DIPToScreenSize(right_hwnd, gfx::Size(42, 131)));
}
-TEST_F(ScreenWinTestTwoDisplays2x1x, GetSystemMetricsForHwnd) {
- HWND left_hwnd = GetLeftFakeHwnd();
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(left_hwnd, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(left_hwnd, 42));
- HWND right_hwnd = GetRightFakeHwnd();
- EXPECT_EQ(16, ScreenWin::GetSystemMetricsForHwnd(right_hwnd, 31));
- EXPECT_EQ(21, ScreenWin::GetSystemMetricsForHwnd(right_hwnd, 42));
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(nullptr, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(nullptr, 42));
-}
-
TEST_F(ScreenWinTestTwoDisplays2x1x, GetSystemMetricsInDIP) {
EXPECT_EQ(16, ScreenWin::GetSystemMetricsInDIP(31));
EXPECT_EQ(21, ScreenWin::GetSystemMetricsInDIP(42));
@@ -3296,17 +3189,6 @@ TEST_F(ScreenWinTestTwoDisplays2x1xVirtualized, DIPToScreenSize) {
ScreenWin::DIPToScreenSize(right_hwnd, gfx::Size(21, 66)));
}
-TEST_F(ScreenWinTestTwoDisplays2x1xVirtualized, GetSystemMetricsForHwnd) {
- HWND left_hwnd = GetLeftFakeHwnd();
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(left_hwnd, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(left_hwnd, 42));
- HWND right_hwnd = GetRightFakeHwnd();
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(right_hwnd, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(right_hwnd, 42));
- EXPECT_EQ(31, ScreenWin::GetSystemMetricsForHwnd(nullptr, 31));
- EXPECT_EQ(42, ScreenWin::GetSystemMetricsForHwnd(nullptr, 42));
-}
-
TEST_F(ScreenWinTestTwoDisplays2x1xVirtualized, GetSystemMetricsInDIP) {
EXPECT_EQ(16, ScreenWin::GetSystemMetricsInDIP(31));
EXPECT_EQ(21, ScreenWin::GetSystemMetricsInDIP(42));
@@ -3485,12 +3367,6 @@ TEST_F(ScreenWinUninitializedForced1x, DIPToScreenSize) {
EXPECT_EQ(size, ScreenWin::DIPToScreenSize(nullptr, size));
}
-TEST_F(ScreenWinUninitializedForced1x, GetSystemMetricsForHwnd) {
- // GetSystemMetricsForHwnd falls back to the system's GetSystemMetrics, so
- // this test is to make sure we don't crash.
- ScreenWin::GetSystemMetricsForHwnd(nullptr, SM_CXSIZEFRAME);
-}
-
TEST_F(ScreenWinUninitializedForced1x, GetSystemMetricsInDIP) {
// GetSystemMetricsInDIP falls back to the system's GetSystemMetrics, so this
// test is to make sure we don't crash.
@@ -3598,14 +3474,8 @@ TEST_F(ScreenWinUninitializedForced2x, DIPToScreenSize) {
ScreenWin::DIPToScreenSize(nullptr, gfx::Size(21, 66)));
}
-TEST_F(ScreenWinUninitializedForced2x, GetSystemMetricsForHwnd) {
- // GetSystemMetricsForHwnd falls back to the system's GetSystemMetrics, so
- // this test is to make sure we don't crash.
- ScreenWin::GetSystemMetricsForHwnd(nullptr, SM_CXSIZEFRAME);
-}
-
TEST_F(ScreenWinUninitializedForced2x, GetSystemMetricsInDIP) {
- // GetSystemMetricsForHwnd falls back to the system's GetSystemMetrics, so
+ // This falls back to the system's GetSystemMetrics, so
// this test is to make sure we don't crash.
ScreenWin::GetSystemMetricsInDIP(SM_CXSIZEFRAME);
}
diff --git a/chromium/ui/display/win/uwp_text_scale_factor.cc b/chromium/ui/display/win/uwp_text_scale_factor.cc
new file mode 100644
index 00000000000..6b661bdbed8
--- /dev/null
+++ b/chromium/ui/display/win/uwp_text_scale_factor.cc
@@ -0,0 +1,236 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/display/win/uwp_text_scale_factor.h"
+
+#include <windows.h>
+
+#include <windows.ui.viewmanagement.h>
+#include <wrl/client.h>
+#include <wrl/event.h>
+
+#include "base/lazy_instance.h"
+#include "base/strings/string_piece.h"
+#include "base/threading/thread_checker.h"
+#include "base/win/core_winrt_util.h"
+#include "base/win/scoped_com_initializer.h"
+#include "base/win/scoped_hstring.h"
+#include "base/win/windows_version.h"
+
+namespace display {
+namespace win {
+
+namespace {
+
+using Microsoft::WRL::ComPtr;
+using Microsoft::WRL::Callback;
+using ABI::Windows::Foundation::ITypedEventHandler;
+using ABI::Windows::UI::ViewManagement::UISettings;
+using ABI::Windows::UI::ViewManagement::IUISettings;
+using ABI::Windows::UI::ViewManagement::IUISettings2;
+
+typedef ITypedEventHandler<UISettings*, IInspectable*>
+ TextScaleChangedEventHandler;
+
+// A zero value indicates an invalid token.
+constexpr EventRegistrationToken kInvalidEventRegistrationToken{0LL};
+
+// Override the default instance for testing purposes.
+UwpTextScaleFactor* g_implementation_for_testing = nullptr;
+
+// Sanity check for access after destruction.
+bool g_default_instance_cleaned_up = false;
+
+// Constructs the UWP UI Settings COM object, or fails with as useful of a log
+// message as possible given Windows error reporting.
+//
+// Lots of things could potentially go wrong so we want to be able to bail out
+// when creating the UWP UI Settings object, so we've moved the initialization
+// to a separate function.
+bool CreateUiSettingsComObject(ComPtr<IUISettings2>& ptr) {
+ DCHECK(!ptr);
+
+ // This is required setup before using ScopedHString.
+ if (!(base::win::ResolveCoreWinRTDelayload() &&
+ base::win::ScopedHString::ResolveCoreWinRTStringDelayload())) {
+ DLOG(ERROR) << "Failed loading functions from combase.dll";
+ return false;
+ }
+
+ // Create the COM object.
+ auto hstring = base::win::ScopedHString::Create(
+ RuntimeClass_Windows_UI_ViewManagement_UISettings);
+ if (!hstring.is_valid()) {
+ return false;
+ }
+ ComPtr<IInspectable> inspectable;
+ HRESULT hr = base::win::RoActivateInstance(hstring.get(), &inspectable);
+ if (FAILED(hr)) {
+ VLOG(2) << "RoActivateInstance failed: "
+ << logging::SystemErrorCodeToString(hr);
+ return false;
+ }
+
+ // Verify that it supports the correct interface.
+ hr = inspectable.As(&ptr);
+ if (FAILED(hr)) {
+ VLOG(2) << "As IUISettings2 failed: "
+ << logging::SystemErrorCodeToString(hr);
+ return false;
+ }
+
+ return true;
+}
+
+// Implements the actual logic for getting screen metrics.
+class UwpTextScaleFactorImpl : public UwpTextScaleFactor {
+ public:
+ UwpTextScaleFactorImpl()
+ : text_scale_factor_changed_token_(kInvalidEventRegistrationToken) {
+ // There's no point in doing this initialization if we're earlier than
+ // Windows 10, since UWP is a Win10 feature.
+ if (base::win::GetVersion() < base::win::VERSION_WIN10)
+ return;
+
+ // We want to bracket all use of our COM object with COM initialization
+ // in order to be sure we don't leak COM listeners into the OS. This may
+ // extend the lifetime of COM on this thread but we do not expect it to be
+ // a problem.
+ scoped_com_initializer_ =
+ std::make_unique<base::win::ScopedCOMInitializer>();
+ if (!scoped_com_initializer_->Succeeded())
+ return;
+
+ // Create our COM object. Again, if we fail, there's no reason to proceed.
+ if (!CreateUiSettingsComObject(ui_settings_com_object_))
+ return;
+
+ // Set up a listener for the TextScaleChanged event. We'll do this here
+ // so that we can use a member function as a callback.
+ auto text_scale_changed_handler = Callback<TextScaleChangedEventHandler>(
+ this, &UwpTextScaleFactorImpl::OnTextScaleFactorChanged);
+ if (text_scale_changed_handler) {
+ HRESULT hr = ui_settings_com_object_->add_TextScaleFactorChanged(
+ text_scale_changed_handler.Get(), &text_scale_factor_changed_token_);
+ if (FAILED(hr)) {
+ VLOG(2) << "Register text scale changed callback failed: "
+ << logging::SystemErrorCodeToString(hr);
+ }
+ }
+ }
+
+ ~UwpTextScaleFactorImpl() override {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ // Release the callback if we've registered one and free our COM objects.
+ if (ui_settings_com_object_) {
+ if (text_scale_factor_changed_token_.value) {
+ HRESULT hr = ui_settings_com_object_->remove_TextScaleFactorChanged(
+ text_scale_factor_changed_token_);
+ if (FAILED(hr)) {
+ VLOG(2) << "Failed to remove TextScaleFactorChanged listener: "
+ << logging::SystemErrorCodeToString(hr);
+ }
+ }
+ ui_settings_com_object_.Reset();
+ }
+
+ g_default_instance_cleaned_up = true;
+ }
+
+ float GetTextScaleFactor() const override {
+ DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+
+ double result = 1.0;
+
+ // This is just a null check, so if we don't have access to the text
+ // scaling / service for any reason we'll just use 1x.
+ if (ui_settings_com_object_) {
+ HRESULT hr = ui_settings_com_object_->get_TextScaleFactor(&result);
+ if (FAILED(hr)) {
+ VLOG(2) << "IUISettings2::TextScaleFactor failed: "
+ << logging::SystemErrorCodeToString(hr);
+ // COM calls overwrite their out-params, typically by zeroing them out.
+ // Since we can't rely on this being a valid value on failure, we'll
+ // reset it.
+ result = 1.0;
+ }
+ }
+
+ // Windows documents this property to always have a value greater than or
+ // equal to 1. Let's make sure that's the case - if we don't, we could get
+ // bizarre behavior and divide-by-zeros later on.
+ DCHECK_GE(result, 1.0);
+ return float{result};
+ }
+
+ private:
+ HRESULT OnTextScaleFactorChanged(IUISettings*, IInspectable*) {
+ NotifyUwpTextScaleFactorChanged();
+ return S_OK;
+ }
+
+ std::unique_ptr<base::win::ScopedCOMInitializer> scoped_com_initializer_;
+ ComPtr<IUISettings2> ui_settings_com_object_;
+ EventRegistrationToken text_scale_factor_changed_token_;
+
+ THREAD_CHECKER(thread_checker_);
+};
+
+} // namespace
+
+//---------------------------------------------------------
+// Base UwpScreenMetrics implementation:
+
+UwpTextScaleFactor::UwpTextScaleFactor() = default;
+
+UwpTextScaleFactor::~UwpTextScaleFactor() {
+ for (auto& observer : observer_list_) {
+ observer.OnUwpTextScaleFactorCleanup(this);
+ }
+}
+
+float UwpTextScaleFactor::GetTextScaleFactor() const {
+ return 1.0f;
+}
+
+void UwpTextScaleFactor::AddObserver(Observer* observer) {
+ observer_list_.AddObserver(observer);
+}
+
+void UwpTextScaleFactor::RemoveObserver(Observer* observer) {
+ observer_list_.RemoveObserver(observer);
+}
+
+void UwpTextScaleFactor::NotifyUwpTextScaleFactorChanged() {
+ for (auto& observer : observer_list_) {
+ observer.OnUwpTextScaleFactorChanged();
+ }
+}
+
+void UwpTextScaleFactor::SetImplementationForTesting(
+ UwpTextScaleFactor* mock_impl) {
+ g_implementation_for_testing = mock_impl;
+}
+
+UwpTextScaleFactor* UwpTextScaleFactor::Instance() {
+ static base::LazyInstance<UwpTextScaleFactorImpl>::DestructorAtExit instance;
+
+ DCHECK(!g_default_instance_cleaned_up)
+ << "Attempting to access UwpScreenMetrics after AtExit cleanup!";
+
+ return g_implementation_for_testing ? g_implementation_for_testing
+ : &instance.Get();
+}
+
+//---------------------------------------------------------
+// UwpScreenMetrics::Observer implementation:
+
+void UwpTextScaleFactor::Observer::OnUwpTextScaleFactorCleanup(
+ UwpTextScaleFactor* source) {
+ source->RemoveObserver(this);
+}
+
+} // namespace win
+} // namespace display
diff --git a/chromium/ui/display/win/uwp_text_scale_factor.h b/chromium/ui/display/win/uwp_text_scale_factor.h
new file mode 100644
index 00000000000..5ad22d22add
--- /dev/null
+++ b/chromium/ui/display/win/uwp_text_scale_factor.h
@@ -0,0 +1,73 @@
+// Copyright (c) 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_DISPLAY_WIN_UWP_TEXT_SCALE_FACTOR_H_
+#define UI_DISPLAY_WIN_UWP_TEXT_SCALE_FACTOR_H_
+
+#include "base/observer_list.h"
+#include "ui/display/display_export.h"
+
+namespace display {
+namespace win {
+
+// Provides access to UWP TextScaleFactor, an accessibility feature.
+//
+// TODO(dfried): In the future we may need to expand this class to capture
+// other UWP-only metrics and functionality. At that point, we probably want to
+// rename the class and/or put it in base/win.
+class DISPLAY_EXPORT UwpTextScaleFactor {
+ public:
+ // Observer for UWP screen metrics and accessibility events.
+ class DISPLAY_EXPORT Observer : public base::CheckedObserver {
+ public:
+ // Notifies the observer that the text scale has changed. Will be called on
+ // the main thread.
+ virtual void OnUwpTextScaleFactorChanged() = 0;
+
+ // Notifies the observer that this object is about to go out of scope and
+ // that it should release any references to this object. The base
+ // implementation removes this object as a listener, so remember to call
+ // it when you're done with derived class cleanup.
+ virtual void OnUwpTextScaleFactorCleanup(UwpTextScaleFactor* source);
+ };
+
+ // Retrieves the one global instance. Lazily-created unless you want to mock
+ // it out with SetImplementationForTesting().
+ static UwpTextScaleFactor* Instance();
+
+ virtual ~UwpTextScaleFactor();
+
+ // Retrieves the Windows Text Zoom scale factor. Guaranteed to be >= 1.
+ virtual float GetTextScaleFactor() const;
+
+ // Registers and observer that will be notified of any changes to UWP screen
+ // or accessibility metrics.
+ void AddObserver(Observer* observer);
+
+ // Removes an observer that has been added. Observers should remove
+ // themselves either during OnUwpScreenMetricsCleanup() or at destruction
+ // (whichever is first).
+ void RemoveObserver(Observer* observer);
+
+ // Override creation of the default UwpTextScaleFactor implementation, using
+ // a mock or other stub implementation of your choice. The caller is
+ // responsible for cleaning up this object.
+ static void SetImplementationForTesting(UwpTextScaleFactor* mock_impl);
+
+ protected:
+ UwpTextScaleFactor();
+ void NotifyUwpTextScaleFactorChanged();
+
+ // The observers that need to be notified when a display is modified, added
+ // or removed.
+ base::ObserverList<Observer> observer_list_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(UwpTextScaleFactor);
+};
+
+} // namespace win
+} // namespace display
+
+#endif // UI_DISPLAY_WIN_UWP_TEXT_SCALE_FACTOR_H_
diff --git a/chromium/ui/events/BUILD.gn b/chromium/ui/events/BUILD.gn
index 25b3dc39f49..75bd864ef4b 100644
--- a/chromium/ui/events/BUILD.gn
+++ b/chromium/ui/events/BUILD.gn
@@ -3,6 +3,7 @@
# found in the LICENSE file.
import("//build/config/features.gni")
+import("//build/config/jumbo.gni")
import("//build/config/ui.gni")
import("//testing/test.gni")
import("//ui/base/ui_features.gni")
@@ -16,7 +17,7 @@ if (is_ios) {
import("//ios/build/config.gni")
}
-static_library("dom_keycode_converter") {
+jumbo_static_library("dom_keycode_converter") {
public = [
"keycodes/dom/dom_code.h",
"keycodes/dom/dom_codes.h",
@@ -92,7 +93,7 @@ source_set("platform_event") {
]
}
-component("events_base") {
+jumbo_component("events_base") {
sources = [
"base_event_utils.cc",
"base_event_utils.h",
@@ -153,62 +154,71 @@ component("events_base") {
}
}
-component("events") {
- sources = [
+jumbo_component("events") {
+ public = [
"cocoa/cocoa_event_utils.h",
- "cocoa/cocoa_event_utils.mm",
- "cocoa/events_mac.mm",
- "event.cc",
"event.h",
- "event_dispatcher.cc",
"event_dispatcher.h",
- "event_handler.cc",
"event_handler.h",
- "event_modifiers.cc",
"event_modifiers.h",
- "event_processor.cc",
"event_processor.h",
- "event_rewriter.cc",
"event_rewriter.h",
"event_sink.h",
- "event_source.cc",
"event_source.h",
- "event_target.cc",
"event_target.h",
"event_target_iterator.h",
"event_targeter.h",
- "event_utils.cc",
"event_utils.h",
"events_export.h",
- "events_stub.cc",
- "gestures/gesture_recognizer_impl_mac.cc",
+ "gestures/gesture_recognizer.h",
"gestures/gesture_recognizer_impl_mac.h",
- "gestures/gesture_types.cc",
+ "gestures/gesture_recognizer_observer.h",
"gestures/gesture_types.h",
"keyboard_hook.h",
+ "null_event_targeter.h",
+ "scoped_target_handler.h",
+ "system_input_injector.h",
+ "win/events_win_utils.h",
+ "win/system_event_state_lookup.h",
+ ]
+
+ sources = [
+ "cocoa/cocoa_event_utils.mm",
+ "cocoa/events_mac.mm",
+ "event.cc",
+ "event_dispatcher.cc",
+ "event_handler.cc",
+ "event_modifiers.cc",
+ "event_processor.cc",
+ "event_rewriter.cc",
+ "event_source.cc",
+ "event_target.cc",
+ "event_utils.cc",
+ "events_stub.cc",
+ "gestures/gesture_recognizer.cc",
+ "gestures/gesture_recognizer_impl_mac.cc",
+ "gestures/gesture_recognizer_observer.cc",
+ "gestures/gesture_types.cc",
"keyboard_hook_base.cc",
"keyboard_hook_base.h",
"keycodes/platform_key_map_win.cc",
"keycodes/platform_key_map_win.h",
"mac/keyboard_hook_mac.mm",
"null_event_targeter.cc",
- "null_event_targeter.h",
"scoped_target_handler.cc",
- "scoped_target_handler.h",
"system_input_injector.cc",
- "system_input_injector.h",
"win/events_win.cc",
"win/events_win_utils.cc",
- "win/events_win_utils.h",
"win/keyboard_hook_win.cc",
+ "win/keyboard_hook_win.h",
"win/system_event_state_lookup.cc",
- "win/system_event_state_lookup.h",
]
defines = [ "EVENTS_IMPLEMENTATION" ]
public_deps = [
":events_base",
+ "//ui/display",
"//ui/latency",
]
deps = [
@@ -216,11 +226,16 @@ component("events") {
":gesture_detection",
"//base/third_party/dynamic_annotations",
"//skia",
- "//ui/display",
"//ui/gfx",
"//ui/gfx/geometry",
]
+ # Expose the internals of this target to other packages in this BUILD file
+ # so the unit tests can access the private header files.
+ # Note: Only 'events_unittests' needs access in this file, however it uses a
+ # template which generates different target names on different platforms.
+ friend = [ ":*" ]
+
if (use_x11) {
sources += [
"x/events_x.cc",
@@ -248,23 +263,24 @@ component("events") {
}
if (use_ozone) {
+ public += [ "ozone/events_ozone.h" ]
sources += [
"ozone/events_ozone.cc",
- "ozone/events_ozone.h",
"ozone/keyboard_hook_ozone.cc",
]
deps += [ "//ui/events/ozone:events_ozone_layout" ]
}
if (use_aura) {
+ public += [
+ "gestures/gesture_provider_aura.h",
+ "gestures/gesture_recognizer_impl.h",
+ "gestures/motion_event_aura.h",
+ ]
sources += [
"gestures/gesture_provider_aura.cc",
- "gestures/gesture_provider_aura.h",
- "gestures/gesture_recognizer.h",
"gestures/gesture_recognizer_impl.cc",
- "gestures/gesture_recognizer_impl.h",
"gestures/motion_event_aura.cc",
- "gestures/motion_event_aura.h",
]
}
@@ -273,21 +289,23 @@ component("events") {
}
if (is_android) {
- sources += [
- "android/drag_event_android.cc",
+ public += [
"android/drag_event_android.h",
- "android/event_handler_android.cc",
"android/event_handler_android.h",
- "android/gesture_event_android.cc",
"android/gesture_event_android.h",
"android/gesture_event_type.h",
- "android/key_event_android.cc",
"android/key_event_android.h",
- "android/key_event_utils.cc",
"android/key_event_utils.h",
+ "android/motion_event_android.h",
+ ]
+ sources += [
+ "android/drag_event_android.cc",
+ "android/event_handler_android.cc",
+ "android/gesture_event_android.cc",
+ "android/key_event_android.cc",
+ "android/key_event_utils.cc",
"android/keyboard_hook_android.cc",
"android/motion_event_android.cc",
- "android/motion_event_android.h",
]
deps += [
":keyevent_jni_headers",
@@ -298,9 +316,18 @@ component("events") {
if (is_mac) {
libs = [ "AppKit.framework" ]
}
+
+ if (is_fuchsia) {
+ public += [
+ "fuchsia/input_event_dispatcher.h",
+ "fuchsia/input_event_dispatcher_delegate.h",
+ ]
+ sources += [ "fuchsia/input_event_dispatcher.cc" ]
+ public_deps += [ "//third_party/fuchsia-sdk/sdk:input" ]
+ }
}
-component("gesture_detection") {
+jumbo_component("gesture_detection") {
sources = [
"gesture_detection/bitset_32.h",
"gesture_detection/filtered_gesture_provider.cc",
@@ -364,7 +391,7 @@ component("gesture_detection") {
}
}
-static_library("test_support") {
+jumbo_static_library("test_support") {
sources = [
"test/cocoa_test_event_utils.h",
"test/cocoa_test_event_utils.mm",
@@ -442,6 +469,8 @@ if (!is_ios) {
"blink/fling_booster_unittest.cc",
"blink/input_handler_proxy_unittest.cc",
"blink/input_scroll_elasticity_controller_unittest.cc",
+ "blink/prediction/input_predictor_unittest_helpers.cc",
+ "blink/prediction/input_predictor_unittest_helpers.h",
"blink/prediction/kalman_predictor_unittest.cc",
"blink/prediction/least_squares_predictor_unittest.cc",
"blink/scroll_predictor_unittest.cc",
@@ -476,6 +505,7 @@ if (!is_ios) {
"platform/platform_event_source_unittest.cc",
"scoped_target_handler_unittest.cc",
"win/event_utils_win_unittest.cc",
+ "win/keyboard_hook_win_unittest.cc",
]
deps = [
@@ -491,6 +521,7 @@ if (!is_ios) {
"//ipc:test_support",
"//mojo/core/test:run_all_unittests",
"//mojo/public/cpp/bindings",
+ "//mojo/public/cpp/test_support:test_utils",
"//skia",
"//testing/gmock",
"//testing/gtest",
@@ -501,8 +532,8 @@ if (!is_ios) {
"//ui/events/devices",
"//ui/events/devices/mojo:test_interfaces",
"//ui/events/gestures/blink",
- "//ui/events/mojo:test_interfaces",
"//ui/events/platform",
+ "//ui/gfx/geometry/mojo:struct_traits",
"//ui/gfx/ipc/geometry",
]
@@ -565,6 +596,7 @@ if (!is_ios) {
if (use_aura) {
sources += [
"gestures/gesture_provider_aura_unittest.cc",
+ "gestures/gesture_recognizer_impl_unittest.cc",
"gestures/motion_event_aura_unittest.cc",
]
}
@@ -576,6 +608,10 @@ if (!is_ios) {
if (is_chromecast && !is_android) {
sources += [ "chromecast/scroller_unittest.cc" ]
}
+
+ if (is_fuchsia) {
+ sources += [ "fuchsia/input_event_dispatcher_unittest.cc" ]
+ }
}
}
diff --git a/chromium/ui/events/blink/blink_features.cc b/chromium/ui/events/blink/blink_features.cc
index 30255a53905..a88686acbcd 100644
--- a/chromium/ui/events/blink/blink_features.cc
+++ b/chromium/ui/events/blink/blink_features.cc
@@ -16,4 +16,10 @@ const base::Feature kResamplingScrollEvents{"ResamplingScrollEvents",
const base::Feature kSendMouseLeaveEvents{"SendMouseLeaveEvents",
base::FEATURE_ENABLED_BY_DEFAULT};
+
+const base::Feature kNoHoverAfterLayoutChange{
+ "NoHoverAfterLayoutChange", base::FEATURE_DISABLED_BY_DEFAULT};
+
+const base::Feature kNoHoverDuringScroll{"NoHoverDuringScroll",
+ base::FEATURE_DISABLED_BY_DEFAULT};
}
diff --git a/chromium/ui/events/blink/blink_features.h b/chromium/ui/events/blink/blink_features.h
index 64e887e0e42..c7ee6ef5495 100644
--- a/chromium/ui/events/blink/blink_features.h
+++ b/chromium/ui/events/blink/blink_features.h
@@ -19,6 +19,16 @@ extern const base::Feature kResamplingScrollEvents;
// converted to mouse move events due to a number of inconsistencies on
// the native platforms. crbug.com/450631
extern const base::Feature kSendMouseLeaveEvents;
+
+// When enabled, this feature prevents Blink from changing the hover state and
+// dispatching mouse enter/exit events for elements under the mouse after the
+// layout under the mouse cursor is changed.
+extern const base::Feature kNoHoverAfterLayoutChange;
+
+// When enabled, this feature prevents Blink from changing the hover state and
+// dispatching mouse enter/exit events for elements under the mouse as the page
+// is scrolled.
+extern const base::Feature kNoHoverDuringScroll;
}
#endif // UI_EVENTS_BLINK_BLINK_FEATURES_H_
diff --git a/chromium/ui/events/blink/input_handler_proxy.cc b/chromium/ui/events/blink/input_handler_proxy.cc
index 420df485950..d37158e58e1 100644
--- a/chromium/ui/events/blink/input_handler_proxy.cc
+++ b/chromium/ui/events/blink/input_handler_proxy.cc
@@ -466,6 +466,17 @@ void InputHandlerProxy::RecordMainThreadScrollingReasons(
DCHECK(
!cc::MainThreadScrollingReason::HasNonCompositedScrollReasons(reasons));
+ int32_t event_disposition_result =
+ (device == blink::kWebGestureDeviceTouchpad ? mouse_wheel_result_
+ : touch_result_);
+ if (event_disposition_result == DID_NOT_HANDLE) {
+ // We should also collect main thread scrolling reasons if a scroll event
+ // scrolls on impl thread but is blocked by main thread event handlers.
+ reasons |= (device == blink::kWebGestureDeviceTouchpad
+ ? cc::MainThreadScrollingReason::kWheelEventHandlerRegion
+ : cc::MainThreadScrollingReason::kTouchEventHandlerRegion);
+ }
+
// UMA_HISTOGRAM_ENUMERATION requires that the enum_max must be strictly
// greater than the sample value. kMainThreadScrollingReasonCount doesn't
// include the NotScrollingOnMain enum but the histograms do so adding
@@ -511,51 +522,6 @@ void InputHandlerProxy::RecordMainThreadScrollingReasons(
}
}
-void InputHandlerProxy::RecordScrollingThreadStatus(
- blink::WebGestureDevice device,
- uint32_t reasons) {
- if (device != blink::kWebGestureDeviceTouchpad &&
- device != blink::kWebGestureDeviceTouchscreen) {
- return;
- }
-
- ScrollingThreadStatus scrolling_thread_status = SCROLLING_ON_MAIN;
- if (reasons == cc::MainThreadScrollingReason::kNotScrollingOnMain) {
- int32_t event_disposition_result =
- (device == blink::kWebGestureDeviceTouchpad ? mouse_wheel_result_
- : touch_result_);
- switch (event_disposition_result) {
- case kEventDispositionUndefined:
- case DID_NOT_HANDLE_NON_BLOCKING_DUE_TO_FLING:
- case DID_HANDLE_NON_BLOCKING:
- case DROP_EVENT:
- scrolling_thread_status = SCROLLING_ON_COMPOSITOR;
- break;
- case DID_NOT_HANDLE:
- scrolling_thread_status = SCROLLING_ON_COMPOSITOR_BLOCKED_ON_MAIN;
- break;
- default:
- NOTREACHED();
- scrolling_thread_status = SCROLLING_ON_COMPOSITOR;
- }
- }
-
- // UMA_HISTOGRAM_ENUMERATION requires that the enum_max must be strictly
- // greater than the sample value.
- const uint32_t kScrolingThreadStatusEnumMax =
- ScrollingThreadStatus::LAST_SCROLLING_THREAD_STATUS_VALUE + 1;
-
- if (device == blink::kWebGestureDeviceTouchscreen) {
- UMA_HISTOGRAM_ENUMERATION("Renderer4.GestureScrollingThreadStatus",
- scrolling_thread_status,
- kScrolingThreadStatusEnumMax);
- } else {
- UMA_HISTOGRAM_ENUMERATION("Renderer4.WheelScrollingThreadStatus",
- scrolling_thread_status,
- kScrolingThreadStatusEnumMax);
- }
-}
-
bool InputHandlerProxy::ShouldAnimate(bool has_precise_scroll_deltas) const {
#if defined(OS_MACOSX)
// Mac does not smooth scroll wheel events (crbug.com/574283).
@@ -646,9 +612,6 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureScrollBegin(
RecordMainThreadScrollingReasons(gesture_event.SourceDevice(),
scroll_status.main_thread_scrolling_reasons);
- RecordScrollingThreadStatus(gesture_event.SourceDevice(),
- scroll_status.main_thread_scrolling_reasons);
-
InputHandlerProxy::EventDisposition result = DID_NOT_HANDLE;
scroll_sequence_ignored_ = false;
in_inertial_scrolling_ = false;
diff --git a/chromium/ui/events/blink/input_handler_proxy_unittest.cc b/chromium/ui/events/blink/input_handler_proxy_unittest.cc
index 9f5bd515b72..c0d6d6fb0b9 100644
--- a/chromium/ui/events/blink/input_handler_proxy_unittest.cc
+++ b/chromium/ui/events/blink/input_handler_proxy_unittest.cc
@@ -1375,234 +1375,6 @@ TEST(SynchronousInputHandlerProxyTest, SetOffset) {
testing::Mock::VerifyAndClearExpectations(&mock_synchronous_input_handler);
}
-TEST_P(InputHandlerProxyTest, MainThreadScrollingMouseWheelHistograms) {
- input_handler_->RecordMainThreadScrollingReasonsForTest(
- blink::kWebGestureDeviceTouchpad,
- cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects |
- cc::MainThreadScrollingReason::kThreadedScrollingDisabled |
- cc::MainThreadScrollingReason::kPageOverlay |
- cc::MainThreadScrollingReason::kHandlingScrollFromMainThread);
-
- EXPECT_THAT(
- histogram_tester().GetAllSamples("Renderer4.MainThreadWheelScrollReason"),
- testing::ElementsAre(base::Bucket(1, 1), base::Bucket(3, 1),
- base::Bucket(5, 1)));
-
- // We only want to record "Handling scroll from main thread" reason if it's
- // the only reason. If it's not the only reason, the "real" reason for
- // scrolling on main is something else, and we only want to pay attention to
- // that reason. So we should only include this reason in the histogram when
- // its on its own.
- input_handler_->RecordMainThreadScrollingReasonsForTest(
- blink::kWebGestureDeviceTouchpad,
- cc::MainThreadScrollingReason::kHandlingScrollFromMainThread);
-
- EXPECT_THAT(
- histogram_tester().GetAllSamples("Renderer4.MainThreadWheelScrollReason"),
- testing::ElementsAre(base::Bucket(1, 1), base::Bucket(3, 1),
- base::Bucket(5, 1), base::Bucket(14, 1)));
-}
-
-TEST_P(InputHandlerProxyTest, GestureScrollingThreadStatusHistogram) {
- VERIFY_AND_RESET_MOCKS();
-
- WebTouchEvent touch_start(WebInputEvent::kTouchStart,
- WebInputEvent::kNoModifiers,
- WebInputEvent::GetStaticTimeStampForTests());
- touch_start.touches_length = 1;
- touch_start.touch_start_or_first_touch_move = true;
- touch_start.touches[0] =
- CreateWebTouchPoint(WebTouchPoint::kStatePressed, 10, 10);
-
- WebGestureEvent gesture_scroll_begin(
- WebInputEvent::kGestureScrollBegin, WebInputEvent::kNoModifiers,
- WebInputEvent::GetStaticTimeStampForTests(),
- blink::kWebGestureDeviceTouchscreen);
-
- WebGestureEvent gesture_scroll_end(
- WebInputEvent::kGestureScrollEnd, WebInputEvent::kNoModifiers,
- WebInputEvent::GetStaticTimeStampForTests(),
- blink::kWebGestureDeviceTouchscreen);
-
- // Touch start with passive event listener.
- EXPECT_CALL(
- mock_input_handler_,
- EventListenerTypeForTouchStartOrMoveAt(
- testing::Property(&gfx::Point::x, testing::Gt(0)), testing::_))
- .WillOnce(testing::Return(
- cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER));
- EXPECT_CALL(
- mock_input_handler_,
- GetEventListenerProperties(cc::EventListenerClass::kTouchStartOrMove))
- .WillOnce(testing::Return(cc::EventListenerProperties::kPassive));
- EXPECT_CALL(mock_client_,
- SetWhiteListedTouchAction(testing::_, testing::_, testing::_))
- .WillOnce(testing::Return());
-
- expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
- EXPECT_EQ(expected_disposition_,
- input_handler_->HandleInputEvent(touch_start));
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(kImplThreadScrollState));
- expected_disposition_ = InputHandlerProxy::DID_HANDLE;
- EXPECT_EQ(expected_disposition_,
- input_handler_->HandleInputEvent(gesture_scroll_begin));
-
- EXPECT_THAT(histogram_tester().GetAllSamples(
- "Renderer4.GestureScrollingThreadStatus"),
- testing::ElementsAre(base::Bucket(0, 1)));
-
- EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_, true));
- expected_disposition_ = InputHandlerProxy::DID_HANDLE;
- EXPECT_EQ(expected_disposition_,
- input_handler_->HandleInputEvent(gesture_scroll_end));
-
- VERIFY_AND_RESET_MOCKS();
-
- // Touch event with HANDLER_ON_SCROLLING_LAYER event listener.
- EXPECT_CALL(
- mock_input_handler_,
- EventListenerTypeForTouchStartOrMoveAt(
- testing::Property(&gfx::Point::x, testing::Gt(0)), testing::_))
- .WillOnce(
- testing::Return(cc::InputHandler::TouchStartOrMoveEventListenerType::
- HANDLER_ON_SCROLLING_LAYER));
- EXPECT_CALL(mock_client_,
- SetWhiteListedTouchAction(testing::_, testing::_, testing::_))
- .WillOnce(testing::Return());
-
- expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
- EXPECT_EQ(expected_disposition_,
- input_handler_->HandleInputEvent(touch_start));
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(kImplThreadScrollState));
- expected_disposition_ = InputHandlerProxy::DID_HANDLE;
- EXPECT_EQ(expected_disposition_,
- input_handler_->HandleInputEvent(gesture_scroll_begin));
-
- EXPECT_THAT(histogram_tester().GetAllSamples(
- "Renderer4.GestureScrollingThreadStatus"),
- testing::ElementsAre(base::Bucket(0, 1), base::Bucket(1, 1)));
-
- EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_, true));
- expected_disposition_ = InputHandlerProxy::DID_HANDLE;
- EXPECT_EQ(expected_disposition_,
- input_handler_->HandleInputEvent(gesture_scroll_end));
-
- VERIFY_AND_RESET_MOCKS();
-
- // Gesture scrolling on main thread.
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(kMainThreadScrollState));
- expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
- EXPECT_EQ(expected_disposition_,
- input_handler_->HandleInputEvent(gesture_scroll_begin));
-
- EXPECT_THAT(histogram_tester().GetAllSamples(
- "Renderer4.GestureScrollingThreadStatus"),
- testing::ElementsAre(base::Bucket(0, 1), base::Bucket(1, 1),
- base::Bucket(2, 1)));
-
- EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_, true));
- expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
- EXPECT_EQ(expected_disposition_,
- input_handler_->HandleInputEvent(gesture_scroll_end));
-
- VERIFY_AND_RESET_MOCKS();
-}
-
-TEST_P(InputHandlerProxyTest, WheelScrollingThreadStatusHistogram) {
- VERIFY_AND_RESET_MOCKS();
-
- WebMouseWheelEvent wheel(WebInputEvent::kMouseWheel,
- WebInputEvent::kControlKey,
- WebInputEvent::GetStaticTimeStampForTests());
-
- WebGestureEvent gesture_scroll_begin(
- WebInputEvent::kGestureScrollBegin, WebInputEvent::kNoModifiers,
- WebInputEvent::GetStaticTimeStampForTests(),
- blink::kWebGestureDeviceTouchpad);
-
- WebGestureEvent gesture_scroll_end(
- WebInputEvent::kGestureScrollEnd, WebInputEvent::kNoModifiers,
- WebInputEvent::GetStaticTimeStampForTests(),
- blink::kWebGestureDeviceTouchpad);
-
- // Wheel event with passive event listener.
- EXPECT_CALL(mock_input_handler_, HasBlockingWheelEventHandlerAt(testing::_))
- .WillRepeatedly(testing::Return(false));
- EXPECT_CALL(mock_input_handler_,
- GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
- .WillOnce(testing::Return(cc::EventListenerProperties::kPassive));
- expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(wheel));
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(kImplThreadScrollState));
- expected_disposition_ = InputHandlerProxy::DID_HANDLE;
- EXPECT_EQ(expected_disposition_,
- input_handler_->HandleInputEvent(gesture_scroll_begin));
-
- EXPECT_THAT(
- histogram_tester().GetAllSamples("Renderer4.WheelScrollingThreadStatus"),
- testing::ElementsAre(base::Bucket(0, 1)));
-
- EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_, true));
- expected_disposition_ = InputHandlerProxy::DID_HANDLE;
- EXPECT_EQ(expected_disposition_,
- input_handler_->HandleInputEvent(gesture_scroll_end));
-
- VERIFY_AND_RESET_MOCKS();
-
- // Wheel event with blocking event listener. If there is a wheel event handler
- // at the point, we do not need to call GetEventListenerProperties since it
- // indicates kBlocking.
- EXPECT_CALL(mock_input_handler_, HasBlockingWheelEventHandlerAt(testing::_))
- .WillRepeatedly(testing::Return(true));
- expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
- EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(wheel));
-
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(kImplThreadScrollState));
- expected_disposition_ = InputHandlerProxy::DID_HANDLE;
- EXPECT_EQ(expected_disposition_,
- input_handler_->HandleInputEvent(gesture_scroll_begin));
-
- EXPECT_THAT(
- histogram_tester().GetAllSamples("Renderer4.WheelScrollingThreadStatus"),
- testing::ElementsAre(base::Bucket(0, 1), base::Bucket(1, 1)));
-
- EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_, true));
- expected_disposition_ = InputHandlerProxy::DID_HANDLE;
- EXPECT_EQ(expected_disposition_,
- input_handler_->HandleInputEvent(gesture_scroll_end));
-
- VERIFY_AND_RESET_MOCKS();
-
- // Wheel scrolling on main thread.
- EXPECT_CALL(mock_input_handler_, HasBlockingWheelEventHandlerAt(testing::_))
- .WillRepeatedly(testing::Return(true));
- EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
- .WillOnce(testing::Return(kMainThreadScrollState));
- expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
- EXPECT_EQ(expected_disposition_,
- input_handler_->HandleInputEvent(gesture_scroll_begin));
-
- EXPECT_THAT(
- histogram_tester().GetAllSamples("Renderer4.WheelScrollingThreadStatus"),
- testing::ElementsAre(base::Bucket(0, 1), base::Bucket(1, 1),
- base::Bucket(2, 1)));
-
- EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_, true));
- expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
- EXPECT_EQ(expected_disposition_,
- input_handler_->HandleInputEvent(gesture_scroll_end));
-
- VERIFY_AND_RESET_MOCKS();
-}
-
TEST_F(InputHandlerProxyEventQueueTest, VSyncAlignedGestureScroll) {
base::HistogramTester histogram_tester;
@@ -2103,8 +1875,423 @@ TEST_F(InputHandlerProxyEventQueueTest, ScrollPredictorTest) {
testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
}
+class InputHandlerProxyMainThreadScrollingReasonTest
+ : public InputHandlerProxyTest {
+ public:
+ enum TestEventType {
+ Touch,
+ MouseWheel,
+ };
+
+ InputHandlerProxyMainThreadScrollingReasonTest() : InputHandlerProxyTest() {}
+ ~InputHandlerProxyMainThreadScrollingReasonTest() { input_handler_.reset(); }
+
+ void SetupEvents(TestEventType type) {
+ touch_start_ =
+ WebTouchEvent(WebInputEvent::kTouchStart, WebInputEvent::kNoModifiers,
+ WebInputEvent::GetStaticTimeStampForTests());
+ touch_end_ =
+ WebTouchEvent(WebInputEvent::kTouchEnd, WebInputEvent::kNoModifiers,
+ WebInputEvent::GetStaticTimeStampForTests());
+ wheel_event_ = WebMouseWheelEvent(
+ WebInputEvent::kMouseWheel, WebInputEvent::kControlKey,
+ WebInputEvent::GetStaticTimeStampForTests());
+ gesture_scroll_begin_ = WebGestureEvent(
+ WebInputEvent::kGestureScrollBegin, WebInputEvent::kNoModifiers,
+ WebInputEvent::GetStaticTimeStampForTests(),
+ type == TestEventType::MouseWheel
+ ? blink::kWebGestureDeviceTouchpad
+ : blink::kWebGestureDeviceTouchscreen);
+ gesture_scroll_end_ = WebGestureEvent(
+ WebInputEvent::kGestureScrollEnd, WebInputEvent::kNoModifiers,
+ WebInputEvent::GetStaticTimeStampForTests(),
+ type == TestEventType::MouseWheel
+ ? blink::kWebGestureDeviceTouchpad
+ : blink::kWebGestureDeviceTouchscreen);
+ touch_start_.touches_length = 1;
+ touch_start_.touch_start_or_first_touch_move = true;
+ touch_start_.touches[0] =
+ CreateWebTouchPoint(WebTouchPoint::kStatePressed, 10, 10);
+
+ touch_end_.touches_length = 1;
+ }
+
+ base::HistogramBase::Sample GetBucketSample(uint32_t reason) {
+ if (reason == cc::MainThreadScrollingReason::kNotScrollingOnMain)
+ return 0;
+
+ uint32_t bucket = 1;
+ while ((reason = reason >> 1))
+ bucket++;
+ return bucket;
+ }
+
+ protected:
+ WebTouchEvent touch_start_;
+ WebTouchEvent touch_end_;
+ WebMouseWheelEvent wheel_event_;
+ WebGestureEvent gesture_scroll_begin_;
+ WebGestureEvent gesture_scroll_end_;
+};
+
+TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
+ GestureScrollNotScrollOnMain) {
+ // Touch start with passive event listener.
+ SetupEvents(TestEventType::Touch);
+
+ EXPECT_CALL(
+ mock_input_handler_,
+ EventListenerTypeForTouchStartOrMoveAt(
+ testing::Property(&gfx::Point::x, testing::Gt(0)), testing::_))
+ .WillOnce(testing::Return(
+ cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER));
+ EXPECT_CALL(
+ mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kTouchStartOrMove))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kPassive));
+ EXPECT_CALL(mock_client_,
+ SetWhiteListedTouchAction(testing::_, testing::_, testing::_))
+ .WillOnce(testing::Return());
+
+ expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(touch_start_));
+
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(kImplThreadScrollState));
+ expected_disposition_ = InputHandlerProxy::DID_HANDLE;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(gesture_scroll_begin_));
+ EXPECT_THAT(
+ histogram_tester().GetAllSamples(
+ "Renderer4.MainThreadGestureScrollReason"),
+ testing::ElementsAre(base::Bucket(
+ GetBucketSample(cc::MainThreadScrollingReason::kNotScrollingOnMain),
+ 1)));
+
+ EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_, true));
+ expected_disposition_ = InputHandlerProxy::DID_HANDLE;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(gesture_scroll_end_));
+}
+
+TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
+ GestureScrollTouchEventHandlerRegion) {
+ // The touch event hits a touch event handler and should block on main thread.
+ // Since ScrollBegin allows the gesture to scroll on impl. We collect
+ // TouchEventHandler reason but not HandlingScrollFromMainThread.
+ SetupEvents(TestEventType::Touch);
+
+ EXPECT_CALL(
+ mock_input_handler_,
+ EventListenerTypeForTouchStartOrMoveAt(
+ testing::Property(&gfx::Point::x, testing::Gt(0)), testing::_))
+ .WillOnce(
+ testing::Return(cc::InputHandler::TouchStartOrMoveEventListenerType::
+ HANDLER_ON_SCROLLING_LAYER));
+ EXPECT_CALL(mock_client_,
+ SetWhiteListedTouchAction(testing::_, testing::_, testing::_))
+ .WillOnce(testing::Return());
+
+ expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(touch_start_));
+
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(kImplThreadScrollState));
+ expected_disposition_ = InputHandlerProxy::DID_HANDLE;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(gesture_scroll_begin_));
+ EXPECT_THAT(histogram_tester().GetAllSamples(
+ "Renderer4.MainThreadGestureScrollReason"),
+ testing::ElementsAre(base::Bucket(
+ GetBucketSample(
+ cc::MainThreadScrollingReason::kTouchEventHandlerRegion),
+ 1)));
+
+ EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_, true));
+ expected_disposition_ = InputHandlerProxy::DID_HANDLE;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(gesture_scroll_end_));
+}
+
+TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
+ GestureScrollTouchEventHandlerRegionAndHandlingScrollFromMainThread) {
+ // The touch event hits a touch event handler and should block on main thread.
+ // Since ScrollBegin doesn't allow the gesture to scroll on impl. We report
+ // TouchEventHandler reason as well as HandlingScrollFromMainThread. Since we
+ // do not collect HandlingScrollFromMainThread when there are other reasons
+ // present, TouchEventHandler is the only reason being collected in the
+ // histogram.
+ SetupEvents(TestEventType::Touch);
+
+ EXPECT_CALL(
+ mock_input_handler_,
+ EventListenerTypeForTouchStartOrMoveAt(
+ testing::Property(&gfx::Point::x, testing::Gt(0)), testing::_))
+ .WillOnce(
+ testing::Return(cc::InputHandler::TouchStartOrMoveEventListenerType::
+ HANDLER_ON_SCROLLING_LAYER));
+ EXPECT_CALL(mock_client_,
+ SetWhiteListedTouchAction(testing::_, testing::_, testing::_))
+ .WillOnce(testing::Return());
+
+ expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(touch_start_));
+
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(kMainThreadScrollState));
+ expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(gesture_scroll_begin_));
+
+ EXPECT_THAT(histogram_tester().GetAllSamples(
+ "Renderer4.MainThreadGestureScrollReason"),
+ testing::ElementsAre(base::Bucket(
+ GetBucketSample(
+ cc::MainThreadScrollingReason::kTouchEventHandlerRegion),
+ 1)));
+
+ // Handle touch end event so that input handler proxy is out of the state of
+ // DID_NOT_HANDLE.
+ EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_, true));
+ expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(gesture_scroll_end_));
+
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(touch_end_));
+}
+
+TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
+ GestureScrollHandlingScrollFromMainThread) {
+ // Gesture scrolling on main thread. We only record
+ // HandlingScrollFromMainThread when it's the only available reason.
+ SetupEvents(TestEventType::Touch);
+ EXPECT_CALL(
+ mock_input_handler_,
+ EventListenerTypeForTouchStartOrMoveAt(
+ testing::Property(&gfx::Point::x, testing::Gt(0)), testing::_))
+ .WillOnce(testing::Return(
+ cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER));
+ EXPECT_CALL(mock_client_,
+ SetWhiteListedTouchAction(testing::_, testing::_, testing::_))
+ .WillOnce(testing::Return());
+ EXPECT_CALL(mock_input_handler_, GetEventListenerProperties(testing::_))
+ .WillRepeatedly(testing::Return(cc::EventListenerProperties::kPassive));
+
+ expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(touch_start_));
+
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(kMainThreadScrollState));
+ expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(gesture_scroll_begin_));
+
+ EXPECT_THAT(
+ histogram_tester().GetAllSamples(
+ "Renderer4.MainThreadGestureScrollReason"),
+ testing::ElementsAre(base::Bucket(
+ GetBucketSample(
+ cc::MainThreadScrollingReason::kHandlingScrollFromMainThread),
+ 1)));
+
+ EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_, true));
+ expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(gesture_scroll_end_));
+}
+
+TEST_P(InputHandlerProxyMainThreadScrollingReasonTest, WheelScrollHistogram) {
+ // Firstly check if input handler can correctly record main thread scrolling
+ // reasons.
+ input_handler_->RecordMainThreadScrollingReasonsForTest(
+ blink::kWebGestureDeviceTouchpad,
+ cc::MainThreadScrollingReason::kHasBackgroundAttachmentFixedObjects |
+ cc::MainThreadScrollingReason::kThreadedScrollingDisabled |
+ cc::MainThreadScrollingReason::kPageOverlay |
+ cc::MainThreadScrollingReason::kHandlingScrollFromMainThread);
+
+ EXPECT_THAT(
+ histogram_tester().GetAllSamples("Renderer4.MainThreadWheelScrollReason"),
+ testing::ElementsAre(
+ base::Bucket(
+ GetBucketSample(cc::MainThreadScrollingReason::
+ kHasBackgroundAttachmentFixedObjects),
+ 1),
+ base::Bucket(
+ GetBucketSample(
+ cc::MainThreadScrollingReason::kThreadedScrollingDisabled),
+ 1),
+ base::Bucket(
+ GetBucketSample(cc::MainThreadScrollingReason::kPageOverlay),
+ 1)));
+
+ // We only want to record "Handling scroll from main thread" reason if it's
+ // the only reason. If it's not the only reason, the "real" reason for
+ // scrolling on main is something else, and we only want to pay attention to
+ // that reason. So we should only include this reason in the histogram when
+ // its on its own.
+ input_handler_->RecordMainThreadScrollingReasonsForTest(
+ blink::kWebGestureDeviceTouchpad,
+ cc::MainThreadScrollingReason::kHandlingScrollFromMainThread);
+
+ EXPECT_THAT(
+ histogram_tester().GetAllSamples("Renderer4.MainThreadWheelScrollReason"),
+ testing::ElementsAre(
+ base::Bucket(
+ GetBucketSample(cc::MainThreadScrollingReason::
+ kHasBackgroundAttachmentFixedObjects),
+ 1),
+ base::Bucket(
+ GetBucketSample(
+ cc::MainThreadScrollingReason::kThreadedScrollingDisabled),
+ 1),
+ base::Bucket(
+ GetBucketSample(cc::MainThreadScrollingReason::kPageOverlay), 1),
+ base::Bucket(
+ GetBucketSample(
+ cc::MainThreadScrollingReason::kHandlingScrollFromMainThread),
+ 1)));
+}
+
+TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
+ WheelScrollNotScrollingOnMain) {
+ // Even if a scroller is composited, we still need to record its main thread
+ // scrolling reason if it is blocked on a main thread event handler.
+ SetupEvents(TestEventType::MouseWheel);
+
+ // We can scroll on impl for an wheel event with passive event listener.
+ EXPECT_CALL(mock_input_handler_, HasBlockingWheelEventHandlerAt(testing::_))
+ .WillRepeatedly(testing::Return(false));
+ EXPECT_CALL(mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kPassive));
+ expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(wheel_event_));
+
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(kImplThreadScrollState));
+ expected_disposition_ = InputHandlerProxy::DID_HANDLE;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(gesture_scroll_begin_));
+
+ EXPECT_THAT(
+ histogram_tester().GetAllSamples("Renderer4.MainThreadWheelScrollReason"),
+ testing::ElementsAre(base::Bucket(
+ GetBucketSample(cc::MainThreadScrollingReason::kNotScrollingOnMain),
+ 1)));
+
+ EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_, true));
+ expected_disposition_ = InputHandlerProxy::DID_HANDLE;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(gesture_scroll_end_));
+}
+
+TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
+ WheelScrollWheelEventHandlerRegion) {
+ // Wheel event with blocking event listener. If there is a wheel event handler
+ // at the point, we do not need to call GetEventListenerProperties since it
+ // indicates kBlocking.
+ SetupEvents(TestEventType::MouseWheel);
+ EXPECT_CALL(mock_input_handler_, HasBlockingWheelEventHandlerAt(testing::_))
+ .WillRepeatedly(testing::Return(true));
+ expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(wheel_event_));
+
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(kImplThreadScrollState));
+ expected_disposition_ = InputHandlerProxy::DID_HANDLE;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(gesture_scroll_begin_));
+
+ EXPECT_THAT(
+ histogram_tester().GetAllSamples("Renderer4.MainThreadWheelScrollReason"),
+ testing::ElementsAre(base::Bucket(
+ GetBucketSample(
+ cc::MainThreadScrollingReason::kWheelEventHandlerRegion),
+ 1)));
+
+ EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_, true));
+ expected_disposition_ = InputHandlerProxy::DID_HANDLE;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(gesture_scroll_end_));
+}
+
+TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
+ WheelScrollWheelEventHandlerRegionAndHandlingScrollFromMainThread) {
+ // Wheel scrolling on main thread. Because we also block scrolling with wheel
+ // event handler, we should record that reason as well.
+ SetupEvents(TestEventType::MouseWheel);
+ EXPECT_CALL(mock_input_handler_, HasBlockingWheelEventHandlerAt(testing::_))
+ .WillRepeatedly(testing::Return(true));
+ expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(wheel_event_));
+
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(kMainThreadScrollState));
+ expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(gesture_scroll_begin_));
+
+ EXPECT_THAT(
+ histogram_tester().GetAllSamples("Renderer4.MainThreadWheelScrollReason"),
+ testing::ElementsAre(base::Bucket(
+ GetBucketSample(
+ cc::MainThreadScrollingReason::kWheelEventHandlerRegion),
+ 1)));
+
+ EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_, true));
+ expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(gesture_scroll_end_));
+}
+
+TEST_P(InputHandlerProxyMainThreadScrollingReasonTest,
+ WheelScrollHandlingScrollFromMainThread) {
+ // Gesture scrolling on main thread. We only record
+ // HandlingScrollFromMainThread when it's the only available reason.
+ SetupEvents(TestEventType::MouseWheel);
+ EXPECT_CALL(mock_input_handler_, HasBlockingWheelEventHandlerAt(testing::_))
+ .WillRepeatedly(testing::Return(false));
+ EXPECT_CALL(mock_input_handler_,
+ GetEventListenerProperties(cc::EventListenerClass::kMouseWheel))
+ .WillOnce(testing::Return(cc::EventListenerProperties::kNone));
+ expected_disposition_ = InputHandlerProxy::DROP_EVENT;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(wheel_event_));
+
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(kMainThreadScrollState));
+ expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(gesture_scroll_begin_));
+
+ EXPECT_THAT(
+ histogram_tester().GetAllSamples("Renderer4.MainThreadWheelScrollReason"),
+ testing::ElementsAre(base::Bucket(
+ GetBucketSample(
+ cc::MainThreadScrollingReason::kHandlingScrollFromMainThread),
+ 1)));
+
+ EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_, true));
+ expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
+ EXPECT_EQ(expected_disposition_,
+ input_handler_->HandleInputEvent(gesture_scroll_end_));
+}
+
INSTANTIATE_TEST_CASE_P(AnimateInput,
InputHandlerProxyTest,
testing::ValuesIn(test_types));
+
+INSTANTIATE_TEST_CASE_P(AnimateInput,
+ InputHandlerProxyMainThreadScrollingReasonTest,
+ testing::ValuesIn(test_types));
} // namespace test
} // namespace ui
diff --git a/chromium/ui/events/blink/prediction/input_predictor_unittest_helpers.cc b/chromium/ui/events/blink/prediction/input_predictor_unittest_helpers.cc
new file mode 100644
index 00000000000..9912ea66222
--- /dev/null
+++ b/chromium/ui/events/blink/prediction/input_predictor_unittest_helpers.cc
@@ -0,0 +1,31 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/blink/prediction/input_predictor_unittest_helpers.h"
+
+namespace ui {
+
+InputPredictorTest::InputPredictorTest() = default;
+InputPredictorTest::~InputPredictorTest() = default;
+
+void InputPredictorTest::ValidatePredictor(
+ const std::vector<double>& x,
+ const std::vector<double>& y,
+ const std::vector<double>& timestamp_ms) {
+ predictor_->Reset();
+ for (size_t i = 0; i < timestamp_ms.size(); i++) {
+ if (predictor_->HasPrediction()) {
+ ui::InputPredictor::InputData result;
+ EXPECT_TRUE(predictor_->GeneratePrediction(
+ FromMilliseconds(timestamp_ms[i]), &result));
+ EXPECT_NEAR(result.pos.x(), x[i], kEpsilon);
+ EXPECT_NEAR(result.pos.y(), y[i], kEpsilon);
+ }
+ InputPredictor::InputData data = {gfx::PointF(x[i], y[i]),
+ FromMilliseconds(timestamp_ms[i])};
+ predictor_->Update(data);
+ }
+}
+
+} // namespace ui
diff --git a/chromium/ui/events/blink/prediction/input_predictor_unittest.cc b/chromium/ui/events/blink/prediction/input_predictor_unittest_helpers.h
index ec8a051a363..569d7a2e74b 100644
--- a/chromium/ui/events/blink/prediction/input_predictor_unittest.cc
+++ b/chromium/ui/events/blink/prediction/input_predictor_unittest_helpers.h
@@ -2,25 +2,21 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_EVENTS_BLINK_PREDICTION_INPUT_PREDICTOR_UNITTEST_H_
-#define UI_EVENTS_BLINK_PREDICTION_INPUT_PREDICTOR_UNITTEST_H_
+#ifndef UI_EVENTS_BLINK_PREDICTION_INPUT_PREDICTOR_UNITTEST_HELPERS_H_
+#define UI_EVENTS_BLINK_PREDICTION_INPUT_PREDICTOR_UNITTEST_HELPERS_H_
#include "ui/events/blink/prediction/input_predictor.h"
+
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/blink/blink_event_util.h"
-namespace {
-
-constexpr double kEpsilon = 0.1;
-
-} // namespace
-
namespace ui {
// Base class for predictor unit tests
class InputPredictorTest : public testing::Test {
public:
- InputPredictorTest() {}
+ InputPredictorTest();
+ ~InputPredictorTest() override;
static base::TimeTicks FromMilliseconds(int64_t ms) {
return blink::WebInputEvent::GetStaticTimeStampForTests() +
@@ -29,23 +25,11 @@ class InputPredictorTest : public testing::Test {
void ValidatePredictor(const std::vector<double>& x,
const std::vector<double>& y,
- const std::vector<double>& timestamp_ms) {
- predictor_->Reset();
- for (size_t i = 0; i < timestamp_ms.size(); i++) {
- if (predictor_->HasPrediction()) {
- ui::InputPredictor::InputData result;
- EXPECT_TRUE(predictor_->GeneratePrediction(
- FromMilliseconds(timestamp_ms[i]), &result));
- EXPECT_NEAR(result.pos.x(), x[i], kEpsilon);
- EXPECT_NEAR(result.pos.y(), y[i], kEpsilon);
- }
- InputPredictor::InputData data = {gfx::PointF(x[i], y[i]),
- FromMilliseconds(timestamp_ms[i])};
- predictor_->Update(data);
- }
- }
+ const std::vector<double>& timestamp_ms);
protected:
+ static constexpr double kEpsilon = 0.1;
+
std::unique_ptr<InputPredictor> predictor_;
DISALLOW_COPY_AND_ASSIGN(InputPredictorTest);
@@ -53,4 +37,4 @@ class InputPredictorTest : public testing::Test {
} // namespace ui
-#endif // UI_EVENTS_BLINK_PREDICTION_INPUT_PREDICTOR_UNITTEST_H_
+#endif // UI_EVENTS_BLINK_PREDICTION_INPUT_PREDICTOR_UNITTEST_HELPERS_H_
diff --git a/chromium/ui/events/blink/prediction/kalman_predictor_unittest.cc b/chromium/ui/events/blink/prediction/kalman_predictor_unittest.cc
index 6a4074cf02c..4d8a1d80deb 100644
--- a/chromium/ui/events/blink/prediction/kalman_predictor_unittest.cc
+++ b/chromium/ui/events/blink/prediction/kalman_predictor_unittest.cc
@@ -5,7 +5,7 @@
#include <vector>
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/events/blink/prediction/input_predictor_unittest.cc"
+#include "ui/events/blink/prediction/input_predictor_unittest_helpers.h"
#include "ui/events/blink/prediction/kalman_predictor.h"
namespace ui {
@@ -13,7 +13,6 @@ namespace test {
namespace {
constexpr uint32_t kExpectedStableIterNum = 4;
-constexpr double kEpsilon = 0.001;
struct DataSet {
double initial_observation;
@@ -26,6 +25,7 @@ struct DataSet {
void ValidateSingleKalmanFilter(const DataSet& data) {
std::unique_ptr<KalmanFilter> kalman_filter =
std::make_unique<KalmanFilter>();
+ constexpr double kEpsilon = 0.001;
constexpr double kDtMillisecond = 8;
kalman_filter->Update(data.initial_observation, kDtMillisecond);
for (size_t i = 0; i < data.observation.size(); i++) {
diff --git a/chromium/ui/events/blink/prediction/least_squares_predictor.cc b/chromium/ui/events/blink/prediction/least_squares_predictor.cc
index 94f1be7dabd..534d3de407d 100644
--- a/chromium/ui/events/blink/prediction/least_squares_predictor.cc
+++ b/chromium/ui/events/blink/prediction/least_squares_predictor.cc
@@ -10,12 +10,12 @@ namespace ui {
namespace {
-constexpr double kEpsilon = std::numeric_limits<double>::epsilon();
-
// Solve XB = y.
static bool SolveLeastSquares(const gfx::Matrix3F& x,
const std::deque<double>& y,
gfx::Vector3dF& result) {
+ constexpr double kEpsilon = std::numeric_limits<double>::epsilon();
+
// return last point if y didn't change.
if (std::abs(y[0] - y[1]) < kEpsilon && std::abs(y[1] - y[2]) < kEpsilon) {
result = gfx::Vector3dF(y[2], 0, 0);
diff --git a/chromium/ui/events/blink/prediction/least_squares_predictor_unittest.cc b/chromium/ui/events/blink/prediction/least_squares_predictor_unittest.cc
index c4836f01b47..d1d2c032ef2 100644
--- a/chromium/ui/events/blink/prediction/least_squares_predictor_unittest.cc
+++ b/chromium/ui/events/blink/prediction/least_squares_predictor_unittest.cc
@@ -4,7 +4,7 @@
#include "ui/events/blink/prediction/least_squares_predictor.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/events/blink/prediction/input_predictor_unittest.cc"
+#include "ui/events/blink/prediction/input_predictor_unittest_helpers.h"
namespace ui {
namespace test {
diff --git a/chromium/ui/events/blink/web_input_event.cc b/chromium/ui/events/blink/web_input_event.cc
index e693fc2e1ca..5f318baf91e 100644
--- a/chromium/ui/events/blink/web_input_event.cc
+++ b/chromium/ui/events/blink/web_input_event.cc
@@ -8,6 +8,7 @@
#include "ui/events/blink/blink_event_util.h"
#include "ui/events/blink/blink_features.h"
#include "ui/events/event.h"
+#include "ui/events/event_target.h"
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/events/keycodes/keyboard_code_conversion.h"
@@ -24,12 +25,8 @@ namespace ui {
namespace {
-gfx::PointF GetScreenLocationFromEvent(
- const LocatedEvent& event,
- const base::Callback<gfx::PointF(const LocatedEvent& event)>&
- screen_location_callback) {
- DCHECK(!screen_location_callback.is_null());
- return event.target() ? screen_location_callback.Run(event)
+gfx::PointF GetScreenLocationFromEvent(const LocatedEvent& event) {
+ return event.target() ? event.target()->GetScreenLocationF(event)
: event.root_location_f();
}
@@ -232,12 +229,11 @@ blink::WebMouseWheelEvent MakeWebMouseWheelEventFromUiEvent(
// The only place where an Event's data differs from what the underlying
// PlatformEvent would provide is position data. We would like to provide
// coordinates relative to its hosting window, rather than the top level
-// platform window. To do this a callback is accepted to allow for clients to
-// map the coordinates.
+// platform window. The event target is used to get the screen coordinates.
//
// The approach is to fully construct a blink::WebInputEvent from the
// Event's PlatformEvent, and then replace the coordinate fields with
-// the translated values from the Event.
+// the translated values from the Event (and EventTarget).
//
// The exception is mouse events on linux. The MouseEvent contains enough
// necessary information to construct a WebMouseEvent. So instead of extracting
@@ -246,10 +242,7 @@ blink::WebMouseWheelEvent MakeWebMouseWheelEventFromUiEvent(
// MouseEvent. This will not be necessary once only XInput2 is supported.
//
-blink::WebMouseEvent MakeWebMouseEvent(
- const MouseEvent& event,
- const base::Callback<gfx::PointF(const LocatedEvent& event)>&
- screen_location_callback) {
+blink::WebMouseEvent MakeWebMouseEvent(const MouseEvent& event) {
// Construct an untranslated event from the platform event data.
blink::WebMouseEvent webkit_event =
#if defined(OS_WIN)
@@ -273,17 +266,13 @@ blink::WebMouseEvent MakeWebMouseEvent(
return webkit_event;
#endif
- const gfx::PointF screen_point =
- GetScreenLocationFromEvent(event, screen_location_callback);
+ const gfx::PointF screen_point = GetScreenLocationFromEvent(event);
webkit_event.SetPositionInScreen(screen_point.x(), screen_point.y());
return webkit_event;
}
-blink::WebMouseWheelEvent MakeWebMouseWheelEvent(
- const MouseWheelEvent& event,
- const base::Callback<gfx::PointF(const LocatedEvent& event)>&
- screen_location_callback) {
+blink::WebMouseWheelEvent MakeWebMouseWheelEvent(const MouseWheelEvent& event) {
#if defined(OS_WIN)
// Construct an untranslated event from the platform event data.
blink::WebMouseWheelEvent webkit_event =
@@ -302,17 +291,13 @@ blink::WebMouseWheelEvent MakeWebMouseWheelEvent(
// |event|.
webkit_event.SetPositionInWidget(event.x(), event.y());
- const gfx::PointF screen_point =
- GetScreenLocationFromEvent(event, screen_location_callback);
+ const gfx::PointF screen_point = GetScreenLocationFromEvent(event);
webkit_event.SetPositionInScreen(screen_point.x(), screen_point.y());
return webkit_event;
}
-blink::WebMouseWheelEvent MakeWebMouseWheelEvent(
- const ScrollEvent& event,
- const base::Callback<gfx::PointF(const LocatedEvent& event)>&
- screen_location_callback) {
+blink::WebMouseWheelEvent MakeWebMouseWheelEvent(const ScrollEvent& event) {
#if defined(OS_WIN)
// Construct an untranslated event from the platform event data.
blink::WebMouseWheelEvent webkit_event =
@@ -331,8 +316,7 @@ blink::WebMouseWheelEvent MakeWebMouseWheelEvent(
// |event|.
webkit_event.SetPositionInWidget(event.x(), event.y());
- const gfx::PointF screen_point =
- GetScreenLocationFromEvent(event, screen_location_callback);
+ const gfx::PointF screen_point = GetScreenLocationFromEvent(event);
webkit_event.SetPositionInScreen(screen_point.x(), screen_point.y());
return webkit_event;
@@ -363,30 +347,22 @@ blink::WebKeyboardEvent MakeWebKeyboardEvent(const KeyEvent& event) {
return webkit_event;
}
-blink::WebGestureEvent MakeWebGestureEvent(
- const GestureEvent& event,
- const base::Callback<gfx::PointF(const LocatedEvent& event)>&
- screen_location_callback) {
+blink::WebGestureEvent MakeWebGestureEvent(const GestureEvent& event) {
blink::WebGestureEvent gesture_event = MakeWebGestureEventFromUIEvent(event);
gesture_event.SetPositionInWidget(event.location_f());
- const gfx::PointF screen_point =
- GetScreenLocationFromEvent(event, screen_location_callback);
+ const gfx::PointF screen_point = GetScreenLocationFromEvent(event);
gesture_event.SetPositionInScreen(screen_point);
return gesture_event;
}
-blink::WebGestureEvent MakeWebGestureEvent(
- const ScrollEvent& event,
- const base::Callback<gfx::PointF(const LocatedEvent& event)>&
- screen_location_callback) {
+blink::WebGestureEvent MakeWebGestureEvent(const ScrollEvent& event) {
blink::WebGestureEvent gesture_event = MakeWebGestureEventFromUiEvent(event);
gesture_event.SetPositionInWidget(event.location_f());
- const gfx::PointF screen_point =
- GetScreenLocationFromEvent(event, screen_location_callback);
+ const gfx::PointF screen_point = GetScreenLocationFromEvent(event);
gesture_event.SetPositionInScreen(screen_point);
return gesture_event;
diff --git a/chromium/ui/events/blink/web_input_event.h b/chromium/ui/events/blink/web_input_event.h
index 17d90025a14..277851aea73 100644
--- a/chromium/ui/events/blink/web_input_event.h
+++ b/chromium/ui/events/blink/web_input_event.h
@@ -5,7 +5,6 @@
#ifndef UI_EVENTS_BLINK_WEB_INPUT_EVENT_H_
#define UI_EVENTS_BLINK_WEB_INPUT_EVENT_H_
-#include "base/callback.h"
#include "third_party/blink/public/platform/web_gesture_event.h"
#include "third_party/blink/public/platform/web_input_event.h"
#include "third_party/blink/public/platform/web_keyboard_event.h"
@@ -15,42 +14,17 @@
namespace ui {
class GestureEvent;
class KeyEvent;
-class LocatedEvent;
class MouseEvent;
class MouseWheelEvent;
class ScrollEvent;
-// Several methods take a |screen_location_callback| which should translate the
-// provided coordinates relative to the hosting window, rather than the top
-// level platform window.
-//
-// If a valid event cannot be created, then the returned events will have the
-// type UNKNOWN.
-//
-// TODO(jonross): Ideally this callback would not be needed. The callback should
-// be removed once ui::Event::root_location has been deprecated and replaced
-// with ui::Event::screen_location (crbug.com/608547)
-blink::WebMouseEvent MakeWebMouseEvent(
- const MouseEvent& event,
- const base::Callback<gfx::PointF(const ui::LocatedEvent& event)>&
- screen_location_callback);
-blink::WebMouseWheelEvent MakeWebMouseWheelEvent(
- const MouseWheelEvent& event,
- const base::Callback<gfx::PointF(const ui::LocatedEvent& event)>&
- screen_location_callback);
-blink::WebMouseWheelEvent MakeWebMouseWheelEvent(
- const ScrollEvent& event,
- const base::Callback<gfx::PointF(const ui::LocatedEvent& event)>&
- screen_location_callback);
+// If a valid event cannot be created, the returned event type will be UNKNOWN.
+blink::WebMouseEvent MakeWebMouseEvent(const MouseEvent& event);
+blink::WebMouseWheelEvent MakeWebMouseWheelEvent(const MouseWheelEvent& event);
+blink::WebMouseWheelEvent MakeWebMouseWheelEvent(const ScrollEvent& event);
blink::WebKeyboardEvent MakeWebKeyboardEvent(const KeyEvent& event);
-blink::WebGestureEvent MakeWebGestureEvent(
- const GestureEvent& event,
- const base::Callback<gfx::PointF(const ui::LocatedEvent& event)>&
- screen_location_callback);
-blink::WebGestureEvent MakeWebGestureEvent(
- const ScrollEvent& event,
- const base::Callback<gfx::PointF(const ui::LocatedEvent& event)>&
- screen_location_callback);
+blink::WebGestureEvent MakeWebGestureEvent(const GestureEvent& event);
+blink::WebGestureEvent MakeWebGestureEvent(const ScrollEvent& event);
blink::WebGestureEvent MakeWebGestureEventFlingCancel(
const blink::WebMouseWheelEvent& wheel_event);
diff --git a/chromium/ui/events/blink/web_input_event_traits.cc b/chromium/ui/events/blink/web_input_event_traits.cc
index 4d1cccadb84..ba06edfb546 100644
--- a/chromium/ui/events/blink/web_input_event_traits.cc
+++ b/chromium/ui/events/blink/web_input_event_traits.cc
@@ -243,18 +243,6 @@ bool WebInputEventTraits::ShouldBlockEventStream(const WebInputEvent& event) {
}
}
-bool WebInputEventTraits::CanCauseScroll(
- const blink::WebMouseWheelEvent& event) {
-#if defined(USE_AURA)
- // Scroll events generated from the mouse wheel when the control key is held
- // don't trigger scrolling. Instead, they may cause zooming.
- return event.has_precise_scrolling_deltas ||
- (event.GetModifiers() & blink::WebInputEvent::kControlKey) == 0;
-#else
- return true;
-#endif
-}
-
uint32_t WebInputEventTraits::GetUniqueTouchEventId(
const WebInputEvent& event) {
if (WebInputEvent::IsTouchEventType(event.GetType())) {
diff --git a/chromium/ui/events/blink/web_input_event_traits.h b/chromium/ui/events/blink/web_input_event_traits.h
index 15708011280..ecaf878c2b2 100644
--- a/chromium/ui/events/blink/web_input_event_traits.h
+++ b/chromium/ui/events/blink/web_input_event_traits.h
@@ -10,7 +10,6 @@
namespace blink {
class WebGestureEvent;
-class WebMouseWheelEvent;
}
namespace ui {
@@ -30,8 +29,6 @@ class WebInputEventTraits {
static WebScopedInputEvent Clone(const blink::WebInputEvent& event);
static bool ShouldBlockEventStream(const blink::WebInputEvent& event);
- static bool CanCauseScroll(const blink::WebMouseWheelEvent& event);
-
// Return uniqueTouchEventId for WebTouchEvent, otherwise return 0.
static uint32_t GetUniqueTouchEventId(const blink::WebInputEvent& event);
static LatencyInfo CreateLatencyInfoForWebGestureEvent(
diff --git a/chromium/ui/events/blink/web_input_event_unittest.cc b/chromium/ui/events/blink/web_input_event_unittest.cc
index ae13e468d74..c304c997ff4 100644
--- a/chromium/ui/events/blink/web_input_event_unittest.cc
+++ b/chromium/ui/events/blink/web_input_event_unittest.cc
@@ -7,7 +7,6 @@
#include <stddef.h>
#include <stdint.h>
-#include "base/bind.h"
#include "base/macros.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -27,14 +26,6 @@
namespace ui {
-namespace {
-
-gfx::PointF GetScreenLocationFromEvent(const LocatedEvent& event) {
- return event.root_location_f();
-}
-
-} // namespace
-
// Checks that MakeWebKeyboardEvent makes a DOM3 spec compliant key event.
// crbug.com/127142
TEST(WebInputEventTest, TestMakeWebKeyboardEvent) {
@@ -251,8 +242,7 @@ TEST(WebInputEventTest, TestMakeWebMouseEvent) {
MouseEvent ui_event(ET_MOUSE_PRESSED, gfx::Point(123, 321),
gfx::Point(123, 321), timestamp, EF_LEFT_MOUSE_BUTTON,
EF_LEFT_MOUSE_BUTTON);
- blink::WebMouseEvent webkit_event =
- MakeWebMouseEvent(ui_event, base::Bind(&GetScreenLocationFromEvent));
+ blink::WebMouseEvent webkit_event = MakeWebMouseEvent(ui_event);
EXPECT_EQ(EventFlagsToWebEventModifiers(ui_event.flags()),
webkit_event.GetModifiers());
EXPECT_EQ(timestamp, webkit_event.TimeStamp());
@@ -268,8 +258,7 @@ TEST(WebInputEventTest, TestMakeWebMouseEvent) {
MouseEvent ui_event(ET_MOUSE_RELEASED, gfx::Point(123, 321),
gfx::Point(123, 321), timestamp, 0,
EF_LEFT_MOUSE_BUTTON);
- blink::WebMouseEvent webkit_event =
- MakeWebMouseEvent(ui_event, base::Bind(&GetScreenLocationFromEvent));
+ blink::WebMouseEvent webkit_event = MakeWebMouseEvent(ui_event);
EXPECT_EQ(EventFlagsToWebEventModifiers(ui_event.flags()),
webkit_event.GetModifiers());
EXPECT_EQ(timestamp, webkit_event.TimeStamp());
@@ -285,8 +274,7 @@ TEST(WebInputEventTest, TestMakeWebMouseEvent) {
MouseEvent ui_event(ET_MOUSE_PRESSED, gfx::Point(123, 321),
gfx::Point(123, 321), timestamp, EF_MIDDLE_MOUSE_BUTTON,
EF_MIDDLE_MOUSE_BUTTON);
- blink::WebMouseEvent webkit_event =
- MakeWebMouseEvent(ui_event, base::Bind(&GetScreenLocationFromEvent));
+ blink::WebMouseEvent webkit_event = MakeWebMouseEvent(ui_event);
EXPECT_EQ(EventFlagsToWebEventModifiers(ui_event.flags()),
webkit_event.GetModifiers());
EXPECT_EQ(timestamp, webkit_event.TimeStamp());
@@ -302,8 +290,7 @@ TEST(WebInputEventTest, TestMakeWebMouseEvent) {
MouseEvent ui_event(ET_MOUSE_RELEASED, gfx::Point(123, 321),
gfx::Point(123, 321), timestamp, 0,
EF_MIDDLE_MOUSE_BUTTON);
- blink::WebMouseEvent webkit_event =
- MakeWebMouseEvent(ui_event, base::Bind(&GetScreenLocationFromEvent));
+ blink::WebMouseEvent webkit_event = MakeWebMouseEvent(ui_event);
EXPECT_EQ(EventFlagsToWebEventModifiers(ui_event.flags()),
webkit_event.GetModifiers());
EXPECT_EQ(timestamp, webkit_event.TimeStamp());
@@ -319,8 +306,7 @@ TEST(WebInputEventTest, TestMakeWebMouseEvent) {
MouseEvent ui_event(ET_MOUSE_PRESSED, gfx::Point(123, 321),
gfx::Point(123, 321), timestamp, EF_RIGHT_MOUSE_BUTTON,
EF_RIGHT_MOUSE_BUTTON);
- blink::WebMouseEvent webkit_event =
- MakeWebMouseEvent(ui_event, base::Bind(&GetScreenLocationFromEvent));
+ blink::WebMouseEvent webkit_event = MakeWebMouseEvent(ui_event);
EXPECT_EQ(EventFlagsToWebEventModifiers(ui_event.flags()),
webkit_event.GetModifiers());
EXPECT_EQ(timestamp, webkit_event.TimeStamp());
@@ -336,8 +322,7 @@ TEST(WebInputEventTest, TestMakeWebMouseEvent) {
MouseEvent ui_event(ET_MOUSE_RELEASED, gfx::Point(123, 321),
gfx::Point(123, 321), timestamp, 0,
EF_RIGHT_MOUSE_BUTTON);
- blink::WebMouseEvent webkit_event =
- MakeWebMouseEvent(ui_event, base::Bind(&GetScreenLocationFromEvent));
+ blink::WebMouseEvent webkit_event = MakeWebMouseEvent(ui_event);
EXPECT_EQ(EventFlagsToWebEventModifiers(ui_event.flags()),
webkit_event.GetModifiers());
EXPECT_EQ(timestamp, webkit_event.TimeStamp());
@@ -352,8 +337,7 @@ TEST(WebInputEventTest, TestMakeWebMouseEvent) {
base::TimeTicks timestamp = EventTimeForNow();
MouseEvent ui_event(ET_MOUSE_MOVED, gfx::Point(123, 321),
gfx::Point(123, 321), timestamp, 0, 0);
- blink::WebMouseEvent webkit_event =
- MakeWebMouseEvent(ui_event, base::Bind(&GetScreenLocationFromEvent));
+ blink::WebMouseEvent webkit_event = MakeWebMouseEvent(ui_event);
EXPECT_EQ(EventFlagsToWebEventModifiers(ui_event.flags()),
webkit_event.GetModifiers());
EXPECT_EQ(timestamp, webkit_event.TimeStamp());
@@ -369,8 +353,7 @@ TEST(WebInputEventTest, TestMakeWebMouseEvent) {
MouseEvent ui_event(ET_MOUSE_MOVED, gfx::Point(123, 321),
gfx::Point(123, 321), timestamp, EF_LEFT_MOUSE_BUTTON,
0);
- blink::WebMouseEvent webkit_event =
- MakeWebMouseEvent(ui_event, base::Bind(&GetScreenLocationFromEvent));
+ blink::WebMouseEvent webkit_event = MakeWebMouseEvent(ui_event);
EXPECT_EQ(EventFlagsToWebEventModifiers(ui_event.flags()),
webkit_event.GetModifiers());
EXPECT_EQ(timestamp, webkit_event.TimeStamp());
@@ -386,8 +369,7 @@ TEST(WebInputEventTest, TestMakeWebMouseEvent) {
MouseEvent ui_event(
ET_MOUSE_PRESSED, gfx::Point(123, 321), gfx::Point(123, 321), timestamp,
EF_LEFT_MOUSE_BUTTON | EF_SHIFT_DOWN, EF_LEFT_MOUSE_BUTTON);
- blink::WebMouseEvent webkit_event =
- MakeWebMouseEvent(ui_event, base::Bind(&GetScreenLocationFromEvent));
+ blink::WebMouseEvent webkit_event = MakeWebMouseEvent(ui_event);
EXPECT_EQ(EventFlagsToWebEventModifiers(ui_event.flags()),
webkit_event.GetModifiers());
EXPECT_EQ(timestamp, webkit_event.TimeStamp());
@@ -403,8 +385,7 @@ TEST(WebInputEventTest, TestMakeWebMouseEvent) {
MouseEvent ui_event(ET_MOUSE_PRESSED, gfx::Point(123, 321),
gfx::Point(123, 321), timestamp, EF_LEFT_MOUSE_BUTTON,
EF_LEFT_MOUSE_BUTTON);
- blink::WebMouseEvent webkit_event =
- MakeWebMouseEvent(ui_event, base::Bind(&GetScreenLocationFromEvent));
+ blink::WebMouseEvent webkit_event = MakeWebMouseEvent(ui_event);
EXPECT_EQ(blink::WebPointerProperties::PointerType::kMouse,
webkit_event.pointer_type);
@@ -431,8 +412,7 @@ TEST(WebInputEventTest, TestMakeWebMouseEvent) {
MouseEvent ui_event(ET_MOUSE_PRESSED, gfx::Point(123, 321),
gfx::Point(123, 321), timestamp, EF_LEFT_MOUSE_BUTTON,
EF_LEFT_MOUSE_BUTTON, pointer_details);
- blink::WebMouseEvent webkit_event =
- MakeWebMouseEvent(ui_event, base::Bind(&GetScreenLocationFromEvent));
+ blink::WebMouseEvent webkit_event = MakeWebMouseEvent(ui_event);
EXPECT_EQ(blink::WebPointerProperties::PointerType::kPen,
webkit_event.pointer_type);
@@ -455,8 +435,7 @@ TEST(WebInputEventTest, TestMakeWebMouseWheelEvent) {
-MouseWheelEvent::kWheelDelta * 2),
gfx::Point(123, 321), gfx::Point(123, 321),
timestamp, 0, 0);
- blink::WebMouseWheelEvent webkit_event = MakeWebMouseWheelEvent(
- ui_event, base::Bind(&GetScreenLocationFromEvent));
+ blink::WebMouseWheelEvent webkit_event = MakeWebMouseWheelEvent(ui_event);
EXPECT_EQ(EventFlagsToWebEventModifiers(ui_event.flags()),
webkit_event.GetModifiers());
EXPECT_EQ(timestamp, webkit_event.TimeStamp());
@@ -510,8 +489,7 @@ TEST(WebInputEventTest, WheelEvent) {
ui::MouseEvent(ui::ET_UNKNOWN, gfx::Point(), gfx::Point(),
base::TimeTicks(), 0, 0),
kDeltaX, kDeltaY);
- blink::WebMouseWheelEvent web_event =
- MakeWebMouseWheelEvent(ui_event, base::Bind(&GetScreenLocationFromEvent));
+ blink::WebMouseWheelEvent web_event = MakeWebMouseWheelEvent(ui_event);
ASSERT_EQ(blink::WebInputEvent::kMouseWheel, web_event.GetType());
ASSERT_EQ(0, web_event.GetModifiers());
ASSERT_EQ(kDeltaX, web_event.delta_x);
@@ -543,8 +521,7 @@ TEST(WebInputEventTest, MousePointerEvent) {
ui::MouseEvent ui_event(tests[i].ui_type, tests[i].location,
tests[i].screen_location, base::TimeTicks(),
tests[i].ui_modifiers, 0);
- blink::WebMouseEvent web_event =
- MakeWebMouseEvent(ui_event, base::Bind(&GetScreenLocationFromEvent));
+ blink::WebMouseEvent web_event = MakeWebMouseEvent(ui_event);
ASSERT_TRUE(blink::WebInputEvent::IsMouseEventType(web_event.GetType()));
ASSERT_EQ(tests[i].web_type, web_event.GetType());
ASSERT_EQ(tests[i].web_modifiers, web_event.GetModifiers());
diff --git a/chromium/ui/events/cocoa/events_mac.mm b/chromium/ui/events/cocoa/events_mac.mm
index c60c04c7661..17d539bb102 100644
--- a/chromium/ui/events/cocoa/events_mac.mm
+++ b/chromium/ui/events/cocoa/events_mac.mm
@@ -63,6 +63,7 @@ EventType EventTypeFromNative(const PlatformEvent& native_event) {
case NSEventTypeRotate:
case NSEventTypeBeginGesture:
case NSEventTypeEndGesture:
+ case NSEventTypePressure:
break;
default:
NOTIMPLEMENTED() << type;
diff --git a/chromium/ui/events/devices/device_util_linux.cc b/chromium/ui/events/devices/device_util_linux.cc
index 4fb5a278789..d81d3a813d9 100644
--- a/chromium/ui/events/devices/device_util_linux.cc
+++ b/chromium/ui/events/devices/device_util_linux.cc
@@ -6,7 +6,6 @@
#include <string>
-#include "base/files/file_enumerator.h"
#include "base/files/file_path.h"
#include "base/files/file_util.h"
#include "base/strings/string_util.h"
@@ -38,8 +37,9 @@ InputDeviceType GetInputDeviceTypeFromPath(const base::FilePath& path) {
path = path.DirName()) {
// Bluetooth LE devices are virtual "uhid" devices.
if (path ==
- base::FilePath(FILE_PATH_LITERAL("/sys/devices/virtual/misc/uhid")))
- return InputDeviceType::INPUT_DEVICE_EXTERNAL;
+ base::FilePath(FILE_PATH_LITERAL("/sys/devices/virtual/misc/uhid"))) {
+ return InputDeviceType::INPUT_DEVICE_BLUETOOTH;
+ }
std::string subsystem_path =
base::MakeAbsoluteFilePath(path.Append(FILE_PATH_LITERAL("subsystem")))
@@ -61,12 +61,12 @@ InputDeviceType GetInputDeviceTypeFromPath(const base::FilePath& path) {
// External bus attachments.
if (subsystem_path == "/sys/bus/usb")
- return InputDeviceType::INPUT_DEVICE_EXTERNAL;
+ return InputDeviceType::INPUT_DEVICE_USB;
if (subsystem_path == "/sys/class/bluetooth")
- return InputDeviceType::INPUT_DEVICE_EXTERNAL;
+ return InputDeviceType::INPUT_DEVICE_BLUETOOTH;
}
return InputDeviceType::INPUT_DEVICE_UNKNOWN;
}
-} // namespace
+} // namespace ui
diff --git a/chromium/ui/events/devices/input_device.h b/chromium/ui/events/devices/input_device.h
index f97154d9f49..2e0da79b1ab 100644
--- a/chromium/ui/events/devices/input_device.h
+++ b/chromium/ui/events/devices/input_device.h
@@ -14,9 +14,10 @@
namespace ui {
enum InputDeviceType {
- INPUT_DEVICE_INTERNAL, // Internally connected input device.
- INPUT_DEVICE_EXTERNAL, // Known externally connected input device.
- INPUT_DEVICE_UNKNOWN, // Device that may or may not be an external device.
+ INPUT_DEVICE_INTERNAL, // Internally connected input device.
+ INPUT_DEVICE_USB, // Known externally connected usb input device.
+ INPUT_DEVICE_BLUETOOTH, // Known externally connected bluetooth input device.
+ INPUT_DEVICE_UNKNOWN, // Device that may or may not be an external device.
};
// Represents an input device state.
diff --git a/chromium/ui/events/devices/mojo/input_device_struct_traits.cc b/chromium/ui/events/devices/mojo/input_device_struct_traits.cc
index b7e005c1305..edae74ac0df 100644
--- a/chromium/ui/events/devices/mojo/input_device_struct_traits.cc
+++ b/chromium/ui/events/devices/mojo/input_device_struct_traits.cc
@@ -15,8 +15,10 @@ EnumTraits<ui::mojom::InputDeviceType, ui::InputDeviceType>::ToMojom(
switch (type) {
case ui::INPUT_DEVICE_INTERNAL:
return ui::mojom::InputDeviceType::INPUT_DEVICE_INTERNAL;
- case ui::INPUT_DEVICE_EXTERNAL:
- return ui::mojom::InputDeviceType::INPUT_DEVICE_EXTERNAL;
+ case ui::INPUT_DEVICE_USB:
+ return ui::mojom::InputDeviceType::INPUT_DEVICE_USB;
+ case ui::INPUT_DEVICE_BLUETOOTH:
+ return ui::mojom::InputDeviceType::INPUT_DEVICE_BLUETOOTH;
case ui::INPUT_DEVICE_UNKNOWN:
return ui::mojom::InputDeviceType::INPUT_DEVICE_UNKNOWN;
}
@@ -31,8 +33,11 @@ bool EnumTraits<ui::mojom::InputDeviceType, ui::InputDeviceType>::FromMojom(
case ui::mojom::InputDeviceType::INPUT_DEVICE_INTERNAL:
*output = ui::INPUT_DEVICE_INTERNAL;
break;
- case ui::mojom::InputDeviceType::INPUT_DEVICE_EXTERNAL:
- *output = ui::INPUT_DEVICE_EXTERNAL;
+ case ui::mojom::InputDeviceType::INPUT_DEVICE_USB:
+ *output = ui::INPUT_DEVICE_USB;
+ break;
+ case ui::mojom::InputDeviceType::INPUT_DEVICE_BLUETOOTH:
+ *output = ui::INPUT_DEVICE_BLUETOOTH;
break;
case ui::mojom::InputDeviceType::INPUT_DEVICE_UNKNOWN:
*output = ui::INPUT_DEVICE_UNKNOWN;
diff --git a/chromium/ui/events/devices/mojo/input_devices.mojom b/chromium/ui/events/devices/mojo/input_devices.mojom
index c9f60f62b22..2671cec05a1 100644
--- a/chromium/ui/events/devices/mojo/input_devices.mojom
+++ b/chromium/ui/events/devices/mojo/input_devices.mojom
@@ -9,7 +9,8 @@ import "ui/gfx/geometry/mojo/geometry.mojom";
// Corresponds to ui::InputDeviceType
enum InputDeviceType {
INPUT_DEVICE_INTERNAL,
- INPUT_DEVICE_EXTERNAL,
+ INPUT_DEVICE_USB,
+ INPUT_DEVICE_BLUETOOTH,
INPUT_DEVICE_UNKNOWN,
};
diff --git a/chromium/ui/events/devices/x11/device_data_manager_x11.cc b/chromium/ui/events/devices/x11/device_data_manager_x11.cc
index ec5a0acedc1..19648ce1bac 100644
--- a/chromium/ui/events/devices/x11/device_data_manager_x11.cc
+++ b/chromium/ui/events/devices/x11/device_data_manager_x11.cc
@@ -832,8 +832,7 @@ void DeviceDataManagerX11::DisableDevice(int deviceid) {
blocked_devices_.set(deviceid, true);
// TODO(rsadam@): Support blocking touchscreen devices.
std::vector<InputDevice> keyboards = GetKeyboardDevices();
- std::vector<InputDevice>::iterator it =
- FindDeviceWithId(keyboards.begin(), keyboards.end(), deviceid);
+ auto it = FindDeviceWithId(keyboards.begin(), keyboards.end(), deviceid);
if (it != std::end(keyboards)) {
blocked_keyboard_devices_.insert(
std::pair<int, InputDevice>(deviceid, *it));
@@ -844,8 +843,7 @@ void DeviceDataManagerX11::DisableDevice(int deviceid) {
void DeviceDataManagerX11::EnableDevice(int deviceid) {
blocked_devices_.set(deviceid, false);
- std::map<int, InputDevice>::iterator it =
- blocked_keyboard_devices_.find(deviceid);
+ auto it = blocked_keyboard_devices_.find(deviceid);
if (it != blocked_keyboard_devices_.end()) {
std::vector<InputDevice> devices = GetKeyboardDevices();
// Add device to current list of active devices.
@@ -879,13 +877,11 @@ bool DeviceDataManagerX11::IsEventBlocked(const XEvent& xev) {
void DeviceDataManagerX11::OnKeyboardDevicesUpdated(
const std::vector<InputDevice>& devices) {
std::vector<InputDevice> keyboards(devices);
- for (std::map<int, InputDevice>::iterator blocked_iter =
- blocked_keyboard_devices_.begin();
+ for (auto blocked_iter = blocked_keyboard_devices_.begin();
blocked_iter != blocked_keyboard_devices_.end();) {
// Check if the blocked device still exists in list of devices.
int device_id = blocked_iter->first;
- std::vector<InputDevice>::iterator it =
- FindDeviceWithId(keyboards.begin(), keyboards.end(), device_id);
+ auto it = FindDeviceWithId(keyboards.begin(), keyboards.end(), device_id);
// If the device no longer exists, unblock it, else filter it out from our
// active list.
if (it == keyboards.end()) {
diff --git a/chromium/ui/events/devices/x11/touch_factory_x11.cc b/chromium/ui/events/devices/x11/touch_factory_x11.cc
index d7c032720df..40c9e65b7d2 100644
--- a/chromium/ui/events/devices/x11/touch_factory_x11.cc
+++ b/chromium/ui/events/devices/x11/touch_factory_x11.cc
@@ -312,8 +312,7 @@ void TouchFactory::SetTouchDeviceForTest(
const std::vector<int>& devices) {
touch_device_lookup_.reset();
touch_device_list_.clear();
- for (std::vector<int>::const_iterator iter = devices.begin();
- iter != devices.end(); ++iter) {
+ for (auto iter = devices.begin(); iter != devices.end(); ++iter) {
DCHECK(IsValidDevice(*iter));
touch_device_lookup_[*iter] = true;
touch_device_list_[*iter] = {true, EventPointerType::POINTER_TYPE_TOUCH};
@@ -324,8 +323,7 @@ void TouchFactory::SetTouchDeviceForTest(
void TouchFactory::SetPointerDeviceForTest(
const std::vector<int>& devices) {
pointer_device_lookup_.reset();
- for (std::vector<int>::const_iterator iter = devices.begin();
- iter != devices.end(); ++iter) {
+ for (auto iter = devices.begin(); iter != devices.end(); ++iter) {
pointer_device_lookup_[*iter] = true;
}
}
diff --git a/chromium/ui/events/event.cc b/chromium/ui/events/event.cc
index d77961db09a..d2eca3cd64b 100644
--- a/chromium/ui/events/event.cc
+++ b/chromium/ui/events/event.cc
@@ -180,6 +180,10 @@ const char* Event::GetName() const {
return EventTypeName(type_);
}
+void Event::SetProperties(const Properties& properties) {
+ properties_ = std::make_unique<Properties>(properties);
+}
+
bool Event::IsMousePointerEvent() const {
return IsPointerEvent() &&
AsPointerEvent()->pointer_details().pointer_type ==
@@ -363,7 +367,34 @@ Event::Event(const Event& copy)
target_(NULL),
phase_(EP_PREDISPATCH),
result_(ER_UNHANDLED),
- source_device_id_(copy.source_device_id_) {
+ source_device_id_(copy.source_device_id_),
+ properties_(copy.properties_
+ ? std::make_unique<Properties>(*copy.properties_)
+ : nullptr) {}
+
+Event& Event::operator=(const Event& rhs) {
+ if (this != &rhs) {
+ if (delete_native_event_)
+ ReleaseCopiedNativeEvent(native_event_);
+
+ type_ = rhs.type_;
+ time_stamp_ = rhs.time_stamp_;
+ latency_ = rhs.latency_;
+ flags_ = rhs.flags_;
+ native_event_ = CopyNativeEvent(rhs.native_event_);
+ delete_native_event_ = true;
+ cancelable_ = rhs.cancelable_;
+ target_ = rhs.target_;
+ phase_ = rhs.phase_;
+ result_ = rhs.result_;
+ source_device_id_ = rhs.source_device_id_;
+ if (rhs.properties_)
+ properties_ = std::make_unique<Properties>(*rhs.properties_);
+ else
+ properties_.reset();
+ }
+ latency_.set_source_event_type(ui::SourceEventType::OTHER);
+ return *this;
}
void Event::SetType(EventType type) {
@@ -795,8 +826,7 @@ TouchEvent::TouchEvent(EventType type,
const gfx::Point& location,
base::TimeTicks time_stamp,
const PointerDetails& pointer_details,
- int flags,
- float angle)
+ int flags)
: LocatedEvent(type,
gfx::PointF(location),
gfx::PointF(location),
@@ -808,7 +838,6 @@ TouchEvent::TouchEvent(EventType type,
hovering_(false),
pointer_details_(pointer_details) {
latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT);
- pointer_details_.twist = angle;
}
TouchEvent::TouchEvent(const TouchEvent& copy)
@@ -1103,7 +1132,7 @@ KeyEvent::KeyEvent(const PlatformEvent& native_event, int event_flags)
#if defined(OS_WIN)
// Only Windows has native character events.
if (is_char_) {
- key_ = DomKey::FromCharacter(native_event.wParam);
+ key_ = DomKey::FromCharacter(static_cast<int32_t>(native_event.wParam));
set_flags(PlatformKeyMap::ReplaceControlAndAltWithAltGraph(flags()));
} else {
int adjusted_flags = flags();
@@ -1161,10 +1190,7 @@ KeyEvent::KeyEvent(const KeyEvent& rhs)
key_code_(rhs.key_code_),
code_(rhs.code_),
is_char_(rhs.is_char_),
- key_(rhs.key_),
- properties_(rhs.properties_
- ? std::make_unique<Properties>(*rhs.properties_)
- : nullptr) {}
+ key_(rhs.key_) {}
KeyEvent& KeyEvent::operator=(const KeyEvent& rhs) {
if (this != &rhs) {
@@ -1173,12 +1199,7 @@ KeyEvent& KeyEvent::operator=(const KeyEvent& rhs) {
code_ = rhs.code_;
key_ = rhs.key_;
is_char_ = rhs.is_char_;
- if (rhs.properties_)
- properties_ = std::make_unique<Properties>(*rhs.properties_);
- else
- properties_.reset();
}
- latency()->set_source_event_type(ui::SourceEventType::OTHER);
return *this;
}
@@ -1312,10 +1333,6 @@ void KeyEvent::NormalizeFlags() {
set_flags(flags() & ~mask);
}
-void KeyEvent::SetProperties(const Properties& properties) {
- properties_ = std::make_unique<Properties>(properties);
-}
-
KeyboardCode KeyEvent::GetLocatedWindowsKeyboardCode() const {
return NonLocatedToLocatedKeyboardCode(key_code_, code_);
}
diff --git a/chromium/ui/events/event.h b/chromium/ui/events/event.h
index 69411630ff0..b9b4c72be8b 100644
--- a/chromium/ui/events/event.h
+++ b/chromium/ui/events/event.h
@@ -34,6 +34,7 @@ class Transform;
namespace ui {
class CancelModeEvent;
+class Event;
class EventTarget;
class KeyEvent;
class LocatedEvent;
@@ -42,15 +43,15 @@ class MouseWheelEvent;
class PointerEvent;
class ScrollEvent;
class TouchEvent;
+
enum class DomCode;
-class Event;
-class MouseWheelEvent;
-using ScopedEvent = std::unique_ptr<Event>;
using PointerId = int32_t;
class EVENTS_EXPORT Event {
public:
+ using Properties = base::flat_map<std::string, std::vector<uint8_t>>;
+
// Copies an arbitrary event. If you have a typed event (e.g. a MouseEvent)
// just use its copy constructor.
static std::unique_ptr<Event> Clone(const Event& event);
@@ -103,6 +104,14 @@ class EVENTS_EXPORT Event {
int source_device_id() const { return source_device_id_; }
void set_source_device_id(int id) { source_device_id_ = id; }
+ // Sets the properties associated with this Event.
+ void SetProperties(const Properties& properties);
+
+ // Returns the properties associated with this event, which may be null.
+ // The properties are meant to provide a way to associate arbitrary key/value
+ // pairs with Events and not used by Event.
+ const Properties* properties() const { return properties_.get(); }
+
// By default, events are "cancelable", this means any default processing that
// the containing abstraction layer may perform can be prevented by calling
// SetHandled(). SetHandled() or StopPropagation() must not be called for
@@ -314,6 +323,8 @@ class EVENTS_EXPORT Event {
Event(EventType type, base::TimeTicks time_stamp, int flags);
Event(const PlatformEvent& native_event, EventType type, int flags);
Event(const Event& copy);
+ Event& operator=(const Event& rhs);
+
void SetType(EventType type);
void set_cancelable(bool cancelable) { cancelable_ = cancelable; }
@@ -338,6 +349,8 @@ class EVENTS_EXPORT Event {
// The device id the event came from, or ED_UNKNOWN_DEVICE if the information
// is not available.
int source_device_id_;
+
+ std::unique_ptr<Properties> properties_;
};
class EVENTS_EXPORT CancelModeEvent : public Event {
@@ -542,7 +555,6 @@ class EVENTS_EXPORT MouseEvent : public LocatedEvent {
set_flags(flags);
}
- // Used for synthetic events in testing, gesture recognizer and Ozone
// Note: Use the ctor for MouseWheelEvent if type is ET_MOUSEWHEEL.
MouseEvent(EventType type,
const gfx::Point& location,
@@ -704,8 +716,7 @@ class EVENTS_EXPORT TouchEvent : public LocatedEvent {
const gfx::Point& location,
base::TimeTicks time_stamp,
const PointerDetails& pointer_details,
- int flags = 0,
- float angle = 0.0f);
+ int flags = 0);
TouchEvent(const TouchEvent& copy);
@@ -725,6 +736,9 @@ class EVENTS_EXPORT TouchEvent : public LocatedEvent {
should_remove_native_touch_id_mapping_ =
should_remove_native_touch_id_mapping;
}
+ bool should_remove_native_touch_id_mapping() const {
+ return should_remove_native_touch_id_mapping_;
+ }
// Overridden from LocatedEvent.
void UpdateForRootTransform(
@@ -744,6 +758,9 @@ class EVENTS_EXPORT TouchEvent : public LocatedEvent {
private:
// A unique identifier for the touch event.
+ // NOTE: this is *not* serialized over mojom, as the number is unique to
+ // a particular process, and as mojom may go cross process, to serialize could
+ // lead to conflicts.
uint32_t unique_event_id_;
// Whether the (unhandled) touch event will produce a scroll event (e.g., a
@@ -755,6 +772,7 @@ class EVENTS_EXPORT TouchEvent : public LocatedEvent {
// event id and the touch_id_. This should only be the case for
// release and cancel events where the associated touch press event
// created a mapping between the native id and the touch_id_.
+ // NOTE: this is not serialized, as it's generally unique to the source.
bool should_remove_native_touch_id_mapping_;
// True for devices like some pens when they support hovering over
@@ -832,8 +850,6 @@ class EVENTS_EXPORT PointerEvent : public LocatedEvent {
//
class EVENTS_EXPORT KeyEvent : public Event {
public:
- using Properties = base::flat_map<std::string, std::vector<uint8_t>>;
-
// Create a KeyEvent from a NativeEvent. For Windows this native event can
// be either a keystroke message (WM_KEYUP/WM_KEYDOWN) or a character message
// (WM_CHAR). Other systems have only keystroke events.
@@ -941,14 +957,6 @@ class EVENTS_EXPORT KeyEvent : public Event {
// (Native X11 event flags describe the state before the event.)
void NormalizeFlags();
- // Sets the properties associated with this KeyEvent.
- void SetProperties(const Properties& properties);
-
- // Returns the properties associated with this event, which may be null.
- // The properties are meant to provide a way to associate arbitrary key/value
- // pairs with KeyEvents and not used by KeyEvent.
- const Properties* properties() const { return properties_.get(); }
-
protected:
friend class KeyEventTestApi;
@@ -987,8 +995,6 @@ class EVENTS_EXPORT KeyEvent : public Event {
// it may be set only if and when GetCharacter() or GetDomKey() is called.
mutable DomKey key_ = DomKey::NONE;
- std::unique_ptr<Properties> properties_;
-
static KeyEvent* last_key_event_;
#if defined(USE_X11)
static KeyEvent* last_ibus_key_event_;
diff --git a/chromium/ui/events/event_handler.cc b/chromium/ui/events/event_handler.cc
index 66279d43cda..179420f376b 100644
--- a/chromium/ui/events/event_handler.cc
+++ b/chromium/ui/events/event_handler.cc
@@ -4,7 +4,6 @@
#include "ui/events/event_handler.h"
-#include "base/debug/alias.h"
#include "ui/events/event.h"
#include "ui/events/event_dispatcher.h"
@@ -22,10 +21,6 @@ EventHandler::~EventHandler() {
}
void EventHandler::OnEvent(Event* event) {
- // TODO(sky): remove |event_type|. Temporary while tracking down crash.
- // https://crbug.com/867035
- const EventType event_type = event->type();
- base::debug::Alias(&event_type);
if (event->IsKeyEvent())
OnKeyEvent(event->AsKeyEvent());
else if (event->IsMouseEvent())
diff --git a/chromium/ui/events/event_rewriter_unittest.cc b/chromium/ui/events/event_rewriter_unittest.cc
index ae9abcea417..90c5d261c54 100644
--- a/chromium/ui/events/event_rewriter_unittest.cc
+++ b/chromium/ui/events/event_rewriter_unittest.cc
@@ -125,8 +125,7 @@ class TestStateMachineEventRewriter : public EventRewriter {
EventRewriteStatus RewriteEvent(
const Event& event,
std::unique_ptr<Event>* rewritten_event) override {
- RewriteRules::iterator find =
- rules_.find(RewriteCase(state_, event.type()));
+ auto find = rules_.find(RewriteCase(state_, event.type()));
if (find == rules_.end())
return EVENT_REWRITE_CONTINUE;
if ((find->second.status == EVENT_REWRITE_REWRITTEN) ||
diff --git a/chromium/ui/events/event_source.cc b/chromium/ui/events/event_source.cc
index 21e160b3130..d2c955ce6fe 100644
--- a/chromium/ui/events/event_source.cc
+++ b/chromium/ui/events/event_source.cc
@@ -34,8 +34,7 @@ void EventSource::AddEventRewriter(EventRewriter* rewriter) {
}
void EventSource::RemoveEventRewriter(EventRewriter* rewriter) {
- EventRewriterList::iterator find =
- std::find(rewriter_list_.begin(), rewriter_list_.end(), rewriter);
+ auto find = std::find(rewriter_list_.begin(), rewriter_list_.end(), rewriter);
if (find != rewriter_list_.end())
rewriter_list_.erase(find);
}
diff --git a/chromium/ui/events/event_target.cc b/chromium/ui/events/event_target.cc
index 431a66a60f9..e72b72cc924 100644
--- a/chromium/ui/events/event_target.cc
+++ b/chromium/ui/events/event_target.cc
@@ -8,18 +8,25 @@
#include "base/logging.h"
#include "ui/events/event.h"
+#include "ui/gfx/geometry/point_conversions.h"
namespace ui {
-EventTarget::EventTarget()
- : target_handler_(NULL) {
-}
+EventTarget::EventTarget() = default;
-EventTarget::~EventTarget() {
-}
+EventTarget::~EventTarget() = default;
void EventTarget::ConvertEventToTarget(EventTarget* target,
- LocatedEvent* event) {
+ LocatedEvent* event) {}
+
+gfx::PointF EventTarget::GetScreenLocationF(
+ const ui::LocatedEvent& event) const {
+ NOTREACHED();
+ return event.root_location_f();
+}
+
+gfx::Point EventTarget::GetScreenLocation(const ui::LocatedEvent& event) const {
+ return gfx::ToFlooredPoint(GetScreenLocationF(event));
}
void EventTarget::AddPreTargetHandler(EventHandler* handler,
@@ -51,10 +58,8 @@ void EventTarget::AddPostTargetHandler(EventHandler* handler) {
}
void EventTarget::RemovePostTargetHandler(EventHandler* handler) {
- EventHandlerList::iterator find =
- std::find(post_target_list_.begin(),
- post_target_list_.end(),
- handler);
+ auto find =
+ std::find(post_target_list_.begin(), post_target_list_.end(), handler);
if (find != post_target_list_.end())
post_target_list_.erase(find);
}
@@ -92,8 +97,9 @@ void EventTarget::GetPreTargetHandlers(EventHandlerList* list) {
void EventTarget::GetPostTargetHandlers(EventHandlerList* list) {
EventTarget* target = this;
while (target) {
- for (EventHandlerList::iterator it = target->post_target_list_.begin(),
- end = target->post_target_list_.end(); it != end; ++it) {
+ for (auto it = target->post_target_list_.begin(),
+ end = target->post_target_list_.end();
+ it != end; ++it) {
list->push_back(*it);
}
target = target->GetParentTarget();
diff --git a/chromium/ui/events/event_target.h b/chromium/ui/events/event_target.h
index 4314aca5f6c..7c47527c214 100644
--- a/chromium/ui/events/event_target.h
+++ b/chromium/ui/events/event_target.h
@@ -12,6 +12,8 @@
#include "base/macros.h"
#include "ui/events/event_handler.h"
#include "ui/events/events_export.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/point_f.h"
namespace ui {
@@ -54,6 +56,10 @@ class EVENTS_EXPORT EventTarget {
virtual void ConvertEventToTarget(EventTarget* target,
LocatedEvent* event);
+ // Get |event|'s screen location, using the EventTarget's screen location.
+ virtual gfx::PointF GetScreenLocationF(const LocatedEvent& event) const;
+ gfx::Point GetScreenLocation(const LocatedEvent& event) const;
+
// Priority levels for PreTargetHandlers.
enum class Priority {
// The Accessibility level is the highest, and gets events before
@@ -120,7 +126,7 @@ class EVENTS_EXPORT EventTarget {
EventHandlerPriorityList pre_target_list_;
EventHandlerList post_target_list_;
- EventHandler* target_handler_;
+ EventHandler* target_handler_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(EventTarget);
};
diff --git a/chromium/ui/events/event_unittest.cc b/chromium/ui/events/event_unittest.cc
index 8a63b46a092..4742a797f60 100644
--- a/chromium/ui/events/event_unittest.cc
+++ b/chromium/ui/events/event_unittest.cc
@@ -25,6 +25,7 @@
#if defined(USE_X11)
#include "ui/events/test/events_test_utils_x11.h"
+#include "ui/events/x/events_x_utils.h" // nogncheck
#include "ui/gfx/x/x11.h" // nogncheck
#include "ui/gfx/x/x11_types.h" // nogncheck
#endif
@@ -430,6 +431,15 @@ TEST(EventTest, KeyEventCode) {
#if defined(USE_X11)
namespace {
+class MockTimestampServer : public ui::TimestampServer {
+ public:
+ Time GetCurrentServerTime() override { return base_time_; }
+ void SetBaseTime(Time time) { base_time_ = time; }
+
+ private:
+ Time base_time_ = 0;
+};
+
void SetKeyEventTimestamp(XEvent* event, int64_t time) {
event->xkey.time = time & UINT32_MAX;
}
@@ -440,7 +450,29 @@ void AdvanceKeyEventTimestamp(XEvent* event) {
} // namespace
-TEST(EventTest, AutoRepeat) {
+class X11EventTest : public testing::Test {
+ public:
+ X11EventTest() {}
+ ~X11EventTest() override {}
+
+ void SetUp() override {
+ SetTimestampServer(&server_);
+ SetUseFixedTimeForXEventTesting(true);
+ }
+
+ void TearDown() override {
+ SetTimestampServer(nullptr);
+ SetUseFixedTimeForXEventTesting(false);
+ }
+
+ protected:
+ MockTimestampServer server_;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(X11EventTest);
+};
+
+TEST_F(X11EventTest, AutoRepeat) {
const uint16_t kNativeCodeA =
ui::KeycodeConverter::DomCodeToNativeKeycode(DomCode::US_A);
const uint16_t kNativeCodeB =
@@ -468,6 +500,7 @@ TEST(EventTest, AutoRepeat) {
int64_t ticks_base =
(base::TimeTicks::Now() - base::TimeTicks()).InMilliseconds() - 5000;
+ server_.SetBaseTime(static_cast<Time>(ticks_base));
SetKeyEventTimestamp(native_event_a_pressed, ticks_base);
SetKeyEventTimestamp(native_event_a_pressed_1500, ticks_base + 1500);
SetKeyEventTimestamp(native_event_a_pressed_3000, ticks_base + 3000);
@@ -582,8 +615,8 @@ TEST(EventTest, TouchEventRotationAngleFixing) {
TouchEvent event(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0), time,
PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH,
/* pointer_id*/ 0, radius_x, radius_y,
- /* force */ 0),
- 0, angle_in_range);
+ /* force */ 0, angle_in_range),
+ 0);
EXPECT_FLOAT_EQ(angle_in_range, event.ComputeRotationAngle());
}
@@ -592,8 +625,8 @@ TEST(EventTest, TouchEventRotationAngleFixing) {
TouchEvent event(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0), time,
PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH,
/* pointer_id*/ 0, radius_x, radius_y,
- /* force */ 0),
- 0, angle_in_range);
+ /* force */ 0, angle_in_range),
+ 0);
EXPECT_FLOAT_EQ(angle_in_range, event.ComputeRotationAngle());
}
@@ -602,8 +635,8 @@ TEST(EventTest, TouchEventRotationAngleFixing) {
TouchEvent event(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0), time,
PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH,
/* pointer_id*/ 0, radius_x, radius_y,
- /* force */ 0),
- 0, angle_negative);
+ /* force */ 0, angle_negative),
+ 0);
EXPECT_FLOAT_EQ(180 - 0.1f, event.ComputeRotationAngle());
}
@@ -612,8 +645,8 @@ TEST(EventTest, TouchEventRotationAngleFixing) {
TouchEvent event(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0), time,
PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH,
/* pointer_id*/ 0, radius_x, radius_y,
- /* force */ 0),
- 0, angle_negative);
+ /* force */ 0, angle_negative),
+ 0);
EXPECT_FLOAT_EQ(360 - 200, event.ComputeRotationAngle());
}
@@ -622,8 +655,8 @@ TEST(EventTest, TouchEventRotationAngleFixing) {
TouchEvent event(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0), time,
PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH,
/* pointer_id*/ 0, radius_x, radius_y,
- /* force */ 0),
- 0, angle_too_big);
+ /* force */ 0, angle_too_big),
+ 0);
EXPECT_FLOAT_EQ(0, event.ComputeRotationAngle());
}
@@ -632,8 +665,8 @@ TEST(EventTest, TouchEventRotationAngleFixing) {
TouchEvent event(ui::ET_TOUCH_PRESSED, gfx::Point(0, 0), time,
PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH,
/* pointer_id*/ 0, radius_x, radius_y,
- /* force */ 0),
- 0, angle_too_big);
+ /* force */ 0, angle_too_big),
+ 0);
EXPECT_FLOAT_EQ(400 - 360, event.ComputeRotationAngle());
}
}
@@ -999,8 +1032,9 @@ TEST(EventTest, PointerEventToTouchEventDetails) {
/* pointer_id*/ 15,
/* radius_x */ 11.5,
/* radius_y */ 13.5,
- /* force */ 0.5),
- 0, 13.0));
+ /* force */ 0.0,
+ /* twist */ 13.0),
+ 0));
ui::TouchEvent touch_event(pointer_event);
EXPECT_EQ(pointer_event.location(), touch_event.location());
@@ -1122,6 +1156,20 @@ TEST(EventTest, UpdateForRootTransformation) {
}
}
+TEST(EventTest, OperatorEqual) {
+ MouseEvent m1(ET_MOUSE_PRESSED, gfx::Point(1, 2), gfx::Point(2, 3),
+ EventTimeForNow(), EF_LEFT_MOUSE_BUTTON, EF_RIGHT_MOUSE_BUTTON);
+ base::flat_map<std::string, std::vector<uint8_t>> properties;
+ properties["a"] = {1u};
+ m1.SetProperties(properties);
+ EXPECT_EQ(properties, *(m1.properties()));
+ MouseEvent m2(ET_MOUSE_RELEASED, gfx::Point(11, 21), gfx::Point(2, 2),
+ EventTimeForNow(), EF_RIGHT_MOUSE_BUTTON, EF_LEFT_MOUSE_BUTTON);
+ m2 = m1;
+ ASSERT_TRUE(m2.properties());
+ EXPECT_EQ(properties, *(m2.properties()));
+}
+
#if defined(OS_WIN)
namespace {
diff --git a/chromium/ui/events/event_utils.cc b/chromium/ui/events/event_utils.cc
index 404b4525b7c..164fd2285ce 100644
--- a/chromium/ui/events/event_utils.cc
+++ b/chromium/ui/events/event_utils.cc
@@ -7,6 +7,7 @@
#include <vector>
#include "base/metrics/histogram_macros.h"
+#include "base/numerics/safe_conversions.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
@@ -88,8 +89,7 @@ display::Display::TouchSupport GetInternalDisplayTouchSupport() {
if (!screen)
return display::Display::TouchSupport::UNKNOWN;
const std::vector<display::Display>& displays = screen->GetAllDisplays();
- for (std::vector<display::Display>::const_iterator it = displays.begin();
- it != displays.end(); ++it) {
+ for (auto it = displays.begin(); it != displays.end(); ++it) {
if (it->IsInternal())
return it->touch_support();
}
@@ -108,20 +108,24 @@ void ComputeEventLatencyOS(const PlatformEvent& native_event) {
case ET_SCROLL:
#endif
case ET_MOUSEWHEEL:
- UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.OS.MOUSE_WHEEL",
- delta.InMicroseconds(), 1, 1000000, 50);
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Event.Latency.OS.MOUSE_WHEEL",
+ base::saturated_cast<int>(delta.InMicroseconds()), 1, 1000000, 50);
return;
case ET_TOUCH_MOVED:
- UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.OS.TOUCH_MOVED",
- delta.InMicroseconds(), 1, 1000000, 50);
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Event.Latency.OS.TOUCH_MOVED",
+ base::saturated_cast<int>(delta.InMicroseconds()), 1, 1000000, 50);
return;
case ET_TOUCH_PRESSED:
- UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.OS.TOUCH_PRESSED",
- delta.InMicroseconds(), 1, 1000000, 50);
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Event.Latency.OS.TOUCH_PRESSED",
+ base::saturated_cast<int>(delta.InMicroseconds()), 1, 1000000, 50);
return;
case ET_TOUCH_RELEASED:
- UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.OS.TOUCH_RELEASED",
- delta.InMicroseconds(), 1, 1000000, 50);
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Event.Latency.OS.TOUCH_RELEASED",
+ base::saturated_cast<int>(delta.InMicroseconds()), 1, 1000000, 50);
return;
default:
return;
diff --git a/chromium/ui/events/fuchsia/input_event_dispatcher.cc b/chromium/ui/events/fuchsia/input_event_dispatcher.cc
new file mode 100644
index 00000000000..b240779e533
--- /dev/null
+++ b/chromium/ui/events/fuchsia/input_event_dispatcher.cc
@@ -0,0 +1,194 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/fuchsia/input_event_dispatcher.h"
+
+#include <memory>
+
+#include "base/memory/ptr_util.h"
+#include "ui/events/event.h"
+#include "ui/events/fuchsia/input_event_dispatcher_delegate.h"
+#include "ui/events/keycodes/dom/keycode_converter.h"
+#include "ui/events/keycodes/keyboard_code_conversion.h"
+
+namespace ui {
+namespace {
+
+const uint32_t kUsbHidKeyboardPage = 0x07;
+
+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() = default;
+
+bool InputEventDispatcher::ProcessEvent(
+ const fuchsia::ui::input::InputEvent& event) const {
+ switch (event.Which()) {
+ case fuchsia::ui::input::InputEvent::Tag::kPointer:
+ switch (event.pointer().type) {
+ case fuchsia::ui::input::PointerEventType::MOUSE:
+ return ProcessMouseEvent(event.pointer());
+ case fuchsia::ui::input::PointerEventType::TOUCH:
+ return ProcessTouchEvent(event.pointer());
+ case fuchsia::ui::input::PointerEventType::STYLUS:
+ case fuchsia::ui::input::PointerEventType::INVERTED_STYLUS:
+ NOTIMPLEMENTED() << "Stylus input is not yet supported.";
+ return false;
+ }
+
+ case fuchsia::ui::input::InputEvent::Tag::kKeyboard:
+ return ProcessKeyboardEvent(event.keyboard());
+
+ case fuchsia::ui::input::InputEvent::Tag::kFocus:
+ case fuchsia::ui::input::InputEvent::Tag::Invalid:
+ return false;
+ }
+}
+
+bool InputEventDispatcher::ProcessMouseEvent(
+ const fuchsia::ui::input::PointerEvent& event) const {
+ int flags = 0;
+ EventType event_type;
+ int buttons_flags = 0;
+ if (event.buttons & fuchsia::ui::input::kMouseButtonPrimary) {
+ buttons_flags |= EF_LEFT_MOUSE_BUTTON;
+ }
+ if (event.buttons & fuchsia::ui::input::kMouseButtonSecondary) {
+ buttons_flags |= EF_RIGHT_MOUSE_BUTTON;
+ }
+ if (event.buttons & fuchsia::ui::input::kMouseButtonTertiary) {
+ buttons_flags |= EF_MIDDLE_MOUSE_BUTTON;
+ }
+
+ switch (event.phase) {
+ case fuchsia::ui::input::PointerEventPhase::DOWN:
+ event_type = ET_MOUSE_PRESSED;
+ break;
+ case fuchsia::ui::input::PointerEventPhase::MOVE:
+ event_type = flags ? ET_MOUSE_DRAGGED : ET_MOUSE_MOVED;
+ break;
+ case fuchsia::ui::input::PointerEventPhase::UP:
+ event_type = ET_MOUSE_RELEASED;
+ break;
+
+ // Following phases are not expected for mouse events.
+ case fuchsia::ui::input::PointerEventPhase::HOVER:
+ case fuchsia::ui::input::PointerEventPhase::CANCEL:
+ case fuchsia::ui::input::PointerEventPhase::ADD:
+ case fuchsia::ui::input::PointerEventPhase::REMOVE:
+ NOTREACHED() << "Unexpected mouse phase "
+ << fidl::ToUnderlying(event.phase);
+ return false;
+ }
+
+ ui::MouseEvent mouse_event(event_type, gfx::Point(), gfx::Point(),
+ 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);
+ return mouse_event.handled();
+}
+
+bool InputEventDispatcher::ProcessTouchEvent(
+ const fuchsia::ui::input::PointerEvent& event) const {
+ EventType event_type;
+ bool hovering = false;
+ switch (event.phase) {
+ case fuchsia::ui::input::PointerEventPhase::HOVER:
+ hovering = true;
+ event_type = ET_TOUCH_PRESSED;
+ break;
+ case fuchsia::ui::input::PointerEventPhase::DOWN:
+ event_type = ET_TOUCH_PRESSED;
+ break;
+ case fuchsia::ui::input::PointerEventPhase::MOVE:
+ event_type = ET_TOUCH_MOVED;
+ break;
+ case fuchsia::ui::input::PointerEventPhase::CANCEL:
+ event_type = ET_TOUCH_CANCELLED;
+ break;
+ case fuchsia::ui::input::PointerEventPhase::UP:
+ event_type = ET_TOUCH_RELEASED;
+ break;
+ case fuchsia::ui::input::PointerEventPhase::ADD:
+ case fuchsia::ui::input::PointerEventPhase::REMOVE:
+ return false;
+ }
+
+ // TODO(crbug.com/876933): Add more detailed fields such as
+ // force/orientation/tilt once they are added to PointerEvent.
+ ui::PointerDetails pointer_details(ui::EventPointerType::POINTER_TYPE_TOUCH,
+ event.pointer_id);
+
+ ui::TouchEvent touch_event(event_type, gfx::Point(),
+ base::TimeTicks::FromZxTime(event.event_time),
+ pointer_details);
+ touch_event.set_hovering(hovering);
+ touch_event.set_location_f(gfx::PointF(event.x, event.y));
+ delegate_->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;
+ }
+
+ // Currently KeyboardEvent doesn't specify HID Usage page. |hid_usage|
+ // field always contains values from the Keyboard page. See
+ // https://fuchsia.atlassian.net/browse/SCN-762 .
+ DomCode dom_code = KeycodeConverter::UsbKeycodeToDomCode(
+ (kUsbHidKeyboardPage << 16) | 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
new file mode 100644
index 00000000000..6307773edd8
--- /dev/null
+++ b/chromium/ui/events/fuchsia/input_event_dispatcher.h
@@ -0,0 +1,44 @@
+// 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_H_
+#define UI_EVENTS_FUCHSIA_INPUT_EVENT_DISPATCHER_H_
+
+#include <fuchsia/ui/input/cpp/fidl.h>
+
+#include "base/macros.h"
+#include "ui/events/events_export.h"
+
+namespace ui {
+
+class InputEventDispatcherDelegate;
+
+// Translates Fuchsia input events to Chrome ui::Events.
+class EVENTS_EXPORT InputEventDispatcher {
+ public:
+ // |delegate|: The recipient of any Chrome events that are processed from
+ // Fuchsia events.
+ explicit InputEventDispatcher(InputEventDispatcherDelegate* delegate);
+ ~InputEventDispatcher();
+
+ // Processes a Fuchsia |event| and dispatches Chrome ui::Events from it.
+ // |event|'s coordinates must be specified in device-independent pixels.
+ //
+ // Returns true if the event was processed.
+ bool ProcessEvent(const fuchsia::ui::input::InputEvent& event) const;
+
+ 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_;
+
+ DISALLOW_COPY_AND_ASSIGN(InputEventDispatcher);
+};
+
+} // namespace ui
+
+#endif // UI_EVENTS_FUCHSIA_INPUT_EVENT_DISPATCHER_H_
diff --git a/chromium/ui/events/fuchsia/input_event_dispatcher_delegate.h b/chromium/ui/events/fuchsia/input_event_dispatcher_delegate.h
new file mode 100644
index 00000000000..78a70a8b327
--- /dev/null
+++ b/chromium/ui/events/fuchsia/input_event_dispatcher_delegate.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_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
new file mode 100644
index 00000000000..54a14b9909b
--- /dev/null
+++ b/chromium/ui/events/fuchsia/input_event_dispatcher_unittest.cc
@@ -0,0 +1,263 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/fuchsia/input_event_dispatcher.h"
+
+#include <fuchsia/ui/input/cpp/fidl.h>
+#include <memory>
+
+#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/keycodes/dom/dom_key.h"
+
+using fuchsia::ui::input::InputEvent;
+using FuchsiaKeyboardEvent = fuchsia::ui::input::KeyboardEvent;
+using FuchsiaPointerEvent = fuchsia::ui::input::PointerEvent;
+
+namespace ui {
+namespace {
+
+class InputEventDispatcherTest : public testing::Test,
+ public InputEventDispatcherDelegate {
+ public:
+ InputEventDispatcherTest() : dispatcher_(this) {}
+ ~InputEventDispatcherTest() override = default;
+
+ void DispatchEvent(Event* event) override {
+ DCHECK(!captured_event_);
+ captured_event_ = Event::Clone(*event);
+ }
+
+ protected:
+ InputEventDispatcher dispatcher_;
+ std::unique_ptr<ui::Event> captured_event_;
+
+ void ResetCapturedEvent() {
+ DCHECK(captured_event_);
+ captured_event_.reset();
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(InputEventDispatcherTest);
+};
+
+TEST_F(InputEventDispatcherTest, MouseEventButtons) {
+ // Left mouse button.
+ FuchsiaPointerEvent pointer_event;
+ pointer_event.x = 1;
+ pointer_event.y = 1;
+ pointer_event.phase = fuchsia::ui::input::PointerEventPhase::DOWN;
+ pointer_event.buttons = fuchsia::ui::input::kMouseButtonPrimary;
+ pointer_event.type = fuchsia::ui::input::PointerEventType::MOUSE;
+ InputEvent event;
+ event.set_pointer(pointer_event);
+ dispatcher_.ProcessEvent(event);
+ EXPECT_TRUE(captured_event_->AsMouseEvent()->IsLeftMouseButton());
+ ResetCapturedEvent();
+
+ // Right mouse button.
+ pointer_event.buttons = fuchsia::ui::input::kMouseButtonSecondary;
+ event.set_pointer(pointer_event);
+ dispatcher_.ProcessEvent(event);
+ EXPECT_TRUE(captured_event_->AsMouseEvent()->IsRightMouseButton());
+ ResetCapturedEvent();
+
+ // Middle mouse button.
+ pointer_event.buttons = fuchsia::ui::input::kMouseButtonTertiary;
+ event.set_pointer(pointer_event);
+ dispatcher_.ProcessEvent(event);
+ EXPECT_TRUE(captured_event_->AsMouseEvent()->IsMiddleMouseButton());
+ ResetCapturedEvent();
+
+ // Left mouse drag.
+ pointer_event.buttons = fuchsia::ui::input::kMouseButtonPrimary;
+ pointer_event.phase = fuchsia::ui::input::PointerEventPhase::MOVE;
+ event.set_pointer(pointer_event);
+ dispatcher_.ProcessEvent(event);
+ EXPECT_EQ(ET_MOUSE_DRAGGED, captured_event_->type());
+ ResetCapturedEvent();
+
+ // Left mouse up.
+ pointer_event.buttons = fuchsia::ui::input::kMouseButtonPrimary;
+ pointer_event.phase = fuchsia::ui::input::PointerEventPhase::UP;
+ event.set_pointer(pointer_event);
+ dispatcher_.ProcessEvent(event);
+ EXPECT_EQ(ET_MOUSE_RELEASED, captured_event_->type());
+}
+
+TEST_F(InputEventDispatcherTest, MouseMove) {
+ FuchsiaPointerEvent pointer_event;
+ pointer_event.x = 1.5;
+ pointer_event.y = 2.5;
+ pointer_event.phase = fuchsia::ui::input::PointerEventPhase::MOVE;
+ pointer_event.type = fuchsia::ui::input::PointerEventType::MOUSE;
+ InputEvent event;
+ event.set_pointer(pointer_event);
+ dispatcher_.ProcessEvent(event);
+ EXPECT_EQ(1.5, captured_event_->AsMouseEvent()->x());
+ EXPECT_EQ(2.5, captured_event_->AsMouseEvent()->y());
+}
+
+TEST_F(InputEventDispatcherTest, TouchLocation) {
+ FuchsiaPointerEvent pointer_event;
+ pointer_event.phase = fuchsia::ui::input::PointerEventPhase::DOWN;
+ pointer_event.type = fuchsia::ui::input::PointerEventType::TOUCH;
+ pointer_event.x = 1.5;
+ pointer_event.y = 2.5;
+ InputEvent event;
+ event.set_pointer(pointer_event);
+ dispatcher_.ProcessEvent(event);
+ EXPECT_EQ(1.5, captured_event_->AsTouchEvent()->x());
+ EXPECT_EQ(2.5, captured_event_->AsTouchEvent()->y());
+}
+
+TEST_F(InputEventDispatcherTest, TouchPointerIds) {
+ FuchsiaPointerEvent pointer_event;
+ pointer_event.phase = fuchsia::ui::input::PointerEventPhase::DOWN;
+ pointer_event.type = fuchsia::ui::input::PointerEventType::TOUCH;
+ pointer_event.pointer_id = 1;
+ InputEvent event;
+ event.set_pointer(pointer_event);
+ dispatcher_.ProcessEvent(event);
+ EXPECT_EQ(ET_TOUCH_PRESSED, captured_event_->type());
+ EXPECT_EQ(1, captured_event_->AsTouchEvent()->pointer_details().id);
+ ResetCapturedEvent();
+
+ pointer_event.pointer_id = 2;
+ event.set_pointer(pointer_event);
+ dispatcher_.ProcessEvent(event);
+ EXPECT_EQ(ET_TOUCH_PRESSED, captured_event_->type());
+ EXPECT_EQ(2, captured_event_->AsTouchEvent()->pointer_details().id);
+}
+
+TEST_F(InputEventDispatcherTest, TouchPhases) {
+ FuchsiaPointerEvent pointer_event;
+ pointer_event.x = 1;
+ pointer_event.y = 1;
+ pointer_event.phase = fuchsia::ui::input::PointerEventPhase::DOWN;
+ pointer_event.type = fuchsia::ui::input::PointerEventType::TOUCH;
+ InputEvent event;
+ event.set_pointer(pointer_event);
+ dispatcher_.ProcessEvent(event);
+ EXPECT_EQ(ET_TOUCH_PRESSED, captured_event_->type());
+ ResetCapturedEvent();
+
+ pointer_event.phase = fuchsia::ui::input::PointerEventPhase::HOVER;
+ event.set_pointer(pointer_event);
+ dispatcher_.ProcessEvent(event);
+ EXPECT_EQ(ET_TOUCH_PRESSED, captured_event_->type());
+ EXPECT_TRUE(captured_event_->AsTouchEvent()->hovering());
+ ResetCapturedEvent();
+
+ pointer_event.phase = fuchsia::ui::input::PointerEventPhase::MOVE;
+ event.set_pointer(pointer_event);
+ dispatcher_.ProcessEvent(event);
+ EXPECT_EQ(ET_TOUCH_MOVED, captured_event_->type());
+ ResetCapturedEvent();
+
+ pointer_event.phase = fuchsia::ui::input::PointerEventPhase::CANCEL;
+ event.set_pointer(pointer_event);
+ dispatcher_.ProcessEvent(event);
+ EXPECT_EQ(ET_TOUCH_CANCELLED, captured_event_->type());
+ ResetCapturedEvent();
+
+ pointer_event.phase = fuchsia::ui::input::PointerEventPhase::UP;
+ event.set_pointer(pointer_event);
+ dispatcher_.ProcessEvent(event);
+ EXPECT_EQ(ET_TOUCH_RELEASED, captured_event_->type());
+ ResetCapturedEvent();
+
+ pointer_event.phase = fuchsia::ui::input::PointerEventPhase::ADD;
+ event.set_pointer(pointer_event);
+ dispatcher_.ProcessEvent(event);
+ EXPECT_EQ(nullptr, captured_event_.get());
+
+ pointer_event.phase = fuchsia::ui::input::PointerEventPhase::REMOVE;
+ event.set_pointer(pointer_event);
+ dispatcher_.ProcessEvent(event);
+ 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/gesture_detection/filtered_gesture_provider.cc b/chromium/ui/events/gesture_detection/filtered_gesture_provider.cc
index 9ef35b20278..b44f953463d 100644
--- a/chromium/ui/events/gesture_detection/filtered_gesture_provider.cc
+++ b/chromium/ui/events/gesture_detection/filtered_gesture_provider.cc
@@ -64,6 +64,10 @@ void FilteredGestureProvider::OnTouchEventAck(
is_source_touch_event_set_non_blocking);
}
+void FilteredGestureProvider::ResetGestureHandlingState() {
+ gesture_filter_.ResetGestureHandlingState();
+}
+
void FilteredGestureProvider::ResetDetection() {
gesture_provider_->ResetDetection();
}
diff --git a/chromium/ui/events/gesture_detection/filtered_gesture_provider.h b/chromium/ui/events/gesture_detection/filtered_gesture_provider.h
index 1f6761203d7..14718904d29 100644
--- a/chromium/ui/events/gesture_detection/filtered_gesture_provider.h
+++ b/chromium/ui/events/gesture_detection/filtered_gesture_provider.h
@@ -49,6 +49,8 @@ class GESTURE_DETECTION_EXPORT FilteredGestureProvider
bool event_consumed,
bool is_source_touch_event_set_non_blocking);
+ void ResetGestureHandlingState();
+
// Methods delegated to |gesture_provider_|.
void ResetDetection();
void SetMultiTouchZoomSupportEnabled(bool enabled);
diff --git a/chromium/ui/events/gesture_detection/gesture_provider.cc b/chromium/ui/events/gesture_detection/gesture_provider.cc
index ad21fe07cc5..d724b5dc819 100644
--- a/chromium/ui/events/gesture_detection/gesture_provider.cc
+++ b/chromium/ui/events/gesture_detection/gesture_provider.cc
@@ -196,8 +196,10 @@ class GestureProvider::GestureListenerImpl : public ScaleGestureListener,
break;
case ET_GESTURE_PINCH_BEGIN:
DCHECK(!pinch_event_sent_);
- if (!scroll_event_sent_)
+ if (!scroll_event_sent_ &&
+ !scale_gesture_detector_.InAnchoredScaleMode()) {
Send(GestureEventData(ET_GESTURE_SCROLL_BEGIN, gesture));
+ }
pinch_event_sent_ = true;
break;
case ET_GESTURE_PINCH_END:
diff --git a/chromium/ui/events/gesture_detection/gesture_provider_unittest.cc b/chromium/ui/events/gesture_detection/gesture_provider_unittest.cc
index 3207893aed8..4cf65bc0863 100644
--- a/chromium/ui/events/gesture_detection/gesture_provider_unittest.cc
+++ b/chromium/ui/events/gesture_detection/gesture_provider_unittest.cc
@@ -773,7 +773,6 @@ TEST_F(GestureProviderTest, DoubleTapDragZoomBasic) {
MotionEvent::Action::MOVE, kFakeCoordX,
kFakeCoordY + 100);
EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
- EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN));
ASSERT_EQ(ET_GESTURE_PINCH_BEGIN, GetNthMostRecentGestureEventType(1));
ASSERT_EQ(ET_GESTURE_PINCH_UPDATE, GetMostRecentGestureEventType());
EXPECT_LT(1.f, GetMostRecentGestureEvent().details.scale());
@@ -803,7 +802,7 @@ TEST_F(GestureProviderTest, DoubleTapDragZoomBasic) {
kFakeCoordY - 200);
EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_PINCH_END));
- EXPECT_EQ(ET_GESTURE_SCROLL_END, GetMostRecentGestureEventType());
+ EXPECT_EQ(ET_GESTURE_PINCH_END, GetMostRecentGestureEventType());
EXPECT_EQ(BoundsForSingleMockTouchAtLocation(kFakeCoordX, kFakeCoordY - 200),
GetMostRecentGestureEvent().details.bounding_box_f());
}
@@ -1273,7 +1272,7 @@ TEST_F(GestureProviderTest, NoGestureLongPressDuringDoubleTap) {
MotionEvent::Action::UP, kFakeCoordX, kFakeCoordY + 1);
event.SetPrimaryPointerId(motion_event_id);
EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
- EXPECT_EQ(ET_GESTURE_SCROLL_END, GetMostRecentGestureEventType());
+ EXPECT_EQ(ET_GESTURE_PINCH_END, GetMostRecentGestureEventType());
EXPECT_EQ(motion_event_id, GetMostRecentGestureEvent().motion_event_id);
EXPECT_EQ(1, GetMostRecentGestureEvent().details.touch_points());
EXPECT_FALSE(gesture_provider_->IsDoubleTapInProgress());
@@ -1641,7 +1640,6 @@ TEST_F(GestureProviderTest, FixedPageScaleDuringDoubleTapDragZoom) {
MotionEvent::Action::MOVE, kFakeCoordX,
kFakeCoordY + 100);
EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
- EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN));
EXPECT_EQ(ET_GESTURE_PINCH_BEGIN, GetNthMostRecentGestureEventType(1));
EXPECT_EQ(ET_GESTURE_PINCH_UPDATE, GetMostRecentGestureEventType());
EXPECT_LT(1.f, GetMostRecentGestureEvent().details.scale());
@@ -1664,7 +1662,7 @@ TEST_F(GestureProviderTest, FixedPageScaleDuringDoubleTapDragZoom) {
kFakeCoordY + 200);
EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_PINCH_END));
- EXPECT_EQ(ET_GESTURE_SCROLL_END, GetMostRecentGestureEventType());
+ EXPECT_EQ(ET_GESTURE_PINCH_END, GetMostRecentGestureEventType());
EXPECT_EQ(1, GetMostRecentGestureEvent().details.touch_points());
// The double-tap gesture has finished, but the page scale is fixed.
@@ -2094,7 +2092,6 @@ TEST_F(GestureProviderTest, DoubleTapDragZoomCancelledOnSecondaryPointerDown) {
MotionEvent::Action::MOVE, kFakeCoordX,
kFakeCoordY - 30);
EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
- EXPECT_TRUE(HasReceivedGesture(ET_GESTURE_SCROLL_BEGIN));
EXPECT_EQ(ET_GESTURE_PINCH_BEGIN, GetNthMostRecentGestureEventType(1));
EXPECT_EQ(ET_GESTURE_PINCH_UPDATE, GetMostRecentGestureEventType());
EXPECT_EQ(1, GetMostRecentGestureEvent().details.touch_points());
@@ -2115,9 +2112,7 @@ TEST_F(GestureProviderTest, DoubleTapDragZoomCancelledOnSecondaryPointerDown) {
event = ObtainMotionEvent(down_time_2 + kOneSecond, MotionEvent::Action::UP);
EXPECT_TRUE(gesture_provider_->OnTouchEvent(event));
- EXPECT_EQ(gesture_count + 1, GetReceivedGestureCount());
- EXPECT_EQ(ET_GESTURE_SCROLL_END, GetMostRecentGestureEventType());
- EXPECT_EQ(1, GetMostRecentGestureEvent().details.touch_points());
+ EXPECT_EQ(ET_GESTURE_PINCH_END, GetMostRecentGestureEventType());
}
// Verify that gesture begin and gesture end events are dispatched correctly.
diff --git a/chromium/ui/events/gesture_detection/touch_disposition_gesture_filter.cc b/chromium/ui/events/gesture_detection/touch_disposition_gesture_filter.cc
index 37bbda37ecb..6f6af6f15ae 100644
--- a/chromium/ui/events/gesture_detection/touch_disposition_gesture_filter.cc
+++ b/chromium/ui/events/gesture_detection/touch_disposition_gesture_filter.cc
@@ -181,9 +181,9 @@ TouchDispositionGestureFilter::OnGesturePacket(
Tail().back().unique_touch_event_id()));
}
if (!Head().empty()) {
- DCHECK_NE(packet.unique_touch_event_id(),
- Head().front().unique_touch_event_id());
-
+ DCHECK((packet.gesture_source() == GestureEventDataPacket::TOUCH_TIMEOUT) ||
+ packet.unique_touch_event_id() !=
+ Head().front().unique_touch_event_id());
}
Tail().push(packet);
@@ -259,6 +259,10 @@ bool TouchDispositionGestureFilter::IsEmpty() const {
return sequences_.empty();
}
+void TouchDispositionGestureFilter::ResetGestureHandlingState() {
+ state_ = GestureHandlingState();
+}
+
void TouchDispositionGestureFilter::FilterAndSendPacket(
const GestureEventDataPacket& packet) {
if (packet.gesture_source() == GestureEventDataPacket::TOUCH_SEQUENCE_START) {
diff --git a/chromium/ui/events/gesture_detection/touch_disposition_gesture_filter.h b/chromium/ui/events/gesture_detection/touch_disposition_gesture_filter.h
index 6f4683fcf71..8c63fdeb77f 100644
--- a/chromium/ui/events/gesture_detection/touch_disposition_gesture_filter.h
+++ b/chromium/ui/events/gesture_detection/touch_disposition_gesture_filter.h
@@ -52,6 +52,8 @@ class GESTURE_DETECTION_EXPORT TouchDispositionGestureFilter {
// Whether there are any active gesture sequences still queued in the filter.
bool IsEmpty() const;
+ void ResetGestureHandlingState();
+
private:
// A single GestureSequence corresponds to all gestures created
// between the first finger down and the last finger up, including gestures
diff --git a/chromium/ui/events/gestures/gesture_provider_aura.cc b/chromium/ui/events/gestures/gesture_provider_aura.cc
index b2a4d792ff2..83f085a1cae 100644
--- a/chromium/ui/events/gestures/gesture_provider_aura.cc
+++ b/chromium/ui/events/gestures/gesture_provider_aura.cc
@@ -66,6 +66,10 @@ void GestureProviderAura::OnTouchEventAck(
is_source_touch_event_set_non_blocking);
}
+void GestureProviderAura::ResetGestureHandlingState() {
+ filtered_gesture_provider_.ResetGestureHandlingState();
+}
+
void GestureProviderAura::OnGestureEvent(const GestureEventData& gesture) {
std::unique_ptr<ui::GestureEvent> event(
new ui::GestureEvent(gesture.x, gesture.y, gesture.flags,
@@ -92,10 +96,10 @@ GestureProviderAura::GetAndResetPendingGestures() {
}
void GestureProviderAura::OnTouchEnter(int pointer_id, float x, float y) {
- std::unique_ptr<TouchEvent> touch_event(new TouchEvent(
+ auto touch_event = std::make_unique<TouchEvent>(
ET_TOUCH_PRESSED, gfx::Point(), ui::EventTimeForNow(),
PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, pointer_id),
- EF_IS_SYNTHESIZED, 0.0f));
+ EF_IS_SYNTHESIZED);
gfx::PointF point(x, y);
touch_event->set_location_f(point);
touch_event->set_root_location_f(point);
diff --git a/chromium/ui/events/gestures/gesture_provider_aura.h b/chromium/ui/events/gestures/gesture_provider_aura.h
index 987fbbe254b..7072bf8e9ff 100644
--- a/chromium/ui/events/gestures/gesture_provider_aura.h
+++ b/chromium/ui/events/gestures/gesture_provider_aura.h
@@ -49,6 +49,8 @@ class EVENTS_EXPORT GestureProviderAura : public GestureProviderClient {
std::vector<std::unique_ptr<GestureEvent>> GetAndResetPendingGestures();
void OnTouchEnter(int pointer_id, float x, float y);
+ void ResetGestureHandlingState();
+
// GestureProviderClient implementation
void OnGestureEvent(const GestureEventData& gesture) override;
bool RequiresDoubleTapGestureEvents() const override;
diff --git a/chromium/ui/events/gestures/gesture_provider_aura_unittest.cc b/chromium/ui/events/gestures/gesture_provider_aura_unittest.cc
index 1eaa215287d..b425a987fae 100644
--- a/chromium/ui/events/gestures/gesture_provider_aura_unittest.cc
+++ b/chromium/ui/events/gestures/gesture_provider_aura_unittest.cc
@@ -125,55 +125,55 @@ TEST_F(GestureProviderAuraTest, IgnoresIdenticalMoveEvents) {
const int kTouchId0 = 5;
const int kTouchId1 = 3;
- PointerDetails pointerDetails1(EventPointerType::POINTER_TYPE_TOUCH,
- kTouchId0);
+ PointerDetails pointer_details1(EventPointerType::POINTER_TYPE_TOUCH,
+ kTouchId0);
base::TimeTicks time = ui::EventTimeForNow();
TouchEvent press0_1(ET_TOUCH_PRESSED, gfx::Point(9, 10), time,
- pointerDetails1);
+ pointer_details1);
EXPECT_TRUE(provider()->OnTouchEvent(&press0_1));
- PointerDetails pointerDetails2(EventPointerType::POINTER_TYPE_TOUCH,
- kTouchId1);
+ PointerDetails pointer_details2(EventPointerType::POINTER_TYPE_TOUCH,
+ kTouchId1);
TouchEvent press1_1(ET_TOUCH_PRESSED, gfx::Point(40, 40), time,
- pointerDetails2);
+ pointer_details2);
EXPECT_TRUE(provider()->OnTouchEvent(&press1_1));
time += base::TimeDelta::FromMilliseconds(10);
- pointerDetails1 = PointerDetails(EventPointerType::POINTER_TYPE_TOUCH,
- kTouchId0, kRadiusX, kRadiusY, kForce);
- TouchEvent move0_1(ET_TOUCH_MOVED, gfx::Point(10, 10), time, pointerDetails1,
- 0, kAngle);
+ pointer_details1 =
+ PointerDetails(EventPointerType::POINTER_TYPE_TOUCH, kTouchId0, kRadiusX,
+ kRadiusY, kForce, kAngle);
+ TouchEvent move0_1(ET_TOUCH_MOVED, gfx::Point(10, 10), time, pointer_details1,
+ 0);
EXPECT_TRUE(provider()->OnTouchEvent(&move0_1));
- pointerDetails2 = PointerDetails(EventPointerType::POINTER_TYPE_TOUCH,
- kTouchId1, kRadiusX, kRadiusY, kForce);
+ pointer_details2 =
+ PointerDetails(EventPointerType::POINTER_TYPE_TOUCH, kTouchId1, kRadiusX,
+ kRadiusY, kForce, kAngle);
TouchEvent move1_1(ET_TOUCH_MOVED, gfx::Point(100, 200), time,
- pointerDetails2, 0, kAngle);
+ pointer_details2, 0);
EXPECT_TRUE(provider()->OnTouchEvent(&move1_1));
time += base::TimeDelta::FromMilliseconds(10);
- TouchEvent move0_2(ET_TOUCH_MOVED, gfx::Point(10, 10), time, pointerDetails1,
- 0, kAngle);
+ TouchEvent move0_2(ET_TOUCH_MOVED, gfx::Point(10, 10), time, pointer_details1,
+ 0);
// Nothing has changed, so ignore the move.
EXPECT_FALSE(provider()->OnTouchEvent(&move0_2));
TouchEvent move1_2(ET_TOUCH_MOVED, gfx::Point(100, 200), time,
- pointerDetails2, 0, kAngle);
+ pointer_details2, 0);
// Nothing has changed, so ignore the move.
EXPECT_FALSE(provider()->OnTouchEvent(&move1_2));
time += base::TimeDelta::FromMilliseconds(10);
- TouchEvent move0_3(ET_TOUCH_MOVED, gfx::Point(), time, pointerDetails1, 0,
- kAngle);
+ TouchEvent move0_3(ET_TOUCH_MOVED, gfx::Point(), time, pointer_details1, 0);
move0_3.set_location_f(gfx::PointF(70, 75.1f));
move0_3.set_root_location_f(gfx::PointF(70, 75.1f));
// Position has changed, so don't ignore the move.
EXPECT_TRUE(provider()->OnTouchEvent(&move0_3));
time += base::TimeDelta::FromMilliseconds(10);
- pointerDetails2.radius_y += 1;
- TouchEvent move0_4(ET_TOUCH_MOVED, gfx::Point(), time, pointerDetails2, 0,
- kAngle);
+ pointer_details2.radius_y += 1;
+ TouchEvent move0_4(ET_TOUCH_MOVED, gfx::Point(), time, pointer_details2, 0);
move0_4.set_location_f(gfx::PointF(70, 75.1f));
move0_4.set_root_location_f(gfx::PointF(70, 75.1f));
}
diff --git a/chromium/ui/events/gestures/gesture_recognizer.cc b/chromium/ui/events/gestures/gesture_recognizer.cc
new file mode 100644
index 00000000000..533ab77e924
--- /dev/null
+++ b/chromium/ui/events/gestures/gesture_recognizer.cc
@@ -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.
+
+#include "ui/events/gestures/gesture_recognizer.h"
+
+#include "ui/events/gestures/gesture_recognizer_observer.h"
+
+namespace ui {
+
+GestureRecognizer::GestureRecognizer() = default;
+GestureRecognizer::~GestureRecognizer() = default;
+
+void GestureRecognizer::AddObserver(GestureRecognizerObserver* observer) {
+ observers_.AddObserver(observer);
+}
+
+void GestureRecognizer::RemoveObserver(GestureRecognizerObserver* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+} // namespace ui
diff --git a/chromium/ui/events/gestures/gesture_recognizer.h b/chromium/ui/events/gestures/gesture_recognizer.h
index f4da6a06dd7..de966ee36aa 100644
--- a/chromium/ui/events/gestures/gesture_recognizer.h
+++ b/chromium/ui/events/gestures/gesture_recognizer.h
@@ -10,19 +10,23 @@
#include <memory>
#include <vector>
+#include "base/observer_list.h"
#include "ui/events/event_constants.h"
#include "ui/events/events_export.h"
#include "ui/events/gestures/gesture_types.h"
#include "ui/gfx/geometry/point_f.h"
namespace ui {
+class GestureRecognizerObserver;
+
// A GestureRecognizer is an abstract base class for conversion of touch events
// into gestures.
class EVENTS_EXPORT GestureRecognizer {
public:
using Gestures = std::vector<std::unique_ptr<GestureEvent>>;
- virtual ~GestureRecognizer() {}
+ GestureRecognizer();
+ virtual ~GestureRecognizer();
// Invoked before event dispatch. If the event is invalid given the current
// touch sequence, returns false.
@@ -57,15 +61,14 @@ class EVENTS_EXPORT GestureRecognizer {
// |not_cancelled| == nullptr, cancels all touches.
virtual void CancelActiveTouchesExcept(GestureConsumer* not_cancelled) = 0;
- enum class ShouldCancelTouches { Cancel, DontCancel };
-
// Transfer the gesture stream from the drag source (current_consumer) to the
- // consumer used for dragging (new_consumer). If |should_cancel_touches| is
- // Cancel, dispatches cancel events to |current_consumer| to ensure that its
- // touch stream remains valid.
- virtual void TransferEventsTo(GestureConsumer* current_consumer,
- GestureConsumer* new_consumer,
- ShouldCancelTouches should_cancel_touches) = 0;
+ // consumer used for dragging (new_consumer). If |transfer_touches_behavior|
+ // is kCancel, dispatches cancel events to |current_consumer| to ensure that
+ // its touch stream remains valid.
+ virtual void TransferEventsTo(
+ GestureConsumer* current_consumer,
+ GestureConsumer* new_consumer,
+ TransferTouchesBehavior transfer_touches_behavior) = 0;
// If a gesture is underway for |consumer| |point| is set to the last touch
// point and true is returned. If no touch events have been processed for
@@ -87,6 +90,19 @@ class EVENTS_EXPORT GestureRecognizer {
// Since the GestureRecognizer does not own the |helper|, it is not deleted
// and must be cleaned up appropriately by the caller.
virtual void RemoveGestureEventHelper(GestureEventHelper* helper) = 0;
+
+ void AddObserver(GestureRecognizerObserver* observer);
+ void RemoveObserver(GestureRecognizerObserver* observer);
+
+ protected:
+ const base::ObserverList<GestureRecognizerObserver>& observers() {
+ return observers_;
+ }
+
+ private:
+ base::ObserverList<GestureRecognizerObserver> observers_;
+
+ DISALLOW_COPY_AND_ASSIGN(GestureRecognizer);
};
} // namespace ui
diff --git a/chromium/ui/events/gestures/gesture_recognizer_impl.cc b/chromium/ui/events/gestures/gesture_recognizer_impl.cc
index 1702be9de15..6e811311856 100644
--- a/chromium/ui/events/gestures/gesture_recognizer_impl.cc
+++ b/chromium/ui/events/gestures/gesture_recognizer_impl.cc
@@ -19,6 +19,7 @@
#include "ui/events/event_switches.h"
#include "ui/events/event_utils.h"
#include "ui/events/gesture_detection/gesture_configuration.h"
+#include "ui/events/gestures/gesture_recognizer_observer.h"
#include "ui/events/gestures/gesture_types.h"
namespace ui {
@@ -107,33 +108,21 @@ GestureConsumer* GestureRecognizerImpl::GetTargetForLocation(
void GestureRecognizerImpl::CancelActiveTouchesExcept(
GestureConsumer* not_cancelled) {
- // Do not iterate directly over |consumer_gesture_provider_| because canceling
- // active touches may cause the consumer to be removed from
- // |consumer_gesture_provider_|. See crbug.com/651258 for more info.
- std::vector<GestureConsumer*> consumers(consumer_gesture_provider_.size());
- for (const auto& entry : consumer_gesture_provider_) {
- if (entry.first == not_cancelled)
- continue;
-
- consumers.push_back(entry.first);
- }
-
- for (auto* consumer : consumers)
- CancelActiveTouches(consumer);
+ CancelActiveTouchesExceptImpl(not_cancelled, kNotifyObservers);
}
void GestureRecognizerImpl::TransferEventsTo(
GestureConsumer* current_consumer,
GestureConsumer* new_consumer,
- ShouldCancelTouches should_cancel_touches) {
+ TransferTouchesBehavior transfer_touches_behavior) {
// This method transfers the gesture stream from |current_consumer| to
- // |new_consumer|. If |should_cancel_touches| is Cancel, it ensures that both
- // consumers retain a touch event stream which is reasonably valid. In order
- // to do this we
+ // |new_consumer|. If |transfer_touches_behavior| is kCancel, it ensures that
+ // both consumers retain a touch event stream which is reasonably valid. In
+ // order to do this we
// - record what pointers are currently down on |current_consumer|
// - cancel touches on consumers other than |current_consumer|
// - move the gesture provider from |current_consumer| to |new_consumer|
- // - if |should_cancel_touches|
+ // - if |transfer_touches_behavior| is kCancel
// - synchronize the state of the new gesture provider associated with
// current_consumer with with the touch state of the consumer itself via
// OnTouchEnter.
@@ -153,7 +142,7 @@ void GestureRecognizerImpl::TransferEventsTo(
touchids_targeted_at_current.push_back(touch_id_target.first);
}
- CancelActiveTouchesExcept(current_consumer);
+ CancelActiveTouchesExceptImpl(current_consumer, kDontNotifyObservers);
std::vector<std::unique_ptr<TouchEvent>> cancelling_touches =
GetEventPerPointForConsumer(current_consumer, ET_TOUCH_CANCELLED);
@@ -164,9 +153,7 @@ void GestureRecognizerImpl::TransferEventsTo(
// but has some pointers down which need cancelling. In order to ensure that
// the GR sees a valid event stream, inform it of these pointers via
// OnTouchEnter, and then synthesize a touch cancel per pointer.
- if (should_cancel_touches ==
- GestureRecognizer::ShouldCancelTouches::Cancel &&
- helper) {
+ if (transfer_touches_behavior == TransferTouchesBehavior::kCancel && helper) {
GestureProviderAura* gesture_provider =
GetGestureProviderForConsumer(current_consumer);
@@ -177,8 +164,18 @@ void GestureRecognizerImpl::TransferEventsTo(
}
}
+ // The underlying gesture provider for current_consumer might have filtered
+ // gesture detection for some reasons but that might not be applied to the new
+ // consumer. See also:
+ // https://docs.google.com/document/d/1AKeK8IuF-j2TJ-2sPsewORXdjnr6oAzy5nnR1zwrsfc/edit#
+ if (base::ContainsKey(consumer_gesture_provider_, new_consumer))
+ GetGestureProviderForConsumer(new_consumer)->ResetGestureHandlingState();
+
for (int touch_id : touchids_targeted_at_current)
touch_id_target_[touch_id] = new_consumer;
+ for (GestureRecognizerObserver& observer : observers())
+ observer.OnEventsTransferred(current_consumer, new_consumer,
+ transfer_touches_behavior);
}
bool GestureRecognizerImpl::GetLastTouchPointForTarget(
@@ -210,11 +207,11 @@ GestureRecognizerImpl::GetEventPerPointForConsumer(GestureConsumer* consumer,
if (pointer_state.GetPointerCount() == 0)
return cancelling_touches;
for (size_t i = 0; i < pointer_state.GetPointerCount(); ++i) {
- std::unique_ptr<TouchEvent> touch_event(
- new TouchEvent(type, gfx::Point(), EventTimeForNow(),
- PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH,
- pointer_state.GetPointerId(i)),
- EF_IS_SYNTHESIZED, 0.0f));
+ auto touch_event = std::make_unique<TouchEvent>(
+ type, gfx::Point(), EventTimeForNow(),
+ PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH,
+ pointer_state.GetPointerId(i)),
+ EF_IS_SYNTHESIZED);
gfx::PointF point(pointer_state.GetX(i), pointer_state.GetY(i));
touch_event->set_location_f(point);
touch_event->set_root_location_f(point);
@@ -224,21 +221,11 @@ GestureRecognizerImpl::GetEventPerPointForConsumer(GestureConsumer* consumer,
}
bool GestureRecognizerImpl::CancelActiveTouches(GestureConsumer* consumer) {
- GestureEventHelper* helper =
- FindDispatchHelperForConsumer(consumer);
-
- if (!helper)
- return false;
-
- std::vector<std::unique_ptr<TouchEvent>> cancelling_touches =
- GetEventPerPointForConsumer(consumer, ET_TOUCH_CANCELLED);
- for (const std::unique_ptr<TouchEvent>& cancelling_touch : cancelling_touches)
- helper->DispatchSyntheticTouchEvent(cancelling_touch.get());
- return cancelling_touches.size() > 0U;
+ return CancelActiveTouchesImpl(consumer, kNotifyObservers);
}
////////////////////////////////////////////////////////////////////////////////
-// GestureRecognizerImpl, private:
+// GestureRecognizerImpl, protected:
GestureProviderAura* GestureRecognizerImpl::GetGestureProviderForConsumer(
GestureConsumer* consumer) {
@@ -256,6 +243,22 @@ GestureProviderAura* GestureRecognizerImpl::GetGestureProviderForConsumer(
return gesture_provider;
}
+bool GestureRecognizerImpl::ProcessTouchEventPreDispatch(
+ TouchEvent* event,
+ GestureConsumer* consumer) {
+ SetupTargets(*event, consumer);
+
+ if (event->result() & ER_CONSUMED)
+ return false;
+
+ GestureProviderAura* gesture_provider =
+ GetGestureProviderForConsumer(consumer);
+ return gesture_provider->OnTouchEvent(event);
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// GestureRecognizerImpl, private:
+
void GestureRecognizerImpl::SetupTargets(const TouchEvent& event,
GestureConsumer* target) {
event_to_gesture_provider_[event.unique_event_id()] =
@@ -279,19 +282,6 @@ void GestureRecognizerImpl::DispatchGestureEvent(
}
}
-bool GestureRecognizerImpl::ProcessTouchEventPreDispatch(
- TouchEvent* event,
- GestureConsumer* consumer) {
- SetupTargets(*event, consumer);
-
- if (event->result() & ER_CONSUMED)
- return false;
-
- GestureProviderAura* gesture_provider =
- GetGestureProviderForConsumer(consumer);
- return gesture_provider->OnTouchEvent(event);
-}
-
GestureRecognizer::Gestures GestureRecognizerImpl::AckTouchEvent(
uint32_t unique_event_id,
ui::EventResult result,
@@ -314,6 +304,48 @@ GestureRecognizer::Gestures GestureRecognizerImpl::AckTouchEvent(
return gesture_provider->GetAndResetPendingGestures();
}
+void GestureRecognizerImpl::CancelActiveTouchesExceptImpl(
+ GestureConsumer* not_cancelled,
+ ShouldNotifyObservers should_notify) {
+ // Do not iterate directly over |consumer_gesture_provider_| because canceling
+ // active touches may cause the consumer to be removed from
+ // |consumer_gesture_provider_|. See https://crbug.com/651258 for more info.
+ std::vector<GestureConsumer*> consumers(consumer_gesture_provider_.size());
+ for (const auto& entry : consumer_gesture_provider_) {
+ if (entry.first == not_cancelled)
+ continue;
+
+ consumers.push_back(entry.first);
+ }
+
+ for (auto* consumer : consumers)
+ CancelActiveTouchesImpl(consumer, kDontNotifyObservers);
+
+ if (should_notify == kDontNotifyObservers)
+ return;
+ for (GestureRecognizerObserver& observer : observers())
+ observer.OnActiveTouchesCanceledExcept(not_cancelled);
+}
+
+bool GestureRecognizerImpl::CancelActiveTouchesImpl(
+ GestureConsumer* consumer,
+ ShouldNotifyObservers should_notify) {
+ GestureEventHelper* helper = FindDispatchHelperForConsumer(consumer);
+
+ if (!helper)
+ return false;
+
+ std::vector<std::unique_ptr<TouchEvent>> cancelling_touches =
+ GetEventPerPointForConsumer(consumer, ET_TOUCH_CANCELLED);
+ for (const std::unique_ptr<TouchEvent>& cancelling_touch : cancelling_touches)
+ helper->DispatchSyntheticTouchEvent(cancelling_touch.get());
+ if (should_notify == kNotifyObservers) {
+ for (GestureRecognizerObserver& observer : observers())
+ observer.OnActiveTouchesCanceled(consumer);
+ }
+ return !cancelling_touches.empty();
+}
+
bool GestureRecognizerImpl::CleanupStateForConsumer(
GestureConsumer* consumer) {
bool state_cleaned_up = false;
@@ -341,8 +373,7 @@ void GestureRecognizerImpl::AddGestureEventHelper(GestureEventHelper* helper) {
void GestureRecognizerImpl::RemoveGestureEventHelper(
GestureEventHelper* helper) {
- std::vector<GestureEventHelper*>::iterator it = std::find(helpers_.begin(),
- helpers_.end(), helper);
+ auto it = std::find(helpers_.begin(), helpers_.end(), helper);
if (it != helpers_.end())
helpers_.erase(it);
}
diff --git a/chromium/ui/events/gestures/gesture_recognizer_impl.h b/chromium/ui/events/gestures/gesture_recognizer_impl.h
index ba6c416b7fc..36e8fc9f2cc 100644
--- a/chromium/ui/events/gestures/gesture_recognizer_impl.h
+++ b/chromium/ui/events/gestures/gesture_recognizer_impl.h
@@ -48,9 +48,10 @@ class EVENTS_EXPORT GestureRecognizerImpl : public GestureRecognizer,
GestureConsumer* GetTargetForLocation(const gfx::PointF& location,
int source_device_id) override;
void CancelActiveTouchesExcept(GestureConsumer* not_cancelled) override;
- void TransferEventsTo(GestureConsumer* current_consumer,
- GestureConsumer* new_consumer,
- ShouldCancelTouches should_cancel_touches) override;
+ void TransferEventsTo(
+ GestureConsumer* current_consumer,
+ GestureConsumer* new_consumer,
+ TransferTouchesBehavior transfer_touches_behavior) override;
bool GetLastTouchPointForTarget(GestureConsumer* consumer,
gfx::PointF* point) override;
bool CancelActiveTouches(GestureConsumer* consumer) override;
@@ -64,6 +65,8 @@ class EVENTS_EXPORT GestureRecognizerImpl : public GestureRecognizer,
GestureConsumer* consumer) override;
private:
+ enum ShouldNotifyObservers { kNotifyObservers, kDontNotifyObservers };
+
// Sets up the target consumer for gestures based on the touch-event.
void SetupTargets(const TouchEvent& event, GestureConsumer* consumer);
@@ -75,6 +78,11 @@ class EVENTS_EXPORT GestureRecognizerImpl : public GestureRecognizer,
bool is_source_touch_event_set_non_blocking,
GestureConsumer* consumer) override;
+ void CancelActiveTouchesExceptImpl(GestureConsumer* not_cancelled,
+ ShouldNotifyObservers should_notify);
+ bool CancelActiveTouchesImpl(GestureConsumer* consumer,
+ ShouldNotifyObservers should_notify);
+
bool CleanupStateForConsumer(GestureConsumer* consumer) override;
void AddGestureEventHelper(GestureEventHelper* helper) override;
void RemoveGestureEventHelper(GestureEventHelper* helper) override;
diff --git a/chromium/ui/events/gestures/gesture_recognizer_impl_mac.cc b/chromium/ui/events/gestures/gesture_recognizer_impl_mac.cc
index b52a8db1d32..d66805dfef0 100644
--- a/chromium/ui/events/gestures/gesture_recognizer_impl_mac.cc
+++ b/chromium/ui/events/gestures/gesture_recognizer_impl_mac.cc
@@ -45,7 +45,7 @@ void GestureRecognizerImplMac::CancelActiveTouchesExcept(
void GestureRecognizerImplMac::TransferEventsTo(
GestureConsumer* current_consumer,
GestureConsumer* new_consumer,
- ShouldCancelTouches should_cancel_touches) {}
+ TransferTouchesBehavior transfer_touches_behavior) {}
bool GestureRecognizerImplMac::GetLastTouchPointForTarget(
GestureConsumer* consumer,
diff --git a/chromium/ui/events/gestures/gesture_recognizer_impl_mac.h b/chromium/ui/events/gestures/gesture_recognizer_impl_mac.h
index 391bd2bbec3..f0c4615f436 100644
--- a/chromium/ui/events/gestures/gesture_recognizer_impl_mac.h
+++ b/chromium/ui/events/gestures/gesture_recognizer_impl_mac.h
@@ -34,9 +34,10 @@ class EVENTS_EXPORT GestureRecognizerImplMac : public GestureRecognizer {
GestureConsumer* GetTargetForLocation(const gfx::PointF& location,
int source_device_id) override;
void CancelActiveTouchesExcept(GestureConsumer* not_cancelled) override;
- void TransferEventsTo(GestureConsumer* current_consumer,
- GestureConsumer* new_consumer,
- ShouldCancelTouches should_cancel_touches) override;
+ void TransferEventsTo(
+ GestureConsumer* current_consumer,
+ GestureConsumer* new_consumer,
+ TransferTouchesBehavior transfer_touches_behavior) override;
bool GetLastTouchPointForTarget(GestureConsumer* consumer,
gfx::PointF* point) override;
bool CancelActiveTouches(GestureConsumer* consumer) override;
diff --git a/chromium/ui/events/gestures/gesture_recognizer_impl_unittest.cc b/chromium/ui/events/gestures/gesture_recognizer_impl_unittest.cc
new file mode 100644
index 00000000000..6446df7a5c5
--- /dev/null
+++ b/chromium/ui/events/gestures/gesture_recognizer_impl_unittest.cc
@@ -0,0 +1,163 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/gestures/gesture_recognizer_impl.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/gestures/gesture_recognizer_observer.h"
+
+namespace ui {
+
+class TestGestureRecognizerObserver : public GestureRecognizerObserver {
+ public:
+ TestGestureRecognizerObserver(GestureRecognizer* gesture_recognizer)
+ : gesture_recognizer_(gesture_recognizer) {
+ gesture_recognizer_->AddObserver(this);
+ }
+
+ ~TestGestureRecognizerObserver() override {
+ gesture_recognizer_->RemoveObserver(this);
+ }
+
+ int active_touches_cancelled_except_call_count() const {
+ return active_touches_cancelled_except_call_count_;
+ }
+ int active_touches_cancelled_call_count() const {
+ return active_touches_cancelled_call_count_;
+ }
+ int events_transfer_call_count() const { return events_transfer_call_count_; }
+
+ const GestureConsumer* last_not_cancelled() const {
+ return last_not_cancelled_;
+ }
+ const GestureConsumer* last_cancelled() const {
+ return last_cancelled_consumer_;
+ }
+
+ const GestureConsumer* last_transferred_source() const {
+ return last_transferred_source_;
+ }
+ const GestureConsumer* last_transferred_destination() const {
+ return last_transferred_destination_;
+ }
+ TransferTouchesBehavior last_transfer_touches_behavior() const {
+ return last_transfer_touches_behavior_;
+ }
+
+ private:
+ // GestureRecognizerObserver:
+ void OnActiveTouchesCanceledExcept(GestureConsumer* not_cancelled) override {
+ active_touches_cancelled_except_call_count_++;
+ last_not_cancelled_ = not_cancelled;
+ }
+ void OnEventsTransferred(
+ GestureConsumer* current_consumer,
+ GestureConsumer* new_consumer,
+ TransferTouchesBehavior transfer_touches_behavior) override {
+ events_transfer_call_count_++;
+ last_transferred_source_ = current_consumer;
+ last_transferred_destination_ = new_consumer;
+ last_transfer_touches_behavior_ = transfer_touches_behavior;
+ }
+ void OnActiveTouchesCanceled(GestureConsumer* consumer) override {
+ active_touches_cancelled_call_count_++;
+ last_cancelled_consumer_ = consumer;
+ }
+
+ GestureRecognizer* gesture_recognizer_;
+
+ int active_touches_cancelled_except_call_count_ = 0;
+ int active_touches_cancelled_call_count_ = 0;
+ int events_transfer_call_count_ = 0;
+ GestureConsumer* last_not_cancelled_ = nullptr;
+ GestureConsumer* last_cancelled_consumer_ = nullptr;
+ GestureConsumer* last_transferred_source_ = nullptr;
+ GestureConsumer* last_transferred_destination_ = nullptr;
+ TransferTouchesBehavior last_transfer_touches_behavior_ =
+ TransferTouchesBehavior::kCancel;
+
+ DISALLOW_COPY_AND_ASSIGN(TestGestureRecognizerObserver);
+};
+
+class TestGestureEventHelper : public GestureEventHelper {
+ public:
+ TestGestureEventHelper() = default;
+ ~TestGestureEventHelper() override = default;
+
+ private:
+ // GestureEventHelper:
+ bool CanDispatchToConsumer(GestureConsumer* consumer) override {
+ return true;
+ }
+ void DispatchGestureEvent(GestureConsumer* raw_input_consumer,
+ GestureEvent* event) override {}
+ void DispatchSyntheticTouchEvent(TouchEvent* event) override {}
+
+ DISALLOW_COPY_AND_ASSIGN(TestGestureEventHelper);
+};
+
+class GestureRecognizerImplTest : public testing::Test {
+ public:
+ GestureRecognizerImplTest() = default;
+ ~GestureRecognizerImplTest() override = default;
+
+ void SetUp() override {
+ gesture_recognizer_.helpers().push_back(&helper_);
+ observer_ =
+ std::make_unique<TestGestureRecognizerObserver>(&gesture_recognizer_);
+ }
+
+ void TearDown() override { observer_.reset(); }
+
+ protected:
+ GestureRecognizer* gesture_recognizer() { return &gesture_recognizer_; }
+ TestGestureRecognizerObserver* observer() { return observer_.get(); }
+
+ private:
+ GestureRecognizerImpl gesture_recognizer_;
+ TestGestureEventHelper helper_;
+ std::unique_ptr<TestGestureRecognizerObserver> observer_;
+
+ DISALLOW_COPY_AND_ASSIGN(GestureRecognizerImplTest);
+};
+
+TEST_F(GestureRecognizerImplTest, CancelActiveTouchEvents) {
+ GestureConsumer consumer;
+ gesture_recognizer()->CancelActiveTouches(&consumer);
+
+ EXPECT_EQ(1, observer()->active_touches_cancelled_call_count());
+ EXPECT_EQ(&consumer, observer()->last_cancelled());
+}
+
+TEST_F(GestureRecognizerImplTest, CancelActiveTouchEventsExcept) {
+ GestureConsumer consumer;
+ gesture_recognizer()->CancelActiveTouchesExcept(&consumer);
+
+ // OnActiveTouchesCancelled() shouldn't occur.
+ EXPECT_EQ(0, observer()->active_touches_cancelled_call_count());
+ EXPECT_EQ(1, observer()->active_touches_cancelled_except_call_count());
+ EXPECT_EQ(&consumer, observer()->last_not_cancelled());
+}
+
+TEST_F(GestureRecognizerImplTest, CancelActiveTouchEventsExceptNullPtr) {
+ gesture_recognizer()->CancelActiveTouchesExcept(nullptr);
+
+ EXPECT_EQ(1, observer()->active_touches_cancelled_except_call_count());
+ EXPECT_FALSE(observer()->last_not_cancelled());
+}
+
+TEST_F(GestureRecognizerImplTest, TransferEventsTo) {
+ GestureConsumer consumer1;
+ GestureConsumer consumer2;
+
+ gesture_recognizer()->TransferEventsTo(&consumer1, &consumer2,
+ TransferTouchesBehavior::kDontCancel);
+ EXPECT_EQ(1, observer()->events_transfer_call_count());
+ EXPECT_EQ(&consumer1, observer()->last_transferred_source());
+ EXPECT_EQ(&consumer2, observer()->last_transferred_destination());
+ EXPECT_EQ(TransferTouchesBehavior::kDontCancel,
+ observer()->last_transfer_touches_behavior());
+}
+
+} // namespace ui
diff --git a/chromium/ui/events/gestures/gesture_recognizer_observer.cc b/chromium/ui/events/gestures/gesture_recognizer_observer.cc
new file mode 100644
index 00000000000..4430530ca6e
--- /dev/null
+++ b/chromium/ui/events/gestures/gesture_recognizer_observer.cc
@@ -0,0 +1,11 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/events/gestures/gesture_recognizer_observer.h"
+
+namespace ui {
+
+GestureRecognizerObserver::~GestureRecognizerObserver() = default;
+
+} // namespace ui
diff --git a/chromium/ui/events/gestures/gesture_recognizer_observer.h b/chromium/ui/events/gestures/gesture_recognizer_observer.h
new file mode 100644
index 00000000000..4826cda5bb2
--- /dev/null
+++ b/chromium/ui/events/gestures/gesture_recognizer_observer.h
@@ -0,0 +1,30 @@
+// 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_GESTURES_GESTURE_RECOGNIZER_OBSERVER_H_
+#define UI_EVENTS_GESTURES_GESTURE_RECOGNIZER_OBSERVER_H_
+
+#include "base/observer_list_types.h"
+#include "ui/events/events_export.h"
+#include "ui/events/gestures/gesture_types.h"
+
+namespace ui {
+
+class EVENTS_EXPORT GestureRecognizerObserver : public base::CheckedObserver {
+ public:
+ virtual void OnActiveTouchesCanceledExcept(
+ GestureConsumer* not_cancelled) = 0;
+ virtual void OnEventsTransferred(
+ GestureConsumer* current_consumer,
+ GestureConsumer* new_consumer,
+ TransferTouchesBehavior transfer_touches_behavior) = 0;
+ virtual void OnActiveTouchesCanceled(GestureConsumer* consumer) = 0;
+
+ protected:
+ ~GestureRecognizerObserver() override;
+};
+
+} // namespace ui
+
+#endif // UI_EVENTS_GESTURES_GESTURE_RECOGNIZER_OBSERVER_H_
diff --git a/chromium/ui/events/gestures/gesture_types.h b/chromium/ui/events/gestures/gesture_types.h
index 3d63c572279..e2334111ea8 100644
--- a/chromium/ui/events/gestures/gesture_types.h
+++ b/chromium/ui/events/gestures/gesture_types.h
@@ -12,6 +12,17 @@ namespace ui {
class GestureEvent;
class TouchEvent;
+// TransferTouchesBehavior customizes the behavior of
+// GestureRecognizer::TransferEventsTo.
+enum class TransferTouchesBehavior {
+ // Dispatches the cancel events to the current consumer on transfer to ensure
+ // its touch stream remains valid.
+ kCancel,
+
+ // Do not dispatch cancel events.
+ kDontCancel
+};
+
// An abstract type for consumers of gesture-events created by the
// gesture-recognizer.
class EVENTS_EXPORT GestureConsumer {
diff --git a/chromium/ui/events/gestures/motion_event_aura_unittest.cc b/chromium/ui/events/gestures/motion_event_aura_unittest.cc
index 276876f2059..5fb665b71cd 100644
--- a/chromium/ui/events/gestures/motion_event_aura_unittest.cc
+++ b/chromium/ui/events/gestures/motion_event_aura_unittest.cc
@@ -40,8 +40,8 @@ ui::TouchEvent TouchWithTapParams(ui::EventType type,
ui::TouchEvent event(
type, gfx::Point(1, 1), base::TimeTicks(),
ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, id, radius_x,
- radius_y, pressure),
- 0, rotation_angle);
+ radius_y, pressure, rotation_angle),
+ 0);
return event;
}
diff --git a/chromium/ui/events/keyboard_hook.h b/chromium/ui/events/keyboard_hook.h
index accb8050a79..36e9b88f23e 100644
--- a/chromium/ui/events/keyboard_hook.h
+++ b/chromium/ui/events/keyboard_hook.h
@@ -38,7 +38,7 @@ class EVENTS_EXPORT KeyboardHook {
KeyEventCallback callback);
// True if |dom_code| is reserved for an active KeyboardLock request.
- virtual bool IsKeyLocked(DomCode dom_code) = 0;
+ virtual bool IsKeyLocked(DomCode dom_code) const = 0;
};
} // namespace ui
diff --git a/chromium/ui/events/keyboard_hook_base.cc b/chromium/ui/events/keyboard_hook_base.cc
index 6f971814170..56381738b4a 100644
--- a/chromium/ui/events/keyboard_hook_base.cc
+++ b/chromium/ui/events/keyboard_hook_base.cc
@@ -23,7 +23,7 @@ KeyboardHookBase::KeyboardHookBase(
KeyboardHookBase::~KeyboardHookBase() = default;
-bool KeyboardHookBase::IsKeyLocked(DomCode dom_code) {
+bool KeyboardHookBase::IsKeyLocked(DomCode dom_code) const {
return ShouldCaptureKeyEvent(dom_code);
}
diff --git a/chromium/ui/events/keyboard_hook_base.h b/chromium/ui/events/keyboard_hook_base.h
index 8d18d94246d..81ffae2ff9f 100644
--- a/chromium/ui/events/keyboard_hook_base.h
+++ b/chromium/ui/events/keyboard_hook_base.h
@@ -22,7 +22,7 @@ class KeyboardHookBase : public KeyboardHook {
~KeyboardHookBase() override;
// KeyboardHook implementation.
- bool IsKeyLocked(DomCode dom_code) override;
+ bool IsKeyLocked(DomCode dom_code) const override;
protected:
// Indicates whether |dom_code| should be intercepted by the keyboard hook.
diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm b/chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm
index 2b4dd2f096d..873c4ce4457 100644
--- a/chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm
+++ b/chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm
@@ -892,7 +892,7 @@ UniChar TranslatedUnicodeCharFromKeyCode(TISInputSourceRef input_source,
&buffer_length, char_buffer);
OSSTATUS_DCHECK(ret == noErr, ret);
- // TODO(chongz): Handle multiple character case. Should be rare.
+ // TODO(input-dev): Handle multiple character case. Should be rare.
return char_buffer[0];
}
diff --git a/chromium/ui/events/keycodes/keysym_to_unicode.cc b/chromium/ui/events/keycodes/keysym_to_unicode.cc
index 5a358804aed..9413e97d59b 100644
--- a/chromium/ui/events/keycodes/keysym_to_unicode.cc
+++ b/chromium/ui/events/keycodes/keysym_to_unicode.cc
@@ -834,7 +834,7 @@ class KeySymToUnicode {
}
// Other KeySyms which are not Unicode-style.
- KeySymToUnicodeMap::const_iterator i = keysym_to_unicode_map_.find(keysym);
+ auto i = keysym_to_unicode_map_.find(keysym);
return i != keysym_to_unicode_map_.end() ? i->second : 0;
}
diff --git a/chromium/ui/events/keycodes/platform_key_map_win.cc b/chromium/ui/events/keycodes/platform_key_map_win.cc
index c1e3b8368df..c803dc47130 100644
--- a/chromium/ui/events/keycodes/platform_key_map_win.cc
+++ b/chromium/ui/events/keycodes/platform_key_map_win.cc
@@ -192,7 +192,7 @@ const struct NonPrintableKeyEntry {
{VKEY_EREOF, DomKey::ERASE_EOF},
{VKEY_PLAY, DomKey::PLAY},
{VKEY_ZOOM, DomKey::ZOOM_TOGGLE},
- // TODO(chongz): Handle VKEY_NONAME, VKEY_PA1.
+ // TODO(input-dev): Handle VKEY_NONAME, VKEY_PA1.
// https://crbug.com/616910
{VKEY_OEM_CLEAR, DomKey::CLEAR},
};
@@ -268,7 +268,8 @@ struct PlatformKeyMapInstanceTlsTraits
base::ThreadLocalStorage::Slot> {
static base::ThreadLocalStorage::Slot* New(void* instance) {
// Use placement new to initialize our instance in our preallocated space.
- // TODO(chongz): Use std::default_delete instead of providing own function.
+ // TODO(input-dev): Use std::default_delete instead of providing own
+ // function.
return new (instance) base::ThreadLocalStorage::Slot(CleanupKeyMapTls);
}
};
@@ -382,7 +383,7 @@ void PlatformKeyMap::UpdateLayout(HKL layout) {
if (!::GetKeyboardState(keyboard_state_to_restore))
return;
- // TODO(chongz): Optimize layout switching (see crbug.com/587147).
+ // TODO(input-dev): Optimize layout switching (see crbug.com/587147).
keyboard_layout_ = layout;
printable_keycode_to_key_.clear();
has_alt_graph_ = false;
@@ -418,7 +419,7 @@ void PlatformKeyMap::UpdateLayout(HKL layout) {
flags)] =
DomKey::DeadKeyFromCombiningCharacter(translated_chars[0]);
} else {
- // TODO(chongz): Check if this will actually happen.
+ // TODO(input-dev): Check if this will actually happen.
}
} else if (rv == 1) {
if (translated_chars[0] >= 0x20) {
@@ -434,7 +435,7 @@ void PlatformKeyMap::UpdateLayout(HKL layout) {
// Ignores legacy non-printable control characters.
}
} else {
- // TODO(chongz): Handle rv <= -2 and rv >= 2.
+ // TODO(input-dev): Handle rv <= -2 and rv >= 2.
}
}
}
diff --git a/chromium/ui/events/keycodes/platform_key_map_win.h b/chromium/ui/events/keycodes/platform_key_map_win.h
index bf0e19a72a7..2a8dc38b720 100644
--- a/chromium/ui/events/keycodes/platform_key_map_win.h
+++ b/chromium/ui/events/keycodes/platform_key_map_win.h
@@ -44,12 +44,12 @@ class EVENTS_EXPORT PlatformKeyMap {
PlatformKeyMap();
- // TODO(chongz): Expose this function when we need to access separate layout.
- // Returns the DomKey 'meaning' of |KeyboardCode| in the context of specified
- // |EventFlags| and stored keyboard layout.
+ // TODO(input-dev): Expose this function when we need to access separate
+ // layout. Returns the DomKey 'meaning' of |KeyboardCode| in the context of
+ // specified |EventFlags| and stored keyboard layout.
DomKey DomKeyFromKeyboardCodeImpl(KeyboardCode, int* flags) const;
- // TODO(chongz): Expose this function in response to WM_INPUTLANGCHANGE.
+ // TODO(input-dev): Expose this function in response to WM_INPUTLANGCHANGE.
void UpdateLayout(HKL layout);
HKL keyboard_layout_ = 0;
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 f992eefc7cf..da2459ca174 100644
--- a/chromium/ui/events/keycodes/platform_key_map_win_unittest.cc
+++ b/chromium/ui/events/keycodes/platform_key_map_win_unittest.cc
@@ -265,8 +265,8 @@ TEST_F(PlatformKeyMapTest, NonPrintableKey) {
int scan_code =
ui::KeycodeConverter::DomCodeToNativeKeycode(test_case.dom_code);
- // TODO(chongz): Some |scan_code| should map to different |key_code| based
- // on modifiers.
+ // TODO(input-dev): Some |scan_code| should map to different |key_code|
+ // based on modifiers.
KeyboardCode key_code = static_cast<KeyboardCode>(
::MapVirtualKeyEx(scan_code, MAPVK_VSC_TO_VK, layout));
diff --git a/chromium/ui/events/mojo/BUILD.gn b/chromium/ui/events/mojo/BUILD.gn
index 9515ba479c4..a4523c50e25 100644
--- a/chromium/ui/events/mojo/BUILD.gn
+++ b/chromium/ui/events/mojo/BUILD.gn
@@ -13,18 +13,7 @@ mojom("interfaces") {
public_deps = [
"//mojo/public/mojom/base",
- "//ui/gfx/mojo",
+ "//ui/gfx/geometry/mojo",
"//ui/latency/mojo:interfaces",
]
}
-
-mojom("test_interfaces") {
- testonly = true
- sources = [
- "traits_test_service.mojom",
- ]
-
- public_deps = [
- ":interfaces",
- ]
-}
diff --git a/chromium/ui/events/mojo/event.mojom b/chromium/ui/events/mojo/event.mojom
index b68dff4550b..9dafcc23621 100644
--- a/chromium/ui/events/mojo/event.mojom
+++ b/chromium/ui/events/mojo/event.mojom
@@ -7,6 +7,7 @@ module ui.mojom;
import "mojo/public/mojom/base/time.mojom";
import "ui/events/mojo/event_constants.mojom";
import "ui/events/mojo/keyboard_codes.mojom";
+import "ui/gfx/geometry/mojo/geometry.mojom";
import "ui/latency/mojo/latency_info.mojom";
struct KeyData {
@@ -46,23 +47,13 @@ struct KeyData {
// Like |text|, but unmodified by concurrently held modifier keys (except
// shift). Corresponds to blink::WebKeyboardEvent::unmodifiedText.
uint16 unmodified_text;
-
- // Mirrors KeyEvent::properties_.
- map<string, array<uint8>>? properties;
};
struct LocationData {
- // |x| and |y| are in the coordinate system of the View.
- // Typically, this will be an integer-valued translation w.r.t.
- // the screen and in this case, |x| and |y| are in units of physical
- // pixels. However, some View embedders may apply arbitrary transformations
- // of a view w.r.t. the screen.
- float x;
- float y;
- // |screen_x| and |screen_y| are in screen coordinates in units of
- // physical pixels.
- float screen_x;
- float screen_y;
+ // |relative_location| is in the coordinate system of the target and in DIPs.
+ gfx.mojom.PointF relative_location;
+ // |root_location| is relative to the client's root and in dips.
+ gfx.mojom.PointF root_location;
};
// TODO(rjkroege,sadrul): Add gesture representation.
@@ -143,6 +134,37 @@ struct ScrollData {
ScrollEventPhase scroll_event_phase;
};
+// This mirrors the C++ class of the same name, see it for details.
+struct PointerDetails {
+ PointerKind pointer_type;
+ float radius_x;
+ float radius_y;
+ float force;
+ float tilt_x;
+ float tilt_y;
+ float tangential_pressure;
+ float twist;
+ int32 id;
+ int32 offset_x;
+ int32 offset_y;
+};
+
+struct MouseData {
+ int32 changed_button_flags;
+ LocationData location;
+ PointerDetails pointer_details;
+ // Only used for mouse wheel.
+ gfx.mojom.Vector2d wheel_offset;
+};
+
+// This is used for TouchEvents.
+struct TouchData {
+ bool may_cause_scrolling;
+ bool hovering;
+ LocationData location;
+ PointerDetails pointer_details;
+};
+
struct Event {
// TODO(sky): rename to type.
EventType action;
@@ -160,4 +182,7 @@ struct Event {
PointerData? pointer_data;
GestureData? gesture_data;
ScrollData? scroll_data;
+ TouchData? touch_data;
+ MouseData? mouse_data;
+ map<string, array<uint8>>? properties;
};
diff --git a/chromium/ui/events/mojo/event.typemap b/chromium/ui/events/mojo/event.typemap
index d8fe8661fcb..a652049bb12 100644
--- a/chromium/ui/events/mojo/event.typemap
+++ b/chromium/ui/events/mojo/event.typemap
@@ -8,6 +8,7 @@ traits_headers = [ "//ui/events/mojo/event_struct_traits.h" ]
public_deps = [
"//ui/events",
"//ui/events:dom_keycode_converter",
+ "//ui/gfx/geometry/mojo",
"//ui/latency/mojo:interfaces",
]
deps = [
@@ -22,5 +23,6 @@ sources = [
type_mappings = [
"ui.mojom.Event=std::unique_ptr<ui::Event>[move_only]",
"ui.mojom.EventMomentumPhase=ui::EventMomentumPhase",
+ "ui.mojom.PointerDetails=ui::PointerDetails",
"ui.mojom.ScrollEventPhase=ui::ScrollEventPhase",
]
diff --git a/chromium/ui/events/mojo/event_constants.mojom b/chromium/ui/events/mojo/event_constants.mojom
index c7bd18fd4a2..e013bf06a5d 100644
--- a/chromium/ui/events/mojo/event_constants.mojom
+++ b/chromium/ui/events/mojo/event_constants.mojom
@@ -29,6 +29,21 @@ enum EventType {
SCROLL_FLING_START,
SCROLL_FLING_CANCEL,
CANCEL_MODE,
+ // MOUSE_MOVED has a naming conflict in Windows, where there is a
+ // #define MOUSE_MOVED. Therefore we had to add the suffix, _EVENT. for
+ // consistency, all other mouse event types also were given this suffix.
+ MOUSE_PRESSED_EVENT,
+ MOUSE_DRAGGED_EVENT,
+ MOUSE_RELEASED_EVENT,
+ MOUSE_MOVED_EVENT,
+ MOUSE_ENTERED_EVENT,
+ MOUSE_EXITED_EVENT,
+ MOUSE_WHEEL_EVENT,
+ MOUSE_CAPTURE_CHANGED_EVENT,
+ TOUCH_RELEASED,
+ TOUCH_PRESSED,
+ TOUCH_MOVED,
+ TOUCH_CANCELLED,
};
// This mirrors ui::EventFlags
@@ -56,7 +71,9 @@ const int32 kMouseEventFlagIsNonClient = 0x20000;
// TODO(erg): Move accessibility flags and maybe synthetic touch events here.
+// TODO(sky): rename EventPointerType.
enum PointerKind {
+ UNKNOWN,
MOUSE,
PEN,
TOUCH,
diff --git a/chromium/ui/events/mojo/event_struct_traits.cc b/chromium/ui/events/mojo/event_struct_traits.cc
index 054e31bdab3..c5324bbc8f5 100644
--- a/chromium/ui/events/mojo/event_struct_traits.cc
+++ b/chromium/ui/events/mojo/event_struct_traits.cc
@@ -17,36 +17,31 @@ namespace mojo {
namespace {
-ui::mojom::LocationDataPtr GetLocationData(const ui::LocatedEvent* event) {
+ui::mojom::LocationDataPtr CreateLocationData(const ui::LocatedEvent* event) {
ui::mojom::LocationDataPtr location_data(ui::mojom::LocationData::New());
- location_data->x = event->location_f().x();
- location_data->y = event->location_f().y();
- location_data->screen_x = event->root_location_f().x();
- location_data->screen_y = event->root_location_f().y();
+ location_data->relative_location = event->location_f();
+ location_data->root_location = event->root_location_f();
return location_data;
}
-ui::EventPointerType PointerTypeFromPointerKind(ui::mojom::PointerKind kind) {
- switch (kind) {
- case ui::mojom::PointerKind::MOUSE:
- return ui::EventPointerType::POINTER_TYPE_MOUSE;
- case ui::mojom::PointerKind::TOUCH:
- return ui::EventPointerType::POINTER_TYPE_TOUCH;
- case ui::mojom::PointerKind::PEN:
- return ui::EventPointerType::POINTER_TYPE_PEN;
- case ui::mojom::PointerKind::ERASER:
- return ui::EventPointerType::POINTER_TYPE_ERASER;
- }
- NOTREACHED();
- return ui::EventPointerType::POINTER_TYPE_UNKNOWN;
+void UpdateEventLocation(const ui::mojom::PointerData& pointer_data,
+ EventUniquePtr* out) {
+ // Set the float location, as the constructor only takes a gfx::Point.
+ // This uses the event root_location field to store screen pixel
+ // coordinates. See http://crbug.com/608547
+ out->get()->AsLocatedEvent()->set_location_f(
+ pointer_data.location->relative_location);
+ out->get()->AsLocatedEvent()->set_root_location_f(
+ pointer_data.location->root_location);
}
-bool ReadPointerDetails(ui::mojom::EventType event_type,
- const ui::mojom::PointerData& pointer_data,
- ui::PointerDetails* out) {
+bool ReadPointerDetailsDeprecated(ui::mojom::EventType event_type,
+ const ui::mojom::PointerData& pointer_data,
+ ui::PointerDetails* out) {
switch (pointer_data.kind) {
case ui::mojom::PointerKind::MOUSE: {
- if (event_type == ui::mojom::EventType::POINTER_WHEEL_CHANGED) {
+ if (event_type == ui::mojom::EventType::POINTER_WHEEL_CHANGED ||
+ event_type == ui::mojom::EventType::MOUSE_WHEEL_EVENT) {
*out = ui::PointerDetails(
ui::EventPointerType::POINTER_TYPE_MOUSE,
gfx::Vector2d(static_cast<int>(pointer_data.wheel_data->delta_x),
@@ -60,18 +55,23 @@ bool ReadPointerDetails(ui::mojom::EventType event_type,
}
case ui::mojom::PointerKind::TOUCH:
case ui::mojom::PointerKind::PEN: {
+ ui::EventPointerType pointer_type;
+ if (!EnumTraits<ui::mojom::PointerKind, ui::EventPointerType>::FromMojom(
+ pointer_data.kind, &pointer_type))
+ return false;
const ui::mojom::BrushData& brush_data = *pointer_data.brush_data;
*out = ui::PointerDetails(
- PointerTypeFromPointerKind(pointer_data.kind),
- pointer_data.pointer_id, brush_data.width, brush_data.height,
- brush_data.pressure, brush_data.twist, brush_data.tilt_x,
- brush_data.tilt_y, brush_data.tangential_pressure);
+ pointer_type, pointer_data.pointer_id, brush_data.width,
+ brush_data.height, brush_data.pressure, brush_data.twist,
+ brush_data.tilt_x, brush_data.tilt_y, brush_data.tangential_pressure);
return true;
}
case ui::mojom::PointerKind::ERASER:
// TODO(jamescook): Eraser support.
NOTIMPLEMENTED();
return false;
+ case ui::mojom::PointerKind::UNKNOWN:
+ return false;
}
NOTREACHED();
return false;
@@ -86,7 +86,8 @@ bool ReadScrollData(ui::mojom::EventDataView* event,
*out = std::make_unique<ui::ScrollEvent>(
mojo::ConvertTo<ui::EventType>(event->action()),
- gfx::Point(scroll_data->location->x, scroll_data->location->y),
+ gfx::Point(scroll_data->location->relative_location.x(),
+ scroll_data->location->relative_location.y()),
time_stamp, event->flags(), scroll_data->x_offset, scroll_data->y_offset,
scroll_data->x_offset_ordinal, scroll_data->y_offset_ordinal,
scroll_data->finger_count, scroll_data->momentum_phase);
@@ -101,8 +102,8 @@ bool ReadGestureData(ui::mojom::EventDataView* event,
return false;
*out = std::make_unique<ui::GestureEvent>(
- gesture_data->location->x, gesture_data->location->y, event->flags(),
- time_stamp,
+ gesture_data->location->relative_location.x(),
+ gesture_data->location->relative_location.y(), event->flags(), time_stamp,
ui::GestureEventDetails(ConvertTo<ui::EventType>(event->action())));
return true;
}
@@ -193,6 +194,30 @@ ui::mojom::EventType TypeConverter<ui::mojom::EventType,
return ui::mojom::EventType::SCROLL_FLING_CANCEL;
case ui::ET_CANCEL_MODE:
return ui::mojom::EventType::CANCEL_MODE;
+ case ui::ET_MOUSE_PRESSED:
+ return ui::mojom::EventType::MOUSE_PRESSED_EVENT;
+ case ui::ET_MOUSE_DRAGGED:
+ return ui::mojom::EventType::MOUSE_DRAGGED_EVENT;
+ case ui::ET_MOUSE_RELEASED:
+ return ui::mojom::EventType::MOUSE_RELEASED_EVENT;
+ case ui::ET_MOUSE_MOVED:
+ return ui::mojom::EventType::MOUSE_MOVED_EVENT;
+ case ui::ET_MOUSE_ENTERED:
+ return ui::mojom::EventType::MOUSE_ENTERED_EVENT;
+ case ui::ET_MOUSE_EXITED:
+ return ui::mojom::EventType::MOUSE_EXITED_EVENT;
+ case ui::ET_MOUSEWHEEL:
+ return ui::mojom::EventType::MOUSE_WHEEL_EVENT;
+ case ui::ET_MOUSE_CAPTURE_CHANGED:
+ return ui::mojom::EventType::MOUSE_CAPTURE_CHANGED_EVENT;
+ case ui::ET_TOUCH_RELEASED:
+ return ui::mojom::EventType::TOUCH_RELEASED;
+ case ui::ET_TOUCH_PRESSED:
+ return ui::mojom::EventType::TOUCH_PRESSED;
+ case ui::ET_TOUCH_MOVED:
+ return ui::mojom::EventType::TOUCH_MOVED;
+ case ui::ET_TOUCH_CANCELLED:
+ return ui::mojom::EventType::TOUCH_CANCELLED;
default:
NOTREACHED() << "Using unknown event types closes connections:"
<< ui::EventTypeName(type);
@@ -235,35 +260,64 @@ ui::EventType TypeConverter<ui::EventType, ui::mojom::EventType>::Convert(
return ui::ET_SCROLL_FLING_START;
case ui::mojom::EventType::SCROLL_FLING_CANCEL:
return ui::ET_SCROLL_FLING_CANCEL;
+ case ui::mojom::EventType::MOUSE_PRESSED_EVENT:
+ return ui::ET_MOUSE_PRESSED;
+ case ui::mojom::EventType::MOUSE_DRAGGED_EVENT:
+ return ui::ET_MOUSE_DRAGGED;
+ case ui::mojom::EventType::MOUSE_RELEASED_EVENT:
+ return ui::ET_MOUSE_RELEASED;
+ case ui::mojom::EventType::MOUSE_MOVED_EVENT:
+ return ui::ET_MOUSE_MOVED;
+ case ui::mojom::EventType::MOUSE_ENTERED_EVENT:
+ return ui::ET_MOUSE_ENTERED;
+ case ui::mojom::EventType::MOUSE_EXITED_EVENT:
+ return ui::ET_MOUSE_EXITED;
+ case ui::mojom::EventType::MOUSE_WHEEL_EVENT:
+ return ui::ET_MOUSEWHEEL;
+ case ui::mojom::EventType::MOUSE_CAPTURE_CHANGED_EVENT:
+ return ui::ET_MOUSE_CAPTURE_CHANGED;
+ case ui::mojom::EventType::TOUCH_RELEASED:
+ return ui::ET_TOUCH_RELEASED;
+ case ui::mojom::EventType::TOUCH_PRESSED:
+ return ui::ET_TOUCH_PRESSED;
+ case ui::mojom::EventType::TOUCH_MOVED:
+ return ui::ET_TOUCH_MOVED;
+ case ui::mojom::EventType::TOUCH_CANCELLED:
+ return ui::ET_TOUCH_CANCELLED;
default:
NOTREACHED();
}
return ui::ET_UNKNOWN;
}
+// static
ui::mojom::EventType
StructTraits<ui::mojom::EventDataView, EventUniquePtr>::action(
const EventUniquePtr& event) {
return mojo::ConvertTo<ui::mojom::EventType>(event->type());
}
+// static
int32_t StructTraits<ui::mojom::EventDataView, EventUniquePtr>::flags(
const EventUniquePtr& event) {
return event->flags();
}
+// static
base::TimeTicks
StructTraits<ui::mojom::EventDataView, EventUniquePtr>::time_stamp(
const EventUniquePtr& event) {
return event->time_stamp();
}
+// static
const ui::LatencyInfo&
StructTraits<ui::mojom::EventDataView, EventUniquePtr>::latency(
const EventUniquePtr& event) {
return *event->latency();
}
+// static
ui::mojom::KeyDataPtr
StructTraits<ui::mojom::EventDataView, EventUniquePtr>::key_data(
const EventUniquePtr& event) {
@@ -281,23 +335,22 @@ StructTraits<ui::mojom::EventDataView, EventUniquePtr>::key_data(
key_event->GetLocatedWindowsKeyboardCode());
key_data->text = key_event->GetText();
key_data->unmodified_text = key_event->GetUnmodifiedText();
- if (key_event->properties())
- key_data->properties = *(key_event->properties());
-
return key_data;
}
+// static
ui::mojom::PointerDataPtr
StructTraits<ui::mojom::EventDataView, EventUniquePtr>::pointer_data(
const EventUniquePtr& event) {
if (!event->IsPointerEvent())
return nullptr;
- const ui::PointerEvent* pointer_event = event->AsPointerEvent();
ui::mojom::PointerDataPtr pointer_data(ui::mojom::PointerData::New());
- pointer_data->pointer_id = pointer_event->pointer_details().id;
- pointer_data->changed_button_flags = pointer_event->changed_button_flags();
+ const ui::PointerEvent* pointer_event = event->AsPointerEvent();
const ui::PointerDetails* pointer_details = &pointer_event->pointer_details();
+ pointer_data->changed_button_flags = pointer_event->changed_button_flags();
+ pointer_data->location = CreateLocationData(event->AsLocatedEvent());
+ pointer_data->pointer_id = pointer_details->id;
ui::EventPointerType pointer_type = pointer_details->pointer_type;
switch (pointer_type) {
@@ -335,8 +388,6 @@ StructTraits<ui::mojom::EventDataView, EventUniquePtr>::pointer_data(
// TODO(rjkroege): Handle force-touch on MacOS
// TODO(rjkroege): Adjust brush data appropriately for Android.
- pointer_data->location = GetLocationData(event->AsLocatedEvent());
-
if (event->type() == ui::ET_POINTER_WHEEL_CHANGED) {
ui::mojom::WheelDataPtr wheel_data(ui::mojom::WheelData::New());
@@ -362,6 +413,24 @@ StructTraits<ui::mojom::EventDataView, EventUniquePtr>::pointer_data(
return pointer_data;
}
+// static
+ui::mojom::MouseDataPtr
+StructTraits<ui::mojom::EventDataView, EventUniquePtr>::mouse_data(
+ const EventUniquePtr& event) {
+ if (!event->IsMouseEvent())
+ return nullptr;
+
+ const ui::MouseEvent* mouse_event = event->AsMouseEvent();
+ ui::mojom::MouseDataPtr mouse_data(ui::mojom::MouseData::New());
+ mouse_data->changed_button_flags = mouse_event->changed_button_flags();
+ mouse_data->pointer_details = mouse_event->pointer_details();
+ mouse_data->location = CreateLocationData(mouse_event);
+ if (mouse_event->IsMouseWheelEvent())
+ mouse_data->wheel_offset = mouse_event->AsMouseWheelEvent()->offset();
+ return mouse_data;
+}
+
+// static
ui::mojom::GestureDataPtr
StructTraits<ui::mojom::EventDataView, EventUniquePtr>::gesture_data(
const EventUniquePtr& event) {
@@ -369,10 +438,11 @@ StructTraits<ui::mojom::EventDataView, EventUniquePtr>::gesture_data(
return nullptr;
ui::mojom::GestureDataPtr gesture_data(ui::mojom::GestureData::New());
- gesture_data->location = GetLocationData(event->AsLocatedEvent());
+ gesture_data->location = CreateLocationData(event->AsLocatedEvent());
return gesture_data;
}
+// static
ui::mojom::ScrollDataPtr
StructTraits<ui::mojom::EventDataView, EventUniquePtr>::scroll_data(
const EventUniquePtr& event) {
@@ -380,7 +450,7 @@ StructTraits<ui::mojom::EventDataView, EventUniquePtr>::scroll_data(
return nullptr;
ui::mojom::ScrollDataPtr scroll_data(ui::mojom::ScrollData::New());
- scroll_data->location = GetLocationData(event->AsLocatedEvent());
+ scroll_data->location = CreateLocationData(event->AsLocatedEvent());
const ui::ScrollEvent* scroll_event = event->AsScrollEvent();
scroll_data->x_offset = scroll_event->x_offset();
scroll_data->y_offset = scroll_event->y_offset();
@@ -391,6 +461,30 @@ StructTraits<ui::mojom::EventDataView, EventUniquePtr>::scroll_data(
return scroll_data;
}
+// static
+ui::mojom::TouchDataPtr
+StructTraits<ui::mojom::EventDataView, EventUniquePtr>::touch_data(
+ const EventUniquePtr& event) {
+ if (!event->IsTouchEvent())
+ return nullptr;
+
+ const ui::TouchEvent* touch_event = event->AsTouchEvent();
+ ui::mojom::TouchDataPtr touch_data(ui::mojom::TouchData::New());
+ touch_data->may_cause_scrolling = touch_event->may_cause_scrolling();
+ touch_data->hovering = touch_event->hovering();
+ touch_data->location = CreateLocationData(touch_event);
+ touch_data->pointer_details = touch_event->pointer_details();
+ return touch_data;
+}
+
+// static
+base::flat_map<std::string, std::vector<uint8_t>>
+StructTraits<ui::mojom::EventDataView, EventUniquePtr>::properties(
+ const EventUniquePtr& event) {
+ return event->properties() ? *(event->properties()) : ui::Event::Properties();
+}
+
+// static
bool StructTraits<ui::mojom::EventDataView, EventUniquePtr>::Read(
ui::mojom::EventDataView event,
EventUniquePtr* out) {
@@ -420,8 +514,6 @@ bool StructTraits<ui::mojom::EventDataView, EventUniquePtr>::Read(
static_cast<ui::KeyboardCode>(key_data->key_code), event.flags(),
time_stamp);
}
- if (key_data->properties)
- (*out)->AsKeyEvent()->SetProperties(*key_data->properties);
break;
}
case ui::mojom::EventType::POINTER_DOWN:
@@ -437,19 +529,16 @@ bool StructTraits<ui::mojom::EventDataView, EventUniquePtr>::Read(
return false;
ui::PointerDetails pointer_details;
- if (!ReadPointerDetails(event.action(), *pointer_data, &pointer_details))
+ if (!ReadPointerDetailsDeprecated(event.action(), *pointer_data,
+ &pointer_details))
return false;
- const gfx::Point location(pointer_data->location->x,
- pointer_data->location->y);
- const gfx::Point screen_location(pointer_data->location->screen_x,
- pointer_data->location->screen_y);
- // This uses the event root_location field to store screen pixel
- // coordinates. See http://crbug.com/608547
*out = std::make_unique<ui::PointerEvent>(
- mojo::ConvertTo<ui::EventType>(event.action()), location,
- screen_location, event.flags(), pointer_data->changed_button_flags,
+ mojo::ConvertTo<ui::EventType>(event.action()), gfx::Point(),
+ gfx::Point(), event.flags(), pointer_data->changed_button_flags,
pointer_details, time_stamp);
+
+ UpdateEventLocation(*pointer_data, out);
break;
}
case ui::mojom::EventType::GESTURE_TAP:
@@ -474,6 +563,57 @@ bool StructTraits<ui::mojom::EventDataView, EventUniquePtr>::Read(
case ui::mojom::EventType::CANCEL_MODE:
*out = std::make_unique<ui::CancelModeEvent>();
break;
+ case ui::mojom::EventType::MOUSE_PRESSED_EVENT:
+ case ui::mojom::EventType::MOUSE_RELEASED_EVENT:
+ case ui::mojom::EventType::MOUSE_DRAGGED_EVENT:
+ case ui::mojom::EventType::MOUSE_MOVED_EVENT:
+ case ui::mojom::EventType::MOUSE_ENTERED_EVENT:
+ case ui::mojom::EventType::MOUSE_EXITED_EVENT:
+ case ui::mojom::EventType::MOUSE_WHEEL_EVENT:
+ case ui::mojom::EventType::MOUSE_CAPTURE_CHANGED_EVENT: {
+ ui::mojom::MouseDataPtr mouse_data;
+ if (!event.ReadMouseData(&mouse_data))
+ return false;
+
+ std::unique_ptr<ui::MouseEvent> mouse_event;
+ if (event.action() == ui::mojom::EventType::MOUSE_WHEEL_EVENT) {
+ mouse_event = std::make_unique<ui::MouseWheelEvent>(
+ mouse_data->wheel_offset,
+ gfx::Point(), // Real location set below.
+ gfx::Point(), // Real location set below.
+ time_stamp, event.flags(), mouse_data->changed_button_flags);
+ } else {
+ mouse_event = std::make_unique<ui::MouseEvent>(
+ mojo::ConvertTo<ui::EventType>(event.action()),
+ gfx::Point(), // Real location set below.
+ gfx::Point(), // Real location set below.
+ time_stamp, event.flags(), mouse_data->changed_button_flags,
+ mouse_data->pointer_details);
+ }
+ mouse_event->set_location_f(mouse_data->location->relative_location);
+ mouse_event->set_root_location_f(mouse_data->location->root_location);
+ *out = std::move(mouse_event);
+ break;
+ }
+ case ui::mojom::EventType::TOUCH_RELEASED:
+ case ui::mojom::EventType::TOUCH_PRESSED:
+ case ui::mojom::EventType::TOUCH_MOVED:
+ case ui::mojom::EventType::TOUCH_CANCELLED: {
+ ui::mojom::TouchDataPtr touch_data;
+ if (!event.ReadTouchData(&touch_data))
+ return false;
+ std::unique_ptr<ui::TouchEvent> touch_event =
+ std::make_unique<ui::TouchEvent>(
+ mojo::ConvertTo<ui::EventType>(event.action()),
+ gfx::Point(), // Real location set below.
+ time_stamp, touch_data->pointer_details, event.flags());
+ touch_event->set_location_f(touch_data->location->relative_location);
+ touch_event->set_root_location_f(touch_data->location->root_location);
+ touch_event->set_may_cause_scrolling(touch_data->may_cause_scrolling);
+ touch_event->set_hovering(touch_data->hovering);
+ *out = std::move(touch_event);
+ break;
+ }
case ui::mojom::EventType::UNKNOWN:
NOTREACHED() << "Using unknown event types closes connections";
return false;
@@ -482,7 +622,35 @@ bool StructTraits<ui::mojom::EventDataView, EventUniquePtr>::Read(
if (!out->get())
return false;
- return event.ReadLatency((*out)->latency());
+ if (!event.ReadLatency((*out)->latency()))
+ return false;
+
+ ui::Event::Properties properties;
+ if (!event.ReadProperties(&properties))
+ return false;
+ if (!properties.empty())
+ (*out)->SetProperties(properties);
+
+ return true;
+}
+
+// static
+bool StructTraits<ui::mojom::PointerDetailsDataView, ui::PointerDetails>::Read(
+ ui::mojom::PointerDetailsDataView data,
+ ui::PointerDetails* out) {
+ if (!data.ReadPointerType(&out->pointer_type))
+ return false;
+ out->radius_x = data.radius_x();
+ out->radius_y = data.radius_y();
+ out->force = data.force();
+ out->tilt_x = data.tilt_x();
+ out->tilt_y = data.tilt_y();
+ out->tangential_pressure = data.tangential_pressure();
+ out->twist = data.twist();
+ out->id = data.id();
+ out->offset.set_x(data.offset_x());
+ out->offset.set_y(data.offset_y());
+ return true;
}
} // namespace mojo
diff --git a/chromium/ui/events/mojo/event_struct_traits.h b/chromium/ui/events/mojo/event_struct_traits.h
index 68b5680775d..1e5d3fb1bbb 100644
--- a/chromium/ui/events/mojo/event_struct_traits.h
+++ b/chromium/ui/events/mojo/event_struct_traits.h
@@ -5,6 +5,11 @@
#ifndef UI_EVENTS_MOJO_EVENT_STRUCT_TRAITS_H_
#define UI_EVENTS_MOJO_EVENT_STRUCT_TRAITS_H_
+#include <stdint.h>
+
+#include <string>
+
+#include "base/containers/flat_map.h"
#include "mojo/public/cpp/bindings/type_converter.h"
#include "ui/events/event_constants.h"
#include "ui/events/mojo/event.mojom.h"
@@ -13,6 +18,7 @@
namespace ui {
class Event;
class LatencyInfo;
+struct PointerDetails;
}
namespace mojo {
@@ -39,6 +45,10 @@ struct StructTraits<ui::mojom::EventDataView, EventUniquePtr> {
static ui::mojom::PointerDataPtr pointer_data(const EventUniquePtr& event);
static ui::mojom::GestureDataPtr gesture_data(const EventUniquePtr& event);
static ui::mojom::ScrollDataPtr scroll_data(const EventUniquePtr& event);
+ static ui::mojom::TouchDataPtr touch_data(const EventUniquePtr& event);
+ static ui::mojom::MouseDataPtr mouse_data(const EventUniquePtr& event);
+ static base::flat_map<std::string, std::vector<uint8_t>> properties(
+ const EventUniquePtr& event);
static bool Read(ui::mojom::EventDataView r, EventUniquePtr* out);
};
@@ -86,6 +96,71 @@ struct EnumTraits<ui::mojom::EventMomentumPhase, ui::EventMomentumPhase> {
};
template <>
+struct EnumTraits<ui::mojom::PointerKind, ui::EventPointerType> {
+ static ui::mojom::PointerKind ToMojom(ui::EventPointerType input) {
+ switch (input) {
+ case ui::EventPointerType::POINTER_TYPE_UNKNOWN:
+ return ui::mojom::PointerKind::UNKNOWN;
+ case ui::EventPointerType::POINTER_TYPE_MOUSE:
+ return ui::mojom::PointerKind::MOUSE;
+ case ui::EventPointerType::POINTER_TYPE_PEN:
+ return ui::mojom::PointerKind::PEN;
+ case ui::EventPointerType::POINTER_TYPE_TOUCH:
+ return ui::mojom::PointerKind::TOUCH;
+ case ui::EventPointerType::POINTER_TYPE_ERASER:
+ return ui::mojom::PointerKind::ERASER;
+ }
+ NOTREACHED();
+ return ui::mojom::PointerKind::UNKNOWN;
+ }
+
+ static bool FromMojom(ui::mojom::PointerKind input,
+ ui::EventPointerType* out) {
+ switch (input) {
+ case ui::mojom::PointerKind::UNKNOWN:
+ *out = ui::EventPointerType::POINTER_TYPE_UNKNOWN;
+ return true;
+ case ui::mojom::PointerKind::MOUSE:
+ *out = ui::EventPointerType::POINTER_TYPE_MOUSE;
+ return true;
+ case ui::mojom::PointerKind::PEN:
+ *out = ui::EventPointerType::POINTER_TYPE_PEN;
+ return true;
+ case ui::mojom::PointerKind::TOUCH:
+ *out = ui::EventPointerType::POINTER_TYPE_TOUCH;
+ return true;
+ case ui::mojom::PointerKind::ERASER:
+ *out = ui::EventPointerType::POINTER_TYPE_ERASER;
+ return true;
+ }
+ NOTREACHED();
+ return false;
+ }
+};
+
+template <>
+struct StructTraits<ui::mojom::PointerDetailsDataView, ui::PointerDetails> {
+ static ui::EventPointerType pointer_type(const ui::PointerDetails& i) {
+ return i.pointer_type;
+ }
+ static float radius_x(const ui::PointerDetails& i) { return i.radius_x; }
+ static float radius_y(const ui::PointerDetails& i) { return i.radius_y; }
+ static float force(const ui::PointerDetails& i) { return i.force; }
+ static float tilt_x(const ui::PointerDetails& i) { return i.tilt_x; }
+ static float tilt_y(const ui::PointerDetails& i) { return i.tilt_y; }
+ static float tangential_pressure(const ui::PointerDetails& i) {
+ return i.tangential_pressure;
+ }
+ static float twist(const ui::PointerDetails& i) { return i.twist; }
+ static int32_t id(const ui::PointerDetails& i) { return i.id; }
+ static int32_t offset_x(const ui::PointerDetails& i) { return i.offset.x(); }
+ static int32_t offset_y(const ui::PointerDetails& i) { return i.offset.y(); }
+
+ static bool Read(ui::mojom::PointerDetailsDataView data,
+ ui::PointerDetails* out);
+};
+
+template <>
struct EnumTraits<ui::mojom::ScrollEventPhase, ui::ScrollEventPhase> {
static ui::mojom::ScrollEventPhase ToMojom(ui::ScrollEventPhase input) {
switch (input) {
diff --git a/chromium/ui/events/mojo/struct_traits_unittest.cc b/chromium/ui/events/mojo/struct_traits_unittest.cc
index 1a7bdbb8a85..2c4d62b7b32 100644
--- a/chromium/ui/events/mojo/struct_traits_unittest.cc
+++ b/chromium/ui/events/mojo/struct_traits_unittest.cc
@@ -4,74 +4,97 @@
#include <utility>
-#include "base/message_loop/message_loop.h"
+#include "base/stl_util.h"
#include "mojo/public/cpp/base/time_mojom_traits.h"
-#include "mojo/public/cpp/bindings/binding_set.h"
+#include "mojo/public/cpp/test_support/test_utils.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/mojo/event.mojom.h"
#include "ui/events/mojo/event_struct_traits.h"
-#include "ui/events/mojo/traits_test_service.mojom.h"
+#include "ui/gfx/geometry/mojo/geometry_struct_traits.h"
#include "ui/latency/mojo/latency_info_struct_traits.h"
namespace ui {
namespace {
-class StructTraitsTest : public testing::Test, public mojom::TraitsTestService {
- public:
- StructTraitsTest() {}
- ~StructTraitsTest() override = default;
+void ExpectTouchEventsEqual(const TouchEvent& expected,
+ const TouchEvent& actual) {
+ EXPECT_EQ(expected.may_cause_scrolling(), actual.may_cause_scrolling());
+ EXPECT_EQ(expected.hovering(), actual.hovering());
+ EXPECT_EQ(expected.pointer_details(), actual.pointer_details());
+}
- protected:
- mojom::TraitsTestServicePtr GetTraitsTestProxy() {
- mojom::TraitsTestServicePtr proxy;
- traits_test_bindings_.AddBinding(this, mojo::MakeRequest(&proxy));
- return proxy;
- }
+void ExpectLocatedEventsEqual(const LocatedEvent& expected,
+ const LocatedEvent& actual) {
+ EXPECT_EQ(expected.location_f(), actual.location_f());
+ EXPECT_EQ(expected.root_location_f(), actual.root_location_f());
+}
- private:
- // TraitsTestService:
- void EchoEvent(std::unique_ptr<ui::Event> e,
- EchoEventCallback callback) override {
- std::move(callback).Run(std::move(e));
- }
+void ExpectMouseEventsEqual(const MouseEvent& expected,
+ const MouseEvent& actual) {
+ EXPECT_EQ(expected.pointer_details(), actual.pointer_details());
+ EXPECT_EQ(expected.changed_button_flags(), actual.changed_button_flags());
+}
- base::MessageLoop loop_;
- mojo::BindingSet<TraitsTestService> traits_test_bindings_;
- DISALLOW_COPY_AND_ASSIGN(StructTraitsTest);
-};
+void ExpectMouseWheelEventsEqual(const MouseWheelEvent& expected,
+ const MouseWheelEvent& actual) {
+ EXPECT_EQ(expected.offset(), actual.offset());
+}
+
+void ExpectEventsEqual(const Event& expected, const Event& actual) {
+ EXPECT_EQ(expected.type(), actual.type());
+ EXPECT_EQ(expected.time_stamp(), actual.time_stamp());
+ EXPECT_EQ(expected.flags(), actual.flags());
+ if (expected.IsLocatedEvent()) {
+ ASSERT_TRUE(actual.IsLocatedEvent());
+ ExpectLocatedEventsEqual(*expected.AsLocatedEvent(),
+ *actual.AsLocatedEvent());
+ }
+ if (expected.IsMouseEvent()) {
+ ASSERT_TRUE(actual.IsMouseEvent());
+ ExpectMouseEventsEqual(*expected.AsMouseEvent(), *actual.AsMouseEvent());
+ }
+ if (expected.IsMouseWheelEvent()) {
+ ASSERT_TRUE(actual.IsMouseWheelEvent());
+ ExpectMouseWheelEventsEqual(*expected.AsMouseWheelEvent(),
+ *actual.AsMouseWheelEvent());
+ }
+ if (expected.IsTouchEvent()) {
+ ASSERT_TRUE(actual.IsTouchEvent());
+ ExpectTouchEventsEqual(*expected.AsTouchEvent(), *actual.AsTouchEvent());
+ }
+}
} // namespace
-TEST_F(StructTraitsTest, KeyEvent) {
- KeyEvent kTestData[] = {
+TEST(StructTraitsTest, KeyEvent) {
+ const KeyEvent kTestData[] = {
{ET_KEY_PRESSED, VKEY_RETURN, EF_CONTROL_DOWN},
{ET_KEY_PRESSED, VKEY_MENU, EF_ALT_DOWN},
{ET_KEY_RELEASED, VKEY_SHIFT, EF_SHIFT_DOWN},
{ET_KEY_RELEASED, VKEY_MENU, EF_ALT_DOWN},
- {ET_KEY_PRESSED, VKEY_A, ui::DomCode::US_A, EF_NONE},
- {ET_KEY_PRESSED, VKEY_B, ui::DomCode::US_B,
- EF_CONTROL_DOWN | EF_ALT_DOWN},
- {'\x12', VKEY_2, ui::DomCode::NONE, EF_CONTROL_DOWN},
- {'Z', VKEY_Z, ui::DomCode::NONE, EF_CAPS_LOCK_ON},
- {'z', VKEY_Z, ui::DomCode::NONE, EF_NONE},
+ {ET_KEY_PRESSED, VKEY_A, DomCode::US_A, EF_NONE},
+ {ET_KEY_PRESSED, VKEY_B, DomCode::US_B, EF_CONTROL_DOWN | EF_ALT_DOWN},
+ {'\x12', VKEY_2, DomCode::NONE, EF_CONTROL_DOWN},
+ {'Z', VKEY_Z, DomCode::NONE, EF_CAPS_LOCK_ON},
+ {'z', VKEY_Z, DomCode::NONE, EF_NONE},
{ET_KEY_PRESSED, VKEY_Z, EF_NONE,
base::TimeTicks() + base::TimeDelta::FromMicroseconds(101)},
- {'Z', VKEY_Z, ui::DomCode::NONE, EF_NONE,
+ {'Z', VKEY_Z, DomCode::NONE, EF_NONE,
base::TimeTicks() + base::TimeDelta::FromMicroseconds(102)},
};
- mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy();
- for (size_t i = 0; i < arraysize(kTestData); i++) {
+ for (size_t i = 0; i < base::size(kTestData); i++) {
+ std::unique_ptr<Event> expected_copy = Event::Clone(kTestData[i]);
std::unique_ptr<Event> output;
- proxy->EchoEvent(Event::Clone(kTestData[i]), &output);
+ ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Event>(
+ &expected_copy, &output));
EXPECT_TRUE(output->IsKeyEvent());
const KeyEvent* output_key_event = output->AsKeyEvent();
- EXPECT_EQ(kTestData[i].type(), output_key_event->type());
- EXPECT_EQ(kTestData[i].flags(), output_key_event->flags());
+ ExpectEventsEqual(kTestData[i], *output_key_event);
EXPECT_EQ(kTestData[i].GetCharacter(), output_key_event->GetCharacter());
EXPECT_EQ(kTestData[i].GetUnmodifiedText(),
output_key_event->GetUnmodifiedText());
@@ -81,12 +104,11 @@ TEST_F(StructTraitsTest, KeyEvent) {
EXPECT_EQ(kTestData[i].GetConflatedWindowsKeyCode(),
output_key_event->GetConflatedWindowsKeyCode());
EXPECT_EQ(kTestData[i].code(), output_key_event->code());
- EXPECT_EQ(kTestData[i].time_stamp(), output_key_event->time_stamp());
}
}
-TEST_F(StructTraitsTest, PointerEvent) {
- PointerEvent kTestData[] = {
+TEST(StructTraitsTest, PointerEvent) {
+ const PointerEvent kTestData[] = {
// Mouse pointer events:
{ET_POINTER_DOWN, gfx::Point(10, 10), gfx::Point(20, 30), EF_NONE, 0,
PointerDetails(EventPointerType::POINTER_TYPE_MOUSE,
@@ -168,10 +190,11 @@ TEST_F(StructTraitsTest, PointerEvent) {
base::TimeTicks() + base::TimeDelta::FromMicroseconds(211)},
};
- mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy();
- for (size_t i = 0; i < arraysize(kTestData); i++) {
+ for (size_t i = 0; i < base::size(kTestData); i++) {
+ std::unique_ptr<Event> expected_copy = Event::Clone(kTestData[i]);
std::unique_ptr<Event> output;
- proxy->EchoEvent(Event::Clone(kTestData[i]), &output);
+ ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Event>(
+ &expected_copy, &output));
EXPECT_TRUE(output->IsPointerEvent());
const PointerEvent* output_ptr_event = output->AsPointerEvent();
@@ -189,8 +212,56 @@ TEST_F(StructTraitsTest, PointerEvent) {
}
}
-TEST_F(StructTraitsTest, PointerWheelEvent) {
- MouseWheelEvent kTestData[] = {
+TEST(StructTraitsTest, MouseEvent) {
+ const MouseEvent kTestData[] = {
+ {ET_MOUSE_PRESSED, gfx::Point(10, 10), gfx::Point(20, 30),
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(201), EF_NONE, 0,
+ PointerDetails(EventPointerType::POINTER_TYPE_MOUSE,
+ MouseEvent::kMousePointerId)},
+ {ET_MOUSE_DRAGGED, gfx::Point(1, 5), gfx::Point(5, 1),
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(202),
+ EF_LEFT_MOUSE_BUTTON, EF_LEFT_MOUSE_BUTTON,
+ PointerDetails(EventPointerType::POINTER_TYPE_MOUSE,
+ MouseEvent::kMousePointerId)},
+ {ET_MOUSE_RELEASED, gfx::Point(411, 130), gfx::Point(20, 30),
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(203),
+ EF_MIDDLE_MOUSE_BUTTON | EF_RIGHT_MOUSE_BUTTON, EF_RIGHT_MOUSE_BUTTON,
+ PointerDetails(EventPointerType::POINTER_TYPE_MOUSE,
+ MouseEvent::kMousePointerId)},
+ {ET_MOUSE_MOVED, gfx::Point(0, 1), gfx::Point(2, 3),
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(204), EF_ALT_DOWN,
+ 0,
+ PointerDetails(EventPointerType::POINTER_TYPE_MOUSE,
+ MouseEvent::kMousePointerId)},
+ {ET_MOUSE_ENTERED, gfx::Point(6, 7), gfx::Point(8, 9),
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(205), EF_NONE, 0,
+ PointerDetails(EventPointerType::POINTER_TYPE_MOUSE,
+ MouseEvent::kMousePointerId)},
+ {ET_MOUSE_EXITED, gfx::Point(10, 10), gfx::Point(20, 30),
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(206),
+ EF_BACK_MOUSE_BUTTON, 0,
+ PointerDetails(EventPointerType::POINTER_TYPE_MOUSE,
+ MouseEvent::kMousePointerId)},
+ {ET_MOUSE_CAPTURE_CHANGED, gfx::Point(99, 99), gfx::Point(99, 99),
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(207),
+ EF_CONTROL_DOWN, 0,
+ PointerDetails(EventPointerType::POINTER_TYPE_MOUSE,
+ MouseEvent::kMousePointerId)},
+ };
+
+ for (size_t i = 0; i < base::size(kTestData); i++) {
+ std::unique_ptr<Event> expected_copy = Event::Clone(kTestData[i]);
+ std::unique_ptr<Event> output;
+ ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Event>(
+ &expected_copy, &output));
+ ASSERT_TRUE(output->IsMouseEvent());
+
+ ExpectEventsEqual(kTestData[i], *output);
+ }
+}
+
+TEST(StructTraitsTest, PointerWheelEvent) {
+ const MouseWheelEvent kTestData[] = {
{gfx::Vector2d(11, 15), gfx::Point(3, 4), gfx::Point(40, 30),
base::TimeTicks() + base::TimeDelta::FromMicroseconds(301),
EF_LEFT_MOUSE_BUTTON, EF_LEFT_MOUSE_BUTTON},
@@ -203,10 +274,12 @@ TEST_F(StructTraitsTest, PointerWheelEvent) {
EF_NONE},
};
- mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy();
- for (size_t i = 0; i < arraysize(kTestData); i++) {
+ for (size_t i = 0; i < base::size(kTestData); i++) {
+ std::unique_ptr<Event> expected_copy =
+ std::make_unique<PointerEvent>(kTestData[i]);
std::unique_ptr<Event> output;
- proxy->EchoEvent(Event::Clone(ui::PointerEvent(kTestData[i])), &output);
+ ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Event>(
+ &expected_copy, &output));
EXPECT_EQ(ET_POINTER_WHEEL_CHANGED, output->type());
const PointerEvent* output_pointer_event = output->AsPointerEvent();
@@ -221,7 +294,54 @@ TEST_F(StructTraitsTest, PointerWheelEvent) {
}
}
-TEST_F(StructTraitsTest, KeyEventPropertiesSerialized) {
+TEST(StructTraitsTest, MouseWheelEvent) {
+ const MouseWheelEvent kTestData[] = {
+ {gfx::Vector2d(11, 15), gfx::Point(3, 4), gfx::Point(40, 30),
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(301),
+ EF_LEFT_MOUSE_BUTTON, EF_LEFT_MOUSE_BUTTON},
+ {gfx::Vector2d(-5, 3), gfx::Point(40, 3), gfx::Point(4, 0),
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(302),
+ EF_MIDDLE_MOUSE_BUTTON | EF_RIGHT_MOUSE_BUTTON,
+ EF_MIDDLE_MOUSE_BUTTON | EF_RIGHT_MOUSE_BUTTON},
+ {gfx::Vector2d(1, 0), gfx::Point(3, 4), gfx::Point(40, 30),
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(303), EF_NONE,
+ EF_NONE},
+ };
+
+ for (size_t i = 0; i < base::size(kTestData); i++) {
+ std::unique_ptr<Event> expected_copy =
+ std::make_unique<MouseWheelEvent>(PointerEvent(kTestData[i]));
+ std::unique_ptr<Event> output;
+ ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Event>(
+ &expected_copy, &output));
+ ASSERT_EQ(ET_MOUSEWHEEL, output->type());
+
+ const MouseWheelEvent* output_event = output->AsMouseWheelEvent();
+ // TODO(sky): make this use ExpectEventsEqual().
+ ExpectMouseWheelEventsEqual(kTestData[i], *output_event);
+ }
+}
+
+TEST(StructTraitsTest, FloatingPointLocations) {
+ MouseEvent input_event(
+ ET_MOUSE_PRESSED, gfx::Point(10, 10), gfx::Point(20, 30),
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(201), EF_NONE, 0,
+ PointerDetails(EventPointerType::POINTER_TYPE_MOUSE,
+ MouseEvent::kMousePointerId));
+
+ input_event.set_location_f(gfx::PointF(10.1, 10.2));
+ input_event.set_root_location_f(gfx::PointF(20.2, 30.3));
+
+ std::unique_ptr<Event> expected_copy = Event::Clone(input_event);
+ std::unique_ptr<Event> output;
+ ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Event>(&expected_copy,
+ &output));
+ ASSERT_TRUE(output->IsMouseEvent());
+
+ ExpectEventsEqual(input_event, *output->AsMouseEvent());
+}
+
+TEST(StructTraitsTest, KeyEventPropertiesSerialized) {
KeyEvent key_event(ET_KEY_PRESSED, VKEY_T, EF_NONE);
const std::string key = "key";
const std::vector<uint8_t> value(0xCD, 2);
@@ -238,8 +358,8 @@ TEST_F(StructTraitsTest, KeyEventPropertiesSerialized) {
EXPECT_EQ(properties, *(deserialized->AsKeyEvent()->properties()));
}
-TEST_F(StructTraitsTest, GestureEvent) {
- GestureEvent kTestData[] = {
+TEST(StructTraitsTest, GestureEvent) {
+ const GestureEvent kTestData[] = {
{10, 20, EF_NONE,
base::TimeTicks() + base::TimeDelta::FromMicroseconds(401),
GestureEventDetails(ET_SCROLL_FLING_START)},
@@ -248,26 +368,23 @@ TEST_F(StructTraitsTest, GestureEvent) {
GestureEventDetails(ET_GESTURE_TAP)},
};
- mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy();
- for (size_t i = 0; i < arraysize(kTestData); i++) {
+ for (size_t i = 0; i < base::size(kTestData); i++) {
+ std::unique_ptr<Event> expected_copy = Event::Clone(kTestData[i]);
std::unique_ptr<Event> output;
- proxy->EchoEvent(Event::Clone(kTestData[i]), &output);
+ ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Event>(
+ &expected_copy, &output));
EXPECT_TRUE(output->IsGestureEvent());
const GestureEvent* output_ptr_event = output->AsGestureEvent();
- EXPECT_EQ(kTestData[i].type(), output_ptr_event->type());
- EXPECT_EQ(kTestData[i].flags(), output_ptr_event->flags());
- EXPECT_EQ(kTestData[i].location(), output_ptr_event->location());
- EXPECT_EQ(kTestData[i].root_location(), output_ptr_event->root_location());
+ ExpectEventsEqual(kTestData[i], *output);
EXPECT_EQ(kTestData[i].details(), output_ptr_event->details());
EXPECT_EQ(kTestData[i].unique_touch_event_id(),
output_ptr_event->unique_touch_event_id());
- EXPECT_EQ(kTestData[i].time_stamp(), output_ptr_event->time_stamp());
}
}
-TEST_F(StructTraitsTest, ScrollEvent) {
- ScrollEvent kTestData[] = {
+TEST(StructTraitsTest, ScrollEvent) {
+ const ScrollEvent kTestData[] = {
{ET_SCROLL, gfx::Point(10, 20),
base::TimeTicks() + base::TimeDelta::FromMicroseconds(501), EF_NONE, 1,
2, 3, 4, 5, EventMomentumPhase::NONE, ScrollEventPhase::kNone},
@@ -298,17 +415,15 @@ TEST_F(StructTraitsTest, ScrollEvent) {
2, 3, 4, 5, EventMomentumPhase::END, ScrollEventPhase::kNone},
};
- mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy();
- for (size_t i = 0; i < arraysize(kTestData); i++) {
+ for (size_t i = 0; i < base::size(kTestData); i++) {
+ std::unique_ptr<Event> expected_copy = Event::Clone(kTestData[i]);
std::unique_ptr<Event> output;
- proxy->EchoEvent(Event::Clone(kTestData[i]), &output);
+ ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Event>(
+ &expected_copy, &output));
EXPECT_TRUE(output->IsScrollEvent());
const ScrollEvent* output_ptr_event = output->AsScrollEvent();
- EXPECT_EQ(kTestData[i].type(), output_ptr_event->type());
- EXPECT_EQ(kTestData[i].location(), output_ptr_event->location());
- EXPECT_EQ(kTestData[i].time_stamp(), output_ptr_event->time_stamp());
- EXPECT_EQ(kTestData[i].flags(), output_ptr_event->flags());
+ ExpectEventsEqual(kTestData[i], *output_ptr_event);
EXPECT_EQ(kTestData[i].x_offset(), output_ptr_event->x_offset());
EXPECT_EQ(kTestData[i].y_offset(), output_ptr_event->y_offset());
EXPECT_EQ(kTestData[i].x_offset_ordinal(),
@@ -321,4 +436,79 @@ TEST_F(StructTraitsTest, ScrollEvent) {
}
}
+TEST(StructTraitsTest, PointerDetails) {
+ const PointerDetails kTestData[] = {
+ {EventPointerType::POINTER_TYPE_UNKNOWN, 1, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f},
+ {EventPointerType::POINTER_TYPE_MOUSE, 1, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f},
+ {EventPointerType::POINTER_TYPE_PEN, 11, 12.f, 13.f, 14.f, 15.f, 16.f,
+ 17.f},
+ {EventPointerType::POINTER_TYPE_TOUCH, 1, 2.f, 3.f, 4.f, 5.f, 6.f, 7.f},
+ {EventPointerType::POINTER_TYPE_ERASER, 21, 22.f, 23.f, 24.f, 25.f, 26.f,
+ 27.f},
+ };
+ for (size_t i = 0; i < base::size(kTestData); i++) {
+ // Set |offset| as the constructor used above does not modify it.
+ PointerDetails input(kTestData[i]);
+ input.offset.set_x(i);
+ input.offset.set_y(i + 1);
+
+ PointerDetails output;
+ ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::PointerDetails>(
+ &input, &output));
+ EXPECT_EQ(input, output);
+ }
+}
+
+TEST(StructTraitsTest, TouchEvent) {
+ const TouchEvent kTestData[] = {
+ {ET_TOUCH_RELEASED,
+ {1, 2},
+ base::TimeTicks::Now(),
+ {EventPointerType::POINTER_TYPE_UNKNOWN, 1, 2.f, 3.f, 4.f, 5.f, 6.f,
+ 7.f},
+ EF_SHIFT_DOWN},
+ {ET_TOUCH_PRESSED, {1, 2}, base::TimeTicks::Now(), {}, EF_CONTROL_DOWN},
+ {ET_TOUCH_MOVED, {1, 2}, base::TimeTicks::Now(), {}, EF_NONE},
+ {ET_TOUCH_CANCELLED, {1, 2}, base::TimeTicks::Now(), {}, EF_NONE},
+ };
+ for (size_t i = 0; i < base::size(kTestData); i++) {
+ std::unique_ptr<Event> expected_copy = Event::Clone(kTestData[i]);
+ std::unique_ptr<Event> output;
+ ASSERT_TRUE(mojo::test::SerializeAndDeserialize<mojom::Event>(
+ &expected_copy, &output));
+ ExpectEventsEqual(*expected_copy, *output);
+ }
+
+ // Serialize/Deserialize with fields that can not be set from constructor.
+ std::unique_ptr<TouchEvent> touch_event =
+ std::make_unique<TouchEvent>(ET_TOUCH_CANCELLED, gfx::Point(),
+ base::TimeTicks::Now(), PointerDetails());
+ touch_event->set_may_cause_scrolling(true);
+ touch_event->set_hovering(true);
+ std::unique_ptr<Event> expected = std::move(touch_event);
+ std::unique_ptr<Event> output;
+ ASSERT_TRUE(
+ mojo::test::SerializeAndDeserialize<mojom::Event>(&expected, &output));
+ ExpectEventsEqual(*expected, *output);
+}
+
+TEST(StructTraitsTest, UnserializedTouchEventFields) {
+ std::unique_ptr<TouchEvent> touch_event =
+ std::make_unique<TouchEvent>(ET_TOUCH_CANCELLED, gfx::Point(),
+ base::TimeTicks::Now(), PointerDetails());
+ touch_event->set_should_remove_native_touch_id_mapping(true);
+ std::unique_ptr<Event> expected = std::move(touch_event);
+ std::unique_ptr<Event> output;
+ ASSERT_TRUE(
+ mojo::test::SerializeAndDeserialize<mojom::Event>(&expected, &output));
+ ExpectEventsEqual(*expected, *output);
+ // Have to set this back to false, else the destructor tries to access
+ // state not setup in tests.
+ expected->AsTouchEvent()->set_should_remove_native_touch_id_mapping(false);
+ // See comments in TouchEvent for why these two fields are not persisted.
+ EXPECT_FALSE(output->AsTouchEvent()->should_remove_native_touch_id_mapping());
+ EXPECT_NE(expected->AsTouchEvent()->unique_event_id(),
+ output->AsTouchEvent()->unique_event_id());
+}
+
} // namespace ui
diff --git a/chromium/ui/events/mojo/traits_test_service.mojom b/chromium/ui/events/mojo/traits_test_service.mojom
deleted file mode 100644
index 1df4cbecf80..00000000000
--- a/chromium/ui/events/mojo/traits_test_service.mojom
+++ /dev/null
@@ -1,12 +0,0 @@
-// Copyright 2016 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 ui.mojom;
-
-import "ui/events/mojo/event.mojom";
-
-interface TraitsTestService {
- [Sync]
- EchoEvent(Event e) => (Event pass);
-};
diff --git a/chromium/ui/events/ozone/evdev/event_device_info.cc b/chromium/ui/events/ozone/evdev/event_device_info.cc
index c04cf9c51b4..c7e5d043d03 100644
--- a/chromium/ui/events/ozone/evdev/event_device_info.cc
+++ b/chromium/ui/events/ozone/evdev/event_device_info.cc
@@ -197,6 +197,11 @@ bool EventDeviceInfo::Initialize(int fd, const base::FilePath& path) {
device_type_ = GetInputDeviceTypeFromPath(path);
+ // TODO(spang): Implement these quirks in a better way.
+ constexpr uint16_t kGoogleVendorId = 0x18d1;
+ if (vendor_id_ == kGoogleVendorId && product_id_ == 0x5030)
+ device_type_ = InputDeviceType::INPUT_DEVICE_INTERNAL;
+
return true;
}
diff --git a/chromium/ui/events/ozone/evdev/event_device_test_util.cc b/chromium/ui/events/ozone/evdev/event_device_test_util.cc
index 86feff7d83d..e72c4e7b7e6 100644
--- a/chromium/ui/events/ozone/evdev/event_device_test_util.cc
+++ b/chromium/ui/events/ozone/evdev/event_device_test_util.cc
@@ -634,7 +634,7 @@ ui::InputDeviceType InputDeviceTypeFromBusType(int bustype) {
return ui::InputDeviceType::INPUT_DEVICE_INTERNAL;
case BUS_USB:
case 0x1D: // Used in kLogitechTouchKeyboardK400 but not listed in input.h.
- return ui::InputDeviceType::INPUT_DEVICE_EXTERNAL;
+ return ui::InputDeviceType::INPUT_DEVICE_USB;
default:
NOTREACHED() << "Unexpected bus type";
return ui::InputDeviceType::INPUT_DEVICE_UNKNOWN;
diff --git a/chromium/ui/events/ozone/evdev/event_factory_evdev.cc b/chromium/ui/events/ozone/evdev/event_factory_evdev.cc
index 733f2979d8b..27f934cbe0b 100644
--- a/chromium/ui/events/ozone/evdev/event_factory_evdev.cc
+++ b/chromium/ui/events/ozone/evdev/event_factory_evdev.cc
@@ -336,13 +336,13 @@ void EventFactoryEvdev::DispatchTouchEvent(const TouchEventParams& params) {
gfx::PointF location = GetTransformedEventLocation(params);
PointerDetails details = GetTransformedEventPointerDetails(params);
+ details.twist = 0.f;
// params.slot is guaranteed to be < kNumTouchEvdevSlots.
int input_id = params.device_id * kNumTouchEvdevSlots + params.slot;
details.id = touch_id_generator_.GetGeneratedID(input_id);
TouchEvent touch_event(params.type, gfx::Point(), params.timestamp, details,
- modifiers_.GetModifierFlags() | params.flags,
- /* angle */ 0.f);
+ modifiers_.GetModifierFlags() | params.flags);
touch_event.set_location_f(location);
touch_event.set_root_location_f(location);
touch_event.set_source_device_id(params.device_id);
diff --git a/chromium/ui/events/platform/x11/x11_event_source.cc b/chromium/ui/events/platform/x11/x11_event_source.cc
index 7e9f6df4762..a68188d77dc 100644
--- a/chromium/ui/events/platform/x11/x11_event_source.cc
+++ b/chromium/ui/events/platform/x11/x11_event_source.cc
@@ -100,6 +100,7 @@ X11EventSource::X11EventSource(X11EventSourceDelegate* delegate,
distribution_(0, 999) {
DCHECK(!instance_);
instance_ = this;
+ SetTimestampServer(this);
DCHECK(delegate_);
DCHECK(display_);
@@ -110,6 +111,7 @@ X11EventSource::X11EventSource(X11EventSourceDelegate* delegate,
X11EventSource::~X11EventSource() {
DCHECK_EQ(this, instance_);
instance_ = nullptr;
+ SetTimestampServer(nullptr);
if (dummy_initialized_)
XDestroyWindow(display_, dummy_window_);
}
diff --git a/chromium/ui/events/platform/x11/x11_event_source.h b/chromium/ui/events/platform/x11/x11_event_source.h
index e818c4acfa8..c2ee795b68f 100644
--- a/chromium/ui/events/platform/x11/x11_event_source.h
+++ b/chromium/ui/events/platform/x11/x11_event_source.h
@@ -14,6 +14,7 @@
#include "base/optional.h"
#include "build/build_config.h"
#include "ui/events/events_export.h"
+#include "ui/events/x/events_x_utils.h"
#include "ui/gfx/x/x11_types.h"
using Time = unsigned long;
@@ -46,7 +47,7 @@ class X11EventSourceDelegate {
// Receives X11 events and sends them to X11EventSourceDelegate. Handles
// receiving, pre-process and post-processing XEvents.
-class EVENTS_EXPORT X11EventSource {
+class EVENTS_EXPORT X11EventSource : TimestampServer {
public:
X11EventSource(X11EventSourceDelegate* delegate, XDisplay* display);
~X11EventSource();
@@ -82,7 +83,7 @@ class EVENTS_EXPORT X11EventSource {
// Explicitly asks the X11 server for the current timestamp, and updates
// |last_seen_server_time_| with this value.
- Time GetCurrentServerTime();
+ Time GetCurrentServerTime() override;
protected:
// Extracts cookie data from |xevent| if it's of GenericType, and dispatches
diff --git a/chromium/ui/events/win/events_win_utils.cc b/chromium/ui/events/win/events_win_utils.cc
index f8bd8d3c155..4025b905b62 100644
--- a/chromium/ui/events/win/events_win_utils.cc
+++ b/chromium/ui/events/win/events_win_utils.cc
@@ -254,7 +254,7 @@ gfx::Point EventLocationFromMSG(const MSG& native_event) {
// Note: Wheel events are considered client, but their position is in screen
// coordinates.
// Client message. The position is contained in the LPARAM.
- return gfx::Point(native_event.lParam);
+ return gfx::Point(static_cast<DWORD>(native_event.lParam));
} else {
DCHECK(IsNonClientMouseEvent(native_event) ||
IsMouseWheelEvent(native_event) || IsScrollEvent(native_event));
diff --git a/chromium/ui/events/win/keyboard_hook_win.cc b/chromium/ui/events/win/keyboard_hook_win.cc
index 1688827db96..042e295679c 100644
--- a/chromium/ui/events/win/keyboard_hook_win.cc
+++ b/chromium/ui/events/win/keyboard_hook_win.cc
@@ -2,12 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/events/keyboard_hook_base.h"
+#include "ui/events/win/keyboard_hook_win.h"
#include <utility>
-#include <windows.h>
-
#include "base/logging.h"
#include "base/macros.h"
#include "base/optional.h"
@@ -16,30 +14,112 @@
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
+#include "ui/events/keycodes/keyboard_code_conversion.h"
+#include "ui/events/win/events_win_utils.h"
#include "ui/gfx/native_widget_types.h"
namespace ui {
namespace {
-// These keys interfere with the return value of ::GetKeyState() as observing
-// them directly in LowLevelKeyboardProc will cause their key combinations to be
-// ignored. As an example, the KeyF event in an Alt + F combination will result
-// in a missing alt-down flag. Since a regular application can successfully
-// receive these keys without using LowLevelKeyboardProc, they can be ignored.
-bool IsOSReservedKey(DWORD vk) {
- return vk == VK_SHIFT || vk == VK_LSHIFT || vk == VK_RSHIFT ||
- vk == VK_CONTROL || vk == VK_LCONTROL || vk == VK_RCONTROL ||
- vk == VK_MENU || vk == VK_LMENU || vk == VK_RMENU || vk == VK_LWIN ||
- vk == VK_RWIN || vk == VK_CAPITAL || vk == VK_NUMLOCK ||
- vk == VK_SCROLL;
+// The Windows KeyboardHook implementation uses a low-level hook in order to
+// intercept system key combinations such as Alt + Tab. A standard hook or
+// other window message filtering mechanisms will allow us to observe key events
+// but we would be unable to block them or the corresponding system action.
+// There are downsides to this approach as described in the following blurbs.
+
+// Low-level hooks are not given a repeat state for each key event. This is
+// because the events are intercepted prior to the OS handling them and tracking
+// their states the usual way. We solve this by tracking the last key seen and
+// modifying the event manually to indicate it is a repeat. This works for
+// every key except escape which is used to exit fullscreen and tear down the
+// hook. The quirk is that after the hook is torn down, the first escape key
+// event passed to the window will appear like an initial keydown. This is
+// because it *is* an initial keydown from Windows' perspective as it was being
+// intercepted before then.
+
+// Intercepting modifier keys (Ctrl, Shift, Win, Etc.) within a low-level
+// keyboard hook will result in an incorrect modifier state reported by the OS
+// for that key. This is because the hook intercepts the event before the OS
+// has a chance to observe the event and update its internal state. This
+// trade-off is necessary as we also want to intercept and prevent specific key
+// combos from taking effect.
+
+// A related side-effect occurs when intercepting printable characters. Since
+// the key event is intercepted before the OS handles it, no char events are
+// produced. So if we intercept scan codes which should generate a printable
+// character, the result is that the key up/down events are sent correctly but
+// no WM_CHAR message is generated. This is unacceptable for some usages of the
+// hook as the behavior is very different between locked and unlocked states.
+
+// This is a fair number of downsides however the ability to block system key
+// combos is a hard requirement so we need to work around them.
+
+// The solution we have adopted is:
+// - Only intercept modifiers and allow all other keys to pass through
+// Note: Shift is not included as otherwise it is not applied by the OS and
+// the printable characters generated by the key event will be wrong.
+// - Track the repeat state ourselves
+// - Update the per-thread key state for the tracked modifiers using
+// SetKeyboardState().
+
+// In practice this works well as intercepting the modifiers allows us to block
+// system keyboard combos and all other keys generate the proper events and
+// printable chars.
+
+// Using SetKeyboardState() allows us to tell Windows the current state for the
+// modifiers we intercept. This state only works for the current thread,
+// meaning that other applications / threads which check the key state for the
+// modifiers will not receive an accurate value. One constraint for the
+// KeyboardHook is that it is only engaged when our window is fullscreen and
+// focused so we don't need to worry too much about other apps.
+
+// Represents a VK_LCONTROL scancode with the 0x02 flag in the high word.
+// The 0x02 flag does not seem to be documented on MSDN or in the public Windows
+// headers. I suspect it is related to the KF_ family of constants which skips
+// from 0x0100 to 0x0800 with 0x0200 and 0x0400 undocumented (likely reserved).
+constexpr DWORD kSynthesizedControlScanCodeForAltGr = 0x021D;
+
+// {Get|Set}KeyboardState() receives an array with 256 elements. This is
+// described in MSDN but no constant exists for this value. Function reference:
+// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-getkeyboardstate
+// https://docs.microsoft.com/en-us/windows/desktop/api/winuser/nf-winuser-setkeyboardstate
+constexpr int kKeyboardStateArraySize = 256;
+
+// Used for setting and testing the bits in the KeyboardState array.
+constexpr BYTE kKeyDown = 0x80;
+constexpr BYTE kKeyUp = 0x00;
+
+bool IsAltKey(DWORD vk) {
+ return vk == VK_MENU || vk == VK_LMENU || vk == VK_RMENU;
+}
+
+bool IsControlKey(DWORD vk) {
+ return vk == VK_CONTROL || vk == VK_LCONTROL || vk == VK_RCONTROL;
+}
+
+bool IsWindowsKey(DWORD vk) {
+ return vk == VK_LWIN || vk == VK_RWIN;
+}
+
+bool IsModifierKey(DWORD vk) {
+ // We don't track the state of the shift key as we want to allow the OS to
+ // know about its state so it is correctly applied to printable characters.
+ return IsAltKey(vk) || IsControlKey(vk) || IsWindowsKey(vk);
}
-class KeyboardHookWin : public KeyboardHookBase {
+class KeyboardHookWinImpl : public KeyboardHookWin {
public:
- KeyboardHookWin(base::Optional<base::flat_set<DomCode>> dom_codes,
- KeyEventCallback callback);
- ~KeyboardHookWin() override;
+ KeyboardHookWinImpl(base::Optional<base::flat_set<DomCode>> dom_codes,
+ KeyEventCallback callback,
+ bool enable_hook_registration);
+ ~KeyboardHookWinImpl() override;
+
+ // KeyboardHookWin implementation.
+ bool ProcessKeyEventMessage(WPARAM w_param,
+ DWORD vk,
+ DWORD scan_code,
+ DWORD time_stamp) override;
bool Register();
@@ -47,30 +127,50 @@ class KeyboardHookWin : public KeyboardHookBase {
static LRESULT CALLBACK ProcessKeyEvent(int code,
WPARAM w_param,
LPARAM l_param);
- static KeyboardHookWin* instance_;
+
+ void UpdateModifierState(DWORD vk, bool key_down);
+
+ void ClearModifierStates();
+
+ static KeyboardHookWinImpl* instance_;
THREAD_CHECKER(thread_checker_);
HHOOK hook_ = nullptr;
- // Tracks the last key down seen in order to determine if the current key
- // event is a repeated key press.
+ // Tracks the last non-located key down seen in order to determine if the
+ // current key event should be marked as a repeated key press.
DWORD last_key_down_ = 0;
- DISALLOW_COPY_AND_ASSIGN(KeyboardHookWin);
+ // Tracks the number of AltGr key sequences seen since the start of the most
+ // recent AltGr key down. When the AltGr key is pressed, Windows injects a
+ // synthesized left control key event followed by the right alt key event.
+ // This sequence occurs on the initial keypress and every repeat.
+ int altgr_sequence_count_ = 0;
+
+ const bool enable_hook_registration_ = true;
+
+ DISALLOW_COPY_AND_ASSIGN(KeyboardHookWinImpl);
};
// static
-KeyboardHookWin* KeyboardHookWin::instance_ = nullptr;
+KeyboardHookWinImpl* KeyboardHookWinImpl::instance_ = nullptr;
-KeyboardHookWin::KeyboardHookWin(
+KeyboardHookWinImpl::KeyboardHookWinImpl(
base::Optional<base::flat_set<DomCode>> dom_codes,
- KeyEventCallback callback)
- : KeyboardHookBase(std::move(dom_codes), std::move(callback)) {}
+ KeyEventCallback callback,
+ bool enable_hook_registration)
+ : KeyboardHookWin(std::move(dom_codes), std::move(callback)),
+ enable_hook_registration_(enable_hook_registration) {}
-KeyboardHookWin::~KeyboardHookWin() {
+KeyboardHookWinImpl::~KeyboardHookWinImpl() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ ClearModifierStates();
+
+ if (!enable_hook_registration_)
+ return;
+
DCHECK_EQ(instance_, this);
instance_ = nullptr;
@@ -78,9 +178,12 @@ KeyboardHookWin::~KeyboardHookWin() {
DPLOG(ERROR) << "UnhookWindowsHookEx failed";
}
-bool KeyboardHookWin::Register() {
+bool KeyboardHookWinImpl::Register() {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
+ // If the hook was created for testing, |Register()| should not be called.
+ DCHECK(enable_hook_registration_);
+
// Only one instance of this class can be registered at a time.
DCHECK(!instance_);
instance_ = this;
@@ -89,7 +192,7 @@ bool KeyboardHookWin::Register() {
// which installed it.
hook_ = SetWindowsHookEx(
WH_KEYBOARD_LL,
- reinterpret_cast<HOOKPROC>(&KeyboardHookWin::ProcessKeyEvent),
+ reinterpret_cast<HOOKPROC>(&KeyboardHookWinImpl::ProcessKeyEvent),
/*hMod=*/nullptr,
/*dwThreadId=*/0);
DPLOG_IF(ERROR, !hook_) << "SetWindowsHookEx failed";
@@ -97,10 +200,127 @@ bool KeyboardHookWin::Register() {
return hook_ != nullptr;
}
+void KeyboardHookWinImpl::ClearModifierStates() {
+ BYTE keyboard_state[kKeyboardStateArraySize] = {0};
+ if (!GetKeyboardState(keyboard_state)) {
+ DPLOG(ERROR) << "GetKeyboardState() failed: ";
+ return;
+ }
+
+ // Reset each modifier position.
+ keyboard_state[VK_CONTROL] = kKeyUp;
+ keyboard_state[VK_LCONTROL] = kKeyUp;
+ keyboard_state[VK_RCONTROL] = kKeyUp;
+ keyboard_state[VK_MENU] = kKeyUp;
+ keyboard_state[VK_LMENU] = kKeyUp;
+ keyboard_state[VK_RMENU] = kKeyUp;
+ keyboard_state[VK_LWIN] = kKeyUp;
+ keyboard_state[VK_RWIN] = kKeyUp;
+
+ if (!SetKeyboardState(keyboard_state))
+ DPLOG(ERROR) << "SetKeyboardState() failed: ";
+}
+
+bool KeyboardHookWinImpl::ProcessKeyEventMessage(WPARAM w_param,
+ DWORD vk,
+ DWORD scan_code,
+ DWORD time_stamp) {
+ // The |vk| delivered to the low-level hook includes a location which is
+ // needed to track individual keystates such as when both left and right
+ // control keys are pressed. Make sure that location information was retained
+ // when the vkey was passed into this method.
+ DCHECK_NE(vk, static_cast<DWORD>(VK_CONTROL));
+ DCHECK_NE(vk, static_cast<DWORD>(VK_MENU));
+
+ if (!IsModifierKey(vk))
+ return false;
+
+ // Windows synthesizes an additional key event when AltGr is pressed. The
+ // event has the left control scan code in the low word and a 0x02 flag set in
+ // the high word. The VK_RMENU event will be sent once this key is processed.
+ bool is_altgr_sequence = false;
+ if (scan_code == kSynthesizedControlScanCodeForAltGr) {
+ is_altgr_sequence = true;
+ scan_code = KeycodeConverter::DomCodeToNativeKeycode(DomCode::CONTROL_LEFT);
+ }
+
+ // If the caller has only requested that Alt be captured, then we don't want
+ // to bail early on the injected control event.
+ DomCode dom_code = DomCode::NONE;
+ if (is_altgr_sequence)
+ dom_code = DomCode::ALT_RIGHT;
+ else
+ dom_code = KeycodeConverter::NativeKeycodeToDomCode(scan_code);
+
+ if (!ShouldCaptureKeyEvent(dom_code))
+ return false;
+
+ if (is_altgr_sequence)
+ altgr_sequence_count_++;
+ else if (vk != VK_RMENU)
+ altgr_sequence_count_ = 0;
+
+ // The Windows key is always located, the other modifiers are not.
+ DWORD non_located_vk =
+ IsWindowsKey(vk)
+ ? vk
+ : LocatedToNonLocatedKeyboardCode(static_cast<KeyboardCode>(vk));
+
+ bool is_repeat = false;
+ MSG msg = {nullptr, w_param, non_located_vk, GetLParamFromScanCode(scan_code),
+ time_stamp};
+ EventType event_type = EventTypeFromMSG(msg);
+ if (event_type == ET_KEY_PRESSED) {
+ UpdateModifierState(vk, /*key_down=*/true);
+ // We use the non-located vkey to determine whether a key event is a repeat
+ // or not. The exception is for AltGr which has a two key sequence which
+ // alternates.
+ is_repeat = (last_key_down_ == non_located_vk) || altgr_sequence_count_ > 1;
+ last_key_down_ = non_located_vk;
+ } else {
+ DCHECK_EQ(event_type, ET_KEY_RELEASED);
+ UpdateModifierState(vk, /*key_down=*/false);
+ altgr_sequence_count_ = 0;
+ last_key_down_ = 0;
+ }
+
+ std::unique_ptr<KeyEvent> key_event =
+ std::make_unique<KeyEvent>(KeyEventFromMSG(msg));
+ if (is_repeat)
+ key_event->set_flags(key_event->flags() | EF_IS_REPEAT);
+ ForwardCapturedKeyEvent(std::move(key_event));
+
+ return true;
+}
+
+void KeyboardHookWinImpl::UpdateModifierState(DWORD vk, bool is_key_down) {
+ BYTE keyboard_state[kKeyboardStateArraySize] = {0};
+ if (!GetKeyboardState(keyboard_state)) {
+ DPLOG(ERROR) << "GetKeyboardState() failed: ";
+ return;
+ }
+
+ // Update the located virtual key first.
+ keyboard_state[vk] = is_key_down ? kKeyDown : kKeyUp;
+
+ // Now update the non-located virtual key.
+ keyboard_state[VK_CONTROL] = (keyboard_state[VK_LCONTROL] == kKeyDown ||
+ keyboard_state[VK_RCONTROL] == kKeyDown)
+ ? kKeyDown
+ : kKeyUp;
+ keyboard_state[VK_MENU] = (keyboard_state[VK_LMENU] == kKeyDown ||
+ keyboard_state[VK_RMENU] == kKeyDown)
+ ? kKeyDown
+ : kKeyUp;
+
+ if (!SetKeyboardState(keyboard_state))
+ PLOG(ERROR) << "SetKeyboardState() failed: ";
+}
+
// static
-LRESULT CALLBACK KeyboardHookWin::ProcessKeyEvent(int code,
- WPARAM w_param,
- LPARAM l_param) {
+LRESULT CALLBACK KeyboardHookWinImpl::ProcessKeyEvent(int code,
+ WPARAM w_param,
+ LPARAM l_param) {
// If there is an error unhooking, this method could be called with a null
// |instance_|. Ensure we have a valid instance and that |code| is correct
// before proceeding.
@@ -110,33 +330,20 @@ LRESULT CALLBACK KeyboardHookWin::ProcessKeyEvent(int code,
DCHECK_CALLED_ON_VALID_THREAD(instance_->thread_checker_);
KBDLLHOOKSTRUCT* ll_hooks = reinterpret_cast<KBDLLHOOKSTRUCT*>(l_param);
- DomCode dom_code =
- KeycodeConverter::NativeKeycodeToDomCode(ll_hooks->scanCode);
- if (!IsOSReservedKey(ll_hooks->vkCode) &&
- instance_->ShouldCaptureKeyEvent(dom_code)) {
- MSG msg = {nullptr, w_param, ll_hooks->vkCode,
- (ll_hooks->scanCode << 16) | (ll_hooks->flags & 0xFFFF),
- ll_hooks->time};
- KeyEvent key_event = KeyEventFromMSG(msg);
-
- // Determine if this key event represents a repeated key event.
- // A low level KB Hook is not passed a parameter or flag which indicates
- // whether the key event is a repeat or not as it is called very early in
- // input handling pipeline. That means we need to apply our own heuristic
- // to determine if it should be treated as a repeated key press or not.
- if (key_event.type() == ET_KEY_PRESSED) {
- if (instance_->last_key_down_ != 0 &&
- instance_->last_key_down_ == ll_hooks->vkCode) {
- key_event.set_flags(key_event.flags() | EF_IS_REPEAT);
- }
- instance_->last_key_down_ = ll_hooks->vkCode;
- } else {
- DCHECK_EQ(key_event.type(), ET_KEY_RELEASED);
- instance_->last_key_down_ = 0;
- }
- instance_->ForwardCapturedKeyEvent(std::make_unique<KeyEvent>(key_event));
+
+ // This vkey represents both a vkey and a location on the keyboard such as
+ // VK_LCONTROL or VK_RCONTROL.
+ DWORD vk = ll_hooks->vkCode;
+
+ // Apply the extended flag prior to passing |scan_code| since |instance_| does
+ // not have access to the low-level hook flags.
+ DWORD scan_code = ll_hooks->scanCode;
+ if (ll_hooks->flags & LLKHF_EXTENDED)
+ scan_code |= 0xE000;
+
+ if (instance_->ProcessKeyEventMessage(w_param, vk, scan_code, ll_hooks->time))
return 1;
- }
+
return CallNextHookEx(nullptr, code, w_param, l_param);
}
@@ -147,9 +354,10 @@ std::unique_ptr<KeyboardHook> KeyboardHook::Create(
base::Optional<base::flat_set<DomCode>> dom_codes,
gfx::AcceleratedWidget accelerated_widget,
KeyEventCallback callback) {
- std::unique_ptr<KeyboardHookWin> keyboard_hook =
- std::make_unique<KeyboardHookWin>(std::move(dom_codes),
- std::move(callback));
+ std::unique_ptr<KeyboardHookWinImpl> keyboard_hook =
+ std::make_unique<KeyboardHookWinImpl>(std::move(dom_codes),
+ std::move(callback),
+ /*enable_hook_registration=*/true);
if (!keyboard_hook->Register())
return nullptr;
@@ -157,4 +365,19 @@ std::unique_ptr<KeyboardHook> KeyboardHook::Create(
return keyboard_hook;
}
+std::unique_ptr<KeyboardHookWin> KeyboardHookWin::CreateForTesting(
+ base::Optional<base::flat_set<DomCode>> dom_codes,
+ KeyEventCallback callback) {
+ return std::make_unique<KeyboardHookWinImpl>(
+ std::move(dom_codes), std::move(callback),
+ /*enable_hook_registration=*/false);
+}
+
+KeyboardHookWin::KeyboardHookWin(
+ base::Optional<base::flat_set<DomCode>> dom_codes,
+ KeyEventCallback callback)
+ : KeyboardHookBase(std::move(dom_codes), std::move(callback)) {}
+
+KeyboardHookWin::~KeyboardHookWin() = default;
+
} // namespace ui
diff --git a/chromium/ui/events/win/keyboard_hook_win.h b/chromium/ui/events/win/keyboard_hook_win.h
new file mode 100644
index 00000000000..627ba313b17
--- /dev/null
+++ b/chromium/ui/events/win/keyboard_hook_win.h
@@ -0,0 +1,52 @@
+// 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_WIN_KEYBOARD_HOOK_WIN_H_
+#define UI_EVENTS_WIN_KEYBOARD_HOOK_WIN_H_
+
+#include <memory>
+
+#include <windows.h>
+
+#include "base/containers/flat_set.h"
+#include "base/logging.h"
+#include "base/macros.h"
+#include "base/optional.h"
+#include "ui/events/event.h"
+#include "ui/events/events_export.h"
+#include "ui/events/keyboard_hook_base.h"
+#include "ui/events/keycodes/dom/dom_code.h"
+
+namespace ui {
+
+// Exposes a method to drive the Windows KeyboardHook implementation by feeding
+// it key event data. This method is used by both the low-level keyboard hook
+// and by unit tests which simulate the hooked behavior w/o actually installing
+// a hook (doing so would cause problems with test parallelization).
+class EVENTS_EXPORT KeyboardHookWin : public KeyboardHookBase {
+ public:
+ KeyboardHookWin(base::Optional<base::flat_set<DomCode>> dom_codes,
+ KeyEventCallback callback);
+ ~KeyboardHookWin() override;
+
+ // Create a KeyboardHookWin instance which does not register a low-level hook.
+ static std::unique_ptr<KeyboardHookWin> CreateForTesting(
+ base::Optional<base::flat_set<DomCode>> dom_codes,
+ KeyEventCallback callback);
+
+ // Called when a key event message is delivered via the low-level hook.
+ // Exposed here to allow for testing w/o engaging the low-level hook.
+ // Returns true if the message was handled.
+ virtual bool ProcessKeyEventMessage(WPARAM w_param,
+ DWORD vk,
+ DWORD scan_code,
+ DWORD time_stamp) = 0;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(KeyboardHookWin);
+};
+
+} // namespace ui
+
+#endif // UI_EVENTS_WIN_KEYBOARD_HOOK_WIN_H_
diff --git a/chromium/ui/events/win/keyboard_hook_win_unittest.cc b/chromium/ui/events/win/keyboard_hook_win_unittest.cc
new file mode 100644
index 00000000000..d8f3deaa805
--- /dev/null
+++ b/chromium/ui/events/win/keyboard_hook_win_unittest.cc
@@ -0,0 +1,1085 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <memory>
+#include <vector>
+
+#include "base/bind.h"
+#include "base/containers/flat_set.h"
+#include "base/optional.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/events/event.h"
+#include "ui/events/keyboard_hook.h"
+#include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/events/keycodes/dom/keycode_converter.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+#include "ui/events/test/keyboard_layout.h"
+#include "ui/events/win/keyboard_hook_win.h"
+#include "ui/events/win/system_event_state_lookup.h"
+
+namespace ui {
+
+class KeyboardHookWinTest : public testing::Test {
+ public:
+ KeyboardHookWinTest();
+ ~KeyboardHookWinTest() override;
+
+ // testing::Test overrides.
+ void SetUp() override;
+
+ void HandleKeyPress(KeyEvent* key_event);
+
+ protected:
+ KeyboardHookWin* keyboard_hook() { return keyboard_hook_.get(); }
+
+ uint32_t next_time_stamp() { return time_stamp_++; }
+
+ std::vector<KeyEvent>* key_events() { return &key_events_; }
+
+ // Used for sending key events which are handled by the hook.
+ void SendModifierKeyDownEvent(KeyboardCode key_code,
+ DomCode dom_code,
+ int repeat_count = 1);
+ void SendModifierKeyUpEvent(KeyboardCode key_code, DomCode dom_code);
+
+ void SetKeyboardLayoutForTest(KeyboardLayout new_layout);
+
+ private:
+ uint32_t time_stamp_ = 0;
+ std::unique_ptr<KeyboardHookWin> keyboard_hook_;
+ std::vector<KeyEvent> key_events_;
+ std::unique_ptr<ScopedKeyboardLayout> keyboard_layout_;
+
+ DISALLOW_COPY_AND_ASSIGN(KeyboardHookWinTest);
+};
+
+KeyboardHookWinTest::KeyboardHookWinTest() = default;
+
+KeyboardHookWinTest::~KeyboardHookWinTest() = default;
+
+void KeyboardHookWinTest::SetUp() {
+ keyboard_hook_ = KeyboardHookWin::CreateForTesting(
+ base::Optional<base::flat_set<DomCode>>(),
+ base::BindRepeating(&KeyboardHookWinTest::HandleKeyPress,
+ base::Unretained(this)));
+
+ keyboard_layout_ = std::make_unique<ScopedKeyboardLayout>(
+ KeyboardLayout::KEYBOARD_LAYOUT_ENGLISH_US);
+}
+
+void KeyboardHookWinTest::HandleKeyPress(KeyEvent* key_event) {
+ key_events_.push_back(*key_event);
+}
+
+void KeyboardHookWinTest::SendModifierKeyDownEvent(KeyboardCode key_code,
+ DomCode dom_code,
+ int repeat_count /*=1*/) {
+ // Ensure we have a valid repeat count and the modifer passed in contains
+ // location information.
+ DCHECK_GT(repeat_count, 0);
+ DCHECK_NE(key_code, KeyboardCode::VKEY_CONTROL);
+ DCHECK_NE(key_code, KeyboardCode::VKEY_MENU);
+
+ for (int i = 0; i < repeat_count; i++) {
+ ASSERT_TRUE(keyboard_hook()->ProcessKeyEventMessage(
+ WM_KEYDOWN, key_code,
+ KeycodeConverter::DomCodeToNativeKeycode(dom_code), next_time_stamp()));
+ }
+}
+
+void KeyboardHookWinTest::SendModifierKeyUpEvent(KeyboardCode key_code,
+ DomCode dom_code) {
+ // Ensure we have a valid repeat count and the modifer passed in contains
+ // location information.
+ DCHECK_NE(key_code, KeyboardCode::VKEY_CONTROL);
+ DCHECK_NE(key_code, KeyboardCode::VKEY_MENU);
+
+ ASSERT_TRUE(keyboard_hook()->ProcessKeyEventMessage(
+ WM_KEYUP, key_code, KeycodeConverter::DomCodeToNativeKeycode(dom_code),
+ next_time_stamp()));
+}
+
+void VerifyKeyEvent(KeyEvent* key_event,
+ KeyboardCode non_located_key_code,
+ DomCode dom_code,
+ bool key_down,
+ bool is_repeat) {
+ if (key_down) {
+ ASSERT_EQ(key_event->type(), ET_KEY_PRESSED);
+ ASSERT_EQ(key_event->is_repeat(), is_repeat);
+ } else {
+ ASSERT_EQ(key_event->type(), ET_KEY_RELEASED);
+ ASSERT_FALSE(key_event->is_repeat());
+ }
+ ASSERT_EQ(key_event->key_code(), non_located_key_code);
+ ASSERT_EQ(key_event->code(), dom_code);
+}
+
+TEST_F(KeyboardHookWinTest, SimpleLeftControlKeypressTest) {
+ const KeyboardCode key_code = KeyboardCode::VKEY_LCONTROL;
+ const DomCode dom_code = DomCode::CONTROL_LEFT;
+ SendModifierKeyDownEvent(key_code, dom_code);
+ ASSERT_EQ(key_events()->size(), 1ULL);
+ SendModifierKeyUpEvent(key_code, dom_code);
+ ASSERT_EQ(key_events()->size(), 2ULL);
+
+ KeyEvent down_event = key_events()->at(0);
+ VerifyKeyEvent(&down_event, KeyboardCode::VKEY_CONTROL, dom_code, true,
+ false);
+ ASSERT_TRUE(down_event.IsControlDown());
+ ASSERT_FALSE(down_event.IsAltDown());
+ ASSERT_FALSE(down_event.IsCommandDown());
+
+ KeyEvent up_event = key_events()->at(1);
+ VerifyKeyEvent(&up_event, KeyboardCode::VKEY_CONTROL, dom_code, false, false);
+ ASSERT_FALSE(up_event.IsControlDown());
+}
+
+TEST_F(KeyboardHookWinTest, RepeatingLeftControlKeypressTest) {
+ const int repeat_count = 10;
+ const KeyboardCode key_code = KeyboardCode::VKEY_LCONTROL;
+ const DomCode dom_code = DomCode::CONTROL_LEFT;
+ SendModifierKeyDownEvent(key_code, dom_code, repeat_count);
+ ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count);
+ SendModifierKeyUpEvent(key_code, dom_code);
+ ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count + 1);
+
+ bool should_repeat = false;
+ for (int i = 0; i < repeat_count; i++) {
+ KeyEvent event = key_events()->at(i);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, dom_code, true,
+ should_repeat);
+ ASSERT_TRUE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_FALSE(event.IsCommandDown());
+ should_repeat = true;
+ }
+
+ KeyEvent up_event = key_events()->at(repeat_count);
+ VerifyKeyEvent(&up_event, KeyboardCode::VKEY_CONTROL, dom_code, false, false);
+ ASSERT_FALSE(up_event.IsControlDown());
+}
+
+TEST_F(KeyboardHookWinTest, SimpleRightControlKeypressTest) {
+ const KeyboardCode key_code = KeyboardCode::VKEY_RCONTROL;
+ const DomCode dom_code = DomCode::CONTROL_RIGHT;
+ SendModifierKeyDownEvent(key_code, dom_code);
+ ASSERT_EQ(key_events()->size(), 1ULL);
+ SendModifierKeyUpEvent(key_code, dom_code);
+ ASSERT_EQ(key_events()->size(), 2ULL);
+
+ KeyEvent down_event = key_events()->at(0);
+ VerifyKeyEvent(&down_event, KeyboardCode::VKEY_CONTROL, dom_code, true,
+ false);
+ ASSERT_TRUE(down_event.IsControlDown());
+ ASSERT_FALSE(down_event.IsAltDown());
+ ASSERT_FALSE(down_event.IsCommandDown());
+
+ KeyEvent up_event = key_events()->at(1);
+ VerifyKeyEvent(&up_event, KeyboardCode::VKEY_CONTROL, dom_code, false, false);
+ ASSERT_FALSE(up_event.IsControlDown());
+}
+
+TEST_F(KeyboardHookWinTest, RepeatingRightControlKeypressTest) {
+ const int repeat_count = 10;
+ const KeyboardCode key_code = KeyboardCode::VKEY_RCONTROL;
+ const DomCode dom_code = DomCode::CONTROL_RIGHT;
+ SendModifierKeyDownEvent(key_code, dom_code, repeat_count);
+ ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count);
+ SendModifierKeyUpEvent(key_code, dom_code);
+ ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count + 1);
+
+ bool should_repeat = false;
+ for (int i = 0; i < repeat_count; i++) {
+ KeyEvent event = key_events()->at(i);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, dom_code, true,
+ should_repeat);
+ ASSERT_TRUE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_FALSE(event.IsCommandDown());
+ should_repeat = true;
+ }
+
+ KeyEvent up_event = key_events()->at(repeat_count);
+ VerifyKeyEvent(&up_event, KeyboardCode::VKEY_CONTROL, dom_code, false, false);
+ ASSERT_FALSE(up_event.IsControlDown());
+}
+
+TEST_F(KeyboardHookWinTest, SimpleLifoControlSequenceTest) {
+ const KeyboardCode left_key_code = KeyboardCode::VKEY_LCONTROL;
+ const DomCode left_dom_code = DomCode::CONTROL_LEFT;
+ const KeyboardCode right_key_code = KeyboardCode::VKEY_RCONTROL;
+ const DomCode right_dom_code = DomCode::CONTROL_RIGHT;
+ SendModifierKeyDownEvent(left_key_code, left_dom_code, 2);
+ SendModifierKeyDownEvent(right_key_code, right_dom_code, 2);
+ SendModifierKeyUpEvent(right_key_code, right_dom_code);
+ SendModifierKeyUpEvent(left_key_code, left_dom_code);
+ ASSERT_EQ(key_events()->size(), 6ULL);
+
+ // First key down, no repeat.
+ KeyEvent event = key_events()->at(0);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, left_dom_code, true,
+ false);
+ ASSERT_TRUE(event.IsControlDown());
+
+ // First key still down, repeat.
+ event = key_events()->at(1);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, left_dom_code, true, true);
+ ASSERT_TRUE(event.IsControlDown());
+
+ // Second key down, repeat.
+ event = key_events()->at(2);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, right_dom_code, true,
+ true);
+ ASSERT_TRUE(event.IsControlDown());
+
+ // Second key still down, repeat.
+ event = key_events()->at(3);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, right_dom_code, true,
+ true);
+ ASSERT_TRUE(event.IsControlDown());
+
+ // Second key up.
+ event = key_events()->at(4);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, right_dom_code, false,
+ false);
+ ASSERT_TRUE(event.IsControlDown());
+
+ // First key up.
+ event = key_events()->at(5);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, left_dom_code, false,
+ false);
+ ASSERT_FALSE(event.IsControlDown());
+}
+
+TEST_F(KeyboardHookWinTest, SimpleFifoControlSequenceTest) {
+ const KeyboardCode left_key_code = KeyboardCode::VKEY_LCONTROL;
+ const DomCode left_dom_code = DomCode::CONTROL_LEFT;
+ const KeyboardCode right_key_code = KeyboardCode::VKEY_RCONTROL;
+ const DomCode right_dom_code = DomCode::CONTROL_RIGHT;
+ SendModifierKeyDownEvent(right_key_code, right_dom_code, 2);
+ SendModifierKeyDownEvent(left_key_code, left_dom_code, 2);
+ SendModifierKeyUpEvent(right_key_code, right_dom_code);
+ SendModifierKeyUpEvent(left_key_code, left_dom_code);
+ ASSERT_EQ(key_events()->size(), 6ULL);
+
+ // First key down, no repeat.
+ KeyEvent event = key_events()->at(0);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, right_dom_code, true,
+ false);
+ ASSERT_TRUE(event.IsControlDown());
+
+ // First key still down, repeat.
+ event = key_events()->at(1);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, right_dom_code, true,
+ true);
+ ASSERT_TRUE(event.IsControlDown());
+
+ // Second key down, repeat.
+ event = key_events()->at(2);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, left_dom_code, true, true);
+ ASSERT_TRUE(event.IsControlDown());
+
+ // Second key still down, repeat.
+ event = key_events()->at(3);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, left_dom_code, true, true);
+ ASSERT_TRUE(event.IsControlDown());
+
+ // First key up.
+ event = key_events()->at(4);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, right_dom_code, false,
+ false);
+ ASSERT_TRUE(event.IsControlDown());
+
+ // Second key up.
+ event = key_events()->at(5);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, left_dom_code, false,
+ false);
+ ASSERT_FALSE(event.IsControlDown());
+}
+
+TEST_F(KeyboardHookWinTest, SimpleLeftAltKeypressTest) {
+ const KeyboardCode key_code = KeyboardCode::VKEY_LMENU;
+ const DomCode dom_code = DomCode::ALT_LEFT;
+ SendModifierKeyDownEvent(key_code, dom_code);
+ ASSERT_EQ(key_events()->size(), 1ULL);
+ SendModifierKeyUpEvent(key_code, dom_code);
+ ASSERT_EQ(key_events()->size(), 2ULL);
+
+ KeyEvent down_event = key_events()->at(0);
+ VerifyKeyEvent(&down_event, KeyboardCode::VKEY_MENU, dom_code, true, false);
+ ASSERT_FALSE(down_event.IsControlDown());
+ ASSERT_TRUE(down_event.IsAltDown());
+ ASSERT_FALSE(down_event.IsCommandDown());
+
+ KeyEvent up_event = key_events()->at(1);
+ VerifyKeyEvent(&up_event, KeyboardCode::VKEY_MENU, dom_code, false, false);
+ ASSERT_FALSE(up_event.IsAltDown());
+}
+
+TEST_F(KeyboardHookWinTest, RepeatingLeftAltKeypressTest) {
+ const int repeat_count = 10;
+ const KeyboardCode key_code = KeyboardCode::VKEY_LMENU;
+ const DomCode dom_code = DomCode::ALT_LEFT;
+ SendModifierKeyDownEvent(key_code, dom_code, repeat_count);
+ ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count);
+ SendModifierKeyUpEvent(key_code, dom_code);
+ ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count + 1);
+
+ bool should_repeat = false;
+ for (int i = 0; i < repeat_count; i++) {
+ KeyEvent event = key_events()->at(i);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, dom_code, true,
+ should_repeat);
+ ASSERT_FALSE(event.IsControlDown());
+ ASSERT_TRUE(event.IsAltDown());
+ ASSERT_FALSE(event.IsCommandDown());
+ should_repeat = true;
+ }
+
+ KeyEvent up_event = key_events()->at(repeat_count);
+ VerifyKeyEvent(&up_event, KeyboardCode::VKEY_MENU, dom_code, false, false);
+ ASSERT_FALSE(up_event.IsAltDown());
+}
+
+TEST_F(KeyboardHookWinTest, SimpleRightAltKeypressTest) {
+ const KeyboardCode key_code = KeyboardCode::VKEY_RMENU;
+ const DomCode dom_code = DomCode::ALT_LEFT;
+ SendModifierKeyDownEvent(key_code, dom_code);
+ ASSERT_EQ(key_events()->size(), 1ULL);
+ SendModifierKeyUpEvent(key_code, dom_code);
+ ASSERT_EQ(key_events()->size(), 2ULL);
+
+ KeyEvent down_event = key_events()->at(0);
+ VerifyKeyEvent(&down_event, KeyboardCode::VKEY_MENU, dom_code, true, false);
+ ASSERT_FALSE(down_event.IsControlDown());
+ ASSERT_TRUE(down_event.IsAltDown());
+ ASSERT_FALSE(down_event.IsCommandDown());
+
+ KeyEvent up_event = key_events()->at(1);
+ VerifyKeyEvent(&up_event, KeyboardCode::VKEY_MENU, dom_code, false, false);
+ ASSERT_FALSE(up_event.IsAltDown());
+}
+
+TEST_F(KeyboardHookWinTest, RepeatingRightAltKeypressTest) {
+ const int repeat_count = 10;
+ const KeyboardCode key_code = KeyboardCode::VKEY_RMENU;
+ const DomCode dom_code = DomCode::ALT_RIGHT;
+ SendModifierKeyDownEvent(key_code, dom_code, repeat_count);
+ ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count);
+ SendModifierKeyUpEvent(key_code, dom_code);
+ ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count + 1);
+
+ bool should_repeat = false;
+ for (int i = 0; i < repeat_count; i++) {
+ KeyEvent event = key_events()->at(i);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, dom_code, true,
+ should_repeat);
+ ASSERT_FALSE(event.IsControlDown());
+ ASSERT_TRUE(event.IsAltDown());
+ ASSERT_FALSE(event.IsCommandDown());
+ should_repeat = true;
+ }
+
+ KeyEvent up_event = key_events()->at(repeat_count);
+ VerifyKeyEvent(&up_event, KeyboardCode::VKEY_MENU, dom_code, false, false);
+ ASSERT_FALSE(up_event.IsAltDown());
+}
+
+TEST_F(KeyboardHookWinTest, SimpleLifoAltSequenceTest) {
+ const KeyboardCode left_key_code = KeyboardCode::VKEY_LMENU;
+ const DomCode left_dom_code = DomCode::ALT_LEFT;
+ const KeyboardCode right_key_code = KeyboardCode::VKEY_RMENU;
+ const DomCode right_dom_code = DomCode::ALT_RIGHT;
+ SendModifierKeyDownEvent(left_key_code, left_dom_code, 2);
+ SendModifierKeyDownEvent(right_key_code, right_dom_code, 2);
+ SendModifierKeyUpEvent(right_key_code, right_dom_code);
+ SendModifierKeyUpEvent(left_key_code, left_dom_code);
+ ASSERT_EQ(key_events()->size(), 6ULL);
+
+ // First key down, no repeat.
+ KeyEvent event = key_events()->at(0);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, left_dom_code, true, false);
+ ASSERT_TRUE(event.IsAltDown());
+
+ // First key still down, repeat.
+ event = key_events()->at(1);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, left_dom_code, true, true);
+ ASSERT_TRUE(event.IsAltDown());
+
+ // Second key down, repeat.
+ event = key_events()->at(2);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, right_dom_code, true, true);
+ ASSERT_TRUE(event.IsAltDown());
+
+ // Second key still down, repeat.
+ event = key_events()->at(3);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, right_dom_code, true, true);
+ ASSERT_TRUE(event.IsAltDown());
+
+ // Second key up.
+ event = key_events()->at(4);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, right_dom_code, false, false);
+ ASSERT_TRUE(event.IsAltDown());
+
+ // First key up.
+ event = key_events()->at(5);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, left_dom_code, false, false);
+ ASSERT_FALSE(event.IsAltDown());
+}
+
+TEST_F(KeyboardHookWinTest, SimpleFifoAltSequenceTest) {
+ const KeyboardCode left_key_code = KeyboardCode::VKEY_LMENU;
+ const DomCode left_dom_code = DomCode::ALT_LEFT;
+ const KeyboardCode right_key_code = KeyboardCode::VKEY_RMENU;
+ const DomCode right_dom_code = DomCode::ALT_RIGHT;
+ SendModifierKeyDownEvent(right_key_code, right_dom_code, 2);
+ SendModifierKeyDownEvent(left_key_code, left_dom_code, 2);
+ SendModifierKeyUpEvent(right_key_code, right_dom_code);
+ SendModifierKeyUpEvent(left_key_code, left_dom_code);
+ ASSERT_EQ(key_events()->size(), 6ULL);
+
+ // First key down, no repeat.
+ KeyEvent event = key_events()->at(0);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, right_dom_code, true, false);
+ ASSERT_TRUE(event.IsAltDown());
+
+ // First key still down, repeat.
+ event = key_events()->at(1);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, right_dom_code, true, true);
+ ASSERT_TRUE(event.IsAltDown());
+
+ // Second key down, repeat.
+ event = key_events()->at(2);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, left_dom_code, true, true);
+ ASSERT_TRUE(event.IsAltDown());
+
+ // Second key still down, repeat.
+ event = key_events()->at(3);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, left_dom_code, true, true);
+ ASSERT_TRUE(event.IsAltDown());
+
+ // First key up.
+ event = key_events()->at(4);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, right_dom_code, false, false);
+ ASSERT_TRUE(event.IsAltDown());
+
+ // Second key up.
+ event = key_events()->at(5);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, left_dom_code, false, false);
+ ASSERT_FALSE(event.IsAltDown());
+}
+
+TEST_F(KeyboardHookWinTest, SimpleLeftWinKeypressTest) {
+ const KeyboardCode key_code = KeyboardCode::VKEY_LWIN;
+ const DomCode dom_code = DomCode::META_LEFT;
+ SendModifierKeyDownEvent(key_code, dom_code);
+ ASSERT_EQ(key_events()->size(), 1ULL);
+ SendModifierKeyUpEvent(key_code, dom_code);
+ ASSERT_EQ(key_events()->size(), 2ULL);
+
+ KeyEvent down_event = key_events()->at(0);
+ // VKEY_LWIN is the 'non-located' version of the Windows key.
+ VerifyKeyEvent(&down_event, KeyboardCode::VKEY_LWIN, dom_code, true, false);
+ ASSERT_FALSE(down_event.IsControlDown());
+ ASSERT_FALSE(down_event.IsAltDown());
+ ASSERT_TRUE(down_event.IsCommandDown());
+
+ KeyEvent up_event = key_events()->at(1);
+ VerifyKeyEvent(&up_event, KeyboardCode::VKEY_LWIN, dom_code, false, false);
+ ASSERT_FALSE(up_event.IsCommandDown());
+}
+
+TEST_F(KeyboardHookWinTest, RepeatingLeftWinKeypressTest) {
+ const int repeat_count = 10;
+ const KeyboardCode key_code = KeyboardCode::VKEY_LWIN;
+ const DomCode dom_code = DomCode::META_LEFT;
+ SendModifierKeyDownEvent(key_code, dom_code, repeat_count);
+ ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count);
+ SendModifierKeyUpEvent(key_code, dom_code);
+ ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count + 1);
+
+ bool should_repeat = false;
+ for (int i = 0; i < repeat_count; i++) {
+ KeyEvent event = key_events()->at(i);
+ // VKEY_LWIN is the 'non-located' version of the Windows key.
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_LWIN, dom_code, true,
+ should_repeat);
+ ASSERT_FALSE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_TRUE(event.IsCommandDown());
+ should_repeat = true;
+ }
+
+ KeyEvent up_event = key_events()->at(repeat_count);
+ VerifyKeyEvent(&up_event, KeyboardCode::VKEY_LWIN, dom_code, false, false);
+ ASSERT_FALSE(up_event.IsCommandDown());
+}
+
+TEST_F(KeyboardHookWinTest, SimpleRightWinKeypressTest) {
+ const KeyboardCode key_code = KeyboardCode::VKEY_RWIN;
+ const DomCode dom_code = DomCode::META_RIGHT;
+ SendModifierKeyDownEvent(key_code, dom_code);
+ ASSERT_EQ(key_events()->size(), 1ULL);
+ SendModifierKeyUpEvent(key_code, dom_code);
+ ASSERT_EQ(key_events()->size(), 2ULL);
+
+ KeyEvent down_event = key_events()->at(0);
+ // VKEY_LWIN is the 'non-located' version of the Windows key.
+ VerifyKeyEvent(&down_event, KeyboardCode::VKEY_RWIN, dom_code, true, false);
+ ASSERT_FALSE(down_event.IsControlDown());
+ ASSERT_FALSE(down_event.IsAltDown());
+ ASSERT_TRUE(down_event.IsCommandDown());
+
+ KeyEvent up_event = key_events()->at(1);
+ VerifyKeyEvent(&up_event, KeyboardCode::VKEY_RWIN, dom_code, false, false);
+ ASSERT_FALSE(up_event.IsCommandDown());
+}
+
+TEST_F(KeyboardHookWinTest, RepeatingRightWinKeypressTest) {
+ const int repeat_count = 10;
+ const KeyboardCode key_code = KeyboardCode::VKEY_RWIN;
+ const DomCode dom_code = DomCode::META_RIGHT;
+ SendModifierKeyDownEvent(key_code, dom_code, repeat_count);
+ ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count);
+ SendModifierKeyUpEvent(key_code, dom_code);
+ ASSERT_EQ(static_cast<int>(key_events()->size()), repeat_count + 1);
+
+ bool should_repeat = false;
+ for (int i = 0; i < repeat_count; i++) {
+ KeyEvent event = key_events()->at(i);
+ // VKEY_LWIN is the 'non-located' version of the Windows key.
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_RWIN, dom_code, true,
+ should_repeat);
+ ASSERT_FALSE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_TRUE(event.IsCommandDown());
+ should_repeat = true;
+ }
+
+ KeyEvent up_event = key_events()->at(repeat_count);
+ VerifyKeyEvent(&up_event, KeyboardCode::VKEY_RWIN, dom_code, false, false);
+ ASSERT_FALSE(up_event.IsCommandDown());
+}
+
+TEST_F(KeyboardHookWinTest, SimpleLifoWinSequenceTest) {
+ const KeyboardCode left_key_code = KeyboardCode::VKEY_LWIN;
+ const DomCode left_dom_code = DomCode::META_LEFT;
+ const KeyboardCode right_key_code = KeyboardCode::VKEY_RWIN;
+ const DomCode right_dom_code = DomCode::META_RIGHT;
+ SendModifierKeyDownEvent(left_key_code, left_dom_code, 2);
+ SendModifierKeyDownEvent(right_key_code, right_dom_code, 2);
+ SendModifierKeyUpEvent(right_key_code, right_dom_code);
+ SendModifierKeyUpEvent(left_key_code, left_dom_code);
+ ASSERT_EQ(key_events()->size(), 6ULL);
+
+ // First key down, no repeat.
+ KeyEvent event = key_events()->at(0);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_LWIN, left_dom_code, true, false);
+ ASSERT_TRUE(event.IsCommandDown());
+
+ // First key still down, repeat.
+ event = key_events()->at(1);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_LWIN, left_dom_code, true, true);
+ ASSERT_TRUE(event.IsCommandDown());
+
+ // Second key down, no repeat.
+ event = key_events()->at(2);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_RWIN, right_dom_code, true, false);
+ ASSERT_TRUE(event.IsCommandDown());
+
+ // Second key still down, repeat.
+ event = key_events()->at(3);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_RWIN, right_dom_code, true, true);
+ ASSERT_TRUE(event.IsCommandDown());
+
+ // Second key up.
+ event = key_events()->at(4);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_RWIN, right_dom_code, false, false);
+ ASSERT_TRUE(event.IsCommandDown());
+
+ // First key up.
+ event = key_events()->at(5);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_LWIN, left_dom_code, false, false);
+ ASSERT_FALSE(event.IsCommandDown());
+}
+
+TEST_F(KeyboardHookWinTest, SimpleFifoWinSequenceTest) {
+ const KeyboardCode left_key_code = KeyboardCode::VKEY_LWIN;
+ const DomCode left_dom_code = DomCode::META_LEFT;
+ const KeyboardCode right_key_code = KeyboardCode::VKEY_RWIN;
+ const DomCode right_dom_code = DomCode::META_RIGHT;
+ SendModifierKeyDownEvent(right_key_code, right_dom_code, 2);
+ SendModifierKeyDownEvent(left_key_code, left_dom_code, 2);
+ SendModifierKeyUpEvent(right_key_code, right_dom_code);
+ SendModifierKeyUpEvent(left_key_code, left_dom_code);
+ ASSERT_EQ(key_events()->size(), 6ULL);
+
+ // First key down, no repeat.
+ KeyEvent event = key_events()->at(0);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_RWIN, right_dom_code, true, false);
+ ASSERT_TRUE(event.IsCommandDown());
+
+ // First key still down, repeat.
+ event = key_events()->at(1);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_RWIN, right_dom_code, true, true);
+ ASSERT_TRUE(event.IsCommandDown());
+
+ // Second key down, no repeat.
+ event = key_events()->at(2);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_LWIN, left_dom_code, true, false);
+ ASSERT_TRUE(event.IsCommandDown());
+
+ // Second key still down, repeat.
+ event = key_events()->at(3);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_LWIN, left_dom_code, true, true);
+ ASSERT_TRUE(event.IsCommandDown());
+
+ // First key up.
+ event = key_events()->at(4);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_RWIN, right_dom_code, false, false);
+ ASSERT_TRUE(event.IsCommandDown());
+
+ // Second key up.
+ event = key_events()->at(5);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_LWIN, left_dom_code, false, false);
+ ASSERT_FALSE(event.IsCommandDown());
+}
+
+TEST_F(KeyboardHookWinTest, CombinedModifierLifoSequenceKeypressTest) {
+ const KeyboardCode first_key_code = KeyboardCode::VKEY_LCONTROL;
+ const DomCode first_dom_code = DomCode::CONTROL_LEFT;
+ const KeyboardCode second_key_code = KeyboardCode::VKEY_RWIN;
+ const DomCode second_dom_code = DomCode::META_RIGHT;
+ const KeyboardCode third_key_code = KeyboardCode::VKEY_LMENU;
+ const DomCode third_dom_code = DomCode::ALT_LEFT;
+ SendModifierKeyDownEvent(first_key_code, first_dom_code, 2);
+ SendModifierKeyDownEvent(second_key_code, second_dom_code, 2);
+ SendModifierKeyDownEvent(third_key_code, third_dom_code, 2);
+ SendModifierKeyUpEvent(third_key_code, third_dom_code);
+ SendModifierKeyUpEvent(second_key_code, second_dom_code);
+ SendModifierKeyUpEvent(first_key_code, first_dom_code);
+ ASSERT_EQ(key_events()->size(), 9ULL);
+
+ // First key down, no repeat.
+ KeyEvent event = key_events()->at(0);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, first_dom_code, true,
+ false);
+ ASSERT_TRUE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_FALSE(event.IsCommandDown());
+
+ // First key still down, repeat.
+ event = key_events()->at(1);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, first_dom_code, true,
+ true);
+ ASSERT_TRUE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_FALSE(event.IsCommandDown());
+
+ // Second key down, no repeat.
+ event = key_events()->at(2);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_RWIN, second_dom_code, true, false);
+ ASSERT_TRUE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_TRUE(event.IsCommandDown());
+
+ // Second key still down, repeat.
+ event = key_events()->at(3);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_RWIN, second_dom_code, true, true);
+ ASSERT_TRUE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_TRUE(event.IsCommandDown());
+
+ // Third key down, no repeat.
+ event = key_events()->at(4);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, third_dom_code, true, false);
+ ASSERT_TRUE(event.IsControlDown());
+ ASSERT_TRUE(event.IsAltDown());
+ ASSERT_TRUE(event.IsCommandDown());
+
+ // Third key still down, repeat.
+ event = key_events()->at(5);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, third_dom_code, true, true);
+ ASSERT_TRUE(event.IsControlDown());
+ ASSERT_TRUE(event.IsAltDown());
+ ASSERT_TRUE(event.IsCommandDown());
+
+ // Third key up.
+ event = key_events()->at(6);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, third_dom_code, false, false);
+ ASSERT_TRUE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_TRUE(event.IsCommandDown());
+
+ // Second key up.
+ event = key_events()->at(7);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_RWIN, second_dom_code, false,
+ false);
+ ASSERT_TRUE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_FALSE(event.IsCommandDown());
+
+ // First key up.
+ event = key_events()->at(8);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, first_dom_code, false,
+ false);
+ ASSERT_FALSE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_FALSE(event.IsCommandDown());
+}
+
+TEST_F(KeyboardHookWinTest, CombinedModifierFifoSequenceKeypressTest) {
+ const KeyboardCode first_key_code = KeyboardCode::VKEY_RCONTROL;
+ const DomCode first_dom_code = DomCode::CONTROL_RIGHT;
+ const KeyboardCode second_key_code = KeyboardCode::VKEY_LWIN;
+ const DomCode second_dom_code = DomCode::META_LEFT;
+ const KeyboardCode third_key_code = KeyboardCode::VKEY_RMENU;
+ const DomCode third_dom_code = DomCode::ALT_RIGHT;
+ SendModifierKeyDownEvent(first_key_code, first_dom_code, 2);
+ SendModifierKeyDownEvent(second_key_code, second_dom_code, 2);
+ SendModifierKeyDownEvent(third_key_code, third_dom_code, 2);
+ SendModifierKeyUpEvent(first_key_code, first_dom_code);
+ SendModifierKeyUpEvent(second_key_code, second_dom_code);
+ SendModifierKeyUpEvent(third_key_code, third_dom_code);
+ ASSERT_EQ(key_events()->size(), 9ULL);
+
+ // First key down, no repeat.
+ KeyEvent event = key_events()->at(0);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, first_dom_code, true,
+ false);
+ ASSERT_TRUE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_FALSE(event.IsCommandDown());
+
+ // First key still down, repeat.
+ event = key_events()->at(1);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, first_dom_code, true,
+ true);
+ ASSERT_TRUE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_FALSE(event.IsCommandDown());
+
+ // Second key down, no repeat.
+ event = key_events()->at(2);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_LWIN, second_dom_code, true, false);
+ ASSERT_TRUE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_TRUE(event.IsCommandDown());
+
+ // Second key still down, repeat.
+ event = key_events()->at(3);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_LWIN, second_dom_code, true, true);
+ ASSERT_TRUE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_TRUE(event.IsCommandDown());
+
+ // Third key down, no repeat.
+ event = key_events()->at(4);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, third_dom_code, true, false);
+ ASSERT_TRUE(event.IsControlDown());
+ ASSERT_TRUE(event.IsAltDown());
+ ASSERT_TRUE(event.IsCommandDown());
+
+ // Third key still down, repeat.
+ event = key_events()->at(5);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, third_dom_code, true, true);
+ ASSERT_TRUE(event.IsControlDown());
+ ASSERT_TRUE(event.IsAltDown());
+ ASSERT_TRUE(event.IsCommandDown());
+
+ // First key up.
+ event = key_events()->at(6);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, first_dom_code, false,
+ false);
+ ASSERT_FALSE(event.IsControlDown());
+ ASSERT_TRUE(event.IsAltDown());
+ ASSERT_TRUE(event.IsCommandDown());
+
+ // Second key up.
+ event = key_events()->at(7);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_LWIN, second_dom_code, false,
+ false);
+ ASSERT_FALSE(event.IsControlDown());
+ ASSERT_TRUE(event.IsAltDown());
+ ASSERT_FALSE(event.IsCommandDown());
+
+ // Third key up.
+ event = key_events()->at(8);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, third_dom_code, false, false);
+ ASSERT_FALSE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_FALSE(event.IsCommandDown());
+}
+
+TEST_F(KeyboardHookWinTest, VerifyPlatformModifierStateTest) {
+ SendModifierKeyDownEvent(KeyboardCode::VKEY_LCONTROL, DomCode::CONTROL_LEFT);
+ ASSERT_TRUE(win::IsCtrlPressed());
+ ASSERT_FALSE(win::IsAltPressed());
+ ASSERT_FALSE(win::IsWindowsKeyPressed());
+
+ SendModifierKeyDownEvent(KeyboardCode::VKEY_RWIN, DomCode::META_RIGHT);
+ ASSERT_TRUE(win::IsCtrlPressed());
+ ASSERT_FALSE(win::IsAltPressed());
+ ASSERT_TRUE(win::IsWindowsKeyPressed());
+
+ SendModifierKeyDownEvent(KeyboardCode::VKEY_LMENU, DomCode::ALT_LEFT);
+ ASSERT_TRUE(win::IsCtrlPressed());
+ ASSERT_TRUE(win::IsAltPressed());
+ ASSERT_FALSE(win::IsAltRightPressed());
+ ASSERT_TRUE(win::IsWindowsKeyPressed());
+
+ SendModifierKeyUpEvent(KeyboardCode::VKEY_RWIN, DomCode::META_RIGHT);
+ ASSERT_TRUE(win::IsCtrlPressed());
+ ASSERT_TRUE(win::IsAltPressed());
+ ASSERT_FALSE(win::IsWindowsKeyPressed());
+
+ SendModifierKeyUpEvent(KeyboardCode::VKEY_LCONTROL, DomCode::CONTROL_LEFT);
+ ASSERT_FALSE(win::IsCtrlPressed());
+ ASSERT_TRUE(win::IsAltPressed());
+ ASSERT_FALSE(win::IsWindowsKeyPressed());
+
+ SendModifierKeyUpEvent(KeyboardCode::VKEY_LMENU, DomCode::ALT_LEFT);
+ ASSERT_FALSE(win::IsCtrlPressed());
+ ASSERT_FALSE(win::IsAltPressed());
+ ASSERT_FALSE(win::IsWindowsKeyPressed());
+
+ SendModifierKeyDownEvent(KeyboardCode::VKEY_RMENU, DomCode::ALT_RIGHT);
+ ASSERT_TRUE(win::IsAltPressed());
+ ASSERT_TRUE(win::IsAltRightPressed());
+}
+
+TEST_F(KeyboardHookWinTest, SimpleAltGrKeyPressTest) {
+ ScopedKeyboardLayout keyboard_layout(KeyboardLayout::KEYBOARD_LAYOUT_GERMAN);
+
+ // AltGr produces two events, an injected, modified scan code for VK_LCONTROL,
+ // and an event for VK_RMENU. We simulate that sequence here.
+ const KeyboardCode altgr_key_code = KeyboardCode::VKEY_RMENU;
+ const DomCode altgr_dom_code = DomCode::ALT_RIGHT;
+ const DomCode control_dom_code = DomCode::CONTROL_LEFT;
+ const DWORD control_scan_code =
+ KeycodeConverter::DomCodeToNativeKeycode(control_dom_code);
+ const DWORD injected_control_scan_code = control_scan_code | 0x0200;
+
+ ASSERT_TRUE(keyboard_hook()->ProcessKeyEventMessage(
+ WM_KEYDOWN, KeyboardCode::VKEY_LCONTROL, injected_control_scan_code,
+ next_time_stamp()));
+ SendModifierKeyDownEvent(altgr_key_code, altgr_dom_code);
+
+ ASSERT_TRUE(keyboard_hook()->ProcessKeyEventMessage(
+ WM_KEYUP, KeyboardCode::VKEY_LCONTROL,
+ KeycodeConverter::DomCodeToNativeKeycode(control_dom_code),
+ next_time_stamp()));
+ SendModifierKeyUpEvent(altgr_key_code, altgr_dom_code);
+ ASSERT_EQ(key_events()->size(), 4ULL);
+
+ // Injected control key down, no repeat.
+ KeyEvent event = key_events()->at(0);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, control_dom_code, true,
+ false);
+ ASSERT_TRUE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_FALSE(event.IsAltGrDown());
+ ASSERT_FALSE(event.IsCommandDown());
+
+ // Altgr key down.
+ event = key_events()->at(1);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, altgr_dom_code, true, false);
+ ASSERT_FALSE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_TRUE(event.IsAltGrDown());
+ ASSERT_FALSE(event.IsCommandDown());
+
+ // Injected control key up.
+ event = key_events()->at(2);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, control_dom_code, false,
+ false);
+ ASSERT_FALSE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_TRUE(event.IsAltGrDown());
+ ASSERT_FALSE(event.IsCommandDown());
+
+ // AltGr key up.
+ event = key_events()->at(3);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, altgr_dom_code, false, false);
+ ASSERT_FALSE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_FALSE(event.IsAltGrDown());
+ ASSERT_FALSE(event.IsCommandDown());
+}
+
+TEST_F(KeyboardHookWinTest, RepeatingAltGrKeyPressTest) {
+ ScopedKeyboardLayout keyboard_layout(KeyboardLayout::KEYBOARD_LAYOUT_GERMAN);
+
+ // AltGr produces two events, an injected, modified scan code for VK_LCONTROL,
+ // and an event for VK_RMENU. This sequence repeats for each repeated key
+ // press. We simulate that sequence here.
+ const KeyboardCode altgr_key_code = KeyboardCode::VKEY_RMENU;
+ const DomCode altgr_dom_code = DomCode::ALT_RIGHT;
+ const DomCode control_dom_code = DomCode::CONTROL_LEFT;
+ const DWORD control_scan_code =
+ KeycodeConverter::DomCodeToNativeKeycode(control_dom_code);
+ const DWORD injected_control_scan_code = control_scan_code | 0x0200;
+
+ ASSERT_TRUE(keyboard_hook()->ProcessKeyEventMessage(
+ WM_KEYDOWN, KeyboardCode::VKEY_LCONTROL, injected_control_scan_code,
+ next_time_stamp()));
+ SendModifierKeyDownEvent(altgr_key_code, altgr_dom_code);
+ ASSERT_TRUE(keyboard_hook()->ProcessKeyEventMessage(
+ WM_KEYDOWN, KeyboardCode::VKEY_LCONTROL, injected_control_scan_code,
+ next_time_stamp()));
+ SendModifierKeyDownEvent(altgr_key_code, altgr_dom_code);
+ ASSERT_TRUE(keyboard_hook()->ProcessKeyEventMessage(
+ WM_KEYDOWN, KeyboardCode::VKEY_LCONTROL, injected_control_scan_code,
+ next_time_stamp()));
+ SendModifierKeyDownEvent(altgr_key_code, altgr_dom_code);
+ ASSERT_TRUE(keyboard_hook()->ProcessKeyEventMessage(
+ WM_KEYUP, KeyboardCode::VKEY_LCONTROL,
+ KeycodeConverter::DomCodeToNativeKeycode(control_dom_code),
+ next_time_stamp()));
+ SendModifierKeyUpEvent(altgr_key_code, altgr_dom_code);
+ ASSERT_EQ(key_events()->size(), 8ULL);
+
+ // Injected control key down, no repeat.
+ KeyEvent event = key_events()->at(0);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, control_dom_code, true,
+ false);
+ ASSERT_TRUE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_FALSE(event.IsAltGrDown());
+ ASSERT_FALSE(event.IsCommandDown());
+
+ // Altgr key down.
+ event = key_events()->at(1);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, altgr_dom_code, true, false);
+ ASSERT_FALSE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_TRUE(event.IsAltGrDown());
+ ASSERT_FALSE(event.IsCommandDown());
+
+ // Injected control key down, repeat.
+ event = key_events()->at(2);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, control_dom_code, true,
+ true);
+ ASSERT_FALSE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_TRUE(event.IsAltGrDown());
+ ASSERT_FALSE(event.IsCommandDown());
+
+ // Altgr key down, repeat.
+ event = key_events()->at(3);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, altgr_dom_code, true, true);
+ ASSERT_FALSE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_TRUE(event.IsAltGrDown());
+ ASSERT_FALSE(event.IsCommandDown());
+
+ // Injected control key down, repeat.
+ event = key_events()->at(4);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, control_dom_code, true,
+ true);
+ ASSERT_FALSE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_TRUE(event.IsAltGrDown());
+ ASSERT_FALSE(event.IsCommandDown());
+
+ // Altgr key down, repeat.
+ event = key_events()->at(5);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, altgr_dom_code, true, true);
+ ASSERT_FALSE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_TRUE(event.IsAltGrDown());
+ ASSERT_FALSE(event.IsCommandDown());
+
+ // Injected control key up.
+ event = key_events()->at(6);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_CONTROL, control_dom_code, false,
+ false);
+ ASSERT_FALSE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_TRUE(event.IsAltGrDown());
+ ASSERT_FALSE(event.IsCommandDown());
+
+ // AltGr key up.
+ event = key_events()->at(7);
+ VerifyKeyEvent(&event, KeyboardCode::VKEY_MENU, altgr_dom_code, false, false);
+ ASSERT_FALSE(event.IsControlDown());
+ ASSERT_FALSE(event.IsAltDown());
+ ASSERT_FALSE(event.IsAltGrDown());
+ ASSERT_FALSE(event.IsCommandDown());
+}
+
+TEST_F(KeyboardHookWinTest, VerifyAltGrPlatformModifierStateTest) {
+ ScopedKeyboardLayout keyboard_layout(KeyboardLayout::KEYBOARD_LAYOUT_GERMAN);
+
+ // AltGr produces two events, an injected, modified scan code for VK_LCONTROL,
+ // and an event for VK_RMENU. We simulate that sequence here.
+ const KeyboardCode altgr_key_code = KeyboardCode::VKEY_RMENU;
+ const DomCode altgr_dom_code = DomCode::ALT_RIGHT;
+ const DomCode control_dom_code = DomCode::CONTROL_LEFT;
+ const DWORD control_scan_code =
+ KeycodeConverter::DomCodeToNativeKeycode(control_dom_code);
+ const DWORD injected_control_scan_code = control_scan_code | 0x0200;
+
+ ASSERT_TRUE(keyboard_hook()->ProcessKeyEventMessage(
+ WM_KEYDOWN, KeyboardCode::VKEY_LCONTROL, injected_control_scan_code,
+ next_time_stamp()));
+ ASSERT_TRUE(win::IsCtrlPressed());
+ ASSERT_FALSE(win::IsAltPressed());
+ ASSERT_FALSE(win::IsAltRightPressed());
+ ASSERT_FALSE(win::IsWindowsKeyPressed());
+
+ SendModifierKeyDownEvent(altgr_key_code, altgr_dom_code);
+ ASSERT_TRUE(win::IsCtrlPressed());
+ ASSERT_TRUE(win::IsAltPressed());
+ ASSERT_TRUE(win::IsAltRightPressed());
+ ASSERT_FALSE(win::IsWindowsKeyPressed());
+
+ ASSERT_TRUE(keyboard_hook()->ProcessKeyEventMessage(
+ WM_KEYUP, KeyboardCode::VKEY_LCONTROL,
+ KeycodeConverter::DomCodeToNativeKeycode(control_dom_code),
+ next_time_stamp()));
+ ASSERT_FALSE(win::IsCtrlPressed());
+ ASSERT_TRUE(win::IsAltPressed());
+ ASSERT_TRUE(win::IsAltRightPressed());
+ ASSERT_FALSE(win::IsWindowsKeyPressed());
+
+ SendModifierKeyUpEvent(altgr_key_code, altgr_dom_code);
+ ASSERT_FALSE(win::IsCtrlPressed());
+ ASSERT_FALSE(win::IsAltPressed());
+ ASSERT_FALSE(win::IsAltRightPressed());
+ ASSERT_FALSE(win::IsWindowsKeyPressed());
+}
+
+TEST_F(KeyboardHookWinTest, NonInterceptedKeysTest) {
+ // Here we try a few keys we do not expect to be intercepted / handled.
+ ASSERT_FALSE(keyboard_hook()->ProcessKeyEventMessage(
+ WM_KEYDOWN, KeyboardCode::VKEY_RSHIFT,
+ KeycodeConverter::DomCodeToNativeKeycode(DomCode::SHIFT_RIGHT),
+ next_time_stamp()));
+ ASSERT_FALSE(keyboard_hook()->ProcessKeyEventMessage(
+ WM_KEYUP, KeyboardCode::VKEY_RSHIFT,
+ KeycodeConverter::DomCodeToNativeKeycode(DomCode::SHIFT_RIGHT),
+ next_time_stamp()));
+
+ ASSERT_FALSE(keyboard_hook()->ProcessKeyEventMessage(
+ WM_KEYDOWN, KeyboardCode::VKEY_MEDIA_PLAY_PAUSE,
+ KeycodeConverter::DomCodeToNativeKeycode(DomCode::MEDIA_PLAY_PAUSE),
+ next_time_stamp()));
+ ASSERT_FALSE(keyboard_hook()->ProcessKeyEventMessage(
+ WM_KEYUP, KeyboardCode::VKEY_MEDIA_PLAY_PAUSE,
+ KeycodeConverter::DomCodeToNativeKeycode(DomCode::MEDIA_PLAY_PAUSE),
+ next_time_stamp()));
+
+ ASSERT_FALSE(keyboard_hook()->ProcessKeyEventMessage(
+ WM_KEYDOWN, KeyboardCode::VKEY_A,
+ KeycodeConverter::DomCodeToNativeKeycode(DomCode::US_A),
+ next_time_stamp()));
+ ASSERT_FALSE(keyboard_hook()->ProcessKeyEventMessage(
+ WM_KEYUP, KeyboardCode::VKEY_A,
+ KeycodeConverter::DomCodeToNativeKeycode(DomCode::US_A),
+ next_time_stamp()));
+}
+
+} // namespace ui
diff --git a/chromium/ui/events/x/events_x.cc b/chromium/ui/events/x/events_x.cc
index b8df7b02091..62530318bc2 100644
--- a/chromium/ui/events/x/events_x.cc
+++ b/chromium/ui/events/x/events_x.cc
@@ -81,9 +81,7 @@ int EventFlagsFromNative(const PlatformEvent& native_event) {
}
base::TimeTicks EventTimeFromNative(const PlatformEvent& native_event) {
- base::TimeTicks timestamp = EventTimeFromXEvent(*native_event);
- ValidateEventTimeClock(&timestamp);
- return timestamp;
+ return EventTimeFromXEvent(*native_event);
}
gfx::PointF EventLocationFromNative(const PlatformEvent& native_event) {
diff --git a/chromium/ui/events/x/events_x_unittest.cc b/chromium/ui/events/x/events_x_unittest.cc
index 897c5c5cb94..3419309a22a 100644
--- a/chromium/ui/events/x/events_x_unittest.cc
+++ b/chromium/ui/events/x/events_x_unittest.cc
@@ -76,6 +76,15 @@ float ComputeRotationAngle(float twist) {
return rotation_angle;
}
+class MockTimestampServer : public ui::TimestampServer {
+ public:
+ Time GetCurrentServerTime() override { return base_time_; }
+ void SetBaseTime(Time time) { base_time_ = time; }
+
+ private:
+ Time base_time_ = 0;
+};
+
} // namespace
class EventsXTest : public testing::Test {
@@ -84,13 +93,15 @@ class EventsXTest : public testing::Test {
~EventsXTest() override {}
void SetUp() override {
+ SetTimestampServer(&server_);
DeviceDataManagerX11::CreateInstance();
ui::TouchFactory::GetInstance()->ResetForTest();
- ResetTimestampRolloverCountersForTesting();
}
- void TearDown() override { ResetTimestampRolloverCountersForTesting(); }
+
+ void TearDown() override { SetTimestampServer(nullptr); }
private:
+ MockTimestampServer server_;
DISALLOW_COPY_AND_ASSIGN(EventsXTest);
};
@@ -542,52 +553,4 @@ TEST_F(EventsXTest, IgnoresMotionEventForMouseWheelScroll) {
EXPECT_EQ(ui::ET_UNKNOWN, ui::EventTypeFromNative(xev));
}
-namespace {
-
-// Returns a fake TimeTicks based on the given millisecond offset.
-base::TimeTicks TimeTicksFromMillis(int64_t millis) {
- return base::TimeTicks() + base::TimeDelta::FromMilliseconds(millis);
-}
-
-} // namespace
-
-TEST_F(EventsXTest, TimestampRolloverAndAdjustWhenDecreasing) {
- XEvent event;
- InitButtonEvent(&event, true, gfx::Point(5, 10), 1, 0);
-
- test::ScopedEventTestTickClock clock;
- clock.SetNowTicks(TimeTicksFromMillis(0x100000001));
- ResetTimestampRolloverCountersForTesting();
-
- event.xbutton.time = 0xFFFFFFFF;
- EXPECT_EQ(TimeTicksFromMillis(0xFFFFFFFF), ui::EventTimeFromNative(&event));
-
- clock.SetNowTicks(TimeTicksFromMillis(0x100000007));
- ResetTimestampRolloverCountersForTesting();
-
- event.xbutton.time = 3;
- EXPECT_EQ(TimeTicksFromMillis(0x100000000 + 3),
- ui::EventTimeFromNative(&event));
-}
-
-TEST_F(EventsXTest, NoTimestampRolloverWhenMonotonicIncreasing) {
- XEvent event;
- InitButtonEvent(&event, true, gfx::Point(5, 10), 1, 0);
-
- test::ScopedEventTestTickClock clock;
- clock.SetNowTicks(TimeTicksFromMillis(10));
- ResetTimestampRolloverCountersForTesting();
-
- event.xbutton.time = 6;
- EXPECT_EQ(TimeTicksFromMillis(6), ui::EventTimeFromNative(&event));
- event.xbutton.time = 7;
- EXPECT_EQ(TimeTicksFromMillis(7), ui::EventTimeFromNative(&event));
-
- clock.SetNowTicks(TimeTicksFromMillis(0x100000005));
- ResetTimestampRolloverCountersForTesting();
-
- event.xbutton.time = 0xFFFFFFFF;
- EXPECT_EQ(TimeTicksFromMillis(0xFFFFFFFF), ui::EventTimeFromNative(&event));
-}
-
} // namespace ui
diff --git a/chromium/ui/events/x/events_x_utils.cc b/chromium/ui/events/x/events_x_utils.cc
index 86fbd1937c6..8dec888198a 100644
--- a/chromium/ui/events/x/events_x_utils.cc
+++ b/chromium/ui/events/x/events_x_utils.cc
@@ -27,6 +27,25 @@
namespace {
+ui::TimestampServer* g_timestamp_server = nullptr;
+bool g_use_fixed_time_for_testing = false;
+
+// Clamps a TimeDelta to be within [-30 seconds, 30 seconds].
+base::TimeDelta ClampDeltaFromExternalSource(const base::TimeDelta& delta) {
+ // Ignore pathologically long deltas. External source is probably having
+ // issues.
+ constexpr base::TimeDelta pathologically_long_duration =
+ base::TimeDelta::FromSeconds(30);
+ if (delta > pathologically_long_duration)
+ return base::TimeDelta();
+
+ // Ignore negative deltas. External source is probably having issues.
+ if (delta < -pathologically_long_duration)
+ return base::TimeDelta();
+
+ return delta;
+}
+
// Scroll amount for each wheelscroll event. 53 is also the value used for GTK+.
const int kWheelScrollAmount = 53;
@@ -308,40 +327,36 @@ bool GetGestureTimes(const XEvent& xev, double* start_time, double* end_time) {
return true;
}
-int64_t g_last_seen_timestamp_ms = 0;
-int64_t g_rollover_ms = 0;
-
-// Takes Xlib Time and returns a time delta that is immune to timer rollover.
-// This function is not thread safe as we do not use a lock.
base::TimeTicks TimeTicksFromXEventTime(Time timestamp) {
- int64_t timestamp64 = timestamp;
-
- if (!timestamp)
- return ui::EventTimeForNow();
-
- // If this is the first event that we get, assume the time stamp roll-over
- // might have happened before the process was started.
- // Register a rollover if the distance between last timestamp and current one
- // is larger than half the width. This avoids false rollovers even in a case
- // where X server delivers reasonably close events out-of-order.
- bool had_recent_rollover =
- !g_last_seen_timestamp_ms ||
- g_last_seen_timestamp_ms - timestamp64 > (UINT32_MAX >> 1);
-
- g_last_seen_timestamp_ms = timestamp64;
- if (!had_recent_rollover)
- return base::TimeTicks() +
- base::TimeDelta::FromMilliseconds(g_rollover_ms + timestamp);
-
- DCHECK(timestamp64 <= UINT32_MAX)
- << "X11 Time does not roll over 32 bit, the below logic is likely wrong";
-
- base::TimeTicks now_ticks = ui::EventTimeForNow();
- int64_t now_ms = (now_ticks - base::TimeTicks()).InMilliseconds();
-
- g_rollover_ms = now_ms & ~static_cast<int64_t>(UINT32_MAX);
- uint32_t delta = static_cast<uint32_t>(now_ms - timestamp);
- return base::TimeTicks() + base::TimeDelta::FromMilliseconds(now_ms - delta);
+ // There's no way to convert from an X time to a base::TimeTicks without
+ // knowing the current X server time.
+ if (!g_timestamp_server)
+ return base::TimeTicks();
+
+ // X11 uses a uint32_t on the wire protocol. Xlib casts this to an unsigned
+ // long by prepending with 0s. We cast back to a uint32_t so that subtraction
+ // works properly when the timestamp overflows back to 0.
+ uint32_t event_server_time_ms = static_cast<uint32_t>(timestamp);
+ uint32_t current_server_time_ms =
+ static_cast<uint32_t>(g_timestamp_server->GetCurrentServerTime());
+
+ // On X11, event times are in X11 Server time. To convert to base::TimeTicks,
+ // we perform a round-trip to the X11 Server, subtract the two times to get a
+ // TimeDelta, and then subtract that from base::TimeTicks::Now(). Since we're
+ // working with units of time from an external source, we clamp the TimeDelta
+ // to reasonable values.
+ int64_t delta_ms = static_cast<int64_t>(current_server_time_ms) -
+ static_cast<int64_t>(event_server_time_ms);
+ base::TimeDelta delta = base::TimeDelta::FromMilliseconds(delta_ms);
+ base::TimeDelta sanitized = ClampDeltaFromExternalSource(delta);
+
+ base::TimeTicks now;
+ if (g_use_fixed_time_for_testing)
+ now = base::TimeTicks() + base::TimeDelta::FromDays(1);
+ else
+ now = base::TimeTicks::Now();
+
+ return now - sanitized;
}
} // namespace
@@ -831,9 +846,16 @@ bool IsAltPressed() {
return XModifierStateWatcher::GetInstance()->state() & Mod1Mask;
}
-void ResetTimestampRolloverCountersForTesting() {
- g_last_seen_timestamp_ms = 0;
- g_rollover_ms = 0;
+void SetTimestampServer(TimestampServer* server) {
+ // This method must be setting or unsetting a timestamp server. It should
+ // never replace an existing timestamp server, nor change from
+ // nullptr->nullptr.
+ CHECK(!!g_timestamp_server ^ !!server);
+ g_timestamp_server = server;
+}
+
+void SetUseFixedTimeForXEventTesting(bool use_fixed_time) {
+ g_use_fixed_time_for_testing = use_fixed_time;
}
} // namespace ui
diff --git a/chromium/ui/events/x/events_x_utils.h b/chromium/ui/events/x/events_x_utils.h
index 64814e87715..ad11a08a17a 100644
--- a/chromium/ui/events/x/events_x_utils.h
+++ b/chromium/ui/events/x/events_x_utils.h
@@ -16,6 +16,8 @@
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/x/x11_types.h"
+using Time = unsigned long;
+
namespace ui {
// Gets the EventType from a XEvent.
@@ -91,6 +93,18 @@ EVENTS_X_EXPORT bool IsAltPressed();
EVENTS_X_EXPORT void ResetTimestampRolloverCountersForTesting();
+// Conversion from X Time to base::TimeTicks requires checking the current X
+// Server Time. This functionality is provided by X11EventSource, but due to odd
+// layering that cannot be referenced directly.
+class TimestampServer {
+ public:
+ virtual Time GetCurrentServerTime() = 0;
+};
+EVENTS_X_EXPORT void SetTimestampServer(TimestampServer* server);
+
+// Allows tests to force a fixed time..
+EVENTS_X_EXPORT void SetUseFixedTimeForXEventTesting(bool use_fixed_time);
+
} // namespace ui
#endif // UI_EVENTS_X_EVENTS_X_UTILS_H_
diff --git a/chromium/ui/file_manager/BUILD.gn b/chromium/ui/file_manager/BUILD.gn
index 01983b819db..99433199a4b 100644
--- a/chromium/ui/file_manager/BUILD.gn
+++ b/chromium/ui/file_manager/BUILD.gn
@@ -33,6 +33,7 @@ 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/foreground/elements:closure_compile",
@@ -50,7 +51,10 @@ group("closure_compile") {
group("unit_test_data") {
deps = [
+ "file_manager/common/js:unit_tests",
+ "file_manager/foreground/js:unit_tests",
"gallery/js:unit_tests",
"gallery/js/image_editor:unit_tests",
+ "image_loader:unit_tests",
]
}
diff --git a/chromium/ui/file_manager/audio_player/js/BUILD.gn b/chromium/ui/file_manager/audio_player/js/BUILD.gn
index 2225d46efb7..89c18c22f10 100644
--- a/chromium/ui/file_manager/audio_player/js/BUILD.gn
+++ b/chromium/ui/file_manager/audio_player/js/BUILD.gn
@@ -18,10 +18,8 @@ js_library("closure_compile_externs") {
sources = []
externs_list = [
"$externs_path/chrome_extensions.js",
- "$externs_path/command_line_private.js",
"$externs_path/metrics_private.js",
"../../externs/audio_player_foreground.js",
- "../../externs/entry_location.js",
"../../externs/platform.js",
"//third_party/analytics/externs.js",
]
@@ -29,12 +27,12 @@ js_library("closure_compile_externs") {
js_library("audio_player") {
deps = [
- "../../file_manager/common/js:util",
- "../../file_manager/foreground/js:volume_manager_wrapper",
- "../../file_manager/foreground/js/metadata:content_metadata_provider",
- "../../file_manager/foreground/js/metadata:metadata_model",
"../elements:audio_player",
"../elements:track_list",
+ "//ui/file_manager/base/js:filtered_volume_manager",
+ "//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",
]
}
diff --git a/chromium/ui/file_manager/base/js/BUILD.gn b/chromium/ui/file_manager/base/js/BUILD.gn
new file mode 100644
index 00000000000..b71798141bb
--- /dev/null
+++ b/chromium/ui/file_manager/base/js/BUILD.gn
@@ -0,0 +1,27 @@
+# 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/*" ]
+
+js_type_check("closure_compile") {
+ deps = [
+ ":filtered_volume_manager",
+ ]
+}
+
+js_library("filtered_volume_manager") {
+ deps = [
+ "//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/file_manager/file_manager/common/js:volume_manager_common",
+ "//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" ]
+}
diff --git a/chromium/ui/file_manager/externs/BUILD.gn b/chromium/ui/file_manager/externs/BUILD.gn
index 1d7d52ae3dc..dad5e37013e 100644
--- a/chromium/ui/file_manager/externs/BUILD.gn
+++ b/chromium/ui/file_manager/externs/BUILD.gn
@@ -15,3 +15,29 @@ js_library("webview_tag") {
"webview_tag.js",
]
}
+
+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("volume_manager") {
+ sources = []
+
+ # Encapsulate volume_manager.js and its dependencies. Note this should really
+ # depend on volume_manager_common.js as well, but that's not an extern.
+ externs_list = [
+ "entry_location.js",
+ "volume_info.js",
+ "volume_info_list.js",
+ "volume_manager.js",
+ ]
+}
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 d6a933fbfe3..a645f6897d8 100644
--- a/chromium/ui/file_manager/file_manager/background/js/BUILD.gn
+++ b/chromium/ui/file_manager/file_manager/background/js/BUILD.gn
@@ -4,6 +4,22 @@
import("//third_party/closure_compiler/compile_js.gni")
+# TODO(tapted): This folder should be restricted to file_manager, but related
+# apps currently depend on background_base, which depends on
+# volume_manager_factory, and that pulls in nearly everything else. For now,
+# document externally-exposed targets visible with this helper, and hide
+# transitive dependencies (but note those transitive dependencies should move
+# elsewhere too).
+related_apps = [
+ "//ui/file_manager/audio_player/*",
+ "//ui/file_manager/file_manager/*",
+ "//ui/file_manager/gallery/*",
+ "//ui/file_manager/video_player/*",
+]
+
+# Default to private.
+visibility = [ ":*" ]
+
js_type_check("closure_compile") {
deps = [
":app_window_wrapper",
@@ -39,9 +55,6 @@ js_type_check("closure_compile") {
js_library("closure_compile_externs") {
sources = []
externs_list = [
- "$externs_path/command_line_private.js",
- "$externs_path/file_manager_private.js",
- "$externs_path/file_system_provider.js",
"$externs_path/metrics_private.js",
"../../../externs/background/file_browser_background.js",
"../../../externs/background/file_browser_background_full.js",
@@ -62,6 +75,7 @@ js_library("closure_compile_externs") {
}
js_library("app_window_wrapper") {
+ visibility += related_apps
deps = [
":app_windows",
"../../common/js:async_util",
@@ -94,6 +108,7 @@ js_library("background") {
}
js_library("background_base") {
+ visibility += related_apps
deps = [
":app_windows",
":volume_manager_factory",
@@ -211,10 +226,12 @@ js_library("media_scanner") {
}
js_library("mock_volume_manager") {
+ visibility += related_apps
deps = [
":volume_info_impl",
":volume_info_list_impl",
":volume_manager_factory",
+ ":volume_manager_impl",
"../../common/js:mock_entry",
]
}
@@ -236,21 +253,17 @@ js_library("task_queue") {
}
js_library("test_util_base") {
+ # TODO(tapted): Move this target to //ui/file_manager/base. It is used in the
+ # background page of all |related_apps|, but accessed via extension messaging.
+ # So it doesn't need to be visible as a closure dependency, except for the
+ # "unpacked" test framework.
+ visibility += [ "//ui/file_manager/file_manager/test/js:test_util" ]
+
deps = [
":app_windows",
+ "../../../externs:webview_tag",
"../../common/js:error_util",
]
-
- # The callback test_util_base.js passes to chrome.runtime.onMessageExternal()
- # requires chrome_extensions.js, which has a dependency on chrome.js. Ensure
- # the externs are introduced at the same time (in this order). Note we are
- # lucky the list below also sorts in this order, or we'd need some other fix.
- # A compile error results if the dependency walker encounters a target
- # that puts chrome_extensions.js into the argument list before chrome.js.
- externs_list = [
- "$externs_path/chrome.js",
- "$externs_path/chrome_extensions.js",
- ]
}
js_library("volume_info_impl") {
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 506fde5ff24..f4b2fdf8e92 100644
--- a/chromium/ui/file_manager/file_manager/common/js/BUILD.gn
+++ b/chromium/ui/file_manager/file_manager/common/js/BUILD.gn
@@ -3,11 +3,14 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//third_party/closure_compiler/js_unit_tests.gni")
-js_type_check("closure_compile") {
+# TODO(tapted): This entire folder should move to //ui/file_manager/base.
+visibility = [ "//ui/file_manager/*" ]
+
+js_type_check("closure_compile_module") {
deps = [
":async_util",
- ":closure_compile_externs",
":error_util",
":file_type",
":files_app_entry_types",
@@ -24,45 +27,95 @@ js_type_check("closure_compile") {
]
}
-js_library("closure_compile_externs") {
- sources = []
- externs_list = [
- "../../../externs/background/file_browser_background.js",
- "../../../externs/background_window.js",
- ]
+js_library("async_util") {
}
-js_library("async_util") {
+js_library("async_util_unittest") {
+ deps = [
+ ":async_util",
+ ":unittest_util",
+ ]
}
js_library("error_util") {
}
js_library("files_app_entry_types") {
+ deps = [
+ "../../../externs:file_manager_private",
+ ]
externs_list = [ "../../../externs/volume_info.js" ]
}
+js_library("files_app_entry_types_unittest") {
+ deps = [
+ ":files_app_entry_types",
+ ":unittest_util",
+ ":volume_manager_common",
+ ]
+}
+
js_library("file_type") {
+ deps = [
+ ":files_app_entry_types",
+ ":volume_manager_common",
+ ]
}
+# These importer files actually belong here. Nothing outside the Files app uses
+# them, so restrict visibility. TODO(tapted): Simplify visibility when
+# everything else moves to //ui/file_manager/base.
js_library("importer_common") {
+ visibility = []
+ visibility = [ "//ui/file_manager/file_manager/*" ]
deps = [
":file_type",
":volume_manager_common",
+ "../../../externs:volume_manager",
+ ]
+ externs_list = [
+ "//third_party/analytics/externs.js",
+ "../../../externs/volume_info_list.js",
+ "../../../externs/background_window.js",
+ "../../../externs/background/file_browser_background.js",
+ ]
+}
+
+js_library("test_importer_common") {
+ deps = [
+ ":importer_common",
+ ":unittest_util",
+ ]
+ visibility = []
+ visibility = [ "//ui/file_manager/file_manager/*" ]
+}
+
+js_library("importer_common_unittest") {
+ deps = [
+ ":mock_entry",
+ ":test_importer_common",
+ ":util",
+ "//ui/file_manager/file_manager/background/js:mock_volume_manager",
]
}
js_library("lru_cache") {
}
+js_library("lru_cache_unittest") {
+ deps = [
+ ":lru_cache",
+ "//ui/webui/resources/js:webui_resource_test",
+ ]
+}
+
js_library("metrics") {
deps = [
":metrics_base",
+ "../../../externs:file_manager_private",
"//ui/webui/resources/js:assert",
]
externs_list = [
- "$externs_path/file_manager_private.js",
- "$externs_path/file_system_provider.js",
"$externs_path/metrics_private.js",
"//third_party/analytics/externs.js",
]
@@ -91,20 +144,20 @@ js_library("unittest_util") {
deps = [
"//ui/webui/resources/js:webui_resource_test",
]
+ externs_list = [ "$externs_path/command_line_private.js" ]
}
js_library("util") {
deps = [
":files_app_entry_types",
":volume_manager_common",
+ "../../../externs:file_manager_private",
"//ui/webui/resources/js:load_time_data",
"//ui/webui/resources/js:util",
"//ui/webui/resources/js/cr:event_target",
"//ui/webui/resources/js/cr:ui",
]
externs_list = [
- "$externs_path/chrome.js",
- "$externs_path/chrome_extensions.js",
"$externs_path/command_line_private.js",
"../../../externs/app_window_common.js",
"../../../externs/entry_location.js",
@@ -112,8 +165,40 @@ js_library("util") {
]
}
+js_library("util_unittest") {
+ deps = [
+ ":mock_entry",
+ ":unittest_util",
+ ":util",
+ ]
+}
+
js_library("volume_manager_common") {
deps = [
"//ui/webui/resources/js:assert",
]
}
+
+js_unit_tests("unit_tests") {
+ deps = [
+ ":async_util_unittest",
+ ":files_app_entry_types_unittest",
+ ":importer_common_unittest",
+ ":lru_cache_unittest",
+ ":util_unittest",
+ ]
+}
+
+js_type_check("test_support_type_check") {
+ deps = [
+ ":test_importer_common",
+ ]
+}
+
+group("closure_compile") {
+ deps = [
+ ":closure_compile_module",
+ ":test_support_type_check",
+ ":unit_tests_type_check",
+ ]
+}
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 dcb7cb91d6a..b1ecbbcb771 100644
--- a/chromium/ui/file_manager/file_manager/foreground/elements/BUILD.gn
+++ b/chromium/ui/file_manager/file_manager/foreground/elements/BUILD.gn
@@ -4,6 +4,8 @@
import("//third_party/closure_compiler/compile_js.gni")
+visibility = [ "//ui/file_manager/file_manager/foreground/*" ]
+
js_type_check("closure_compile") {
deps = [
":files_icon_button",
@@ -51,12 +53,18 @@ js_library("files_safe_media") {
js_library("files_safe_media_webview_content") {
}
+# TODO(tapted): Move this to //ui/file_manager/base.
js_library("files_toast") {
+ visibility += [ "//ui/file_manager/gallery/*" ]
externs_list = [ "$externs_path/web_animations.js" ]
}
+# TODO(tapted): Move this to //ui/file_manager/base.
js_library("files_toggle_ripple") {
+ visibility += [ "//ui/file_manager/gallery/*" ]
}
+# TODO(tapted): Move this to //ui/file_manager/base.
js_library("files_tooltip") {
+ visibility += [ "//ui/file_manager/gallery/*" ]
}
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 4d9de83bf71..2823093fb10 100644
--- a/chromium/ui/file_manager/file_manager/foreground/js/BUILD.gn
+++ b/chromium/ui/file_manager/file_manager/foreground/js/BUILD.gn
@@ -3,8 +3,14 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//third_party/closure_compiler/js_unit_tests.gni")
-js_type_check("closure_compile") {
+visibility = [
+ "//ui/file_manager/file_manager/foreground/*",
+ "//ui/file_manager/file_manager/test/*",
+]
+
+js_type_check("closure_compile_module") {
deps = [
":actions_controller",
":actions_model",
@@ -12,6 +18,7 @@ js_type_check("closure_compile") {
":closure_compile_externs",
":column_visibility_controller",
":constants",
+ ":crostini",
":dialog_action_controller",
":dialog_type",
":directory_contents",
@@ -49,14 +56,12 @@ js_type_check("closure_compile") {
":scan_controller",
":search_controller",
":selection_menu_controller",
- ":share_client",
":sort_menu_controller",
":spinner_controller",
":task_controller",
":task_history",
":thumbnail_loader",
":toolbar_controller",
- ":volume_manager_wrapper",
":web_store_utils",
":webui_command_extender",
]
@@ -110,11 +115,11 @@ js_library("actions_controller") {
js_library("actions_model") {
deps = [
":folder_shortcuts_data_model",
+ "../../common/js:util",
"metadata:metadata_model",
"ui:error_dialog",
"ui:files_alert_dialog",
"ui:list_container",
- "ui:share_dialog",
"//ui/webui/resources/js:cr",
]
}
@@ -146,7 +151,6 @@ js_library("dialog_action_controller") {
":file_selection",
":launch_param",
":naming_controller",
- ":volume_manager_wrapper",
"../../common/js:metrics",
"metadata:metadata_model",
"ui:dialog_footer",
@@ -154,6 +158,10 @@ js_library("dialog_action_controller") {
]
}
+js_library("crostini") {
+ deps = []
+}
+
js_library("dialog_type") {
}
@@ -175,7 +183,6 @@ js_library("directory_model") {
deps = [
":directory_contents",
":file_watcher",
- ":volume_manager_wrapper",
"../../common/js:importer_common",
"../../common/js:metrics_events",
"ui:file_list_selection_model",
@@ -185,7 +192,6 @@ js_library("directory_model") {
js_library("navigation_uma") {
deps = [
":dialog_type",
- ":volume_manager_wrapper",
"../../common/js:metrics",
]
}
@@ -253,10 +259,10 @@ js_library("file_manager") {
":spinner_controller",
":task_controller",
":toolbar_controller",
- ":volume_manager_wrapper",
"ui:commandbutton",
"ui:directory_tree",
"ui:file_manager_ui",
+ "//ui/file_manager/base/js:filtered_volume_manager",
"//ui/webui/resources/js/cr/ui:list_selection_model",
]
}
@@ -274,7 +280,6 @@ js_library("file_manager_commands") {
":providers_model",
":spinner_controller",
":task_controller",
- ":volume_manager_wrapper",
"ui:directory_tree",
"ui:file_manager_ui",
"//ui/webui/resources/cr_elements/cr_input:cr_input",
@@ -285,7 +290,6 @@ js_library("file_selection") {
deps = [
":constants",
":directory_model",
- ":volume_manager_wrapper",
"../../common/js:file_type",
"../../common/js:util",
"../../common/js:volume_manager_common",
@@ -298,9 +302,9 @@ js_library("file_selection") {
js_library("file_tasks") {
deps = [
+ ":crostini",
":directory_model",
":task_history",
- ":volume_manager_wrapper",
"metadata:metadata_model",
"ui:file_manager_ui",
]
@@ -311,7 +315,6 @@ js_library("file_transfer_controller") {
":directory_model",
":drop_effect_and_label",
":file_selection",
- ":volume_manager_wrapper",
":webui_command_extender",
"../../common/js:progress_center_common",
"metadata:metadata_model",
@@ -335,11 +338,11 @@ js_library("file_watcher") {
js_library("folder_shortcuts_data_model") {
deps = [
- ":volume_manager_wrapper",
- "../../common/js:async_util",
- "../../common/js:metrics",
- "../../common/js:util",
- "../../common/js:volume_manager_common",
+ "//ui/file_manager/base/js:filtered_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_common",
]
}
@@ -389,7 +392,6 @@ js_library("list_thumbnail_loader") {
":directory_model",
":file_list_model",
":thumbnail_loader",
- ":volume_manager_wrapper",
"../../common/js:volume_manager_common",
"metadata:thumbnail_model",
]
@@ -413,7 +415,6 @@ js_library("main_window_component") {
":file_selection",
":naming_controller",
":task_controller",
- ":volume_manager_wrapper",
"ui:file_manager_ui",
]
}
@@ -457,7 +458,6 @@ js_library("naming_controller") {
js_library("navigation_list_model") {
deps = [
":folder_shortcuts_data_model",
- ":volume_manager_wrapper",
"//ui/webui/resources/js/cr:event_target",
"//ui/webui/resources/js/cr/ui:array_data_model",
]
@@ -472,7 +472,6 @@ js_library("progress_center_item_group") {
js_library("providers_model") {
deps = [
- ":volume_manager_wrapper",
"//ui/webui/resources/js:assert",
]
}
@@ -485,7 +484,6 @@ js_library("quick_view_controller") {
":quick_view_model",
":quick_view_uma",
":task_controller",
- ":volume_manager_wrapper",
"metadata:metadata_model",
"ui:list_container",
"//ui/webui/resources/js/cr/ui:list_selection_model",
@@ -503,7 +501,6 @@ js_library("quick_view_uma") {
deps = [
":dialog_type",
":file_tasks",
- ":volume_manager_wrapper",
"../../common/js:file_type",
]
}
@@ -535,14 +532,6 @@ js_library("selection_menu_controller") {
]
}
-js_library("share_client") {
- deps = [
- "../../../externs:webview_tag",
- "../../common/js:volume_manager_common",
- "//ui/webui/resources/js/cr:event_target",
- ]
-}
-
js_library("sort_menu_controller") {
deps = [
":file_list_model",
@@ -565,7 +554,6 @@ js_library("task_controller") {
":file_tasks",
":metadata_update_controller",
":task_history",
- ":volume_manager_wrapper",
"metadata:metadata_model",
"ui:file_manager_ui",
]
@@ -577,7 +565,9 @@ js_library("task_history") {
]
}
+# TODO(tapted): Move this into //ui/file_manager/base.
js_library("thumbnail_loader") {
+ visibility += [ "//ui/file_manager/gallery/*" ]
deps = [
"../../../image_loader:image_loader_client",
"../../common/js:file_type",
@@ -586,6 +576,15 @@ js_library("thumbnail_loader") {
]
}
+js_library("thumbnail_loader_unittest") {
+ deps = [
+ ":thumbnail_loader",
+ "../../common/js:mock_entry",
+ "../../common/js:unittest_util",
+ "//ui/webui/resources/js:webui_resource_test",
+ ]
+}
+
js_library("toolbar_controller") {
deps = [
":file_selection",
@@ -596,27 +595,6 @@ js_library("toolbar_controller") {
]
}
-js_library("volume_manager_wrapper") {
- deps = [
- "../../common/js:async_util",
- "../../common/js:volume_manager_common",
- "//ui/webui/resources/js:cr",
- "//ui/webui/resources/js/cr:event_target",
- "//ui/webui/resources/js/cr/ui:array_data_model",
- ]
- externs_list = [
- # Note: volume_info has a dependency on chrome.fileManagerPrivate.IconSet.
- # Also, fileManagerPrivate depends on chrome.fileSystemProvider, so these
- # must be introduced together.
- "$externs_path/file_manager_private.js",
- "$externs_path/file_system_provider.js",
- "../../../externs/background/volume_manager_factory.js",
- "../../../externs/volume_info.js",
- "../../../externs/volume_info_list.js",
- "../../../externs/volume_manager.js",
- ]
-}
-
js_library("web_store_utils") {
deps = [
":constants",
@@ -629,3 +607,17 @@ js_library("webui_command_extender") {
"//ui/webui/resources/js/cr/ui:command",
]
}
+
+js_unit_tests("unit_tests") {
+ deps = [
+ ":thumbnail_loader_unittest",
+ ]
+}
+
+group("closure_compile") {
+ visibility += [ "*" ]
+ deps = [
+ ":closure_compile_module",
+ ":unit_tests_type_check",
+ ]
+}
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 4269da747f9..a698efc533c 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
@@ -4,6 +4,9 @@
import("//third_party/closure_compiler/compile_js.gni")
+# TODO(tapted): This entire folder should move to //ui/file_manager/base.
+visibility = [ "//ui/file_manager/*" ]
+
js_type_check("closure_compile") {
deps = [
":byte_reader",
@@ -35,9 +38,6 @@ js_type_check("closure_compile") {
js_library("closure_compile_externs") {
sources = []
externs_list = [
- "$externs_path/command_line_private.js",
- "$externs_path/file_manager_private.js",
- "$externs_path/file_system_provider.js",
"../../../../externs/app_window_common.js",
"../../../../externs/entry_location.js",
"../../../../externs/platform.js",
@@ -148,6 +148,7 @@ js_library("metadata_model") {
":metadata_provider",
":multi_metadata_provider",
"../../../common/js:util",
+ "//ui/file_manager/externs:volume_manager",
]
}
@@ -186,6 +187,7 @@ js_library("multi_metadata_provider") {
":external_metadata_provider",
":file_system_metadata_provider",
":metadata_provider",
+ "//ui/file_manager/externs:volume_manager",
]
}
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 d3105ea28e8..3462ef36301 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
@@ -4,6 +4,8 @@
import("//third_party/closure_compiler/compile_js.gni")
+visibility = [ "//ui/file_manager/file_manager/foreground/*" ]
+
js_type_check("closure_compile") {
deps = [
":actions_submenu",
@@ -36,7 +38,6 @@ js_type_check("closure_compile") {
":progress_center_panel",
":providers_menu",
":search_box",
- ":share_dialog",
":suggest_apps_dialog",
]
}
@@ -44,7 +45,6 @@ js_type_check("closure_compile") {
js_library("closure_compile_externs") {
sources = []
externs_list = [
- "$externs_path/command_line_private.js",
"$externs_path/metrics_private.js",
"$externs_path/web_animations.js",
"../../../../externs/app_window_common.js",
@@ -59,7 +59,6 @@ js_library("closure_compile_externs") {
"../../../../externs/css_rule.js",
"../../../../externs/drag_target.js",
"../../../../externs/entries_changed_event.js",
- "../../../../externs/entry_location.js",
"../../../../externs/gallery_foreground.js",
"../../../../externs/menu_item_update_event.js",
"../../../../externs/paper_elements.js",
@@ -81,7 +80,6 @@ js_library("actions_submenu") {
js_library("banners") {
deps = [
"..:directory_model",
- "..:volume_manager_wrapper",
"../../../common/js:util",
"../../../common/js:volume_manager_common",
"//ui/webui/resources/js:assert",
@@ -128,7 +126,6 @@ js_library("directory_tree") {
deps = [
"..:directory_model",
"..:navigation_list_model",
- "..:volume_manager_wrapper",
"../../../common/js:util",
"../../../common/js:volume_manager_common",
"../metadata:metadata_model",
@@ -209,7 +206,6 @@ js_library("file_manager_ui") {
":progress_center_panel",
":providers_menu",
":search_box",
- ":share_dialog",
":suggest_apps_dialog",
"..:launch_param",
"..:providers_model",
@@ -261,13 +257,17 @@ js_library("file_tap_handler") {
]
}
+# TODO(tapted): Move this into //ui/file_manager/base.
js_library("files_alert_dialog") {
+ visibility += [ "//ui/file_manager/gallery/*" ]
deps = [
"//ui/webui/resources/js/cr/ui:dialogs",
]
}
+# TODO(tapted): Move this into //ui/file_manager/base.
js_library("files_confirm_dialog") {
+ visibility += [ "//ui/file_manager/gallery/*" ]
deps = [
"//ui/webui/resources/js/cr/ui:dialogs",
]
@@ -303,11 +303,11 @@ js_library("list_container") {
js_library("location_line") {
deps = [
- "..:volume_manager_wrapper",
"../../../common/js:files_app_entry_types",
"../../../common/js:metrics",
"../../../common/js:util",
"../../../common/js:volume_manager_common",
+ "//ui/file_manager/externs:volume_manager",
]
}
@@ -319,6 +319,9 @@ js_library("multi_profile_share_dialog") {
}
js_library("progress_center_panel") {
+ # The progress_center on the background page maintains a list of panels.
+ visibility += [ "//ui/file_manager/file_manager/background/*" ]
+
deps = [
"..:progress_center_item_group",
"../../../common/js:progress_center_common",
@@ -349,15 +352,6 @@ js_library("search_box") {
]
}
-js_library("share_dialog") {
- deps = [
- ":file_manager_dialog_base",
- "..:share_client",
- "../../../common/js:async_util",
- "../../../common/js:util",
- ]
-}
-
js_library("suggest_apps_dialog") {
deps = [
":file_manager_dialog_base",
diff --git a/chromium/ui/file_manager/file_manager/test/BUILD.gn b/chromium/ui/file_manager/file_manager/test/BUILD.gn
index 6ec1da2d8e3..7c5254a8c5c 100644
--- a/chromium/ui/file_manager/file_manager/test/BUILD.gn
+++ b/chromium/ui/file_manager/file_manager/test/BUILD.gn
@@ -8,7 +8,6 @@ action("create_test_main") {
script = "//ui/file_manager/file_manager/test/scripts/create_test_main.py"
output = "$target_gen_dir/../test.html"
sources = [
- "../../../webui/resources/css/text_defaults.css",
"../background/js/background_common_scripts.js",
"../background/js/background_scripts.js",
"../foreground/elements/elements_bundle.html",
@@ -18,20 +17,18 @@ action("create_test_main") {
"../foreground/js/elements_importer.js",
"../foreground/js/main_scripts.js",
"../main.html",
+ "//chrome/app/file_manager_strings.grdp",
+ "//chrome/browser/chromeos/extensions/file_manager/private_api_strings.cc",
+ "//ui/webui/resources/css/text_defaults.css",
"check_select.js",
"crostini.js",
+ "js/strings.js",
"quick_view.js",
"uma.js",
]
args = [ "--output=" + rebase_path(output, root_build_dir) ]
outputs = [
output,
- "$target_gen_dir/gen/css/text_defaults.css",
- "$target_gen_dir/gen/elements/elements_bundle.html",
- "$target_gen_dir/gen/elements/files_quick_view.html",
- "$target_gen_dir/gen/elements/files_safe_media.html",
- "$target_gen_dir/gen/elements/files_safe_media.js",
- "$target_gen_dir/gen/js/elements_importer.js",
]
}
@@ -45,13 +42,14 @@ js_type_check("closure_compile") {
]
}
+# 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/file_manager_private.js",
- "$externs_path/file_system_provider.js",
"$externs_path/metrics_private.js",
"../../externs/app_window_common.js",
"../../externs/background/file_browser_background.js",
@@ -72,6 +70,7 @@ js_library("check_select") {
js_library("crostini") {
deps = [
+ "../foreground/js:crostini",
"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
index 46577f8a83b..df093277383 100644
--- a/chromium/ui/file_manager/file_manager/test/js/BUILD.gn
+++ b/chromium/ui/file_manager/file_manager/test/js/BUILD.gn
@@ -4,6 +4,8 @@
import("//third_party/closure_compiler/compile_js.gni")
+visibility = [ "//ui/file_manager/file_manager/*" ]
+
js_library("chrome_api_test_impl") {
}
diff --git a/chromium/ui/file_manager/gallery/js/BUILD.gn b/chromium/ui/file_manager/gallery/js/BUILD.gn
index 02347f8e835..17e71d7f579 100644
--- a/chromium/ui/file_manager/gallery/js/BUILD.gn
+++ b/chromium/ui/file_manager/gallery/js/BUILD.gn
@@ -3,7 +3,7 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
-import("//ui/file_manager/js_unit_tests.gni")
+import("//third_party/closure_compiler/js_unit_tests.gni")
js_type_check("closure_compile_module") {
deps = [
@@ -52,13 +52,10 @@ js_library("dimmable_ui_controller_unittest") {
js_library("entry_list_watcher") {
deps = [
+ "../../externs:file_manager_private",
"//ui/webui/resources/js:assert",
"//ui/webui/resources/js/cr/ui:array_data_model",
]
- externs_list = [
- "$externs_path/file_system_provider.js",
- "$externs_path/file_manager_private.js",
- ]
}
js_library("entry_list_watcher_unittest") {
@@ -81,11 +78,10 @@ js_library("gallery") {
":gallery_constants",
":gallery_item",
":thumbnail_mode",
- "../../file_manager/common/js:util",
- "../../file_manager/foreground/js:volume_manager_wrapper",
- "../../file_manager/foreground/js/ui:files_confirm_dialog",
- "../../file_manager/foreground/js/ui:share_dialog",
- "../../gallery/js:slide_mode",
+ "//ui/file_manager/base/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",
"//ui/webui/resources/js:i18n_template_no_process",
]
}
@@ -117,7 +113,6 @@ js_library("gallery_item") {
":gallery_util",
"../../file_manager/common/js:metrics",
"../../file_manager/common/js:util",
- "../../file_manager/foreground/js:volume_manager_wrapper",
"../../file_manager/foreground/js/metadata:metadata_model",
"../../file_manager/foreground/js/metadata:thumbnail_model",
"image_editor:image_encoder",
@@ -140,7 +135,7 @@ js_library("gallery_util") {
"../../file_manager/common/js:file_type",
"../../file_manager/common/js:util",
"../../file_manager/common/js:volume_manager_common",
- "../../file_manager/foreground/js:volume_manager_wrapper",
+ "//ui/file_manager/externs:volume_manager",
]
}
@@ -240,6 +235,6 @@ js_unit_tests("unit_tests") {
group("closure_compile") {
deps = [
":closure_compile_module",
- ":unit_tests",
+ ":unit_tests_type_check",
]
}
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 86440b68a0f..e7a6675b35f 100644
--- a/chromium/ui/file_manager/gallery/js/image_editor/BUILD.gn
+++ b/chromium/ui/file_manager/gallery/js/image_editor/BUILD.gn
@@ -3,7 +3,7 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
-import("//ui/file_manager/js_unit_tests.gni")
+import("//third_party/closure_compiler/js_unit_tests.gni")
js_type_check("closure_compile_module") {
deps = [
@@ -209,6 +209,6 @@ js_unit_tests("unit_tests") {
group("closure_compile") {
deps = [
":closure_compile_module",
- ":unit_tests",
+ ":unit_tests_type_check",
]
}
diff --git a/chromium/ui/file_manager/image_loader/BUILD.gn b/chromium/ui/file_manager/image_loader/BUILD.gn
index 1b4618741b0..f88321191fc 100644
--- a/chromium/ui/file_manager/image_loader/BUILD.gn
+++ b/chromium/ui/file_manager/image_loader/BUILD.gn
@@ -3,32 +3,23 @@
# found in the LICENSE file.
import("//third_party/closure_compiler/compile_js.gni")
+import("//third_party/closure_compiler/js_unit_tests.gni")
-js_type_check("closure_compile") {
+js_type_check("closure_compile_module") {
+ closure_flags = default_closure_args + [ "jscomp_error=strictCheckTypes" ]
deps = [
":background",
":cache",
- ":closure_compile_externs",
":image_loader",
":image_loader_client",
":image_loader_util",
+ ":load_image_request",
":piex_loader",
":request",
":scheduler",
]
}
-js_library("closure_compile_externs") {
- sources = []
- externs_list = [
- "$externs_path/chrome_extensions.js",
- "$externs_path/file_manager_private.js",
- "$externs_path/file_system_provider.js",
- "$externs_path/metrics_private.js",
- "//third_party/analytics/externs.js",
- ]
-}
-
js_library("background") {
deps = [
":image_loader",
@@ -38,43 +29,93 @@ js_library("background") {
js_library("cache") {
}
+js_library("cache_unittest") {
+ deps = [
+ ":cache",
+ ":load_image_request",
+ "//ui/webui/resources/js:webui_resource_test",
+ ]
+}
+
js_library("image_loader") {
deps = [
":cache",
+ ":load_image_request",
":piex_loader",
":request",
":scheduler",
+ "../externs:file_manager_private",
+ ]
+}
+
+js_library("image_loader_unittest") {
+ deps = [
+ ":image_loader",
+ "//ui/webui/resources/js:webui_resource_test",
]
}
js_library("image_loader_util") {
deps = [
+ ":load_image_request",
":piex_loader",
"//ui/webui/resources/js:assert",
]
}
+js_library("load_image_request") {
+ deps = [
+ "../file_manager/foreground/js/metadata:image_orientation",
+ "//ui/webui/resources/js:assert",
+ ]
+}
+
js_library("image_loader_client") {
deps = [
+ ":load_image_request",
"../file_manager/common/js:lru_cache",
]
+ externs_list = [
+ "$externs_path/chrome.js",
+ "$externs_path/chrome_extensions.js",
+ "$externs_path/metrics_private.js",
+ ]
+}
+
+js_library("image_loader_client_unittest") {
+ deps = [
+ ":image_loader_client",
+ "../file_manager/common/js:unittest_util",
+ "//ui/webui/resources/js:webui_resource_test",
+ ]
}
js_library("piex_loader") {
deps = [
+ ":load_image_request",
"../file_manager/foreground/js/metadata:image_orientation",
]
}
+js_library("piex_loader_unittest") {
+ deps = [
+ ":piex_loader",
+ "../file_manager/common/js:unittest_util",
+ "//ui/webui/resources/js:webui_resource_test",
+ ]
+}
+
js_library("request") {
deps = [
":cache",
":image_loader_util",
+ ":load_image_request",
":piex_loader",
"../file_manager/common/js:file_type",
"../file_manager/common/js:metrics",
"../file_manager/common/js:metrics_events",
]
+ externs_list = [ "../externs/platform.js" ]
}
js_library("scheduler") {
@@ -82,3 +123,20 @@ js_library("scheduler") {
":request",
]
}
+
+js_unit_tests("unit_tests") {
+ closure_flags = default_closure_args + [ "jscomp_error=strictCheckTypes" ]
+ deps = [
+ ":cache_unittest",
+ ":image_loader_client_unittest",
+ ":image_loader_unittest",
+ ":piex_loader_unittest",
+ ]
+}
+
+group("closure_compile") {
+ deps = [
+ ":closure_compile_module",
+ ":unit_tests_type_check",
+ ]
+}
diff --git a/chromium/ui/file_manager/js_unit_tests.gni b/chromium/ui/file_manager/js_unit_tests.gni
deleted file mode 100644
index edb9a07e950..00000000000
--- a/chromium/ui/file_manager/js_unit_tests.gni
+++ /dev/null
@@ -1,68 +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")
-
-# Describes a list of js_library targets that will each have an html file
-# written listing all its (flattened) js dependencies, for loading as a test.
-# Must be declared after the js_library targets it depends on.
-#
-# Variables:
-# deps:
-# List of js_library targets to depend on
-#
-# mocks:
-# An optional list of .js files to load before any other scripts
-#
-# Example:
-# js_unit_tests("folder_tests") {
-# deps = [
-# ":foo_unittest",
-# ":bar_unittest",
-# ":baz_unittest",
-# ]
-# mocks = [ "my_mocks.js" ]
-# }
-
-template("js_unit_tests") {
- html_gen_target_name = target_name + "_html_gen"
- action_foreach(html_gen_target_name) {
- script_path = "//ui/file_manager"
- script = "$script_path/js_unit_test.py"
- forward_variables_from(invoker,
- [
- "deps",
- "mocks",
- ])
- sources = []
- foreach(dep, deps) {
- sources += get_target_outputs(dep)
- }
-
- outputs = [
- "$target_gen_dir/{{source_name_part}}.html",
- ]
- args = [ "--output" ] + rebase_path(outputs, root_build_dir)
- args += [ "--input" ] + [ "{{source}}" ]
-
- if (defined(mocks)) {
- args += [ "--mocks" ] + rebase_path(mocks, root_build_dir)
- data = mocks
- }
- }
- type_check_deps = []
- foreach(dep, invoker.deps) {
- type_check_target_name = target_name + "_" + dep + "_type_check"
- type_check_deps += [ ":$type_check_target_name" ]
- js_type_check(type_check_target_name) {
- deps = [
- dep,
- ]
- }
- }
- group(target_name) {
- data = get_target_outputs(":$html_gen_target_name")
- deps = [ ":$html_gen_target_name" ] + type_check_deps
- }
-}
diff --git a/chromium/ui/file_manager/video_player/js/BUILD.gn b/chromium/ui/file_manager/video_player/js/BUILD.gn
index 38d3912324b..e00d4b6fb28 100644
--- a/chromium/ui/file_manager/video_player/js/BUILD.gn
+++ b/chromium/ui/file_manager/video_player/js/BUILD.gn
@@ -20,11 +20,9 @@ js_library("closure_compile_externs") {
sources = []
externs_list = [
"$externs_path/chrome_extensions.js",
- "$externs_path/command_line_private.js",
"$externs_path/media_player_private.js",
"$externs_path/metrics_private.js",
"../../externs/chrome_cast.js",
- "../../externs/entry_location.js",
"../../externs/platform.js",
"//third_party/analytics/externs.js",
]
@@ -58,12 +56,12 @@ js_library("video_player") {
":media_controls",
":mouse_inactivity_watcher",
":video_player_metrics",
- "../../file_manager/common/js:metrics",
- "../../file_manager/common/js:util",
- "../../file_manager/foreground/js:volume_manager_wrapper",
- "../../image_loader:image_loader_client",
"cast:cast_video_element",
"cast:media_manager",
+ "//ui/file_manager/base/js:filtered_volume_manager",
+ "//ui/file_manager/file_manager/common/js:metrics",
+ "//ui/file_manager/file_manager/common/js:util",
+ "//ui/file_manager/image_loader:image_loader_client",
"//ui/webui/resources/js:i18n_template_no_process",
"//ui/webui/resources/js/cr/ui:menu",
"//ui/webui/resources/js/cr/ui:menu_item",
diff --git a/chromium/ui/file_manager/video_player/js/cast/BUILD.gn b/chromium/ui/file_manager/video_player/js/cast/BUILD.gn
index 2435e5b479f..6071386427a 100644
--- a/chromium/ui/file_manager/video_player/js/cast/BUILD.gn
+++ b/chromium/ui/file_manager/video_player/js/cast/BUILD.gn
@@ -18,19 +18,12 @@ js_library("closure_compile_externs") {
sources = []
externs_list = [
"$externs_path/chrome_extensions.js",
- "$externs_path/command_line_private.js",
- "$externs_path/file_manager_private.js",
- "$externs_path/file_system_provider.js",
"$externs_path/media_player_private.js",
"$externs_path/metrics_private.js",
"../../../externs/app_window_common.js",
"../../../externs/background/volume_manager_factory.js",
"../../../externs/chrome_cast.js",
- "../../../externs/entry_location.js",
"../../../externs/platform.js",
- "../../../externs/volume_info.js",
- "../../../externs/volume_info_list.js",
- "../../../externs/volume_manager.js",
"//third_party/analytics/externs.js",
]
}
diff --git a/chromium/ui/gfx/BUILD.gn b/chromium/ui/gfx/BUILD.gn
index 7611eb0879b..b9e0290dba2 100644
--- a/chromium/ui/gfx/BUILD.gn
+++ b/chromium/ui/gfx/BUILD.gn
@@ -25,6 +25,7 @@ source_set("gfx_export") {
jumbo_component("geometry_skia") {
sources = [
+ "geometry_skia_export.h",
"skia_util.cc",
"skia_util.h",
"transform.cc",
@@ -32,16 +33,14 @@ jumbo_component("geometry_skia") {
"transform_util.cc",
"transform_util.h",
]
- public_deps = [
- ":gfx_export",
- ]
+ configs += [ "//build/config/compiler:wexit_time_destructors" ]
deps = [
"//base",
"//gpu/vulkan:buildflags",
"//skia",
"//ui/gfx/geometry",
]
- defines = [ "GFX_IMPLEMENTATION" ]
+ defines = [ "GEOMETRY_SKIA_IMPLEMENTATION" ]
}
jumbo_component("gfx") {
@@ -104,7 +103,6 @@ jumbo_component("gfx") {
"image/image_png_rep.h",
"image/image_skia.cc",
"image/image_skia.h",
- "image/image_skia_rep.cc",
"image/image_skia_rep.h",
"image/image_skia_source.cc",
"image/image_skia_source.h",
@@ -212,6 +210,8 @@ jumbo_component("gfx") {
"image/image_generic.cc",
"image/image_skia_operations.cc",
"image/image_skia_operations.h",
+ "image/image_skia_rep_default.cc",
+ "image/image_skia_rep_default.h",
"paint_throbber.cc",
"paint_throbber.h",
"scoped_canvas.cc",
@@ -220,6 +220,16 @@ jumbo_component("gfx") {
"shadow_util.h",
"skia_paint_util.cc",
"skia_paint_util.h",
+ "skia_vector_animation.cc",
+ "skia_vector_animation.h",
+ "skia_vector_animation_observer.h",
+ "skottie_wrapper.cc",
+ "skottie_wrapper.h",
+ ]
+ } else {
+ sources += [
+ "image/image_skia_rep_ios.cc",
+ "image/image_skia_rep_ios.h",
]
}
@@ -228,6 +238,7 @@ jumbo_component("gfx") {
# TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
"//build/config/compiler:no_size_t_to_int_warning",
+ "//build/config/compiler:wexit_time_destructors",
]
# This is part of the gfx component in the component build.
@@ -401,20 +412,6 @@ jumbo_component("color_space") {
defines = [ "COLOR_SPACE_IMPLEMENTATION" ]
}
-# Depend on this to use half_float.h without pulling in all of gfx.
-source_set("half_float") {
- sources = [
- "half_float.h",
- ]
-
- defines = [ "GFX_IMPLEMENTATION" ]
-
- public_deps = [
- ":gfx_export",
- "//base",
- ]
-}
-
# Depend on this to use native_widget_types.h without pulling in all of gfx.
source_set("native_widget_types") {
public = [
@@ -449,6 +446,8 @@ source_set("selection_bound_sources") {
"selection_bound.h",
]
+ configs += [ "//build/config/compiler:wexit_time_destructors" ]
+
defines = [ "GFX_IMPLEMENTATION" ]
public_deps = [
@@ -483,7 +482,7 @@ group("memory_buffer") {
}
# Cannot be a static_library in component builds due to exported functions
-source_set("memory_buffer_sources") {
+jumbo_source_set("memory_buffer_sources") {
visibility = [ ":*" ] # Depend on through ":memory_buffer".
# TODO(brettw) refactor this so these sources are in a coherent directory
@@ -516,6 +515,8 @@ source_set("memory_buffer_sources") {
]
}
+ configs += [ "//build/config/compiler:wexit_time_destructors" ]
+
defines = [ "GFX_IMPLEMENTATION" ]
public_deps = [
@@ -574,7 +575,7 @@ jumbo_component("gfx_switches") {
]
}
-static_library("test_support") {
+jumbo_static_library("test_support") {
testonly = true
sources = [
"animation/animation_test_api.cc",
@@ -686,6 +687,7 @@ test("gfx_unittests") {
"sequential_id_generator_unittest.cc",
"shadow_value_unittest.cc",
"skbitmap_operations_unittest.cc",
+ "skia_vector_animation_unittest.cc",
"skrect_conversion_unittest.cc",
"transform_util_unittest.cc",
"utf16_indexing_unittest.cc",
diff --git a/chromium/ui/gfx/OWNERS b/chromium/ui/gfx/OWNERS
index 128cf4cb9ca..225898fbe52 100644
--- a/chromium/ui/gfx/OWNERS
+++ b/chromium/ui/gfx/OWNERS
@@ -27,12 +27,17 @@ per-file skia_paint_util*=danakj@chromium.org
# GPU memory buffer and GpuFence interfaces.
per-file gpu_fence*=reveman@chromium.org
per-file gpu_fence*=dcastagna@chromium.org
+per-file gpu_fence*=rjkroege@chromium.org
per-file gpu_memory_buffer*=reveman@chromium.org
per-file gpu_memory_buffer*=dcastagna@chromium.org
+per-file gpu_memory_buffer*=rjkroege@chromium.org
per-file buffer_format*=reveman@chromium.org
per-file buffer_format*=dcastagna@chromium.org
+per-file buffer_format*=rjkroege@chromium.org
per-file *buffer_types.*=reveman@chromium.org
per-file *buffer_types.*=dcastagna@chromium.org
+per-file *buffer_types.*=rjkroege@chromium.org
+per-file *pixmap.*=rjkroege@chromium.org
# Vector icons.
per-file *vector_icon*=estade@chromium.org
diff --git a/chromium/ui/gfx/android/java_bitmap.h b/chromium/ui/gfx/android/java_bitmap.h
index 919e62a9168..950509164a6 100644
--- a/chromium/ui/gfx/android/java_bitmap.h
+++ b/chromium/ui/gfx/android/java_bitmap.h
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/gfx_export.h"
namespace gfx {
diff --git a/chromium/ui/gfx/animation/animation_container.cc b/chromium/ui/gfx/animation/animation_container.cc
index ef15c8f64c2..884c3c82081 100644
--- a/chromium/ui/gfx/animation/animation_container.cc
+++ b/chromium/ui/gfx/animation/animation_container.cc
@@ -114,7 +114,7 @@ std::pair<TimeDelta, size_t> AnimationContainer::GetMinIntervalAndCount()
// elements in the set share the same interval).
TimeDelta min;
size_t count = 1;
- Elements::const_iterator i = elements_.begin();
+ auto i = elements_.begin();
min = (*i)->GetTimerInterval();
for (++i; i != elements_.end(); ++i) {
auto interval = (*i)->GetTimerInterval();
diff --git a/chromium/ui/gfx/buffer_format_util.cc b/chromium/ui/gfx/buffer_format_util.cc
index f72941f5258..5e3de26ae3f 100644
--- a/chromium/ui/gfx/buffer_format_util.cc
+++ b/chromium/ui/gfx/buffer_format_util.cc
@@ -11,26 +11,15 @@
namespace gfx {
namespace {
-const BufferFormat kBufferFormats[] = {BufferFormat::ATC,
- BufferFormat::ATCIA,
- BufferFormat::DXT1,
- BufferFormat::DXT5,
- BufferFormat::ETC1,
- BufferFormat::R_8,
- BufferFormat::R_16,
- BufferFormat::RG_88,
- BufferFormat::BGR_565,
- BufferFormat::RGBA_4444,
- BufferFormat::RGBX_8888,
- BufferFormat::RGBA_8888,
- BufferFormat::BGRX_8888,
- BufferFormat::BGRX_1010102,
- BufferFormat::RGBX_1010102,
- BufferFormat::BGRA_8888,
- BufferFormat::RGBA_F16,
- BufferFormat::UYVY_422,
- BufferFormat::YUV_420_BIPLANAR,
- BufferFormat::YVU_420};
+const BufferFormat kBufferFormats[] = {
+ BufferFormat::R_8, BufferFormat::R_16,
+ BufferFormat::RG_88, BufferFormat::BGR_565,
+ BufferFormat::RGBA_4444, BufferFormat::RGBX_8888,
+ BufferFormat::RGBA_8888, BufferFormat::BGRX_8888,
+ BufferFormat::BGRX_1010102, BufferFormat::RGBX_1010102,
+ BufferFormat::BGRA_8888, BufferFormat::RGBA_F16,
+ BufferFormat::UYVY_422, BufferFormat::YUV_420_BIPLANAR,
+ BufferFormat::YVU_420};
static_assert(arraysize(kBufferFormats) ==
(static_cast<int>(BufferFormat::LAST) + 1),
@@ -41,18 +30,6 @@ bool RowSizeForBufferFormatChecked(
size_t width, BufferFormat format, size_t plane, size_t* size_in_bytes) {
base::CheckedNumeric<size_t> checked_size = width;
switch (format) {
- case BufferFormat::ATCIA:
- case BufferFormat::DXT5:
- DCHECK_EQ(0u, plane);
- *size_in_bytes = width;
- return true;
- case BufferFormat::ATC:
- case BufferFormat::DXT1:
- case BufferFormat::ETC1:
- DCHECK_EQ(0u, plane);
- DCHECK_EQ(0u, width % 2);
- *size_in_bytes = width / 2;
- return true;
case BufferFormat::R_8:
checked_size += 3;
if (!checked_size.IsValid())
@@ -109,11 +86,6 @@ std::vector<BufferFormat> GetBufferFormatsForTesting() {
size_t NumberOfPlanesForBufferFormat(BufferFormat format) {
switch (format) {
- case BufferFormat::ATC:
- case BufferFormat::ATCIA:
- case BufferFormat::DXT1:
- case BufferFormat::DXT5:
- case BufferFormat::ETC1:
case BufferFormat::R_8:
case BufferFormat::R_16:
case BufferFormat::RG_88:
@@ -139,11 +111,6 @@ size_t NumberOfPlanesForBufferFormat(BufferFormat format) {
size_t SubsamplingFactorForBufferFormat(BufferFormat format, size_t plane) {
switch (format) {
- case BufferFormat::ATC:
- case BufferFormat::ATCIA:
- case BufferFormat::DXT1:
- case BufferFormat::DXT5:
- case BufferFormat::ETC1:
case BufferFormat::R_8:
case BufferFormat::R_16:
case BufferFormat::RG_88:
@@ -214,11 +181,6 @@ size_t BufferOffsetForBufferFormat(const Size& size,
size_t plane) {
DCHECK_LT(plane, gfx::NumberOfPlanesForBufferFormat(format));
switch (format) {
- case BufferFormat::ATC:
- case BufferFormat::ATCIA:
- case BufferFormat::DXT1:
- case BufferFormat::DXT5:
- case BufferFormat::ETC1:
case BufferFormat::R_8:
case BufferFormat::R_16:
case BufferFormat::RG_88:
@@ -252,16 +214,6 @@ size_t BufferOffsetForBufferFormat(const Size& size,
const char* BufferFormatToString(BufferFormat format) {
switch (format) {
- case BufferFormat::ATC:
- return "ATC";
- case BufferFormat::ATCIA:
- return "ATCIA";
- case BufferFormat::DXT1:
- return "DXT1";
- case BufferFormat::DXT5:
- return "DXT5";
- case BufferFormat::ETC1:
- return "ETC1";
case BufferFormat::R_8:
return "R_8";
case BufferFormat::R_16:
diff --git a/chromium/ui/gfx/buffer_types.h b/chromium/ui/gfx/buffer_types.h
index 47c8b60c10e..be72cf7480b 100644
--- a/chromium/ui/gfx/buffer_types.h
+++ b/chromium/ui/gfx/buffer_types.h
@@ -12,11 +12,6 @@ namespace gfx {
// The format needs to be taken into account when mapping a buffer into the
// client's address space.
enum class BufferFormat {
- ATC,
- ATCIA,
- DXT1,
- DXT5,
- ETC1,
R_8,
R_16,
RG_88,
diff --git a/chromium/ui/gfx/canvas.cc b/chromium/ui/gfx/canvas.cc
index ab5bcab982a..21b6e1358a6 100644
--- a/chromium/ui/gfx/canvas.cc
+++ b/chromium/ui/gfx/canvas.cc
@@ -26,6 +26,7 @@
#include "ui/gfx/scoped_canvas.h"
#include "ui/gfx/skia_paint_util.h"
#include "ui/gfx/skia_util.h"
+#include "ui/gfx/switches.h"
#include "ui/gfx/transform.h"
namespace gfx {
@@ -357,8 +358,17 @@ void Canvas::DrawImageInt(const ImageSkia& image,
ScopedCanvas scoper(this);
canvas_->scale(SkFloatToScalar(1.0f / bitmap_scale),
SkFloatToScalar(1.0f / bitmap_scale));
- canvas_->drawImage(image_rep.paint_image(), SkFloatToScalar(x * bitmap_scale),
- SkFloatToScalar(y * bitmap_scale), &flags);
+ if (base::FeatureList::IsEnabled(features::kUsePaintRecordForImageSkia)) {
+ canvas_->translate(std::round(x * bitmap_scale),
+ std::round(y * bitmap_scale));
+ canvas_->saveLayer(nullptr, &flags);
+ canvas_->drawPicture(image_rep.GetPaintRecord());
+ canvas_->restore();
+ } else {
+ canvas_->drawImage(image_rep.paint_image(),
+ SkFloatToScalar(x * bitmap_scale),
+ SkFloatToScalar(y * bitmap_scale), &flags);
+ }
}
void Canvas::DrawImageInt(const ImageSkia& image,
diff --git a/chromium/ui/gfx/codec/chromeos/jpeg_codec_robust_slow.cc b/chromium/ui/gfx/codec/chromeos/jpeg_codec_robust_slow.cc
index 1ab3208d090..e029cafe31e 100644
--- a/chromium/ui/gfx/codec/chromeos/jpeg_codec_robust_slow.cc
+++ b/chromium/ui/gfx/codec/chromeos/jpeg_codec_robust_slow.cc
@@ -139,26 +139,12 @@ void RGBtoBGRA(const unsigned char* bgra, int pixel_width, unsigned char* rgb) {
}
#endif // !defined(JCS_EXTENSIONS)
-// This class destroys the given jpeg_decompress object when it goes out of
-// scope. It simplifies the error handling in Decode (and even applies to the
-// success case).
-class IjgDecompressDestroyer {
- public:
- IjgDecompressDestroyer() : cinfo_(NULL) {}
- ~IjgDecompressDestroyer() { DestroyManagedObject(); }
- void SetManagedObject(jpeg_decompress_struct* ci) {
- DestroyManagedObject();
- cinfo_ = ci;
+// jpeg_decompress_struct Deleter.
+struct JpegRobustDecompressStructDeleter {
+ void operator()(jpeg_decompress_struct* ptr) {
+ jpeg_destroy_decompress(ptr);
+ delete ptr;
}
- void DestroyManagedObject() {
- if (cinfo_) {
- jpeg_destroy_decompress(cinfo_);
- cinfo_ = NULL;
- }
- }
-
- private:
- jpeg_decompress_struct* cinfo_;
};
} // namespace
@@ -169,28 +155,26 @@ bool JPEGCodecRobustSlow::Decode(const unsigned char* input,
std::vector<unsigned char>* output,
int* w,
int* h) {
- jpeg_decompress_struct cinfo;
- IjgDecompressDestroyer destroyer;
- destroyer.SetManagedObject(&cinfo);
+ std::unique_ptr<jpeg_decompress_struct, JpegRobustDecompressStructDeleter>
+ cinfo(new jpeg_decompress_struct);
output->clear();
// We set up the normal JPEG error routines, then override error_exit.
// This must be done before the call to create_decompress.
IjgCoderErrorMgr errmgr;
- cinfo.err = jpeg_std_error(&errmgr.pub);
+ cinfo->err = jpeg_std_error(&errmgr.pub);
errmgr.pub.error_exit = IjgErrorExit;
// Establish the setjmp return context for IjgErrorExit to use.
if (setjmp(errmgr.setjmp_buffer)) {
// If we get here, the JPEG code has signaled an error.
- // See note in JPEGCodec::Encode() for why we need to destroy the cinfo
- // manually here.
- destroyer.DestroyManagedObject();
+ // Release |cinfo| by hand to avoid use-after-free of |errmgr|.
+ cinfo.reset();
return false;
}
// The destroyer will destroy() cinfo on exit. We don't want to set the
// destroyer's object until cinfo is initialized.
- jpeg_create_decompress(&cinfo);
+ jpeg_create_decompress(cinfo.get());
// set up the source manager
jpeg_source_mgr srcmgr;
@@ -199,17 +183,17 @@ bool JPEGCodecRobustSlow::Decode(const unsigned char* input,
srcmgr.skip_input_data = IjgSkipInputData;
srcmgr.resync_to_restart = jpeg_resync_to_restart; // use default routine
srcmgr.term_source = IjgTermSource;
- cinfo.src = &srcmgr;
+ cinfo->src = &srcmgr;
IjgJpegDecoderState state(input, input_size);
- cinfo.client_data = &state;
+ cinfo->client_data = &state;
// fill the file metadata into our buffer
- if (jpeg_read_header(&cinfo, true) != JPEG_HEADER_OK)
+ if (jpeg_read_header(cinfo.get(), true) != JPEG_HEADER_OK)
return false;
// we want to always get RGB data out
- switch (cinfo.jpeg_color_space) {
+ switch (cinfo->jpeg_color_space) {
case JCS_GRAYSCALE:
case JCS_RGB:
case JCS_YCbCr:
@@ -219,24 +203,22 @@ bool JPEGCodecRobustSlow::Decode(const unsigned char* input,
// used by Chromium (i.e. RGB, RGBA, and BGRA) and we just map the input
// parameters to a colorspace.
if (format == FORMAT_RGB) {
- cinfo.out_color_space = JCS_RGB;
- cinfo.output_components = 3;
+ cinfo->out_color_space = JCS_RGB;
+ cinfo->output_components = 3;
} else if (format == FORMAT_RGBA ||
(format == FORMAT_SkBitmap && SK_R32_SHIFT == 0)) {
- cinfo.out_color_space = JCS_EXT_RGBX;
- cinfo.output_components = 4;
+ cinfo->out_color_space = JCS_EXT_RGBX;
+ cinfo->output_components = 4;
} else if (format == FORMAT_BGRA ||
(format == FORMAT_SkBitmap && SK_B32_SHIFT == 0)) {
- cinfo.out_color_space = JCS_EXT_BGRX;
- cinfo.output_components = 4;
+ cinfo->out_color_space = JCS_EXT_BGRX;
+ cinfo->output_components = 4;
} else {
- // We can exit this function without calling jpeg_destroy_decompress()
- // because IjgDecompressDestroyer automaticaly calls it.
NOTREACHED() << "Invalid pixel format";
return false;
}
#else
- cinfo.out_color_space = JCS_RGB;
+ cinfo->out_color_space = JCS_RGB;
#endif
break;
case JCS_CMYK:
@@ -248,39 +230,39 @@ bool JPEGCodecRobustSlow::Decode(const unsigned char* input,
return false;
}
#ifndef JCS_EXTENSIONS
- cinfo.output_components = 3;
+ cinfo->output_components = 3;
#endif
- jpeg_calc_output_dimensions(&cinfo);
- *w = cinfo.output_width;
- *h = cinfo.output_height;
+ jpeg_calc_output_dimensions(cinfo.get());
+ *w = cinfo->output_width;
+ *h = cinfo->output_height;
- jpeg_start_decompress(&cinfo);
+ jpeg_start_decompress(cinfo.get());
// FIXME(brettw) we may want to allow the capability for callers to request
// how to align row lengths as we do for the compressor.
- int row_read_stride = cinfo.output_width * cinfo.output_components;
+ int row_read_stride = cinfo->output_width * cinfo->output_components;
#ifdef JCS_EXTENSIONS
// Create memory for a decoded image and write decoded lines to the memory
// without conversions same as JPEGCodec::Encode().
int row_write_stride = row_read_stride;
- output->resize(row_write_stride * cinfo.output_height);
+ output->resize(row_write_stride * cinfo->output_height);
- for (int row = 0; row < static_cast<int>(cinfo.output_height); row++) {
+ for (int row = 0; row < static_cast<int>(cinfo->output_height); row++) {
unsigned char* rowptr = &(*output)[row * row_write_stride];
- if (!jpeg_read_scanlines(&cinfo, &rowptr, 1))
+ if (!jpeg_read_scanlines(cinfo.get(), &rowptr, 1))
return false;
}
#else
if (format == FORMAT_RGB) {
// easy case, row needs no conversion
int row_write_stride = row_read_stride;
- output->resize(row_write_stride * cinfo.output_height);
+ output->resize(row_write_stride * cinfo->output_height);
- for (int row = 0; row < static_cast<int>(cinfo.output_height); row++) {
+ for (int row = 0; row < static_cast<int>(cinfo->output_height); row++) {
unsigned char* rowptr = &(*output)[row * row_write_stride];
- if (!jpeg_read_scanlines(&cinfo, &rowptr, 1))
+ if (!jpeg_read_scanlines(cinfo.get(), &rowptr, 1))
return false;
}
} else {
@@ -291,33 +273,32 @@ bool JPEGCodecRobustSlow::Decode(const unsigned char* input,
void (*converter)(const unsigned char* rgb, int w, unsigned char* out);
if (format == FORMAT_RGBA ||
(format == FORMAT_SkBitmap && SK_R32_SHIFT == 0)) {
- row_write_stride = cinfo.output_width * 4;
+ row_write_stride = cinfo->output_width * 4;
converter = AddAlpha;
} else if (format == FORMAT_BGRA ||
(format == FORMAT_SkBitmap && SK_B32_SHIFT == 0)) {
- row_write_stride = cinfo.output_width * 4;
+ row_write_stride = cinfo->output_width * 4;
converter = RGBtoBGRA;
} else {
NOTREACHED() << "Invalid pixel format";
- jpeg_destroy_decompress(&cinfo);
+ jpeg_destroy_decompress(cinfo.get());
return false;
}
- output->resize(row_write_stride * cinfo.output_height);
+ output->resize(row_write_stride * cinfo->output_height);
std::unique_ptr<unsigned char[]> row_data(
new unsigned char[row_read_stride]);
unsigned char* rowptr = row_data.get();
- for (int row = 0; row < static_cast<int>(cinfo.output_height); row++) {
- if (!jpeg_read_scanlines(&cinfo, &rowptr, 1))
+ for (int row = 0; row < static_cast<int>(cinfo->output_height); row++) {
+ if (!jpeg_read_scanlines(cinfo.get(), &rowptr, 1))
return false;
converter(rowptr, *w, &(*output)[row * row_write_stride]);
}
}
#endif
- jpeg_finish_decompress(&cinfo);
- jpeg_destroy_decompress(&cinfo);
+ jpeg_finish_decompress(cinfo.get());
return true;
}
diff --git a/chromium/ui/gfx/codec/jpeg_codec.cc b/chromium/ui/gfx/codec/jpeg_codec.cc
index 5ff77d782b8..b03dc8f9368 100644
--- a/chromium/ui/gfx/codec/jpeg_codec.cc
+++ b/chromium/ui/gfx/codec/jpeg_codec.cc
@@ -11,7 +11,6 @@
#include "base/logging.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkColorPriv.h"
-#include "third_party/skia/include/encode/SkJpegEncoder.h"
#include "ui/gfx/codec/vector_wstream.h"
extern "C" {
@@ -47,15 +46,23 @@ void ErrorExit(jpeg_common_struct* cinfo) {
// Encoder ---------------------------------------------------------------------
-bool JPEGCodec::Encode(const SkPixmap& src,
+bool JPEGCodec::Encode(const SkPixmap& input,
int quality,
+ SkJpegEncoder::Downsample downsample,
std::vector<unsigned char>* output) {
output->clear();
VectorWStream dst(output);
SkJpegEncoder::Options options;
options.fQuality = quality;
- return SkJpegEncoder::Encode(&dst, src, options);
+ options.fDownsample = downsample;
+ return SkJpegEncoder::Encode(&dst, input, options);
+}
+
+bool JPEGCodec::Encode(const SkPixmap& input,
+ int quality,
+ std::vector<unsigned char>* output) {
+ return Encode(input, quality, SkJpegEncoder::Downsample::k420, output);
}
bool JPEGCodec::Encode(const SkBitmap& src,
@@ -143,31 +150,14 @@ void SkipInputData(j_decompress_ptr cinfo, long num_bytes) {
// "Terminate source --- called by jpeg_finish_decompress() after all data has
// been read to clean up JPEG source manager. NOT called by jpeg_abort() or
// jpeg_destroy()."
-void TermSource(j_decompress_ptr cinfo) {
-}
+void TermSource(j_decompress_ptr cinfo) {}
-// This class destroys the given jpeg_decompress object when it goes out of
-// scope. It simplifies the error handling in Decode (and even applies to the
-// success case).
-class DecompressDestroyer {
- public:
- DecompressDestroyer() : cinfo_(NULL) {
- }
- ~DecompressDestroyer() {
- DestroyManagedObject();
- }
- void SetManagedObject(jpeg_decompress_struct* ci) {
- DestroyManagedObject();
- cinfo_ = ci;
- }
- void DestroyManagedObject() {
- if (cinfo_) {
- jpeg_destroy_decompress(cinfo_);
- cinfo_ = NULL;
- }
+// jpeg_decompress_struct Deleter.
+struct JpegDecompressStructDeleter {
+ void operator()(jpeg_decompress_struct* ptr) {
+ jpeg_destroy_decompress(ptr);
+ delete ptr;
}
- private:
- jpeg_decompress_struct* cinfo_;
};
} // namespace
@@ -175,28 +165,26 @@ class DecompressDestroyer {
bool JPEGCodec::Decode(const unsigned char* input, size_t input_size,
ColorFormat format, std::vector<unsigned char>* output,
int* w, int* h) {
- jpeg_decompress_struct cinfo;
- DecompressDestroyer destroyer;
- destroyer.SetManagedObject(&cinfo);
+ std::unique_ptr<jpeg_decompress_struct, JpegDecompressStructDeleter> cinfo(
+ new jpeg_decompress_struct);
output->clear();
// We set up the normal JPEG error routines, then override error_exit.
- // This must be done before the call to create_decompress.
+ // This must be done before the call to jpeg_create_decompress.
CoderErrorMgr errmgr;
- cinfo.err = jpeg_std_error(&errmgr.pub);
+ cinfo->err = jpeg_std_error(&errmgr.pub);
errmgr.pub.error_exit = ErrorExit;
// Establish the setjmp return context for ErrorExit to use.
if (setjmp(errmgr.setjmp_buffer)) {
// If we get here, the JPEG code has signaled an error.
- // See note in JPEGCodec::Encode() for why we need to destroy the cinfo
- // manually here.
- destroyer.DestroyManagedObject();
+ // Release |cinfo| by hand to avoid use-after-free of |errmgr|.
+ cinfo.reset();
return false;
}
// The destroyer will destroy() cinfo on exit. We don't want to set the
// destroyer's object until cinfo is initialized.
- jpeg_create_decompress(&cinfo);
+ jpeg_create_decompress(cinfo.get());
// set up the source manager
jpeg_source_mgr srcmgr;
@@ -205,17 +193,17 @@ bool JPEGCodec::Decode(const unsigned char* input, size_t input_size,
srcmgr.skip_input_data = SkipInputData;
srcmgr.resync_to_restart = jpeg_resync_to_restart; // use default routine
srcmgr.term_source = TermSource;
- cinfo.src = &srcmgr;
+ cinfo->src = &srcmgr;
JpegDecoderState state(input, input_size);
- cinfo.client_data = &state;
+ cinfo->client_data = &state;
// fill the file metadata into our buffer
- if (jpeg_read_header(&cinfo, true) != JPEG_HEADER_OK)
+ if (jpeg_read_header(cinfo.get(), true) != JPEG_HEADER_OK)
return false;
// we want to always get RGB data out
- switch (cinfo.jpeg_color_space) {
+ switch (cinfo->jpeg_color_space) {
case JCS_GRAYSCALE:
case JCS_RGB:
case JCS_YCbCr:
@@ -225,15 +213,13 @@ bool JPEGCodec::Decode(const unsigned char* input, size_t input_size,
// parameters to a colorspace.
if (format == FORMAT_RGBA ||
(format == FORMAT_SkBitmap && SK_R32_SHIFT == 0)) {
- cinfo.out_color_space = JCS_EXT_RGBX;
- cinfo.output_components = 4;
+ cinfo->out_color_space = JCS_EXT_RGBX;
+ cinfo->output_components = 4;
} else if (format == FORMAT_BGRA ||
(format == FORMAT_SkBitmap && SK_B32_SHIFT == 0)) {
- cinfo.out_color_space = JCS_EXT_BGRX;
- cinfo.output_components = 4;
+ cinfo->out_color_space = JCS_EXT_BGRX;
+ cinfo->output_components = 4;
} else {
- // We can exit this function without calling jpeg_destroy_decompress()
- // because DecompressDestroyer automaticaly calls it.
NOTREACHED() << "Invalid pixel format";
return false;
}
@@ -247,29 +233,28 @@ bool JPEGCodec::Decode(const unsigned char* input, size_t input_size,
return false;
}
- jpeg_calc_output_dimensions(&cinfo);
- *w = cinfo.output_width;
- *h = cinfo.output_height;
+ jpeg_calc_output_dimensions(cinfo.get());
+ *w = cinfo->output_width;
+ *h = cinfo->output_height;
- jpeg_start_decompress(&cinfo);
+ jpeg_start_decompress(cinfo.get());
// FIXME(brettw) we may want to allow the capability for callers to request
// how to align row lengths as we do for the compressor.
- int row_read_stride = cinfo.output_width * cinfo.output_components;
+ int row_read_stride = cinfo->output_width * cinfo->output_components;
// Create memory for a decoded image and write decoded lines to the memory
// without conversions same as JPEGCodec::Encode().
int row_write_stride = row_read_stride;
- output->resize(row_write_stride * cinfo.output_height);
+ output->resize(row_write_stride * cinfo->output_height);
- for (int row = 0; row < static_cast<int>(cinfo.output_height); row++) {
+ for (int row = 0; row < static_cast<int>(cinfo->output_height); row++) {
unsigned char* rowptr = &(*output)[row * row_write_stride];
- if (!jpeg_read_scanlines(&cinfo, &rowptr, 1))
+ if (!jpeg_read_scanlines(cinfo.get(), &rowptr, 1))
return false;
}
- jpeg_finish_decompress(&cinfo);
- jpeg_destroy_decompress(&cinfo);
+ jpeg_finish_decompress(cinfo.get());
return true;
}
diff --git a/chromium/ui/gfx/codec/jpeg_codec.h b/chromium/ui/gfx/codec/jpeg_codec.h
index 1fdd143e8d7..14f88793d2d 100644
--- a/chromium/ui/gfx/codec/jpeg_codec.h
+++ b/chromium/ui/gfx/codec/jpeg_codec.h
@@ -12,6 +12,7 @@
#include "third_party/skia/include/core/SkImageInfo.h"
#include "third_party/skia/include/core/SkPixmap.h"
+#include "third_party/skia/include/encode/SkJpegEncoder.h"
#include "ui/gfx/codec/codec_export.h"
class SkBitmap;
@@ -43,6 +44,20 @@ class CODEC_EXPORT JPEGCodec {
// success. On failure (false), the contents of the output buffer are
// undefined.
//
+ // downsample: specifies how pixels will be sampled in the encoded JPEG image,
+ // can be either k420, k422 or k444.
+ // quality: an integer in the range 0-100, where 100 is the highest quality.
+ static bool Encode(const SkPixmap& input,
+ int quality,
+ SkJpegEncoder::Downsample downsample,
+ std::vector<unsigned char>* output);
+
+ // Encodes the given raw 'input' pixmap, which includes a pointer to pixels
+ // as well as information describing the pixel format. The encoded JPEG data
+ // will be written into the supplied vector and true will be returned on
+ // success. On failure (false), the contents of the output buffer are
+ // undefined.
+ //
// quality: an integer in the range 0-100, where 100 is the highest quality.
static bool Encode(const SkPixmap& input,
int quality,
diff --git a/chromium/ui/gfx/color_analysis.cc b/chromium/ui/gfx/color_analysis.cc
index 07c3cfbd79c..a23a9ad95c1 100644
--- a/chromium/ui/gfx/color_analysis.cc
+++ b/chromium/ui/gfx/color_analysis.cc
@@ -137,16 +137,6 @@ class KMeanCluster {
uint32_t weight_;
};
-// Un-premultiplies each pixel in |bitmap| into an output |buffer|. Requires
-// approximately 10 microseconds for a 16x16 icon on an Intel Core i5.
-void UnPreMultiply(const SkBitmap& bitmap, uint32_t* buffer, int buffer_size) {
- uint32_t* in = static_cast<uint32_t*>(bitmap.getPixels());
- uint32_t* out = buffer;
- int pixel_count = std::min(bitmap.width() * bitmap.height(), buffer_size);
- for (int i = 0; i < pixel_count; ++i)
- *out++ = SkUnPreMultiply::PMColorToColor(*in++);
-}
-
// Prominent color utilities ---------------------------------------------------
// A color value with an associated weight.
@@ -551,7 +541,7 @@ SkColor CalculateKMeanColorOfBuffer(uint8_t* decoded_data,
clusters.resize(kNumberOfClusters, KMeanCluster());
// Pick a starting point for each cluster
- std::vector<KMeanCluster>::iterator cluster = clusters.begin();
+ auto cluster = clusters.begin();
while (cluster != clusters.end()) {
// Try up to 10 times to find a unique color. If no unique color can be
// found, destroy this cluster.
@@ -572,9 +562,8 @@ SkColor CalculateKMeanColorOfBuffer(uint8_t* decoded_data,
// Loop through the previous clusters and check to see if we have seen
// this color before.
color_unique = true;
- for (std::vector<KMeanCluster>::iterator
- cluster_check = clusters.begin();
- cluster_check != cluster; ++cluster_check) {
+ for (auto cluster_check = clusters.begin(); cluster_check != cluster;
+ ++cluster_check) {
if (cluster_check->IsAtCentroid(r, g, b)) {
color_unique = false;
break;
@@ -622,11 +611,11 @@ SkColor CalculateKMeanColorOfBuffer(uint8_t* decoded_data,
continue;
uint32_t distance_sqr_to_closest_cluster = UINT_MAX;
- std::vector<KMeanCluster>::iterator closest_cluster = clusters.begin();
+ auto closest_cluster = clusters.begin();
// Figure out which cluster this color is closest to in RGB space.
- for (std::vector<KMeanCluster>::iterator cluster = clusters.begin();
- cluster != clusters.end(); ++cluster) {
+ for (auto cluster = clusters.begin(); cluster != clusters.end();
+ ++cluster) {
uint32_t distance_sqr = cluster->GetDistanceSqr(r, g, b);
if (distance_sqr < distance_sqr_to_closest_cluster) {
@@ -640,8 +629,8 @@ SkColor CalculateKMeanColorOfBuffer(uint8_t* decoded_data,
// Calculate the new cluster centers and see if we've converged or not.
convergence = true;
- for (std::vector<KMeanCluster>::iterator cluster = clusters.begin();
- cluster != clusters.end(); ++cluster) {
+ for (auto cluster = clusters.begin(); cluster != clusters.end();
+ ++cluster) {
convergence &= cluster->CompareCentroidWithAggregate();
cluster->RecomputeCentroid();
@@ -655,8 +644,8 @@ SkColor CalculateKMeanColorOfBuffer(uint8_t* decoded_data,
// Loop through the clusters to figure out which cluster has an appropriate
// color. Skip any that are too bright/dark and go in order of weight.
- for (std::vector<KMeanCluster>::iterator cluster = clusters.begin();
- cluster != clusters.end(); ++cluster) {
+ for (auto cluster = clusters.begin(); cluster != clusters.end();
+ ++cluster) {
uint8_t r, g, b;
cluster->GetCentroid(&r, &g, &b);
@@ -713,12 +702,24 @@ SkColor CalculateKMeanColorOfBitmap(const SkBitmap& bitmap,
const HSL& lower_bound,
const HSL& upper_bound,
bool find_closest) {
+ // Clamp the height being used to the height of the provided image (otherwise,
+ // we can end up creating a larger buffer than we have data for, and the end
+ // of the buffer will remain uninitialized after we copy/UnPreMultiply the
+ // image data into it).
+ height = std::min(height, bitmap.height());
+
// SkBitmap uses pre-multiplied alpha but the KMean clustering function
// above uses non-pre-multiplied alpha. Transform the bitmap before we
// analyze it because the function reads each pixel multiple times.
int pixel_count = bitmap.width() * height;
std::unique_ptr<uint32_t[]> image(new uint32_t[pixel_count]);
- UnPreMultiply(bitmap, image.get(), pixel_count);
+
+ // Un-premultiplies each pixel in bitmap into the buffer. Requires
+ // approximately 10 microseconds for a 16x16 icon on an Intel Core i5.
+ uint32_t* in = static_cast<uint32_t*>(bitmap.getPixels());
+ uint32_t* out = image.get();
+ for (int i = 0; i < pixel_count; ++i)
+ *out++ = SkUnPreMultiply::PMColorToColor(*in++);
GridSampler sampler;
return CalculateKMeanColorOfBuffer(reinterpret_cast<uint8_t*>(image.get()),
diff --git a/chromium/ui/gfx/color_palette.h b/chromium/ui/gfx/color_palette.h
index 0d55ae0ab9a..7b2d2358891 100644
--- a/chromium/ui/gfx/color_palette.h
+++ b/chromium/ui/gfx/color_palette.h
@@ -20,16 +20,20 @@ constexpr SkColor kGoogleBlue500 = SkColorSetRGB(0x42, 0x85, 0xF4);
constexpr SkColor kGoogleBlue600 = SkColorSetRGB(0x1A, 0x73, 0xE8);
constexpr SkColor kGoogleBlue700 = SkColorSetRGB(0x19, 0x67, 0xD2);
constexpr SkColor kGoogleBlue900 = SkColorSetRGB(0x17, 0x4E, 0xA6);
+constexpr SkColor kGoogleBlueDark400 = SkColorSetRGB(0x6B, 0xA5, 0xED);
constexpr SkColor kGoogleBlueDark600 = SkColorSetRGB(0x25, 0x81, 0xDF);
constexpr SkColor kGoogleRed300 = SkColorSetRGB(0xF2, 0x8B, 0xB2);
+constexpr SkColor kGoogleRed500 = SkColorSetRGB(0xEA, 0x43, 0x35);
constexpr SkColor kGoogleRed600 = SkColorSetRGB(0xD9, 0x30, 0x25);
constexpr SkColor kGoogleRed700 = SkColorSetRGB(0xC5, 0x22, 0x1F);
constexpr SkColor kGoogleRed800 = SkColorSetRGB(0xB3, 0x14, 0x12);
+constexpr SkColor kGoogleRedDark500 = SkColorSetRGB(0xE6, 0x6A, 0x5E);
constexpr SkColor kGoogleRedDark600 = SkColorSetRGB(0xD3, 0x3B, 0x30);
constexpr SkColor kGoogleRedDark800 = SkColorSetRGB(0xB4, 0x1B, 0x1A);
constexpr SkColor kGoogleGreen300 = SkColorSetRGB(0x81, 0xC9, 0x95);
constexpr SkColor kGoogleGreen600 = SkColorSetRGB(0x1E, 0x8E, 0x3E);
constexpr SkColor kGoogleGreen700 = SkColorSetRGB(0x18, 0x80, 0x38);
+constexpr SkColor kGoogleGreenDark500 = SkColorSetRGB(0x41, 0xAF, 0x6A);
constexpr SkColor kGoogleGreenDark600 = SkColorSetRGB(0x28, 0x99, 0x4F);
constexpr SkColor kGoogleYellow300 = SkColorSetRGB(0xFD, 0xD6, 0x63);
constexpr SkColor kGoogleYellow700 = SkColorSetRGB(0xF2, 0x99, 0x00);
diff --git a/chromium/ui/gfx/color_space.cc b/chromium/ui/gfx/color_space.cc
index d341167573e..95f8665d61f 100644
--- a/chromium/ui/gfx/color_space.cc
+++ b/chromium/ui/gfx/color_space.cc
@@ -48,8 +48,6 @@ static bool IsAlmostZero(float value) {
// static
int ColorSpace::kInvalidId = -1;
-ColorSpace::ColorSpace() {}
-
ColorSpace::ColorSpace(PrimaryID primaries,
TransferID transfer)
: primaries_(primaries),
@@ -58,15 +56,6 @@ ColorSpace::ColorSpace(PrimaryID primaries,
range_(RangeID::FULL) {}
ColorSpace::ColorSpace(PrimaryID primaries,
- TransferID transfer,
- MatrixID matrix,
- RangeID range)
- : primaries_(primaries),
- transfer_(transfer),
- matrix_(matrix),
- range_(range) {}
-
-ColorSpace::ColorSpace(PrimaryID primaries,
const SkColorSpaceTransferFn& fn,
MatrixID matrix,
RangeID range)
@@ -120,9 +109,10 @@ ColorSpace::ColorSpace(const SkColorSpace& sk_color_space)
}
// Use custom primaries, if they are representable as a "to XYZD50" matrix.
- if (const auto* to_XYZD50 = sk_color_space.toXYZD50()) {
+ SkMatrix44 to_XYZD50{SkMatrix44::kUninitialized_Constructor};
+ if (sk_color_space.toXYZD50(&to_XYZD50)) {
primaries_ = PrimaryID::CUSTOM;
- SetCustomPrimaries(*to_XYZD50);
+ SetCustomPrimaries(to_XYZD50);
return;
}
@@ -130,52 +120,12 @@ ColorSpace::ColorSpace(const SkColorSpace& sk_color_space)
primaries_ = PrimaryID::INVALID;
}
-ColorSpace::ColorSpace(const ColorSpace& other)
- : primaries_(other.primaries_),
- transfer_(other.transfer_),
- matrix_(other.matrix_),
- range_(other.range_),
- icc_profile_id_(other.icc_profile_id_) {
- if (transfer_ == TransferID::CUSTOM) {
- memcpy(custom_transfer_params_, other.custom_transfer_params_,
- sizeof(custom_transfer_params_));
- }
- if (primaries_ == PrimaryID::CUSTOM) {
- memcpy(custom_primary_matrix_, other.custom_primary_matrix_,
- sizeof(custom_primary_matrix_));
- }
-}
-
-ColorSpace::ColorSpace(ColorSpace&& other) = default;
-
-ColorSpace& ColorSpace::operator=(const ColorSpace& other) = default;
-
-ColorSpace::~ColorSpace() = default;
-
bool ColorSpace::IsValid() const {
return primaries_ != PrimaryID::INVALID && transfer_ != TransferID::INVALID &&
matrix_ != MatrixID::INVALID && range_ != RangeID::INVALID;
}
// static
-ColorSpace ColorSpace::CreateSRGB() {
- return ColorSpace(PrimaryID::BT709, TransferID::IEC61966_2_1, MatrixID::RGB,
- RangeID::FULL);
-}
-
-// static
-ColorSpace ColorSpace::CreateDisplayP3D65() {
- return ColorSpace(PrimaryID::SMPTEST432_1, TransferID::IEC61966_2_1,
- MatrixID::RGB, RangeID::FULL);
-}
-
-// static
-ColorSpace ColorSpace::CreateExtendedSRGB() {
- return ColorSpace(PrimaryID::BT709, TransferID::IEC61966_2_1_HDR,
- MatrixID::RGB, RangeID::FULL);
-}
-
-// static
ColorSpace ColorSpace::CreateCustom(const SkMatrix44& to_XYZD50,
const SkColorSpaceTransferFn& fn) {
ColorSpace result(ColorSpace::PrimaryID::CUSTOM,
@@ -219,38 +169,6 @@ ColorSpace ColorSpace::CreateCustom(const SkMatrix44& to_XYZD50,
}
// static
-ColorSpace ColorSpace::CreateSCRGBLinear() {
- return ColorSpace(PrimaryID::BT709, TransferID::LINEAR_HDR, MatrixID::RGB,
- RangeID::FULL);
-}
-
-// Static
-ColorSpace ColorSpace::CreateXYZD50() {
- return ColorSpace(PrimaryID::XYZ_D50, TransferID::LINEAR, MatrixID::RGB,
- RangeID::FULL);
-}
-
-// static
-ColorSpace ColorSpace::CreateJpeg() {
- // TODO(ccameron): Determine which primaries and transfer function were
- // intended here.
- return ColorSpace(PrimaryID::BT709, TransferID::IEC61966_2_1,
- MatrixID::SMPTE170M, RangeID::FULL);
-}
-
-// static
-ColorSpace ColorSpace::CreateREC601() {
- return ColorSpace(PrimaryID::SMPTE170M, TransferID::SMPTE170M,
- MatrixID::SMPTE170M, RangeID::LIMITED);
-}
-
-// static
-ColorSpace ColorSpace::CreateREC709() {
- return ColorSpace(PrimaryID::BT709, TransferID::BT709, MatrixID::BT709,
- RangeID::LIMITED);
-}
-
-// static
int ColorSpace::GetNextId() {
return g_color_space_id.GetNext();
}
diff --git a/chromium/ui/gfx/color_space.h b/chromium/ui/gfx/color_space.h
index a625b30ecc1..862edfa8c15 100644
--- a/chromium/ui/gfx/color_space.h
+++ b/chromium/ui/gfx/color_space.h
@@ -119,45 +119,73 @@ class COLOR_SPACE_EXPORT ColorSpace {
LAST = DERIVED,
};
- ColorSpace();
+ constexpr ColorSpace() {}
ColorSpace(PrimaryID primaries, TransferID transfer);
- ColorSpace(PrimaryID primaries,
- TransferID transfer,
- MatrixID matrix,
- RangeID full_range);
+ constexpr ColorSpace(PrimaryID primaries,
+ TransferID transfer,
+ MatrixID matrix,
+ RangeID full_range)
+ : primaries_(primaries),
+ transfer_(transfer),
+ matrix_(matrix),
+ range_(full_range) {}
+
ColorSpace(PrimaryID primaries,
const SkColorSpaceTransferFn& fn,
MatrixID matrix,
RangeID full_range);
explicit ColorSpace(const SkColorSpace& sk_color_space);
- ColorSpace(const ColorSpace& other);
- ColorSpace(ColorSpace&& other);
- ColorSpace& operator=(const ColorSpace& other);
- ~ColorSpace();
// Returns true if this is not the default-constructor object.
bool IsValid() const;
- static ColorSpace CreateSRGB();
- static ColorSpace CreateDisplayP3D65();
+ static constexpr ColorSpace CreateSRGB() {
+ return ColorSpace(PrimaryID::BT709, TransferID::IEC61966_2_1, MatrixID::RGB,
+ RangeID::FULL);
+ }
+
+ static constexpr ColorSpace CreateDisplayP3D65() {
+ return ColorSpace(PrimaryID::SMPTEST432_1, TransferID::IEC61966_2_1,
+ MatrixID::RGB, RangeID::FULL);
+ }
static ColorSpace CreateCustom(const SkMatrix44& to_XYZD50,
TransferID transfer_id);
static ColorSpace CreateCustom(const SkMatrix44& to_XYZD50,
const SkColorSpaceTransferFn& fn);
- static ColorSpace CreateXYZD50();
+ static constexpr ColorSpace CreateXYZD50() {
+ return ColorSpace(PrimaryID::XYZ_D50, TransferID::LINEAR, MatrixID::RGB,
+ RangeID::FULL);
+ }
// Extended sRGB matches sRGB for values in [0, 1], and extends the transfer
// function to all real values.
- static ColorSpace CreateExtendedSRGB();
+ static constexpr ColorSpace CreateExtendedSRGB() {
+ return ColorSpace(PrimaryID::BT709, TransferID::IEC61966_2_1_HDR,
+ MatrixID::RGB, RangeID::FULL);
+ }
// scRGB uses the same primaries as sRGB but has a linear transfer function
// for all real values.
- static ColorSpace CreateSCRGBLinear();
+ static constexpr ColorSpace CreateSCRGBLinear() {
+ return ColorSpace(PrimaryID::BT709, TransferID::LINEAR_HDR, MatrixID::RGB,
+ RangeID::FULL);
+ }
// TODO(ccameron): Remove these, and replace with more generic constructors.
- static ColorSpace CreateJpeg();
- static ColorSpace CreateREC601();
- static ColorSpace CreateREC709();
+ static constexpr ColorSpace CreateJpeg() {
+ // TODO(ccameron): Determine which primaries and transfer function were
+ // intended here.
+ return ColorSpace(PrimaryID::BT709, TransferID::IEC61966_2_1,
+ MatrixID::SMPTE170M, RangeID::FULL);
+ }
+ static constexpr ColorSpace CreateREC601() {
+ return ColorSpace(PrimaryID::SMPTE170M, TransferID::SMPTE170M,
+ MatrixID::SMPTE170M, RangeID::LIMITED);
+ }
+ static constexpr ColorSpace CreateREC709() {
+ return ColorSpace(PrimaryID::BT709, TransferID::BT709, MatrixID::BT709,
+ RangeID::LIMITED);
+ }
// Generates a process global unique ID that can be used to key a color space.
static int GetNextId();
diff --git a/chromium/ui/gfx/color_space_win.cc b/chromium/ui/gfx/color_space_win.cc
index 84507a6bc6c..a4541e08b68 100644
--- a/chromium/ui/gfx/color_space_win.cc
+++ b/chromium/ui/gfx/color_space_win.cc
@@ -132,8 +132,9 @@ DXVA2_ExtendedFormat ColorSpaceWin::GetExtendedFormat(
}
DXGI_COLOR_SPACE_TYPE ColorSpaceWin::GetDXGIColorSpace(
- const ColorSpace& color_space) {
- if (color_space.matrix_ == gfx::ColorSpace::MatrixID::RGB) {
+ const ColorSpace& color_space,
+ bool force_yuv) {
+ if (color_space.matrix_ == gfx::ColorSpace::MatrixID::RGB && !force_yuv) {
// For RGB, we default to FULL
if (color_space.range_ == gfx::ColorSpace::RangeID::LIMITED) {
if (color_space.primaries_ == gfx::ColorSpace::PrimaryID::BT2020) {
diff --git a/chromium/ui/gfx/color_space_win.h b/chromium/ui/gfx/color_space_win.h
index d02bca7898f..9a00bf573b3 100644
--- a/chromium/ui/gfx/color_space_win.h
+++ b/chromium/ui/gfx/color_space_win.h
@@ -27,7 +27,14 @@ namespace gfx {
class COLOR_SPACE_EXPORT ColorSpaceWin {
public:
static DXVA2_ExtendedFormat GetExtendedFormat(const ColorSpace& color_space);
- static DXGI_COLOR_SPACE_TYPE GetDXGIColorSpace(const ColorSpace& color_space);
+
+ // Returns a DXGI_COLOR_SPACE value based on the primaries and transfer
+ // function of |color_space|. If the color space's MatrixID is RGB, then the
+ // returned color space is also RGB unless |force_yuv| is true in which case
+ // it is a YUV color space.
+ static DXGI_COLOR_SPACE_TYPE GetDXGIColorSpace(const ColorSpace& color_space,
+ bool force_yuv = false);
+
static D3D11_VIDEO_PROCESSOR_COLOR_SPACE GetD3D11ColorSpace(
const ColorSpace& color_space);
};
diff --git a/chromium/ui/gfx/color_transform_unittest.cc b/chromium/ui/gfx/color_transform_unittest.cc
index 59407f4ef34..77c85b84902 100644
--- a/chromium/ui/gfx/color_transform_unittest.cc
+++ b/chromium/ui/gfx/color_transform_unittest.cc
@@ -110,7 +110,6 @@ TEST(SimpleColorSpace, BT2020CLtoBT2020RGB) {
ColorSpace bt2020rgb(ColorSpace::PrimaryID::BT2020,
ColorSpace::TransferID::BT2020_10,
ColorSpace::MatrixID::RGB, ColorSpace::RangeID::FULL);
- ColorSpace sRGB = ColorSpace::CreateSRGB();
std::unique_ptr<ColorTransform> t(ColorTransform::NewColorTransform(
bt2020cl, bt2020rgb, ColorTransform::Intent::INTENT_ABSOLUTE));
@@ -492,9 +491,9 @@ TEST(SimpleColorSpace, MAYBE_SampleShaderSource) {
" color.r = TransferFn1(color.r);\n"
" color.g = TransferFn1(color.g);\n"
" color.b = TransferFn1(color.b);\n"
- " color = mat3(6.27403915e-01, 6.90973178e-02, 1.63914412e-02,\n"
- " 3.29283148e-01, 9.19540286e-01, 8.80132914e-02,\n"
- " 4.33131084e-02, 1.13623003e-02, 8.95595253e-01) "
+ " color = mat3(6.27404153e-01, 6.90974146e-02, 1.63914431e-02,\n"
+ " 3.29283088e-01, 9.19540644e-01, 8.80132765e-02,\n"
+ " 4.33131084e-02, 1.13623096e-02, 8.95595253e-01) "
"* color;\n"
" color.r = TransferFn3(color.r);\n"
" color.g = TransferFn3(color.g);\n"
diff --git a/chromium/ui/gfx/color_utils.cc b/chromium/ui/gfx/color_utils.cc
index 62a98b0e4a7..6bb5a66e51e 100644
--- a/chromium/ui/gfx/color_utils.cc
+++ b/chromium/ui/gfx/color_utils.cc
@@ -189,9 +189,10 @@ void MakeHSLShiftValid(HSL* hsl) {
}
bool IsHSLShiftMeaningful(const HSL& hsl) {
- // -1 in any channel is no-op, but additionally 0.5 is no-op for S/L.
- return hsl.h != -1 && hsl.s != -1 && hsl.s != 0.5 && hsl.l != -1 &&
- hsl.l != 0.5;
+ // -1 in any channel has no effect, and 0.5 has no effect for S/L. A shift
+ // with an effective value in ANY channel is meaningful.
+ return hsl.h != -1 || (hsl.s != -1 && hsl.s != 0.5) ||
+ (hsl.l != -1 && hsl.l != 0.5);
}
SkColor HSLShift(SkColor color, const HSL& shift) {
diff --git a/chromium/ui/gfx/color_utils_unittest.cc b/chromium/ui/gfx/color_utils_unittest.cc
index 966205af9ec..bb0a5426aa7 100644
--- a/chromium/ui/gfx/color_utils_unittest.cc
+++ b/chromium/ui/gfx/color_utils_unittest.cc
@@ -103,6 +103,32 @@ TEST(ColorUtils, IsWithinHSLRangeHueWrapAround) {
EXPECT_FALSE(IsWithinHSLRange(hsl, lower, upper));
}
+TEST(ColorUtils, IsHSLShiftMeaningful) {
+ HSL noop_all_neg_one{-1.0, -1.0, -1.0};
+ HSL noop_s_point_five{-1.0, 0.5, -1.0};
+ HSL noop_l_point_five{-1.0, -1.0, 0.5};
+
+ HSL only_h{0.1, -1.0, -1.0};
+ HSL only_s{-1.0, 0.1, -1.0};
+ HSL only_l{-1.0, -1.0, 0.1};
+ HSL only_hs{0.1, 0.1, -1.0};
+ HSL only_hl{0.1, -1.0, 0.1};
+ HSL only_sl{-1.0, 0.1, 0.1};
+ HSL all_set{0.1, 0.2, 0.3};
+
+ EXPECT_FALSE(IsHSLShiftMeaningful(noop_all_neg_one));
+ EXPECT_FALSE(IsHSLShiftMeaningful(noop_s_point_five));
+ EXPECT_FALSE(IsHSLShiftMeaningful(noop_l_point_five));
+
+ EXPECT_TRUE(IsHSLShiftMeaningful(only_h));
+ EXPECT_TRUE(IsHSLShiftMeaningful(only_s));
+ EXPECT_TRUE(IsHSLShiftMeaningful(only_l));
+ EXPECT_TRUE(IsHSLShiftMeaningful(only_hs));
+ EXPECT_TRUE(IsHSLShiftMeaningful(only_hl));
+ EXPECT_TRUE(IsHSLShiftMeaningful(only_sl));
+ EXPECT_TRUE(IsHSLShiftMeaningful(all_set));
+}
+
TEST(ColorUtils, ColorToHSLRegisterSpill) {
// In a opt build on Linux, this was causing a register spill on my laptop
// (Pentium M) when converting from SkColor to HSL.
diff --git a/chromium/ui/gfx/font_list_impl.cc b/chromium/ui/gfx/font_list_impl.cc
index 6decee94999..da82a0fb90b 100644
--- a/chromium/ui/gfx/font_list_impl.cc
+++ b/chromium/ui/gfx/font_list_impl.cc
@@ -219,8 +219,7 @@ void FontListImpl::CacheCommonFontHeightAndBaseline() const {
int ascent = 0;
int descent = 0;
const std::vector<Font>& fonts = GetFonts();
- for (std::vector<Font>::const_iterator i = fonts.begin();
- i != fonts.end(); ++i) {
+ for (auto i = fonts.begin(); i != fonts.end(); ++i) {
ascent = std::max(ascent, i->GetBaseline());
descent = std::max(descent, i->GetHeight() - i->GetBaseline());
}
diff --git a/chromium/ui/gfx/font_render_params_android.cc b/chromium/ui/gfx/font_render_params_android.cc
index 846190937ce..4657d6a5e42 100644
--- a/chromium/ui/gfx/font_render_params_android.cc
+++ b/chromium/ui/gfx/font_render_params_android.cc
@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "base/macros.h"
+#include "base/no_destructor.h"
namespace gfx {
@@ -39,8 +40,8 @@ FontRenderParams GetFontRenderParams(const FontRenderParamsQuery& query,
if (family_out)
NOTIMPLEMENTED();
// Customized font rendering settings are not supported, only defaults.
- CR_DEFINE_STATIC_LOCAL(const gfx::FontRenderParams, params, (LoadDefaults()));
- return params;
+ static const base::NoDestructor<gfx::FontRenderParams> params(LoadDefaults());
+ return *params;
}
float GetFontRenderParamsDeviceScaleFactor() {
diff --git a/chromium/ui/gfx/font_render_params_fuchsia.cc b/chromium/ui/gfx/font_render_params_fuchsia.cc
index f693f926c22..6229bcc9db6 100644
--- a/chromium/ui/gfx/font_render_params_fuchsia.cc
+++ b/chromium/ui/gfx/font_render_params_fuchsia.cc
@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "base/macros.h"
+#include "base/no_destructor.h"
namespace gfx {
@@ -31,8 +32,8 @@ FontRenderParams GetFontRenderParams(const FontRenderParamsQuery& query,
if (family_out)
NOTIMPLEMENTED();
// Customized font rendering settings are not supported, only defaults.
- CR_DEFINE_STATIC_LOCAL(const gfx::FontRenderParams, params, (LoadDefaults()));
- return params;
+ static const base::NoDestructor<gfx::FontRenderParams> params(LoadDefaults());
+ return *params;
}
} // namespace gfx
diff --git a/chromium/ui/gfx/font_render_params_linux.cc b/chromium/ui/gfx/font_render_params_linux.cc
index f12db00e1b9..1277d923a7f 100644
--- a/chromium/ui/gfx/font_render_params_linux.cc
+++ b/chromium/ui/gfx/font_render_params_linux.cc
@@ -138,8 +138,7 @@ bool QueryFontconfig(const FontRenderParamsQuery& query,
FcPatternAddBool(query_pattern.get(), FC_SCALABLE, FcTrue);
- for (std::vector<std::string>::const_iterator it = query.families.begin();
- it != query.families.end(); ++it) {
+ for (auto it = query.families.begin(); it != query.families.end(); ++it) {
FcPatternAddString(query_pattern.get(),
FC_FAMILY, reinterpret_cast<const FcChar8*>(it->c_str()));
}
diff --git a/chromium/ui/gfx/font_render_params_mac.cc b/chromium/ui/gfx/font_render_params_mac.cc
index 83fd341e507..80b46daadfc 100644
--- a/chromium/ui/gfx/font_render_params_mac.cc
+++ b/chromium/ui/gfx/font_render_params_mac.cc
@@ -6,6 +6,7 @@
#include "base/logging.h"
#include "base/macros.h"
+#include "base/no_destructor.h"
namespace gfx {
@@ -31,8 +32,8 @@ FontRenderParams GetFontRenderParams(const FontRenderParamsQuery& query,
if (family_out)
NOTIMPLEMENTED();
// TODO: Query the OS for font render settings instead of returning defaults.
- CR_DEFINE_STATIC_LOCAL(const gfx::FontRenderParams, params, (LoadDefaults()));
- return params;
+ static const base::NoDestructor<gfx::FontRenderParams> params(LoadDefaults());
+ return *params;
}
} // namespace gfx
diff --git a/chromium/ui/gfx/font_unittest.cc b/chromium/ui/gfx/font_unittest.cc
index 00945ae910d..e9e810640ec 100644
--- a/chromium/ui/gfx/font_unittest.cc
+++ b/chromium/ui/gfx/font_unittest.cc
@@ -21,33 +21,6 @@ namespace {
using FontTest = testing::Test;
-#if defined(OS_WIN)
-class ScopedMinimumFontSizeCallback {
- public:
- explicit ScopedMinimumFontSizeCallback(int minimum_size) {
- minimum_size_ = minimum_size;
- old_callback_ = PlatformFontWin::get_minimum_font_size_callback;
- PlatformFontWin::get_minimum_font_size_callback = &GetMinimumFontSize;
- }
-
- ~ScopedMinimumFontSizeCallback() {
- PlatformFontWin::get_minimum_font_size_callback = old_callback_;
- }
-
- private:
- static int GetMinimumFontSize() {
- return minimum_size_;
- }
-
- PlatformFontWin::GetMinimumFontSizeCallback old_callback_;
- static int minimum_size_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedMinimumFontSizeCallback);
-};
-
-int ScopedMinimumFontSizeCallback::minimum_size_ = 0;
-#endif // defined(OS_WIN)
-
TEST_F(FontTest, LoadArial) {
Font cf(kTestFontName, 16);
#if defined(OS_WIN) || defined(OS_MACOSX) || defined(OS_IOS)
@@ -151,8 +124,7 @@ TEST_F(FontTest, DeriveFont) {
#if defined(OS_WIN)
TEST_F(FontTest, DeriveResizesIfSizeTooSmall) {
Font cf(kTestFontName, 8);
- // The minimum font size is set to 5 in browser_main.cc.
- ScopedMinimumFontSizeCallback minimum_size(5);
+ PlatformFontWin::SetGetMinimumFontSizeCallback([] { return 5; });
Font derived_font = cf.Derive(-4, cf.GetStyle(), cf.GetWeight());
EXPECT_EQ(5, derived_font.GetFontSize());
@@ -160,8 +132,7 @@ TEST_F(FontTest, DeriveResizesIfSizeTooSmall) {
TEST_F(FontTest, DeriveKeepsOriginalSizeIfHeightOk) {
Font cf(kTestFontName, 8);
- // The minimum font size is set to 5 in browser_main.cc.
- ScopedMinimumFontSizeCallback minimum_size(5);
+ PlatformFontWin::SetGetMinimumFontSizeCallback([] { return 5; });
Font derived_font = cf.Derive(-2, cf.GetStyle(), cf.GetWeight());
EXPECT_EQ(6, derived_font.GetFontSize());
diff --git a/chromium/ui/gfx/geometry/BUILD.gn b/chromium/ui/gfx/geometry/BUILD.gn
index 74043fa5e0f..6450fdd952c 100644
--- a/chromium/ui/gfx/geometry/BUILD.gn
+++ b/chromium/ui/gfx/geometry/BUILD.gn
@@ -16,6 +16,7 @@ jumbo_component("geometry") {
"cubic_bezier.h",
"dip_util.cc",
"dip_util.h",
+ "geometry_export.h",
"insets.cc",
"insets.h",
"insets_f.cc",
@@ -59,11 +60,10 @@ jumbo_component("geometry") {
"vector3d_f.h",
]
- defines = [ "GFX_IMPLEMENTATION" ]
+ defines = [ "GEOMETRY_IMPLEMENTATION" ]
deps = [
"//base",
- "//ui/gfx:gfx_export",
]
if (is_android && !is_debug) {
diff --git a/chromium/ui/gfx/geometry/angle_conversions.h b/chromium/ui/gfx/geometry/angle_conversions.h
index 68e9209f726..876ad5c5ac4 100644
--- a/chromium/ui/gfx/geometry/angle_conversions.h
+++ b/chromium/ui/gfx/geometry/angle_conversions.h
@@ -6,21 +6,21 @@
#define UI_GFX_GEOMETRY_ANGLE_CONVERSIONS_H_
#include "base/numerics/math_constants.h"
-#include "ui/gfx/gfx_export.h"
+#include "ui/gfx/geometry/geometry_export.h"
namespace gfx {
-GFX_EXPORT constexpr double DegToRad(double deg) {
+GEOMETRY_EXPORT constexpr double DegToRad(double deg) {
return deg * base::kPiDouble / 180.0;
}
-GFX_EXPORT constexpr float DegToRad(float deg) {
+GEOMETRY_EXPORT constexpr float DegToRad(float deg) {
return deg * base::kPiFloat / 180.0f;
}
-GFX_EXPORT constexpr double RadToDeg(double rad) {
+GEOMETRY_EXPORT constexpr double RadToDeg(double rad) {
return rad * 180.0 / base::kPiDouble;
}
-GFX_EXPORT constexpr float RadToDeg(float rad) {
+GEOMETRY_EXPORT constexpr float RadToDeg(float rad) {
return rad * 180.0f / base::kPiFloat;
}
diff --git a/chromium/ui/gfx/geometry/axis_transform2d.h b/chromium/ui/gfx/geometry/axis_transform2d.h
index 1829bf60fcf..6aec0e5acbf 100644
--- a/chromium/ui/gfx/geometry/axis_transform2d.h
+++ b/chromium/ui/gfx/geometry/axis_transform2d.h
@@ -5,9 +5,9 @@
#ifndef UI_GFX_GEOMETRY_AXIS_TRANSFORM2D_H_
#define UI_GFX_GEOMETRY_AXIS_TRANSFORM2D_H_
+#include "ui/gfx/geometry/geometry_export.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/geometry/vector2d_f.h"
-#include "ui/gfx/gfx_export.h"
namespace gfx {
@@ -16,7 +16,7 @@ namespace gfx {
// Internally this is stored as a scalar pre-scale factor, and a vector
// for post-translation. The class constructor and member accessor follows
// the same convention.
-class GFX_EXPORT AxisTransform2d {
+class GEOMETRY_EXPORT AxisTransform2d {
public:
constexpr AxisTransform2d() = default;
constexpr AxisTransform2d(float scale, const Vector2dF& translation)
diff --git a/chromium/ui/gfx/geometry/box_f.h b/chromium/ui/gfx/geometry/box_f.h
index b4d9eff1c02..443174d3eb6 100644
--- a/chromium/ui/gfx/geometry/box_f.h
+++ b/chromium/ui/gfx/geometry/box_f.h
@@ -15,7 +15,7 @@ namespace gfx {
// A 3d version of gfx::RectF, with the positive z-axis pointed towards
// the camera.
-class GFX_EXPORT BoxF {
+class GEOMETRY_EXPORT BoxF {
public:
constexpr BoxF() : BoxF(0, 0, 0) {}
constexpr BoxF(float width, float height, float depth)
@@ -114,7 +114,7 @@ class GFX_EXPORT BoxF {
float depth_;
};
-GFX_EXPORT BoxF UnionBoxes(const BoxF& a, const BoxF& b);
+GEOMETRY_EXPORT BoxF UnionBoxes(const BoxF& a, const BoxF& b);
inline BoxF ScaleBox(const BoxF& b,
float x_scale,
diff --git a/chromium/ui/gfx/geometry/cubic_bezier.h b/chromium/ui/gfx/geometry/cubic_bezier.h
index 013123999c5..dcda5798695 100644
--- a/chromium/ui/gfx/geometry/cubic_bezier.h
+++ b/chromium/ui/gfx/geometry/cubic_bezier.h
@@ -6,11 +6,11 @@
#define UI_GFX_GEOMETRY_CUBIC_BEZIER_H_
#include "base/macros.h"
-#include "ui/gfx/gfx_export.h"
+#include "ui/gfx/geometry/geometry_export.h"
namespace gfx {
-class GFX_EXPORT CubicBezier {
+class GEOMETRY_EXPORT CubicBezier {
public:
CubicBezier(double p1x, double p1y, double p2x, double p2y);
CubicBezier(const CubicBezier& other);
diff --git a/chromium/ui/gfx/geometry/dip_util.h b/chromium/ui/gfx/geometry/dip_util.h
index e88d49b0079..cb344c93fed 100644
--- a/chromium/ui/gfx/geometry/dip_util.h
+++ b/chromium/ui/gfx/geometry/dip_util.h
@@ -5,7 +5,7 @@
#ifndef UI_GFX_GEOMETRY_DIP_UTIL_H_
#define UI_GFX_GEOMETRY_DIP_UTIL_H_
-#include "ui/gfx/gfx_export.h"
+#include "ui/gfx/geometry/geometry_export.h"
namespace gfx {
@@ -15,27 +15,31 @@ class PointF;
class Rect;
class Size;
-GFX_EXPORT gfx::Insets ConvertInsetsToDIP(float scale_factor,
- const gfx::Insets& insets_in_pixel);
-GFX_EXPORT gfx::Point ConvertPointToDIP(float scale_factor,
- const gfx::Point& point_in_pixel);
-GFX_EXPORT gfx::PointF ConvertPointToDIP(float scale_factor,
- const gfx::PointF& point_in_pixel);
-GFX_EXPORT gfx::Size ConvertSizeToDIP(float scale_factor,
- const gfx::Size& size_in_pixel);
-GFX_EXPORT gfx::Rect ConvertRectToDIP(float scale_factor,
- const gfx::Rect& rect_in_pixel);
+GEOMETRY_EXPORT gfx::Insets ConvertInsetsToDIP(
+ float scale_factor,
+ const gfx::Insets& insets_in_pixel);
+GEOMETRY_EXPORT gfx::Point ConvertPointToDIP(float scale_factor,
+ const gfx::Point& point_in_pixel);
+GEOMETRY_EXPORT gfx::PointF ConvertPointToDIP(
+ float scale_factor,
+ const gfx::PointF& point_in_pixel);
+GEOMETRY_EXPORT gfx::Size ConvertSizeToDIP(float scale_factor,
+ const gfx::Size& size_in_pixel);
+GEOMETRY_EXPORT gfx::Rect ConvertRectToDIP(float scale_factor,
+ const gfx::Rect& rect_in_pixel);
-GFX_EXPORT gfx::Insets ConvertInsetsToPixel(float scale_factor,
- const gfx::Insets& insets_in_dip);
-GFX_EXPORT gfx::Point ConvertPointToPixel(float scale_factor,
- const gfx::Point& point_in_dip);
-GFX_EXPORT gfx::PointF ConvertPointToPixel(float scale_factor,
- const gfx::PointF& point_in_dip);
-GFX_EXPORT gfx::Size ConvertSizeToPixel(float scale_factor,
- const gfx::Size& size_in_dip);
-GFX_EXPORT gfx::Rect ConvertRectToPixel(float scale_factor,
- const gfx::Rect& rect_in_dip);
+GEOMETRY_EXPORT gfx::Insets ConvertInsetsToPixel(
+ float scale_factor,
+ const gfx::Insets& insets_in_dip);
+GEOMETRY_EXPORT gfx::Point ConvertPointToPixel(float scale_factor,
+ const gfx::Point& point_in_dip);
+GEOMETRY_EXPORT gfx::PointF ConvertPointToPixel(
+ float scale_factor,
+ const gfx::PointF& point_in_dip);
+GEOMETRY_EXPORT gfx::Size ConvertSizeToPixel(float scale_factor,
+ const gfx::Size& size_in_dip);
+GEOMETRY_EXPORT gfx::Rect ConvertRectToPixel(float scale_factor,
+ const gfx::Rect& rect_in_dip);
} // gfx
#endif // UI_GFX_GEOMETRY_DIP_UTIL_H_
diff --git a/chromium/ui/gfx/geometry/geometry_export.h b/chromium/ui/gfx/geometry/geometry_export.h
new file mode 100644
index 00000000000..5e687875eb9
--- /dev/null
+++ b/chromium/ui/gfx/geometry/geometry_export.h
@@ -0,0 +1,29 @@
+// 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_GFX_GEOMETRY_GEOMETRY_EXPORT_H_
+#define UI_GFX_GEOMETRY_GEOMETRY_EXPORT_H_
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(GEOMETRY_IMPLEMENTATION)
+#define GEOMETRY_EXPORT __declspec(dllexport)
+#else
+#define GEOMETRY_EXPORT __declspec(dllimport)
+#endif // defined(GEOMETRY_IMPLEMENTATION)
+
+#else // defined(WIN32)
+#if defined(GEOMETRY_IMPLEMENTATION)
+#define GEOMETRY_EXPORT __attribute__((visibility("default")))
+#else
+#define GEOMETRY_EXPORT
+#endif
+#endif
+
+#else // defined(COMPONENT_BUILD)
+#define GEOMETRY_EXPORT
+#endif
+
+#endif // UI_GFX_GEOMETRY_GEOMETRY_EXPORT_H_
diff --git a/chromium/ui/gfx/geometry/insets.h b/chromium/ui/gfx/geometry/insets.h
index a88bae3e42b..10516583b82 100644
--- a/chromium/ui/gfx/geometry/insets.h
+++ b/chromium/ui/gfx/geometry/insets.h
@@ -7,8 +7,8 @@
#include <string>
+#include "ui/gfx/geometry/geometry_export.h"
#include "ui/gfx/geometry/insets_f.h"
-#include "ui/gfx/gfx_export.h"
namespace gfx {
@@ -21,7 +21,7 @@ class Vector2d;
// This can be used to represent a space within a rectangle, by "shrinking" the
// rectangle by the inset amount on all four sides. Alternatively, it can
// represent a border that has a different thickness on each side.
-class GFX_EXPORT Insets {
+class GEOMETRY_EXPORT Insets {
public:
constexpr Insets() : top_(0), left_(0), bottom_(0), right_(0) {}
constexpr explicit Insets(int all)
diff --git a/chromium/ui/gfx/geometry/insets_f.h b/chromium/ui/gfx/geometry/insets_f.h
index 32302879578..281a599b97d 100644
--- a/chromium/ui/gfx/geometry/insets_f.h
+++ b/chromium/ui/gfx/geometry/insets_f.h
@@ -7,12 +7,12 @@
#include <string>
-#include "ui/gfx/gfx_export.h"
+#include "ui/gfx/geometry/geometry_export.h"
namespace gfx {
// A floating point version of gfx::Insets.
-class GFX_EXPORT InsetsF {
+class GEOMETRY_EXPORT InsetsF {
public:
constexpr InsetsF() : top_(0.f), left_(0.f), bottom_(0.f), right_(0.f) {}
constexpr explicit InsetsF(float all)
diff --git a/chromium/ui/gfx/geometry/matrix3_f.h b/chromium/ui/gfx/geometry/matrix3_f.h
index 7fab2e3e7c7..065a7fb3f92 100644
--- a/chromium/ui/gfx/geometry/matrix3_f.h
+++ b/chromium/ui/gfx/geometry/matrix3_f.h
@@ -10,7 +10,7 @@
namespace gfx {
-class GFX_EXPORT Matrix3F {
+class GEOMETRY_EXPORT Matrix3F {
public:
~Matrix3F();
@@ -131,8 +131,10 @@ inline Matrix3F operator-(const Matrix3F& lhs, const Matrix3F& rhs) {
return lhs.Subtract(rhs);
}
-GFX_EXPORT Matrix3F MatrixProduct(const Matrix3F& lhs, const Matrix3F& rhs);
-GFX_EXPORT Vector3dF MatrixProduct(const Matrix3F& lhs, const Vector3dF& rhs);
+GEOMETRY_EXPORT Matrix3F MatrixProduct(const Matrix3F& lhs,
+ const Matrix3F& rhs);
+GEOMETRY_EXPORT Vector3dF MatrixProduct(const Matrix3F& lhs,
+ const Vector3dF& rhs);
} // namespace gfx
diff --git a/chromium/ui/gfx/geometry/point.h b/chromium/ui/gfx/geometry/point.h
index b1ba5065de4..f68433b9065 100644
--- a/chromium/ui/gfx/geometry/point.h
+++ b/chromium/ui/gfx/geometry/point.h
@@ -11,8 +11,8 @@
#include "base/numerics/clamped_math.h"
#include "build/build_config.h"
+#include "ui/gfx/geometry/geometry_export.h"
#include "ui/gfx/geometry/vector2d.h"
-#include "ui/gfx/gfx_export.h"
#if defined(OS_WIN)
typedef unsigned long DWORD;
@@ -24,7 +24,7 @@ typedef struct CGPoint CGPoint;
namespace gfx {
// A point has an x and y coordinate.
-class GFX_EXPORT Point {
+class GEOMETRY_EXPORT Point {
public:
constexpr Point() : x_(0), y_(0) {}
constexpr Point(int x, int y) : x_(x), y_(y) {}
@@ -130,18 +130,18 @@ inline Point PointAtOffsetFromOrigin(const Vector2d& offset_from_origin) {
void PrintTo(const Point& point, ::std::ostream* os);
// Helper methods to scale a gfx::Point to a new gfx::Point.
-GFX_EXPORT Point ScaleToCeiledPoint(const Point& point,
- float x_scale,
- float y_scale);
-GFX_EXPORT Point ScaleToCeiledPoint(const Point& point, float x_scale);
-GFX_EXPORT Point ScaleToFlooredPoint(const Point& point,
- float x_scale,
- float y_scale);
-GFX_EXPORT Point ScaleToFlooredPoint(const Point& point, float x_scale);
-GFX_EXPORT Point ScaleToRoundedPoint(const Point& point,
- float x_scale,
- float y_scale);
-GFX_EXPORT Point ScaleToRoundedPoint(const Point& point, float x_scale);
+GEOMETRY_EXPORT Point ScaleToCeiledPoint(const Point& point,
+ float x_scale,
+ float y_scale);
+GEOMETRY_EXPORT Point ScaleToCeiledPoint(const Point& point, float x_scale);
+GEOMETRY_EXPORT Point ScaleToFlooredPoint(const Point& point,
+ float x_scale,
+ float y_scale);
+GEOMETRY_EXPORT Point ScaleToFlooredPoint(const Point& point, float x_scale);
+GEOMETRY_EXPORT Point ScaleToRoundedPoint(const Point& point,
+ float x_scale,
+ float y_scale);
+GEOMETRY_EXPORT Point ScaleToRoundedPoint(const Point& point, float x_scale);
} // namespace gfx
diff --git a/chromium/ui/gfx/geometry/point3_f.h b/chromium/ui/gfx/geometry/point3_f.h
index 15a560c4972..e295e988ffe 100644
--- a/chromium/ui/gfx/geometry/point3_f.h
+++ b/chromium/ui/gfx/geometry/point3_f.h
@@ -8,14 +8,14 @@
#include <iosfwd>
#include <string>
+#include "ui/gfx/geometry/geometry_export.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/vector3d_f.h"
-#include "ui/gfx/gfx_export.h"
namespace gfx {
// A point has an x, y and z coordinate.
-class GFX_EXPORT Point3F {
+class GEOMETRY_EXPORT Point3F {
public:
constexpr Point3F() : x_(0), y_(0), z_(0) {}
constexpr Point3F(float x, float y, float z) : x_(x), y_(y), z_(z) {}
@@ -89,15 +89,15 @@ inline bool operator!=(const Point3F& lhs, const Point3F& rhs) {
}
// Add a vector to a point, producing a new point offset by the vector.
-GFX_EXPORT Point3F operator+(const Point3F& lhs, const Vector3dF& rhs);
+GEOMETRY_EXPORT Point3F operator+(const Point3F& lhs, const Vector3dF& rhs);
// Subtract a vector from a point, producing a new point offset by the vector's
// inverse.
-GFX_EXPORT Point3F operator-(const Point3F& lhs, const Vector3dF& rhs);
+GEOMETRY_EXPORT Point3F operator-(const Point3F& lhs, const Vector3dF& rhs);
// Subtract one point from another, producing a vector that represents the
// distances between the two points along each axis.
-GFX_EXPORT Vector3dF operator-(const Point3F& lhs, const Point3F& rhs);
+GEOMETRY_EXPORT Vector3dF operator-(const Point3F& lhs, const Point3F& rhs);
inline Point3F PointAtOffsetFromOrigin(const Vector3dF& offset) {
return Point3F(offset.x(), offset.y(), offset.z());
diff --git a/chromium/ui/gfx/geometry/point_conversions.h b/chromium/ui/gfx/geometry/point_conversions.h
index bfab9e4e463..894272c6bd3 100644
--- a/chromium/ui/gfx/geometry/point_conversions.h
+++ b/chromium/ui/gfx/geometry/point_conversions.h
@@ -11,13 +11,13 @@
namespace gfx {
// Returns a Point with each component from the input PointF floored.
-GFX_EXPORT Point ToFlooredPoint(const PointF& point);
+GEOMETRY_EXPORT Point ToFlooredPoint(const PointF& point);
// Returns a Point with each component from the input PointF ceiled.
-GFX_EXPORT Point ToCeiledPoint(const PointF& point);
+GEOMETRY_EXPORT Point ToCeiledPoint(const PointF& point);
// Returns a Point with each component from the input PointF rounded.
-GFX_EXPORT Point ToRoundedPoint(const PointF& point);
+GEOMETRY_EXPORT Point ToRoundedPoint(const PointF& point);
} // namespace gfx
diff --git a/chromium/ui/gfx/geometry/point_f.h b/chromium/ui/gfx/geometry/point_f.h
index 5d92b1100c4..a3823bcb0f5 100644
--- a/chromium/ui/gfx/geometry/point_f.h
+++ b/chromium/ui/gfx/geometry/point_f.h
@@ -9,14 +9,14 @@
#include <string>
#include <tuple>
+#include "ui/gfx/geometry/geometry_export.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/vector2d_f.h"
-#include "ui/gfx/gfx_export.h"
namespace gfx {
// A floating version of gfx::Point.
-class GFX_EXPORT PointF {
+class GEOMETRY_EXPORT PointF {
public:
constexpr PointF() : x_(0.f), y_(0.f) {}
constexpr PointF(float x, float y) : x_(x), y_(y) {}
@@ -110,7 +110,9 @@ inline PointF PointAtOffsetFromOrigin(const Vector2dF& offset_from_origin) {
return PointF(offset_from_origin.x(), offset_from_origin.y());
}
-GFX_EXPORT PointF ScalePoint(const PointF& p, float x_scale, float y_scale);
+GEOMETRY_EXPORT PointF ScalePoint(const PointF& p,
+ float x_scale,
+ float y_scale);
inline PointF ScalePoint(const PointF& p, float scale) {
return ScalePoint(p, scale, scale);
diff --git a/chromium/ui/gfx/geometry/quad_f.h b/chromium/ui/gfx/geometry/quad_f.h
index 8e45b3e2dea..3f9e08ac3b9 100644
--- a/chromium/ui/gfx/geometry/quad_f.h
+++ b/chromium/ui/gfx/geometry/quad_f.h
@@ -13,15 +13,15 @@
#include <string>
#include "base/logging.h"
+#include "ui/gfx/geometry/geometry_export.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/rect_f.h"
-#include "ui/gfx/gfx_export.h"
namespace gfx {
// A Quad is defined by four corners, allowing it to have edges that are not
// axis-aligned, unlike a Rect.
-class GFX_EXPORT QuadF {
+class GEOMETRY_EXPORT QuadF {
public:
constexpr QuadF() = default;
constexpr QuadF(const PointF& p1,
@@ -115,10 +115,10 @@ inline bool operator!=(const QuadF& lhs, const QuadF& rhs) {
}
// Add a vector to a quad, offseting each point in the quad by the vector.
-GFX_EXPORT QuadF operator+(const QuadF& lhs, const Vector2dF& rhs);
+GEOMETRY_EXPORT QuadF operator+(const QuadF& lhs, const Vector2dF& rhs);
// Subtract a vector from a quad, offseting each point in the quad by the
// inverse of the vector.
-GFX_EXPORT QuadF operator-(const QuadF& lhs, const Vector2dF& rhs);
+GEOMETRY_EXPORT QuadF operator-(const QuadF& lhs, const Vector2dF& rhs);
// This is declared here for use in gtest-based unit tests but is defined in
// the //ui/gfx:test_support target. Depend on that to use this in your unit
diff --git a/chromium/ui/gfx/geometry/quaternion.h b/chromium/ui/gfx/geometry/quaternion.h
index 7f65b796e6f..2558f271063 100644
--- a/chromium/ui/gfx/geometry/quaternion.h
+++ b/chromium/ui/gfx/geometry/quaternion.h
@@ -7,13 +7,13 @@
#include <string>
-#include "ui/gfx/gfx_export.h"
+#include "ui/gfx/geometry/geometry_export.h"
namespace gfx {
class Vector3dF;
-class GFX_EXPORT Quaternion {
+class GEOMETRY_EXPORT Quaternion {
public:
constexpr Quaternion() = default;
constexpr Quaternion(double x, double y, double z, double w)
diff --git a/chromium/ui/gfx/geometry/rect.h b/chromium/ui/gfx/geometry/rect.h
index 8a4a3f878f6..84dc72c069c 100644
--- a/chromium/ui/gfx/geometry/rect.h
+++ b/chromium/ui/gfx/geometry/rect.h
@@ -33,7 +33,7 @@ namespace gfx {
class Insets;
-class GFX_EXPORT Rect {
+class GEOMETRY_EXPORT Rect {
public:
constexpr Rect() = default;
constexpr Rect(int width, int height) : size_(width, height) {}
@@ -258,16 +258,16 @@ inline bool operator!=(const Rect& lhs, const Rect& rhs) {
return !(lhs == rhs);
}
-GFX_EXPORT Rect operator+(const Rect& lhs, const Vector2d& rhs);
-GFX_EXPORT Rect operator-(const Rect& lhs, const Vector2d& rhs);
+GEOMETRY_EXPORT Rect operator+(const Rect& lhs, const Vector2d& rhs);
+GEOMETRY_EXPORT Rect operator-(const Rect& lhs, const Vector2d& rhs);
inline Rect operator+(const Vector2d& lhs, const Rect& rhs) {
return rhs + lhs;
}
-GFX_EXPORT Rect IntersectRects(const Rect& a, const Rect& b);
-GFX_EXPORT Rect UnionRects(const Rect& a, const Rect& b);
-GFX_EXPORT Rect SubtractRects(const Rect& a, const Rect& b);
+GEOMETRY_EXPORT Rect IntersectRects(const Rect& a, const Rect& b);
+GEOMETRY_EXPORT Rect UnionRects(const Rect& a, const Rect& b);
+GEOMETRY_EXPORT Rect SubtractRects(const Rect& a, const Rect& b);
// Constructs a rectangle with |p1| and |p2| as opposite corners.
//
@@ -275,7 +275,7 @@ GFX_EXPORT Rect SubtractRects(const Rect& a, const Rect& b);
// points", except that we consider points on the right/bottom edges of the
// rect to be outside the rect. So technically one or both points will not be
// contained within the rect, because they will appear on one of these edges.
-GFX_EXPORT Rect BoundingRect(const Point& p1, const Point& p2);
+GEOMETRY_EXPORT Rect BoundingRect(const Point& p1, const Point& p2);
// Scales the rect and returns the enclosing rect. Use this only the inputs are
// known to not overflow. Use ScaleToEnclosingRectSafe if the inputs are
diff --git a/chromium/ui/gfx/geometry/rect_conversions.cc b/chromium/ui/gfx/geometry/rect_conversions.cc
index 3a5b2dceade..43d866f8dba 100644
--- a/chromium/ui/gfx/geometry/rect_conversions.cc
+++ b/chromium/ui/gfx/geometry/rect_conversions.cc
@@ -12,6 +12,20 @@
namespace gfx {
+namespace {
+
+int ToFlooredIntIgnoringError(float f, float error) {
+ int rounded = ToRoundedInt(f);
+ return std::abs(rounded - f) < error ? rounded : ToFlooredInt(f);
+}
+
+int ToCeiledIntIgnoringError(float f, float error) {
+ int rounded = ToRoundedInt(f);
+ return std::abs(rounded - f) < error ? rounded : ToCeiledInt(f);
+}
+
+} // anonymous namespace
+
Rect ToEnclosingRect(const RectF& r) {
int left = ToFlooredInt(r.x());
int right = r.width() ? ToCeiledInt(r.right()) : left;
@@ -23,6 +37,17 @@ Rect ToEnclosingRect(const RectF& r) {
return result;
}
+Rect ToEnclosingRectIgnoringError(const RectF& r, float error) {
+ int left = ToFlooredIntIgnoringError(r.x(), error);
+ int right = r.width() ? ToCeiledIntIgnoringError(r.right(), error) : left;
+ int top = ToFlooredIntIgnoringError(r.y(), error);
+ int bottom = r.height() ? ToCeiledIntIgnoringError(r.bottom(), error) : top;
+
+ Rect result;
+ result.SetByBounds(left, top, right, bottom);
+ return result;
+}
+
Rect ToEnclosedRect(const RectF& rect) {
Rect result;
result.SetByBounds(ToCeiledInt(rect.x()), ToCeiledInt(rect.y()),
diff --git a/chromium/ui/gfx/geometry/rect_conversions.h b/chromium/ui/gfx/geometry/rect_conversions.h
index 617074abeee..44b94d9104a 100644
--- a/chromium/ui/gfx/geometry/rect_conversions.h
+++ b/chromium/ui/gfx/geometry/rect_conversions.h
@@ -11,25 +11,33 @@
namespace gfx {
// Returns the smallest Rect that encloses the given RectF.
-GFX_EXPORT Rect ToEnclosingRect(const RectF& rect);
+GEOMETRY_EXPORT Rect ToEnclosingRect(const RectF& rect);
+
+// Similar to ToEnclosingRect(), but for each edge, if the distance between the
+// edge and the nearest integer grid is smaller than |error|, the edge is
+// snapped to the integer grid. Unlike ToNearestRect() which only accepts
+// integer rect with or without floating point error, this function also accepts
+// non-integer rect.
+GEOMETRY_EXPORT Rect ToEnclosingRectIgnoringError(const RectF& rect,
+ float error);
// Returns the largest Rect that is enclosed by the given RectF.
-GFX_EXPORT Rect ToEnclosedRect(const RectF& rect);
+GEOMETRY_EXPORT Rect ToEnclosedRect(const RectF& rect);
// Returns the Rect after snapping the corners of the RectF to an integer grid.
// This should only be used when the RectF you provide is expected to be an
// integer rect with floating point error. If it is an arbitrary RectF, then
// you should use a different method.
-GFX_EXPORT Rect ToNearestRect(const RectF& rect);
+GEOMETRY_EXPORT Rect ToNearestRect(const RectF& rect);
// Returns true if the Rect produced after snapping the corners of the RectF
// to an integer grid is withing |distance|.
-GFX_EXPORT bool IsNearestRectWithinDistance(
- const gfx::RectF& rect, float distance);
+GEOMETRY_EXPORT bool IsNearestRectWithinDistance(const gfx::RectF& rect,
+ float distance);
// Returns a Rect obtained by flooring the values of the given RectF.
// Please prefer the previous two functions in new code.
-GFX_EXPORT Rect ToFlooredRectDeprecated(const RectF& rect);
+GEOMETRY_EXPORT Rect ToFlooredRectDeprecated(const RectF& rect);
} // namespace gfx
diff --git a/chromium/ui/gfx/geometry/rect_f.h b/chromium/ui/gfx/geometry/rect_f.h
index 7ec5c97549b..e07f86d50db 100644
--- a/chromium/ui/gfx/geometry/rect_f.h
+++ b/chromium/ui/gfx/geometry/rect_f.h
@@ -23,7 +23,7 @@ namespace gfx {
class InsetsF;
// A floating version of gfx::Rect.
-class GFX_EXPORT RectF {
+class GEOMETRY_EXPORT RectF {
public:
constexpr RectF() = default;
constexpr RectF(float width, float height) : size_(width, height) {}
@@ -225,9 +225,9 @@ inline RectF operator+(const Vector2dF& lhs, const RectF& rhs) {
return rhs + lhs;
}
-GFX_EXPORT RectF IntersectRects(const RectF& a, const RectF& b);
-GFX_EXPORT RectF UnionRects(const RectF& a, const RectF& b);
-GFX_EXPORT RectF SubtractRects(const RectF& a, const RectF& b);
+GEOMETRY_EXPORT RectF IntersectRects(const RectF& a, const RectF& b);
+GEOMETRY_EXPORT RectF UnionRects(const RectF& a, const RectF& b);
+GEOMETRY_EXPORT RectF SubtractRects(const RectF& a, const RectF& b);
inline RectF ScaleRect(const RectF& r, float x_scale, float y_scale) {
return RectF(r.x() * x_scale, r.y() * y_scale,
@@ -244,7 +244,7 @@ inline RectF ScaleRect(const RectF& r, float scale) {
// points", except that we consider points on the right/bottom edges of the
// rect to be outside the rect. So technically one or both points will not be
// contained within the rect, because they will appear on one of these edges.
-GFX_EXPORT RectF BoundingRect(const PointF& p1, const PointF& p2);
+GEOMETRY_EXPORT RectF BoundingRect(const PointF& p1, const PointF& p2);
// This is declared here for use in gtest-based unit tests but is defined in
// the //ui/gfx:test_support target. Depend on that to use this in your unit
diff --git a/chromium/ui/gfx/geometry/rect_unittest.cc b/chromium/ui/gfx/geometry/rect_unittest.cc
index 7acfb806501..1f6d576b9e4 100644
--- a/chromium/ui/gfx/geometry/rect_unittest.cc
+++ b/chromium/ui/gfx/geometry/rect_unittest.cc
@@ -6,7 +6,7 @@
#include <stddef.h>
-#include "base/macros.h"
+#include "base/stl_util.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/rect.h"
@@ -40,7 +40,7 @@ TEST(RectTest, Contains) {
{0, 0, -10, -10, 0, 0, false},
#endif
};
- for (size_t i = 0; i < arraysize(contains_cases); ++i) {
+ for (size_t i = 0; i < base::size(contains_cases); ++i) {
const ContainsCase& value = contains_cases[i];
Rect rect(value.rect_x, value.rect_y, value.rect_width, value.rect_height);
EXPECT_EQ(value.contained, rect.Contains(value.point_x, value.point_y));
@@ -70,7 +70,7 @@ TEST(RectTest, Intersects) {
{ 10, 10, 10, 10, 20, 15, 10, 10, false },
{ 10, 10, 10, 10, 21, 15, 10, 10, false }
};
- for (size_t i = 0; i < arraysize(tests); ++i) {
+ for (size_t i = 0; i < base::size(tests); ++i) {
Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
EXPECT_EQ(tests[i].intersects, r1.Intersects(r2));
@@ -112,7 +112,7 @@ TEST(RectTest, Intersect) {
0, 0, 2, 2,
0, 0, 0, 0 }
};
- for (size_t i = 0; i < arraysize(tests); ++i) {
+ for (size_t i = 0; i < base::size(tests); ++i) {
Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
Rect r3(tests[i].x3, tests[i].y3, tests[i].w3, tests[i].h3);
@@ -161,7 +161,7 @@ TEST(RectTest, Union) {
2, 2, 2, 2,
2, 2, 2, 2 }
};
- for (size_t i = 0; i < arraysize(tests); ++i) {
+ for (size_t i = 0; i < base::size(tests); ++i) {
Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
Rect r3(tests[i].x3, tests[i].y3, tests[i].w3, tests[i].h3);
@@ -213,7 +213,7 @@ TEST(RectTest, AdjustToFit) {
0, 0, 3, 3,
2, 2, 1, 1 }
};
- for (size_t i = 0; i < arraysize(tests); ++i) {
+ for (size_t i = 0; i < base::size(tests); ++i) {
Rect r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
Rect r3(tests[i].x3, tests[i].y3, tests[i].w3, tests[i].h3);
@@ -457,7 +457,7 @@ TEST(RectTest, ScaleRect) {
std::numeric_limits<float>::max() }
};
- for (size_t i = 0; i < arraysize(tests); ++i) {
+ for (size_t i = 0; i < base::size(tests); ++i) {
RectF r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
RectF r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
@@ -496,9 +496,12 @@ TEST(RectTest, ToEnclosedRect) {
{{max_float, max_float, 2.0f, 2.0f}, {max_int, max_int, 0, 0}},
{{0.0f, 0.0f, max_float, max_float}, {0, 0, max_int, max_int}},
{{20000.5f, 20000.5f, 0.5f, 0.5f}, {20001, 20001, 0, 0}},
- {{max_int_f, max_int_f, max_int_f, max_int_f}, {max_int, max_int, 0, 0}}};
+ {{max_int_f, max_int_f, max_int_f, max_int_f}, {max_int, max_int, 0, 0}},
+ {{1.9999f, 2.0002f, 5.9998f, 6.0001f}, {2, 3, 5, 5}},
+ {{1.9999f, 2.0001f, 6.0002f, 5.9998f}, {2, 3, 6, 4}},
+ {{1.9998f, 2.0002f, 6.0001f, 5.9999f}, {2, 3, 5, 5}}};
- for (size_t i = 0; i < arraysize(tests); ++i) {
+ for (size_t i = 0; i < base::size(tests); ++i) {
RectF source(tests[i].in.x, tests[i].in.y, tests[i].in.width,
tests[i].in.height);
Rect enclosed = ToEnclosedRect(source);
@@ -556,9 +559,12 @@ TEST(RectTest, ToEnclosingRect) {
{{0.0f, 0.0f, max_float, max_float}, {0, 0, max_int, max_int}},
{{20000.5f, 20000.5f, 0.5f, 0.5f}, {20000, 20000, 1, 1}},
{{max_int_f, max_int_f, max_int_f, max_int_f}, {max_int, max_int, 0, 0}},
- {{-0.5f, -0.5f, 22777712.f, 1.f}, {-1, -1, 22777713, 2}}};
+ {{-0.5f, -0.5f, 22777712.f, 1.f}, {-1, -1, 22777713, 2}},
+ {{1.9999f, 2.0002f, 5.9998f, 6.0001f}, {1, 2, 7, 7}},
+ {{1.9999f, 2.0001f, 6.0002f, 5.9998f}, {1, 2, 8, 6}},
+ {{1.9998f, 2.0002f, 6.0001f, 5.9999f}, {1, 2, 7, 7}}};
- for (size_t i = 0; i < arraysize(tests); ++i) {
+ for (size_t i = 0; i < base::size(tests); ++i) {
RectF source(tests[i].in.x, tests[i].in.y, tests[i].in.width,
tests[i].in.height);
@@ -585,6 +591,53 @@ TEST(RectTest, ToEnclosingRect) {
}
}
+TEST(RectTest, ToEnclosingRectIgnoringError) {
+ static const int max_int = std::numeric_limits<int>::max();
+ static const float max_float = std::numeric_limits<float>::max();
+ static const float epsilon_float = std::numeric_limits<float>::epsilon();
+ static const float max_int_f = static_cast<float>(max_int);
+ static const float error = 0.001f;
+ static const struct Test {
+ struct {
+ float x;
+ float y;
+ float width;
+ float height;
+ } in;
+ struct {
+ int x;
+ int y;
+ int width;
+ int height;
+ } expected;
+ } tests[] = {
+ {{0.0f, 0.0f, 0.0f, 0.0f}, {0, 0, 0, 0}},
+ {{5.5f, 5.5f, 0.0f, 0.0f}, {5, 5, 0, 0}},
+ {{3.5f, 2.5f, epsilon_float, -0.0f}, {3, 2, 0, 0}},
+ {{3.5f, 2.5f, 0.f, 0.001f}, {3, 2, 0, 1}},
+ {{-1.5f, -1.5f, 3.0f, 3.0f}, {-2, -2, 4, 4}},
+ {{-1.5f, -1.5f, 3.5f, 3.5f}, {-2, -2, 4, 4}},
+ {{max_float, max_float, 2.0f, 2.0f}, {max_int, max_int, 0, 0}},
+ {{0.0f, 0.0f, max_float, max_float}, {0, 0, max_int, max_int}},
+ {{20000.5f, 20000.5f, 0.5f, 0.5f}, {20000, 20000, 1, 1}},
+ {{max_int_f, max_int_f, max_int_f, max_int_f}, {max_int, max_int, 0, 0}},
+ {{-0.5f, -0.5f, 22777712.f, 1.f}, {-1, -1, 22777713, 2}},
+ {{1.9999f, 2.0002f, 5.9998f, 6.0001f}, {2, 2, 6, 6}},
+ {{1.9999f, 2.0001f, 6.0002f, 5.9998f}, {2, 2, 6, 6}},
+ {{1.9998f, 2.0002f, 6.0001f, 5.9999f}, {2, 2, 6, 6}}};
+
+ for (size_t i = 0; i < base::size(tests); ++i) {
+ RectF source(tests[i].in.x, tests[i].in.y, tests[i].in.width,
+ tests[i].in.height);
+
+ Rect enclosing = ToEnclosingRectIgnoringError(source, error);
+ EXPECT_EQ(tests[i].expected.x, enclosing.x());
+ EXPECT_EQ(tests[i].expected.y, enclosing.y());
+ EXPECT_EQ(tests[i].expected.width, enclosing.width());
+ EXPECT_EQ(tests[i].expected.height, enclosing.height());
+ }
+}
+
TEST(RectTest, ToNearestRect) {
Rect rect;
EXPECT_EQ(rect, ToNearestRect(RectF(rect)));
@@ -617,7 +670,7 @@ TEST(RectTest, ToFlooredRect) {
20000, 20000, 0, 0 },
};
- for (size_t i = 0; i < arraysize(tests); ++i) {
+ for (size_t i = 0; i < base::size(tests); ++i) {
RectF r1(tests[i].x1, tests[i].y1, tests[i].w1, tests[i].h1);
Rect r2(tests[i].x2, tests[i].y2, tests[i].w2, tests[i].h2);
@@ -666,7 +719,7 @@ TEST(RectTest, ScaleToEnclosedRect) {
}
};
- for (size_t i = 0; i < arraysize(tests); ++i) {
+ for (size_t i = 0; i < base::size(tests); ++i) {
Rect result = ScaleToEnclosedRect(tests[i].input_rect,
tests[i].input_scale);
EXPECT_EQ(tests[i].expected_rect, result);
@@ -710,7 +763,7 @@ TEST(RectTest, ScaleToEnclosingRect) {
}
};
- for (size_t i = 0; i < arraysize(tests); ++i) {
+ for (size_t i = 0; i < base::size(tests); ++i) {
Rect result =
ScaleToEnclosingRect(tests[i].input_rect, tests[i].input_scale);
EXPECT_EQ(tests[i].expected_rect, result);
@@ -760,7 +813,7 @@ TEST(RectTest, BoundingRect) {
{ Point(-4, 6), Point(6, -4), Rect(-4, -4, 10, 10) },
};
- for (size_t i = 0; i < arraysize(int_tests); ++i) {
+ for (size_t i = 0; i < base::size(int_tests); ++i) {
Rect actual = BoundingRect(int_tests[i].a, int_tests[i].b);
EXPECT_EQ(int_tests[i].expected, actual);
}
@@ -797,7 +850,7 @@ TEST(RectTest, BoundingRect) {
RectF(-4.2f, -4.2f, 11.0f, 11.0f) }
};
- for (size_t i = 0; i < arraysize(float_tests); ++i) {
+ for (size_t i = 0; i < base::size(float_tests); ++i) {
RectF actual = BoundingRect(float_tests[i].a, float_tests[i].b);
EXPECT_RECTF_EQ(float_tests[i].expected, actual);
}
diff --git a/chromium/ui/gfx/geometry/safe_integer_conversions.h b/chromium/ui/gfx/geometry/safe_integer_conversions.h
index 5efe134f079..c89cec2d422 100644
--- a/chromium/ui/gfx/geometry/safe_integer_conversions.h
+++ b/chromium/ui/gfx/geometry/safe_integer_conversions.h
@@ -9,7 +9,6 @@
#include <limits>
#include "base/numerics/safe_conversions.h"
-#include "ui/gfx/gfx_export.h"
namespace gfx {
diff --git a/chromium/ui/gfx/geometry/scroll_offset.h b/chromium/ui/gfx/geometry/scroll_offset.h
index d7aa2f97d88..1f604fa6a7f 100644
--- a/chromium/ui/gfx/geometry/scroll_offset.h
+++ b/chromium/ui/gfx/geometry/scroll_offset.h
@@ -8,9 +8,9 @@
#include <iosfwd>
#include <string>
+#include "ui/gfx/geometry/geometry_export.h"
#include "ui/gfx/geometry/safe_integer_conversions.h"
#include "ui/gfx/geometry/vector2d.h"
-#include "ui/gfx/gfx_export.h"
namespace gfx {
@@ -18,7 +18,7 @@ namespace gfx {
// to a 'position' in blink. In blink, 'offset' means something else. See
// third_party/WebKit/Source/core/layout/README.md for more information.
-class GFX_EXPORT ScrollOffset {
+class GEOMETRY_EXPORT ScrollOffset {
public:
ScrollOffset() : x_(0), y_(0) {}
ScrollOffset(float x, float y) : x_(x), y_(y) {}
diff --git a/chromium/ui/gfx/geometry/size.h b/chromium/ui/gfx/geometry/size.h
index 8ce4178b3cf..03490b5ab81 100644
--- a/chromium/ui/gfx/geometry/size.h
+++ b/chromium/ui/gfx/geometry/size.h
@@ -11,7 +11,7 @@
#include "base/compiler_specific.h"
#include "base/numerics/safe_math.h"
#include "build/build_config.h"
-#include "ui/gfx/gfx_export.h"
+#include "ui/gfx/geometry/geometry_export.h"
#if defined(OS_WIN)
typedef struct tagSIZE SIZE;
@@ -22,7 +22,7 @@ typedef struct CGSize CGSize;
namespace gfx {
// A size has width and height values.
-class GFX_EXPORT Size {
+class GEOMETRY_EXPORT Size {
public:
constexpr Size() : width_(0), height_(0) {}
constexpr Size(int width, int height)
@@ -85,18 +85,18 @@ inline bool operator!=(const Size& lhs, const Size& rhs) {
void PrintTo(const Size& size, ::std::ostream* os);
// Helper methods to scale a gfx::Size to a new gfx::Size.
-GFX_EXPORT Size ScaleToCeiledSize(const Size& size,
- float x_scale,
- float y_scale);
-GFX_EXPORT Size ScaleToCeiledSize(const Size& size, float scale);
-GFX_EXPORT Size ScaleToFlooredSize(const Size& size,
- float x_scale,
- float y_scale);
-GFX_EXPORT Size ScaleToFlooredSize(const Size& size, float scale);
-GFX_EXPORT Size ScaleToRoundedSize(const Size& size,
- float x_scale,
- float y_scale);
-GFX_EXPORT Size ScaleToRoundedSize(const Size& size, float scale);
+GEOMETRY_EXPORT Size ScaleToCeiledSize(const Size& size,
+ float x_scale,
+ float y_scale);
+GEOMETRY_EXPORT Size ScaleToCeiledSize(const Size& size, float scale);
+GEOMETRY_EXPORT Size ScaleToFlooredSize(const Size& size,
+ float x_scale,
+ float y_scale);
+GEOMETRY_EXPORT Size ScaleToFlooredSize(const Size& size, float scale);
+GEOMETRY_EXPORT Size ScaleToRoundedSize(const Size& size,
+ float x_scale,
+ float y_scale);
+GEOMETRY_EXPORT Size ScaleToRoundedSize(const Size& size, float scale);
} // namespace gfx
diff --git a/chromium/ui/gfx/geometry/size_conversions.h b/chromium/ui/gfx/geometry/size_conversions.h
index 96fb79f93c2..6bc74c0a612 100644
--- a/chromium/ui/gfx/geometry/size_conversions.h
+++ b/chromium/ui/gfx/geometry/size_conversions.h
@@ -11,13 +11,13 @@
namespace gfx {
// Returns a Size with each component from the input SizeF floored.
-GFX_EXPORT Size ToFlooredSize(const SizeF& size);
+GEOMETRY_EXPORT Size ToFlooredSize(const SizeF& size);
// Returns a Size with each component from the input SizeF ceiled.
-GFX_EXPORT Size ToCeiledSize(const SizeF& size);
+GEOMETRY_EXPORT Size ToCeiledSize(const SizeF& size);
// Returns a Size with each component from the input SizeF rounded.
-GFX_EXPORT Size ToRoundedSize(const SizeF& size);
+GEOMETRY_EXPORT Size ToRoundedSize(const SizeF& size);
} // namespace gfx
diff --git a/chromium/ui/gfx/geometry/size_f.h b/chromium/ui/gfx/geometry/size_f.h
index 0757ef6481a..ceda9edfc44 100644
--- a/chromium/ui/gfx/geometry/size_f.h
+++ b/chromium/ui/gfx/geometry/size_f.h
@@ -10,8 +10,8 @@
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
+#include "ui/gfx/geometry/geometry_export.h"
#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/gfx_export.h"
namespace gfx {
@@ -20,7 +20,7 @@ FORWARD_DECLARE_TEST(SizeTest, ClampsToZero);
FORWARD_DECLARE_TEST(SizeTest, ConsistentClamping);
// A floating version of gfx::Size.
-class GFX_EXPORT SizeF {
+class GEOMETRY_EXPORT SizeF {
public:
constexpr SizeF() : width_(0.f), height_(0.f) {}
constexpr SizeF(float width, float height)
@@ -81,7 +81,7 @@ inline bool operator!=(const SizeF& lhs, const SizeF& rhs) {
return !(lhs == rhs);
}
-GFX_EXPORT SizeF ScaleSize(const SizeF& p, float x_scale, float y_scale);
+GEOMETRY_EXPORT SizeF ScaleSize(const SizeF& p, float x_scale, float y_scale);
inline SizeF ScaleSize(const SizeF& p, float scale) {
return ScaleSize(p, scale, scale);
diff --git a/chromium/ui/gfx/geometry/vector2d.h b/chromium/ui/gfx/geometry/vector2d.h
index d9964532f51..11d55bf0e82 100644
--- a/chromium/ui/gfx/geometry/vector2d.h
+++ b/chromium/ui/gfx/geometry/vector2d.h
@@ -15,12 +15,12 @@
#include <iosfwd>
#include <string>
+#include "ui/gfx/geometry/geometry_export.h"
#include "ui/gfx/geometry/vector2d_f.h"
-#include "ui/gfx/gfx_export.h"
namespace gfx {
-class GFX_EXPORT Vector2d {
+class GEOMETRY_EXPORT Vector2d {
public:
constexpr Vector2d() : x_(0), y_(0) {}
constexpr Vector2d(int x, int y) : x_(x), y_(y) {}
diff --git a/chromium/ui/gfx/geometry/vector2d_conversions.h b/chromium/ui/gfx/geometry/vector2d_conversions.h
index f4e16ae4be7..055ebd05f18 100644
--- a/chromium/ui/gfx/geometry/vector2d_conversions.h
+++ b/chromium/ui/gfx/geometry/vector2d_conversions.h
@@ -11,13 +11,13 @@
namespace gfx {
// Returns a Vector2d with each component from the input Vector2dF floored.
-GFX_EXPORT Vector2d ToFlooredVector2d(const Vector2dF& vector2d);
+GEOMETRY_EXPORT Vector2d ToFlooredVector2d(const Vector2dF& vector2d);
// Returns a Vector2d with each component from the input Vector2dF ceiled.
-GFX_EXPORT Vector2d ToCeiledVector2d(const Vector2dF& vector2d);
+GEOMETRY_EXPORT Vector2d ToCeiledVector2d(const Vector2dF& vector2d);
// Returns a Vector2d with each component from the input Vector2dF rounded.
-GFX_EXPORT Vector2d ToRoundedVector2d(const Vector2dF& vector2d);
+GEOMETRY_EXPORT Vector2d ToRoundedVector2d(const Vector2dF& vector2d);
} // namespace gfx
diff --git a/chromium/ui/gfx/geometry/vector2d_f.h b/chromium/ui/gfx/geometry/vector2d_f.h
index 7e40ea881fc..938e45aeacc 100644
--- a/chromium/ui/gfx/geometry/vector2d_f.h
+++ b/chromium/ui/gfx/geometry/vector2d_f.h
@@ -13,11 +13,11 @@
#include <iosfwd>
#include <string>
-#include "ui/gfx/gfx_export.h"
+#include "ui/gfx/geometry/geometry_export.h"
namespace gfx {
-class GFX_EXPORT Vector2dF {
+class GEOMETRY_EXPORT Vector2dF {
public:
constexpr Vector2dF() : x_(0), y_(0) {}
constexpr Vector2dF(float x, float y) : x_(x), y_(y) {}
@@ -92,16 +92,16 @@ inline Vector2dF operator-(const Vector2dF& lhs, const Vector2dF& rhs) {
}
// Return the cross product of two vectors.
-GFX_EXPORT double CrossProduct(const Vector2dF& lhs, const Vector2dF& rhs);
+GEOMETRY_EXPORT double CrossProduct(const Vector2dF& lhs, const Vector2dF& rhs);
// Return the dot product of two vectors.
-GFX_EXPORT double DotProduct(const Vector2dF& lhs, const Vector2dF& rhs);
+GEOMETRY_EXPORT double DotProduct(const Vector2dF& lhs, const Vector2dF& rhs);
// Return a vector that is |v| scaled by the given scale factors along each
// axis.
-GFX_EXPORT Vector2dF ScaleVector2d(const Vector2dF& v,
- float x_scale,
- float y_scale);
+GEOMETRY_EXPORT Vector2dF ScaleVector2d(const Vector2dF& v,
+ float x_scale,
+ float y_scale);
// Return a vector that is |v| scaled by the given scale factor.
inline Vector2dF ScaleVector2d(const Vector2dF& v, float scale) {
diff --git a/chromium/ui/gfx/geometry/vector3d_f.h b/chromium/ui/gfx/geometry/vector3d_f.h
index 0e5e43713a8..32b72655b1e 100644
--- a/chromium/ui/gfx/geometry/vector3d_f.h
+++ b/chromium/ui/gfx/geometry/vector3d_f.h
@@ -13,12 +13,12 @@
#include <iosfwd>
#include <string>
+#include "ui/gfx/geometry/geometry_export.h"
#include "ui/gfx/geometry/vector2d_f.h"
-#include "ui/gfx/gfx_export.h"
namespace gfx {
-class GFX_EXPORT Vector3dF {
+class GEOMETRY_EXPORT Vector3dF {
public:
constexpr Vector3dF() : x_(0), y_(0), z_(0) {}
constexpr Vector3dF(float x, float y, float z) : x_(x), y_(y), z_(z) {}
@@ -111,14 +111,14 @@ inline Vector3dF CrossProduct(const Vector3dF& lhs, const Vector3dF& rhs) {
}
// Return the dot product of two vectors.
-GFX_EXPORT float DotProduct(const Vector3dF& lhs, const Vector3dF& rhs);
+GEOMETRY_EXPORT float DotProduct(const Vector3dF& lhs, const Vector3dF& rhs);
// Return a vector that is |v| scaled by the given scale factors along each
// axis.
-GFX_EXPORT Vector3dF ScaleVector3d(const Vector3dF& v,
- float x_scale,
- float y_scale,
- float z_scale);
+GEOMETRY_EXPORT Vector3dF ScaleVector3d(const Vector3dF& v,
+ float x_scale,
+ float y_scale,
+ float z_scale);
// Return a vector that is |v| scaled by the components of |s|
inline Vector3dF ScaleVector3d(const Vector3dF& v, const Vector3dF& s) {
@@ -131,12 +131,12 @@ inline Vector3dF ScaleVector3d(const Vector3dF& v, float scale) {
}
// Returns the angle between |base| and |other| in degrees.
-GFX_EXPORT float AngleBetweenVectorsInDegrees(const gfx::Vector3dF& base,
- const gfx::Vector3dF& other);
+GEOMETRY_EXPORT float AngleBetweenVectorsInDegrees(const gfx::Vector3dF& base,
+ const gfx::Vector3dF& other);
// Returns the clockwise angle between |base| and |other| where |normal| is the
// normal of the virtual surface to measure clockwise according to.
-GFX_EXPORT float ClockwiseAngleBetweenVectorsInDegrees(
+GEOMETRY_EXPORT float ClockwiseAngleBetweenVectorsInDegrees(
const gfx::Vector3dF& base,
const gfx::Vector3dF& other,
const gfx::Vector3dF& normal);
diff --git a/chromium/ui/gfx/geometry_skia_export.h b/chromium/ui/gfx/geometry_skia_export.h
new file mode 100644
index 00000000000..c6819823476
--- /dev/null
+++ b/chromium/ui/gfx/geometry_skia_export.h
@@ -0,0 +1,29 @@
+// 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_GFX_GEOMETRY_SKIA_EXPORT_H_
+#define UI_GFX_GEOMETRY_SKIA_EXPORT_H_
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(GEOMETRY_SKIA_IMPLEMENTATION)
+#define GEOMETRY_SKIA_EXPORT __declspec(dllexport)
+#else
+#define GEOMETRY_SKIA_EXPORT __declspec(dllimport)
+#endif // defined(GEOMETRY_SKIA_IMPLEMENTATION)
+
+#else // defined(WIN32)
+#if defined(GEOMETRY_SKIA_IMPLEMENTATION)
+#define GEOMETRY_SKIA_EXPORT __attribute__((visibility("default")))
+#else
+#define GEOMETRY_SKIA_EXPORT
+#endif
+#endif
+
+#else // defined(COMPONENT_BUILD)
+#define GEOMETRY_SKIA_EXPORT
+#endif
+
+#endif // UI_GFX_GEOMETRY_SKIA_EXPORT_H_
diff --git a/chromium/ui/gfx/gpu_memory_buffer.cc b/chromium/ui/gfx/gpu_memory_buffer.cc
index e6751d82f6d..5da026af502 100644
--- a/chromium/ui/gfx/gpu_memory_buffer.cc
+++ b/chromium/ui/gfx/gpu_memory_buffer.cc
@@ -8,7 +8,8 @@
namespace gfx {
-GpuMemoryBufferHandle::GpuMemoryBufferHandle() : type(EMPTY_BUFFER), id(0) {}
+GpuMemoryBufferHandle::GpuMemoryBufferHandle()
+ : type(EMPTY_BUFFER), id(0), offset(0), stride(0) {}
// TODO(crbug.com/863011): Reset |type| and possibly the handles on the
// moved-from object.
diff --git a/chromium/ui/gfx/harfbuzz_font_skia.cc b/chromium/ui/gfx/harfbuzz_font_skia.cc
index cad4334a045..fe88148b97c 100644
--- a/chromium/ui/gfx/harfbuzz_font_skia.cc
+++ b/chromium/ui/gfx/harfbuzz_font_skia.cc
@@ -13,6 +13,7 @@
#include "base/lazy_instance.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/no_destructor.h"
#include "build/build_config.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "ui/gfx/render_text.h"
@@ -285,10 +286,11 @@ hb_font_t* CreateHarfBuzzFont(sk_sp<SkTypeface> skia_face,
SkScalar text_size,
const FontRenderParams& params,
bool subpixel_rendering_suppressed) {
- // TODO(ckocagil): This shouldn't grow indefinitely. Maybe use base::MRUCache?
- static std::map<SkFontID, FaceCache> face_caches;
+ // TODO(https://crbug.com/890298): This shouldn't grow indefinitely.
+ // Maybe use base::MRUCache?
+ static base::NoDestructor<std::map<SkFontID, FaceCache>> face_caches;
- FaceCache* face_cache = &face_caches[skia_face->uniqueID()];
+ FaceCache* face_cache = &(*face_caches)[skia_face->uniqueID()];
if (face_cache->first.get() == NULL)
face_cache->first.Init(skia_face.get());
diff --git a/chromium/ui/gfx/icc_profile.cc b/chromium/ui/gfx/icc_profile.cc
index a126363087e..3fcef25f18c 100644
--- a/chromium/ui/gfx/icc_profile.cc
+++ b/chromium/ui/gfx/icc_profile.cc
@@ -12,7 +12,7 @@
#include "base/lazy_instance.h"
#include "base/metrics/histogram_macros.h"
#include "base/synchronization/lock.h"
-#include "third_party/skia/include/core/SkColorSpaceXform.h"
+#include "third_party/skia/include/core/SkColorSpace.h"
#include "third_party/skia/third_party/skcms/skcms.h"
#include "ui/gfx/skia_color_space_util.h"
@@ -163,7 +163,6 @@ ICCProfile ICCProfile::FromDataWithId(const void* data_as_void,
}
// Insert the profile into all caches.
- ColorSpace color_space = icc_profile.GetColorSpace();
if (icc_profile.internals_->id_)
g_id_to_profile_cache.Get().Put(icc_profile.internals_->id_, icc_profile);
g_data_to_profile_cache.Get().Put(icc_profile.internals_->data_, icc_profile);
diff --git a/chromium/ui/gfx/image/canvas_image_source.cc b/chromium/ui/gfx/image/canvas_image_source.cc
index 4d68d315bde..c6ddb53c21d 100644
--- a/chromium/ui/gfx/image/canvas_image_source.cc
+++ b/chromium/ui/gfx/image/canvas_image_source.cc
@@ -5,9 +5,13 @@
#include "ui/gfx/image/canvas_image_source.h"
#include "base/logging.h"
+#include "cc/paint/display_item_list.h"
+#include "cc/paint/record_paint_canvas.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/switches.h"
namespace gfx {
@@ -49,7 +53,33 @@ CanvasImageSource::CanvasImageSource(const Size& size, bool is_opaque)
: size_(size), is_opaque_(is_opaque) {}
ImageSkiaRep CanvasImageSource::GetImageForScale(float scale) {
- Canvas canvas(size_, scale, is_opaque_);
+ if (base::FeatureList::IsEnabled(features::kUsePaintRecordForImageSkia)) {
+ scoped_refptr<cc::DisplayItemList> display_item_list =
+ base::MakeRefCounted<cc::DisplayItemList>(
+ cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer);
+ display_item_list->StartPaint();
+
+ SizeF size_in_pixel = ScaleSize(SizeF(size_), scale);
+ cc::RecordPaintCanvas record_canvas(
+ display_item_list.get(),
+ SkRect::MakeWH(SkFloatToScalar(size_in_pixel.width()),
+ SkFloatToScalar(size_in_pixel.height())));
+ gfx::Canvas canvas(&record_canvas, scale);
+#if DCHECK_IS_ON()
+ Rect clip_rect;
+ DCHECK(canvas.GetClipBounds(&clip_rect));
+ DCHECK(clip_rect.Contains(gfx::Rect(ToCeiledSize(size_in_pixel))));
+#endif
+ canvas.Scale(scale, scale);
+ Draw(&canvas);
+
+ display_item_list->EndPaintOfPairedEnd();
+ display_item_list->Finalize();
+ return ImageSkiaRep(display_item_list->ReleaseAsRecord(),
+ gfx::ScaleToCeiledSize(size_, scale), scale);
+ }
+
+ gfx::Canvas canvas(size_, scale, is_opaque_);
Draw(&canvas);
return ImageSkiaRep(canvas.GetBitmap(), scale);
}
diff --git a/chromium/ui/gfx/image/image.cc b/chromium/ui/gfx/image/image.cc
index 855387a4238..a81091e8975 100644
--- a/chromium/ui/gfx/image/image.cc
+++ b/chromium/ui/gfx/image/image.cc
@@ -123,8 +123,7 @@ class ImageRepPNG : public ImageRep {
gfx::Size Size() const override {
// Read the PNG data to get the image size, caching it.
if (!size_cache_) {
- for (std::vector<ImagePNGRep>::const_iterator it = image_reps().begin();
- it != image_reps().end(); ++it) {
+ for (auto it = image_reps().begin(); it != image_reps().end(); ++it) {
if (it->scale == 1.0f) {
size_cache_.reset(new gfx::Size(it->Size()));
return *size_cache_;
diff --git a/chromium/ui/gfx/image/image_family.cc b/chromium/ui/gfx/image/image_family.cc
index 0adc6692336..adc1482c398 100644
--- a/chromium/ui/gfx/image/image_family.cc
+++ b/chromium/ui/gfx/image/image_family.cc
@@ -79,8 +79,7 @@ const gfx::Image* ImageFamily::GetBest(int width, int height) const {
float ImageFamily::GetClosestAspect(float desired_aspect) const {
// Find the two aspect ratios on either side of |desired_aspect|.
- std::map<MapKey, gfx::Image>::const_iterator greater_or_equal =
- map_.lower_bound(MapKey(desired_aspect, 0));
+ auto greater_or_equal = map_.lower_bound(MapKey(desired_aspect, 0));
// Early exit optimization if there is an exact match.
if (greater_or_equal != map_.end() &&
greater_or_equal->first.aspect() == desired_aspect) {
@@ -91,8 +90,7 @@ float ImageFamily::GetClosestAspect(float desired_aspect) const {
// aspect ratio >= |desired_aspect|, and |less_than| will point to the last
// image with aspect ratio < |desired_aspect|.
if (greater_or_equal != map_.begin()) {
- std::map<MapKey, gfx::Image>::const_iterator less_than =
- greater_or_equal;
+ auto less_than = greater_or_equal;
--less_than;
float thinner_aspect = less_than->first.aspect();
DCHECK_GT(thinner_aspect, 0.0f);
@@ -148,8 +146,7 @@ gfx::Image ImageFamily::CreateExact(const gfx::Size& size) const {
const gfx::Image* ImageFamily::GetWithExactAspect(float aspect,
int width) const {
// Find the two images of given aspect ratio on either side of |width|.
- std::map<MapKey, gfx::Image>::const_iterator greater_or_equal =
- map_.lower_bound(MapKey(aspect, width));
+ auto greater_or_equal = map_.lower_bound(MapKey(aspect, width));
if (greater_or_equal != map_.end() &&
greater_or_equal->first.aspect() == aspect) {
// We have found the smallest image of the same size or greater.
@@ -157,7 +154,7 @@ const gfx::Image* ImageFamily::GetWithExactAspect(float aspect,
}
DCHECK(greater_or_equal != map_.begin());
- std::map<MapKey, gfx::Image>::const_iterator less_than = greater_or_equal;
+ auto less_than = greater_or_equal;
--less_than;
// This must be true because there must be at least one image with |aspect|.
DCHECK_EQ(less_than->first.aspect(), aspect);
diff --git a/chromium/ui/gfx/image/image_generic.cc b/chromium/ui/gfx/image/image_generic.cc
index 3f424915dc9..acca9d0bd36 100644
--- a/chromium/ui/gfx/image/image_generic.cc
+++ b/chromium/ui/gfx/image/image_generic.cc
@@ -39,8 +39,8 @@ class PNGImageSource : public ImageSkiaSource {
// 1) The ImageSkiaRep with the highest scale if all available
// scales are smaller than |scale|.
// 2) The ImageSkiaRep with the smallest one that is larger than |scale|.
- for (ImageSkiaRepSet::const_iterator iter = image_skia_reps_.begin();
- iter != image_skia_reps_.end(); ++iter) {
+ for (auto iter = image_skia_reps_.begin(); iter != image_skia_reps_.end();
+ ++iter) {
if ((*iter).scale() == scale)
return (*iter);
if (!rep || rep->scale() < (*iter).scale())
@@ -112,7 +112,7 @@ scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia(
scoped_refptr<base::RefCountedBytes> png_bytes(new base::RefCountedBytes());
if (image_skia_rep.scale() != 1.0f ||
- !PNGCodec::EncodeBGRASkBitmap(image_skia_rep.sk_bitmap(), false,
+ !PNGCodec::EncodeBGRASkBitmap(image_skia_rep.GetBitmap(), false,
&png_bytes->data())) {
return NULL;
}
diff --git a/chromium/ui/gfx/image/image_mac_unittest.mm b/chromium/ui/gfx/image/image_mac_unittest.mm
index f54b9bc4867..dc26e924e91 100644
--- a/chromium/ui/gfx/image/image_mac_unittest.mm
+++ b/chromium/ui/gfx/image/image_mac_unittest.mm
@@ -200,10 +200,10 @@ TEST_F(ImageMacTest, MultiResolutionPNGToNSImage) {
// Convert to ImageSkia to check pixel contents of NSImageReps.
gfx::ImageSkia image_skia = gfx::ImageSkiaFromNSImage(ns_image);
EXPECT_TRUE(gt::ArePNGBytesCloseToBitmap(
- bytes1x, image_skia.GetRepresentation(1.0f).sk_bitmap(),
+ bytes1x, image_skia.GetRepresentation(1.0f).GetBitmap(),
gt::MaxColorSpaceConversionColorShift()));
- EXPECT_TRUE(gt::ArePNGBytesCloseToBitmap(bytes2x,
- image_skia.GetRepresentation(2.0f).sk_bitmap(),
+ EXPECT_TRUE(gt::ArePNGBytesCloseToBitmap(
+ bytes2x, image_skia.GetRepresentation(2.0f).GetBitmap(),
gt::MaxColorSpaceConversionColorShift()));
}
diff --git a/chromium/ui/gfx/image/image_skia.cc b/chromium/ui/gfx/image/image_skia.cc
index 772344f967d..245a74081d9 100644
--- a/chromium/ui/gfx/image/image_skia.cc
+++ b/chromium/ui/gfx/image/image_skia.cc
@@ -14,6 +14,7 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "base/memory/ptr_util.h"
+#include "base/no_destructor.h"
#include "base/sequence_checker.h"
#include "build/build_config.h"
#include "ui/gfx/geometry/rect.h"
@@ -29,8 +30,8 @@ namespace {
// static
gfx::ImageSkiaRep& NullImageRep() {
- CR_DEFINE_STATIC_LOCAL(ImageSkiaRep, null_image_rep, ());
- return null_image_rep;
+ static base::NoDestructor<ImageSkiaRep> null_image_rep;
+ return *null_image_rep;
}
std::vector<float>* g_supported_scales = NULL;
@@ -63,11 +64,11 @@ ImageSkiaRep ScaleImageSkiaRep(const ImageSkiaRep& rep, float target_scale) {
gfx::Size scaled_size =
gfx::ScaleToCeiledSize(rep.pixel_size(), target_scale / rep.scale());
- return ImageSkiaRep(skia::ImageOperations::Resize(
- rep.sk_bitmap(),
- skia::ImageOperations::RESIZE_LANCZOS3,
- scaled_size.width(),
- scaled_size.height()), target_scale);
+ return ImageSkiaRep(
+ skia::ImageOperations::Resize(rep.GetBitmap(),
+ skia::ImageOperations::RESIZE_LANCZOS3,
+ scaled_size.width(), scaled_size.height()),
+ target_scale);
}
} // namespace
@@ -153,7 +154,7 @@ ImageSkiaStorage::ImageSkiaStorage(std::unique_ptr<ImageSkiaSource> source,
float scale)
: source_(std::move(source)), read_only_(false) {
DCHECK(source_);
- ImageSkia::ImageSkiaReps::iterator it = FindRepresentation(scale, true);
+ auto it = FindRepresentation(scale, true);
if (it == image_reps_.end() || it->is_null())
source_.reset();
else
@@ -186,11 +187,11 @@ void ImageSkiaStorage::AddRepresentation(const ImageSkiaRep& image) {
DCHECK(!HasRepresentationAtAllScales());
if (image.scale() != 1.0f) {
- for (ImageSkia::ImageSkiaReps::iterator it = image_reps_.begin();
- it < image_reps_.end(); ++it) {
+ ImageSkia::ImageSkiaReps::iterator it;
+ for (it = image_reps_.begin(); it < image_reps_.end(); ++it) {
if (it->unscaled()) {
DCHECK_EQ(1.0f, it->scale());
- it->SetScaled();
+ *it = ImageSkiaRep(it->GetBitmap(), it->scale());
break;
}
}
@@ -207,12 +208,11 @@ std::vector<ImageSkiaRep>::iterator ImageSkiaStorage::FindRepresentation(
bool fetch_new_image) const {
ImageSkiaStorage* non_const = const_cast<ImageSkiaStorage*>(this);
- ImageSkia::ImageSkiaReps::iterator closest_iter =
- non_const->image_reps().end();
- ImageSkia::ImageSkiaReps::iterator exact_iter = non_const->image_reps().end();
+ auto closest_iter = non_const->image_reps().end();
+ auto exact_iter = non_const->image_reps().end();
float smallest_diff = std::numeric_limits<float>::max();
- for (ImageSkia::ImageSkiaReps::iterator it = non_const->image_reps().begin();
- it < image_reps_.end(); ++it) {
+ for (auto it = non_const->image_reps().begin(); it < image_reps_.end();
+ ++it) {
if (it->scale() == scale) {
// found exact match
fetch_new_image = false;
@@ -238,8 +238,7 @@ std::vector<ImageSkiaRep>::iterator ImageSkiaStorage::FindRepresentation(
if (!HasRepresentationAtAllScales() && g_supported_scales)
resource_scale = MapToSupportedScale(scale);
if (scale != resource_scale) {
- std::vector<ImageSkiaRep>::iterator iter =
- FindRepresentation(resource_scale, fetch_new_image);
+ auto iter = FindRepresentation(resource_scale, fetch_new_image);
CHECK(iter != image_reps_.end());
image = iter->unscaled() ? (*iter) : ScaleImageSkiaRep(*iter, scale);
} else {
@@ -348,8 +347,7 @@ std::unique_ptr<ImageSkia> ImageSkia::DeepCopy() const {
CHECK(CanRead());
std::vector<gfx::ImageSkiaRep>& reps = storage_->image_reps();
- for (std::vector<gfx::ImageSkiaRep>::iterator iter = reps.begin();
- iter != reps.end(); ++iter) {
+ for (auto iter = reps.begin(); iter != reps.end(); ++iter) {
copy->AddRepresentation(*iter);
}
// The copy has its own storage. Detach the copy from the current
@@ -391,8 +389,7 @@ void ImageSkia::RemoveRepresentation(float scale) {
CHECK(CanModify());
ImageSkiaReps& image_reps = storage_->image_reps();
- ImageSkiaReps::iterator it =
- storage_->FindRepresentation(scale, false);
+ auto it = storage_->FindRepresentation(scale, false);
if (it != image_reps.end() && it->scale() == scale)
image_reps.erase(it);
}
@@ -410,7 +407,7 @@ bool ImageSkia::HasRepresentation(float scale) const {
if (storage_->HasRepresentationAtAllScales())
return true;
- ImageSkiaReps::iterator it = storage_->FindRepresentation(scale, false);
+ auto it = storage_->FindRepresentation(scale, false);
return (it != storage_->image_reps().end() && it->scale() == scale);
}
@@ -420,7 +417,7 @@ const ImageSkiaRep& ImageSkia::GetRepresentation(float scale) const {
CHECK(CanRead());
- ImageSkiaReps::iterator it = storage_->FindRepresentation(scale, true);
+ auto it = storage_->FindRepresentation(scale, true);
if (it == storage_->image_reps().end())
return NullImageRep();
@@ -469,8 +466,8 @@ std::vector<ImageSkiaRep> ImageSkia::image_reps() const {
// Create list of image reps to return, skipping null image reps which were
// added for caching purposes only.
ImageSkiaReps image_reps;
- for (ImageSkiaReps::iterator it = internal_image_reps.begin();
- it != internal_image_reps.end(); ++it) {
+ for (auto it = internal_image_reps.begin(); it != internal_image_reps.end();
+ ++it) {
if (!it->is_null())
image_reps.push_back(*it);
}
@@ -499,7 +496,7 @@ void ImageSkia::RemoveUnsupportedRepresentationsForScale(float scale) {
}
void ImageSkia::Init(const ImageSkiaRep& image_rep) {
- if (image_rep.sk_bitmap().drawsNothing()) {
+ if (image_rep.GetBitmap().drawsNothing()) {
storage_ = NULL;
return;
}
@@ -512,7 +509,7 @@ const SkBitmap& ImageSkia::GetBitmap() const {
if (isNull()) {
// Callers expect a ImageSkiaRep even if it is |isNull()|.
// TODO(pkotwicz): Fix this.
- return NullImageRep().sk_bitmap();
+ return NullImageRep().GetBitmap();
}
// TODO(oshima): This made a few tests flaky on Windows.
@@ -521,10 +518,10 @@ const SkBitmap& ImageSkia::GetBitmap() const {
CHECK(CanRead());
#endif
- ImageSkiaReps::iterator it = storage_->FindRepresentation(1.0f, true);
+ auto it = storage_->FindRepresentation(1.0f, true);
if (it != storage_->image_reps().end())
- return it->sk_bitmap();
- return NullImageRep().sk_bitmap();
+ return it->GetBitmap();
+ return NullImageRep().GetBitmap();
}
bool ImageSkia::CanRead() const {
diff --git a/chromium/ui/gfx/image/image_skia_operations.cc b/chromium/ui/gfx/image/image_skia_operations.cc
index c6928208db4..51743e51fc5 100644
--- a/chromium/ui/gfx/image/image_skia_operations.cc
+++ b/chromium/ui/gfx/image/image_skia_operations.cc
@@ -119,7 +119,7 @@ class BlendingImageSource : public BinaryImageSource {
const ImageSkiaRep& first_rep,
const ImageSkiaRep& second_rep) const override {
SkBitmap blended = SkBitmapOperations::CreateBlendedBitmap(
- first_rep.sk_bitmap(), second_rep.sk_bitmap(), alpha_);
+ first_rep.GetBitmap(), second_rep.GetBitmap(), alpha_);
return ImageSkiaRep(blended, first_rep.scale());
}
@@ -173,7 +173,7 @@ class TransparentImageSource : public gfx::ImageSkiaSource {
image_rep.pixel_height());
alpha.eraseColor(SkColorSetARGB(alpha_ * 255, 0, 0, 0));
return ImageSkiaRep(
- SkBitmapOperations::CreateMaskedBitmap(image_rep.sk_bitmap(), alpha),
+ SkBitmapOperations::CreateMaskedBitmap(image_rep.GetBitmap(), alpha),
image_rep.scale());
}
@@ -196,7 +196,7 @@ class MaskedImageSource : public BinaryImageSource {
const ImageSkiaRep& first_rep,
const ImageSkiaRep& second_rep) const override {
return ImageSkiaRep(SkBitmapOperations::CreateMaskedBitmap(
- first_rep.sk_bitmap(), second_rep.sk_bitmap()),
+ first_rep.GetBitmap(), second_rep.GetBitmap()),
first_rep.scale());
}
@@ -223,11 +223,10 @@ class TiledImageSource : public gfx::ImageSkiaSource {
ImageSkiaRep source_rep = source_.GetRepresentation(scale);
gfx::Rect bounds = DIPToPixelBounds(gfx::Rect(src_x_, src_y_, dst_w_,
dst_h_), source_rep.scale());
- return ImageSkiaRep(
- SkBitmapOperations::CreateTiledBitmap(
- source_rep.sk_bitmap(),
- bounds.x(), bounds.y(), bounds.width(), bounds.height()),
- source_rep.scale());
+ return ImageSkiaRep(SkBitmapOperations::CreateTiledBitmap(
+ source_rep.GetBitmap(), bounds.x(), bounds.y(),
+ bounds.width(), bounds.height()),
+ source_rep.scale());
}
private:
@@ -253,9 +252,9 @@ class HSLImageSource : public gfx::ImageSkiaSource {
// gfx::ImageSkiaSource overrides:
ImageSkiaRep GetImageForScale(float scale) override {
ImageSkiaRep image_rep = image_.GetRepresentation(scale);
- return gfx::ImageSkiaRep(
- SkBitmapOperations::CreateHSLShiftedBitmap(image_rep.sk_bitmap(),
- hsl_shift_), image_rep.scale());
+ return gfx::ImageSkiaRep(SkBitmapOperations::CreateHSLShiftedBitmap(
+ image_rep.GetBitmap(), hsl_shift_),
+ image_rep.scale());
}
private:
@@ -288,9 +287,9 @@ class ButtonImageSource: public gfx::ImageSkiaSource {
mask_rep = mask_.GetRepresentation(1.0f);
}
return gfx::ImageSkiaRep(
- SkBitmapOperations::CreateButtonBackground(color_,
- image_rep.sk_bitmap(), mask_rep.sk_bitmap()),
- image_rep.scale());
+ SkBitmapOperations::CreateButtonBackground(
+ color_, image_rep.GetBitmap(), mask_rep.GetBitmap()),
+ image_rep.scale());
}
private:
@@ -319,8 +318,8 @@ class ExtractSubsetImageSource: public gfx::ImageSkiaSource {
SkIRect subset_bounds_in_pixel = RectToSkIRect(
DIPToPixelBounds(subset_bounds_, image_rep.scale()));
SkBitmap dst;
- bool success = image_rep.sk_bitmap().extractSubset(&dst,
- subset_bounds_in_pixel);
+ bool success =
+ image_rep.GetBitmap().extractSubset(&dst, subset_bounds_in_pixel);
DCHECK(success);
return gfx::ImageSkiaRep(dst, image_rep.scale());
}
@@ -354,9 +353,7 @@ class ResizeSource : public ImageSkiaSource {
const Size target_pixel_size = DIPToPixelSize(target_dip_size_, scale);
const SkBitmap resized = skia::ImageOperations::Resize(
- image_rep.sk_bitmap(),
- resize_method_,
- target_pixel_size.width(),
+ image_rep.GetBitmap(), resize_method_, target_pixel_size.width(),
target_pixel_size.height());
return ImageSkiaRep(resized, scale);
}
@@ -386,8 +383,7 @@ class DropShadowSource : public ImageSkiaSource {
shadows_in_pixel.push_back(shadows_in_dip_[i].Scale(scale));
const SkBitmap shadow_bitmap = SkBitmapOperations::CreateDropShadow(
- image_rep.sk_bitmap(),
- shadows_in_pixel);
+ image_rep.GetBitmap(), shadows_in_pixel);
return ImageSkiaRep(shadow_bitmap, image_rep.scale());
}
@@ -447,7 +443,7 @@ class RotatedSource : public ImageSkiaSource {
ImageSkiaRep GetImageForScale(float scale) override {
const ImageSkiaRep& image_rep = source_.GetRepresentation(scale);
const SkBitmap rotated_bitmap =
- SkBitmapOperations::Rotate(image_rep.sk_bitmap(), rotation_);
+ SkBitmapOperations::Rotate(image_rep.GetBitmap(), rotation_);
return ImageSkiaRep(rotated_bitmap, image_rep.scale());
}
diff --git a/chromium/ui/gfx/image/image_skia_rep.h b/chromium/ui/gfx/image/image_skia_rep.h
index 3942ad7e851..4f9d6b1bbc6 100644
--- a/chromium/ui/gfx/image/image_skia_rep.h
+++ b/chromium/ui/gfx/image/image_skia_rep.h
@@ -6,75 +6,11 @@
#define UI_GFX_IMAGE_IMAGE_SKIA_REP_H_
#include "build/build_config.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/gfx_export.h"
-#if !defined(OS_IOS)
-#include "cc/paint/paint_image.h"
-#endif
-
-namespace gfx {
-
-// An ImageSkiaRep represents a bitmap and the scale factor it is intended for.
-// 0.0f scale is used to indicate that this ImageSkiaRep is used for unscaled
-// image (the image that only returns 1.0f scale image).
-class GFX_EXPORT ImageSkiaRep {
- public:
- // Create null bitmap.
- ImageSkiaRep();
- ~ImageSkiaRep();
-
- // Note: This is for testing purpose only.
- // Creates a bitmap with kARGB_8888_Config config with given |size| in DIP.
- // This allocates pixels in the bitmap. It is guaranteed that the data in the
- // bitmap are initialized but the actual values are undefined.
- // Specifying 0 scale means the image is for unscaled image. (unscaled()
- // returns truen, and scale() returns 1.0f;)
- ImageSkiaRep(const gfx::Size& size, float scale);
-
- // Creates a bitmap with given scale.
- // Adds ref to |src|.
- ImageSkiaRep(const SkBitmap& src, float scale);
-
- // Returns true if the backing bitmap is null.
- bool is_null() const { return bitmap_.isNull(); }
-
- // Get width and height of bitmap in DIP.
- int GetWidth() const;
- int GetHeight() const;
-
- // Get width and height of bitmap in pixels.
- int pixel_width() const { return bitmap_.width(); }
- int pixel_height() const { return bitmap_.height(); }
- Size pixel_size() const {
- return Size(pixel_width(), pixel_height());
- }
-
- // Retrieves the scale that the bitmap will be painted at.
- float scale() const { return unscaled() ? 1.0f : scale_; }
-
- bool unscaled() const { return scale_ == 0.0f; }
-
- // Mark the image to be used as scaled image.
- void SetScaled();
-
- // Returns backing bitmap.
- const SkBitmap& sk_bitmap() const { return bitmap_; }
-
-#if !defined(OS_IOS)
- const cc::PaintImage& paint_image() const { return paint_image_; }
-#endif
-
- private:
-#if !defined(OS_IOS)
- cc::PaintImage paint_image_;
-#endif
- SkBitmap bitmap_;
-
- float scale_;
-};
-
-} // namespace gfx
+#if defined(OS_IOS)
+#include "ui/gfx/image/image_skia_rep_ios.h"
+#else
+#include "ui/gfx/image/image_skia_rep_default.h"
+#endif // defined(OS_IOS)
#endif // UI_GFX_IMAGE_IMAGE_SKIA_REP_H_
diff --git a/chromium/ui/gfx/image/image_skia_rep_default.cc b/chromium/ui/gfx/image/image_skia_rep_default.cc
new file mode 100644
index 00000000000..bee88848ac5
--- /dev/null
+++ b/chromium/ui/gfx/image/image_skia_rep_default.cc
@@ -0,0 +1,106 @@
+// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/image/image_skia_rep_default.h"
+
+#include "base/logging.h"
+#include "cc/paint/display_item_list.h"
+#include "cc/paint/record_paint_canvas.h"
+#include "cc/paint/skia_paint_canvas.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+
+namespace gfx {
+
+ImageSkiaRep::ImageSkiaRep()
+ : type_(ImageRepType::kImageTypeDrawable), scale_(0.0f) {}
+
+ImageSkiaRep::ImageSkiaRep(const gfx::Size& size, float scale)
+ : type_(ImageRepType::kImageTypeBitmap), scale_(scale) {
+ bitmap_.allocN32Pixels(static_cast<int>(size.width() * this->scale()),
+ static_cast<int>(size.height() * this->scale()));
+ bitmap_.eraseColor(SK_ColorRED);
+ bitmap_.setImmutable();
+ pixel_size_.SetSize(bitmap_.width(), bitmap_.height());
+ paint_image_ = cc::PaintImage::CreateFromBitmap(bitmap_);
+}
+
+ImageSkiaRep::ImageSkiaRep(const SkBitmap& src, float scale)
+ : type_(ImageRepType::kImageTypeBitmap),
+ pixel_size_(gfx::Size(src.width(), src.height())),
+ bitmap_(src),
+ scale_(scale) {
+ bitmap_.setImmutable();
+ paint_image_ = cc::PaintImage::CreateFromBitmap(src);
+}
+
+ImageSkiaRep::ImageSkiaRep(sk_sp<cc::PaintRecord> paint_record,
+ const gfx::Size& pixel_size,
+ float scale)
+ : paint_record_(std::move(paint_record)),
+ type_(ImageRepType::kImageTypeDrawable),
+ pixel_size_(pixel_size),
+ scale_(scale) {}
+
+ImageSkiaRep::ImageSkiaRep(const ImageSkiaRep& other)
+ : paint_image_(other.paint_image_),
+ paint_record_(other.paint_record_),
+ type_(other.type_),
+ pixel_size_(other.pixel_size_),
+ bitmap_(other.bitmap_),
+ scale_(other.scale_) {}
+
+ImageSkiaRep::~ImageSkiaRep() {}
+
+int ImageSkiaRep::GetWidth() const {
+ return static_cast<int>(pixel_width() / scale());
+}
+
+int ImageSkiaRep::GetHeight() const {
+ return static_cast<int>(pixel_height() / scale());
+}
+
+sk_sp<cc::PaintRecord> ImageSkiaRep::GetPaintRecord() const {
+ DCHECK(type_ == ImageRepType::kImageTypeBitmap || !is_null());
+ // If this image rep is of |kImageTypeDrawable| then it must have a paint
+ // record.
+ if (type_ == ImageRepType::kImageTypeDrawable || paint_record_)
+ return paint_record_;
+
+ // If this ImageRep was generated using a bitmap then it may not have a
+ // paint record generated for it yet. We would have to generate it now.
+ scoped_refptr<cc::DisplayItemList> display_item_list =
+ base::MakeRefCounted<cc::DisplayItemList>(
+ cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer);
+
+ cc::RecordPaintCanvas record_canvas(
+ display_item_list.get(), SkRect::MakeIWH(pixel_width(), pixel_height()));
+
+ display_item_list->StartPaint();
+ record_canvas.drawImage(paint_image(), 0, 0, nullptr);
+ display_item_list->EndPaintOfPairedEnd();
+ display_item_list->Finalize();
+
+ paint_record_ = display_item_list->ReleaseAsRecord();
+ return paint_record_;
+}
+
+const SkBitmap& ImageSkiaRep::GetBitmap() const {
+ if (type_ == ImageRepType::kImageTypeDrawable && bitmap_.isNull() &&
+ paint_record_) {
+ // TODO(malaykeshav): Add a NOTREACHED() once all instances of this call
+ // path is removed from the code base.
+
+ // A request for bitmap was made even though this ImageSkiaRep is sourced
+ // form a drawable(e.g. CanvasImageSource). This should not be happenning
+ // as it forces a rasterization on the UI thread.
+ bitmap_.allocN32Pixels(pixel_width(), pixel_height());
+ bitmap_.eraseColor(SK_ColorTRANSPARENT);
+ SkCanvas canvas(bitmap_);
+ paint_record_->Playback(&canvas);
+ bitmap_.setImmutable();
+ }
+ return bitmap_;
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/image/image_skia_rep_default.h b/chromium/ui/gfx/image/image_skia_rep_default.h
new file mode 100644
index 00000000000..79705fb0435
--- /dev/null
+++ b/chromium/ui/gfx/image/image_skia_rep_default.h
@@ -0,0 +1,98 @@
+// 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_GFX_IMAGE_IMAGE_SKIA_REP_DEFAULT_H_
+#define UI_GFX_IMAGE_IMAGE_SKIA_REP_DEFAULT_H_
+
+#include "build/build_config.h"
+#include "cc/paint/paint_image.h"
+#include "cc/paint/paint_op_buffer.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+
+// An ImageSkiaRep represents an image and the scale factor it is intended for.
+// 0.0f scale is used to indicate that this ImageSkiaRep is used for unscaled
+// (ImageSkia does not automatically scale the image).
+// TODO(malaykeshav): Support transport of PaintRecord across mojo. This would
+// require adding inline serialization support for PaintRecords.
+class GFX_EXPORT ImageSkiaRep {
+ public:
+ // Create null bitmap.
+ ImageSkiaRep();
+
+ // Note: This is for testing purpose only.
+ // Creates a bitmap with kARGB_8888_Config config with given |size| in DIP.
+ // This allocates pixels in the bitmap. It is guaranteed that the data in the
+ // bitmap are initialized but the actual values are undefined.
+ // Specifying 0 scale means the image is for unscaled image. (unscaled()
+ // returns truen, and scale() returns 1.0f;)
+ ImageSkiaRep(const gfx::Size& size, float scale);
+
+ // Creates a bitmap with given scale.
+ // Adds ref to |src|.
+ ImageSkiaRep(const SkBitmap& src, float scale);
+
+ // Creates an image rep backed by a paint record of given size and scale. This
+ // is used when the image representation is sourced from a drawable sunch as
+ // CanvasImageSource.
+ ImageSkiaRep(sk_sp<cc::PaintRecord> paint_record,
+ const gfx::Size& size,
+ float scale);
+
+ ImageSkiaRep(const ImageSkiaRep& other);
+ ~ImageSkiaRep();
+
+ // Get width and height of the image in pixels.
+ int pixel_width() const { return pixel_size_.width(); }
+ int pixel_height() const { return pixel_size_.height(); }
+ const Size& pixel_size() const { return pixel_size_; }
+
+ // Get width and height of the image in DIP.
+ int GetWidth() const;
+ int GetHeight() const;
+
+ // Retrieves the scale for which this image is a representation of.
+ float scale() const { return unscaled() ? 1.0f : scale_; }
+ bool unscaled() const { return scale_ == 0.0f; }
+
+ bool is_null() const {
+ return type_ == ImageRepType::kImageTypeBitmap ? bitmap_.isNull()
+ : !paint_record_;
+ }
+
+ // Returns the backing bitmap when the image representation is sourced from a
+ // bitmap. If this is a |kImageTypeDrawable| then it will generate(and cache)
+ // a bitmap.
+ const SkBitmap& GetBitmap() const;
+
+ // Returns the backing drawable as a PaintRecord. Use this when the type of
+ // ImageRep is |kImageTypeDrawable|.
+ sk_sp<cc::PaintRecord> GetPaintRecord() const;
+
+ const cc::PaintImage& paint_image() const { return paint_image_; };
+ bool has_paint_image() const { return !!paint_image_; }
+
+ private:
+ enum class ImageRepType {
+ kImageTypeBitmap, // When the source image is rasterized. (Bitmaps, PNGs)
+ kImageTypeDrawable // When the source image is a drawable generated by a
+ // CanvasImageSource.
+ };
+
+ // TODO(malaykeshav): Remove when migration is complete and it is safe.
+ cc::PaintImage paint_image_;
+ mutable sk_sp<cc::PaintRecord> paint_record_;
+ ImageRepType type_;
+
+ Size pixel_size_;
+ mutable SkBitmap bitmap_;
+ float scale_;
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_IMAGE_IMAGE_SKIA_REP_DEFAULT_H_
diff --git a/chromium/ui/gfx/image/image_skia_rep.cc b/chromium/ui/gfx/image/image_skia_rep_ios.cc
index 241569ee684..5e389f5c75d 100644
--- a/chromium/ui/gfx/image/image_skia_rep.cc
+++ b/chromium/ui/gfx/image/image_skia_rep_ios.cc
@@ -1,50 +1,47 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/gfx/image/image_skia_rep.h"
+#include "ui/gfx/image/image_skia_rep_ios.h"
#include "base/logging.h"
namespace gfx {
-ImageSkiaRep::ImageSkiaRep() : scale_(0.0f) {
-}
-
-ImageSkiaRep::~ImageSkiaRep() {
-}
+ImageSkiaRep::ImageSkiaRep() : scale_(0.0f) {}
ImageSkiaRep::ImageSkiaRep(const gfx::Size& size, float scale) : scale_(scale) {
bitmap_.allocN32Pixels(static_cast<int>(size.width() * this->scale()),
static_cast<int>(size.height() * this->scale()));
bitmap_.eraseColor(SK_ColorRED);
bitmap_.setImmutable();
-#if !defined(OS_IOS)
- paint_image_ = cc::PaintImage::CreateFromBitmap(bitmap_);
-#endif
+ pixel_size_.SetSize(bitmap_.width(), bitmap_.height());
}
ImageSkiaRep::ImageSkiaRep(const SkBitmap& src, float scale)
- : bitmap_(src),
+ : pixel_size_(gfx::Size(src.width(), src.height())),
+ bitmap_(src),
scale_(scale) {
bitmap_.setImmutable();
-#if !defined(OS_IOS)
- paint_image_ = cc::PaintImage::CreateFromBitmap(bitmap_);
-#endif
}
+ImageSkiaRep::ImageSkiaRep(const ImageSkiaRep& other)
+ : pixel_size_(other.pixel_size_),
+ bitmap_(other.bitmap_),
+ scale_(other.scale_) {}
+
+ImageSkiaRep::~ImageSkiaRep() {}
+
int ImageSkiaRep::GetWidth() const {
- return static_cast<int>(bitmap_.width() / scale());
+ return static_cast<int>(pixel_width() / scale());
}
int ImageSkiaRep::GetHeight() const {
- return static_cast<int>(bitmap_.height() / scale());
+ return static_cast<int>(pixel_height() / scale());
}
-void ImageSkiaRep::SetScaled() {
- DCHECK_EQ(0.0f, scale_);
- if (scale_ == 0.0f)
- scale_ = 1.0f;
+const SkBitmap& ImageSkiaRep::GetBitmap() const {
+ return bitmap_;
}
} // namespace gfx
diff --git a/chromium/ui/gfx/image/image_skia_rep_ios.h b/chromium/ui/gfx/image/image_skia_rep_ios.h
new file mode 100644
index 00000000000..51e8f8473c0
--- /dev/null
+++ b/chromium/ui/gfx/image/image_skia_rep_ios.h
@@ -0,0 +1,67 @@
+// 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_GFX_IMAGE_IMAGE_SKIA_REP_IOS_H_
+#define UI_GFX_IMAGE_IMAGE_SKIA_REP_IOS_H_
+
+#include "build/build_config.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+
+// An ImageSkiaRep represents an image and the scale factor it is intended for.
+// 0.0f scale is used to indicate that this ImageSkiaRep is used for unscaled
+// image (ImageSkia does not automatically scale the image).
+// iOS does not support cc's PaintOpBuffer and instead uses cocoa frameworks
+// image formats.
+class GFX_EXPORT ImageSkiaRep {
+ public:
+ // Create null bitmap.
+ ImageSkiaRep();
+
+ // Note: This is for testing purpose only.
+ // Creates a bitmap with kARGB_8888_Config config with given |size| in DIP.
+ // This allocates pixels in the bitmap. It is guaranteed that the data in the
+ // bitmap are initialized but the actual values are undefined.
+ // Specifying 0 scale means the image is for unscaled image. (unscaled()
+ // returns truen, and scale() returns 1.0f;)
+ ImageSkiaRep(const gfx::Size& size, float scale);
+
+ // Creates a bitmap with given scale.
+ // Adds ref to |src|.
+ ImageSkiaRep(const SkBitmap& src, float scale);
+ ImageSkiaRep(const ImageSkiaRep& other);
+
+ ~ImageSkiaRep();
+
+ // Get width and height of the image in pixels.
+ int pixel_width() const { return bitmap_.width(); }
+ int pixel_height() const { return bitmap_.height(); }
+ Size pixel_size() const { return gfx::Size(pixel_width(), pixel_height()); }
+
+ // Get width and height of the image in DIP.
+ int GetWidth() const;
+ int GetHeight() const;
+
+ // Retrieves the scale for which this image is a representation of.
+ float scale() const { return unscaled() ? 1.0f : scale_; }
+ bool unscaled() const { return scale_ == 0.0f; }
+
+ bool is_null() const { return bitmap_.isNull(); }
+
+ // Returns the backing bitmap when the image representation is sourced from a
+ // bitmap.
+ const SkBitmap& GetBitmap() const;
+
+ private:
+ Size pixel_size_;
+ SkBitmap bitmap_;
+ float scale_;
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_IMAGE_IMAGE_SKIA_REP_IOS_H_
diff --git a/chromium/ui/gfx/image/image_skia_util_ios.mm b/chromium/ui/gfx/image/image_skia_util_ios.mm
index 89b25eb27ad..e7ac3b490e5 100644
--- a/chromium/ui/gfx/image/image_skia_util_ios.mm
+++ b/chromium/ui/gfx/image/image_skia_util_ios.mm
@@ -49,7 +49,7 @@ UIImage* UIImageFromImageSkiaRep(const gfx::ImageSkiaRep& image_skia_rep) {
float scale = image_skia_rep.scale();
base::ScopedCFTypeRef<CGColorSpaceRef> color_space(
CGColorSpaceCreateDeviceRGB());
- return skia::SkBitmapToUIImageWithColorSpace(image_skia_rep.sk_bitmap(),
+ return skia::SkBitmapToUIImageWithColorSpace(image_skia_rep.GetBitmap(),
scale, color_space);
}
diff --git a/chromium/ui/gfx/image/image_skia_util_mac.mm b/chromium/ui/gfx/image/image_skia_util_mac.mm
index b06eddf4518..35b3845e977 100644
--- a/chromium/ui/gfx/image/image_skia_util_mac.mm
+++ b/chromium/ui/gfx/image/image_skia_util_mac.mm
@@ -88,8 +88,7 @@ NSImage* NSImageFromImageSkia(const gfx::ImageSkia& image_skia) {
std::vector<gfx::ImageSkiaRep> image_reps = image_skia.image_reps();
for (std::vector<gfx::ImageSkiaRep>::const_iterator it = image_reps.begin();
it != image_reps.end(); ++it) {
- [image addRepresentation:
- skia::SkBitmapToNSBitmapImageRep(it->sk_bitmap())];
+ [image addRepresentation:skia::SkBitmapToNSBitmapImageRep(it->GetBitmap())];
}
[image setSize:NSMakeSize(image_skia.width(), image_skia.height())];
@@ -106,9 +105,8 @@ NSImage* NSImageFromImageSkiaWithColorSpace(const gfx::ImageSkia& image_skia,
std::vector<gfx::ImageSkiaRep> image_reps = image_skia.image_reps();
for (std::vector<gfx::ImageSkiaRep>::const_iterator it = image_reps.begin();
it != image_reps.end(); ++it) {
- [image addRepresentation:
- skia::SkBitmapToNSBitmapImageRepWithColorSpace(it->sk_bitmap(),
- color_space)];
+ [image addRepresentation:skia::SkBitmapToNSBitmapImageRepWithColorSpace(
+ it->GetBitmap(), color_space)];
}
[image setSize:NSMakeSize(image_skia.width(), image_skia.height())];
diff --git a/chromium/ui/gfx/image/image_unittest.cc b/chromium/ui/gfx/image/image_unittest.cc
index aaad851ed24..faa55c299a0 100644
--- a/chromium/ui/gfx/image/image_unittest.cc
+++ b/chromium/ui/gfx/image/image_unittest.cc
@@ -227,11 +227,11 @@ TEST_F(ImageTest, MultiResolutionPNGToImageSkia) {
scales.push_back(1.0f);
scales.push_back(2.0f);
gfx::ImageSkia image_skia = image.AsImageSkia();
- EXPECT_TRUE(gt::ArePNGBytesCloseToBitmap(bytes1x,
- image_skia.GetRepresentation(1.0f).sk_bitmap(),
+ EXPECT_TRUE(gt::ArePNGBytesCloseToBitmap(
+ bytes1x, image_skia.GetRepresentation(1.0f).GetBitmap(),
gt::MaxColorSpaceConversionColorShift()));
- EXPECT_TRUE(gt::ArePNGBytesCloseToBitmap(bytes2x,
- image_skia.GetRepresentation(2.0f).sk_bitmap(),
+ EXPECT_TRUE(gt::ArePNGBytesCloseToBitmap(
+ bytes2x, image_skia.GetRepresentation(2.0f).GetBitmap(),
gt::MaxColorSpaceConversionColorShift()));
EXPECT_TRUE(gt::ImageSkiaStructureMatches(image_skia, kSize1x, kSize1x,
scales));
diff --git a/chromium/ui/gfx/image/image_unittest_util.cc b/chromium/ui/gfx/image/image_unittest_util.cc
index f618cee205e..95cfd57f866 100644
--- a/chromium/ui/gfx/image/image_unittest_util.cc
+++ b/chromium/ui/gfx/image/image_unittest_util.cc
@@ -112,7 +112,7 @@ bool AreImagesClose(const gfx::Image& img1,
float scale = img1_reps[i].scale();
const gfx::ImageSkiaRep& image_rep2 = image_skia2.GetRepresentation(scale);
if (image_rep2.scale() != scale ||
- !AreBitmapsClose(img1_reps[i].sk_bitmap(), image_rep2.sk_bitmap(),
+ !AreBitmapsClose(img1_reps[i].GetBitmap(), image_rep2.GetBitmap(),
max_deviation)) {
return false;
}
diff --git a/chromium/ui/gfx/image/image_util.cc b/chromium/ui/gfx/image/image_util.cc
index 624620c90bc..dc0061dbde2 100644
--- a/chromium/ui/gfx/image/image_util.cc
+++ b/chromium/ui/gfx/image/image_util.cc
@@ -61,7 +61,7 @@ bool JPEG1xEncodedDataFromSkiaRepresentation(const Image& image,
if (image_skia_rep.scale() != 1.0f)
return false;
- const SkBitmap& bitmap = image_skia_rep.sk_bitmap();
+ const SkBitmap& bitmap = image_skia_rep.GetBitmap();
if (!bitmap.readyToDraw())
return false;
@@ -74,7 +74,7 @@ void GetVisibleMargins(const ImageSkia& image, int* left, int* right) {
*right = 0;
if (!image.HasRepresentation(1.f))
return;
- const SkBitmap& bitmap = image.GetRepresentation(1.f).sk_bitmap();
+ const SkBitmap& bitmap = image.GetRepresentation(1.f).GetBitmap();
if (bitmap.drawsNothing() || bitmap.isOpaque())
return;
diff --git a/chromium/ui/gfx/image/mojo/image_skia_struct_traits.h b/chromium/ui/gfx/image/mojo/image_skia_struct_traits.h
index 8eabab01fd2..43529dbce87 100644
--- a/chromium/ui/gfx/image/mojo/image_skia_struct_traits.h
+++ b/chromium/ui/gfx/image/mojo/image_skia_struct_traits.h
@@ -20,7 +20,7 @@ namespace mojo {
template <>
struct StructTraits<gfx::mojom::ImageSkiaRepDataView, gfx::ImageSkiaRep> {
static SkBitmap bitmap(const gfx::ImageSkiaRep& input) {
- return input.sk_bitmap();
+ return input.GetBitmap();
}
static float scale(const gfx::ImageSkiaRep& input);
diff --git a/chromium/ui/gfx/image/mojo/image_traits_unittest.cc b/chromium/ui/gfx/image/mojo/image_traits_unittest.cc
index de87d867765..1977989f001 100644
--- a/chromium/ui/gfx/image/mojo/image_traits_unittest.cc
+++ b/chromium/ui/gfx/image/mojo/image_traits_unittest.cc
@@ -96,8 +96,8 @@ TEST_F(ImageTraitsTest, EmptyImageSkiaRep) {
ImageSkiaRep output(gfx::Size(1, 1), 1.0f);
ASSERT_FALSE(output.is_null());
service()->EchoImageSkiaRep(empty_rep, &output);
- EXPECT_TRUE(empty_rep.sk_bitmap().drawsNothing());
- EXPECT_TRUE(test::AreBitmapsEqual(empty_rep.sk_bitmap(), output.sk_bitmap()));
+ EXPECT_TRUE(empty_rep.GetBitmap().drawsNothing());
+ EXPECT_TRUE(test::AreBitmapsEqual(empty_rep.GetBitmap(), output.GetBitmap()));
}
TEST_F(ImageTraitsTest, ImageSkiaRep) {
@@ -108,7 +108,7 @@ TEST_F(ImageTraitsTest, ImageSkiaRep) {
EXPECT_FALSE(output.is_null());
EXPECT_EQ(image_rep.scale(), output.scale());
- EXPECT_TRUE(test::AreBitmapsEqual(image_rep.sk_bitmap(), output.sk_bitmap()));
+ EXPECT_TRUE(test::AreBitmapsEqual(image_rep.GetBitmap(), output.GetBitmap()));
}
TEST_F(ImageTraitsTest, UnscaledImageSkiaRep) {
@@ -119,7 +119,7 @@ TEST_F(ImageTraitsTest, UnscaledImageSkiaRep) {
EXPECT_FALSE(output.unscaled());
service()->EchoImageSkiaRep(image_rep, &output);
EXPECT_TRUE(output.unscaled());
- EXPECT_TRUE(test::AreBitmapsEqual(image_rep.sk_bitmap(), output.sk_bitmap()));
+ EXPECT_TRUE(test::AreBitmapsEqual(image_rep.GetBitmap(), output.GetBitmap()));
}
TEST_F(ImageTraitsTest, NullImageSkia) {
diff --git a/chromium/ui/gfx/interpolated_transform.h b/chromium/ui/gfx/interpolated_transform.h
index 3e0c6456641..33c50d91560 100644
--- a/chromium/ui/gfx/interpolated_transform.h
+++ b/chromium/ui/gfx/interpolated_transform.h
@@ -11,6 +11,7 @@
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/point3_f.h"
#include "ui/gfx/geometry/vector3d_f.h"
+#include "ui/gfx/gfx_export.h"
#include "ui/gfx/transform.h"
#include "ui/gfx/transform_util.h"
diff --git a/chromium/ui/gfx/linux/OWNERS b/chromium/ui/gfx/linux/OWNERS
index 4bd7b3f514a..2d13a903030 100644
--- a/chromium/ui/gfx/linux/OWNERS
+++ b/chromium/ui/gfx/linux/OWNERS
@@ -2,3 +2,4 @@ dcastagna@chromium.org
dongseong.hwang@chromium.org
dnicoara@chromium.org
reveman@chromium.org
+rjkroege@chromium.org
diff --git a/chromium/ui/gfx/mac/io_surface.cc b/chromium/ui/gfx/mac/io_surface.cc
index 00ad38db090..8d9f38b1f3d 100644
--- a/chromium/ui/gfx/mac/io_surface.cc
+++ b/chromium/ui/gfx/mac/io_surface.cc
@@ -52,11 +52,6 @@ int32_t BytesPerElement(gfx::BufferFormat format, int plane) {
case gfx::BufferFormat::UYVY_422:
DCHECK_EQ(plane, 0);
return 2;
- case gfx::BufferFormat::ATC:
- case gfx::BufferFormat::ATCIA:
- case gfx::BufferFormat::DXT1:
- case gfx::BufferFormat::DXT5:
- case gfx::BufferFormat::ETC1:
case gfx::BufferFormat::BGR_565:
case gfx::BufferFormat::RGBA_4444:
case gfx::BufferFormat::RGBX_8888:
@@ -88,11 +83,6 @@ int32_t PixelFormat(gfx::BufferFormat format) {
return '2vuy';
case gfx::BufferFormat::R_16:
case gfx::BufferFormat::RG_88:
- case gfx::BufferFormat::ATC:
- case gfx::BufferFormat::ATCIA:
- case gfx::BufferFormat::DXT1:
- case gfx::BufferFormat::DXT5:
- case gfx::BufferFormat::ETC1:
case gfx::BufferFormat::BGR_565:
case gfx::BufferFormat::RGBA_4444:
case gfx::BufferFormat::RGBX_8888:
diff --git a/chromium/ui/gfx/mojo/BUILD.gn b/chromium/ui/gfx/mojo/BUILD.gn
index 046afff7f55..fb02266e148 100644
--- a/chromium/ui/gfx/mojo/BUILD.gn
+++ b/chromium/ui/gfx/mojo/BUILD.gn
@@ -15,6 +15,7 @@ mojom("mojo") {
"overlay_transform.mojom",
"presentation_feedback.mojom",
"selection_bound.mojom",
+ "swap_result.mojom",
"transform.mojom",
]
diff --git a/chromium/ui/gfx/mojo/buffer_types.mojom b/chromium/ui/gfx/mojo/buffer_types.mojom
index c14e5ae8698..170f1eb60e3 100644
--- a/chromium/ui/gfx/mojo/buffer_types.mojom
+++ b/chromium/ui/gfx/mojo/buffer_types.mojom
@@ -6,11 +6,6 @@ module gfx.mojom;
// gfx::BufferFormat
enum BufferFormat {
- ATC,
- ATCIA,
- DXT1,
- DXT5,
- ETC1,
R_8,
R_16,
RG_88,
diff --git a/chromium/ui/gfx/mojo/buffer_types_struct_traits.cc b/chromium/ui/gfx/mojo/buffer_types_struct_traits.cc
index 534c7f9a509..bfe71c55134 100644
--- a/chromium/ui/gfx/mojo/buffer_types_struct_traits.cc
+++ b/chromium/ui/gfx/mojo/buffer_types_struct_traits.cc
@@ -13,6 +13,10 @@
#include "mojo/public/cpp/system/scope_to_message_pipe.h"
#endif
+#if !defined(OS_LINUX)
+#include "base/no_destructor.h"
+#endif
+
namespace mojo {
// static
@@ -74,8 +78,8 @@ StructTraits<gfx::mojom::GpuMemoryBufferHandleDataView,
#if defined(OS_LINUX)
return handle.native_pixmap_handle;
#else
- static gfx::NativePixmapHandle pixmap_handle;
- return pixmap_handle;
+ static base::NoDestructor<gfx::NativePixmapHandle> pixmap_handle;
+ return *pixmap_handle;
#endif
}
diff --git a/chromium/ui/gfx/mojo/buffer_types_struct_traits.h b/chromium/ui/gfx/mojo/buffer_types_struct_traits.h
index 33069bc27af..8c8c1fc9d5e 100644
--- a/chromium/ui/gfx/mojo/buffer_types_struct_traits.h
+++ b/chromium/ui/gfx/mojo/buffer_types_struct_traits.h
@@ -15,16 +15,6 @@ template <>
struct EnumTraits<gfx::mojom::BufferFormat, gfx::BufferFormat> {
static gfx::mojom::BufferFormat ToMojom(gfx::BufferFormat format) {
switch (format) {
- case gfx::BufferFormat::ATC:
- return gfx::mojom::BufferFormat::ATC;
- case gfx::BufferFormat::ATCIA:
- return gfx::mojom::BufferFormat::ATCIA;
- case gfx::BufferFormat::DXT1:
- return gfx::mojom::BufferFormat::DXT1;
- case gfx::BufferFormat::DXT5:
- return gfx::mojom::BufferFormat::DXT5;
- case gfx::BufferFormat::ETC1:
- return gfx::mojom::BufferFormat::ETC1;
case gfx::BufferFormat::R_8:
return gfx::mojom::BufferFormat::R_8;
case gfx::BufferFormat::R_16:
@@ -63,21 +53,6 @@ struct EnumTraits<gfx::mojom::BufferFormat, gfx::BufferFormat> {
static bool FromMojom(gfx::mojom::BufferFormat input,
gfx::BufferFormat* out) {
switch (input) {
- case gfx::mojom::BufferFormat::ATC:
- *out = gfx::BufferFormat::ATC;
- return true;
- case gfx::mojom::BufferFormat::ATCIA:
- *out = gfx::BufferFormat::ATCIA;
- return true;
- case gfx::mojom::BufferFormat::DXT1:
- *out = gfx::BufferFormat::DXT1;
- return true;
- case gfx::mojom::BufferFormat::DXT5:
- *out = gfx::BufferFormat::DXT5;
- return true;
- case gfx::mojom::BufferFormat::ETC1:
- *out = gfx::BufferFormat::ETC1;
- return true;
case gfx::mojom::BufferFormat::R_8:
*out = gfx::BufferFormat::R_8;
return true;
diff --git a/chromium/ui/gfx/mojo/selection_bound.typemap b/chromium/ui/gfx/mojo/selection_bound.typemap
index e2b16f7a264..d6bb0940b34 100644
--- a/chromium/ui/gfx/mojo/selection_bound.typemap
+++ b/chromium/ui/gfx/mojo/selection_bound.typemap
@@ -6,3 +6,6 @@ mojom = "//ui/gfx/mojo/selection_bound.mojom"
public_headers = [ "//ui/gfx/selection_bound.h" ]
traits_headers = [ "//ui/gfx/mojo/selection_bound_struct_traits.h" ]
type_mappings = [ "gfx.mojom.SelectionBound=gfx::SelectionBound" ]
+deps = [
+ "//ui/gfx/geometry/mojo:struct_traits",
+]
diff --git a/chromium/ui/gfx/mojo/selection_bound_struct_traits.h b/chromium/ui/gfx/mojo/selection_bound_struct_traits.h
index f4ba831b09b..681de71703b 100644
--- a/chromium/ui/gfx/mojo/selection_bound_struct_traits.h
+++ b/chromium/ui/gfx/mojo/selection_bound_struct_traits.h
@@ -5,6 +5,7 @@
#ifndef UI_GFX_MOJO_SELECTION_BOUND_STRUCT_TRAITS_H_
#define UI_GFX_MOJO_SELECTION_BOUND_STRUCT_TRAITS_H_
+#include "ui/gfx/geometry/mojo/geometry_struct_traits.h"
#include "ui/gfx/mojo/selection_bound.mojom-shared.h"
#include "ui/gfx/selection_bound.h"
diff --git a/chromium/ui/gfx/mojo/swap_result.mojom b/chromium/ui/gfx/mojo/swap_result.mojom
new file mode 100644
index 00000000000..b73d4e43f59
--- /dev/null
+++ b/chromium/ui/gfx/mojo/swap_result.mojom
@@ -0,0 +1,16 @@
+// 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.
+
+module gfx.mojom;
+
+// SwapResult information which is used to indicate whether buffer swap
+// succeeded or not. These values correspond to gfx::SwapResult values in
+// ui/gfx/swap_result.h. Currently, it is used by the Ozone/Wayland to identify
+// whether a buffer swap requested by the GPU process has been successful on
+// the browser process side or not.
+enum SwapResult {
+ ACK,
+ FAILED,
+ NAK_RECREATE_BUFFERS,
+};
diff --git a/chromium/ui/gfx/mojo/swap_result.typemap b/chromium/ui/gfx/mojo/swap_result.typemap
new file mode 100644
index 00000000000..76d24a5085c
--- /dev/null
+++ b/chromium/ui/gfx/mojo/swap_result.typemap
@@ -0,0 +1,8 @@
+# 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.
+
+mojom = "//ui/gfx/mojo/swap_result.mojom"
+public_headers = [ "//ui/gfx/swap_result.h" ]
+traits_headers = [ "//ui/gfx/mojo/swap_result_enum_traits.h" ]
+type_mappings = [ "gfx.mojom.SwapResult=gfx::SwapResult" ]
diff --git a/chromium/ui/gfx/mojo/swap_result_enum_traits.h b/chromium/ui/gfx/mojo/swap_result_enum_traits.h
new file mode 100644
index 00000000000..c32ca59b055
--- /dev/null
+++ b/chromium/ui/gfx/mojo/swap_result_enum_traits.h
@@ -0,0 +1,48 @@
+// 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_GFX_MOJO_SWAP_RESULT_ENUM_TRAITS_H_
+#define UI_GFX_MOJO_SWAP_RESULT_ENUM_TRAITS_H_
+
+#include "mojo/public/cpp/bindings/enum_traits.h"
+#include "ui/gfx/mojo/swap_result.mojom-shared.h"
+#include "ui/gfx/swap_result.h"
+
+namespace mojo {
+
+template <>
+struct EnumTraits<gfx::mojom::SwapResult, gfx::SwapResult> {
+ static gfx::mojom::SwapResult ToMojom(gfx::SwapResult input) {
+ switch (input) {
+ case gfx::SwapResult::SWAP_ACK:
+ return gfx::mojom::SwapResult::ACK;
+ case gfx::SwapResult::SWAP_FAILED:
+ return gfx::mojom::SwapResult::FAILED;
+ case gfx::SwapResult::SWAP_NAK_RECREATE_BUFFERS:
+ return gfx::mojom::SwapResult::NAK_RECREATE_BUFFERS;
+ }
+ NOTREACHED();
+ return gfx::mojom::SwapResult::FAILED;
+ }
+
+ static bool FromMojom(gfx::mojom::SwapResult input, gfx::SwapResult* out) {
+ switch (input) {
+ case gfx::mojom::SwapResult::ACK:
+ *out = gfx::SwapResult::SWAP_ACK;
+ return true;
+ case gfx::mojom::SwapResult::FAILED:
+ *out = gfx::SwapResult::SWAP_FAILED;
+ return true;
+ case gfx::mojom::SwapResult::NAK_RECREATE_BUFFERS:
+ *out = gfx::SwapResult::SWAP_NAK_RECREATE_BUFFERS;
+ return true;
+ }
+ NOTREACHED();
+ return false;
+ }
+};
+
+} // namespace mojo
+
+#endif // UI_GFX_MOJO_SWAP_RESULT_ENUM_TRAITS_H_
diff --git a/chromium/ui/gfx/platform_font_win.cc b/chromium/ui/gfx/platform_font_win.cc
index 187ffbdaa03..7a43e1309b2 100644
--- a/chromium/ui/gfx/platform_font_win.cc
+++ b/chromium/ui/gfx/platform_font_win.cc
@@ -4,19 +4,22 @@
#include "ui/gfx/platform_font_win.h"
-#include <windows.h>
#include <dwrite.h>
#include <limits.h>
#include <math.h>
#include <stdint.h>
#include <wchar.h>
+#include <windows.h>
#include <wrl/client.h>
#include <algorithm>
+#include <utility>
+#include "base/containers/flat_map.h"
#include "base/debug/alias.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/no_destructor.h"
#include "base/strings/string16.h"
#include "base/strings/string_util.h"
#include "base/strings/sys_string_conversions.h"
@@ -35,32 +38,6 @@
namespace {
-// Returns the minimum font size, using the minimum size callback, if set.
-int GetMinimumFontSize() {
- int min_font_size = 0;
- if (gfx::PlatformFontWin::get_minimum_font_size_callback)
- min_font_size = gfx::PlatformFontWin::get_minimum_font_size_callback();
- return min_font_size;
-}
-
-// Returns either minimum font allowed for a current locale or
-// lf_height + size_delta value.
-int AdjustFontSize(int lf_height, int size_delta) {
- if (lf_height < 0) {
- lf_height -= size_delta;
- } else {
- lf_height += size_delta;
- }
- const int min_font_size = GetMinimumFontSize();
- // Make sure lf_height is not smaller than allowed min font size for current
- // locale.
- if (abs(lf_height) < min_font_size) {
- return lf_height < 0 ? -min_font_size : min_font_size;
- } else {
- return lf_height;
- }
-}
-
// Sets style properties on |font_info| based on |font_style|.
void SetLogFontStyle(int font_style, LOGFONT* font_info) {
font_info->lfUnderline = (font_style & gfx::Font::UNDERLINE) != 0;
@@ -251,14 +228,134 @@ HRESULT GetMatchingDirectWriteFont(LOGFONT* font_info,
namespace gfx {
+namespace internal {
+
+class SystemFonts {
+ public:
+ SystemFonts() {
+ NONCLIENTMETRICS_XP metrics;
+ base::win::GetNonClientMetrics(&metrics);
+
+ // NOTE(dfried): When rendering Chrome, we do all of our own font scaling
+ // based on a number of factors, but what Windows reports to us has some
+ // (but not all) of these factors baked in, and not in a way that is
+ // display-consistent.
+ //
+ // For example, if your system DPI is 192 (200%) but you connect a monitor
+ // with a standard DPI (100%) then even if Chrome starts on the second
+ // monitor, we will be told the system font is 24pt instead of 12pt.
+ // Conversely, if the system DPI is set to 96 (100%) but all of our monitors
+ // are currently at 150%, Windows will still report 12pt fonts.
+ //
+ // The same is true with Text Zoom (a new accessibility feature). If zoom is
+ // set to 150%, then Windows will report a font size of 18pt. But again, we
+ // already take Text Zoom into account when rendering, so we want to account
+ // for that.
+ //
+ // Our system fonts are in DIPs, so we must always take what Windows gives
+ // us, figure out which adjustments it's making (and undo them), make our
+ // own adjustments for localization (for example, we always render Hindi 25%
+ // larger for readability), and only then can we store (and report) the
+ // system fonts.
+
+ // Factor in/out scale adjustment that fall outside what we can access here.
+ // This includes l10n adjustments and those we have to ask UWP or other COM
+ // interfaces for (since we don't have dependencies on that code from this
+ // module, and don't want to implicitly invoke COM for testing purposes if
+ // we don't have to).
+ gfx::PlatformFontWin::FontAdjustment font_adjustment;
+ if (PlatformFontWin::adjust_font_callback_) {
+ PlatformFontWin::adjust_font_callback_(&font_adjustment);
+ }
+
+ // Factor out system DPI scale that Windows will include in reported font
+ // sizes. Note that these are (sadly) system-wide and do not reflect
+ // specific displays' DPI.
+ double system_scale = GetSystemScale();
+ font_adjustment.font_scale /= system_scale;
+
+ // Grab each of the fonts from the NONCLIENTMETRICS block, adjust it
+ // appropriately, and store it in the font table.
+ AddFont(gfx::PlatformFontWin::SystemFont::kCaption, font_adjustment,
+ &metrics.lfCaptionFont);
+ AddFont(gfx::PlatformFontWin::SystemFont::kSmallCaption, font_adjustment,
+ &metrics.lfSmCaptionFont);
+ AddFont(gfx::PlatformFontWin::SystemFont::kMenu, font_adjustment,
+ &metrics.lfMenuFont);
+ AddFont(gfx::PlatformFontWin::SystemFont::kMessage, font_adjustment,
+ &metrics.lfMessageFont);
+ AddFont(gfx::PlatformFontWin::SystemFont::kStatus, font_adjustment,
+ &metrics.lfStatusFont);
+
+ is_initialized_ = true;
+ }
+
+ const gfx::Font& GetFont(gfx::PlatformFontWin::SystemFont system_font) const {
+ auto it = system_fonts_.find(system_font);
+ DCHECK(it != system_fonts_.end())
+ << "System font #" << static_cast<int>(system_font) << " not found!";
+ DCHECK(it->second.GetNativeFont())
+ << "Font for system font #" << static_cast<int>(system_font)
+ << " has invalid handle.";
+ return it->second;
+ }
+
+ static SystemFonts* Instance() {
+ static base::NoDestructor<SystemFonts> instance;
+ return instance.get();
+ }
+
+ static bool IsInitialized() { return is_initialized_; }
+
+ private:
+ void AddFont(gfx::PlatformFontWin::SystemFont system_font,
+ const gfx::PlatformFontWin::FontAdjustment& font_adjustment,
+ LOGFONT* logfont) {
+ // Make adjustments to the font as necessary.
+ PlatformFontWin::AdjustLOGFONT(font_adjustment, logfont);
+
+ // Cap at minimum font size.
+ logfont->lfHeight = PlatformFontWin::AdjustFontSize(logfont->lfHeight, 0);
+
+ // Create the Font object.
+ HFONT font = CreateFontIndirect(logfont);
+ DLOG_ASSERT(font);
+ system_fonts_.emplace(system_font, gfx::PlatformFontWin::HFontToFont(font));
+ }
+
+ // Returns the system DPI scale (standard DPI being 1.0).
+ // TODO(dfried): move dpi.[h|cc] somewhere in base/win so we can share this
+ // logic. However, note that the similar function in dpi.h is used many places
+ // it ought not to be.
+ static double GetSystemScale() {
+ constexpr double kDefaultDPI = 96.0;
+ base::win::ScopedGetDC screen_dc(nullptr);
+ return GetDeviceCaps(screen_dc, LOGPIXELSY) / kDefaultDPI;
+ }
+
+ // Use a flat map for faster lookups.
+ base::flat_map<gfx::PlatformFontWin::SystemFont, gfx::Font> system_fonts_;
+
+ static bool is_initialized_;
+
+ DISALLOW_COPY_AND_ASSIGN(SystemFonts);
+};
+
+// static
+bool SystemFonts::is_initialized_ = false;
+
+} // namespace internal
+
// static
PlatformFontWin::HFontRef* PlatformFontWin::base_font_ref_;
// static
-PlatformFontWin::AdjustFontCallback
- PlatformFontWin::adjust_font_callback = nullptr;
-PlatformFontWin::GetMinimumFontSizeCallback
- PlatformFontWin::get_minimum_font_size_callback = NULL;
+gfx::PlatformFontWin::AdjustFontCallback
+ PlatformFontWin::adjust_font_callback_ = nullptr;
+
+// static
+gfx::PlatformFontWin::GetMinimumFontSizeCallback
+ PlatformFontWin::get_minimum_font_size_callback_ = nullptr;
IDWriteFactory* PlatformFontWin::direct_write_factory_ = nullptr;
@@ -303,6 +400,57 @@ PlatformFontWin::PlatformFontWin(const std::string& font_name,
InitWithFontNameAndSize(font_name, font_size);
}
+// static
+void PlatformFontWin::SetGetMinimumFontSizeCallback(
+ GetMinimumFontSizeCallback callback) {
+ DCHECK(!internal::SystemFonts::IsInitialized());
+ get_minimum_font_size_callback_ = callback;
+}
+
+// static
+void PlatformFontWin::SetAdjustFontCallback(AdjustFontCallback callback) {
+ DCHECK(!internal::SystemFonts::IsInitialized());
+ adjust_font_callback_ = callback;
+}
+
+// static
+void PlatformFontWin::SetDirectWriteFactory(IDWriteFactory* factory) {
+ // We grab a reference on the DirectWrite factory. This reference is
+ // leaked, which is ok because skia leaks it as well.
+ factory->AddRef();
+ direct_write_factory_ = factory;
+}
+
+// static
+bool PlatformFontWin::IsDirectWriteEnabled() {
+ return direct_write_factory_ != nullptr;
+}
+
+// static
+const Font& PlatformFontWin::GetSystemFont(SystemFont system_font) {
+ return internal::SystemFonts::Instance()->GetFont(system_font);
+}
+
+// static
+Font PlatformFontWin::AdjustExistingFont(
+ NativeFont existing_font,
+ const FontAdjustment& font_adjustment) {
+ LOGFONT logfont;
+ auto result = GetObject(existing_font, sizeof(logfont), &logfont);
+ DCHECK(result);
+
+ // Make the necessary adjustments.
+ AdjustLOGFONT(font_adjustment, &logfont);
+
+ // Cap at minimum font size.
+ logfont.lfHeight = AdjustFontSize(logfont.lfHeight, 0);
+
+ // Create the Font object.
+ HFONT hfont = CreateFontIndirect(&logfont);
+ DCHECK(hfont);
+ return HFontToFont(hfont);
+}
+
////////////////////////////////////////////////////////////////////////////////
// PlatformFontWin, PlatformFont implementation:
@@ -377,49 +525,15 @@ int PlatformFontWin::GetFontSize() const {
}
const FontRenderParams& PlatformFontWin::GetFontRenderParams() {
- CR_DEFINE_STATIC_LOCAL(const FontRenderParams, params,
- (gfx::GetFontRenderParams(FontRenderParamsQuery(), NULL)));
- return params;
+ static const base::NoDestructor<FontRenderParams> params(
+ gfx::GetFontRenderParams(FontRenderParamsQuery(), nullptr));
+ return *params;
}
NativeFont PlatformFontWin::GetNativeFont() const {
return font_ref_->hfont();
}
-// static
-void PlatformFontWin::SetDirectWriteFactory(IDWriteFactory* factory) {
- // We grab a reference on the DirectWrite factory. This reference is
- // leaked, which is ok because skia leaks it as well.
- factory->AddRef();
- direct_write_factory_ = factory;
-}
-
-// static
-bool PlatformFontWin::IsDirectWriteEnabled() {
- return direct_write_factory_ != nullptr;
-}
-
-// static
-void PlatformFontWin::GetTextMetricsForFont(HDC hdc,
- HFONT font,
- TEXTMETRIC* text_metrics) {
- base::win::ScopedSelectObject scoped_font(hdc, font);
- GetTextMetrics(hdc, text_metrics);
-}
-
-// static
-int PlatformFontWin::GetFontSize(const LOGFONT& font_info) {
- if (font_info.lfHeight < 0)
- return -font_info.lfHeight;
-
- base::win::ScopedGetDC screen_dc(NULL);
- base::win::ScopedGDIObject<HFONT> font(CreateFontIndirect(&font_info));
-
- TEXTMETRIC font_metrics = {0};
- PlatformFontWin::GetTextMetricsForFont(screen_dc, font.get(), &font_metrics);
- return font_metrics.tmAscent;
-}
-
////////////////////////////////////////////////////////////////////////////////
// Font, private:
@@ -443,20 +557,23 @@ void PlatformFontWin::InitWithFontNameAndSize(const std::string& font_name,
}
// static
-PlatformFontWin::HFontRef* PlatformFontWin::GetBaseFontRef() {
- if (base_font_ref_ == NULL) {
- NONCLIENTMETRICS_XP metrics;
- base::win::GetNonClientMetrics(&metrics);
+void PlatformFontWin::GetTextMetricsForFont(HDC hdc,
+ HFONT font,
+ TEXTMETRIC* text_metrics) {
+ base::win::ScopedSelectObject scoped_font(hdc, font);
+ GetTextMetrics(hdc, text_metrics);
+}
- if (adjust_font_callback)
- adjust_font_callback(&metrics.lfMessageFont);
- metrics.lfMessageFont.lfHeight =
- AdjustFontSize(metrics.lfMessageFont.lfHeight, 0);
- HFONT font = CreateFontIndirect(&metrics.lfMessageFont);
- DLOG_ASSERT(font);
- base_font_ref_ = PlatformFontWin::CreateHFontRef(font);
- // base_font_ref_ is global, up the ref count so it's never deleted.
- base_font_ref_->AddRef();
+// static
+PlatformFontWin::HFontRef* PlatformFontWin::GetBaseFontRef() {
+ if (base_font_ref_ == nullptr) {
+ // We'll delegate to our SystemFonts instance to give us the default
+ // message font.
+ PlatformFontWin* message_font =
+ static_cast<PlatformFontWin*>(internal::SystemFonts::Instance()
+ ->GetFont(SystemFont::kMessage)
+ .platform_font());
+ base_font_ref_ = message_font->font_ref_.get();
}
return base_font_ref_;
}
@@ -596,6 +713,50 @@ PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRefFromSkia(
ToGfxFontWeight(font_info.lfWeight), style);
}
+// static
+int PlatformFontWin::AdjustFontSize(int lf_height, int size_delta) {
+ // Extract out the sign of |lf_height| - we'll add it back later.
+ const int lf_sign = lf_height < 0 ? -1 : 1;
+ lf_height = std::abs(lf_height);
+
+ // Apply the size adjustment.
+ lf_height += size_delta;
+
+ // Make sure |lf_height| is not smaller than allowed min allowed font size.
+ int min_font_size = 0;
+ if (get_minimum_font_size_callback_) {
+ min_font_size = get_minimum_font_size_callback_();
+ DCHECK_GE(min_font_size, 0);
+ }
+ lf_height = std::max(min_font_size, lf_height);
+
+ // Add back the sign.
+ return lf_sign * lf_height;
+}
+
+// static
+void PlatformFontWin::AdjustLOGFONT(
+ const gfx::PlatformFontWin::FontAdjustment& font_adjustment,
+ LOGFONT* logfont) {
+ DCHECK_GT(font_adjustment.font_scale, 0.0);
+ LONG new_height =
+ LONG{std::round(logfont->lfHeight * font_adjustment.font_scale)};
+ if (logfont->lfHeight && !new_height)
+ new_height = logfont->lfHeight > 0 ? 1 : -1;
+ logfont->lfHeight = new_height;
+ if (!font_adjustment.font_family_override.empty()) {
+ auto result = wcscpy_s(logfont->lfFaceName,
+ font_adjustment.font_family_override.c_str());
+ DCHECK_EQ(0, result) << "Font name " << font_adjustment.font_family_override
+ << " cannot be copied into LOGFONT structure.";
+ }
+}
+
+// static
+Font PlatformFontWin::HFontToFont(HFONT hfont) {
+ return Font(new PlatformFontWin(CreateHFontRef(hfont)));
+}
+
PlatformFontWin::PlatformFontWin(HFontRef* hfont_ref) : font_ref_(hfont_ref) {
}
diff --git a/chromium/ui/gfx/platform_font_win.h b/chromium/ui/gfx/platform_font_win.h
index 487d4677b43..96003b89fa4 100644
--- a/chromium/ui/gfx/platform_font_win.h
+++ b/chromium/ui/gfx/platform_font_win.h
@@ -5,6 +5,8 @@
#ifndef UI_GFX_PLATFORM_FONT_WIN_H_
#define UI_GFX_PLATFORM_FONT_WIN_H_
+#include <windows.h>
+
#include <string>
#include "base/compiler_specific.h"
@@ -14,15 +16,31 @@
#include "ui/gfx/gfx_export.h"
#include "ui/gfx/platform_font.h"
-#include <windows.h>
-
struct IDWriteFactory;
struct IDWriteFont;
namespace gfx {
+namespace internal {
+class SystemFonts;
+}
+
class GFX_EXPORT PlatformFontWin : public PlatformFont {
public:
+ enum class SystemFont : int {
+ kCaption = 0,
+ kSmallCaption,
+ kMenu,
+ kStatus,
+ kMessage
+ };
+
+ // Represents an optional override of system font and scale.
+ struct FontAdjustment {
+ base::string16 font_family_override;
+ double font_scale = 1.0;
+ };
+
PlatformFontWin();
explicit PlatformFontWin(NativeFont native_font);
PlatformFontWin(const std::string& font_name, int font_size);
@@ -39,14 +57,15 @@ class GFX_EXPORT PlatformFontWin : public PlatformFont {
// Callback that returns the minimum height that should be used for
// gfx::Fonts. Optional. If not specified, the minimum font size is 0.
typedef int (*GetMinimumFontSizeCallback)();
- static GetMinimumFontSizeCallback get_minimum_font_size_callback;
+ static void SetGetMinimumFontSizeCallback(
+ GetMinimumFontSizeCallback callback);
- // Callback that adjusts a LOGFONT to meet suitability requirements of the
- // embedding application. Optional. If not specified, no adjustments are
- // performed other than clamping to a minimum font height if
+ // Callback that adjusts a SystemFontInfo to meet suitability requirements
+ // of the embedding application. Optional. If not specified, no adjustments
+ // are performed other than clamping to a minimum font size if
// |get_minimum_font_size_callback| is specified.
- typedef void (*AdjustFontCallback)(LOGFONT* lf);
- static AdjustFontCallback adjust_font_callback;
+ typedef void (*AdjustFontCallback)(FontAdjustment* font_adjustment);
+ static void SetAdjustFontCallback(AdjustFontCallback callback);
// Returns the font name for the system locale. Some fonts, particularly
// East Asian fonts, have different names per locale. If the localized font
@@ -75,18 +94,31 @@ class GFX_EXPORT PlatformFontWin : public PlatformFont {
static bool IsDirectWriteEnabled();
- // Returns the GDI metrics for the font passed in.
- static void GetTextMetricsForFont(HDC hdc,
- HFONT font,
- TEXTMETRIC* text_metrics);
+ // Returns the specified Windows system font, suitable for drawing on screen
+ // elements.
+ static const Font& GetSystemFont(SystemFont system_font);
- // Returns the size of the font based on the font information passed in.
- static int GetFontSize(const LOGFONT& font_info);
+ // Apply a font adjustment to an existing font.
+ static Font AdjustExistingFont(NativeFont existing_font,
+ const FontAdjustment& font_adjustment);
private:
+ friend class internal::SystemFonts;
FRIEND_TEST_ALL_PREFIXES(RenderTextHarfBuzzTest, HarfBuzz_UniscribeFallback);
FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest, Metrics_SkiaVersusGDI);
FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest, DirectWriteFontSubstitution);
+ FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest, AdjustFontSize);
+ FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest,
+ AdjustFontSize_MinimumSizeSpecified);
+ FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest, AdjustLOGFONT_NoAdjustment);
+ FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest, AdjustLOGFONT_ChangeFace);
+ FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest, AdjustLOGFONT_ScaleDown);
+ FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest,
+ AdjustLOGFONT_ScaleDownWithRounding);
+ FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest,
+ AdjustLOGFONT_ScaleUpWithFaceChange);
+ FRIEND_TEST_ALL_PREFIXES(PlatformFontWinTest,
+ AdjustLOGFONT_ScaleUpWithRounding);
~PlatformFontWin() override;
@@ -168,6 +200,11 @@ class GFX_EXPORT PlatformFontWin : public PlatformFont {
void InitWithFontNameAndSize(const std::string& font_name,
int font_size);
+ // Returns the GDI metrics for the font passed in.
+ static void GetTextMetricsForFont(HDC hdc,
+ HFONT font,
+ TEXTMETRIC* text_metrics);
+
// Returns the base font ref. This should ONLY be invoked on the
// UI thread.
static HFontRef* GetBaseFontRef();
@@ -194,6 +231,22 @@ class GFX_EXPORT PlatformFontWin : public PlatformFont {
HFONT gdi_font,
const TEXTMETRIC& font_metrics);
+ // Adjust a font smaller or larger, subject to the global minimum size.
+ // |lf_height| is the height as reported by the LOGFONT structure, and may
+ // be positive or negative (but is typically negative, indicating character
+ // size rather than cell size). The absolute value of |lf_size| will be
+ // adjusted by |size_delta| and then returned with the original sign.
+ static int AdjustFontSize(int lf_height, int size_delta);
+
+ // Adjust a LOGFONT structure for optional size scale and face override.
+ static void AdjustLOGFONT(const FontAdjustment& font_adjustment,
+ LOGFONT* logfont);
+
+ // Takes control of a native font (e.g. from CreateFontIndirect()) and wraps
+ // it in a Font object to manage its lifespan. Note that |hfont| may not be
+ // valid after the call; use the returned Font object instead.
+ static Font HFontToFont(HFONT hfont);
+
// Creates a new PlatformFontWin with the specified HFontRef. Used when
// constructing a Font from a HFONT we don't want to copy.
explicit PlatformFontWin(HFontRef* hfont_ref);
@@ -207,6 +260,12 @@ class GFX_EXPORT PlatformFontWin : public PlatformFont {
// Pointer to the global IDWriteFactory interface.
static IDWriteFactory* direct_write_factory_;
+ // Font adjustment callback.
+ static AdjustFontCallback adjust_font_callback_;
+
+ // Minimum size callback.
+ static GetMinimumFontSizeCallback get_minimum_font_size_callback_;
+
DISALLOW_COPY_AND_ASSIGN(PlatformFontWin);
};
diff --git a/chromium/ui/gfx/platform_font_win_unittest.cc b/chromium/ui/gfx/platform_font_win_unittest.cc
index 854377974d5..53684536529 100644
--- a/chromium/ui/gfx/platform_font_win_unittest.cc
+++ b/chromium/ui/gfx/platform_font_win_unittest.cc
@@ -4,6 +4,10 @@
#include "ui/gfx/platform_font_win.h"
+#include <memory.h>
+#include <string.h>
+#include <windows.h>
+
#include "base/logging.h"
#include "base/memory/ref_counted.h"
#include "base/strings/string16.h"
@@ -17,6 +21,121 @@
namespace gfx {
+TEST(PlatformFontWinTest, AdjustFontSize) {
+ PlatformFontWin::SetGetMinimumFontSizeCallback(nullptr);
+ EXPECT_EQ(10, PlatformFontWin::AdjustFontSize(10, 0));
+ EXPECT_EQ(-10, PlatformFontWin::AdjustFontSize(-10, 0));
+ EXPECT_EQ(8, PlatformFontWin::AdjustFontSize(10, -2));
+ EXPECT_EQ(-8, PlatformFontWin::AdjustFontSize(-10, -2));
+ EXPECT_EQ(13, PlatformFontWin::AdjustFontSize(10, 3));
+ EXPECT_EQ(-13, PlatformFontWin::AdjustFontSize(-10, 3));
+ EXPECT_EQ(1, PlatformFontWin::AdjustFontSize(10, -9));
+ EXPECT_EQ(-1, PlatformFontWin::AdjustFontSize(-10, -9));
+ EXPECT_EQ(0, PlatformFontWin::AdjustFontSize(10, -12));
+ EXPECT_EQ(0, PlatformFontWin::AdjustFontSize(-10, -12));
+}
+
+TEST(PlatformFontWinTest, AdjustFontSize_MinimumSizeSpecified) {
+ PlatformFontWin::SetGetMinimumFontSizeCallback([] { return 1; });
+ EXPECT_EQ(10, PlatformFontWin::AdjustFontSize(10, 0));
+ EXPECT_EQ(-10, PlatformFontWin::AdjustFontSize(-10, 0));
+ EXPECT_EQ(8, PlatformFontWin::AdjustFontSize(10, -2));
+ EXPECT_EQ(-8, PlatformFontWin::AdjustFontSize(-10, -2));
+ EXPECT_EQ(13, PlatformFontWin::AdjustFontSize(10, 3));
+ EXPECT_EQ(-13, PlatformFontWin::AdjustFontSize(-10, 3));
+ EXPECT_EQ(1, PlatformFontWin::AdjustFontSize(10, -9));
+ EXPECT_EQ(-1, PlatformFontWin::AdjustFontSize(-10, -9));
+ EXPECT_EQ(1, PlatformFontWin::AdjustFontSize(10, -12));
+ EXPECT_EQ(-1, PlatformFontWin::AdjustFontSize(-10, -12));
+}
+
+namespace {
+
+LOGFONT CreateLOGFONT(const base::string16& name, LONG height) {
+ LOGFONT logfont{};
+ logfont.lfHeight = height;
+ auto result = wcscpy_s(logfont.lfFaceName, name.c_str());
+ DCHECK_EQ(0, result);
+ return logfont;
+}
+
+const base::string16 kSegoeUI(L"Segoe UI");
+const base::string16 kArial(L"Arial");
+
+} // namespace
+
+TEST(PlatformFontWinTest, AdjustLOGFONT_NoAdjustment) {
+ LOGFONT logfont = CreateLOGFONT(kSegoeUI, -12);
+ PlatformFontWin::FontAdjustment adjustment;
+ PlatformFontWin::AdjustLOGFONT(adjustment, &logfont);
+ EXPECT_EQ(-12, logfont.lfHeight);
+ EXPECT_EQ(kSegoeUI, logfont.lfFaceName);
+}
+
+TEST(PlatformFontWinTest, AdjustLOGFONT_ChangeFace) {
+ LOGFONT logfont = CreateLOGFONT(kSegoeUI, -12);
+ PlatformFontWin::FontAdjustment adjustment{kArial, 1.0};
+ PlatformFontWin::AdjustLOGFONT(adjustment, &logfont);
+ EXPECT_EQ(-12, logfont.lfHeight);
+ EXPECT_EQ(kArial, logfont.lfFaceName);
+}
+
+TEST(PlatformFontWinTest, AdjustLOGFONT_ScaleDown) {
+ LOGFONT logfont = CreateLOGFONT(kSegoeUI, -12);
+ PlatformFontWin::FontAdjustment adjustment{L"", 0.5};
+ PlatformFontWin::AdjustLOGFONT(adjustment, &logfont);
+ EXPECT_EQ(-6, logfont.lfHeight);
+ EXPECT_EQ(kSegoeUI, logfont.lfFaceName);
+
+ logfont = CreateLOGFONT(kSegoeUI, 12);
+ adjustment = {L"", 0.5};
+ PlatformFontWin::AdjustLOGFONT(adjustment, &logfont);
+ EXPECT_EQ(6, logfont.lfHeight);
+ EXPECT_EQ(kSegoeUI, logfont.lfFaceName);
+}
+
+TEST(PlatformFontWinTest, AdjustLOGFONT_ScaleDownWithRounding) {
+ LOGFONT logfont = CreateLOGFONT(kSegoeUI, -10);
+ PlatformFontWin::FontAdjustment adjustment{L"", 0.85};
+ PlatformFontWin::AdjustLOGFONT(adjustment, &logfont);
+ EXPECT_EQ(-9, logfont.lfHeight);
+ EXPECT_EQ(kSegoeUI, logfont.lfFaceName);
+
+ logfont = CreateLOGFONT(kSegoeUI, 10);
+ adjustment = {L"", 0.85};
+ PlatformFontWin::AdjustLOGFONT(adjustment, &logfont);
+ EXPECT_EQ(9, logfont.lfHeight);
+ EXPECT_EQ(kSegoeUI, logfont.lfFaceName);
+}
+
+TEST(PlatformFontWinTest, AdjustLOGFONT_ScaleUpWithFaceChange) {
+ LOGFONT logfont = CreateLOGFONT(kSegoeUI, -12);
+ PlatformFontWin::FontAdjustment adjustment{kArial, 1.5};
+ PlatformFontWin::AdjustLOGFONT(adjustment, &logfont);
+ EXPECT_EQ(-18, logfont.lfHeight);
+ EXPECT_EQ(kArial, logfont.lfFaceName);
+
+ logfont = CreateLOGFONT(kSegoeUI, 12);
+ adjustment = {kArial, 1.5};
+ PlatformFontWin::AdjustLOGFONT(adjustment, &logfont);
+ EXPECT_EQ(18, logfont.lfHeight);
+ EXPECT_EQ(kArial, logfont.lfFaceName);
+}
+
+TEST(PlatformFontWinTest, AdjustLOGFONT_ScaleUpWithRounding) {
+ LOGFONT logfont = CreateLOGFONT(kSegoeUI, -10);
+ PlatformFontWin::FontAdjustment adjustment{L"", 1.111};
+ PlatformFontWin::AdjustLOGFONT(adjustment, &logfont);
+ EXPECT_EQ(-11, logfont.lfHeight);
+ EXPECT_EQ(kSegoeUI, logfont.lfFaceName);
+
+ logfont = CreateLOGFONT(kSegoeUI, 10);
+ adjustment = {L"", 1.11};
+ PlatformFontWin::AdjustLOGFONT(adjustment, &logfont);
+ EXPECT_EQ(11, logfont.lfHeight);
+ EXPECT_EQ(kSegoeUI, logfont.lfFaceName);
+}
+
// Test whether font metrics retrieved by DirectWrite (skia) and GDI match as
// per assumptions mentioned below:-
// 1. Font size is the same
diff --git a/chromium/ui/gfx/render_text.cc b/chromium/ui/gfx/render_text.cc
index c29ed3e92bc..deada9af341 100644
--- a/chromium/ui/gfx/render_text.cc
+++ b/chromium/ui/gfx/render_text.cc
@@ -36,7 +36,6 @@
#include "ui/gfx/scoped_canvas.h"
#include "ui/gfx/skia_paint_util.h"
#include "ui/gfx/skia_util.h"
-#include "ui/gfx/switches.h"
#include "ui/gfx/text_elider.h"
#include "ui/gfx/text_utils.h"
#include "ui/gfx/utf16_indexing.h"
@@ -241,11 +240,9 @@ void SkiaTextRenderer::DrawPosText(const SkPoint* pos,
static_assert(sizeof(*pos) == 2 * sizeof(*run_buffer.pos), "");
memcpy(run_buffer.pos, pos, glyph_count * sizeof(*pos));
- // TODO(vmpstr): In order to OOP raster this, we would have to plumb PaintFont
- // here instead of |flags_|.
canvas_skia_->drawTextBlob(
base::MakeRefCounted<cc::PaintTextBlob>(builder.make(),
- std::vector<cc::PaintTypeface>{}),
+ std::vector<sk_sp<SkTypeface>>{}),
0, 0, flags_);
}
@@ -356,14 +353,6 @@ std::unique_ptr<RenderText> RenderText::CreateFor(Typesetter typesetter) {
if (typesetter == Typesetter::NATIVE)
return std::make_unique<RenderTextMac>();
- if (typesetter == Typesetter::HARFBUZZ)
- return CreateHarfBuzzInstance();
-
- static const bool use_native =
- !base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableHarfBuzzRenderText);
- if (use_native)
- return std::make_unique<RenderTextMac>();
#endif // defined(OS_MACOSX)
return CreateHarfBuzzInstance();
}
diff --git a/chromium/ui/gfx/render_text_harfbuzz.cc b/chromium/ui/gfx/render_text_harfbuzz.cc
index d08db4ca9da..c8a9af201d3 100644
--- a/chromium/ui/gfx/render_text_harfbuzz.cc
+++ b/chromium/ui/gfx/render_text_harfbuzz.cc
@@ -1595,10 +1595,9 @@ void RenderTextHarfBuzz::DrawVisualText(internal::SkiaTextRenderer* renderer) {
SkIntToScalar(origin.x()) + offset_x,
SkIntToScalar(origin.y() + run.font_params.baseline_offset));
}
- for (BreakList<SkColor>::const_iterator it =
- colors().GetBreak(segment.char_range.start());
+ for (auto it = colors().GetBreak(segment.char_range.start());
it != colors().breaks().end() &&
- it->first < segment.char_range.end();
+ it->first < segment.char_range.end();
++it) {
const Range intersection =
colors().GetRange(it).Intersect(segment.char_range);
diff --git a/chromium/ui/gfx/sequential_id_generator.cc b/chromium/ui/gfx/sequential_id_generator.cc
index 3d8b246e233..ad5ab8c3dd4 100644
--- a/chromium/ui/gfx/sequential_id_generator.cc
+++ b/chromium/ui/gfx/sequential_id_generator.cc
@@ -11,7 +11,7 @@ namespace {
// Removes |key| from |first|, and |first[key]| from |second|.
template <typename T>
void Remove(uint32_t key, T* first, T* second) {
- typename T::iterator iter = first->find(key);
+ auto iter = first->find(key);
if (iter == first->end())
return;
@@ -34,7 +34,7 @@ SequentialIDGenerator::~SequentialIDGenerator() {
}
uint32_t SequentialIDGenerator::GetGeneratedID(uint32_t number) {
- IDMap::iterator find = number_to_id_.find(number);
+ auto find = number_to_id_.find(number);
if (find != number_to_id_.end())
return find->second;
diff --git a/chromium/ui/gfx/skia_paint_util.cc b/chromium/ui/gfx/skia_paint_util.cc
index 3ca09ee21c8..40c36a49e2d 100644
--- a/chromium/ui/gfx/skia_paint_util.cc
+++ b/chromium/ui/gfx/skia_paint_util.cc
@@ -10,6 +10,7 @@
#include "third_party/skia/include/effects/SkGradientShader.h"
#include "third_party/skia/include/effects/SkLayerDrawLooper.h"
#include "ui/gfx/image/image_skia_rep.h"
+#include "ui/gfx/switches.h"
namespace gfx {
@@ -39,8 +40,22 @@ sk_sp<cc::PaintShader> CreateImageRepShaderForScale(
shader_scale.setScaleX(local_matrix.getScaleX() / scale);
shader_scale.setScaleY(local_matrix.getScaleY() / scale);
- return cc::PaintShader::MakeImage(image_rep.paint_image(), tile_mode_x,
- tile_mode_y, &shader_scale);
+ // TODO(malaykeshav): The check for has_paint_image was only added here to
+ // prevent generating a paint record in tests. Tests need an instance of
+ // base::DiscardableMemoryAllocator to generate the PaintRecord. However most
+ // test suites dont have this set. Ensure that the check is removed before
+ // enabling the |kUsePaintRecordForImageSkia| feature by default.
+ // https://crbug.com/891469
+ if (base::FeatureList::IsEnabled(features::kUsePaintRecordForImageSkia) &&
+ !image_rep.has_paint_image()) {
+ return cc::PaintShader::MakePaintRecord(
+ image_rep.GetPaintRecord(),
+ SkRect::MakeIWH(image_rep.pixel_width(), image_rep.pixel_height()),
+ tile_mode_x, tile_mode_y, &shader_scale);
+ } else {
+ return cc::PaintShader::MakeImage(image_rep.paint_image(), tile_mode_x,
+ tile_mode_y, &shader_scale);
+ }
}
sk_sp<cc::PaintShader> CreateGradientShader(int start_point,
diff --git a/chromium/ui/gfx/skia_util.h b/chromium/ui/gfx/skia_util.h
index de6ed6d2085..beea3bd99b1 100644
--- a/chromium/ui/gfx/skia_util.h
+++ b/chromium/ui/gfx/skia_util.h
@@ -13,7 +13,7 @@
#include "third_party/skia/include/core/SkRect.h"
#include "ui/gfx/geometry/quad_f.h"
#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/gfx_export.h"
+#include "ui/gfx/geometry_skia_export.h"
#if BUILDFLAG(ENABLE_VULKAN)
#include "third_party/skia/include/core/SkImageInfo.h"
@@ -32,45 +32,47 @@ class RectF;
class Transform;
// Convert between Skia and gfx types.
-GFX_EXPORT SkPoint PointToSkPoint(const Point& point);
-GFX_EXPORT SkIPoint PointToSkIPoint(const Point& point);
-GFX_EXPORT SkPoint PointFToSkPoint(const PointF& point);
-GFX_EXPORT SkRect RectToSkRect(const Rect& rect);
-GFX_EXPORT SkIRect RectToSkIRect(const Rect& rect);
-GFX_EXPORT Rect SkIRectToRect(const SkIRect& rect);
-GFX_EXPORT SkRect RectFToSkRect(const RectF& rect);
-GFX_EXPORT RectF SkRectToRectF(const SkRect& rect);
-GFX_EXPORT SkSize SizeFToSkSize(const SizeF& size);
-GFX_EXPORT SkISize SizeToSkISize(const Size& size);
-GFX_EXPORT SizeF SkSizeToSizeF(const SkSize& size);
-GFX_EXPORT Size SkISizeToSize(const SkISize& size);
-
-GFX_EXPORT void QuadFToSkPoints(const gfx::QuadF& quad, SkPoint points[4]);
-
-GFX_EXPORT void TransformToFlattenedSkMatrix(const gfx::Transform& transform,
- SkMatrix* flattened);
+GEOMETRY_SKIA_EXPORT SkPoint PointToSkPoint(const Point& point);
+GEOMETRY_SKIA_EXPORT SkIPoint PointToSkIPoint(const Point& point);
+GEOMETRY_SKIA_EXPORT SkPoint PointFToSkPoint(const PointF& point);
+GEOMETRY_SKIA_EXPORT SkRect RectToSkRect(const Rect& rect);
+GEOMETRY_SKIA_EXPORT SkIRect RectToSkIRect(const Rect& rect);
+GEOMETRY_SKIA_EXPORT Rect SkIRectToRect(const SkIRect& rect);
+GEOMETRY_SKIA_EXPORT SkRect RectFToSkRect(const RectF& rect);
+GEOMETRY_SKIA_EXPORT RectF SkRectToRectF(const SkRect& rect);
+GEOMETRY_SKIA_EXPORT SkSize SizeFToSkSize(const SizeF& size);
+GEOMETRY_SKIA_EXPORT SkISize SizeToSkISize(const Size& size);
+GEOMETRY_SKIA_EXPORT SizeF SkSizeToSizeF(const SkSize& size);
+GEOMETRY_SKIA_EXPORT Size SkISizeToSize(const SkISize& size);
+
+GEOMETRY_SKIA_EXPORT void QuadFToSkPoints(const gfx::QuadF& quad,
+ SkPoint points[4]);
+
+GEOMETRY_SKIA_EXPORT void TransformToFlattenedSkMatrix(
+ const gfx::Transform& transform,
+ SkMatrix* flattened);
// Returns true if the two bitmaps contain the same pixels.
-GFX_EXPORT bool BitmapsAreEqual(const SkBitmap& bitmap1,
- const SkBitmap& bitmap2);
+GEOMETRY_SKIA_EXPORT bool BitmapsAreEqual(const SkBitmap& bitmap1,
+ const SkBitmap& bitmap2);
// Converts Skia ARGB format pixels in |skia| to RGBA.
-GFX_EXPORT void ConvertSkiaToRGBA(const unsigned char* skia,
- int pixel_width,
- unsigned char* rgba);
+GEOMETRY_SKIA_EXPORT void ConvertSkiaToRGBA(const unsigned char* skia,
+ int pixel_width,
+ unsigned char* rgba);
// Converts a Skia floating-point value to an int appropriate for hb_position_t.
-GFX_EXPORT int SkiaScalarToHarfBuzzUnits(SkScalar value);
+GEOMETRY_SKIA_EXPORT int SkiaScalarToHarfBuzzUnits(SkScalar value);
// Converts an hb_position_t to a Skia floating-point value.
-GFX_EXPORT SkScalar HarfBuzzUnitsToSkiaScalar(int value);
+GEOMETRY_SKIA_EXPORT SkScalar HarfBuzzUnitsToSkiaScalar(int value);
// Converts an hb_position_t to a float.
-GFX_EXPORT float HarfBuzzUnitsToFloat(int value);
+GEOMETRY_SKIA_EXPORT float HarfBuzzUnitsToFloat(int value);
#if BUILDFLAG(ENABLE_VULKAN)
// Converts a Skia color type to a compitable VkFormat
-GFX_EXPORT VkFormat SkColorTypeToVkFormat(SkColorType color_type);
+GEOMETRY_SKIA_EXPORT VkFormat SkColorTypeToVkFormat(SkColorType color_type);
#endif
} // namespace gfx
diff --git a/chromium/ui/gfx/skia_vector_animation.cc b/chromium/ui/gfx/skia_vector_animation.cc
new file mode 100644
index 00000000000..8e16dc9dcc6
--- /dev/null
+++ b/chromium/ui/gfx/skia_vector_animation.cc
@@ -0,0 +1,261 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/skia_vector_animation.h"
+
+#include "base/trace_event/trace_event.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkImage.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/geometry/size_conversions.h"
+#include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/skia_util.h"
+#include "ui/gfx/skia_vector_animation_observer.h"
+#include "ui/gfx/skottie_wrapper.h"
+
+namespace gfx {
+
+SkiaVectorAnimation::TimerControl::TimerControl(
+ const base::TimeDelta& offset,
+ const base::TimeDelta& cycle_duration,
+ const base::TimeDelta& total_duration,
+ const base::TimeTicks& start_timestamp,
+ bool should_reverse)
+ : start_offset_(offset),
+ end_offset_((offset + cycle_duration)),
+ cycle_duration_(end_offset_ - start_offset_),
+ progress_per_millisecond_(1.0 / total_duration.InMillisecondsF()),
+ previous_tick_(start_timestamp),
+ progress_(base::TimeDelta::FromMilliseconds(0)),
+ current_cycle_progress_(start_offset_),
+ should_reverse_(should_reverse) {}
+
+void SkiaVectorAnimation::TimerControl::Step(const base::TimeTicks& timestamp) {
+ progress_ += timestamp - previous_tick_;
+ previous_tick_ = timestamp;
+
+ base::TimeDelta completed_cycles_duration =
+ completed_cycles_ * cycle_duration_;
+ if (progress_ >= completed_cycles_duration + cycle_duration_) {
+ completed_cycles_++;
+ completed_cycles_duration += cycle_duration_;
+ }
+
+ current_cycle_progress_ =
+ start_offset_ + progress_ - completed_cycles_duration;
+ if (should_reverse_ && completed_cycles_ % 2) {
+ current_cycle_progress_ =
+ end_offset_ - (current_cycle_progress_ - start_offset_);
+ }
+}
+
+void SkiaVectorAnimation::TimerControl::Resume(
+ const base::TimeTicks& timestamp) {
+ previous_tick_ = timestamp;
+}
+
+double SkiaVectorAnimation::TimerControl::GetNormalizedCurrentCycleProgress()
+ const {
+ return current_cycle_progress_.InMillisecondsF() * progress_per_millisecond_;
+}
+
+double SkiaVectorAnimation::TimerControl::GetNormalizedStartOffset() const {
+ return start_offset_.InMillisecondsF() * progress_per_millisecond_;
+}
+
+double SkiaVectorAnimation::TimerControl::GetNormalizedEndOffset() const {
+ return end_offset_.InMillisecondsF() * progress_per_millisecond_;
+}
+
+SkiaVectorAnimation::SkiaVectorAnimation(scoped_refptr<SkottieWrapper> skottie)
+ : skottie_(skottie) {}
+
+SkiaVectorAnimation::~SkiaVectorAnimation() {}
+
+void SkiaVectorAnimation::SetAnimationObserver(
+ SkiaVectorAnimationObserver* observer) {
+ DCHECK(!observer_ || !observer);
+ observer_ = observer;
+}
+
+base::TimeDelta SkiaVectorAnimation::GetAnimationDuration() const {
+ return base::TimeDelta::FromMilliseconds(
+ std::floor(SkScalarToFloat(skottie_->duration()) * 1000.f));
+}
+
+gfx::Size SkiaVectorAnimation::GetOriginalSize() const {
+#if DCHECK_IS_ON()
+ // The size should have no fractional component.
+ gfx::SizeF float_size = gfx::SkSizeToSizeF(skottie_->size());
+ gfx::Size rounded_size = gfx::ToRoundedSize(float_size);
+
+ float height_diff = std::abs(float_size.height() - rounded_size.height());
+ float width_diff = std::abs(float_size.width() - rounded_size.width());
+
+ DCHECK_LE(height_diff, std::numeric_limits<float>::epsilon());
+ DCHECK_LE(width_diff, std::numeric_limits<float>::epsilon());
+#endif
+ return gfx::ToRoundedSize(gfx::SkSizeToSizeF(skottie_->size()));
+}
+
+void SkiaVectorAnimation::Start(Style style) {
+ DCHECK_NE(state_, PlayState::kPaused);
+ DCHECK_NE(state_, PlayState::kPlaying);
+ StartSubsection(base::TimeDelta(), GetAnimationDuration(), style);
+}
+
+void SkiaVectorAnimation::StartSubsection(base::TimeDelta start_offset,
+ base::TimeDelta duration,
+ Style style) {
+ DCHECK(state_ == PlayState::kStopped || state_ == PlayState::kEnded);
+ DCHECK_LE(start_offset + duration, GetAnimationDuration());
+
+ style_ = style;
+
+ // Reset the |timer_control_| object for a new animation play.
+ timer_control_.reset(nullptr);
+
+ // Schedule a play for the animation and store the necessary information
+ // needed to start playing.
+ state_ = PlayState::kSchedulePlay;
+ scheduled_start_offset_ = start_offset;
+ scheduled_duration_ = duration;
+}
+
+void SkiaVectorAnimation::Pause() {
+ DCHECK(state_ == PlayState::kPlaying || state_ == PlayState::kSchedulePlay);
+ state_ = PlayState::kPaused;
+}
+
+void SkiaVectorAnimation::ResumePlaying() {
+ DCHECK(state_ == PlayState::kPaused);
+ state_ = PlayState::kScheduleResume;
+}
+
+void SkiaVectorAnimation::Stop() {
+ state_ = PlayState::kStopped;
+ timer_control_.reset(nullptr);
+}
+
+float SkiaVectorAnimation::GetCurrentProgress() const {
+ switch (state_) {
+ case PlayState::kStopped:
+ return 0;
+ case PlayState::kEnded:
+ DCHECK(timer_control_);
+ return timer_control_->GetNormalizedEndOffset();
+ case PlayState::kPaused:
+ if (timer_control_) {
+ return timer_control_->GetNormalizedCurrentCycleProgress();
+ } else {
+ // It may be that the timer hasn't been initialized which may happen if
+ // the animation was paused while it was in |kScheculePlay| state.
+ return scheduled_start_offset_.InMillisecondsF() / skottie_->duration();
+ }
+ case PlayState::kSchedulePlay:
+ case PlayState::kPlaying:
+ case PlayState::kScheduleResume:
+ // The timer control needs to be initialized before making this call. It
+ // may not have been initialized if OnAnimationStep has not been called
+ // yet
+ DCHECK(timer_control_);
+ return timer_control_->GetNormalizedCurrentCycleProgress();
+ }
+}
+
+void SkiaVectorAnimation::Paint(gfx::Canvas* canvas,
+ const base::TimeTicks& timestamp,
+ const gfx::Size& size) {
+ switch (state_) {
+ case PlayState::kStopped:
+ return;
+ case PlayState::kSchedulePlay:
+ InitTimer(timestamp);
+ state_ = PlayState::kPlaying;
+ if (observer_)
+ observer_->AnimationWillStartPlaying(this);
+ break;
+ case PlayState::kPlaying:
+ UpdateState(timestamp);
+ break;
+ case PlayState::kPaused:
+ break;
+ case PlayState::kScheduleResume:
+ state_ = PlayState::kPlaying;
+ if (timer_control_) {
+ timer_control_->Resume(timestamp);
+ } else {
+ // The animation may have been paused after a play was scheduled but
+ // before it started playing.
+ InitTimer(timestamp);
+ }
+ if (observer_)
+ observer_->AnimationResuming(this);
+ break;
+ case PlayState::kEnded:
+ break;
+ }
+ PaintFrame(canvas, GetCurrentProgress(), size);
+}
+
+void SkiaVectorAnimation::PaintFrame(gfx::Canvas* canvas,
+ float t,
+ const gfx::Size& size) {
+ TRACE_EVENT0("ui", "SkiaVectorAnimation Paint");
+ DCHECK_GE(t, 0.f);
+ DCHECK_LE(t, 1.f);
+
+ float scale = canvas->UndoDeviceScaleFactor();
+ gfx::Size pixel_size = gfx::ScaleToRoundedSize(size, scale);
+
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(std::round(pixel_size.width()),
+ std::round(pixel_size.height()), false);
+ SkCanvas skcanvas(bitmap);
+ skcanvas.clear(SK_ColorTRANSPARENT);
+
+ skottie_->Draw(&skcanvas, t, pixel_size);
+
+ canvas->DrawImageInt(gfx::ImageSkia::CreateFrom1xBitmap(bitmap), 0, 0);
+}
+
+void SkiaVectorAnimation::InitTimer(const base::TimeTicks& timestamp) {
+ DCHECK(!timer_control_);
+ timer_control_ = std::make_unique<TimerControl>(
+ scheduled_start_offset_, scheduled_duration_, GetAnimationDuration(),
+ timestamp, style_ == Style::kThrobbing);
+}
+
+void SkiaVectorAnimation::UpdateState(const base::TimeTicks& timestamp) {
+ DCHECK(timer_control_);
+ int cycles = timer_control_->completed_cycles();
+ timer_control_->Step(timestamp);
+
+ if (cycles == timer_control_->completed_cycles())
+ return;
+
+ bool inform_observer = true;
+ switch (style_) {
+ case Style::kLoop:
+ break;
+ case Style::kThrobbing:
+ // For a throbbing animation, the animation cycle ends when the timer
+ // goes from 0 to 1 and then back to 0. So the number of timer cycles
+ // must be even at the end of one throbbing animation cycle.
+ if (timer_control_->completed_cycles() % 2 != 0)
+ inform_observer = false;
+ break;
+ case Style::kLinear:
+ state_ = PlayState::kEnded;
+ break;
+ }
+
+ // Inform observer if the cycle has ended.
+ if (observer_ && inform_observer) {
+ observer_->AnimationCycleEnded(this);
+ }
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/skia_vector_animation.h b/chromium/ui/gfx/skia_vector_animation.h
new file mode 100644
index 00000000000..14081bfd3e0
--- /dev/null
+++ b/chromium/ui/gfx/skia_vector_animation.h
@@ -0,0 +1,241 @@
+// 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_GFX_SKIA_VECTOR_ANIMATION_H_
+#define UI_GFX_SKIA_VECTOR_ANIMATION_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted_memory.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/time/time.h"
+#include "third_party/skia/include/core/SkStream.h"
+#include "third_party/skia/modules/skottie/include/Skottie.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+class Canvas;
+class SkiaVectorAnimationTest;
+class SkiaVectorAnimationObserver;
+class SkottieWrapper;
+
+// This class is a wrapper over the Skia object for lottie vector graphic
+// animations. It has its own timeline manager for the animation controls. The
+// framerate of the animation and the animation ticks are controlled externally
+// and hence the consumer must manage the timer and call paint at the desired
+// frame per second.
+// This helps keep multiple animations be synchronized by having a common
+// external tick clock.
+// In general you want to use the view framework integrated class that we have
+// for SkiaVectorAnimation instead of this class.
+//
+// Usage example:
+// 1. Rendering a single frame on the canvas:
+// SkiaVectorAnimation animation_ = SkiaVectorAnimation(data);
+// animation_.Paint(canvas, t);
+//
+// 2. Playing the animation and rendering each frame:
+// void SampleClient::Init() {
+// SkiaVectorAnimation animation_ = SkiaVectorAnimation(data);
+// animation_.Start(SkiaVectorAnimation::Style::LINEAR);
+// }
+//
+// // overrides cc::CompositorAnimationObserver
+// void SampleClient::OnAnimationStep(TimeTicks* timestamp) {
+// timestamp_ = timestamp;
+// SchedulePaint();
+// }
+//
+// void SampleClient::OnPaint(Canvas* canvas) {
+// animation_.Paint(canvas, timestamp_);
+// }
+//
+// 2. If you only want to play a subsection of the animation:
+// void SampleClient::Init() {
+// // This will seek to the 1st second of the animation and from there
+// // play it for 5 seconds.
+// SkiaVectorAnimation animation_ = SkiaVectorAnimation(data);
+// animation_.Start(TimeDelta::FromSeconds(1),
+// TimeDelta::FromSeconds(5));
+// }
+//
+// // overrides cc::CompositorAnimationObserver
+// void SampleClient::OnAnimationStep(TimeTicks*) {
+// timestamp_ = timestamp;
+// SchedulePaint();
+// }
+//
+// void SampleClient::OnPaint(Canvas* canvas) {
+// animation_.Paint(canvas, timestamp_, gfx::Size(10, 10));
+// }
+//
+class GFX_EXPORT SkiaVectorAnimation {
+ public:
+ enum class Style {
+ kLinear = 0, // The animation plays from one time instant to another.
+ kThrobbing, // The animation plays from one time instant to another and
+ // then back. The animation plays in loop until stopped.
+ kLoop // Same as LINEAR, except the animation repeats after it ends.
+ };
+
+ explicit SkiaVectorAnimation(scoped_refptr<SkottieWrapper> skottie);
+ ~SkiaVectorAnimation();
+
+ void SetAnimationObserver(SkiaVectorAnimationObserver* Observer);
+
+ // Animation properties ------------------------------------------------------
+ // Returns the total duration of the animation as reported by |animation_|.
+ base::TimeDelta GetAnimationDuration() const;
+
+ // Returns the size of the vector graphic as reported by |animation_|. This is
+ // constant for a given |animation_|.
+ gfx::Size GetOriginalSize() const;
+
+ // Animation controls --------------------------------------------------------
+ // This is an asynchronous call that would start playing the animation on the
+ // next animation step. On a successful start the |observer_| would be
+ // notified. Use this if you want to play the entire animation.
+ void Start(Style style = Style::kLoop);
+
+ // This is an asynchronous call that would start playing the animation on the
+ // next animation step. On a successful start the |observer_| would be
+ // notified.
+ // The animation will be scheduled to play from the |start_offset| to
+ // |start_offset| + |duration|. The values will be clamped so as to not go out
+ // of bounds.
+ void StartSubsection(base::TimeDelta start_offset,
+ base::TimeDelta duration,
+ Style style = Style::kLoop);
+
+ // Pauses the animation.
+ void Pause();
+
+ // This is an asynchronous call that would resume playing a paused animation
+ // on the next animation step.
+ void ResumePlaying();
+
+ // Resets the animation to the first frame and stops.
+ void Stop();
+
+ // Returns the current normalized [0..1] value at which the animation frame
+ // is.
+ // 0 -> first frame and 1 -> last frame.
+ float GetCurrentProgress() const;
+
+ // Paint operations ----------------------------------------------------------
+ // Paints the frame of the animation for the given |timestamp| at the given
+ // |size|.
+ void Paint(gfx::Canvas* canvas,
+ const base::TimeTicks& timestamp,
+ const gfx::Size& size);
+
+ // Paints the frame of the animation for the normalized time instance |t|. Use
+ // this for special cases when you want to manually manage which frame to
+ // paint.
+ void PaintFrame(gfx::Canvas* canvas, float t, const gfx::Size& size);
+
+ // Returns the skottie object that contins the animation data.
+ scoped_refptr<SkottieWrapper> skottie() const { return skottie_; }
+
+ private:
+ friend class SkiaVectorAnimationTest;
+
+ enum class PlayState {
+ kStopped = 0, // Animation is stopped.
+ kSchedulePlay, // Animation will start playing on the next animatin step.
+ kPlaying, // Animation is playing.
+ kPaused, // Animation is paused.
+ kScheduleResume, // Animation will resume playing on the next animation
+ // step
+ kEnded // Animation has ended.
+ };
+
+ // Class to manage the timeline when playing the animation. Manages the
+ // normalized progress [0..1] between the given start and end offset. If the
+ // reverse flag is set, the progress runs in reverse.
+ class GFX_EXPORT TimerControl {
+ public:
+ TimerControl(const base::TimeDelta& offset,
+ const base::TimeDelta& cycle_duration,
+ const base::TimeDelta& total_duration,
+ const base::TimeTicks& start_timestamp,
+ bool should_reverse);
+ ~TimerControl() = default;
+
+ // Update timeline progress based on the new timetick |timestamp|.
+ void Step(const base::TimeTicks& timestamp);
+
+ // Resumes the timer.
+ void Resume(const base::TimeTicks& timestamp);
+
+ double GetNormalizedCurrentCycleProgress() const;
+ double GetNormalizedStartOffset() const;
+ double GetNormalizedEndOffset() const;
+ int completed_cycles() const { return completed_cycles_; }
+
+ private:
+ friend class SkiaVectorAnimationTest;
+
+ // Time duration from 0 which marks the beginning of a cycle.
+ const base::TimeDelta start_offset_;
+
+ // Time duration from 0 which marks the end of a cycle.
+ const base::TimeDelta end_offset_;
+
+ // Time duration for one cycle. This is essentially a cache of the
+ // difference between |end_offset_| - |start_offset_|.
+ const base::TimeDelta cycle_duration_;
+
+ // Normalized animation progress delta per millisecond, that is, the
+ // normalized progress in per millisecond of time duration.
+ const double progress_per_millisecond_;
+
+ // The timetick at which |progress_| was updated last.
+ base::TimeTicks previous_tick_;
+
+ // The progress of the timer. This is a monotonically increasing value.
+ base::TimeDelta progress_;
+
+ // This is the progress of the timer in the current cycle.
+ base::TimeDelta current_cycle_progress_;
+
+ // If true, the progress will go into reverse after each cycle. This is used
+ // for throbbing animations.
+ bool should_reverse_ = false;
+
+ // The number of times each |cycle_duration_| is covered by the timer.
+ int completed_cycles_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(TimerControl);
+ };
+
+ void InitTimer(const base::TimeTicks& timestamp);
+ void UpdateState(const base::TimeTicks& timestamp);
+
+ // Manages the timeline for the current playing animation.
+ std::unique_ptr<TimerControl> timer_control_;
+
+ // The style of animation to play.
+ Style style_ = Style::kLoop;
+
+ // The current state of animation.
+ PlayState state_ = PlayState::kStopped;
+
+ // The below values of scheduled_* are set when we have scheduled a play.
+ // These will be used to initialize |timer_control_|.
+ base::TimeDelta scheduled_start_offset_;
+ base::TimeDelta scheduled_duration_;
+
+ SkiaVectorAnimationObserver* observer_ = nullptr;
+
+ scoped_refptr<SkottieWrapper> skottie_;
+
+ DISALLOW_COPY_AND_ASSIGN(SkiaVectorAnimation);
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_SKIA_VECTOR_ANIMATION_H_
diff --git a/chromium/ui/gfx/skia_vector_animation_observer.h b/chromium/ui/gfx/skia_vector_animation_observer.h
new file mode 100644
index 00000000000..1e6e479a29d
--- /dev/null
+++ b/chromium/ui/gfx/skia_vector_animation_observer.h
@@ -0,0 +1,33 @@
+// 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_GFX_SKIA_VECTOR_ANIMATION_OBSERVER_H_
+#define UI_GFX_SKIA_VECTOR_ANIMATION_OBSERVER_H_
+
+#include "ui/gfx/gfx_export.h"
+
+namespace gfx {
+class SkiaVectorAnimation;
+
+class GFX_EXPORT SkiaVectorAnimationObserver {
+ public:
+ // Called when the animation started playing.
+ virtual void AnimationWillStartPlaying(const SkiaVectorAnimation* animation) {
+ }
+
+ // Called when one animation cycle has completed. This happens when a linear
+ // animation has reached its end, or a loop/throbbing animation has finished
+ // a cycle.
+ virtual void AnimationCycleEnded(const SkiaVectorAnimation* animation) {}
+
+ // Called when the animation has successfully resumed.
+ virtual void AnimationResuming(const SkiaVectorAnimation* animation) {}
+
+ protected:
+ virtual ~SkiaVectorAnimationObserver() = default;
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_SKIA_VECTOR_ANIMATION_OBSERVER_H_
diff --git a/chromium/ui/gfx/skia_vector_animation_unittest.cc b/chromium/ui/gfx/skia_vector_animation_unittest.cc
new file mode 100644
index 00000000000..e7394e2ae7d
--- /dev/null
+++ b/chromium/ui/gfx/skia_vector_animation_unittest.cc
@@ -0,0 +1,835 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/skia_vector_animation.h"
+
+#include <string>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted_memory.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/test/simple_test_tick_clock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkStream.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/skia_vector_animation_observer.h"
+#include "ui/gfx/skottie_wrapper.h"
+
+namespace gfx {
+namespace {
+
+// A skottie animation with solid green color for the first 2.5 seconds and then
+// a solid blue color for the next 2.5 seconds.
+constexpr char kData[] =
+ "{"
+ " \"v\" : \"4.12.0\","
+ " \"fr\": 30,"
+ " \"w\" : 400,"
+ " \"h\" : 200,"
+ " \"ip\": 0,"
+ " \"op\": 150,"
+ " \"assets\": [],"
+
+ " \"layers\": ["
+ " {"
+ " \"ty\": 1,"
+ " \"sw\": 400,"
+ " \"sh\": 200,"
+ " \"sc\": \"#00ff00\","
+ " \"ip\": 0,"
+ " \"op\": 75"
+ " },"
+ " {"
+ " \"ty\": 1,"
+ " \"sw\": 400,"
+ " \"sh\": 200,"
+ " \"sc\": \"#0000ff\","
+ " \"ip\": 76,"
+ " \"op\": 150"
+ " }"
+ " ]"
+ "}";
+constexpr float kAnimationWidth = 400.f;
+constexpr float kAnimationHeight = 200.f;
+constexpr float kAnimationDuration = 5.f;
+
+class TestAnimationObserver : public SkiaVectorAnimationObserver {
+ public:
+ TestAnimationObserver() = default;
+
+ void AnimationWillStartPlaying(
+ const SkiaVectorAnimation* animation) override {
+ animation_will_start_playing_ = true;
+ }
+
+ void AnimationCycleEnded(const SkiaVectorAnimation* animation) override {
+ animation_cycle_ended_ = true;
+ }
+
+ void AnimationResuming(const SkiaVectorAnimation* animation) override {
+ animation_resuming_ = true;
+ }
+
+ void Reset() {
+ animation_cycle_ended_ = false;
+ animation_will_start_playing_ = false;
+ animation_resuming_ = false;
+ }
+
+ bool animation_cycle_ended() const { return animation_cycle_ended_; }
+ bool animation_will_start_playing() const {
+ return animation_will_start_playing_;
+ }
+ bool animation_resuming() const { return animation_resuming_; }
+
+ private:
+ bool animation_cycle_ended_ = false;
+ bool animation_will_start_playing_ = false;
+ bool animation_resuming_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(TestAnimationObserver);
+};
+
+} // namespace
+
+class SkiaVectorAnimationTest : public testing::Test {
+ public:
+ SkiaVectorAnimationTest() = default;
+ ~SkiaVectorAnimationTest() override {}
+
+ void SetUp() override {
+ canvas_.reset(new gfx::Canvas(gfx::Size(kAnimationWidth, kAnimationHeight),
+ 1.f, false));
+ skottie_ = base::MakeRefCounted<SkottieWrapper>(
+ std::make_unique<SkMemoryStream>(kData, std::strlen(kData)));
+ animation_ = std::make_unique<SkiaVectorAnimation>(skottie_);
+ }
+
+ void TearDown() override { animation_.reset(nullptr); }
+
+ Canvas* canvas() { return canvas_.get(); }
+
+ SkiaVectorAnimation::Style GetStyle() const { return animation_->style_; }
+
+ SkiaVectorAnimation::PlayState GetState() const { return animation_->state_; }
+
+ bool IsStopped() const {
+ return GetState() == SkiaVectorAnimation::PlayState::kStopped;
+ }
+
+ bool IsScheduledToPlay() const {
+ return GetState() == SkiaVectorAnimation::PlayState::kSchedulePlay;
+ }
+
+ bool IsPlaying() const {
+ return GetState() == SkiaVectorAnimation::PlayState::kPlaying;
+ }
+
+ bool IsScheduledToResume() const {
+ return GetState() == SkiaVectorAnimation::PlayState::kScheduleResume;
+ }
+
+ bool HasAnimationEnded() const {
+ return GetState() == SkiaVectorAnimation::PlayState::kEnded;
+ }
+
+ bool IsPaused() const {
+ return GetState() == SkiaVectorAnimation::PlayState::kPaused;
+ }
+
+ const SkiaVectorAnimation::TimerControl* GetTimerControl() const {
+ return animation_->timer_control_.get();
+ }
+
+ const base::TickClock* test_clock() const { return &test_clock_; }
+
+ void AdvanceClock(int64_t ms) {
+ test_clock_.Advance(base::TimeDelta::FromMilliseconds(ms));
+ }
+
+ base::TimeDelta TimeDeltaSince(const base::TimeTicks& ticks) const {
+ return test_clock_.NowTicks() - ticks;
+ }
+
+ const base::TimeTicks NowTicks() const { return test_clock_.NowTicks(); }
+
+ double GetTimerStartOffset() const {
+ return animation_->timer_control_->GetNormalizedStartOffset();
+ }
+
+ double GetTimerEndOffset() const {
+ return animation_->timer_control_->GetNormalizedEndOffset();
+ }
+
+ const base::TimeTicks& GetTimerPreviousTick() const {
+ return animation_->timer_control_->previous_tick_;
+ }
+
+ double GetTimerProgressPerMs() const {
+ return animation_->timer_control_->progress_per_millisecond_;
+ }
+
+ int GetTimerCycles() const {
+ return animation_->timer_control_->completed_cycles();
+ }
+
+ void IsAllSameColor(SkColor color, const SkBitmap& bitmap) const {
+ if (bitmap.colorType() == kBGRA_8888_SkColorType) {
+ const SkColor* pixels = reinterpret_cast<SkColor*>(bitmap.getPixels());
+ const int num_pixels = bitmap.width() * bitmap.height();
+ for (int i = 0; i < num_pixels; i++)
+ EXPECT_EQ(pixels[i], color);
+ } else {
+ for (int x = 0; x < bitmap.width(); x++)
+ for (int y = 0; y < bitmap.height(); y++)
+ EXPECT_EQ(bitmap.getColor(x, y), color);
+ }
+ }
+
+ protected:
+ std::unique_ptr<SkiaVectorAnimation> animation_;
+ scoped_refptr<SkottieWrapper> skottie_;
+
+ private:
+ std::unique_ptr<gfx::Canvas> canvas_;
+ base::SimpleTestTickClock test_clock_;
+
+ DISALLOW_COPY_AND_ASSIGN(SkiaVectorAnimationTest);
+};
+
+TEST_F(SkiaVectorAnimationTest, InitializationAndLoadingData) {
+ auto bytes = base::MakeRefCounted<base::RefCountedBytes>(
+ std::vector<unsigned char>(kData, kData + std::strlen(kData)));
+ skottie_ = base::MakeRefCounted<SkottieWrapper>(bytes.get());
+ animation_ = std::make_unique<SkiaVectorAnimation>(skottie_);
+ EXPECT_FLOAT_EQ(animation_->GetOriginalSize().width(), kAnimationWidth);
+ EXPECT_FLOAT_EQ(animation_->GetOriginalSize().height(), kAnimationHeight);
+ EXPECT_FLOAT_EQ(animation_->GetAnimationDuration().InSecondsF(),
+ kAnimationDuration);
+ EXPECT_TRUE(IsStopped());
+
+ skottie_ = base::MakeRefCounted<SkottieWrapper>(
+ std::make_unique<SkMemoryStream>(kData, std::strlen(kData)));
+ animation_ = std::make_unique<SkiaVectorAnimation>(skottie_);
+ EXPECT_FLOAT_EQ(animation_->GetOriginalSize().width(), kAnimationWidth);
+ EXPECT_FLOAT_EQ(animation_->GetOriginalSize().height(), kAnimationHeight);
+ EXPECT_FLOAT_EQ(animation_->GetAnimationDuration().InSecondsF(),
+ kAnimationDuration);
+ EXPECT_TRUE(IsStopped());
+}
+
+TEST_F(SkiaVectorAnimationTest, PlayLinearAnimation) {
+ TestAnimationObserver observer;
+ animation_->SetAnimationObserver(&observer);
+
+ // Advance clock by 300 milliseconds.
+ AdvanceClock(300);
+
+ EXPECT_TRUE(IsStopped());
+ animation_->Start(SkiaVectorAnimation::Style::kLinear);
+ EXPECT_TRUE(IsScheduledToPlay());
+ EXPECT_FALSE(observer.animation_will_start_playing());
+
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FALSE(IsScheduledToPlay());
+ EXPECT_TRUE(IsPlaying());
+ EXPECT_TRUE(observer.animation_will_start_playing());
+
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 0);
+ EXPECT_FLOAT_EQ(GetTimerStartOffset(), 0);
+ EXPECT_FLOAT_EQ(GetTimerEndOffset(), 1.f);
+
+ EXPECT_FLOAT_EQ(GetTimerProgressPerMs(), 1.f / 5000.f);
+
+ AdvanceClock(50);
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 50);
+
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 50.f / 5000.f);
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 0);
+
+ // Advance the clock to the end of the animation.
+ AdvanceClock(4951);
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 4951);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 1.f);
+ EXPECT_TRUE(HasAnimationEnded());
+ EXPECT_TRUE(observer.animation_cycle_ended());
+}
+
+TEST_F(SkiaVectorAnimationTest, StopLinearAnimation) {
+ TestAnimationObserver observer;
+ animation_->SetAnimationObserver(&observer);
+
+ // Advance clock by 300 milliseconds.
+ AdvanceClock(300);
+
+ animation_->Start(SkiaVectorAnimation::Style::kLinear);
+
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_TRUE(IsPlaying());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 0);
+
+ AdvanceClock(50);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 50.f / 5000.f);
+
+ animation_->Stop();
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 0.f);
+ EXPECT_TRUE(IsStopped());
+}
+
+TEST_F(SkiaVectorAnimationTest, PlaySubsectionOfLinearAnimation) {
+ const int start_time_ms = 400;
+ const int duration_ms = 1000;
+ const float total_duration_ms = kAnimationDuration * 1000.f;
+
+ TestAnimationObserver observer;
+
+ animation_->SetAnimationObserver(&observer);
+
+ // Advance clock by 300 milliseconds.
+ AdvanceClock(300);
+
+ EXPECT_FALSE(observer.animation_cycle_ended());
+ animation_->StartSubsection(base::TimeDelta::FromMilliseconds(start_time_ms),
+ base::TimeDelta::FromMilliseconds(duration_ms),
+ SkiaVectorAnimation::Style::kLinear);
+
+ EXPECT_TRUE(IsScheduledToPlay());
+ EXPECT_FALSE(observer.animation_will_start_playing());
+
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+
+ EXPECT_FALSE(IsScheduledToPlay());
+ EXPECT_TRUE(IsPlaying());
+ EXPECT_TRUE(observer.animation_will_start_playing());
+
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), GetTimerStartOffset());
+ EXPECT_FLOAT_EQ(GetTimerEndOffset(),
+ (start_time_ms + duration_ms) / total_duration_ms);
+
+ EXPECT_FLOAT_EQ(GetTimerProgressPerMs(), 1.f / total_duration_ms);
+
+ AdvanceClock(100);
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 100);
+
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 0);
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(),
+ (100.f + start_time_ms) / total_duration_ms);
+ EXPECT_FALSE(observer.animation_cycle_ended());
+
+ // Advance clock another 300 ms.
+ AdvanceClock(300);
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 300);
+
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 0);
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(),
+ (100.f + 300.f + start_time_ms) / total_duration_ms);
+ EXPECT_FALSE(observer.animation_cycle_ended());
+
+ // Reach the end of animation.
+ AdvanceClock(601);
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 601);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), GetTimerEndOffset());
+ EXPECT_TRUE(observer.animation_cycle_ended());
+ EXPECT_TRUE(HasAnimationEnded());
+}
+
+TEST_F(SkiaVectorAnimationTest, PausingLinearAnimation) {
+ const int start_time_ms = 400;
+ const int duration_ms = 1000;
+ const float total_duration_ms = kAnimationDuration * 1000.f;
+ TestAnimationObserver observer;
+ animation_->SetAnimationObserver(&observer);
+
+ AdvanceClock(200);
+
+ animation_->StartSubsection(base::TimeDelta::FromMilliseconds(start_time_ms),
+ base::TimeDelta::FromMilliseconds(duration_ms),
+ SkiaVectorAnimation::Style::kLinear);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+
+ AdvanceClock(100);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 500.f / total_duration_ms);
+
+ AdvanceClock(100);
+ animation_->Pause();
+ EXPECT_TRUE(IsPaused());
+
+ // Advancing clock and stepping animation should have no effect when animation
+ // is paused.
+ AdvanceClock(5000);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 500.f / total_duration_ms);
+
+ // Resume playing the animation.
+ animation_->ResumePlaying();
+ EXPECT_TRUE(IsScheduledToResume());
+
+ // There should be no progress, since we haven't advanced the clock yet.
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_TRUE(IsPlaying());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 500.f / total_duration_ms);
+
+ AdvanceClock(100);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 600.f / total_duration_ms);
+
+ AdvanceClock(801);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+}
+
+TEST_F(SkiaVectorAnimationTest, PlayLoopAnimation) {
+ TestAnimationObserver observer;
+ animation_->SetAnimationObserver(&observer);
+
+ // Advance clock by 300 milliseconds.
+ AdvanceClock(300);
+
+ EXPECT_TRUE(IsStopped());
+ animation_->Start(SkiaVectorAnimation::Style::kLoop);
+ EXPECT_TRUE(IsScheduledToPlay());
+ EXPECT_FALSE(observer.animation_will_start_playing());
+
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+
+ EXPECT_FALSE(IsScheduledToPlay());
+ EXPECT_TRUE(IsPlaying());
+ EXPECT_TRUE(observer.animation_will_start_playing());
+
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 0);
+ EXPECT_FLOAT_EQ(GetTimerStartOffset(), 0);
+ EXPECT_FLOAT_EQ(GetTimerEndOffset(), 1.f);
+
+ EXPECT_FLOAT_EQ(GetTimerProgressPerMs(), 1.f / 5000.f);
+
+ AdvanceClock(50);
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 50);
+
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 50.f / 5000.f);
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 0);
+
+ // Advance the clock to the end of the animation.
+ AdvanceClock(4950);
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 4950);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_EQ(GetTimerCycles(), 1);
+ EXPECT_TRUE(std::abs(animation_->GetCurrentProgress() - 0.f) < 0.0001f);
+ EXPECT_TRUE(observer.animation_cycle_ended());
+ EXPECT_TRUE(IsPlaying());
+}
+
+TEST_F(SkiaVectorAnimationTest, PlaySubsectionOfLoopAnimation) {
+ const int start_time_ms = 400;
+ const int duration_ms = 1000;
+ const float total_duration_ms = kAnimationDuration * 1000.f;
+
+
+ TestAnimationObserver observer;
+ animation_->SetAnimationObserver(&observer);
+
+ // Advance clock by 300 milliseconds.
+ AdvanceClock(300);
+ EXPECT_TRUE(IsStopped());
+ animation_->StartSubsection(base::TimeDelta::FromMilliseconds(start_time_ms),
+ base::TimeDelta::FromMilliseconds(duration_ms),
+ SkiaVectorAnimation::Style::kLoop);
+ EXPECT_TRUE(IsScheduledToPlay());
+ EXPECT_FALSE(observer.animation_will_start_playing());
+
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+
+ EXPECT_FALSE(IsScheduledToPlay());
+ EXPECT_TRUE(IsPlaying());
+ EXPECT_TRUE(observer.animation_will_start_playing());
+
+ EXPECT_FALSE(observer.animation_cycle_ended());
+ EXPECT_FLOAT_EQ(GetTimerStartOffset(), 400.f / total_duration_ms);
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), GetTimerStartOffset());
+ EXPECT_FLOAT_EQ(GetTimerEndOffset(),
+ (start_time_ms + duration_ms) / total_duration_ms);
+
+ EXPECT_FLOAT_EQ(GetTimerProgressPerMs(), 1.f / total_duration_ms);
+
+ AdvanceClock(100);
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 100);
+ EXPECT_FALSE(observer.animation_cycle_ended());
+
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 0);
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(),
+ (100.f + start_time_ms) / total_duration_ms);
+
+ // Advance clock another 300 ms.
+ AdvanceClock(300);
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 300);
+
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 0);
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(),
+ (100.f + 300.f + start_time_ms) / total_duration_ms);
+ EXPECT_FALSE(observer.animation_cycle_ended());
+
+ // Reach the end of animation.
+ AdvanceClock(600);
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 600);
+
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_TRUE(observer.animation_cycle_ended());
+ EXPECT_TRUE(IsPlaying());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), GetTimerStartOffset());
+}
+
+TEST_F(SkiaVectorAnimationTest, PausingLoopAnimation) {
+ const int start_time_ms = 400;
+ const int duration_ms = 1000;
+ const float total_duration_ms = kAnimationDuration * 1000.f;
+
+ TestAnimationObserver observer;
+ animation_->SetAnimationObserver(&observer);
+
+ AdvanceClock(200);
+
+ animation_->StartSubsection(base::TimeDelta::FromMilliseconds(start_time_ms),
+ base::TimeDelta::FromMilliseconds(duration_ms),
+ SkiaVectorAnimation::Style::kLoop);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 400.f / total_duration_ms);
+
+ AdvanceClock(100);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 500.f / total_duration_ms);
+
+ AdvanceClock(100);
+ animation_->Pause();
+ EXPECT_TRUE(IsPaused());
+
+ // Advancing clock and stepping animation should have no effect when animation
+ // is paused.
+ AdvanceClock(5000);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 500.f / total_duration_ms);
+
+ // Resume playing the animation.
+ animation_->ResumePlaying();
+ EXPECT_TRUE(IsScheduledToResume());
+
+ // There should be no progress, since we haven't advanced the clock yet.
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_TRUE(IsPlaying());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 500.f / total_duration_ms);
+
+ AdvanceClock(100);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 600.f / total_duration_ms);
+ EXPECT_FALSE(observer.animation_cycle_ended());
+
+ AdvanceClock(800);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), GetTimerStartOffset());
+ EXPECT_TRUE(IsPlaying());
+ EXPECT_TRUE(observer.animation_cycle_ended());
+}
+
+TEST_F(SkiaVectorAnimationTest, PlayThrobbingAnimation) {
+
+ TestAnimationObserver observer;
+ animation_->SetAnimationObserver(&observer);
+ // Advance clock by 300 milliseconds.
+ AdvanceClock(300);
+
+ animation_->Start(SkiaVectorAnimation::Style::kThrobbing);
+ EXPECT_TRUE(IsScheduledToPlay());
+ EXPECT_FALSE(observer.animation_will_start_playing());
+
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+
+ EXPECT_FALSE(IsScheduledToPlay());
+ EXPECT_TRUE(IsPlaying());
+ EXPECT_TRUE(observer.animation_will_start_playing());
+
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 0);
+ EXPECT_FLOAT_EQ(GetTimerStartOffset(), 0);
+ EXPECT_FLOAT_EQ(GetTimerEndOffset(), 1.f);
+
+ EXPECT_FLOAT_EQ(GetTimerProgressPerMs(), 1.f / 5000.f);
+
+ AdvanceClock(50);
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 50);
+
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 50.f / 5000.f);
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 0);
+
+ // Advance the clock to the end of the animation.
+ AdvanceClock(4950);
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 4950);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 1.f);
+ EXPECT_TRUE(IsPlaying());
+ EXPECT_FALSE(observer.animation_cycle_ended());
+
+ AdvanceClock(2500);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 0.5f);
+ EXPECT_TRUE(IsPlaying());
+ EXPECT_FALSE(observer.animation_cycle_ended());
+
+ AdvanceClock(2500);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 0);
+ EXPECT_TRUE(IsPlaying());
+ EXPECT_TRUE(observer.animation_cycle_ended());
+}
+
+TEST_F(SkiaVectorAnimationTest, PlaySubsectionOfThrobbingAnimation) {
+ const int start_time_ms = 400;
+ const int duration_ms = 1000;
+ const float total_duration_ms = kAnimationDuration * 1000.f;
+
+
+ TestAnimationObserver observer;
+ animation_->SetAnimationObserver(&observer);
+
+ // Advance clock by 300 milliseconds.
+ AdvanceClock(300);
+
+ animation_->StartSubsection(base::TimeDelta::FromMilliseconds(start_time_ms),
+ base::TimeDelta::FromMilliseconds(duration_ms),
+ SkiaVectorAnimation::Style::kThrobbing);
+ EXPECT_TRUE(IsScheduledToPlay());
+ EXPECT_FALSE(observer.animation_will_start_playing());
+
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+
+ EXPECT_FALSE(IsScheduledToPlay());
+ EXPECT_TRUE(IsPlaying());
+ EXPECT_TRUE(observer.animation_will_start_playing());
+
+ EXPECT_FLOAT_EQ(GetTimerStartOffset(), 400.f / total_duration_ms);
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), GetTimerStartOffset());
+ EXPECT_FLOAT_EQ(GetTimerEndOffset(),
+ (start_time_ms + duration_ms) / total_duration_ms);
+
+ EXPECT_FLOAT_EQ(GetTimerProgressPerMs(), 1.f / total_duration_ms);
+
+ AdvanceClock(100);
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 100);
+
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FALSE(observer.animation_cycle_ended());
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 0);
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(),
+ (100.f + start_time_ms) / total_duration_ms);
+
+ // Advance clock another 300 ms.
+ AdvanceClock(300);
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 300);
+
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FALSE(observer.animation_cycle_ended());
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 0);
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(),
+ (100.f + 300.f + start_time_ms) / total_duration_ms);
+
+ // Reach the end of animation.
+ AdvanceClock(600);
+ EXPECT_EQ(TimeDeltaSince(GetTimerPreviousTick()).InMilliseconds(), 600);
+
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_TRUE(IsPlaying());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), GetTimerEndOffset());
+ EXPECT_FALSE(observer.animation_cycle_ended());
+
+ AdvanceClock(500);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 900.f / total_duration_ms);
+ EXPECT_TRUE(IsPlaying());
+ EXPECT_FALSE(observer.animation_cycle_ended());
+
+ AdvanceClock(500);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), GetTimerStartOffset());
+ EXPECT_TRUE(IsPlaying());
+ EXPECT_TRUE(observer.animation_cycle_ended());
+
+ observer.Reset();
+
+ AdvanceClock(100);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(),
+ (start_time_ms + 100.f) / total_duration_ms);
+ EXPECT_TRUE(IsPlaying());
+}
+
+TEST_F(SkiaVectorAnimationTest, PausingThrobbingAnimation) {
+ const int start_time_ms = 400;
+ const int duration_ms = 1000;
+ const float total_duration_ms = kAnimationDuration * 1000.f;
+
+ AdvanceClock(200);
+
+ animation_->StartSubsection(base::TimeDelta::FromMilliseconds(start_time_ms),
+ base::TimeDelta::FromMilliseconds(duration_ms),
+ SkiaVectorAnimation::Style::kThrobbing);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+
+ EXPECT_TRUE(IsPlaying());
+
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(),
+ start_time_ms / total_duration_ms);
+
+ AdvanceClock(100);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(),
+ (start_time_ms + 100.f) / total_duration_ms);
+
+ AdvanceClock(100);
+ animation_->Pause();
+ EXPECT_TRUE(IsPaused());
+
+ // Advancing clock and stepping animation should have no effect when animation
+ // is paused.
+ AdvanceClock(5000);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(),
+ (start_time_ms + 100.f) / total_duration_ms);
+
+ // Resume playing the animation.
+ animation_->ResumePlaying();
+ EXPECT_TRUE(IsScheduledToResume());
+
+ // There should be no progress, since we haven't advanced the clock yet.
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_TRUE(IsPlaying());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(),
+ (start_time_ms + 100.f) / total_duration_ms);
+
+ AdvanceClock(100);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(),
+ (start_time_ms + 200.f) / total_duration_ms);
+
+ AdvanceClock(800);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), GetTimerEndOffset());
+ EXPECT_TRUE(IsPlaying());
+
+ AdvanceClock(100);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(),
+ (start_time_ms + 900.f) / total_duration_ms);
+ EXPECT_TRUE(IsPlaying());
+
+ animation_->Pause();
+ EXPECT_TRUE(IsPaused());
+
+ AdvanceClock(10000);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(),
+ (start_time_ms + 900.f) / total_duration_ms);
+
+ // Resume playing the animation.
+ animation_->ResumePlaying();
+ EXPECT_TRUE(IsScheduledToResume());
+
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_TRUE(IsPlaying());
+
+ AdvanceClock(500);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(),
+ (start_time_ms + 400.f) / total_duration_ms);
+
+ AdvanceClock(400);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), GetTimerStartOffset());
+
+ AdvanceClock(100);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(),
+ (start_time_ms + 100.f) / total_duration_ms);
+ EXPECT_TRUE(IsPlaying());
+}
+
+TEST_F(SkiaVectorAnimationTest, PauseBeforePlay) {
+ const float total_duration_ms = kAnimationDuration * 1000.f;
+
+ // Test to see if the race condition is handled correctly. It may happen that
+ // we pause the video before it even starts playing.
+
+ TestAnimationObserver observer;
+ animation_->SetAnimationObserver(&observer);
+
+ AdvanceClock(300);
+
+ animation_->Start();
+ EXPECT_TRUE(IsScheduledToPlay());
+
+ animation_->Pause();
+ EXPECT_TRUE(IsPaused());
+
+ AdvanceClock(100);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+
+ animation_->ResumePlaying();
+ EXPECT_TRUE(IsScheduledToResume());
+
+ AdvanceClock(100);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_TRUE(IsPlaying());
+
+ AdvanceClock(100);
+ animation_->Paint(canvas(), NowTicks(), animation_->GetOriginalSize());
+ EXPECT_FLOAT_EQ(animation_->GetCurrentProgress(), 100.f / total_duration_ms);
+}
+
+TEST_F(SkiaVectorAnimationTest, PaintTest) {
+ std::unique_ptr<gfx::Canvas> canvas(new gfx::Canvas(
+ gfx::Size(kAnimationWidth, kAnimationHeight), 1.f, false));
+
+ // Advance clock by 300 milliseconds.
+ AdvanceClock(300);
+
+ animation_->Start(SkiaVectorAnimation::Style::kLinear);
+ animation_->Paint(canvas.get(), NowTicks(), animation_->GetOriginalSize());
+
+ AdvanceClock(50);
+ animation_->Paint(canvas.get(), NowTicks(), animation_->GetOriginalSize());
+ SkBitmap bitmap = canvas->GetBitmap();
+ IsAllSameColor(SK_ColorGREEN, bitmap);
+
+ AdvanceClock(2450);
+ animation_->Paint(canvas.get(), NowTicks(), animation_->GetOriginalSize());
+ bitmap = canvas->GetBitmap();
+ IsAllSameColor(SK_ColorGREEN, bitmap);
+
+ AdvanceClock(50);
+ animation_->Paint(canvas.get(), NowTicks(), animation_->GetOriginalSize());
+ bitmap = canvas->GetBitmap();
+ IsAllSameColor(SK_ColorBLUE, bitmap);
+
+ AdvanceClock(1000);
+ animation_->Paint(canvas.get(), NowTicks(), animation_->GetOriginalSize());
+ bitmap = canvas->GetBitmap();
+ IsAllSameColor(SK_ColorBLUE, bitmap);
+
+ AdvanceClock(1400);
+ animation_->Paint(canvas.get(), NowTicks(), animation_->GetOriginalSize());
+ bitmap = canvas->GetBitmap();
+ IsAllSameColor(SK_ColorBLUE, bitmap);
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/skottie_wrapper.cc b/chromium/ui/gfx/skottie_wrapper.cc
new file mode 100644
index 00000000000..1cba085fb46
--- /dev/null
+++ b/chromium/ui/gfx/skottie_wrapper.cc
@@ -0,0 +1,36 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gfx/skottie_wrapper.h"
+
+#include "base/memory/ref_counted_memory.h"
+#include "base/trace_event/trace_event.h"
+#include "third_party/skia/include/core/SkRect.h"
+#include "third_party/skia/include/core/SkStream.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace gfx {
+
+SkottieWrapper::SkottieWrapper(
+ const scoped_refptr<base::RefCountedMemory>& data_stream) {
+ TRACE_EVENT0("ui", "SkottieWrapper Parse");
+ SkMemoryStream sk_stream(data_stream->front(), data_stream->size());
+ animation_ = skottie::Animation::Make(&sk_stream);
+}
+
+SkottieWrapper::SkottieWrapper(std::unique_ptr<SkMemoryStream> stream)
+ : animation_(skottie::Animation::Make(stream.get())) {}
+
+SkottieWrapper::~SkottieWrapper() {}
+
+void SkottieWrapper::Draw(SkCanvas* canvas, float t, const gfx::Size& size) {
+ SkRect dst = SkRect::MakeXYWH(0, 0, size.width(), size.height());
+ {
+ base::AutoLock lock(lock_);
+ animation_->seek(t);
+ animation_->render(canvas, &dst);
+ }
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/skottie_wrapper.h b/chromium/ui/gfx/skottie_wrapper.h
new file mode 100644
index 00000000000..006d0cd26bf
--- /dev/null
+++ b/chromium/ui/gfx/skottie_wrapper.h
@@ -0,0 +1,55 @@
+// 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_GFX_SKOTTIE_WRAPPER_H_
+#define UI_GFX_SKOTTIE_WRAPPER_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/synchronization/lock.h"
+#include "third_party/skia/modules/skottie/include/Skottie.h"
+#include "ui/gfx/gfx_export.h"
+
+class SkCanvas;
+class SkMemoryStream;
+
+namespace base {
+class RefCountedMemory;
+} // namespace base
+
+namespace gfx {
+class Size;
+
+// A wrapper over Skia's Skottie object that can be shared by multiple
+// SkiaVectorAnimation objects. This class is thread safe when performing a draw
+// on an SkCanvas.
+class GFX_EXPORT SkottieWrapper
+ : public base::RefCountedThreadSafe<SkottieWrapper> {
+ public:
+ explicit SkottieWrapper(
+ const scoped_refptr<base::RefCountedMemory>& data_stream);
+ explicit SkottieWrapper(std::unique_ptr<SkMemoryStream> stream);
+
+ // A thread safe call that will draw an image of size |size| for the frame at
+ // normalized time instant |t| onto the |canvas|.
+ void Draw(SkCanvas* canvas, float t, const Size& size);
+
+ float duration() const { return animation_->duration(); }
+ SkSize size() const { return animation_->size(); }
+
+ private:
+ friend class base::RefCountedThreadSafe<SkottieWrapper>;
+ ~SkottieWrapper();
+
+ base::Lock lock_;
+ sk_sp<skottie::Animation> animation_;
+
+ DISALLOW_COPY_AND_ASSIGN(SkottieWrapper);
+};
+
+} // namespace gfx
+
+#endif // UI_GFX_SKOTTIE_WRAPPER_H_
diff --git a/chromium/ui/gfx/switches.cc b/chromium/ui/gfx/switches.cc
index e1943d5970a..b0c3d1daf7a 100644
--- a/chromium/ui/gfx/switches.cc
+++ b/chromium/ui/gfx/switches.cc
@@ -12,12 +12,6 @@ namespace switches {
const char kDisableDirectWriteForUI[] = "disable-directwrite-for-ui";
#endif
-#if defined(OS_MACOSX)
-// Enables the HarfBuzz port of RenderText on Mac (it's already used only for
-// text editing; this enables it for everything else).
-const char kEnableHarfBuzzRenderText[] = "enable-harfbuzz-rendertext";
-#endif
-
// Force disables font subpixel positioning. This affects the character glyph
// sharpness, kerning, hinting and layout.
const char kDisableFontSubpixelPositioning[] =
@@ -37,4 +31,16 @@ namespace features {
const base::Feature kLeftToRightUrls{"LeftToRightUrls",
base::FEATURE_DISABLED_BY_DEFAULT};
+// Enables or disables the use of cc::PaintRecords as a backing store for
+// ImageSkiaReps. This may reduce load on the UI thread by moving rasterization
+// of drawables away from this thread.
+const base::Feature kUsePaintRecordForImageSkia{
+ "UsePaintRecordForImageSkia",
+#if defined(OS_CHROMEOS)
+ base::FEATURE_ENABLED_BY_DEFAULT
+#else
+ base::FEATURE_DISABLED_BY_DEFAULT
+#endif
+};
+
} // namespace features
diff --git a/chromium/ui/gfx/switches.h b/chromium/ui/gfx/switches.h
index dc4921dbf0c..b206f18ad77 100644
--- a/chromium/ui/gfx/switches.h
+++ b/chromium/ui/gfx/switches.h
@@ -15,10 +15,6 @@ namespace switches {
GFX_SWITCHES_EXPORT extern const char kDisableDirectWriteForUI[];
#endif
-#if defined(OS_MACOSX)
-GFX_SWITCHES_EXPORT extern const char kEnableHarfBuzzRenderText[];
-#endif
-
GFX_SWITCHES_EXPORT extern const char kDisableFontSubpixelPositioning[];
GFX_SWITCHES_EXPORT extern const char kHeadless[];
@@ -29,6 +25,8 @@ namespace features {
GFX_SWITCHES_EXPORT extern const base::Feature kLeftToRightUrls;
+GFX_SWITCHES_EXPORT extern const base::Feature kUsePaintRecordForImageSkia;
+
} // namespace features
#endif // UI_GFX_SWITCHES_H_
diff --git a/chromium/ui/gfx/transform.h b/chromium/ui/gfx/transform.h
index f5e600f9f81..433a545dcc1 100644
--- a/chromium/ui/gfx/transform.h
+++ b/chromium/ui/gfx/transform.h
@@ -11,7 +11,7 @@
#include "base/compiler_specific.h"
#include "third_party/skia/include/core/SkMatrix44.h"
#include "ui/gfx/geometry/vector2d_f.h"
-#include "ui/gfx/gfx_export.h"
+#include "ui/gfx/geometry_skia_export.h"
namespace gfx {
@@ -25,7 +25,7 @@ class Vector3dF;
// 4x4 transformation matrix. Transform is cheap and explicitly allows
// copy/assign.
-class GFX_EXPORT Transform {
+class GEOMETRY_SKIA_EXPORT Transform {
public:
enum SkipInitialization {
diff --git a/chromium/ui/gfx/transform_util.h b/chromium/ui/gfx/transform_util.h
index 78b7739e140..2f72cbf4a4a 100644
--- a/chromium/ui/gfx/transform_util.h
+++ b/chromium/ui/gfx/transform_util.h
@@ -7,7 +7,7 @@
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/quaternion.h"
-#include "ui/gfx/gfx_export.h"
+#include "ui/gfx/geometry_skia_export.h"
#include "ui/gfx/transform.h"
namespace gfx {
@@ -16,11 +16,12 @@ class Point;
class Rect;
// Returns a scale transform at |anchor| point.
-GFX_EXPORT Transform GetScaleTransform(const Point& anchor, float scale);
+GEOMETRY_SKIA_EXPORT Transform GetScaleTransform(const Point& anchor,
+ float scale);
// Contains the components of a factored transform. These components may be
// blended and recomposed.
-struct GFX_EXPORT DecomposedTransform {
+struct GEOMETRY_SKIA_EXPORT DecomposedTransform {
// The default constructor initializes the components in such a way that
// if used with Compose below, will produce the identity transform.
DecomposedTransform();
@@ -40,7 +41,7 @@ struct GFX_EXPORT DecomposedTransform {
// routines described in http://www.w3.org/TR/css3-3d-transform/.
// |progress| is in the range [0, 1]. If 0 we will return |from|, if 1, we will
// return |to|.
-GFX_EXPORT DecomposedTransform
+GEOMETRY_SKIA_EXPORT DecomposedTransform
BlendDecomposedTransforms(const DecomposedTransform& to,
const DecomposedTransform& from,
double progress);
@@ -48,23 +49,24 @@ BlendDecomposedTransforms(const DecomposedTransform& to,
// Decomposes this transform into its translation, scale, skew, perspective,
// and rotation components following the routines detailed in this spec:
// http://www.w3.org/TR/css3-3d-transforms/.
-GFX_EXPORT bool DecomposeTransform(DecomposedTransform* out,
- const Transform& transform);
+GEOMETRY_SKIA_EXPORT bool DecomposeTransform(DecomposedTransform* out,
+ const Transform& transform);
// Composes a transform from the given translation, scale, skew, prespective,
// and rotation components following the routines detailed in this spec:
// http://www.w3.org/TR/css3-3d-transforms/.
-GFX_EXPORT Transform ComposeTransform(const DecomposedTransform& decomp);
+GEOMETRY_SKIA_EXPORT Transform
+ComposeTransform(const DecomposedTransform& decomp);
-GFX_EXPORT bool SnapTransform(Transform* out,
- const Transform& transform,
- const Rect& viewport);
+GEOMETRY_SKIA_EXPORT bool SnapTransform(Transform* out,
+ const Transform& transform,
+ const Rect& viewport);
// Calculates a transform with a transformed origin. The resulting tranform is
// created by composing P * T * P^-1 where P is a constant transform to the new
// origin.
-GFX_EXPORT Transform TransformAboutPivot(const gfx::Point& pivot,
- const gfx::Transform& transform);
+GEOMETRY_SKIA_EXPORT Transform
+TransformAboutPivot(const gfx::Point& pivot, const gfx::Transform& transform);
} // namespace gfx
diff --git a/chromium/ui/gfx/typemaps.gni b/chromium/ui/gfx/typemaps.gni
index ba383a829db..c4ea97d798c 100644
--- a/chromium/ui/gfx/typemaps.gni
+++ b/chromium/ui/gfx/typemaps.gni
@@ -13,6 +13,7 @@ typemaps = [
"//ui/gfx/mojo/gpu_fence_handle.typemap",
"//ui/gfx/mojo/overlay_transform.typemap",
"//ui/gfx/mojo/presentation_feedback.typemap",
+ "//ui/gfx/mojo/swap_result.typemap",
"//ui/gfx/mojo/selection_bound.typemap",
"//ui/gfx/mojo/transform.typemap",
"//ui/gfx/range/mojo/range.typemap",
diff --git a/chromium/ui/gl/BUILD.gn b/chromium/ui/gl/BUILD.gn
index 2699acc9460..67cedb57328 100644
--- a/chromium/ui/gl/BUILD.gn
+++ b/chromium/ui/gl/BUILD.gn
@@ -3,6 +3,7 @@
# found in the LICENSE file.
import("//build/buildflag_header.gni")
+import("//build/config/jumbo.gni")
import("//build/config/chrome_build.gni")
import("//build/config/linux/pkg_config.gni")
import("//build/config/ui.gni")
@@ -46,10 +47,12 @@ config("gl_config") {
}
}
-component("gl") {
+jumbo_component("gl") {
output_name = "gl_wrapper" # Avoid colliding with OS X"s libGL.dylib.
sources = [
+ "android/android_surface_composer_compat.cc",
+ "android/android_surface_composer_compat.h",
"android/scoped_java_surface.cc",
"android/scoped_java_surface.h",
"android/surface_texture.cc",
@@ -125,6 +128,7 @@ component("gl") {
"gpu_switching_manager.h",
"gpu_timing.cc",
"gpu_timing.h",
+ "progress_reporter.h",
"scoped_binders.cc",
"scoped_binders.h",
"scoped_make_current.cc",
@@ -194,11 +198,9 @@ component("gl") {
sources += [
"gl_image_ahardwarebuffer.cc",
"gl_image_ahardwarebuffer.h",
+ "gl_surface_egl_surface_control.cc",
+ "gl_surface_egl_surface_control.h",
]
-
- if (use_static_angle) {
- deps += [ "//third_party/angle:libEGL_static" ]
- }
}
if (is_posix && !is_fuchsia && !is_mac) {
@@ -375,7 +377,7 @@ if (is_mac && use_egl) {
}
}
-static_library("gl_unittest_utils") {
+jumbo_static_library("gl_unittest_utils") {
testonly = true
sources = [
"egl_bindings_autogen_mock.cc",
@@ -401,7 +403,7 @@ static_library("gl_unittest_utils") {
]
}
-static_library("test_support") {
+jumbo_static_library("test_support") {
testonly = true
sources = [
"test/gl_image_test_support.cc",
diff --git a/chromium/ui/gl/android/android_surface_composer_compat.cc b/chromium/ui/gl/android/android_surface_composer_compat.cc
new file mode 100644
index 00000000000..f34d25cae13
--- /dev/null
+++ b/chromium/ui/gl/android/android_surface_composer_compat.cc
@@ -0,0 +1,253 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/android/android_surface_composer_compat.h"
+
+#include "base/android/build_info.h"
+#include "base/memory/ptr_util.h"
+#include "base/no_destructor.h"
+
+#include <dlfcn.h>
+
+extern "C" {
+// ASurfaceComposer
+using pASurfaceComposer_Create = ASurfaceComposer* (*)(ANativeWindow*);
+using pASurfaceComposer_Delete = void (*)(ASurfaceComposer*);
+
+// ASurface
+using pASurfaceComposer_CreateSurface = ASurface* (*)(ASurfaceComposer*,
+ int32_t content_type,
+ ASurface* parent,
+ const char* name);
+using pASurfaceComposer_DeleteSurface = void (*)(ASurface*);
+
+// ASurfaceTransaction
+using pASurfaceComposer_CreateTransaction = ASurfaceTransaction* (*)(void);
+using pASurfaceComposer_DeleteTransaction = void (*)(ASurfaceTransaction*);
+using pASurfaceComposer_TransactionApply = int64_t (*)(ASurfaceTransaction*);
+using pASurfaceComposer_TransactionSetVisibility =
+ void (*)(ASurfaceTransaction*, ASurface*, bool show);
+using pASurfaceComposer_TransactionSetPosition = void (*)(ASurfaceTransaction*,
+ ASurface*,
+ float x,
+ float y);
+using pASurfaceComposer_TransactionSetZOrder =
+ void (*)(ASurfaceTransaction* transaction, ASurface*, int32_t z);
+using pASurfaceComposer_TransactionSetBuffer =
+ void (*)(ASurfaceTransaction* transaction,
+ ASurface*,
+ AHardwareBuffer*,
+ int32_t fence_fd);
+using pASurfaceComposer_TransactionSetSize =
+ void (*)(ASurfaceTransaction* transaction,
+ ASurface* surface,
+ uint32_t width,
+ uint32_t height);
+using pASurfaceComposer_TransactionSetCropRect =
+ void (*)(ASurfaceTransaction* transaction,
+ ASurface* surface,
+ int32_t left,
+ int32_t top,
+ int32_t right,
+ int32_t bottom);
+using pASurfaceComposer_TransactionSetOpaque =
+ void (*)(ASurfaceTransaction* transaction,
+ ASurface* surface,
+ uint32_t transform);
+}
+
+namespace gl {
+namespace {
+
+#define LOAD_FUNCTION(lib, func) \
+ do { \
+ func##Fn = reinterpret_cast<p##func>(dlsym(lib, #func)); \
+ if (!func##Fn) { \
+ supported = false; \
+ LOG(ERROR) << "Unable to load function " << #func; \
+ } \
+ } while (0)
+
+struct SurfaceComposerMethods {
+ public:
+ static const SurfaceComposerMethods& Get() {
+ static const base::NoDestructor<SurfaceComposerMethods> instance;
+ return *instance;
+ }
+
+ SurfaceComposerMethods() {
+ void* main_dl_handle = dlopen(nullptr, RTLD_NOW);
+ if (!main_dl_handle) {
+ LOG(ERROR) << "Couldnt load android so";
+ supported = false;
+ return;
+ }
+
+ LOAD_FUNCTION(main_dl_handle, ASurfaceComposer_Create);
+ LOAD_FUNCTION(main_dl_handle, ASurfaceComposer_Delete);
+ LOAD_FUNCTION(main_dl_handle, ASurfaceComposer_CreateSurface);
+ LOAD_FUNCTION(main_dl_handle, ASurfaceComposer_DeleteSurface);
+ LOAD_FUNCTION(main_dl_handle, ASurfaceComposer_CreateTransaction);
+ LOAD_FUNCTION(main_dl_handle, ASurfaceComposer_DeleteTransaction);
+ LOAD_FUNCTION(main_dl_handle, ASurfaceComposer_TransactionApply);
+ LOAD_FUNCTION(main_dl_handle, ASurfaceComposer_TransactionSetVisibility);
+ LOAD_FUNCTION(main_dl_handle, ASurfaceComposer_TransactionSetPosition);
+ LOAD_FUNCTION(main_dl_handle, ASurfaceComposer_TransactionSetZOrder);
+ LOAD_FUNCTION(main_dl_handle, ASurfaceComposer_TransactionSetBuffer);
+ LOAD_FUNCTION(main_dl_handle, ASurfaceComposer_TransactionSetSize);
+ LOAD_FUNCTION(main_dl_handle, ASurfaceComposer_TransactionSetCropRect);
+ LOAD_FUNCTION(main_dl_handle, ASurfaceComposer_TransactionSetOpaque);
+ }
+
+ ~SurfaceComposerMethods() = default;
+
+ bool supported = true;
+ pASurfaceComposer_Create ASurfaceComposer_CreateFn;
+ pASurfaceComposer_Delete ASurfaceComposer_DeleteFn;
+ pASurfaceComposer_CreateSurface ASurfaceComposer_CreateSurfaceFn;
+ pASurfaceComposer_DeleteSurface ASurfaceComposer_DeleteSurfaceFn;
+ pASurfaceComposer_CreateTransaction ASurfaceComposer_CreateTransactionFn;
+ pASurfaceComposer_DeleteTransaction ASurfaceComposer_DeleteTransactionFn;
+ pASurfaceComposer_TransactionApply ASurfaceComposer_TransactionApplyFn;
+ pASurfaceComposer_TransactionSetVisibility
+ ASurfaceComposer_TransactionSetVisibilityFn;
+ pASurfaceComposer_TransactionSetPosition
+ ASurfaceComposer_TransactionSetPositionFn;
+ pASurfaceComposer_TransactionSetZOrder
+ ASurfaceComposer_TransactionSetZOrderFn;
+ pASurfaceComposer_TransactionSetBuffer
+ ASurfaceComposer_TransactionSetBufferFn;
+ pASurfaceComposer_TransactionSetSize ASurfaceComposer_TransactionSetSizeFn;
+ pASurfaceComposer_TransactionSetCropRect
+ ASurfaceComposer_TransactionSetCropRectFn;
+ pASurfaceComposer_TransactionSetOpaque
+ ASurfaceComposer_TransactionSetOpaqueFn;
+};
+};
+
+// static
+bool SurfaceComposer::IsSupported() {
+ const int sdk_int = base::android::BuildInfo::GetInstance()->sdk_int();
+ if (sdk_int < 29) {
+ LOG(ERROR) << "SurfaceControl not supported on sdk: " << sdk_int;
+ return false;
+ }
+ return SurfaceComposerMethods::Get().supported;
+}
+
+// static
+std::unique_ptr<SurfaceComposer> SurfaceComposer::Create(
+ ANativeWindow* window) {
+ DCHECK(SurfaceComposerMethods::Get().supported);
+ auto* a_composer =
+ SurfaceComposerMethods::Get().ASurfaceComposer_CreateFn(window);
+ if (!a_composer)
+ return nullptr;
+ return base::WrapUnique(new SurfaceComposer(a_composer));
+}
+
+SurfaceComposer::SurfaceComposer(ASurfaceComposer* composer)
+ : composer_(composer) {}
+
+SurfaceComposer::~SurfaceComposer() {
+ SurfaceComposerMethods::Get().ASurfaceComposer_DeleteFn(composer_);
+}
+
+SurfaceComposer::Surface::Surface() = default;
+
+SurfaceComposer::Surface::Surface(SurfaceComposer* composer,
+ SurfaceContentType content_type,
+ const char* name,
+ Surface* parent) {
+ surface_ = SurfaceComposerMethods::Get().ASurfaceComposer_CreateSurfaceFn(
+ composer->composer_, static_cast<int32_t>(content_type),
+ parent ? parent->surface() : nullptr, name);
+ DCHECK(surface_);
+}
+
+SurfaceComposer::Surface::~Surface() {
+ if (surface_)
+ SurfaceComposerMethods::Get().ASurfaceComposer_DeleteSurfaceFn(surface_);
+}
+
+SurfaceComposer::Surface::Surface(Surface&& other) {
+ surface_ = other.surface_;
+ other.surface_ = nullptr;
+}
+
+SurfaceComposer::Surface& SurfaceComposer::Surface::operator=(Surface&& other) {
+ if (surface_)
+ SurfaceComposerMethods::Get().ASurfaceComposer_DeleteSurfaceFn(surface_);
+
+ surface_ = other.surface_;
+ other.surface_ = nullptr;
+ return *this;
+}
+
+SurfaceComposer::Transaction::Transaction() {
+ transaction_ =
+ SurfaceComposerMethods::Get().ASurfaceComposer_CreateTransactionFn();
+ DCHECK(transaction_);
+}
+
+SurfaceComposer::Transaction::~Transaction() {
+ SurfaceComposerMethods::Get().ASurfaceComposer_DeleteTransactionFn(
+ transaction_);
+}
+
+void SurfaceComposer::Transaction::SetVisibility(const Surface& surface,
+ bool show) {
+ SurfaceComposerMethods::Get().ASurfaceComposer_TransactionSetVisibilityFn(
+ transaction_, surface.surface(), show);
+}
+
+void SurfaceComposer::Transaction::SetPosition(const Surface& surface,
+ float x,
+ float y) {
+ SurfaceComposerMethods::Get().ASurfaceComposer_TransactionSetPositionFn(
+ transaction_, surface.surface(), x, y);
+}
+
+void SurfaceComposer::Transaction::SetZOrder(const Surface& surface,
+ int32_t z) {
+ SurfaceComposerMethods::Get().ASurfaceComposer_TransactionSetZOrderFn(
+ transaction_, surface.surface(), z);
+}
+
+void SurfaceComposer::Transaction::SetBuffer(const Surface& surface,
+ AHardwareBuffer* buffer,
+ base::ScopedFD fence_fd) {
+ SurfaceComposerMethods::Get().ASurfaceComposer_TransactionSetBufferFn(
+ transaction_, surface.surface(), buffer,
+ fence_fd.is_valid() ? fence_fd.release() : -1);
+}
+
+void SurfaceComposer::Transaction::SetSize(const Surface& surface,
+ uint32_t width,
+ uint32_t height) {
+ SurfaceComposerMethods::Get().ASurfaceComposer_TransactionSetSizeFn(
+ transaction_, surface.surface(), width, height);
+}
+
+void SurfaceComposer::Transaction::SetCropRect(const Surface& surface,
+ int32_t left,
+ int32_t top,
+ int32_t right,
+ int32_t bottom) {
+ SurfaceComposerMethods::Get().ASurfaceComposer_TransactionSetCropRectFn(
+ transaction_, surface.surface(), left, top, right, bottom);
+}
+
+void SurfaceComposer::Transaction::SetOpaque(const Surface& surface,
+ bool opaque) {
+ SurfaceComposerMethods::Get().ASurfaceComposer_TransactionSetOpaqueFn(
+ transaction_, surface.surface(), opaque);
+}
+
+void SurfaceComposer::Transaction::Apply() {
+ SurfaceComposerMethods::Get().ASurfaceComposer_TransactionApplyFn(
+ transaction_);
+}
+
+} // namespace gl
diff --git a/chromium/ui/gl/android/android_surface_composer_compat.h b/chromium/ui/gl/android/android_surface_composer_compat.h
new file mode 100644
index 00000000000..05b6c874794
--- /dev/null
+++ b/chromium/ui/gl/android/android_surface_composer_compat.h
@@ -0,0 +1,86 @@
+// 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_GL_ANDROID_ANDROID_SURFACE_COMPOSER_COMPAT_H_
+#define UI_GL_ANDROID_ANDROID_SURFACE_COMPOSER_COMPAT_H_
+
+#include <memory>
+
+#include <android/hardware_buffer.h>
+#include <android/native_window.h>
+
+#include "base/files/scoped_file.h"
+#include "ui/gl/gl_export.h"
+
+extern "C" {
+typedef struct ASurface ASurface;
+typedef struct ASurfaceComposer ASurfaceComposer;
+typedef struct ASurfaceTransaction ASurfaceTransaction;
+}
+
+namespace gl {
+
+class GL_EXPORT SurfaceComposer {
+ public:
+ enum class SurfaceContentType : int32_t {
+ kNone = 0,
+ kAHardwareBuffer = 1,
+ };
+
+ class GL_EXPORT Surface {
+ public:
+ Surface();
+ Surface(SurfaceComposer* composer,
+ SurfaceContentType content_type,
+ const char* name,
+ Surface* parent = nullptr);
+ ~Surface();
+
+ Surface(Surface&& other);
+ Surface& operator=(Surface&& other);
+
+ ASurface* surface() const { return surface_; }
+
+ private:
+ ASurface* surface_ = nullptr;
+ };
+
+ class GL_EXPORT Transaction {
+ public:
+ Transaction();
+ ~Transaction();
+
+ void SetVisibility(const Surface& surface, bool show);
+ void SetPosition(const Surface& surface, float x, float y);
+ void SetZOrder(const Surface& surface, int32_t z);
+ void SetBuffer(const Surface& surface,
+ AHardwareBuffer* buffer,
+ base::ScopedFD fence_fd);
+ void SetSize(const Surface& surface, uint32_t width, uint32_t height);
+ void SetCropRect(const Surface& surface,
+ int32_t left,
+ int32_t top,
+ int32_t right,
+ int32_t bottom);
+ void SetOpaque(const Surface& surface, bool opaque);
+ void Apply();
+
+ private:
+ ASurfaceTransaction* transaction_;
+ };
+
+ static bool IsSupported();
+
+ static std::unique_ptr<SurfaceComposer> Create(ANativeWindow* window);
+ ~SurfaceComposer();
+
+ private:
+ explicit SurfaceComposer(ASurfaceComposer* composer);
+
+ ASurfaceComposer* composer_;
+};
+
+}; // namespace gl
+
+#endif // UI_GL_ANDROID_ANDROID_SURFACE_COMPOSER_COMPAT_H_
diff --git a/chromium/ui/gl/angle_platform_impl.cc b/chromium/ui/gl/angle_platform_impl.cc
index 93c3bba1a06..4a0bc9aef25 100644
--- a/chromium/ui/gl/angle_platform_impl.cc
+++ b/chromium/ui/gl/angle_platform_impl.cc
@@ -19,13 +19,6 @@ namespace angle {
namespace {
-// This platform context stores user data accessible inside the impl methods.
-struct PlatformContext {
- CacheProgramCallback cache_program_callback;
-};
-
-base::LazyInstance<PlatformContext>::DestructorAtExit g_platform_context =
- LAZY_INSTANCE_INITIALIZER;
// Place the function pointers for ANGLEGetDisplayPlatform and
// ANGLEResetDisplayPlatform in read-only memory after being resolved to prevent
// them from being tampered with. See crbug.com/771365 for details.
@@ -133,26 +126,6 @@ void ANGLEPlatformImpl_histogramBoolean(PlatformMethods* platform,
ANGLEPlatformImpl_histogramEnumeration(platform, name, sample ? 1 : 0, 2);
}
-void ANGLEPlatformImpl_cacheProgram(PlatformMethods* platform,
- const ProgramKeyType& key,
- size_t program_size,
- const uint8_t* program_bytes) {
- PlatformContext* context =
- reinterpret_cast<PlatformContext*>(platform->context);
- if (context && context->cache_program_callback) {
- // Convert the key and binary to string form.
- std::string key_string(reinterpret_cast<const char*>(&key[0]),
- sizeof(ProgramKeyType));
- std::string value_string(reinterpret_cast<const char*>(program_bytes),
- program_size);
- std::string key_string_64;
- std::string value_string_64;
- base::Base64Encode(key_string, &key_string_64);
- base::Base64Encode(value_string, &value_string_64);
- context->cache_program_callback.Run(key_string_64, value_string_64);
- }
-}
-
} // anonymous namespace
bool InitializePlatform(EGLDisplay display) {
@@ -175,7 +148,7 @@ bool InitializePlatform(EGLDisplay display) {
PlatformMethods* platformMethods = nullptr;
if (!base::UnsanitizedCfiCall(g_angle_get_platform)(
static_cast<EGLDisplayType>(display), g_PlatformMethodNames,
- g_NumPlatformMethods, &g_platform_context.Get(), &platformMethods))
+ g_NumPlatformMethods, nullptr, &platformMethods))
return false;
platformMethods->currentTime = ANGLEPlatformImpl_currentTime;
platformMethods->addTraceEvent = ANGLEPlatformImpl_addTraceEvent;
@@ -194,7 +167,6 @@ bool InitializePlatform(EGLDisplay display) {
ANGLEPlatformImpl_monotonicallyIncreasingTime;
platformMethods->updateTraceEventDuration =
ANGLEPlatformImpl_updateTraceEventDuration;
- platformMethods->cacheProgram = ANGLEPlatformImpl_cacheProgram;
return true;
}
@@ -203,19 +175,10 @@ void ResetPlatform(EGLDisplay display) {
return;
base::UnsanitizedCfiCall(g_angle_reset_platform)(
static_cast<EGLDisplayType>(display));
- ResetCacheProgramCallback();
{
auto writer = base::AutoWritableMemory::Create(g_angle_reset_platform);
*g_angle_reset_platform = nullptr;
}
}
-void SetCacheProgramCallback(CacheProgramCallback callback) {
- g_platform_context.Get().cache_program_callback = callback;
-}
-
-void ResetCacheProgramCallback() {
- g_platform_context.Get().cache_program_callback.Reset();
-}
-
} // namespace angle
diff --git a/chromium/ui/gl/angle_platform_impl.h b/chromium/ui/gl/angle_platform_impl.h
index 21f101a7b3e..777b1d20828 100644
--- a/chromium/ui/gl/angle_platform_impl.h
+++ b/chromium/ui/gl/angle_platform_impl.h
@@ -17,11 +17,6 @@ namespace angle {
GL_EXPORT bool InitializePlatform(EGLDisplay display);
GL_EXPORT void ResetPlatform(EGLDisplay display);
-using CacheProgramCallback =
- ::base::RepeatingCallback<void(const std::string&, const std::string&)>;
-GL_EXPORT void SetCacheProgramCallback(CacheProgramCallback callback);
-GL_EXPORT void ResetCacheProgramCallback();
-
} // namespace angle
#endif // UI_GL_ANGLE_PLATFORM_IMPL_H_
diff --git a/chromium/ui/gl/egl_bindings_autogen_mock.cc b/chromium/ui/gl/egl_bindings_autogen_mock.cc
index c1e891ce172..5cfcad5cc73 100644
--- a/chromium/ui/gl/egl_bindings_autogen_mock.cc
+++ b/chromium/ui/gl/egl_bindings_autogen_mock.cc
@@ -391,43 +391,6 @@ MockEGLInterface::Mock_eglPostSubBufferNV(EGLDisplay dpy,
return interface_->PostSubBufferNV(dpy, surface, x, y, width, height);
}
-EGLint GL_BINDING_CALL
-MockEGLInterface::Mock_eglProgramCacheGetAttribANGLE(EGLDisplay dpy,
- EGLenum attrib) {
- MakeEglMockFunctionUnique("eglProgramCacheGetAttribANGLE");
- return interface_->ProgramCacheGetAttribANGLE(dpy, attrib);
-}
-
-void GL_BINDING_CALL
-MockEGLInterface::Mock_eglProgramCachePopulateANGLE(EGLDisplay dpy,
- const void* key,
- EGLint keysize,
- const void* binary,
- EGLint binarysize) {
- MakeEglMockFunctionUnique("eglProgramCachePopulateANGLE");
- interface_->ProgramCachePopulateANGLE(dpy, key, keysize, binary, binarysize);
-}
-
-void GL_BINDING_CALL
-MockEGLInterface::Mock_eglProgramCacheQueryANGLE(EGLDisplay dpy,
- EGLint index,
- void* key,
- EGLint* keysize,
- void* binary,
- EGLint* binarysize) {
- MakeEglMockFunctionUnique("eglProgramCacheQueryANGLE");
- interface_->ProgramCacheQueryANGLE(dpy, index, key, keysize, binary,
- binarysize);
-}
-
-EGLint GL_BINDING_CALL
-MockEGLInterface::Mock_eglProgramCacheResizeANGLE(EGLDisplay dpy,
- EGLint limit,
- EGLenum mode) {
- MakeEglMockFunctionUnique("eglProgramCacheResizeANGLE");
- return interface_->ProgramCacheResizeANGLE(dpy, limit, mode);
-}
-
EGLenum GL_BINDING_CALL MockEGLInterface::Mock_eglQueryAPI(void) {
MakeEglMockFunctionUnique("eglQueryAPI");
return interface_->QueryAPI();
@@ -503,6 +466,14 @@ EGLBoolean GL_BINDING_CALL MockEGLInterface::Mock_eglReleaseThread(void) {
return interface_->ReleaseThread();
}
+void GL_BINDING_CALL
+MockEGLInterface::Mock_eglSetBlobCacheFuncsANDROID(EGLDisplay dpy,
+ EGLSetBlobFuncANDROID set,
+ EGLGetBlobFuncANDROID get) {
+ MakeEglMockFunctionUnique("eglSetBlobCacheFuncsANDROID");
+ interface_->SetBlobCacheFuncsANDROID(dpy, set, get);
+}
+
EGLBoolean GL_BINDING_CALL
MockEGLInterface::Mock_eglStreamAttribKHR(EGLDisplay dpy,
EGLStreamKHR stream,
@@ -723,18 +694,6 @@ MockEGLInterface::GetGLProcAddress(const char* name) {
return reinterpret_cast<GLFunctionPointerType>(Mock_eglMakeCurrent);
if (strcmp(name, "eglPostSubBufferNV") == 0)
return reinterpret_cast<GLFunctionPointerType>(Mock_eglPostSubBufferNV);
- if (strcmp(name, "eglProgramCacheGetAttribANGLE") == 0)
- return reinterpret_cast<GLFunctionPointerType>(
- Mock_eglProgramCacheGetAttribANGLE);
- if (strcmp(name, "eglProgramCachePopulateANGLE") == 0)
- return reinterpret_cast<GLFunctionPointerType>(
- Mock_eglProgramCachePopulateANGLE);
- if (strcmp(name, "eglProgramCacheQueryANGLE") == 0)
- return reinterpret_cast<GLFunctionPointerType>(
- Mock_eglProgramCacheQueryANGLE);
- if (strcmp(name, "eglProgramCacheResizeANGLE") == 0)
- return reinterpret_cast<GLFunctionPointerType>(
- Mock_eglProgramCacheResizeANGLE);
if (strcmp(name, "eglQueryAPI") == 0)
return reinterpret_cast<GLFunctionPointerType>(Mock_eglQueryAPI);
if (strcmp(name, "eglQueryContext") == 0)
@@ -756,6 +715,9 @@ MockEGLInterface::GetGLProcAddress(const char* name) {
return reinterpret_cast<GLFunctionPointerType>(Mock_eglReleaseTexImage);
if (strcmp(name, "eglReleaseThread") == 0)
return reinterpret_cast<GLFunctionPointerType>(Mock_eglReleaseThread);
+ if (strcmp(name, "eglSetBlobCacheFuncsANDROID") == 0)
+ return reinterpret_cast<GLFunctionPointerType>(
+ Mock_eglSetBlobCacheFuncsANDROID);
if (strcmp(name, "eglStreamAttribKHR") == 0)
return reinterpret_cast<GLFunctionPointerType>(Mock_eglStreamAttribKHR);
if (strcmp(name, "eglStreamConsumerAcquireKHR") == 0)
diff --git a/chromium/ui/gl/egl_bindings_autogen_mock.h b/chromium/ui/gl/egl_bindings_autogen_mock.h
index e3e97c8e048..1d5010ba008 100644
--- a/chromium/ui/gl/egl_bindings_autogen_mock.h
+++ b/chromium/ui/gl/egl_bindings_autogen_mock.h
@@ -174,23 +174,6 @@ static EGLBoolean GL_BINDING_CALL Mock_eglPostSubBufferNV(EGLDisplay dpy,
EGLint y,
EGLint width,
EGLint height);
-static EGLint GL_BINDING_CALL
-Mock_eglProgramCacheGetAttribANGLE(EGLDisplay dpy, EGLenum attrib);
-static void GL_BINDING_CALL
-Mock_eglProgramCachePopulateANGLE(EGLDisplay dpy,
- const void* key,
- EGLint keysize,
- const void* binary,
- EGLint binarysize);
-static void GL_BINDING_CALL Mock_eglProgramCacheQueryANGLE(EGLDisplay dpy,
- EGLint index,
- void* key,
- EGLint* keysize,
- void* binary,
- EGLint* binarysize);
-static EGLint GL_BINDING_CALL Mock_eglProgramCacheResizeANGLE(EGLDisplay dpy,
- EGLint limit,
- EGLenum mode);
static EGLenum GL_BINDING_CALL Mock_eglQueryAPI(void);
static EGLBoolean GL_BINDING_CALL Mock_eglQueryContext(EGLDisplay dpy,
EGLContext ctx,
@@ -222,6 +205,10 @@ static EGLBoolean GL_BINDING_CALL Mock_eglReleaseTexImage(EGLDisplay dpy,
EGLSurface surface,
EGLint buffer);
static EGLBoolean GL_BINDING_CALL Mock_eglReleaseThread(void);
+static void GL_BINDING_CALL
+Mock_eglSetBlobCacheFuncsANDROID(EGLDisplay dpy,
+ EGLSetBlobFuncANDROID set,
+ EGLGetBlobFuncANDROID get);
static EGLBoolean GL_BINDING_CALL Mock_eglStreamAttribKHR(EGLDisplay dpy,
EGLStreamKHR stream,
EGLenum attribute,
diff --git a/chromium/ui/gl/generate_bindings.py b/chromium/ui/gl/generate_bindings.py
index c6b5d458d80..864919616df 100755
--- a/chromium/ui/gl/generate_bindings.py
+++ b/chromium/ui/gl/generate_bindings.py
@@ -238,10 +238,6 @@ GL_FUNCTIONS = [
'names': ['glCompileShader'],
'arguments': 'GLuint shader', },
{ 'return_type': 'void',
- 'versions': [{ 'name': 'glCompressedCopyTextureCHROMIUM',
- 'extensions': ['GL_CHROMIUM_copy_compressed_texture'], }],
- 'arguments': 'GLuint sourceId, GLuint destId', },
-{ 'return_type': 'void',
'names': ['glCompressedTexImage2D'],
'arguments':
'GLenum target, GLint level, GLenum internalformat, GLsizei width, '
@@ -1329,10 +1325,15 @@ GL_FUNCTIONS = [
{ 'name': 'glMatrixLoadIdentityCHROMIUM',
'extensions': ['GL_CHROMIUM_path_rendering'] }],
'arguments': 'GLenum matrixMode' },
+{'return_type': 'void',
+ 'known_as': 'glMaxShaderCompilerThreadsKHR',
+ 'versions': [{ 'name': 'glMaxShaderCompilerThreadsKHR',
+ 'extensions': ['GL_KHR_parallel_shader_compile'] }],
+ 'arguments': 'GLuint count', },
{ 'return_type': 'void',
'names': ['glMemoryBarrierByRegion'],
'arguments': 'GLbitfield barriers', },
-{ 'return_type': 'void',
+{'return_type': 'void',
'known_as': 'glMemoryBarrierEXT',
'versions': [{ 'name': 'glMemoryBarrier',
'extensions': ['GL_ARB_shader_image_load_store'] },
@@ -2333,24 +2334,6 @@ EGL_FUNCTIONS = [
'names': ['eglPostSubBufferNV'],
'arguments': 'EGLDisplay dpy, EGLSurface surface, '
'EGLint x, EGLint y, EGLint width, EGLint height', },
-{ 'return_type': 'EGLint',
- 'versions': [{ 'name': 'eglProgramCacheGetAttribANGLE',
- 'extensions': ['EGL_ANGLE_program_cache_control'] }],
- 'arguments': 'EGLDisplay dpy, EGLenum attrib', },
-{ 'return_type': 'void',
- 'versions': [{ 'name': 'eglProgramCachePopulateANGLE',
- 'extensions': ['EGL_ANGLE_program_cache_control'] }],
- 'arguments': 'EGLDisplay dpy, const void* key, '
- 'EGLint keysize, const void* binary, EGLint binarysize', },
-{ 'return_type': 'void',
- 'versions': [{ 'name': 'eglProgramCacheQueryANGLE',
- 'extensions': ['EGL_ANGLE_program_cache_control'] }],
- 'arguments': 'EGLDisplay dpy, EGLint index, '
- 'void* key, EGLint* keysize, void* binary, EGLint* binarysize', },
-{ 'return_type': 'EGLint',
- 'versions': [{ 'name': 'eglProgramCacheResizeANGLE',
- 'extensions': ['EGL_ANGLE_program_cache_control'] }],
- 'arguments': 'EGLDisplay dpy, EGLint limit, EGLenum mode', },
{ 'return_type': 'EGLenum',
'names': ['eglQueryAPI'],
'arguments': 'void', },
@@ -2392,6 +2375,11 @@ EGL_FUNCTIONS = [
{ 'return_type': 'EGLBoolean',
'names': ['eglReleaseThread'],
'arguments': 'void', },
+{ 'return_type': 'void',
+ 'versions': [{ 'name': 'eglSetBlobCacheFuncsANDROID',
+ 'extensions': ['EGL_ANDROID_blob_cache'] }],
+ 'arguments':
+ 'EGLDisplay dpy, EGLSetBlobFuncANDROID set, EGLGetBlobFuncANDROID get' },
{ 'return_type': 'EGLBoolean',
'versions': [{ 'name': 'eglStreamAttribKHR',
'extensions': ['EGL_KHR_stream'] }],
@@ -3217,6 +3205,9 @@ void DriverEGL::InitializeExtensionBindings() {
r'(const )?[a-zA-Z0-9_]+\* ([a-zA-Z0-9_]+)',
r'CONSTVOID_\2', log_argument_names)
log_argument_names = re.sub(
+ r'(const )?EGL[GS]etBlobFuncANDROID ([a-zA-Z0-9_]+)',
+ r'FUNCPTR_\2', log_argument_names)
+ log_argument_names = re.sub(
r'(?<!E)GLboolean ([a-zA-Z0-9_]+)', r'GLboolean_\1', log_argument_names)
log_argument_names = re.sub(
r'GLDEBUGPROC ([a-zA-Z0-9_]+)',
@@ -3239,6 +3230,9 @@ void DriverEGL::InitializeExtensionBindings() {
r'CONSTVOID_([a-zA-Z0-9_]+)',
r'static_cast<const void*>(\1)', log_argument_names)
log_argument_names = re.sub(
+ r'FUNCPTR_([a-zA-Z0-9_]+)',
+ r'reinterpret_cast<const void*>(\1)', log_argument_names)
+ log_argument_names = re.sub(
r'CONSTCHAR_([a-zA-Z0-9_]+)', r'\1', log_argument_names)
log_argument_names = re.sub(
r'GLboolean_([a-zA-Z0-9_]+)', r'GLEnums::GetStringBool(\1)',
@@ -3454,7 +3448,7 @@ def GenerateEnumUtils(out_file, input_filenames):
if m:
name = m.group(1)
value = m.group(2)
- if len(value) <= 10:
+ if len(value) <= 10 and value.startswith('0x'):
if not value in dict:
dict[value] = name
# check our own _CHROMIUM macro conflicts with khronos GL headers.
diff --git a/chromium/ui/gl/gl_bindings.h b/chromium/ui/gl/gl_bindings.h
index 429d277d2f5..ae88b309acf 100644
--- a/chromium/ui/gl/gl_bindings.h
+++ b/chromium/ui/gl/gl_bindings.h
@@ -413,6 +413,12 @@
#define GL_FRAMEBUFFER_FLIP_Y_MESA 0x8BBB
#endif /* GL_MESA_framebuffer_flip_y */
+#ifndef GL_KHR_parallel_shader_compile
+#define GL_KHR_parallel_shader_compile 1
+#define GL_MAX_SHADER_COMPILER_THREADS_KHR 0x91B0
+#define GL_COMPLETION_STATUS_KHR 0x91B1
+#endif /* GL_KHR_parallel_shader_compile */
+
#define GL_GLEXT_PROTOTYPES 1
#if defined(OS_WIN)
@@ -434,6 +440,8 @@
#define GL_MAX_VIEWS_OVR 0x9631
#define GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR 0x9633
+#define GL_QUERY_RESULT_AVAILABLE_NO_FLUSH_CHROMIUM_EXT 0x8868
+
// Forward declare EGL types.
typedef uint64_t EGLuint64CHROMIUM;
diff --git a/chromium/ui/gl/gl_bindings_api_autogen_egl.h b/chromium/ui/gl/gl_bindings_api_autogen_egl.h
index 8b1fa45a636..7e3c0efbc6f 100644
--- a/chromium/ui/gl/gl_bindings_api_autogen_egl.h
+++ b/chromium/ui/gl/gl_bindings_api_autogen_egl.h
@@ -150,21 +150,6 @@ EGLBoolean eglPostSubBufferNVFn(EGLDisplay dpy,
EGLint y,
EGLint width,
EGLint height) override;
-EGLint eglProgramCacheGetAttribANGLEFn(EGLDisplay dpy, EGLenum attrib) override;
-void eglProgramCachePopulateANGLEFn(EGLDisplay dpy,
- const void* key,
- EGLint keysize,
- const void* binary,
- EGLint binarysize) override;
-void eglProgramCacheQueryANGLEFn(EGLDisplay dpy,
- EGLint index,
- void* key,
- EGLint* keysize,
- void* binary,
- EGLint* binarysize) override;
-EGLint eglProgramCacheResizeANGLEFn(EGLDisplay dpy,
- EGLint limit,
- EGLenum mode) override;
EGLenum eglQueryAPIFn(void) override;
EGLBoolean eglQueryContextFn(EGLDisplay dpy,
EGLContext ctx,
@@ -192,6 +177,9 @@ EGLBoolean eglReleaseTexImageFn(EGLDisplay dpy,
EGLSurface surface,
EGLint buffer) override;
EGLBoolean eglReleaseThreadFn(void) override;
+void eglSetBlobCacheFuncsANDROIDFn(EGLDisplay dpy,
+ EGLSetBlobFuncANDROID set,
+ EGLGetBlobFuncANDROID get) override;
EGLBoolean eglStreamAttribKHRFn(EGLDisplay dpy,
EGLStreamKHR stream,
EGLenum attribute,
diff --git a/chromium/ui/gl/gl_bindings_api_autogen_gl.h b/chromium/ui/gl/gl_bindings_api_autogen_gl.h
index c6c69b1428d..2247ae06d71 100644
--- a/chromium/ui/gl/gl_bindings_api_autogen_gl.h
+++ b/chromium/ui/gl/gl_bindings_api_autogen_gl.h
@@ -119,7 +119,6 @@ void glColorMaskFn(GLboolean red,
GLboolean blue,
GLboolean alpha) override;
void glCompileShaderFn(GLuint shader) override;
-void glCompressedCopyTextureCHROMIUMFn(GLuint sourceId, GLuint destId) override;
void glCompressedTexImage2DFn(GLenum target,
GLint level,
GLenum internalformat,
@@ -868,6 +867,7 @@ void* glMapBufferRangeFn(GLenum target,
GLbitfield access) override;
void glMatrixLoadfEXTFn(GLenum matrixMode, const GLfloat* m) override;
void glMatrixLoadIdentityEXTFn(GLenum matrixMode) override;
+void glMaxShaderCompilerThreadsKHRFn(GLuint count) override;
void glMemoryBarrierByRegionFn(GLbitfield barriers) override;
void glMemoryBarrierEXTFn(GLbitfield barriers) override;
void glMinSampleShadingFn(GLfloat value) override;
diff --git a/chromium/ui/gl/gl_bindings_autogen_egl.cc b/chromium/ui/gl/gl_bindings_autogen_egl.cc
index 0c64bd7ea94..42f12de7757 100644
--- a/chromium/ui/gl/gl_bindings_autogen_egl.cc
+++ b/chromium/ui/gl/gl_bindings_autogen_egl.cc
@@ -147,6 +147,8 @@ void DriverEGL::InitializeExtensionBindings() {
gfx::ExtensionSet extensions(gfx::MakeExtensionSet(platform_extensions));
ALLOW_UNUSED_LOCAL(extensions);
+ ext.b_EGL_ANDROID_blob_cache =
+ gfx::HasExtension(extensions, "EGL_ANDROID_blob_cache");
ext.b_EGL_ANDROID_get_frame_timestamps =
gfx::HasExtension(extensions, "EGL_ANDROID_get_frame_timestamps");
ext.b_EGL_ANDROID_get_native_client_buffer =
@@ -155,8 +157,6 @@ void DriverEGL::InitializeExtensionBindings() {
gfx::HasExtension(extensions, "EGL_ANDROID_native_fence_sync");
ext.b_EGL_ANGLE_d3d_share_handle_client_buffer =
gfx::HasExtension(extensions, "EGL_ANGLE_d3d_share_handle_client_buffer");
- ext.b_EGL_ANGLE_program_cache_control =
- gfx::HasExtension(extensions, "EGL_ANGLE_program_cache_control");
ext.b_EGL_ANGLE_query_surface_pointer =
gfx::HasExtension(extensions, "EGL_ANGLE_query_surface_pointer");
ext.b_EGL_ANGLE_stream_producer_d3d_texture =
@@ -283,30 +283,6 @@ void DriverEGL::InitializeExtensionBindings() {
GetGLProcAddress("eglPostSubBufferNV"));
}
- if (ext.b_EGL_ANGLE_program_cache_control) {
- fn.eglProgramCacheGetAttribANGLEFn =
- reinterpret_cast<eglProgramCacheGetAttribANGLEProc>(
- GetGLProcAddress("eglProgramCacheGetAttribANGLE"));
- }
-
- if (ext.b_EGL_ANGLE_program_cache_control) {
- fn.eglProgramCachePopulateANGLEFn =
- reinterpret_cast<eglProgramCachePopulateANGLEProc>(
- GetGLProcAddress("eglProgramCachePopulateANGLE"));
- }
-
- if (ext.b_EGL_ANGLE_program_cache_control) {
- fn.eglProgramCacheQueryANGLEFn =
- reinterpret_cast<eglProgramCacheQueryANGLEProc>(
- GetGLProcAddress("eglProgramCacheQueryANGLE"));
- }
-
- if (ext.b_EGL_ANGLE_program_cache_control) {
- fn.eglProgramCacheResizeANGLEFn =
- reinterpret_cast<eglProgramCacheResizeANGLEProc>(
- GetGLProcAddress("eglProgramCacheResizeANGLE"));
- }
-
if (ext.b_EGL_KHR_stream) {
fn.eglQueryStreamKHRFn = reinterpret_cast<eglQueryStreamKHRProc>(
GetGLProcAddress("eglQueryStreamKHR"));
@@ -323,6 +299,12 @@ void DriverEGL::InitializeExtensionBindings() {
GetGLProcAddress("eglQuerySurfacePointerANGLE"));
}
+ if (ext.b_EGL_ANDROID_blob_cache) {
+ fn.eglSetBlobCacheFuncsANDROIDFn =
+ reinterpret_cast<eglSetBlobCacheFuncsANDROIDProc>(
+ GetGLProcAddress("eglSetBlobCacheFuncsANDROID"));
+ }
+
if (ext.b_EGL_KHR_stream) {
fn.eglStreamAttribKHRFn = reinterpret_cast<eglStreamAttribKHRProc>(
GetGLProcAddress("eglStreamAttribKHR"));
@@ -665,36 +647,6 @@ EGLBoolean EGLApiBase::eglPostSubBufferNVFn(EGLDisplay dpy,
return driver_->fn.eglPostSubBufferNVFn(dpy, surface, x, y, width, height);
}
-EGLint EGLApiBase::eglProgramCacheGetAttribANGLEFn(EGLDisplay dpy,
- EGLenum attrib) {
- return driver_->fn.eglProgramCacheGetAttribANGLEFn(dpy, attrib);
-}
-
-void EGLApiBase::eglProgramCachePopulateANGLEFn(EGLDisplay dpy,
- const void* key,
- EGLint keysize,
- const void* binary,
- EGLint binarysize) {
- driver_->fn.eglProgramCachePopulateANGLEFn(dpy, key, keysize, binary,
- binarysize);
-}
-
-void EGLApiBase::eglProgramCacheQueryANGLEFn(EGLDisplay dpy,
- EGLint index,
- void* key,
- EGLint* keysize,
- void* binary,
- EGLint* binarysize) {
- driver_->fn.eglProgramCacheQueryANGLEFn(dpy, index, key, keysize, binary,
- binarysize);
-}
-
-EGLint EGLApiBase::eglProgramCacheResizeANGLEFn(EGLDisplay dpy,
- EGLint limit,
- EGLenum mode) {
- return driver_->fn.eglProgramCacheResizeANGLEFn(dpy, limit, mode);
-}
-
EGLenum EGLApiBase::eglQueryAPIFn(void) {
return driver_->fn.eglQueryAPIFn();
}
@@ -753,6 +705,12 @@ EGLBoolean EGLApiBase::eglReleaseThreadFn(void) {
return driver_->fn.eglReleaseThreadFn();
}
+void EGLApiBase::eglSetBlobCacheFuncsANDROIDFn(EGLDisplay dpy,
+ EGLSetBlobFuncANDROID set,
+ EGLGetBlobFuncANDROID get) {
+ driver_->fn.eglSetBlobCacheFuncsANDROIDFn(dpy, set, get);
+}
+
EGLBoolean EGLApiBase::eglStreamAttribKHRFn(EGLDisplay dpy,
EGLStreamKHR stream,
EGLenum attribute,
@@ -1184,42 +1142,6 @@ EGLBoolean TraceEGLApi::eglPostSubBufferNVFn(EGLDisplay dpy,
return egl_api_->eglPostSubBufferNVFn(dpy, surface, x, y, width, height);
}
-EGLint TraceEGLApi::eglProgramCacheGetAttribANGLEFn(EGLDisplay dpy,
- EGLenum attrib) {
- TRACE_EVENT_BINARY_EFFICIENT0("gpu",
- "TraceGLAPI::eglProgramCacheGetAttribANGLE")
- return egl_api_->eglProgramCacheGetAttribANGLEFn(dpy, attrib);
-}
-
-void TraceEGLApi::eglProgramCachePopulateANGLEFn(EGLDisplay dpy,
- const void* key,
- EGLint keysize,
- const void* binary,
- EGLint binarysize) {
- TRACE_EVENT_BINARY_EFFICIENT0("gpu",
- "TraceGLAPI::eglProgramCachePopulateANGLE")
- egl_api_->eglProgramCachePopulateANGLEFn(dpy, key, keysize, binary,
- binarysize);
-}
-
-void TraceEGLApi::eglProgramCacheQueryANGLEFn(EGLDisplay dpy,
- EGLint index,
- void* key,
- EGLint* keysize,
- void* binary,
- EGLint* binarysize) {
- TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::eglProgramCacheQueryANGLE")
- egl_api_->eglProgramCacheQueryANGLEFn(dpy, index, key, keysize, binary,
- binarysize);
-}
-
-EGLint TraceEGLApi::eglProgramCacheResizeANGLEFn(EGLDisplay dpy,
- EGLint limit,
- EGLenum mode) {
- TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::eglProgramCacheResizeANGLE")
- return egl_api_->eglProgramCacheResizeANGLEFn(dpy, limit, mode);
-}
-
EGLenum TraceEGLApi::eglQueryAPIFn(void) {
TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::eglQueryAPI")
return egl_api_->eglQueryAPIFn();
@@ -1289,6 +1211,14 @@ EGLBoolean TraceEGLApi::eglReleaseThreadFn(void) {
return egl_api_->eglReleaseThreadFn();
}
+void TraceEGLApi::eglSetBlobCacheFuncsANDROIDFn(EGLDisplay dpy,
+ EGLSetBlobFuncANDROID set,
+ EGLGetBlobFuncANDROID get) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu",
+ "TraceGLAPI::eglSetBlobCacheFuncsANDROID")
+ egl_api_->eglSetBlobCacheFuncsANDROIDFn(dpy, set, get);
+}
+
EGLBoolean TraceEGLApi::eglStreamAttribKHRFn(EGLDisplay dpy,
EGLStreamKHR stream,
EGLenum attribute,
@@ -1929,54 +1859,6 @@ EGLBoolean DebugEGLApi::eglPostSubBufferNVFn(EGLDisplay dpy,
return result;
}
-EGLint DebugEGLApi::eglProgramCacheGetAttribANGLEFn(EGLDisplay dpy,
- EGLenum attrib) {
- GL_SERVICE_LOG("eglProgramCacheGetAttribANGLE"
- << "(" << dpy << ", " << attrib << ")");
- EGLint result = egl_api_->eglProgramCacheGetAttribANGLEFn(dpy, attrib);
- GL_SERVICE_LOG("GL_RESULT: " << result);
- return result;
-}
-
-void DebugEGLApi::eglProgramCachePopulateANGLEFn(EGLDisplay dpy,
- const void* key,
- EGLint keysize,
- const void* binary,
- EGLint binarysize) {
- GL_SERVICE_LOG("eglProgramCachePopulateANGLE"
- << "(" << dpy << ", " << static_cast<const void*>(key) << ", "
- << keysize << ", " << static_cast<const void*>(binary) << ", "
- << binarysize << ")");
- egl_api_->eglProgramCachePopulateANGLEFn(dpy, key, keysize, binary,
- binarysize);
-}
-
-void DebugEGLApi::eglProgramCacheQueryANGLEFn(EGLDisplay dpy,
- EGLint index,
- void* key,
- EGLint* keysize,
- void* binary,
- EGLint* binarysize) {
- GL_SERVICE_LOG("eglProgramCacheQueryANGLE"
- << "(" << dpy << ", " << index << ", "
- << static_cast<const void*>(key) << ", "
- << static_cast<const void*>(keysize) << ", "
- << static_cast<const void*>(binary) << ", "
- << static_cast<const void*>(binarysize) << ")");
- egl_api_->eglProgramCacheQueryANGLEFn(dpy, index, key, keysize, binary,
- binarysize);
-}
-
-EGLint DebugEGLApi::eglProgramCacheResizeANGLEFn(EGLDisplay dpy,
- EGLint limit,
- EGLenum mode) {
- GL_SERVICE_LOG("eglProgramCacheResizeANGLE"
- << "(" << dpy << ", " << limit << ", " << mode << ")");
- EGLint result = egl_api_->eglProgramCacheResizeANGLEFn(dpy, limit, mode);
- GL_SERVICE_LOG("GL_RESULT: " << result);
- return result;
-}
-
EGLenum DebugEGLApi::eglQueryAPIFn(void) {
GL_SERVICE_LOG("eglQueryAPI"
<< "("
@@ -2086,6 +1968,15 @@ EGLBoolean DebugEGLApi::eglReleaseThreadFn(void) {
return result;
}
+void DebugEGLApi::eglSetBlobCacheFuncsANDROIDFn(EGLDisplay dpy,
+ EGLSetBlobFuncANDROID set,
+ EGLGetBlobFuncANDROID get) {
+ GL_SERVICE_LOG("eglSetBlobCacheFuncsANDROID"
+ << "(" << dpy << ", " << reinterpret_cast<const void*>(set)
+ << ", " << reinterpret_cast<const void*>(get) << ")");
+ egl_api_->eglSetBlobCacheFuncsANDROIDFn(dpy, set, get);
+}
+
EGLBoolean DebugEGLApi::eglStreamAttribKHRFn(EGLDisplay dpy,
EGLStreamKHR stream,
EGLenum attribute,
diff --git a/chromium/ui/gl/gl_bindings_autogen_egl.h b/chromium/ui/gl/gl_bindings_autogen_egl.h
index 4ee47ddec6c..4ff1248bec5 100644
--- a/chromium/ui/gl/gl_bindings_autogen_egl.h
+++ b/chromium/ui/gl/gl_bindings_autogen_egl.h
@@ -184,25 +184,6 @@ typedef EGLBoolean(GL_BINDING_CALL* eglPostSubBufferNVProc)(EGLDisplay dpy,
EGLint y,
EGLint width,
EGLint height);
-typedef EGLint(GL_BINDING_CALL* eglProgramCacheGetAttribANGLEProc)(
- EGLDisplay dpy,
- EGLenum attrib);
-typedef void(GL_BINDING_CALL* eglProgramCachePopulateANGLEProc)(
- EGLDisplay dpy,
- const void* key,
- EGLint keysize,
- const void* binary,
- EGLint binarysize);
-typedef void(GL_BINDING_CALL* eglProgramCacheQueryANGLEProc)(
- EGLDisplay dpy,
- EGLint index,
- void* key,
- EGLint* keysize,
- void* binary,
- EGLint* binarysize);
-typedef EGLint(GL_BINDING_CALL* eglProgramCacheResizeANGLEProc)(EGLDisplay dpy,
- EGLint limit,
- EGLenum mode);
typedef EGLenum(GL_BINDING_CALL* eglQueryAPIProc)(void);
typedef EGLBoolean(GL_BINDING_CALL* eglQueryContextProc)(EGLDisplay dpy,
EGLContext ctx,
@@ -234,6 +215,10 @@ typedef EGLBoolean(GL_BINDING_CALL* eglReleaseTexImageProc)(EGLDisplay dpy,
EGLSurface surface,
EGLint buffer);
typedef EGLBoolean(GL_BINDING_CALL* eglReleaseThreadProc)(void);
+typedef void(GL_BINDING_CALL* eglSetBlobCacheFuncsANDROIDProc)(
+ EGLDisplay dpy,
+ EGLSetBlobFuncANDROID set,
+ EGLGetBlobFuncANDROID get);
typedef EGLBoolean(GL_BINDING_CALL* eglStreamAttribKHRProc)(EGLDisplay dpy,
EGLStreamKHR stream,
EGLenum attribute,
@@ -281,11 +266,11 @@ typedef EGLint(GL_BINDING_CALL* eglWaitSyncKHRProc)(EGLDisplay dpy,
struct ExtensionsEGL {
bool b_EGL_EXT_platform_base;
bool b_EGL_KHR_debug;
+ bool b_EGL_ANDROID_blob_cache;
bool b_EGL_ANDROID_get_frame_timestamps;
bool b_EGL_ANDROID_get_native_client_buffer;
bool b_EGL_ANDROID_native_fence_sync;
bool b_EGL_ANGLE_d3d_share_handle_client_buffer;
- bool b_EGL_ANGLE_program_cache_control;
bool b_EGL_ANGLE_query_surface_pointer;
bool b_EGL_ANGLE_stream_producer_d3d_texture;
bool b_EGL_ANGLE_surface_d3d_texture_2d_share_handle;
@@ -355,10 +340,6 @@ struct ProcsEGL {
eglLabelObjectKHRProc eglLabelObjectKHRFn;
eglMakeCurrentProc eglMakeCurrentFn;
eglPostSubBufferNVProc eglPostSubBufferNVFn;
- eglProgramCacheGetAttribANGLEProc eglProgramCacheGetAttribANGLEFn;
- eglProgramCachePopulateANGLEProc eglProgramCachePopulateANGLEFn;
- eglProgramCacheQueryANGLEProc eglProgramCacheQueryANGLEFn;
- eglProgramCacheResizeANGLEProc eglProgramCacheResizeANGLEFn;
eglQueryAPIProc eglQueryAPIFn;
eglQueryContextProc eglQueryContextFn;
eglQueryDebugKHRProc eglQueryDebugKHRFn;
@@ -369,6 +350,7 @@ struct ProcsEGL {
eglQuerySurfacePointerANGLEProc eglQuerySurfacePointerANGLEFn;
eglReleaseTexImageProc eglReleaseTexImageFn;
eglReleaseThreadProc eglReleaseThreadFn;
+ eglSetBlobCacheFuncsANDROIDProc eglSetBlobCacheFuncsANDROIDFn;
eglStreamAttribKHRProc eglStreamAttribKHRFn;
eglStreamConsumerAcquireKHRProc eglStreamConsumerAcquireKHRFn;
eglStreamConsumerGLTextureExternalAttribsNVProc
@@ -543,22 +525,6 @@ class GL_EXPORT EGLApi {
EGLint y,
EGLint width,
EGLint height) = 0;
- virtual EGLint eglProgramCacheGetAttribANGLEFn(EGLDisplay dpy,
- EGLenum attrib) = 0;
- virtual void eglProgramCachePopulateANGLEFn(EGLDisplay dpy,
- const void* key,
- EGLint keysize,
- const void* binary,
- EGLint binarysize) = 0;
- virtual void eglProgramCacheQueryANGLEFn(EGLDisplay dpy,
- EGLint index,
- void* key,
- EGLint* keysize,
- void* binary,
- EGLint* binarysize) = 0;
- virtual EGLint eglProgramCacheResizeANGLEFn(EGLDisplay dpy,
- EGLint limit,
- EGLenum mode) = 0;
virtual EGLenum eglQueryAPIFn(void) = 0;
virtual EGLBoolean eglQueryContextFn(EGLDisplay dpy,
EGLContext ctx,
@@ -586,6 +552,9 @@ class GL_EXPORT EGLApi {
EGLSurface surface,
EGLint buffer) = 0;
virtual EGLBoolean eglReleaseThreadFn(void) = 0;
+ virtual void eglSetBlobCacheFuncsANDROIDFn(EGLDisplay dpy,
+ EGLSetBlobFuncANDROID set,
+ EGLGetBlobFuncANDROID get) = 0;
virtual EGLBoolean eglStreamAttribKHRFn(EGLDisplay dpy,
EGLStreamKHR stream,
EGLenum attribute,
@@ -690,14 +659,6 @@ class GL_EXPORT EGLApi {
#define eglLabelObjectKHR ::gl::g_current_egl_context->eglLabelObjectKHRFn
#define eglMakeCurrent ::gl::g_current_egl_context->eglMakeCurrentFn
#define eglPostSubBufferNV ::gl::g_current_egl_context->eglPostSubBufferNVFn
-#define eglProgramCacheGetAttribANGLE \
- ::gl::g_current_egl_context->eglProgramCacheGetAttribANGLEFn
-#define eglProgramCachePopulateANGLE \
- ::gl::g_current_egl_context->eglProgramCachePopulateANGLEFn
-#define eglProgramCacheQueryANGLE \
- ::gl::g_current_egl_context->eglProgramCacheQueryANGLEFn
-#define eglProgramCacheResizeANGLE \
- ::gl::g_current_egl_context->eglProgramCacheResizeANGLEFn
#define eglQueryAPI ::gl::g_current_egl_context->eglQueryAPIFn
#define eglQueryContext ::gl::g_current_egl_context->eglQueryContextFn
#define eglQueryDebugKHR ::gl::g_current_egl_context->eglQueryDebugKHRFn
@@ -709,6 +670,8 @@ class GL_EXPORT EGLApi {
::gl::g_current_egl_context->eglQuerySurfacePointerANGLEFn
#define eglReleaseTexImage ::gl::g_current_egl_context->eglReleaseTexImageFn
#define eglReleaseThread ::gl::g_current_egl_context->eglReleaseThreadFn
+#define eglSetBlobCacheFuncsANDROID \
+ ::gl::g_current_egl_context->eglSetBlobCacheFuncsANDROIDFn
#define eglStreamAttribKHR ::gl::g_current_egl_context->eglStreamAttribKHRFn
#define eglStreamConsumerAcquireKHR \
::gl::g_current_egl_context->eglStreamConsumerAcquireKHRFn
diff --git a/chromium/ui/gl/gl_bindings_autogen_gl.cc b/chromium/ui/gl/gl_bindings_autogen_gl.cc
index 6fca919e161..9666e7b3320 100644
--- a/chromium/ui/gl/gl_bindings_autogen_gl.cc
+++ b/chromium/ui/gl/gl_bindings_autogen_gl.cc
@@ -334,10 +334,6 @@ void DriverGL::InitializeDynamicBindings(const GLVersionInfo* ver,
gfx::HasExtension(extensions, "GL_ARB_vertex_array_object");
ext.b_GL_CHROMIUM_bind_uniform_location =
gfx::HasExtension(extensions, "GL_CHROMIUM_bind_uniform_location");
- ext.b_GL_CHROMIUM_compressed_copy_texture =
- gfx::HasExtension(extensions, "GL_CHROMIUM_compressed_copy_texture");
- ext.b_GL_CHROMIUM_copy_compressed_texture =
- gfx::HasExtension(extensions, "GL_CHROMIUM_copy_compressed_texture");
ext.b_GL_CHROMIUM_copy_texture =
gfx::HasExtension(extensions, "GL_CHROMIUM_copy_texture");
ext.b_GL_CHROMIUM_framebuffer_mixed_samples =
@@ -400,6 +396,8 @@ void DriverGL::InitializeDynamicBindings(const GLVersionInfo* ver,
ext.b_GL_KHR_blend_equation_advanced =
gfx::HasExtension(extensions, "GL_KHR_blend_equation_advanced");
ext.b_GL_KHR_debug = gfx::HasExtension(extensions, "GL_KHR_debug");
+ ext.b_GL_KHR_parallel_shader_compile =
+ gfx::HasExtension(extensions, "GL_KHR_parallel_shader_compile");
ext.b_GL_KHR_robustness = gfx::HasExtension(extensions, "GL_KHR_robustness");
ext.b_GL_NV_blend_equation_advanced =
gfx::HasExtension(extensions, "GL_NV_blend_equation_advanced");
@@ -617,13 +615,6 @@ void DriverGL::InitializeDynamicBindings(const GLVersionInfo* ver,
GetGLProcAddress("glClientWaitSync"));
}
- if (ext.b_GL_CHROMIUM_copy_compressed_texture ||
- ext.b_GL_CHROMIUM_compressed_copy_texture) {
- fn.glCompressedCopyTextureCHROMIUMFn =
- reinterpret_cast<glCompressedCopyTextureCHROMIUMProc>(
- GetGLProcAddress("glCompressedCopyTextureCHROMIUM"));
- }
-
if (ext.b_GL_ANGLE_robust_client_memory) {
fn.glCompressedTexImage2DRobustANGLEFn =
reinterpret_cast<glCompressedTexImage2DRobustANGLEProc>(
@@ -1839,6 +1830,12 @@ void DriverGL::InitializeDynamicBindings(const GLVersionInfo* ver,
GetGLProcAddress("glMatrixLoadIdentityCHROMIUM"));
}
+ if (ext.b_GL_KHR_parallel_shader_compile) {
+ fn.glMaxShaderCompilerThreadsKHRFn =
+ reinterpret_cast<glMaxShaderCompilerThreadsKHRProc>(
+ GetGLProcAddress("glMaxShaderCompilerThreadsKHR"));
+ }
+
if (ver->IsAtLeastGLES(3u, 1u) || ver->IsAtLeastGL(4u, 5u)) {
fn.glMemoryBarrierByRegionFn =
reinterpret_cast<glMemoryBarrierByRegionProc>(
@@ -2918,11 +2915,6 @@ void GLApiBase::glCompileShaderFn(GLuint shader) {
driver_->fn.glCompileShaderFn(shader);
}
-void GLApiBase::glCompressedCopyTextureCHROMIUMFn(GLuint sourceId,
- GLuint destId) {
- driver_->fn.glCompressedCopyTextureCHROMIUMFn(sourceId, destId);
-}
-
void GLApiBase::glCompressedTexImage2DFn(GLenum target,
GLint level,
GLenum internalformat,
@@ -4478,6 +4470,10 @@ void GLApiBase::glMatrixLoadIdentityEXTFn(GLenum matrixMode) {
driver_->fn.glMatrixLoadIdentityEXTFn(matrixMode);
}
+void GLApiBase::glMaxShaderCompilerThreadsKHRFn(GLuint count) {
+ driver_->fn.glMaxShaderCompilerThreadsKHRFn(count);
+}
+
void GLApiBase::glMemoryBarrierByRegionFn(GLbitfield barriers) {
driver_->fn.glMemoryBarrierByRegionFn(barriers);
}
@@ -5995,13 +5991,6 @@ void TraceGLApi::glCompileShaderFn(GLuint shader) {
gl_api_->glCompileShaderFn(shader);
}
-void TraceGLApi::glCompressedCopyTextureCHROMIUMFn(GLuint sourceId,
- GLuint destId) {
- TRACE_EVENT_BINARY_EFFICIENT0("gpu",
- "TraceGLAPI::glCompressedCopyTextureCHROMIUM")
- gl_api_->glCompressedCopyTextureCHROMIUMFn(sourceId, destId);
-}
-
void TraceGLApi::glCompressedTexImage2DFn(GLenum target,
GLint level,
GLenum internalformat,
@@ -7836,6 +7825,12 @@ void TraceGLApi::glMatrixLoadIdentityEXTFn(GLenum matrixMode) {
gl_api_->glMatrixLoadIdentityEXTFn(matrixMode);
}
+void TraceGLApi::glMaxShaderCompilerThreadsKHRFn(GLuint count) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu",
+ "TraceGLAPI::glMaxShaderCompilerThreadsKHR")
+ gl_api_->glMaxShaderCompilerThreadsKHRFn(count);
+}
+
void TraceGLApi::glMemoryBarrierByRegionFn(GLbitfield barriers) {
TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glMemoryBarrierByRegion")
gl_api_->glMemoryBarrierByRegionFn(barriers);
@@ -9638,13 +9633,6 @@ void DebugGLApi::glCompileShaderFn(GLuint shader) {
gl_api_->glCompileShaderFn(shader);
}
-void DebugGLApi::glCompressedCopyTextureCHROMIUMFn(GLuint sourceId,
- GLuint destId) {
- GL_SERVICE_LOG("glCompressedCopyTextureCHROMIUM"
- << "(" << sourceId << ", " << destId << ")");
- gl_api_->glCompressedCopyTextureCHROMIUMFn(sourceId, destId);
-}
-
void DebugGLApi::glCompressedTexImage2DFn(GLenum target,
GLint level,
GLenum internalformat,
@@ -12094,6 +12082,12 @@ void DebugGLApi::glMatrixLoadIdentityEXTFn(GLenum matrixMode) {
gl_api_->glMatrixLoadIdentityEXTFn(matrixMode);
}
+void DebugGLApi::glMaxShaderCompilerThreadsKHRFn(GLuint count) {
+ GL_SERVICE_LOG("glMaxShaderCompilerThreadsKHR"
+ << "(" << count << ")");
+ gl_api_->glMaxShaderCompilerThreadsKHRFn(count);
+}
+
void DebugGLApi::glMemoryBarrierByRegionFn(GLbitfield barriers) {
GL_SERVICE_LOG("glMemoryBarrierByRegion"
<< "(" << barriers << ")");
@@ -14209,11 +14203,6 @@ void NoContextGLApi::glCompileShaderFn(GLuint shader) {
NoContextHelper("glCompileShader");
}
-void NoContextGLApi::glCompressedCopyTextureCHROMIUMFn(GLuint sourceId,
- GLuint destId) {
- NoContextHelper("glCompressedCopyTextureCHROMIUM");
-}
-
void NoContextGLApi::glCompressedTexImage2DFn(GLenum target,
GLint level,
GLenum internalformat,
@@ -15740,6 +15729,10 @@ void NoContextGLApi::glMatrixLoadIdentityEXTFn(GLenum matrixMode) {
NoContextHelper("glMatrixLoadIdentityEXT");
}
+void NoContextGLApi::glMaxShaderCompilerThreadsKHRFn(GLuint count) {
+ NoContextHelper("glMaxShaderCompilerThreadsKHR");
+}
+
void NoContextGLApi::glMemoryBarrierByRegionFn(GLbitfield barriers) {
NoContextHelper("glMemoryBarrierByRegion");
}
diff --git a/chromium/ui/gl/gl_bindings_autogen_gl.h b/chromium/ui/gl/gl_bindings_autogen_gl.h
index fe9742ab623..7de89ead0e7 100644
--- a/chromium/ui/gl/gl_bindings_autogen_gl.h
+++ b/chromium/ui/gl/gl_bindings_autogen_gl.h
@@ -136,9 +136,6 @@ typedef void(GL_BINDING_CALL* glColorMaskProc)(GLboolean red,
GLboolean blue,
GLboolean alpha);
typedef void(GL_BINDING_CALL* glCompileShaderProc)(GLuint shader);
-typedef void(GL_BINDING_CALL* glCompressedCopyTextureCHROMIUMProc)(
- GLuint sourceId,
- GLuint destId);
typedef void(GL_BINDING_CALL* glCompressedTexImage2DProc)(GLenum target,
GLint level,
GLenum internalformat,
@@ -1023,6 +1020,7 @@ typedef void*(GL_BINDING_CALL* glMapBufferRangeProc)(GLenum target,
typedef void(GL_BINDING_CALL* glMatrixLoadfEXTProc)(GLenum matrixMode,
const GLfloat* m);
typedef void(GL_BINDING_CALL* glMatrixLoadIdentityEXTProc)(GLenum matrixMode);
+typedef void(GL_BINDING_CALL* glMaxShaderCompilerThreadsKHRProc)(GLuint count);
typedef void(GL_BINDING_CALL* glMemoryBarrierByRegionProc)(GLbitfield barriers);
typedef void(GL_BINDING_CALL* glMemoryBarrierEXTProc)(GLbitfield barriers);
typedef void(GL_BINDING_CALL* glMinSampleShadingProc)(GLfloat value);
@@ -1778,8 +1776,6 @@ struct ExtensionsGL {
bool b_GL_ARB_transform_feedback2;
bool b_GL_ARB_vertex_array_object;
bool b_GL_CHROMIUM_bind_uniform_location;
- bool b_GL_CHROMIUM_compressed_copy_texture;
- bool b_GL_CHROMIUM_copy_compressed_texture;
bool b_GL_CHROMIUM_copy_texture;
bool b_GL_CHROMIUM_framebuffer_mixed_samples;
bool b_GL_CHROMIUM_gles_depth_binding_hack;
@@ -1812,6 +1808,7 @@ struct ExtensionsGL {
bool b_GL_INTEL_framebuffer_CMAA;
bool b_GL_KHR_blend_equation_advanced;
bool b_GL_KHR_debug;
+ bool b_GL_KHR_parallel_shader_compile;
bool b_GL_KHR_robustness;
bool b_GL_NV_blend_equation_advanced;
bool b_GL_NV_fence;
@@ -1871,7 +1868,6 @@ struct ProcsGL {
glClientWaitSyncProc glClientWaitSyncFn;
glColorMaskProc glColorMaskFn;
glCompileShaderProc glCompileShaderFn;
- glCompressedCopyTextureCHROMIUMProc glCompressedCopyTextureCHROMIUMFn;
glCompressedTexImage2DProc glCompressedTexImage2DFn;
glCompressedTexImage2DRobustANGLEProc glCompressedTexImage2DRobustANGLEFn;
glCompressedTexImage3DProc glCompressedTexImage3DFn;
@@ -2116,6 +2112,7 @@ struct ProcsGL {
glMapBufferRangeProc glMapBufferRangeFn;
glMatrixLoadfEXTProc glMatrixLoadfEXTFn;
glMatrixLoadIdentityEXTProc glMatrixLoadIdentityEXTFn;
+ glMaxShaderCompilerThreadsKHRProc glMaxShaderCompilerThreadsKHRFn;
glMemoryBarrierByRegionProc glMemoryBarrierByRegionFn;
glMemoryBarrierEXTProc glMemoryBarrierEXTFn;
glMinSampleShadingProc glMinSampleShadingFn;
@@ -2416,8 +2413,6 @@ class GL_EXPORT GLApi {
GLboolean blue,
GLboolean alpha) = 0;
virtual void glCompileShaderFn(GLuint shader) = 0;
- virtual void glCompressedCopyTextureCHROMIUMFn(GLuint sourceId,
- GLuint destId) = 0;
virtual void glCompressedTexImage2DFn(GLenum target,
GLint level,
GLenum internalformat,
@@ -3194,6 +3189,7 @@ class GL_EXPORT GLApi {
GLbitfield access) = 0;
virtual void glMatrixLoadfEXTFn(GLenum matrixMode, const GLfloat* m) = 0;
virtual void glMatrixLoadIdentityEXTFn(GLenum matrixMode) = 0;
+ virtual void glMaxShaderCompilerThreadsKHRFn(GLuint count) = 0;
virtual void glMemoryBarrierByRegionFn(GLbitfield barriers) = 0;
virtual void glMemoryBarrierEXTFn(GLbitfield barriers) = 0;
virtual void glMinSampleShadingFn(GLfloat value) = 0;
@@ -3916,8 +3912,6 @@ class GL_EXPORT GLApi {
#define glClientWaitSync ::gl::g_current_gl_context->glClientWaitSyncFn
#define glColorMask ::gl::g_current_gl_context->glColorMaskFn
#define glCompileShader ::gl::g_current_gl_context->glCompileShaderFn
-#define glCompressedCopyTextureCHROMIUM \
- ::gl::g_current_gl_context->glCompressedCopyTextureCHROMIUMFn
#define glCompressedTexImage2D \
::gl::g_current_gl_context->glCompressedTexImage2DFn
#define glCompressedTexImage2DRobustANGLE \
@@ -4269,6 +4263,8 @@ class GL_EXPORT GLApi {
#define glMatrixLoadfEXT ::gl::g_current_gl_context->glMatrixLoadfEXTFn
#define glMatrixLoadIdentityEXT \
::gl::g_current_gl_context->glMatrixLoadIdentityEXTFn
+#define glMaxShaderCompilerThreadsKHR \
+ ::gl::g_current_gl_context->glMaxShaderCompilerThreadsKHRFn
#define glMemoryBarrierByRegion \
::gl::g_current_gl_context->glMemoryBarrierByRegionFn
#define glMemoryBarrierEXT ::gl::g_current_gl_context->glMemoryBarrierEXTFn
diff --git a/chromium/ui/gl/gl_bindings_autogen_mock.cc b/chromium/ui/gl/gl_bindings_autogen_mock.cc
index 0be76ca4c53..206df2d9ecb 100644
--- a/chromium/ui/gl/gl_bindings_autogen_mock.cc
+++ b/chromium/ui/gl/gl_bindings_autogen_mock.cc
@@ -472,13 +472,6 @@ void GL_BINDING_CALL MockGLInterface::Mock_glCompileShader(GLuint shader) {
}
void GL_BINDING_CALL
-MockGLInterface::Mock_glCompressedCopyTextureCHROMIUM(GLuint sourceId,
- GLuint destId) {
- MakeGlMockFunctionUnique("glCompressedCopyTextureCHROMIUM");
- interface_->CompressedCopyTextureCHROMIUM(sourceId, destId);
-}
-
-void GL_BINDING_CALL
MockGLInterface::Mock_glCompressedTexImage2D(GLenum target,
GLint level,
GLenum internalformat,
@@ -2942,6 +2935,12 @@ void GL_BINDING_CALL MockGLInterface::Mock_glMatrixLoadfEXT(GLenum matrixMode,
}
void GL_BINDING_CALL
+MockGLInterface::Mock_glMaxShaderCompilerThreadsKHR(GLuint count) {
+ MakeGlMockFunctionUnique("glMaxShaderCompilerThreadsKHR");
+ interface_->MaxShaderCompilerThreadsKHR(count);
+}
+
+void GL_BINDING_CALL
MockGLInterface::Mock_glMemoryBarrier(GLbitfield barriers) {
MakeGlMockFunctionUnique("glMemoryBarrier");
interface_->MemoryBarrierEXT(barriers);
@@ -4926,9 +4925,6 @@ MockGLInterface::GetGLProcAddress(const char* name) {
return reinterpret_cast<GLFunctionPointerType>(Mock_glColorMask);
if (strcmp(name, "glCompileShader") == 0)
return reinterpret_cast<GLFunctionPointerType>(Mock_glCompileShader);
- if (strcmp(name, "glCompressedCopyTextureCHROMIUM") == 0)
- return reinterpret_cast<GLFunctionPointerType>(
- Mock_glCompressedCopyTextureCHROMIUM);
if (strcmp(name, "glCompressedTexImage2D") == 0)
return reinterpret_cast<GLFunctionPointerType>(Mock_glCompressedTexImage2D);
if (strcmp(name, "glCompressedTexImage2DRobustANGLE") == 0)
@@ -5650,6 +5646,9 @@ MockGLInterface::GetGLProcAddress(const char* name) {
return reinterpret_cast<GLFunctionPointerType>(Mock_glMatrixLoadfCHROMIUM);
if (strcmp(name, "glMatrixLoadfEXT") == 0)
return reinterpret_cast<GLFunctionPointerType>(Mock_glMatrixLoadfEXT);
+ if (strcmp(name, "glMaxShaderCompilerThreadsKHR") == 0)
+ return reinterpret_cast<GLFunctionPointerType>(
+ Mock_glMaxShaderCompilerThreadsKHR);
if (strcmp(name, "glMemoryBarrier") == 0)
return reinterpret_cast<GLFunctionPointerType>(Mock_glMemoryBarrier);
if (strcmp(name, "glMemoryBarrierByRegion") == 0)
diff --git a/chromium/ui/gl/gl_bindings_autogen_mock.h b/chromium/ui/gl/gl_bindings_autogen_mock.h
index f6e48b21d9c..42545f14529 100644
--- a/chromium/ui/gl/gl_bindings_autogen_mock.h
+++ b/chromium/ui/gl/gl_bindings_autogen_mock.h
@@ -184,8 +184,6 @@ static void GL_BINDING_CALL Mock_glColorMask(GLboolean red,
GLboolean blue,
GLboolean alpha);
static void GL_BINDING_CALL Mock_glCompileShader(GLuint shader);
-static void GL_BINDING_CALL
-Mock_glCompressedCopyTextureCHROMIUM(GLuint sourceId, GLuint destId);
static void GL_BINDING_CALL Mock_glCompressedTexImage2D(GLenum target,
GLint level,
GLenum internalformat,
@@ -1234,6 +1232,7 @@ static void GL_BINDING_CALL Mock_glMatrixLoadfCHROMIUM(GLenum matrixMode,
const GLfloat* m);
static void GL_BINDING_CALL Mock_glMatrixLoadfEXT(GLenum matrixMode,
const GLfloat* m);
+static void GL_BINDING_CALL Mock_glMaxShaderCompilerThreadsKHR(GLuint count);
static void GL_BINDING_CALL Mock_glMemoryBarrier(GLbitfield barriers);
static void GL_BINDING_CALL Mock_glMemoryBarrierByRegion(GLbitfield barriers);
static void GL_BINDING_CALL Mock_glMemoryBarrierEXT(GLbitfield barriers);
diff --git a/chromium/ui/gl/gl_context_egl.cc b/chromium/ui/gl/gl_context_egl.cc
index 66d5f54d829..a8f1c62ba78 100644
--- a/chromium/ui/gl/gl_context_egl.cc
+++ b/chromium/ui/gl/gl_context_egl.cc
@@ -27,17 +27,17 @@
#ifndef EGL_CHROMIUM_create_context_bind_generates_resource
#define EGL_CHROMIUM_create_context_bind_generates_resource 1
-#define EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM 0x3AAD
+#define EGL_CONTEXT_BIND_GENERATES_RESOURCE_CHROMIUM 0x33AD
#endif /* EGL_CHROMIUM_create_context_bind_generates_resource */
#ifndef EGL_ANGLE_create_context_webgl_compatibility
#define EGL_ANGLE_create_context_webgl_compatibility 1
-#define EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE 0x3AAC
+#define EGL_CONTEXT_WEBGL_COMPATIBILITY_ANGLE 0x33AC
#endif /* EGL_ANGLE_create_context_webgl_compatibility */
#ifndef EGL_ANGLE_display_texture_share_group
#define EGL_ANGLE_display_texture_share_group 1
-#define EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE 0x3AAF
+#define EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE 0x33AF
#endif /* EGL_ANGLE_display_texture_share_group */
#ifndef EGL_ANGLE_create_context_client_arrays
diff --git a/chromium/ui/gl/gl_context_glx_unittest.cc b/chromium/ui/gl/gl_context_glx_unittest.cc
index c393a792c5f..ce3dedb0f15 100644
--- a/chromium/ui/gl/gl_context_glx_unittest.cc
+++ b/chromium/ui/gl/gl_context_glx_unittest.cc
@@ -9,6 +9,7 @@
#include "ui/gfx/x/x11.h"
#include "ui/gfx/x/x11_error_tracker.h"
#include "ui/gfx/x/x11_types.h"
+#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_surface_glx_x11.h"
#include "ui/gl/init/gl_factory.h"
#include "ui/gl/test/gl_image_test_support.h"
diff --git a/chromium/ui/gl/gl_enums_implementation_autogen.h b/chromium/ui/gl/gl_enums_implementation_autogen.h
index 27a69b10cd9..8a576262b60 100644
--- a/chromium/ui/gl/gl_enums_implementation_autogen.h
+++ b/chromium/ui/gl/gl_enums_implementation_autogen.h
@@ -13,6273 +13,4905 @@
static const GLEnums::EnumToString enum_to_string_table[] = {
{
- 0,
- "GL_FALSE",
+ 0x00, "GL_CLOSE_PATH_NV",
},
{
- 0x00,
- "GL_CLOSE_PATH_NV",
+ 0x0000, "GL_POINTS",
},
{
- 0x0000,
- "GL_POINTS",
+ 0x00000000, "GL_PERFQUERY_SINGLE_CONTEXT_INTEL",
},
{
- 0x00000000,
- "GL_PERFQUERY_SINGLE_CONTEXT_INTEL",
+ 0x00000001, "GL_SYNC_FLUSH_COMMANDS_BIT_APPLE",
},
{
- 0x00000001,
- "GL_SYNC_FLUSH_COMMANDS_BIT_APPLE",
+ 0x00000002, "GL_CONTEXT_FLAG_DEBUG_BIT_KHR",
},
{
- 0x00000002,
- "GL_CONTEXT_FLAG_DEBUG_BIT_KHR",
+ 0x00000004, "GL_GEOMETRY_SHADER_BIT_OES",
},
{
- 0x00000004,
- "GL_GEOMETRY_SHADER_BIT_OES",
+ 0x00000008, "GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR",
},
{
- 0x00000008,
- "GL_CONTEXT_FLAG_NO_ERROR_BIT_KHR",
+ 0x00000010, "GL_TESS_EVALUATION_SHADER_BIT_OES",
},
{
- 0x00000010,
- "GL_TESS_EVALUATION_SHADER_BIT_OES",
+ 0x00000020, "GL_COLOR_BUFFER_BIT5_QCOM",
},
{
- 0x00000020,
- "GL_COLOR_BUFFER_BIT5_QCOM",
+ 0x00000040, "GL_COLOR_BUFFER_BIT6_QCOM",
},
{
- 0x00000040,
- "GL_COLOR_BUFFER_BIT6_QCOM",
+ 0x00000080, "GL_COLOR_BUFFER_BIT7_QCOM",
},
{
- 0x00000080,
- "GL_COLOR_BUFFER_BIT7_QCOM",
+ 0x00000100, "GL_DEPTH_BUFFER_BIT",
},
{
- 0x00000100,
- "GL_DEPTH_BUFFER_BIT",
+ 0x00000200, "GL_DEPTH_BUFFER_BIT1_QCOM",
},
{
- 0x00000200,
- "GL_DEPTH_BUFFER_BIT1_QCOM",
+ 0x00000400, "GL_STENCIL_BUFFER_BIT",
},
{
- 0x00000400,
- "GL_STENCIL_BUFFER_BIT",
+ 0x00000800, "GL_DEPTH_BUFFER_BIT3_QCOM",
},
{
- 0x00000800,
- "GL_DEPTH_BUFFER_BIT3_QCOM",
+ 0x00001000, "GL_DEPTH_BUFFER_BIT4_QCOM",
},
{
- 0x00001000,
- "GL_DEPTH_BUFFER_BIT4_QCOM",
+ 0x00002000, "GL_DEPTH_BUFFER_BIT5_QCOM",
},
{
- 0x00002000,
- "GL_DEPTH_BUFFER_BIT5_QCOM",
+ 0x00004000, "GL_COLOR_BUFFER_BIT",
},
{
- 0x00004000,
- "GL_COLOR_BUFFER_BIT",
+ 0x00008000, "GL_COVERAGE_BUFFER_BIT_NV",
},
{
- 0x00008000,
- "GL_COVERAGE_BUFFER_BIT_NV",
+ 0x0001, "GL_LINES",
},
{
- 0x0001,
- "GL_LINES",
+ 0x00010000, "GL_FONT_X_MIN_BOUNDS_BIT_NV",
},
{
- 0x00010000,
- "GL_FONT_X_MIN_BOUNDS_BIT_NV",
+ 0x0002, "GL_LINE_LOOP",
},
{
- 0x0002,
- "GL_LINE_LOOP",
+ 0x00020000, "GL_FONT_Y_MIN_BOUNDS_BIT_NV",
},
{
- 0x00020000,
- "GL_FONT_Y_MIN_BOUNDS_BIT_NV",
+ 0x0003, "GL_LINE_STRIP",
},
{
- 0x0003,
- "GL_LINE_STRIP",
+ 0x0004, "GL_TRIANGLES",
},
{
- 0x0004,
- "GL_TRIANGLES",
+ 0x00040000, "GL_FONT_X_MAX_BOUNDS_BIT_NV",
},
{
- 0x00040000,
- "GL_FONT_X_MAX_BOUNDS_BIT_NV",
+ 0x0005, "GL_TRIANGLE_STRIP",
},
{
- 0x0005,
- "GL_TRIANGLE_STRIP",
+ 0x0006, "GL_TRIANGLE_FAN",
},
{
- 0x0006,
- "GL_TRIANGLE_FAN",
+ 0x0007, "GL_QUADS_OES",
},
{
- 0x0007,
- "GL_QUADS_OES",
+ 0x0008, "GL_MAP_INVALIDATE_BUFFER_BIT_EXT",
},
{
- 0x0008,
- "GL_MAP_INVALIDATE_BUFFER_BIT_EXT",
+ 0x00080000, "GL_FONT_Y_MAX_BOUNDS_BIT_NV",
},
{
- 0x00080000,
- "GL_FONT_Y_MAX_BOUNDS_BIT_NV",
+ 0x000A, "GL_LINES_ADJACENCY_OES",
},
{
- 0x000A,
- "GL_LINES_ADJACENCY_OES",
+ 0x000B, "GL_LINE_STRIP_ADJACENCY_OES",
},
{
- 0x000B,
- "GL_LINE_STRIP_ADJACENCY_OES",
+ 0x000C, "GL_TRIANGLES_ADJACENCY_OES",
},
{
- 0x000C,
- "GL_TRIANGLES_ADJACENCY_OES",
+ 0x000D, "GL_TRIANGLE_STRIP_ADJACENCY_OES",
},
{
- 0x000D,
- "GL_TRIANGLE_STRIP_ADJACENCY_OES",
+ 0x000E, "GL_PATCHES_OES",
},
{
- 0x000E,
- "GL_PATCHES_OES",
+ 0x0010, "GL_MAP_FLUSH_EXPLICIT_BIT_EXT",
},
{
- 0x0010,
- "GL_MAP_FLUSH_EXPLICIT_BIT_EXT",
+ 0x00100000, "GL_FONT_UNITS_PER_EM_BIT_NV",
},
{
- 0x00100000,
- "GL_FONT_UNITS_PER_EM_BIT_NV",
+ 0x0020, "GL_MAP_UNSYNCHRONIZED_BIT_EXT",
},
{
- 0x0020,
- "GL_MAP_UNSYNCHRONIZED_BIT_EXT",
+ 0x00200000, "GL_FONT_ASCENDER_BIT_NV",
},
{
- 0x00200000,
- "GL_FONT_ASCENDER_BIT_NV",
+ 0x0040, "GL_MAP_PERSISTENT_BIT_EXT",
},
{
- 0x0040,
- "GL_MAP_PERSISTENT_BIT_EXT",
+ 0x00400000, "GL_FONT_DESCENDER_BIT_NV",
},
{
- 0x00400000,
- "GL_FONT_DESCENDER_BIT_NV",
+ 0x0080, "GL_MAP_COHERENT_BIT_EXT",
},
{
- 0x0080,
- "GL_MAP_COHERENT_BIT_EXT",
+ 0x00800000, "GL_FONT_HEIGHT_BIT_NV",
},
{
- 0x00800000,
- "GL_FONT_HEIGHT_BIT_NV",
+ 0x01, "GL_BOLD_BIT_NV",
},
{
- 0x01,
- "GL_BOLD_BIT_NV",
+ 0x0100, "GL_DYNAMIC_STORAGE_BIT_EXT",
},
{
- 0x0100,
- "GL_DYNAMIC_STORAGE_BIT_EXT",
+ 0x01000000, "GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV",
},
{
- 0x01000000,
- "GL_FONT_MAX_ADVANCE_WIDTH_BIT_NV",
+ 0x02, "GL_MOVE_TO_NV",
},
{
- 0x02,
- "GL_MOVE_TO_NV",
+ 0x0200, "GL_NEVER",
},
{
- 0x0200,
- "GL_NEVER",
+ 0x02000000, "GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV",
},
{
- 0x02000000,
- "GL_FONT_MAX_ADVANCE_HEIGHT_BIT_NV",
+ 0x0201, "GL_LESS",
},
{
- 0x0201,
- "GL_LESS",
+ 0x0202, "GL_EQUAL",
},
{
- 0x0202,
- "GL_EQUAL",
+ 0x0203, "GL_LEQUAL",
},
{
- 0x0203,
- "GL_LEQUAL",
+ 0x0204, "GL_GREATER",
},
{
- 0x0204,
- "GL_GREATER",
+ 0x0205, "GL_NOTEQUAL",
},
{
- 0x0205,
- "GL_NOTEQUAL",
+ 0x0206, "GL_GEQUAL",
},
{
- 0x0206,
- "GL_GEQUAL",
+ 0x0207, "GL_ALWAYS",
},
{
- 0x0207,
- "GL_ALWAYS",
+ 0x03, "GL_RELATIVE_MOVE_TO_NV",
},
{
- 0x03,
- "GL_RELATIVE_MOVE_TO_NV",
+ 0x0300, "GL_SRC_COLOR",
},
{
- 0x0300,
- "GL_SRC_COLOR",
+ 0x0301, "GL_ONE_MINUS_SRC_COLOR",
},
{
- 0x0301,
- "GL_ONE_MINUS_SRC_COLOR",
+ 0x0302, "GL_SRC_ALPHA",
},
{
- 0x0302,
- "GL_SRC_ALPHA",
+ 0x0303, "GL_ONE_MINUS_SRC_ALPHA",
},
{
- 0x0303,
- "GL_ONE_MINUS_SRC_ALPHA",
+ 0x0304, "GL_DST_ALPHA",
},
{
- 0x0304,
- "GL_DST_ALPHA",
+ 0x0305, "GL_ONE_MINUS_DST_ALPHA",
},
{
- 0x0305,
- "GL_ONE_MINUS_DST_ALPHA",
+ 0x0306, "GL_DST_COLOR",
},
{
- 0x0306,
- "GL_DST_COLOR",
+ 0x0307, "GL_ONE_MINUS_DST_COLOR",
},
{
- 0x0307,
- "GL_ONE_MINUS_DST_COLOR",
+ 0x0308, "GL_SRC_ALPHA_SATURATE",
},
{
- 0x0308,
- "GL_SRC_ALPHA_SATURATE",
+ 0x04, "GL_LINE_TO_NV",
},
{
- 0x04,
- "GL_LINE_TO_NV",
+ 0x04000000, "GL_FONT_UNDERLINE_POSITION_BIT_NV",
},
{
- 0x04000000,
- "GL_FONT_UNDERLINE_POSITION_BIT_NV",
+ 0x0404, "GL_FRONT",
},
{
- 0x0404,
- "GL_FRONT",
+ 0x0405, "GL_BACK",
},
{
- 0x0405,
- "GL_BACK",
+ 0x0408, "GL_FRONT_AND_BACK",
},
{
- 0x0408,
- "GL_FRONT_AND_BACK",
+ 0x05, "GL_RELATIVE_LINE_TO_NV",
},
{
- 0x05,
- "GL_RELATIVE_LINE_TO_NV",
+ 0x0500, "GL_INVALID_ENUM",
},
{
- 0x0500,
- "GL_INVALID_ENUM",
+ 0x0501, "GL_INVALID_VALUE",
},
{
- 0x0501,
- "GL_INVALID_VALUE",
+ 0x0502, "GL_INVALID_OPERATION",
},
{
- 0x0502,
- "GL_INVALID_OPERATION",
+ 0x0503, "GL_STACK_OVERFLOW_KHR",
},
{
- 0x0503,
- "GL_STACK_OVERFLOW_KHR",
+ 0x0504, "GL_STACK_UNDERFLOW_KHR",
},
{
- 0x0504,
- "GL_STACK_UNDERFLOW_KHR",
+ 0x0505, "GL_OUT_OF_MEMORY",
},
{
- 0x0505,
- "GL_OUT_OF_MEMORY",
+ 0x0506, "GL_INVALID_FRAMEBUFFER_OPERATION",
},
{
- 0x0506,
- "GL_INVALID_FRAMEBUFFER_OPERATION",
+ 0x0507, "GL_CONTEXT_LOST_KHR",
},
{
- 0x0507,
- "GL_CONTEXT_LOST_KHR",
+ 0x06, "GL_HORIZONTAL_LINE_TO_NV",
},
{
- 0x06,
- "GL_HORIZONTAL_LINE_TO_NV",
+ 0x07, "GL_RELATIVE_HORIZONTAL_LINE_TO_NV",
},
{
- 0x07,
- "GL_RELATIVE_HORIZONTAL_LINE_TO_NV",
+ 0x08, "GL_VERTICAL_LINE_TO_NV",
},
{
- 0x08,
- "GL_VERTICAL_LINE_TO_NV",
+ 0x08000000, "GL_FONT_UNDERLINE_THICKNESS_BIT_NV",
},
{
- 0x08000000,
- "GL_FONT_UNDERLINE_THICKNESS_BIT_NV",
+ 0x09, "GL_RELATIVE_VERTICAL_LINE_TO_NV",
},
{
- 0x09,
- "GL_RELATIVE_VERTICAL_LINE_TO_NV",
+ 0x0900, "GL_CW",
},
{
- 0x0900,
- "GL_CW",
+ 0x0901, "GL_CCW",
},
{
- 0x0901,
- "GL_CCW",
+ 0x0A, "GL_QUADRATIC_CURVE_TO_NV",
},
{
- 0x0A,
- "GL_QUADRATIC_CURVE_TO_NV",
+ 0x0B, "GL_RELATIVE_QUADRATIC_CURVE_TO_NV",
},
{
- 0x0B,
- "GL_RELATIVE_QUADRATIC_CURVE_TO_NV",
+ 0x0B21, "GL_LINE_WIDTH",
},
{
- 0x0B21,
- "GL_LINE_WIDTH",
+ 0x0B40, "GL_POLYGON_MODE_NV",
},
{
- 0x0B40,
- "GL_POLYGON_MODE_NV",
+ 0x0B44, "GL_CULL_FACE",
},
{
- 0x0B44,
- "GL_CULL_FACE",
+ 0x0B45, "GL_CULL_FACE_MODE",
},
{
- 0x0B45,
- "GL_CULL_FACE_MODE",
+ 0x0B46, "GL_FRONT_FACE",
},
{
- 0x0B46,
- "GL_FRONT_FACE",
+ 0x0B70, "GL_DEPTH_RANGE",
},
{
- 0x0B70,
- "GL_DEPTH_RANGE",
+ 0x0B71, "GL_DEPTH_TEST",
},
{
- 0x0B71,
- "GL_DEPTH_TEST",
+ 0x0B72, "GL_DEPTH_WRITEMASK",
},
{
- 0x0B72,
- "GL_DEPTH_WRITEMASK",
+ 0x0B73, "GL_DEPTH_CLEAR_VALUE",
},
{
- 0x0B73,
- "GL_DEPTH_CLEAR_VALUE",
+ 0x0B74, "GL_DEPTH_FUNC",
},
{
- 0x0B74,
- "GL_DEPTH_FUNC",
+ 0x0B90, "GL_STENCIL_TEST",
},
{
- 0x0B90,
- "GL_STENCIL_TEST",
+ 0x0B91, "GL_STENCIL_CLEAR_VALUE",
},
{
- 0x0B91,
- "GL_STENCIL_CLEAR_VALUE",
+ 0x0B92, "GL_STENCIL_FUNC",
},
{
- 0x0B92,
- "GL_STENCIL_FUNC",
+ 0x0B93, "GL_STENCIL_VALUE_MASK",
},
{
- 0x0B93,
- "GL_STENCIL_VALUE_MASK",
+ 0x0B94, "GL_STENCIL_FAIL",
},
{
- 0x0B94,
- "GL_STENCIL_FAIL",
+ 0x0B95, "GL_STENCIL_PASS_DEPTH_FAIL",
},
{
- 0x0B95,
- "GL_STENCIL_PASS_DEPTH_FAIL",
+ 0x0B96, "GL_STENCIL_PASS_DEPTH_PASS",
},
{
- 0x0B96,
- "GL_STENCIL_PASS_DEPTH_PASS",
+ 0x0B97, "GL_STENCIL_REF",
},
{
- 0x0B97,
- "GL_STENCIL_REF",
+ 0x0B98, "GL_STENCIL_WRITEMASK",
},
{
- 0x0B98,
- "GL_STENCIL_WRITEMASK",
+ 0x0BA2, "GL_VIEWPORT",
},
{
- 0x0BA2,
- "GL_VIEWPORT",
+ 0x0BA3, "GL_PATH_MODELVIEW_STACK_DEPTH_NV",
},
{
- 0x0BA3,
- "GL_PATH_MODELVIEW_STACK_DEPTH_NV",
+ 0x0BA4, "GL_PATH_PROJECTION_STACK_DEPTH_NV",
},
{
- 0x0BA4,
- "GL_PATH_PROJECTION_STACK_DEPTH_NV",
+ 0x0BA6, "GL_PATH_MODELVIEW_MATRIX_NV",
},
{
- 0x0BA6,
- "GL_PATH_MODELVIEW_MATRIX_NV",
+ 0x0BA7, "GL_PATH_PROJECTION_MATRIX_NV",
},
{
- 0x0BA7,
- "GL_PATH_PROJECTION_MATRIX_NV",
+ 0x0BC0, "GL_ALPHA_TEST_QCOM",
},
{
- 0x0BC0,
- "GL_ALPHA_TEST_QCOM",
+ 0x0BC1, "GL_ALPHA_TEST_FUNC_QCOM",
},
{
- 0x0BC1,
- "GL_ALPHA_TEST_FUNC_QCOM",
+ 0x0BC2, "GL_ALPHA_TEST_REF_QCOM",
},
{
- 0x0BC2,
- "GL_ALPHA_TEST_REF_QCOM",
+ 0x0BD0, "GL_DITHER",
},
{
- 0x0BD0,
- "GL_DITHER",
+ 0x0BE2, "GL_BLEND",
},
{
- 0x0BE2,
- "GL_BLEND",
+ 0x0C, "GL_CUBIC_CURVE_TO_NV",
},
{
- 0x0C,
- "GL_CUBIC_CURVE_TO_NV",
+ 0x0C01, "GL_DRAW_BUFFER_EXT",
},
{
- 0x0C01,
- "GL_DRAW_BUFFER_EXT",
+ 0x0C02, "GL_READ_BUFFER_EXT",
},
{
- 0x0C02,
- "GL_READ_BUFFER_EXT",
+ 0x0C10, "GL_SCISSOR_BOX",
},
{
- 0x0C10,
- "GL_SCISSOR_BOX",
+ 0x0C11, "GL_SCISSOR_TEST",
},
{
- 0x0C11,
- "GL_SCISSOR_TEST",
+ 0x0C22, "GL_COLOR_CLEAR_VALUE",
},
{
- 0x0C22,
- "GL_COLOR_CLEAR_VALUE",
+ 0x0C23, "GL_COLOR_WRITEMASK",
},
{
- 0x0C23,
- "GL_COLOR_WRITEMASK",
+ 0x0CF2, "GL_UNPACK_ROW_LENGTH_EXT",
},
{
- 0x0CF2,
- "GL_UNPACK_ROW_LENGTH_EXT",
+ 0x0CF3, "GL_UNPACK_SKIP_ROWS_EXT",
},
{
- 0x0CF3,
- "GL_UNPACK_SKIP_ROWS_EXT",
+ 0x0CF4, "GL_UNPACK_SKIP_PIXELS_EXT",
},
{
- 0x0CF4,
- "GL_UNPACK_SKIP_PIXELS_EXT",
+ 0x0CF5, "GL_UNPACK_ALIGNMENT",
},
{
- 0x0CF5,
- "GL_UNPACK_ALIGNMENT",
+ 0x0D, "GL_RELATIVE_CUBIC_CURVE_TO_NV",
},
{
- 0x0D,
- "GL_RELATIVE_CUBIC_CURVE_TO_NV",
+ 0x0D02, "GL_PACK_ROW_LENGTH",
},
{
- 0x0D02,
- "GL_PACK_ROW_LENGTH",
+ 0x0D03, "GL_PACK_SKIP_ROWS",
},
{
- 0x0D03,
- "GL_PACK_SKIP_ROWS",
+ 0x0D04, "GL_PACK_SKIP_PIXELS",
},
{
- 0x0D04,
- "GL_PACK_SKIP_PIXELS",
+ 0x0D05, "GL_PACK_ALIGNMENT",
},
{
- 0x0D05,
- "GL_PACK_ALIGNMENT",
+ 0x0D32, "GL_MAX_CLIP_DISTANCES_APPLE",
},
{
- 0x0D32,
- "GL_MAX_CLIP_DISTANCES_APPLE",
+ 0x0D33, "GL_MAX_TEXTURE_SIZE",
},
{
- 0x0D33,
- "GL_MAX_TEXTURE_SIZE",
+ 0x0D36, "GL_PATH_MAX_MODELVIEW_STACK_DEPTH_NV",
},
{
- 0x0D36,
- "GL_PATH_MAX_MODELVIEW_STACK_DEPTH_NV",
+ 0x0D38, "GL_PATH_MAX_PROJECTION_STACK_DEPTH_NV",
},
{
- 0x0D38,
- "GL_PATH_MAX_PROJECTION_STACK_DEPTH_NV",
+ 0x0D3A, "GL_MAX_VIEWPORT_DIMS",
},
{
- 0x0D3A,
- "GL_MAX_VIEWPORT_DIMS",
+ 0x0D50, "GL_SUBPIXEL_BITS",
},
{
- 0x0D50,
- "GL_SUBPIXEL_BITS",
+ 0x0D52, "GL_RED_BITS",
},
{
- 0x0D52,
- "GL_RED_BITS",
+ 0x0D53, "GL_GREEN_BITS",
},
{
- 0x0D53,
- "GL_GREEN_BITS",
+ 0x0D54, "GL_BLUE_BITS",
},
{
- 0x0D54,
- "GL_BLUE_BITS",
+ 0x0D55, "GL_ALPHA_BITS",
},
{
- 0x0D55,
- "GL_ALPHA_BITS",
+ 0x0D56, "GL_DEPTH_BITS",
},
{
- 0x0D56,
- "GL_DEPTH_BITS",
+ 0x0D57, "GL_STENCIL_BITS",
},
{
- 0x0D57,
- "GL_STENCIL_BITS",
+ 0x0DE1, "GL_TEXTURE_2D",
},
{
- 0x0DE1,
- "GL_TEXTURE_2D",
+ 0x0E, "GL_SMOOTH_QUADRATIC_CURVE_TO_NV",
},
{
- 0x0E,
- "GL_SMOOTH_QUADRATIC_CURVE_TO_NV",
+ 0x0F, "GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV",
},
{
- 0x0F,
- "GL_RELATIVE_SMOOTH_QUADRATIC_CURVE_TO_NV",
+ 0x1, "GL_CA_LAYER_EDGE_LEFT_CHROMIUM",
},
{
- 0x1,
- "GL_CA_LAYER_EDGE_LEFT_CHROMIUM",
+ 0x10, "GL_SMOOTH_CUBIC_CURVE_TO_NV",
},
{
- 0x10,
- "GL_SMOOTH_CUBIC_CURVE_TO_NV",
+ 0x100, "GL_GLYPH_HAS_KERNING_BIT_NV",
},
{
- 0x100,
- "GL_GLYPH_HAS_KERNING_BIT_NV",
+ 0x1000, "GL_TEXTURE_WIDTH",
},
{
- 0x1000,
- "GL_TEXTURE_WIDTH",
+ 0x10000000, "GL_FONT_HAS_KERNING_BIT_NV",
},
{
- 0x10000000,
- "GL_FONT_HAS_KERNING_BIT_NV",
+ 0x1001, "GL_TEXTURE_HEIGHT",
},
{
- 0x1001,
- "GL_TEXTURE_HEIGHT",
+ 0x1003, "GL_TEXTURE_INTERNAL_FORMAT",
},
{
- 0x1003,
- "GL_TEXTURE_INTERNAL_FORMAT",
+ 0x1004, "GL_TEXTURE_BORDER_COLOR_OES",
},
{
- 0x1004,
- "GL_TEXTURE_BORDER_COLOR_OES",
+ 0x11, "GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV",
},
{
- 0x11,
- "GL_RELATIVE_SMOOTH_CUBIC_CURVE_TO_NV",
+ 0x1100, "GL_DONT_CARE",
},
{
- 0x1100,
- "GL_DONT_CARE",
+ 0x1101, "GL_FASTEST",
},
{
- 0x1101,
- "GL_FASTEST",
+ 0x1102, "GL_NICEST",
},
{
- 0x1102,
- "GL_NICEST",
+ 0x12, "GL_SMALL_CCW_ARC_TO_NV",
},
{
- 0x12,
- "GL_SMALL_CCW_ARC_TO_NV",
+ 0x13, "GL_RELATIVE_SMALL_CCW_ARC_TO_NV",
},
{
- 0x13,
- "GL_RELATIVE_SMALL_CCW_ARC_TO_NV",
+ 0x14, "GL_SMALL_CW_ARC_TO_NV",
},
{
- 0x14,
- "GL_SMALL_CW_ARC_TO_NV",
+ 0x1400, "GL_BYTE",
},
{
- 0x1400,
- "GL_BYTE",
+ 0x1401, "GL_UNSIGNED_BYTE",
},
{
- 0x1401,
- "GL_UNSIGNED_BYTE",
+ 0x1402, "GL_SHORT",
},
{
- 0x1402,
- "GL_SHORT",
+ 0x1403, "GL_UNSIGNED_SHORT",
},
{
- 0x1403,
- "GL_UNSIGNED_SHORT",
+ 0x1404, "GL_INT",
},
{
- 0x1404,
- "GL_INT",
+ 0x1405, "GL_UNSIGNED_INT",
},
{
- 0x1405,
- "GL_UNSIGNED_INT",
+ 0x1406, "GL_FLOAT",
},
{
- 0x1406,
- "GL_FLOAT",
+ 0x140B, "GL_HALF_FLOAT",
},
{
- 0x140B,
- "GL_HALF_FLOAT",
+ 0x140C, "GL_FIXED",
},
{
- 0x140C,
- "GL_FIXED",
+ 0x140E, "GL_INT64_NV",
},
{
- 0x140E,
- "GL_INT64_NV",
+ 0x140F, "GL_UNSIGNED_INT64_NV",
},
{
- 0x140F,
- "GL_UNSIGNED_INT64_NV",
+ 0x15, "GL_RELATIVE_SMALL_CW_ARC_TO_NV",
},
{
- 0x15,
- "GL_RELATIVE_SMALL_CW_ARC_TO_NV",
+ 0x1506, "GL_XOR_NV",
},
{
- 0x1506,
- "GL_XOR_NV",
+ 0x150A, "GL_INVERT",
},
{
- 0x150A,
- "GL_INVERT",
+ 0x16, "GL_LARGE_CCW_ARC_TO_NV",
},
{
- 0x16,
- "GL_LARGE_CCW_ARC_TO_NV",
+ 0x17, "GL_RELATIVE_LARGE_CCW_ARC_TO_NV",
},
{
- 0x17,
- "GL_RELATIVE_LARGE_CCW_ARC_TO_NV",
+ 0x1700, "GL_PATH_MODELVIEW_NV",
},
{
- 0x1700,
- "GL_PATH_MODELVIEW_NV",
+ 0x1701, "GL_PATH_PROJECTION_NV",
},
{
- 0x1701,
- "GL_PATH_PROJECTION_NV",
+ 0x1702, "GL_TEXTURE",
},
{
- 0x1702,
- "GL_TEXTURE",
+ 0x18, "GL_LARGE_CW_ARC_TO_NV",
},
{
- 0x18,
- "GL_LARGE_CW_ARC_TO_NV",
+ 0x1800, "GL_COLOR_EXT",
},
{
- 0x1800,
- "GL_COLOR_EXT",
+ 0x1801, "GL_DEPTH_EXT",
},
{
- 0x1801,
- "GL_DEPTH_EXT",
+ 0x1802, "GL_STENCIL_EXT",
},
{
- 0x1802,
- "GL_STENCIL_EXT",
+ 0x19, "GL_RELATIVE_LARGE_CW_ARC_TO_NV",
},
{
- 0x19,
- "GL_RELATIVE_LARGE_CW_ARC_TO_NV",
+ 0x1901, "GL_STENCIL_INDEX_OES",
},
{
- 0x1901,
- "GL_STENCIL_INDEX_OES",
+ 0x1902, "GL_DEPTH_COMPONENT",
},
{
- 0x1902,
- "GL_DEPTH_COMPONENT",
+ 0x1903, "GL_RED_EXT",
},
{
- 0x1903,
- "GL_RED_EXT",
+ 0x1904, "GL_GREEN_NV",
},
{
- 0x1904,
- "GL_GREEN_NV",
+ 0x1905, "GL_BLUE_NV",
},
{
- 0x1905,
- "GL_BLUE_NV",
+ 0x1906, "GL_ALPHA",
},
{
- 0x1906,
- "GL_ALPHA",
+ 0x1907, "GL_RGB",
},
{
- 0x1907,
- "GL_RGB",
+ 0x1908, "GL_RGBA",
},
{
- 0x1908,
- "GL_RGBA",
+ 0x1909, "GL_LUMINANCE",
},
{
- 0x1909,
- "GL_LUMINANCE",
+ 0x190A, "GL_LUMINANCE_ALPHA",
},
{
- 0x190A,
- "GL_LUMINANCE_ALPHA",
+ 0x1A, "GL_CONIC_CURVE_TO_NV",
},
{
- 0x1A,
- "GL_CONIC_CURVE_TO_NV",
+ 0x1B, "GL_RELATIVE_CONIC_CURVE_TO_NV",
},
{
- 0x1B,
- "GL_RELATIVE_CONIC_CURVE_TO_NV",
+ 0x1B00, "GL_POINT_NV",
},
{
- 0x1B00,
- "GL_POINT_NV",
+ 0x1B01, "GL_LINE_NV",
},
{
- 0x1B01,
- "GL_LINE_NV",
+ 0x1B02, "GL_FILL_NV",
},
{
- 0x1B02,
- "GL_FILL_NV",
+ 0x1D00, "GL_FLAT_CHROMIUM",
},
{
- 0x1D00,
- "GL_FLAT_CHROMIUM",
+ 0x1E00, "GL_KEEP",
},
{
- 0x1E00,
- "GL_KEEP",
+ 0x1E01, "GL_REPLACE",
},
{
- 0x1E01,
- "GL_REPLACE",
+ 0x1E02, "GL_INCR",
},
{
- 0x1E02,
- "GL_INCR",
+ 0x1E03, "GL_DECR",
},
{
- 0x1E03,
- "GL_DECR",
+ 0x1F00, "GL_VENDOR",
},
{
- 0x1F00,
- "GL_VENDOR",
+ 0x1F01, "GL_RENDERER",
},
{
- 0x1F01,
- "GL_RENDERER",
+ 0x1F02, "GL_VERSION",
},
{
- 0x1F02,
- "GL_VERSION",
+ 0x1F03, "GL_EXTENSIONS",
},
{
- 0x1F03,
- "GL_EXTENSIONS",
+ 0x2, "GL_CA_LAYER_EDGE_RIGHT_CHROMIUM",
},
{
- 0x2,
- "GL_CA_LAYER_EDGE_RIGHT_CHROMIUM",
+ 0x20, "GL_GLYPH_VERTICAL_BEARING_X_BIT_NV",
},
{
- 0x20,
- "GL_GLYPH_VERTICAL_BEARING_X_BIT_NV",
+ 0x20000000, "GL_FONT_NUM_GLYPH_INDICES_BIT_NV",
},
{
- 0x20000000,
- "GL_FONT_NUM_GLYPH_INDICES_BIT_NV",
+ 0x2400, "GL_EYE_LINEAR_CHROMIUM",
},
{
- 0x2400,
- "GL_EYE_LINEAR_CHROMIUM",
+ 0x2401, "GL_OBJECT_LINEAR_CHROMIUM",
},
{
- 0x2401,
- "GL_OBJECT_LINEAR_CHROMIUM",
+ 0x2600, "GL_NEAREST",
},
{
- 0x2600,
- "GL_NEAREST",
+ 0x2601, "GL_LINEAR",
},
{
- 0x2601,
- "GL_LINEAR",
+ 0x2700, "GL_NEAREST_MIPMAP_NEAREST",
},
{
- 0x2700,
- "GL_NEAREST_MIPMAP_NEAREST",
+ 0x2701, "GL_LINEAR_MIPMAP_NEAREST",
},
{
- 0x2701,
- "GL_LINEAR_MIPMAP_NEAREST",
+ 0x2702, "GL_NEAREST_MIPMAP_LINEAR",
},
{
- 0x2702,
- "GL_NEAREST_MIPMAP_LINEAR",
+ 0x2703, "GL_LINEAR_MIPMAP_LINEAR",
},
{
- 0x2703,
- "GL_LINEAR_MIPMAP_LINEAR",
+ 0x2800, "GL_TEXTURE_MAG_FILTER",
},
{
- 0x2800,
- "GL_TEXTURE_MAG_FILTER",
+ 0x2801, "GL_TEXTURE_MIN_FILTER",
},
{
- 0x2801,
- "GL_TEXTURE_MIN_FILTER",
+ 0x2802, "GL_TEXTURE_WRAP_S",
},
{
- 0x2802,
- "GL_TEXTURE_WRAP_S",
+ 0x2803, "GL_TEXTURE_WRAP_T",
},
{
- 0x2803,
- "GL_TEXTURE_WRAP_T",
+ 0x2901, "GL_REPEAT",
},
{
- 0x2901,
- "GL_REPEAT",
+ 0x2A00, "GL_POLYGON_OFFSET_UNITS",
},
{
- 0x2A00,
- "GL_POLYGON_OFFSET_UNITS",
+ 0x2A01, "GL_POLYGON_OFFSET_POINT_NV",
},
{
- 0x2A01,
- "GL_POLYGON_OFFSET_POINT_NV",
+ 0x2A02, "GL_POLYGON_OFFSET_LINE_NV",
},
{
- 0x2A02,
- "GL_POLYGON_OFFSET_LINE_NV",
+ 0x3000, "GL_CLIP_DISTANCE0_APPLE",
},
{
- 0x3000,
- "GL_CLIP_DISTANCE0_APPLE",
+ 0x3001, "GL_CLIP_DISTANCE1_APPLE",
},
{
- 0x3001,
- "GL_CLIP_DISTANCE1_APPLE",
+ 0x3002, "GL_CLIP_DISTANCE2_APPLE",
},
{
- 0x3002,
- "GL_CLIP_DISTANCE2_APPLE",
+ 0x3003, "GL_CLIP_DISTANCE3_APPLE",
},
{
- 0x3003,
- "GL_CLIP_DISTANCE3_APPLE",
+ 0x3004, "GL_CLIP_DISTANCE4_APPLE",
},
{
- 0x3004,
- "GL_CLIP_DISTANCE4_APPLE",
+ 0x3005, "GL_CLIP_DISTANCE5_APPLE",
},
{
- 0x3005,
- "GL_CLIP_DISTANCE5_APPLE",
+ 0x3006, "GL_CLIP_DISTANCE6_APPLE",
},
{
- 0x3006,
- "GL_CLIP_DISTANCE6_APPLE",
+ 0x3007, "GL_CLIP_DISTANCE7_APPLE",
},
{
- 0x3007,
- "GL_CLIP_DISTANCE7_APPLE",
+ 0x300E, "GL_CONTEXT_LOST",
},
{
- 0x300E,
- "GL_CONTEXT_LOST",
+ 0x4, "GL_CA_LAYER_EDGE_BOTTOM_CHROMIUM",
},
{
- 0x4,
- "GL_CA_LAYER_EDGE_BOTTOM_CHROMIUM",
+ 0x40, "GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV",
},
{
- 0x40,
- "GL_GLYPH_VERTICAL_BEARING_Y_BIT_NV",
+ 0x40000000, "GL_MULTISAMPLE_BUFFER_BIT6_QCOM",
},
{
- 0x40000000,
- "GL_MULTISAMPLE_BUFFER_BIT6_QCOM",
+ 0x6000, "GL_SCANOUT_CHROMIUM",
},
{
- 0x6000,
- "GL_SCANOUT_CHROMIUM",
+ 0x6003, "GL_GET_ERROR_QUERY_CHROMIUM",
},
{
- 0x6003,
- "GL_GET_ERROR_QUERY_CHROMIUM",
+ 0x6004, "GL_COMMANDS_ISSUED_CHROMIUM",
},
{
- 0x6004,
- "GL_COMMANDS_ISSUED_CHROMIUM",
+ 0x6006, "GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM",
},
{
- 0x6006,
- "GL_ASYNC_PIXEL_PACK_COMPLETED_CHROMIUM",
+ 0x6007, "GL_LATENCY_QUERY_CHROMIUM",
},
{
- 0x6007,
- "GL_LATENCY_QUERY_CHROMIUM",
+ 0x78EC, "GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM",
},
{
- 0x78EC,
- "GL_PIXEL_UNPACK_TRANSFER_BUFFER_CHROMIUM",
+ 0x78ED, "GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM",
},
{
- 0x78ED,
- "GL_PIXEL_PACK_TRANSFER_BUFFER_CHROMIUM",
+ 0x78EE, "GL_PIXEL_PACK_TRANSFER_BUFFER_BINDING_CHROMIUM",
},
{
- 0x78EE,
- "GL_PIXEL_PACK_TRANSFER_BUFFER_BINDING_CHROMIUM",
+ 0x78EF, "GL_PIXEL_UNPACK_TRANSFER_BUFFER_BINDING_CHROMIUM",
},
{
- 0x78EF,
- "GL_PIXEL_UNPACK_TRANSFER_BUFFER_BINDING_CHROMIUM",
+ 0x78FA, "GL_RGB_YCRCB_420_CHROMIUM",
},
{
- 0x78FA,
- "GL_RGB_YCRCB_420_CHROMIUM",
+ 0x78FB, "GL_RGB_YCBCR_422_CHROMIUM",
},
{
- 0x78FB,
- "GL_RGB_YCBCR_422_CHROMIUM",
+ 0x78FC, "GL_RGB_YCBCR_420V_CHROMIUM",
},
{
- 0x78FC,
- "GL_RGB_YCBCR_420V_CHROMIUM",
+ 0x8, "GL_CA_LAYER_EDGE_TOP_CHROMIUM",
},
{
- 0x8,
- "GL_CA_LAYER_EDGE_TOP_CHROMIUM",
+ 0x80, "GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV",
},
{
- 0x80,
- "GL_GLYPH_VERTICAL_BEARING_ADVANCE_BIT_NV",
+ 0x80000000, "GL_MULTISAMPLE_BUFFER_BIT7_QCOM",
},
{
- 0x80000000,
- "GL_MULTISAMPLE_BUFFER_BIT7_QCOM",
+ 0x8001, "GL_CONSTANT_COLOR",
},
{
- 0x8001,
- "GL_CONSTANT_COLOR",
+ 0x8002, "GL_ONE_MINUS_CONSTANT_COLOR",
},
{
- 0x8002,
- "GL_ONE_MINUS_CONSTANT_COLOR",
+ 0x8003, "GL_CONSTANT_ALPHA",
},
{
- 0x8003,
- "GL_CONSTANT_ALPHA",
+ 0x8004, "GL_ONE_MINUS_CONSTANT_ALPHA",
},
{
- 0x8004,
- "GL_ONE_MINUS_CONSTANT_ALPHA",
+ 0x8005, "GL_BLEND_COLOR",
},
{
- 0x8005,
- "GL_BLEND_COLOR",
+ 0x8006, "GL_FUNC_ADD",
},
{
- 0x8006,
- "GL_FUNC_ADD",
+ 0x8007, "GL_MIN",
},
{
- 0x8007,
- "GL_MIN",
+ 0x8008, "GL_MAX",
},
{
- 0x8008,
- "GL_MAX",
+ 0x8009, "GL_BLEND_EQUATION",
},
{
- 0x8009,
- "GL_BLEND_EQUATION",
+ 0x800A, "GL_FUNC_SUBTRACT",
},
{
- 0x800A,
- "GL_FUNC_SUBTRACT",
+ 0x800B, "GL_FUNC_REVERSE_SUBTRACT",
},
{
- 0x800B,
- "GL_FUNC_REVERSE_SUBTRACT",
+ 0x8033, "GL_UNSIGNED_SHORT_4_4_4_4",
},
{
- 0x8033,
- "GL_UNSIGNED_SHORT_4_4_4_4",
+ 0x8034, "GL_UNSIGNED_SHORT_5_5_5_1",
},
{
- 0x8034,
- "GL_UNSIGNED_SHORT_5_5_5_1",
+ 0x8037, "GL_POLYGON_OFFSET_FILL",
},
{
- 0x8037,
- "GL_POLYGON_OFFSET_FILL",
+ 0x8038, "GL_POLYGON_OFFSET_FACTOR",
},
{
- 0x8038,
- "GL_POLYGON_OFFSET_FACTOR",
+ 0x803C, "GL_ALPHA8_OES",
},
{
- 0x803C,
- "GL_ALPHA8_OES",
+ 0x8040, "GL_LUMINANCE8_OES",
},
{
- 0x8040,
- "GL_LUMINANCE8_OES",
+ 0x8043, "GL_LUMINANCE4_ALPHA4_OES",
},
{
- 0x8043,
- "GL_LUMINANCE4_ALPHA4_OES",
+ 0x8045, "GL_LUMINANCE8_ALPHA8_OES",
},
{
- 0x8045,
- "GL_LUMINANCE8_ALPHA8_OES",
+ 0x8051, "GL_RGB8_OES",
},
{
- 0x8051,
- "GL_RGB8_OES",
+ 0x8052, "GL_RGB10_EXT",
},
{
- 0x8052,
- "GL_RGB10_EXT",
+ 0x8054, "GL_RGB16_EXT",
},
{
- 0x8054,
- "GL_RGB16_EXT",
+ 0x8056, "GL_RGBA4",
},
{
- 0x8056,
- "GL_RGBA4",
+ 0x8057, "GL_RGB5_A1",
},
{
- 0x8057,
- "GL_RGB5_A1",
+ 0x8058, "GL_RGBA8_OES",
},
{
- 0x8058,
- "GL_RGBA8_OES",
+ 0x8059, "GL_RGB10_A2_EXT",
},
{
- 0x8059,
- "GL_RGB10_A2_EXT",
+ 0x805B, "GL_RGBA16_EXT",
},
{
- 0x805B,
- "GL_RGBA16_EXT",
+ 0x805C, "GL_TEXTURE_RED_SIZE",
},
{
- 0x805C,
- "GL_TEXTURE_RED_SIZE",
+ 0x805D, "GL_TEXTURE_GREEN_SIZE",
},
{
- 0x805D,
- "GL_TEXTURE_GREEN_SIZE",
+ 0x805E, "GL_TEXTURE_BLUE_SIZE",
},
{
- 0x805E,
- "GL_TEXTURE_BLUE_SIZE",
+ 0x805F, "GL_TEXTURE_ALPHA_SIZE",
},
{
- 0x805F,
- "GL_TEXTURE_ALPHA_SIZE",
+ 0x8069, "GL_TEXTURE_BINDING_2D",
},
{
- 0x8069,
- "GL_TEXTURE_BINDING_2D",
+ 0x806A, "GL_TEXTURE_BINDING_3D_OES",
},
{
- 0x806A,
- "GL_TEXTURE_BINDING_3D_OES",
+ 0x806D, "GL_UNPACK_SKIP_IMAGES",
},
{
- 0x806D,
- "GL_UNPACK_SKIP_IMAGES",
+ 0x806E, "GL_UNPACK_IMAGE_HEIGHT",
},
{
- 0x806E,
- "GL_UNPACK_IMAGE_HEIGHT",
+ 0x806F, "GL_TEXTURE_3D_OES",
},
{
- 0x806F,
- "GL_TEXTURE_3D_OES",
+ 0x8071, "GL_TEXTURE_DEPTH",
},
{
- 0x8071,
- "GL_TEXTURE_DEPTH",
+ 0x8072, "GL_TEXTURE_WRAP_R_OES",
},
{
- 0x8072,
- "GL_TEXTURE_WRAP_R_OES",
+ 0x8073, "GL_MAX_3D_TEXTURE_SIZE_OES",
},
{
- 0x8073,
- "GL_MAX_3D_TEXTURE_SIZE_OES",
+ 0x8074, "GL_VERTEX_ARRAY_KHR",
},
{
- 0x8074,
- "GL_VERTEX_ARRAY_KHR",
+ 0x809D, "GL_MULTISAMPLE_EXT",
},
{
- 0x809D,
- "GL_MULTISAMPLE_EXT",
+ 0x809E, "GL_SAMPLE_ALPHA_TO_COVERAGE",
},
{
- 0x809E,
- "GL_SAMPLE_ALPHA_TO_COVERAGE",
+ 0x809F, "GL_SAMPLE_ALPHA_TO_ONE_EXT",
},
{
- 0x809F,
- "GL_SAMPLE_ALPHA_TO_ONE_EXT",
+ 0x80A0, "GL_SAMPLE_COVERAGE",
},
{
- 0x80A0,
- "GL_SAMPLE_COVERAGE",
+ 0x80A8, "GL_SAMPLE_BUFFERS",
},
{
- 0x80A8,
- "GL_SAMPLE_BUFFERS",
+ 0x80A9, "GL_SAMPLES",
},
{
- 0x80A9,
- "GL_SAMPLES",
+ 0x80AA, "GL_SAMPLE_COVERAGE_VALUE",
},
{
- 0x80AA,
- "GL_SAMPLE_COVERAGE_VALUE",
+ 0x80AB, "GL_SAMPLE_COVERAGE_INVERT",
},
{
- 0x80AB,
- "GL_SAMPLE_COVERAGE_INVERT",
+ 0x80C8, "GL_BLEND_DST_RGB",
},
{
- 0x80C8,
- "GL_BLEND_DST_RGB",
+ 0x80C9, "GL_BLEND_SRC_RGB",
},
{
- 0x80C9,
- "GL_BLEND_SRC_RGB",
+ 0x80CA, "GL_BLEND_DST_ALPHA",
},
{
- 0x80CA,
- "GL_BLEND_DST_ALPHA",
+ 0x80CB, "GL_BLEND_SRC_ALPHA",
},
{
- 0x80CB,
- "GL_BLEND_SRC_ALPHA",
+ 0x80E1, "GL_BGRA_EXT",
},
{
- 0x80E1,
- "GL_BGRA_EXT",
+ 0x80E8, "GL_MAX_ELEMENTS_VERTICES",
},
{
- 0x80E8,
- "GL_MAX_ELEMENTS_VERTICES",
+ 0x80E9, "GL_MAX_ELEMENTS_INDICES",
},
{
- 0x80E9,
- "GL_MAX_ELEMENTS_INDICES",
+ 0x812D, "GL_CLAMP_TO_BORDER_OES",
},
{
- 0x812D,
- "GL_CLAMP_TO_BORDER_OES",
+ 0x812F, "GL_CLAMP_TO_EDGE",
},
{
- 0x812F,
- "GL_CLAMP_TO_EDGE",
+ 0x813A, "GL_TEXTURE_MIN_LOD",
},
{
- 0x813A,
- "GL_TEXTURE_MIN_LOD",
+ 0x813B, "GL_TEXTURE_MAX_LOD",
},
{
- 0x813B,
- "GL_TEXTURE_MAX_LOD",
+ 0x813C, "GL_TEXTURE_BASE_LEVEL",
},
{
- 0x813C,
- "GL_TEXTURE_BASE_LEVEL",
+ 0x813D, "GL_TEXTURE_MAX_LEVEL_APPLE",
},
{
- 0x813D,
- "GL_TEXTURE_MAX_LEVEL_APPLE",
+ 0x8192, "GL_GENERATE_MIPMAP_HINT",
},
{
- 0x8192,
- "GL_GENERATE_MIPMAP_HINT",
+ 0x81A5, "GL_DEPTH_COMPONENT16",
},
{
- 0x81A5,
- "GL_DEPTH_COMPONENT16",
+ 0x81A6, "GL_DEPTH_COMPONENT24_OES",
},
{
- 0x81A6,
- "GL_DEPTH_COMPONENT24_OES",
+ 0x81A7, "GL_DEPTH_COMPONENT32_OES",
},
{
- 0x81A7,
- "GL_DEPTH_COMPONENT32_OES",
+ 0x8210, "GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT",
},
{
- 0x8210,
- "GL_FRAMEBUFFER_ATTACHMENT_COLOR_ENCODING_EXT",
+ 0x8211, "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT",
},
{
- 0x8211,
- "GL_FRAMEBUFFER_ATTACHMENT_COMPONENT_TYPE_EXT",
+ 0x8212, "GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE",
},
{
- 0x8212,
- "GL_FRAMEBUFFER_ATTACHMENT_RED_SIZE",
+ 0x8213, "GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE",
},
{
- 0x8213,
- "GL_FRAMEBUFFER_ATTACHMENT_GREEN_SIZE",
+ 0x8214, "GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE",
},
{
- 0x8214,
- "GL_FRAMEBUFFER_ATTACHMENT_BLUE_SIZE",
+ 0x8215, "GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE",
},
{
- 0x8215,
- "GL_FRAMEBUFFER_ATTACHMENT_ALPHA_SIZE",
+ 0x8216, "GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE",
},
{
- 0x8216,
- "GL_FRAMEBUFFER_ATTACHMENT_DEPTH_SIZE",
+ 0x8217, "GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE",
},
{
- 0x8217,
- "GL_FRAMEBUFFER_ATTACHMENT_STENCIL_SIZE",
+ 0x8218, "GL_FRAMEBUFFER_DEFAULT",
},
{
- 0x8218,
- "GL_FRAMEBUFFER_DEFAULT",
+ 0x8219, "GL_FRAMEBUFFER_UNDEFINED_OES",
},
{
- 0x8219,
- "GL_FRAMEBUFFER_UNDEFINED_OES",
+ 0x821A, "GL_DEPTH_STENCIL_ATTACHMENT",
},
{
- 0x821A,
- "GL_DEPTH_STENCIL_ATTACHMENT",
+ 0x821B, "GL_MAJOR_VERSION",
},
{
- 0x821B,
- "GL_MAJOR_VERSION",
+ 0x821C, "GL_MINOR_VERSION",
},
{
- 0x821C,
- "GL_MINOR_VERSION",
+ 0x821D, "GL_NUM_EXTENSIONS",
},
{
- 0x821D,
- "GL_NUM_EXTENSIONS",
+ 0x821F, "GL_BUFFER_IMMUTABLE_STORAGE_EXT",
},
{
- 0x821F,
- "GL_BUFFER_IMMUTABLE_STORAGE_EXT",
+ 0x8220, "GL_BUFFER_STORAGE_FLAGS_EXT",
},
{
- 0x8220,
- "GL_BUFFER_STORAGE_FLAGS_EXT",
+ 0x8221, "GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED_OES",
},
{
- 0x8221,
- "GL_PRIMITIVE_RESTART_FOR_PATCHES_SUPPORTED_OES",
+ 0x8227, "GL_RG_EXT",
},
{
- 0x8227,
- "GL_RG_EXT",
+ 0x8228, "GL_RG_INTEGER",
},
{
- 0x8228,
- "GL_RG_INTEGER",
+ 0x8229, "GL_R8_EXT",
},
{
- 0x8229,
- "GL_R8_EXT",
+ 0x822A, "GL_R16_EXT",
},
{
- 0x822A,
- "GL_R16_EXT",
+ 0x822B, "GL_RG8_EXT",
},
{
- 0x822B,
- "GL_RG8_EXT",
+ 0x822C, "GL_RG16_EXT",
},
{
- 0x822C,
- "GL_RG16_EXT",
+ 0x822D, "GL_R16F_EXT",
},
{
- 0x822D,
- "GL_R16F_EXT",
+ 0x822E, "GL_R32F_EXT",
},
{
- 0x822E,
- "GL_R32F_EXT",
+ 0x822F, "GL_RG16F_EXT",
},
{
- 0x822F,
- "GL_RG16F_EXT",
+ 0x8230, "GL_RG32F_EXT",
},
{
- 0x8230,
- "GL_RG32F_EXT",
+ 0x8231, "GL_R8I",
},
{
- 0x8231,
- "GL_R8I",
+ 0x8232, "GL_R8UI",
},
{
- 0x8232,
- "GL_R8UI",
+ 0x8233, "GL_R16I",
},
{
- 0x8233,
- "GL_R16I",
+ 0x8234, "GL_R16UI",
},
{
- 0x8234,
- "GL_R16UI",
+ 0x8235, "GL_R32I",
},
{
- 0x8235,
- "GL_R32I",
+ 0x8236, "GL_R32UI",
},
{
- 0x8236,
- "GL_R32UI",
+ 0x8237, "GL_RG8I",
},
{
- 0x8237,
- "GL_RG8I",
+ 0x8238, "GL_RG8UI",
},
{
- 0x8238,
- "GL_RG8UI",
+ 0x8239, "GL_RG16I",
},
{
- 0x8239,
- "GL_RG16I",
+ 0x823A, "GL_RG16UI",
},
{
- 0x823A,
- "GL_RG16UI",
+ 0x823B, "GL_RG32I",
},
{
- 0x823B,
- "GL_RG32I",
+ 0x823C, "GL_RG32UI",
},
{
- 0x823C,
- "GL_RG32UI",
+ 0x8242, "GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR",
},
{
- 0x8242,
- "GL_DEBUG_OUTPUT_SYNCHRONOUS_KHR",
+ 0x8243, "GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_KHR",
},
{
- 0x8243,
- "GL_DEBUG_NEXT_LOGGED_MESSAGE_LENGTH_KHR",
+ 0x8244, "GL_DEBUG_CALLBACK_FUNCTION_KHR",
},
{
- 0x8244,
- "GL_DEBUG_CALLBACK_FUNCTION_KHR",
+ 0x8245, "GL_DEBUG_CALLBACK_USER_PARAM_KHR",
},
{
- 0x8245,
- "GL_DEBUG_CALLBACK_USER_PARAM_KHR",
+ 0x8246, "GL_DEBUG_SOURCE_API_KHR",
},
{
- 0x8246,
- "GL_DEBUG_SOURCE_API_KHR",
+ 0x8247, "GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR",
},
{
- 0x8247,
- "GL_DEBUG_SOURCE_WINDOW_SYSTEM_KHR",
+ 0x8248, "GL_DEBUG_SOURCE_SHADER_COMPILER_KHR",
},
{
- 0x8248,
- "GL_DEBUG_SOURCE_SHADER_COMPILER_KHR",
+ 0x8249, "GL_DEBUG_SOURCE_THIRD_PARTY_KHR",
},
{
- 0x8249,
- "GL_DEBUG_SOURCE_THIRD_PARTY_KHR",
+ 0x824A, "GL_DEBUG_SOURCE_APPLICATION_KHR",
},
{
- 0x824A,
- "GL_DEBUG_SOURCE_APPLICATION_KHR",
+ 0x824B, "GL_DEBUG_SOURCE_OTHER_KHR",
},
{
- 0x824B,
- "GL_DEBUG_SOURCE_OTHER_KHR",
+ 0x824C, "GL_DEBUG_TYPE_ERROR_KHR",
},
{
- 0x824C,
- "GL_DEBUG_TYPE_ERROR_KHR",
+ 0x824D, "GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR",
},
{
- 0x824D,
- "GL_DEBUG_TYPE_DEPRECATED_BEHAVIOR_KHR",
+ 0x824E, "GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR",
},
{
- 0x824E,
- "GL_DEBUG_TYPE_UNDEFINED_BEHAVIOR_KHR",
+ 0x824F, "GL_DEBUG_TYPE_PORTABILITY_KHR",
},
{
- 0x824F,
- "GL_DEBUG_TYPE_PORTABILITY_KHR",
+ 0x8250, "GL_DEBUG_TYPE_PERFORMANCE_KHR",
},
{
- 0x8250,
- "GL_DEBUG_TYPE_PERFORMANCE_KHR",
+ 0x8251, "GL_DEBUG_TYPE_OTHER_KHR",
},
{
- 0x8251,
- "GL_DEBUG_TYPE_OTHER_KHR",
+ 0x8252, "GL_LOSE_CONTEXT_ON_RESET_KHR",
},
{
- 0x8252,
- "GL_LOSE_CONTEXT_ON_RESET_KHR",
+ 0x8253, "GL_GUILTY_CONTEXT_RESET_KHR",
},
{
- 0x8253,
- "GL_GUILTY_CONTEXT_RESET_KHR",
+ 0x8254, "GL_INNOCENT_CONTEXT_RESET_KHR",
},
{
- 0x8254,
- "GL_INNOCENT_CONTEXT_RESET_KHR",
+ 0x8255, "GL_UNKNOWN_CONTEXT_RESET_KHR",
},
{
- 0x8255,
- "GL_UNKNOWN_CONTEXT_RESET_KHR",
+ 0x8256, "GL_RESET_NOTIFICATION_STRATEGY_KHR",
},
{
- 0x8256,
- "GL_RESET_NOTIFICATION_STRATEGY_KHR",
+ 0x8257, "GL_PROGRAM_BINARY_RETRIEVABLE_HINT",
},
{
- 0x8257,
- "GL_PROGRAM_BINARY_RETRIEVABLE_HINT",
+ 0x8258, "GL_PROGRAM_SEPARABLE_EXT",
},
{
- 0x8258,
- "GL_PROGRAM_SEPARABLE_EXT",
+ 0x8259, "GL_ACTIVE_PROGRAM_EXT",
},
{
- 0x8259,
- "GL_ACTIVE_PROGRAM_EXT",
+ 0x825A, "GL_PROGRAM_PIPELINE_BINDING_EXT",
},
{
- 0x825A,
- "GL_PROGRAM_PIPELINE_BINDING_EXT",
+ 0x825B, "GL_MAX_VIEWPORTS_OES",
},
{
- 0x825B,
- "GL_MAX_VIEWPORTS_OES",
+ 0x825C, "GL_VIEWPORT_SUBPIXEL_BITS_OES",
},
{
- 0x825C,
- "GL_VIEWPORT_SUBPIXEL_BITS_OES",
+ 0x825D, "GL_VIEWPORT_BOUNDS_RANGE_OES",
},
{
- 0x825D,
- "GL_VIEWPORT_BOUNDS_RANGE_OES",
+ 0x825E, "GL_LAYER_PROVOKING_VERTEX_OES",
},
{
- 0x825E,
- "GL_LAYER_PROVOKING_VERTEX_OES",
+ 0x825F, "GL_VIEWPORT_INDEX_PROVOKING_VERTEX_OES",
},
{
- 0x825F,
- "GL_VIEWPORT_INDEX_PROVOKING_VERTEX_OES",
+ 0x8260, "GL_UNDEFINED_VERTEX_OES",
},
{
- 0x8260,
- "GL_UNDEFINED_VERTEX_OES",
+ 0x8261, "GL_NO_RESET_NOTIFICATION_KHR",
},
{
- 0x8261,
- "GL_NO_RESET_NOTIFICATION_KHR",
+ 0x8262, "GL_MAX_COMPUTE_SHARED_MEMORY_SIZE",
},
{
- 0x8262,
- "GL_MAX_COMPUTE_SHARED_MEMORY_SIZE",
+ 0x8263, "GL_MAX_COMPUTE_UNIFORM_COMPONENTS",
},
{
- 0x8263,
- "GL_MAX_COMPUTE_UNIFORM_COMPONENTS",
+ 0x8264, "GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS",
},
{
- 0x8264,
- "GL_MAX_COMPUTE_ATOMIC_COUNTER_BUFFERS",
+ 0x8265, "GL_MAX_COMPUTE_ATOMIC_COUNTERS",
},
{
- 0x8265,
- "GL_MAX_COMPUTE_ATOMIC_COUNTERS",
+ 0x8266, "GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS",
},
{
- 0x8266,
- "GL_MAX_COMBINED_COMPUTE_UNIFORM_COMPONENTS",
+ 0x8267, "GL_COMPUTE_WORK_GROUP_SIZE",
},
{
- 0x8267,
- "GL_COMPUTE_WORK_GROUP_SIZE",
+ 0x8268, "GL_DEBUG_TYPE_MARKER_KHR",
},
{
- 0x8268,
- "GL_DEBUG_TYPE_MARKER_KHR",
+ 0x8269, "GL_DEBUG_TYPE_PUSH_GROUP_KHR",
},
{
- 0x8269,
- "GL_DEBUG_TYPE_PUSH_GROUP_KHR",
+ 0x826A, "GL_DEBUG_TYPE_POP_GROUP_KHR",
},
{
- 0x826A,
- "GL_DEBUG_TYPE_POP_GROUP_KHR",
+ 0x826B, "GL_DEBUG_SEVERITY_NOTIFICATION_KHR",
},
{
- 0x826B,
- "GL_DEBUG_SEVERITY_NOTIFICATION_KHR",
+ 0x826C, "GL_MAX_DEBUG_GROUP_STACK_DEPTH_KHR",
},
{
- 0x826C,
- "GL_MAX_DEBUG_GROUP_STACK_DEPTH_KHR",
+ 0x826D, "GL_DEBUG_GROUP_STACK_DEPTH_KHR",
},
{
- 0x826D,
- "GL_DEBUG_GROUP_STACK_DEPTH_KHR",
+ 0x826E, "GL_MAX_UNIFORM_LOCATIONS",
},
{
- 0x826E,
- "GL_MAX_UNIFORM_LOCATIONS",
+ 0x82D4, "GL_VERTEX_ATTRIB_BINDING",
},
{
- 0x82D4,
- "GL_VERTEX_ATTRIB_BINDING",
+ 0x82D5, "GL_VERTEX_ATTRIB_RELATIVE_OFFSET",
},
{
- 0x82D5,
- "GL_VERTEX_ATTRIB_RELATIVE_OFFSET",
+ 0x82D6, "GL_VERTEX_BINDING_DIVISOR",
},
{
- 0x82D6,
- "GL_VERTEX_BINDING_DIVISOR",
+ 0x82D7, "GL_VERTEX_BINDING_OFFSET",
},
{
- 0x82D7,
- "GL_VERTEX_BINDING_OFFSET",
+ 0x82D8, "GL_VERTEX_BINDING_STRIDE",
},
{
- 0x82D8,
- "GL_VERTEX_BINDING_STRIDE",
+ 0x82D9, "GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET",
},
{
- 0x82D9,
- "GL_MAX_VERTEX_ATTRIB_RELATIVE_OFFSET",
+ 0x82DA, "GL_MAX_VERTEX_ATTRIB_BINDINGS",
},
{
- 0x82DA,
- "GL_MAX_VERTEX_ATTRIB_BINDINGS",
+ 0x82DB, "GL_TEXTURE_VIEW_MIN_LEVEL_OES",
},
{
- 0x82DB,
- "GL_TEXTURE_VIEW_MIN_LEVEL_OES",
+ 0x82DC, "GL_TEXTURE_VIEW_NUM_LEVELS_OES",
},
{
- 0x82DC,
- "GL_TEXTURE_VIEW_NUM_LEVELS_OES",
+ 0x82DD, "GL_TEXTURE_VIEW_MIN_LAYER_OES",
},
{
- 0x82DD,
- "GL_TEXTURE_VIEW_MIN_LAYER_OES",
+ 0x82DE, "GL_TEXTURE_VIEW_NUM_LAYERS_OES",
},
{
- 0x82DE,
- "GL_TEXTURE_VIEW_NUM_LAYERS_OES",
+ 0x82DF, "GL_TEXTURE_IMMUTABLE_LEVELS",
},
{
- 0x82DF,
- "GL_TEXTURE_IMMUTABLE_LEVELS",
+ 0x82E0, "GL_BUFFER_KHR",
},
{
- 0x82E0,
- "GL_BUFFER_KHR",
+ 0x82E1, "GL_SHADER_KHR",
},
{
- 0x82E1,
- "GL_SHADER_KHR",
+ 0x82E2, "GL_PROGRAM_KHR",
},
{
- 0x82E2,
- "GL_PROGRAM_KHR",
+ 0x82E3, "GL_QUERY_KHR",
},
{
- 0x82E3,
- "GL_QUERY_KHR",
+ 0x82E4, "GL_PROGRAM_PIPELINE_KHR",
},
{
- 0x82E4,
- "GL_PROGRAM_PIPELINE_KHR",
+ 0x82E5, "GL_MAX_VERTEX_ATTRIB_STRIDE",
},
{
- 0x82E5,
- "GL_MAX_VERTEX_ATTRIB_STRIDE",
+ 0x82E6, "GL_SAMPLER_KHR",
},
{
- 0x82E6,
- "GL_SAMPLER_KHR",
+ 0x82E8, "GL_MAX_LABEL_LENGTH_KHR",
},
{
- 0x82E8,
- "GL_MAX_LABEL_LENGTH_KHR",
+ 0x82F9, "GL_MAX_CULL_DISTANCES_EXT",
},
{
- 0x82F9,
- "GL_MAX_CULL_DISTANCES_EXT",
+ 0x82FA, "GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT",
},
{
- 0x82FA,
- "GL_MAX_COMBINED_CLIP_AND_CULL_DISTANCES_EXT",
+ 0x82FB, "GL_CONTEXT_RELEASE_BEHAVIOR_KHR",
},
{
- 0x82FB,
- "GL_CONTEXT_RELEASE_BEHAVIOR_KHR",
+ 0x82FC, "GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR",
},
{
- 0x82FC,
- "GL_CONTEXT_RELEASE_BEHAVIOR_FLUSH_KHR",
+ 0x8363, "GL_UNSIGNED_SHORT_5_6_5",
},
{
- 0x8363,
- "GL_UNSIGNED_SHORT_5_6_5",
+ 0x8365, "GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT",
},
{
- 0x8365,
- "GL_UNSIGNED_SHORT_4_4_4_4_REV_EXT",
+ 0x8366, "GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT",
},
{
- 0x8366,
- "GL_UNSIGNED_SHORT_1_5_5_5_REV_EXT",
+ 0x8368, "GL_UNSIGNED_INT_2_10_10_10_REV_EXT",
},
{
- 0x8368,
- "GL_UNSIGNED_INT_2_10_10_10_REV_EXT",
+ 0x8370, "GL_MIRRORED_REPEAT",
},
{
- 0x8370,
- "GL_MIRRORED_REPEAT",
+ 0x83F0, "GL_COMPRESSED_RGB_S3TC_DXT1_EXT",
},
{
- 0x83F0,
- "GL_COMPRESSED_RGB_S3TC_DXT1_EXT",
+ 0x83F1, "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT",
},
{
- 0x83F1,
- "GL_COMPRESSED_RGBA_S3TC_DXT1_EXT",
+ 0x83F2, "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE",
},
{
- 0x83F2,
- "GL_COMPRESSED_RGBA_S3TC_DXT3_ANGLE",
+ 0x83F3, "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE",
},
{
- 0x83F3,
- "GL_COMPRESSED_RGBA_S3TC_DXT5_ANGLE",
+ 0x83F9, "GL_PERFQUERY_DONOT_FLUSH_INTEL",
},
{
- 0x83F9,
- "GL_PERFQUERY_DONOT_FLUSH_INTEL",
+ 0x83FA, "GL_PERFQUERY_FLUSH_INTEL",
},
{
- 0x83FA,
- "GL_PERFQUERY_FLUSH_INTEL",
+ 0x83FB, "GL_PERFQUERY_WAIT_INTEL",
},
{
- 0x83FB,
- "GL_PERFQUERY_WAIT_INTEL",
+ 0x83FC, "GL_BLACKHOLE_RENDER_INTEL",
},
{
- 0x83FE,
- "GL_CONSERVATIVE_RASTERIZATION_INTEL",
+ 0x83FE, "GL_CONSERVATIVE_RASTERIZATION_INTEL",
},
{
- 0x846D,
- "GL_ALIASED_POINT_SIZE_RANGE",
+ 0x846D, "GL_ALIASED_POINT_SIZE_RANGE",
},
{
- 0x846E,
- "GL_ALIASED_LINE_WIDTH_RANGE",
+ 0x846E, "GL_ALIASED_LINE_WIDTH_RANGE",
},
{
- 0x84C0,
- "GL_TEXTURE0",
+ 0x84C0, "GL_TEXTURE0",
},
{
- 0x84C1,
- "GL_TEXTURE1",
+ 0x84C1, "GL_TEXTURE1",
},
{
- 0x84C2,
- "GL_TEXTURE2",
+ 0x84C2, "GL_TEXTURE2",
},
{
- 0x84C3,
- "GL_TEXTURE3",
+ 0x84C3, "GL_TEXTURE3",
},
{
- 0x84C4,
- "GL_TEXTURE4",
+ 0x84C4, "GL_TEXTURE4",
},
{
- 0x84C5,
- "GL_TEXTURE5",
+ 0x84C5, "GL_TEXTURE5",
},
{
- 0x84C6,
- "GL_TEXTURE6",
+ 0x84C6, "GL_TEXTURE6",
},
{
- 0x84C7,
- "GL_TEXTURE7",
+ 0x84C7, "GL_TEXTURE7",
},
{
- 0x84C8,
- "GL_TEXTURE8",
+ 0x84C8, "GL_TEXTURE8",
},
{
- 0x84C9,
- "GL_TEXTURE9",
+ 0x84C9, "GL_TEXTURE9",
},
{
- 0x84CA,
- "GL_TEXTURE10",
+ 0x84CA, "GL_TEXTURE10",
},
{
- 0x84CB,
- "GL_TEXTURE11",
+ 0x84CB, "GL_TEXTURE11",
},
{
- 0x84CC,
- "GL_TEXTURE12",
+ 0x84CC, "GL_TEXTURE12",
},
{
- 0x84CD,
- "GL_TEXTURE13",
+ 0x84CD, "GL_TEXTURE13",
},
{
- 0x84CE,
- "GL_TEXTURE14",
+ 0x84CE, "GL_TEXTURE14",
},
{
- 0x84CF,
- "GL_TEXTURE15",
+ 0x84CF, "GL_TEXTURE15",
},
{
- 0x84D0,
- "GL_TEXTURE16",
+ 0x84D0, "GL_TEXTURE16",
},
{
- 0x84D1,
- "GL_TEXTURE17",
+ 0x84D1, "GL_TEXTURE17",
},
{
- 0x84D2,
- "GL_TEXTURE18",
+ 0x84D2, "GL_TEXTURE18",
},
{
- 0x84D3,
- "GL_TEXTURE19",
+ 0x84D3, "GL_TEXTURE19",
},
{
- 0x84D4,
- "GL_TEXTURE20",
+ 0x84D4, "GL_TEXTURE20",
},
{
- 0x84D5,
- "GL_TEXTURE21",
+ 0x84D5, "GL_TEXTURE21",
},
{
- 0x84D6,
- "GL_TEXTURE22",
+ 0x84D6, "GL_TEXTURE22",
},
{
- 0x84D7,
- "GL_TEXTURE23",
+ 0x84D7, "GL_TEXTURE23",
},
{
- 0x84D8,
- "GL_TEXTURE24",
+ 0x84D8, "GL_TEXTURE24",
},
{
- 0x84D9,
- "GL_TEXTURE25",
+ 0x84D9, "GL_TEXTURE25",
},
{
- 0x84DA,
- "GL_TEXTURE26",
+ 0x84DA, "GL_TEXTURE26",
},
{
- 0x84DB,
- "GL_TEXTURE27",
+ 0x84DB, "GL_TEXTURE27",
},
{
- 0x84DC,
- "GL_TEXTURE28",
+ 0x84DC, "GL_TEXTURE28",
},
{
- 0x84DD,
- "GL_TEXTURE29",
+ 0x84DD, "GL_TEXTURE29",
},
{
- 0x84DE,
- "GL_TEXTURE30",
+ 0x84DE, "GL_TEXTURE30",
},
{
- 0x84DF,
- "GL_TEXTURE31",
+ 0x84DF, "GL_TEXTURE31",
},
{
- 0x84E0,
- "GL_ACTIVE_TEXTURE",
+ 0x84E0, "GL_ACTIVE_TEXTURE",
},
{
- 0x84E3,
- "GL_PATH_TRANSPOSE_MODELVIEW_MATRIX_NV",
+ 0x84E3, "GL_PATH_TRANSPOSE_MODELVIEW_MATRIX_NV",
},
{
- 0x84E4,
- "GL_PATH_TRANSPOSE_PROJECTION_MATRIX_NV",
+ 0x84E4, "GL_PATH_TRANSPOSE_PROJECTION_MATRIX_NV",
},
{
- 0x84E8,
- "GL_MAX_RENDERBUFFER_SIZE",
+ 0x84E8, "GL_MAX_RENDERBUFFER_SIZE",
},
{
- 0x84F2,
- "GL_ALL_COMPLETED_NV",
+ 0x84F2, "GL_ALL_COMPLETED_NV",
},
{
- 0x84F3,
- "GL_FENCE_STATUS_NV",
+ 0x84F3, "GL_FENCE_STATUS_NV",
},
{
- 0x84F4,
- "GL_FENCE_CONDITION_NV",
+ 0x84F4, "GL_FENCE_CONDITION_NV",
},
{
- 0x84F5,
- "GL_TEXTURE_RECTANGLE_ARB",
+ 0x84F5, "GL_TEXTURE_RECTANGLE_ARB",
},
{
- 0x84F6,
- "GL_TEXTURE_BINDING_RECTANGLE_ARB",
+ 0x84F6, "GL_TEXTURE_BINDING_RECTANGLE_ARB",
},
{
- 0x84F7,
- "GL_COMMANDS_COMPLETED_CHROMIUM",
+ 0x84F7, "GL_COMMANDS_COMPLETED_CHROMIUM",
},
{
- 0x84F8,
- "GL_READBACK_SHADOW_COPIES_UPDATED_CHROMIUM",
+ 0x84F8, "GL_READBACK_SHADOW_COPIES_UPDATED_CHROMIUM",
},
{
- 0x84F9,
- "GL_DEPTH_STENCIL_OES",
+ 0x84F9, "GL_DEPTH_STENCIL_OES",
},
{
- 0x84FA,
- "GL_UNSIGNED_INT_24_8_OES",
+ 0x84FA, "GL_UNSIGNED_INT_24_8_OES",
},
{
- 0x84FD,
- "GL_MAX_TEXTURE_LOD_BIAS",
+ 0x84FD, "GL_MAX_TEXTURE_LOD_BIAS",
},
{
- 0x84FE,
- "GL_TEXTURE_MAX_ANISOTROPY_EXT",
+ 0x84FE, "GL_TEXTURE_MAX_ANISOTROPY_EXT",
},
{
- 0x84FF,
- "GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT",
+ 0x84FF, "GL_MAX_TEXTURE_MAX_ANISOTROPY_EXT",
},
{
- 0x8507,
- "GL_INCR_WRAP",
+ 0x8507, "GL_INCR_WRAP",
},
{
- 0x8508,
- "GL_DECR_WRAP",
+ 0x8508, "GL_DECR_WRAP",
},
{
- 0x8513,
- "GL_TEXTURE_CUBE_MAP",
+ 0x8513, "GL_TEXTURE_CUBE_MAP",
},
{
- 0x8514,
- "GL_TEXTURE_BINDING_CUBE_MAP",
+ 0x8514, "GL_TEXTURE_BINDING_CUBE_MAP",
},
{
- 0x8515,
- "GL_TEXTURE_CUBE_MAP_POSITIVE_X",
+ 0x8515, "GL_TEXTURE_CUBE_MAP_POSITIVE_X",
},
{
- 0x8516,
- "GL_TEXTURE_CUBE_MAP_NEGATIVE_X",
+ 0x8516, "GL_TEXTURE_CUBE_MAP_NEGATIVE_X",
},
{
- 0x8517,
- "GL_TEXTURE_CUBE_MAP_POSITIVE_Y",
+ 0x8517, "GL_TEXTURE_CUBE_MAP_POSITIVE_Y",
},
{
- 0x8518,
- "GL_TEXTURE_CUBE_MAP_NEGATIVE_Y",
+ 0x8518, "GL_TEXTURE_CUBE_MAP_NEGATIVE_Y",
},
{
- 0x8519,
- "GL_TEXTURE_CUBE_MAP_POSITIVE_Z",
+ 0x8519, "GL_TEXTURE_CUBE_MAP_POSITIVE_Z",
},
{
- 0x851A,
- "GL_TEXTURE_CUBE_MAP_NEGATIVE_Z",
+ 0x851A, "GL_TEXTURE_CUBE_MAP_NEGATIVE_Z",
},
{
- 0x851C,
- "GL_MAX_CUBE_MAP_TEXTURE_SIZE",
+ 0x851C, "GL_MAX_CUBE_MAP_TEXTURE_SIZE",
},
{
- 0x8576,
- "GL_CONSTANT_CHROMIUM",
+ 0x8576, "GL_CONSTANT_CHROMIUM",
},
{
- 0x8589,
- "GL_SRC1_ALPHA_EXT",
+ 0x8589, "GL_SRC1_ALPHA_EXT",
},
{
- 0x85B5,
- "GL_VERTEX_ARRAY_BINDING_OES",
+ 0x85B5, "GL_VERTEX_ARRAY_BINDING_OES",
},
{
- 0x85BA,
- "GL_UNSIGNED_SHORT_8_8_APPLE",
+ 0x85BA, "GL_UNSIGNED_SHORT_8_8_APPLE",
},
{
- 0x85BB,
- "GL_UNSIGNED_SHORT_8_8_REV_APPLE",
+ 0x85BB, "GL_UNSIGNED_SHORT_8_8_REV_APPLE",
},
{
- 0x8622,
- "GL_VERTEX_ATTRIB_ARRAY_ENABLED",
+ 0x8622, "GL_VERTEX_ATTRIB_ARRAY_ENABLED",
},
{
- 0x8623,
- "GL_VERTEX_ATTRIB_ARRAY_SIZE",
+ 0x8623, "GL_VERTEX_ATTRIB_ARRAY_SIZE",
},
{
- 0x8624,
- "GL_VERTEX_ATTRIB_ARRAY_STRIDE",
+ 0x8624, "GL_VERTEX_ATTRIB_ARRAY_STRIDE",
},
{
- 0x8625,
- "GL_VERTEX_ATTRIB_ARRAY_TYPE",
+ 0x8625, "GL_VERTEX_ATTRIB_ARRAY_TYPE",
},
{
- 0x8626,
- "GL_CURRENT_VERTEX_ATTRIB",
+ 0x8626, "GL_CURRENT_VERTEX_ATTRIB",
},
{
- 0x8645,
- "GL_VERTEX_ATTRIB_ARRAY_POINTER",
+ 0x8645, "GL_VERTEX_ATTRIB_ARRAY_POINTER",
},
{
- 0x86A1,
- "GL_TEXTURE_COMPRESSED",
+ 0x86A1, "GL_TEXTURE_COMPRESSED",
},
{
- 0x86A2,
- "GL_NUM_COMPRESSED_TEXTURE_FORMATS",
+ 0x86A2, "GL_NUM_COMPRESSED_TEXTURE_FORMATS",
},
{
- 0x86A3,
- "GL_COMPRESSED_TEXTURE_FORMATS",
+ 0x86A3, "GL_COMPRESSED_TEXTURE_FORMATS",
},
{
- 0x8740,
- "GL_Z400_BINARY_AMD",
+ 0x8740, "GL_Z400_BINARY_AMD",
},
{
- 0x8741,
- "GL_PROGRAM_BINARY_LENGTH_OES",
+ 0x8741, "GL_PROGRAM_BINARY_LENGTH_OES",
},
{
- 0x8764,
- "GL_BUFFER_SIZE",
+ 0x8743, "GL_MIRROR_CLAMP_TO_EDGE_EXT",
},
{
- 0x8765,
- "GL_BUFFER_USAGE",
+ 0x875F, "GL_PROGRAM_BINARY_FORMAT_MESA",
},
{
- 0x87EE,
- "GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD",
+ 0x8764, "GL_BUFFER_SIZE",
},
{
- 0x87F9,
- "GL_3DC_X_AMD",
+ 0x8765, "GL_BUFFER_USAGE",
},
{
- 0x87FA,
- "GL_3DC_XY_AMD",
+ 0x87EE, "GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD",
},
{
- 0x87FE,
- "GL_NUM_PROGRAM_BINARY_FORMATS_OES",
+ 0x87F9, "GL_3DC_X_AMD",
},
{
- 0x87FF,
- "GL_PROGRAM_BINARY_FORMATS_OES",
+ 0x87FA, "GL_3DC_XY_AMD",
},
{
- 0x8800,
- "GL_STENCIL_BACK_FUNC",
+ 0x87FE, "GL_NUM_PROGRAM_BINARY_FORMATS_OES",
},
{
- 0x8801,
- "GL_STENCIL_BACK_FAIL",
+ 0x87FF, "GL_PROGRAM_BINARY_FORMATS_OES",
},
{
- 0x8802,
- "GL_STENCIL_BACK_PASS_DEPTH_FAIL",
+ 0x8800, "GL_STENCIL_BACK_FUNC",
},
{
- 0x8803,
- "GL_STENCIL_BACK_PASS_DEPTH_PASS",
+ 0x8801, "GL_STENCIL_BACK_FAIL",
},
{
- 0x8814,
- "GL_RGBA32F_EXT",
+ 0x8802, "GL_STENCIL_BACK_PASS_DEPTH_FAIL",
},
{
- 0x8815,
- "GL_RGB32F_EXT",
+ 0x8803, "GL_STENCIL_BACK_PASS_DEPTH_PASS",
},
{
- 0x8816,
- "GL_ALPHA32F_EXT",
+ 0x8814, "GL_RGBA32F_EXT",
},
{
- 0x8818,
- "GL_LUMINANCE32F_EXT",
+ 0x8815, "GL_RGB32F_EXT",
},
{
- 0x8819,
- "GL_LUMINANCE_ALPHA32F_EXT",
+ 0x8816, "GL_ALPHA32F_EXT",
},
{
- 0x881A,
- "GL_RGBA16F_EXT",
+ 0x8818, "GL_LUMINANCE32F_EXT",
},
{
- 0x881B,
- "GL_RGB16F_EXT",
+ 0x8819, "GL_LUMINANCE_ALPHA32F_EXT",
},
{
- 0x881C,
- "GL_ALPHA16F_EXT",
+ 0x881A, "GL_RGBA16F_EXT",
},
{
- 0x881E,
- "GL_LUMINANCE16F_EXT",
+ 0x881B, "GL_RGB16F_EXT",
},
{
- 0x881F,
- "GL_LUMINANCE_ALPHA16F_EXT",
+ 0x881C, "GL_ALPHA16F_EXT",
},
{
- 0x8823,
- "GL_WRITEONLY_RENDERING_QCOM",
+ 0x881E, "GL_LUMINANCE16F_EXT",
},
{
- 0x8824,
- "GL_MAX_DRAW_BUFFERS_EXT",
+ 0x881F, "GL_LUMINANCE_ALPHA16F_EXT",
},
{
- 0x8825,
- "GL_DRAW_BUFFER0_EXT",
+ 0x8823, "GL_WRITEONLY_RENDERING_QCOM",
},
{
- 0x8826,
- "GL_DRAW_BUFFER1_EXT",
+ 0x8824, "GL_MAX_DRAW_BUFFERS_EXT",
},
{
- 0x8827,
- "GL_DRAW_BUFFER2_EXT",
+ 0x8825, "GL_DRAW_BUFFER0_EXT",
},
{
- 0x8828,
- "GL_DRAW_BUFFER3_EXT",
+ 0x8826, "GL_DRAW_BUFFER1_EXT",
},
{
- 0x8829,
- "GL_DRAW_BUFFER4_EXT",
+ 0x8827, "GL_DRAW_BUFFER2_EXT",
},
{
- 0x882A,
- "GL_DRAW_BUFFER5_EXT",
+ 0x8828, "GL_DRAW_BUFFER3_EXT",
},
{
- 0x882B,
- "GL_DRAW_BUFFER6_EXT",
+ 0x8829, "GL_DRAW_BUFFER4_EXT",
},
{
- 0x882C,
- "GL_DRAW_BUFFER7_EXT",
+ 0x882A, "GL_DRAW_BUFFER5_EXT",
},
{
- 0x882D,
- "GL_DRAW_BUFFER8_EXT",
+ 0x882B, "GL_DRAW_BUFFER6_EXT",
},
{
- 0x882E,
- "GL_DRAW_BUFFER9_EXT",
+ 0x882C, "GL_DRAW_BUFFER7_EXT",
},
{
- 0x882F,
- "GL_DRAW_BUFFER10_EXT",
+ 0x882D, "GL_DRAW_BUFFER8_EXT",
},
{
- 0x8830,
- "GL_DRAW_BUFFER11_EXT",
+ 0x882E, "GL_DRAW_BUFFER9_EXT",
},
{
- 0x8831,
- "GL_DRAW_BUFFER12_EXT",
+ 0x882F, "GL_DRAW_BUFFER10_EXT",
},
{
- 0x8832,
- "GL_DRAW_BUFFER13_EXT",
+ 0x8830, "GL_DRAW_BUFFER11_EXT",
},
{
- 0x8833,
- "GL_DRAW_BUFFER14_EXT",
+ 0x8831, "GL_DRAW_BUFFER12_EXT",
},
{
- 0x8834,
- "GL_DRAW_BUFFER15_EXT",
+ 0x8832, "GL_DRAW_BUFFER13_EXT",
},
{
- 0x883D,
- "GL_BLEND_EQUATION_ALPHA",
+ 0x8833, "GL_DRAW_BUFFER14_EXT",
},
{
- 0x884A,
- "GL_TEXTURE_DEPTH_SIZE",
+ 0x8834, "GL_DRAW_BUFFER15_EXT",
},
{
- 0x884C,
- "GL_TEXTURE_COMPARE_MODE_EXT",
+ 0x883D, "GL_BLEND_EQUATION_ALPHA",
},
{
- 0x884D,
- "GL_TEXTURE_COMPARE_FUNC_EXT",
+ 0x884A, "GL_TEXTURE_DEPTH_SIZE",
},
{
- 0x884E,
- "GL_COMPARE_REF_TO_TEXTURE_EXT",
+ 0x884C, "GL_TEXTURE_COMPARE_MODE_EXT",
},
{
- 0x8864,
- "GL_QUERY_COUNTER_BITS_EXT",
+ 0x884D, "GL_TEXTURE_COMPARE_FUNC_EXT",
},
{
- 0x8865,
- "GL_CURRENT_QUERY_EXT",
+ 0x884E, "GL_COMPARE_REF_TO_TEXTURE_EXT",
},
{
- 0x8866,
- "GL_QUERY_RESULT_EXT",
+ 0x8864, "GL_QUERY_COUNTER_BITS_EXT",
},
{
- 0x8867,
- "GL_QUERY_RESULT_AVAILABLE_EXT",
+ 0x8865, "GL_CURRENT_QUERY_EXT",
},
{
- 0x8869,
- "GL_MAX_VERTEX_ATTRIBS",
+ 0x8866, "GL_QUERY_RESULT_EXT",
},
{
- 0x886A,
- "GL_VERTEX_ATTRIB_ARRAY_NORMALIZED",
+ 0x8867, "GL_QUERY_RESULT_AVAILABLE_EXT",
},
{
- 0x886C,
- "GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_OES",
+ 0x8869, "GL_MAX_VERTEX_ATTRIBS",
},
{
- 0x886D,
- "GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_OES",
+ 0x886A, "GL_VERTEX_ATTRIB_ARRAY_NORMALIZED",
},
{
- 0x8872,
- "GL_MAX_TEXTURE_IMAGE_UNITS",
+ 0x886C, "GL_MAX_TESS_CONTROL_INPUT_COMPONENTS_OES",
},
{
- 0x887F,
- "GL_GEOMETRY_SHADER_INVOCATIONS_OES",
+ 0x886D, "GL_MAX_TESS_EVALUATION_INPUT_COMPONENTS_OES",
},
{
- 0x8892,
- "GL_ARRAY_BUFFER",
+ 0x8872, "GL_MAX_TEXTURE_IMAGE_UNITS",
},
{
- 0x8893,
- "GL_ELEMENT_ARRAY_BUFFER",
+ 0x887F, "GL_GEOMETRY_SHADER_INVOCATIONS_OES",
},
{
- 0x8894,
- "GL_ARRAY_BUFFER_BINDING",
+ 0x8892, "GL_ARRAY_BUFFER",
},
{
- 0x8895,
- "GL_ELEMENT_ARRAY_BUFFER_BINDING",
+ 0x8893, "GL_ELEMENT_ARRAY_BUFFER",
},
{
- 0x889F,
- "GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING",
+ 0x8894, "GL_ARRAY_BUFFER_BINDING",
},
{
- 0x88B8,
- "GL_READ_ONLY",
+ 0x8895, "GL_ELEMENT_ARRAY_BUFFER_BINDING",
},
{
- 0x88B9,
- "GL_WRITE_ONLY_OES",
+ 0x889F, "GL_VERTEX_ATTRIB_ARRAY_BUFFER_BINDING",
},
{
- 0x88BA,
- "GL_READ_WRITE",
+ 0x88B8, "GL_READ_ONLY",
},
{
- 0x88BB,
- "GL_BUFFER_ACCESS_OES",
+ 0x88B9, "GL_WRITE_ONLY_OES",
},
{
- 0x88BC,
- "GL_BUFFER_MAPPED_OES",
+ 0x88BA, "GL_READ_WRITE",
},
{
- 0x88BD,
- "GL_BUFFER_MAP_POINTER_OES",
+ 0x88BB, "GL_BUFFER_ACCESS_OES",
},
{
- 0x88BF,
- "GL_TIME_ELAPSED_EXT",
+ 0x88BC, "GL_BUFFER_MAPPED_OES",
},
{
- 0x88E0,
- "GL_STREAM_DRAW",
+ 0x88BD, "GL_BUFFER_MAP_POINTER_OES",
},
{
- 0x88E1,
- "GL_STREAM_READ",
+ 0x88BF, "GL_TIME_ELAPSED_EXT",
},
{
- 0x88E2,
- "GL_STREAM_COPY",
+ 0x88E0, "GL_STREAM_DRAW",
},
{
- 0x88E4,
- "GL_STATIC_DRAW",
+ 0x88E1, "GL_STREAM_READ",
},
{
- 0x88E5,
- "GL_STATIC_READ",
+ 0x88E2, "GL_STREAM_COPY",
},
{
- 0x88E6,
- "GL_STATIC_COPY",
+ 0x88E4, "GL_STATIC_DRAW",
},
{
- 0x88E8,
- "GL_DYNAMIC_DRAW",
+ 0x88E5, "GL_STATIC_READ",
},
{
- 0x88E9,
- "GL_DYNAMIC_READ",
+ 0x88E6, "GL_STATIC_COPY",
},
{
- 0x88EA,
- "GL_DYNAMIC_COPY",
+ 0x88E8, "GL_DYNAMIC_DRAW",
},
{
- 0x88EB,
- "GL_PIXEL_PACK_BUFFER",
+ 0x88E9, "GL_DYNAMIC_READ",
},
{
- 0x88EC,
- "GL_PIXEL_UNPACK_BUFFER",
+ 0x88EA, "GL_DYNAMIC_COPY",
},
{
- 0x88ED,
- "GL_PIXEL_PACK_BUFFER_BINDING",
+ 0x88EB, "GL_PIXEL_PACK_BUFFER_NV",
},
{
- 0x88EE,
- "GL_ETC1_SRGB8_NV",
+ 0x88EC, "GL_PIXEL_UNPACK_BUFFER_NV",
},
{
- 0x88EF,
- "GL_PIXEL_UNPACK_BUFFER_BINDING",
+ 0x88ED, "GL_PIXEL_PACK_BUFFER_BINDING_NV",
},
{
- 0x88F0,
- "GL_DEPTH24_STENCIL8_OES",
+ 0x88EE, "GL_ETC1_SRGB8_NV",
},
{
- 0x88F1,
- "GL_TEXTURE_STENCIL_SIZE",
+ 0x88EF, "GL_PIXEL_UNPACK_BUFFER_BINDING_NV",
},
{
- 0x88F9,
- "GL_SRC1_COLOR_EXT",
+ 0x88F0, "GL_DEPTH24_STENCIL8_OES",
},
{
- 0x88FA,
- "GL_ONE_MINUS_SRC1_COLOR_EXT",
+ 0x88F1, "GL_TEXTURE_STENCIL_SIZE",
},
{
- 0x88FB,
- "GL_ONE_MINUS_SRC1_ALPHA_EXT",
+ 0x88F9, "GL_SRC1_COLOR_EXT",
},
{
- 0x88FC,
- "GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT",
+ 0x88FA, "GL_ONE_MINUS_SRC1_COLOR_EXT",
},
{
- 0x88FD,
- "GL_VERTEX_ATTRIB_ARRAY_INTEGER",
+ 0x88FB, "GL_ONE_MINUS_SRC1_ALPHA_EXT",
},
{
- 0x88FE,
- "GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE",
+ 0x88FC, "GL_MAX_DUAL_SOURCE_DRAW_BUFFERS_EXT",
},
{
- 0x88FF,
- "GL_MAX_ARRAY_TEXTURE_LAYERS",
+ 0x88FD, "GL_VERTEX_ATTRIB_ARRAY_INTEGER",
},
{
- 0x8904,
- "GL_MIN_PROGRAM_TEXEL_OFFSET",
+ 0x88FE, "GL_VERTEX_ATTRIB_ARRAY_DIVISOR_ANGLE",
},
{
- 0x8905,
- "GL_MAX_PROGRAM_TEXEL_OFFSET",
+ 0x88FF, "GL_MAX_ARRAY_TEXTURE_LAYERS",
},
{
- 0x8914,
- "GL_SAMPLES_PASSED_ARB",
+ 0x8904, "GL_MIN_PROGRAM_TEXEL_OFFSET",
},
{
- 0x8916,
- "GL_GEOMETRY_LINKED_VERTICES_OUT_OES",
+ 0x8905, "GL_MAX_PROGRAM_TEXEL_OFFSET",
},
{
- 0x8917,
- "GL_GEOMETRY_LINKED_INPUT_TYPE_OES",
+ 0x8914, "GL_SAMPLES_PASSED_ARB",
},
{
- 0x8918,
- "GL_GEOMETRY_LINKED_OUTPUT_TYPE_OES",
+ 0x8916, "GL_GEOMETRY_LINKED_VERTICES_OUT_OES",
},
{
- 0x8919,
- "GL_SAMPLER_BINDING",
+ 0x8917, "GL_GEOMETRY_LINKED_INPUT_TYPE_OES",
},
{
- 0x8A11,
- "GL_UNIFORM_BUFFER",
+ 0x8918, "GL_GEOMETRY_LINKED_OUTPUT_TYPE_OES",
},
{
- 0x8A1F,
- "GL_RGB_422_APPLE",
+ 0x8919, "GL_SAMPLER_BINDING",
},
{
- 0x8A28,
- "GL_UNIFORM_BUFFER_BINDING",
+ 0x8A11, "GL_UNIFORM_BUFFER",
},
{
- 0x8A29,
- "GL_UNIFORM_BUFFER_START",
+ 0x8A1F, "GL_RGB_422_APPLE",
},
{
- 0x8A2A,
- "GL_UNIFORM_BUFFER_SIZE",
+ 0x8A28, "GL_UNIFORM_BUFFER_BINDING",
},
{
- 0x8A2B,
- "GL_MAX_VERTEX_UNIFORM_BLOCKS",
+ 0x8A29, "GL_UNIFORM_BUFFER_START",
},
{
- 0x8A2C,
- "GL_MAX_GEOMETRY_UNIFORM_BLOCKS_OES",
+ 0x8A2A, "GL_UNIFORM_BUFFER_SIZE",
},
{
- 0x8A2D,
- "GL_MAX_FRAGMENT_UNIFORM_BLOCKS",
+ 0x8A2B, "GL_MAX_VERTEX_UNIFORM_BLOCKS",
},
{
- 0x8A2E,
- "GL_MAX_COMBINED_UNIFORM_BLOCKS",
+ 0x8A2C, "GL_MAX_GEOMETRY_UNIFORM_BLOCKS_OES",
},
{
- 0x8A2F,
- "GL_MAX_UNIFORM_BUFFER_BINDINGS",
+ 0x8A2D, "GL_MAX_FRAGMENT_UNIFORM_BLOCKS",
},
{
- 0x8A30,
- "GL_MAX_UNIFORM_BLOCK_SIZE",
+ 0x8A2E, "GL_MAX_COMBINED_UNIFORM_BLOCKS",
},
{
- 0x8A31,
- "GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS",
+ 0x8A2F, "GL_MAX_UNIFORM_BUFFER_BINDINGS",
},
{
- 0x8A32,
- "GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_OES",
+ 0x8A30, "GL_MAX_UNIFORM_BLOCK_SIZE",
},
{
- 0x8A33,
- "GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS",
+ 0x8A31, "GL_MAX_COMBINED_VERTEX_UNIFORM_COMPONENTS",
},
{
- 0x8A34,
- "GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT",
+ 0x8A32, "GL_MAX_COMBINED_GEOMETRY_UNIFORM_COMPONENTS_OES",
},
{
- 0x8A35,
- "GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH",
+ 0x8A33, "GL_MAX_COMBINED_FRAGMENT_UNIFORM_COMPONENTS",
},
{
- 0x8A36,
- "GL_ACTIVE_UNIFORM_BLOCKS",
+ 0x8A34, "GL_UNIFORM_BUFFER_OFFSET_ALIGNMENT",
},
{
- 0x8A37,
- "GL_UNIFORM_TYPE",
+ 0x8A35, "GL_ACTIVE_UNIFORM_BLOCK_MAX_NAME_LENGTH",
},
{
- 0x8A38,
- "GL_UNIFORM_SIZE",
+ 0x8A36, "GL_ACTIVE_UNIFORM_BLOCKS",
},
{
- 0x8A39,
- "GL_UNIFORM_NAME_LENGTH",
+ 0x8A37, "GL_UNIFORM_TYPE",
},
{
- 0x8A3A,
- "GL_UNIFORM_BLOCK_INDEX",
+ 0x8A38, "GL_UNIFORM_SIZE",
},
{
- 0x8A3B,
- "GL_UNIFORM_OFFSET",
+ 0x8A39, "GL_UNIFORM_NAME_LENGTH",
},
{
- 0x8A3C,
- "GL_UNIFORM_ARRAY_STRIDE",
+ 0x8A3A, "GL_UNIFORM_BLOCK_INDEX",
},
{
- 0x8A3D,
- "GL_UNIFORM_MATRIX_STRIDE",
+ 0x8A3B, "GL_UNIFORM_OFFSET",
},
{
- 0x8A3E,
- "GL_UNIFORM_IS_ROW_MAJOR",
+ 0x8A3C, "GL_UNIFORM_ARRAY_STRIDE",
},
{
- 0x8A3F,
- "GL_UNIFORM_BLOCK_BINDING",
+ 0x8A3D, "GL_UNIFORM_MATRIX_STRIDE",
},
{
- 0x8A40,
- "GL_UNIFORM_BLOCK_DATA_SIZE",
+ 0x8A3E, "GL_UNIFORM_IS_ROW_MAJOR",
},
{
- 0x8A41,
- "GL_UNIFORM_BLOCK_NAME_LENGTH",
+ 0x8A3F, "GL_UNIFORM_BLOCK_BINDING",
},
{
- 0x8A42,
- "GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS",
+ 0x8A40, "GL_UNIFORM_BLOCK_DATA_SIZE",
},
{
- 0x8A43,
- "GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES",
+ 0x8A41, "GL_UNIFORM_BLOCK_NAME_LENGTH",
},
{
- 0x8A44,
- "GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER",
+ 0x8A42, "GL_UNIFORM_BLOCK_ACTIVE_UNIFORMS",
},
{
- 0x8A46,
- "GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER",
+ 0x8A43, "GL_UNIFORM_BLOCK_ACTIVE_UNIFORM_INDICES",
},
{
- 0x8A48,
- "GL_TEXTURE_SRGB_DECODE_EXT",
+ 0x8A44, "GL_UNIFORM_BLOCK_REFERENCED_BY_VERTEX_SHADER",
},
{
- 0x8A49,
- "GL_DECODE_EXT",
+ 0x8A46, "GL_UNIFORM_BLOCK_REFERENCED_BY_FRAGMENT_SHADER",
},
{
- 0x8A4A,
- "GL_SKIP_DECODE_EXT",
+ 0x8A48, "GL_TEXTURE_SRGB_DECODE_EXT",
},
{
- 0x8A4F,
- "GL_PROGRAM_PIPELINE_OBJECT_EXT",
+ 0x8A49, "GL_DECODE_EXT",
},
{
- 0x8A51,
- "GL_RGB_RAW_422_APPLE",
+ 0x8A4A, "GL_SKIP_DECODE_EXT",
},
{
- 0x8A52,
- "GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT",
+ 0x8A4F, "GL_PROGRAM_PIPELINE_OBJECT_EXT",
},
{
- 0x8A53,
- "GL_SYNC_OBJECT_APPLE",
+ 0x8A51, "GL_RGB_RAW_422_APPLE",
},
{
- 0x8A54,
- "GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT",
+ 0x8A52, "GL_FRAGMENT_SHADER_DISCARDS_SAMPLES_EXT",
},
{
- 0x8A55,
- "GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT",
+ 0x8A53, "GL_SYNC_OBJECT_APPLE",
},
{
- 0x8A56,
- "GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT",
+ 0x8A54, "GL_COMPRESSED_SRGB_PVRTC_2BPPV1_EXT",
},
{
- 0x8A57,
- "GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT",
+ 0x8A55, "GL_COMPRESSED_SRGB_PVRTC_4BPPV1_EXT",
},
{
- 0x8AF0,
- "GL_TEXTURE_FILTERING_HINT_CHROMIUM",
+ 0x8A56, "GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV1_EXT",
},
{
- 0x8AF1,
- "GL_COLOR_SPACE_UNSPECIFIED_CHROMIUM",
+ 0x8A57, "GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT",
},
{
- 0x8AF2,
- "GL_COLOR_SPACE_SCRGB_LINEAR_CHROMIUM",
+ 0x8AF0, "GL_TEXTURE_FILTERING_HINT_CHROMIUM",
},
{
- 0x8AF3,
- "GL_COLOR_SPACE_SRGB_CHROMIUM",
+ 0x8AF1, "GL_COLOR_SPACE_UNSPECIFIED_CHROMIUM",
},
{
- 0x8AF4,
- "GL_COLOR_SPACE_DISPLAY_P3_CHROMIUM",
+ 0x8AF2, "GL_COLOR_SPACE_SCRGB_LINEAR_CHROMIUM",
},
{
- 0x8B30,
- "GL_FRAGMENT_SHADER",
+ 0x8AF3, "GL_COLOR_SPACE_SRGB_CHROMIUM",
},
{
- 0x8B31,
- "GL_VERTEX_SHADER",
+ 0x8AF4, "GL_COLOR_SPACE_DISPLAY_P3_CHROMIUM",
},
{
- 0x8B40,
- "GL_PROGRAM_OBJECT_EXT",
+ 0x8B30, "GL_FRAGMENT_SHADER",
},
{
- 0x8B48,
- "GL_SHADER_OBJECT_EXT",
+ 0x8B31, "GL_VERTEX_SHADER",
},
{
- 0x8B49,
- "GL_MAX_FRAGMENT_UNIFORM_COMPONENTS",
+ 0x8B40, "GL_PROGRAM_OBJECT_EXT",
},
{
- 0x8B4A,
- "GL_MAX_VERTEX_UNIFORM_COMPONENTS",
+ 0x8B48, "GL_SHADER_OBJECT_EXT",
},
{
- 0x8B4B,
- "GL_MAX_VARYING_COMPONENTS",
+ 0x8B49, "GL_MAX_FRAGMENT_UNIFORM_COMPONENTS",
},
{
- 0x8B4C,
- "GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS",
+ 0x8B4A, "GL_MAX_VERTEX_UNIFORM_COMPONENTS",
},
{
- 0x8B4D,
- "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS",
+ 0x8B4B, "GL_MAX_VARYING_COMPONENTS",
},
{
- 0x8B4F,
- "GL_SHADER_TYPE",
+ 0x8B4C, "GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS",
},
{
- 0x8B50,
- "GL_FLOAT_VEC2",
+ 0x8B4D, "GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS",
},
{
- 0x8B51,
- "GL_FLOAT_VEC3",
+ 0x8B4F, "GL_SHADER_TYPE",
},
{
- 0x8B52,
- "GL_FLOAT_VEC4",
+ 0x8B50, "GL_FLOAT_VEC2",
},
{
- 0x8B53,
- "GL_INT_VEC2",
+ 0x8B51, "GL_FLOAT_VEC3",
},
{
- 0x8B54,
- "GL_INT_VEC3",
+ 0x8B52, "GL_FLOAT_VEC4",
},
{
- 0x8B55,
- "GL_INT_VEC4",
+ 0x8B53, "GL_INT_VEC2",
},
{
- 0x8B56,
- "GL_BOOL",
+ 0x8B54, "GL_INT_VEC3",
},
{
- 0x8B57,
- "GL_BOOL_VEC2",
+ 0x8B55, "GL_INT_VEC4",
},
{
- 0x8B58,
- "GL_BOOL_VEC3",
+ 0x8B56, "GL_BOOL",
},
{
- 0x8B59,
- "GL_BOOL_VEC4",
+ 0x8B57, "GL_BOOL_VEC2",
},
{
- 0x8B5A,
- "GL_FLOAT_MAT2",
+ 0x8B58, "GL_BOOL_VEC3",
},
{
- 0x8B5B,
- "GL_FLOAT_MAT3",
+ 0x8B59, "GL_BOOL_VEC4",
},
{
- 0x8B5C,
- "GL_FLOAT_MAT4",
+ 0x8B5A, "GL_FLOAT_MAT2",
},
{
- 0x8B5E,
- "GL_SAMPLER_2D",
+ 0x8B5B, "GL_FLOAT_MAT3",
},
{
- 0x8B5F,
- "GL_SAMPLER_3D_OES",
+ 0x8B5C, "GL_FLOAT_MAT4",
},
{
- 0x8B60,
- "GL_SAMPLER_CUBE",
+ 0x8B5E, "GL_SAMPLER_2D",
},
{
- 0x8B62,
- "GL_SAMPLER_2D_SHADOW_EXT",
+ 0x8B5F, "GL_SAMPLER_3D_OES",
},
{
- 0x8B63,
- "GL_SAMPLER_2D_RECT_ARB",
+ 0x8B60, "GL_SAMPLER_CUBE",
},
{
- 0x8B65,
- "GL_FLOAT_MAT2x3_NV",
+ 0x8B62, "GL_SAMPLER_2D_SHADOW_EXT",
},
{
- 0x8B66,
- "GL_FLOAT_MAT2x4_NV",
+ 0x8B63, "GL_SAMPLER_2D_RECT_ARB",
},
{
- 0x8B67,
- "GL_FLOAT_MAT3x2_NV",
+ 0x8B65, "GL_FLOAT_MAT2x3_NV",
},
{
- 0x8B68,
- "GL_FLOAT_MAT3x4_NV",
+ 0x8B66, "GL_FLOAT_MAT2x4_NV",
},
{
- 0x8B69,
- "GL_FLOAT_MAT4x2_NV",
+ 0x8B67, "GL_FLOAT_MAT3x2_NV",
},
{
- 0x8B6A,
- "GL_FLOAT_MAT4x3_NV",
+ 0x8B68, "GL_FLOAT_MAT3x4_NV",
},
{
- 0x8B80,
- "GL_DELETE_STATUS",
+ 0x8B69, "GL_FLOAT_MAT4x2_NV",
},
{
- 0x8B81,
- "GL_COMPILE_STATUS",
+ 0x8B6A, "GL_FLOAT_MAT4x3_NV",
},
{
- 0x8B82,
- "GL_LINK_STATUS",
+ 0x8B80, "GL_DELETE_STATUS",
},
{
- 0x8B83,
- "GL_VALIDATE_STATUS",
+ 0x8B81, "GL_COMPILE_STATUS",
},
{
- 0x8B84,
- "GL_INFO_LOG_LENGTH",
+ 0x8B82, "GL_LINK_STATUS",
},
{
- 0x8B85,
- "GL_ATTACHED_SHADERS",
+ 0x8B83, "GL_VALIDATE_STATUS",
},
{
- 0x8B86,
- "GL_ACTIVE_UNIFORMS",
+ 0x8B84, "GL_INFO_LOG_LENGTH",
},
{
- 0x8B87,
- "GL_ACTIVE_UNIFORM_MAX_LENGTH",
+ 0x8B85, "GL_ATTACHED_SHADERS",
},
{
- 0x8B88,
- "GL_SHADER_SOURCE_LENGTH",
+ 0x8B86, "GL_ACTIVE_UNIFORMS",
},
{
- 0x8B89,
- "GL_ACTIVE_ATTRIBUTES",
+ 0x8B87, "GL_ACTIVE_UNIFORM_MAX_LENGTH",
},
{
- 0x8B8A,
- "GL_ACTIVE_ATTRIBUTE_MAX_LENGTH",
+ 0x8B88, "GL_SHADER_SOURCE_LENGTH",
},
{
- 0x8B8B,
- "GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES",
+ 0x8B89, "GL_ACTIVE_ATTRIBUTES",
},
{
- 0x8B8C,
- "GL_SHADING_LANGUAGE_VERSION",
+ 0x8B8A, "GL_ACTIVE_ATTRIBUTE_MAX_LENGTH",
},
{
- 0x8B8D,
- "GL_CURRENT_PROGRAM",
+ 0x8B8B, "GL_FRAGMENT_SHADER_DERIVATIVE_HINT_OES",
},
{
- 0x8B90,
- "GL_PALETTE4_RGB8_OES",
+ 0x8B8C, "GL_SHADING_LANGUAGE_VERSION",
},
{
- 0x8B91,
- "GL_PALETTE4_RGBA8_OES",
+ 0x8B8D, "GL_CURRENT_PROGRAM",
},
{
- 0x8B92,
- "GL_PALETTE4_R5_G6_B5_OES",
+ 0x8B90, "GL_PALETTE4_RGB8_OES",
},
{
- 0x8B93,
- "GL_PALETTE4_RGBA4_OES",
+ 0x8B91, "GL_PALETTE4_RGBA8_OES",
},
{
- 0x8B94,
- "GL_PALETTE4_RGB5_A1_OES",
+ 0x8B92, "GL_PALETTE4_R5_G6_B5_OES",
},
{
- 0x8B95,
- "GL_PALETTE8_RGB8_OES",
+ 0x8B93, "GL_PALETTE4_RGBA4_OES",
},
{
- 0x8B96,
- "GL_PALETTE8_RGBA8_OES",
+ 0x8B94, "GL_PALETTE4_RGB5_A1_OES",
},
{
- 0x8B97,
- "GL_PALETTE8_R5_G6_B5_OES",
+ 0x8B95, "GL_PALETTE8_RGB8_OES",
},
{
- 0x8B98,
- "GL_PALETTE8_RGBA4_OES",
+ 0x8B96, "GL_PALETTE8_RGBA8_OES",
},
{
- 0x8B99,
- "GL_PALETTE8_RGB5_A1_OES",
+ 0x8B97, "GL_PALETTE8_R5_G6_B5_OES",
},
{
- 0x8B9A,
- "GL_IMPLEMENTATION_COLOR_READ_TYPE",
+ 0x8B98, "GL_PALETTE8_RGBA4_OES",
},
{
- 0x8B9B,
- "GL_IMPLEMENTATION_COLOR_READ_FORMAT",
+ 0x8B99, "GL_PALETTE8_RGB5_A1_OES",
},
{
- 0x8BBB,
- "GL_FRAMEBUFFER_FLIP_Y_MESA",
+ 0x8B9A, "GL_IMPLEMENTATION_COLOR_READ_TYPE",
},
{
- 0x8BC0,
- "GL_COUNTER_TYPE_AMD",
+ 0x8B9B, "GL_IMPLEMENTATION_COLOR_READ_FORMAT",
},
{
- 0x8BC1,
- "GL_COUNTER_RANGE_AMD",
+ 0x8BBB, "GL_FRAMEBUFFER_FLIP_Y_MESA",
},
{
- 0x8BC2,
- "GL_UNSIGNED_INT64_AMD",
+ 0x8BC0, "GL_COUNTER_TYPE_AMD",
},
{
- 0x8BC3,
- "GL_PERCENTAGE_AMD",
+ 0x8BC1, "GL_COUNTER_RANGE_AMD",
},
{
- 0x8BC4,
- "GL_PERFMON_RESULT_AVAILABLE_AMD",
+ 0x8BC2, "GL_UNSIGNED_INT64_AMD",
},
{
- 0x8BC5,
- "GL_PERFMON_RESULT_SIZE_AMD",
+ 0x8BC3, "GL_PERCENTAGE_AMD",
},
{
- 0x8BC6,
- "GL_PERFMON_RESULT_AMD",
+ 0x8BC4, "GL_PERFMON_RESULT_AVAILABLE_AMD",
},
{
- 0x8BD2,
- "GL_TEXTURE_WIDTH_QCOM",
+ 0x8BC5, "GL_PERFMON_RESULT_SIZE_AMD",
},
{
- 0x8BD3,
- "GL_TEXTURE_HEIGHT_QCOM",
+ 0x8BC6, "GL_PERFMON_RESULT_AMD",
},
{
- 0x8BD4,
- "GL_TEXTURE_DEPTH_QCOM",
+ 0x8BD2, "GL_TEXTURE_WIDTH_QCOM",
},
{
- 0x8BD5,
- "GL_TEXTURE_INTERNAL_FORMAT_QCOM",
+ 0x8BD3, "GL_TEXTURE_HEIGHT_QCOM",
},
{
- 0x8BD6,
- "GL_TEXTURE_FORMAT_QCOM",
+ 0x8BD4, "GL_TEXTURE_DEPTH_QCOM",
},
{
- 0x8BD7,
- "GL_TEXTURE_TYPE_QCOM",
+ 0x8BD5, "GL_TEXTURE_INTERNAL_FORMAT_QCOM",
},
{
- 0x8BD8,
- "GL_TEXTURE_IMAGE_VALID_QCOM",
+ 0x8BD6, "GL_TEXTURE_FORMAT_QCOM",
},
{
- 0x8BD9,
- "GL_TEXTURE_NUM_LEVELS_QCOM",
+ 0x8BD7, "GL_TEXTURE_TYPE_QCOM",
},
{
- 0x8BDA,
- "GL_TEXTURE_TARGET_QCOM",
+ 0x8BD8, "GL_TEXTURE_IMAGE_VALID_QCOM",
},
{
- 0x8BDB,
- "GL_TEXTURE_OBJECT_VALID_QCOM",
+ 0x8BD9, "GL_TEXTURE_NUM_LEVELS_QCOM",
},
{
- 0x8BDC,
- "GL_STATE_RESTORE",
+ 0x8BDA, "GL_TEXTURE_TARGET_QCOM",
},
{
- 0x8BE7,
- "GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT",
+ 0x8BDB, "GL_TEXTURE_OBJECT_VALID_QCOM",
},
{
- 0x8BFA,
- "GL_TEXTURE_PROTECTED_EXT",
+ 0x8BDC, "GL_STATE_RESTORE",
},
{
- 0x8C00,
- "GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG",
+ 0x8BE7, "GL_SAMPLER_EXTERNAL_2D_Y2Y_EXT",
},
{
- 0x8C01,
- "GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG",
+ 0x8BFA, "GL_TEXTURE_PROTECTED_EXT",
},
{
- 0x8C02,
- "GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG",
+ 0x8BFB, "GL_TEXTURE_FOVEATED_FEATURE_BITS_QCOM",
},
{
- 0x8C03,
- "GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG",
+ 0x8BFC, "GL_TEXTURE_FOVEATED_MIN_PIXEL_DENSITY_QCOM",
},
{
- 0x8C0A,
- "GL_SGX_BINARY_IMG",
+ 0x8BFD, "GL_TEXTURE_FOVEATED_FEATURE_QUERY_QCOM",
},
{
- 0x8C10,
- "GL_TEXTURE_RED_TYPE",
+ 0x8BFE, "GL_TEXTURE_FOVEATED_NUM_FOCAL_POINTS_QUERY_QCOM",
},
{
- 0x8C11,
- "GL_TEXTURE_GREEN_TYPE",
+ 0x8BFF, "GL_FRAMEBUFFER_INCOMPLETE_FOVEATION_QCOM",
},
{
- 0x8C12,
- "GL_TEXTURE_BLUE_TYPE",
+ 0x8C00, "GL_COMPRESSED_RGB_PVRTC_4BPPV1_IMG",
},
{
- 0x8C13,
- "GL_TEXTURE_ALPHA_TYPE",
+ 0x8C01, "GL_COMPRESSED_RGB_PVRTC_2BPPV1_IMG",
},
{
- 0x8C16,
- "GL_TEXTURE_DEPTH_TYPE",
+ 0x8C02, "GL_COMPRESSED_RGBA_PVRTC_4BPPV1_IMG",
},
{
- 0x8C17,
- "GL_UNSIGNED_NORMALIZED_EXT",
+ 0x8C03, "GL_COMPRESSED_RGBA_PVRTC_2BPPV1_IMG",
},
{
- 0x8C1A,
- "GL_TEXTURE_2D_ARRAY",
+ 0x8C0A, "GL_SGX_BINARY_IMG",
},
{
- 0x8C1D,
- "GL_TEXTURE_BINDING_2D_ARRAY",
+ 0x8C10, "GL_TEXTURE_RED_TYPE",
},
{
- 0x8C29,
- "GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_OES",
+ 0x8C11, "GL_TEXTURE_GREEN_TYPE",
},
{
- 0x8C2A,
- "GL_TEXTURE_BUFFER_OES",
+ 0x8C12, "GL_TEXTURE_BLUE_TYPE",
},
{
- 0x8C2B,
- "GL_MAX_TEXTURE_BUFFER_SIZE_OES",
+ 0x8C13, "GL_TEXTURE_ALPHA_TYPE",
},
{
- 0x8C2C,
- "GL_TEXTURE_BINDING_BUFFER_OES",
+ 0x8C16, "GL_TEXTURE_DEPTH_TYPE",
},
{
- 0x8C2D,
- "GL_TEXTURE_BUFFER_DATA_STORE_BINDING_OES",
+ 0x8C17, "GL_UNSIGNED_NORMALIZED_EXT",
},
{
- 0x8C2F,
- "GL_ANY_SAMPLES_PASSED_EXT",
+ 0x8C1A, "GL_TEXTURE_2D_ARRAY",
},
{
- 0x8C36,
- "GL_SAMPLE_SHADING_OES",
+ 0x8C1D, "GL_TEXTURE_BINDING_2D_ARRAY",
},
{
- 0x8C37,
- "GL_MIN_SAMPLE_SHADING_VALUE_OES",
+ 0x8C29, "GL_MAX_GEOMETRY_TEXTURE_IMAGE_UNITS_OES",
},
{
- 0x8C3A,
- "GL_R11F_G11F_B10F_APPLE",
+ 0x8C2A, "GL_TEXTURE_BUFFER_OES",
},
{
- 0x8C3B,
- "GL_UNSIGNED_INT_10F_11F_11F_REV_APPLE",
+ 0x8C2B, "GL_MAX_TEXTURE_BUFFER_SIZE_OES",
},
{
- 0x8C3D,
- "GL_RGB9_E5_APPLE",
+ 0x8C2C, "GL_TEXTURE_BINDING_BUFFER_OES",
},
{
- 0x8C3E,
- "GL_UNSIGNED_INT_5_9_9_9_REV_APPLE",
+ 0x8C2D, "GL_TEXTURE_BUFFER_DATA_STORE_BINDING_OES",
},
{
- 0x8C3F,
- "GL_TEXTURE_SHARED_SIZE",
+ 0x8C2F, "GL_ANY_SAMPLES_PASSED_EXT",
},
{
- 0x8C40,
- "GL_SRGB_EXT",
+ 0x8C36, "GL_SAMPLE_SHADING_OES",
},
{
- 0x8C41,
- "GL_SRGB8_NV",
+ 0x8C37, "GL_MIN_SAMPLE_SHADING_VALUE_OES",
},
{
- 0x8C42,
- "GL_SRGB_ALPHA_EXT",
+ 0x8C3A, "GL_R11F_G11F_B10F_APPLE",
},
{
- 0x8C43,
- "GL_SRGB8_ALPHA8_EXT",
+ 0x8C3B, "GL_UNSIGNED_INT_10F_11F_11F_REV_APPLE",
},
{
- 0x8C44,
- "GL_SLUMINANCE_ALPHA_NV",
+ 0x8C3D, "GL_RGB9_E5_APPLE",
},
{
- 0x8C45,
- "GL_SLUMINANCE8_ALPHA8_NV",
+ 0x8C3E, "GL_UNSIGNED_INT_5_9_9_9_REV_APPLE",
},
{
- 0x8C46,
- "GL_SLUMINANCE_NV",
+ 0x8C3F, "GL_TEXTURE_SHARED_SIZE",
},
{
- 0x8C47,
- "GL_SLUMINANCE8_NV",
+ 0x8C40, "GL_SRGB_EXT",
},
{
- 0x8C4C,
- "GL_COMPRESSED_SRGB_S3TC_DXT1_NV",
+ 0x8C41, "GL_SRGB8_NV",
},
{
- 0x8C4D,
- "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_NV",
+ 0x8C42, "GL_SRGB_ALPHA_EXT",
},
{
- 0x8C4E,
- "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_NV",
+ 0x8C43, "GL_SRGB8_ALPHA8_EXT",
},
{
- 0x8C4F,
- "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_NV",
+ 0x8C44, "GL_SLUMINANCE_ALPHA_NV",
},
{
- 0x8C76,
- "GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH",
+ 0x8C45, "GL_SLUMINANCE8_ALPHA8_NV",
},
{
- 0x8C7F,
- "GL_TRANSFORM_FEEDBACK_BUFFER_MODE",
+ 0x8C46, "GL_SLUMINANCE_NV",
},
{
- 0x8C80,
- "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS",
+ 0x8C47, "GL_SLUMINANCE8_NV",
},
{
- 0x8C83,
- "GL_TRANSFORM_FEEDBACK_VARYINGS",
+ 0x8C4C, "GL_COMPRESSED_SRGB_S3TC_DXT1_EXT",
},
{
- 0x8C84,
- "GL_TRANSFORM_FEEDBACK_BUFFER_START",
+ 0x8C4D, "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT1_EXT",
},
{
- 0x8C85,
- "GL_TRANSFORM_FEEDBACK_BUFFER_SIZE",
+ 0x8C4E, "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT3_EXT",
},
{
- 0x8C87,
- "GL_PRIMITIVES_GENERATED_OES",
+ 0x8C4F, "GL_COMPRESSED_SRGB_ALPHA_S3TC_DXT5_EXT",
},
{
- 0x8C88,
- "GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN",
+ 0x8C76, "GL_TRANSFORM_FEEDBACK_VARYING_MAX_LENGTH",
},
{
- 0x8C89,
- "GL_RASTERIZER_DISCARD",
+ 0x8C7F, "GL_TRANSFORM_FEEDBACK_BUFFER_MODE",
},
{
- 0x8C8A,
- "GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS",
+ 0x8C80, "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_COMPONENTS",
},
{
- 0x8C8B,
- "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS",
+ 0x8C83, "GL_TRANSFORM_FEEDBACK_VARYINGS",
},
{
- 0x8C8C,
- "GL_INTERLEAVED_ATTRIBS",
+ 0x8C84, "GL_TRANSFORM_FEEDBACK_BUFFER_START",
},
{
- 0x8C8D,
- "GL_SEPARATE_ATTRIBS",
+ 0x8C85, "GL_TRANSFORM_FEEDBACK_BUFFER_SIZE",
},
{
- 0x8C8E,
- "GL_TRANSFORM_FEEDBACK_BUFFER",
+ 0x8C87, "GL_PRIMITIVES_GENERATED_OES",
},
{
- 0x8C8F,
- "GL_TRANSFORM_FEEDBACK_BUFFER_BINDING",
+ 0x8C88, "GL_TRANSFORM_FEEDBACK_PRIMITIVES_WRITTEN",
},
{
- 0x8C92,
- "GL_ATC_RGB_AMD",
+ 0x8C89, "GL_RASTERIZER_DISCARD",
},
{
- 0x8C93,
- "GL_ATC_RGBA_EXPLICIT_ALPHA_AMD",
+ 0x8C8A, "GL_MAX_TRANSFORM_FEEDBACK_INTERLEAVED_COMPONENTS",
},
{
- 0x8CA3,
- "GL_STENCIL_BACK_REF",
+ 0x8C8B, "GL_MAX_TRANSFORM_FEEDBACK_SEPARATE_ATTRIBS",
},
{
- 0x8CA4,
- "GL_STENCIL_BACK_VALUE_MASK",
+ 0x8C8C, "GL_INTERLEAVED_ATTRIBS",
},
{
- 0x8CA5,
- "GL_STENCIL_BACK_WRITEMASK",
+ 0x8C8D, "GL_SEPARATE_ATTRIBS",
},
{
- 0x8CA6,
- "GL_FRAMEBUFFER_BINDING",
+ 0x8C8E, "GL_TRANSFORM_FEEDBACK_BUFFER",
},
{
- 0x8CA7,
- "GL_RENDERBUFFER_BINDING",
+ 0x8C8F, "GL_TRANSFORM_FEEDBACK_BUFFER_BINDING",
},
{
- 0x8CA8,
- "GL_READ_FRAMEBUFFER_ANGLE",
+ 0x8C92, "GL_ATC_RGB_AMD",
},
{
- 0x8CA9,
- "GL_DRAW_FRAMEBUFFER_ANGLE",
+ 0x8C93, "GL_ATC_RGBA_EXPLICIT_ALPHA_AMD",
},
{
- 0x8CAA,
- "GL_READ_FRAMEBUFFER_BINDING_ANGLE",
+ 0x8CA1, "GL_LOWER_LEFT_EXT",
},
{
- 0x8CAB,
- "GL_RENDERBUFFER_SAMPLES_ANGLE",
+ 0x8CA2, "GL_UPPER_LEFT_EXT",
},
{
- 0x8CAC,
- "GL_DEPTH_COMPONENT32F",
+ 0x8CA3, "GL_STENCIL_BACK_REF",
},
{
- 0x8CAD,
- "GL_DEPTH32F_STENCIL8",
+ 0x8CA4, "GL_STENCIL_BACK_VALUE_MASK",
},
{
- 0x8CD0,
- "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE",
+ 0x8CA5, "GL_STENCIL_BACK_WRITEMASK",
},
{
- 0x8CD1,
- "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME",
+ 0x8CA6, "GL_FRAMEBUFFER_BINDING",
},
{
- 0x8CD2,
- "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL",
+ 0x8CA7, "GL_RENDERBUFFER_BINDING",
},
{
- 0x8CD3,
- "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE",
+ 0x8CA8, "GL_READ_FRAMEBUFFER_ANGLE",
},
{
- 0x8CD4,
- "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES",
+ 0x8CA9, "GL_DRAW_FRAMEBUFFER_ANGLE",
},
{
- 0x8CD5,
- "GL_FRAMEBUFFER_COMPLETE",
+ 0x8CAA, "GL_READ_FRAMEBUFFER_BINDING_ANGLE",
},
{
- 0x8CD6,
- "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT",
+ 0x8CAB, "GL_RENDERBUFFER_SAMPLES_ANGLE",
},
{
- 0x8CD7,
- "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT",
+ 0x8CAC, "GL_DEPTH_COMPONENT32F",
},
{
- 0x8CD9,
- "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS",
+ 0x8CAD, "GL_DEPTH32F_STENCIL8",
},
{
- 0x8CDD,
- "GL_FRAMEBUFFER_UNSUPPORTED",
+ 0x8CD0, "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_TYPE",
},
{
- 0x8CDF,
- "GL_MAX_COLOR_ATTACHMENTS_EXT",
+ 0x8CD1, "GL_FRAMEBUFFER_ATTACHMENT_OBJECT_NAME",
},
{
- 0x8CE0,
- "GL_COLOR_ATTACHMENT0",
+ 0x8CD2, "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_LEVEL",
},
{
- 0x8CE1,
- "GL_COLOR_ATTACHMENT1_EXT",
+ 0x8CD3, "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_CUBE_MAP_FACE",
},
{
- 0x8CE2,
- "GL_COLOR_ATTACHMENT2_EXT",
+ 0x8CD4, "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_3D_ZOFFSET_OES",
},
{
- 0x8CE3,
- "GL_COLOR_ATTACHMENT3_EXT",
+ 0x8CD5, "GL_FRAMEBUFFER_COMPLETE",
},
{
- 0x8CE4,
- "GL_COLOR_ATTACHMENT4_EXT",
+ 0x8CD6, "GL_FRAMEBUFFER_INCOMPLETE_ATTACHMENT",
},
{
- 0x8CE5,
- "GL_COLOR_ATTACHMENT5_EXT",
+ 0x8CD7, "GL_FRAMEBUFFER_INCOMPLETE_MISSING_ATTACHMENT",
},
{
- 0x8CE6,
- "GL_COLOR_ATTACHMENT6_EXT",
+ 0x8CD9, "GL_FRAMEBUFFER_INCOMPLETE_DIMENSIONS",
},
{
- 0x8CE7,
- "GL_COLOR_ATTACHMENT7_EXT",
+ 0x8CDD, "GL_FRAMEBUFFER_UNSUPPORTED",
},
{
- 0x8CE8,
- "GL_COLOR_ATTACHMENT8_EXT",
+ 0x8CDF, "GL_MAX_COLOR_ATTACHMENTS_EXT",
},
{
- 0x8CE9,
- "GL_COLOR_ATTACHMENT9_EXT",
+ 0x8CE0, "GL_COLOR_ATTACHMENT0",
},
{
- 0x8CEA,
- "GL_COLOR_ATTACHMENT10_EXT",
+ 0x8CE1, "GL_COLOR_ATTACHMENT1_EXT",
},
{
- 0x8CEB,
- "GL_COLOR_ATTACHMENT11_EXT",
+ 0x8CE2, "GL_COLOR_ATTACHMENT2_EXT",
},
{
- 0x8CEC,
- "GL_COLOR_ATTACHMENT12_EXT",
+ 0x8CE3, "GL_COLOR_ATTACHMENT3_EXT",
},
{
- 0x8CED,
- "GL_COLOR_ATTACHMENT13_EXT",
+ 0x8CE4, "GL_COLOR_ATTACHMENT4_EXT",
},
{
- 0x8CEE,
- "GL_COLOR_ATTACHMENT14_EXT",
+ 0x8CE5, "GL_COLOR_ATTACHMENT5_EXT",
},
{
- 0x8CEF,
- "GL_COLOR_ATTACHMENT15_EXT",
+ 0x8CE6, "GL_COLOR_ATTACHMENT6_EXT",
},
{
- 0x8CF0,
- "GL_COLOR_ATTACHMENT16",
+ 0x8CE7, "GL_COLOR_ATTACHMENT7_EXT",
},
{
- 0x8CF1,
- "GL_COLOR_ATTACHMENT17",
+ 0x8CE8, "GL_COLOR_ATTACHMENT8_EXT",
},
{
- 0x8CF2,
- "GL_COLOR_ATTACHMENT18",
+ 0x8CE9, "GL_COLOR_ATTACHMENT9_EXT",
},
{
- 0x8CF3,
- "GL_COLOR_ATTACHMENT19",
+ 0x8CEA, "GL_COLOR_ATTACHMENT10_EXT",
},
{
- 0x8CF4,
- "GL_COLOR_ATTACHMENT20",
+ 0x8CEB, "GL_COLOR_ATTACHMENT11_EXT",
},
{
- 0x8CF5,
- "GL_COLOR_ATTACHMENT21",
+ 0x8CEC, "GL_COLOR_ATTACHMENT12_EXT",
},
{
- 0x8CF6,
- "GL_COLOR_ATTACHMENT22",
+ 0x8CED, "GL_COLOR_ATTACHMENT13_EXT",
},
{
- 0x8CF7,
- "GL_COLOR_ATTACHMENT23",
+ 0x8CEE, "GL_COLOR_ATTACHMENT14_EXT",
},
{
- 0x8CF8,
- "GL_COLOR_ATTACHMENT24",
+ 0x8CEF, "GL_COLOR_ATTACHMENT15_EXT",
},
{
- 0x8CF9,
- "GL_COLOR_ATTACHMENT25",
+ 0x8CF0, "GL_COLOR_ATTACHMENT16",
},
{
- 0x8CFA,
- "GL_COLOR_ATTACHMENT26",
+ 0x8CF1, "GL_COLOR_ATTACHMENT17",
},
{
- 0x8CFB,
- "GL_COLOR_ATTACHMENT27",
+ 0x8CF2, "GL_COLOR_ATTACHMENT18",
},
{
- 0x8CFC,
- "GL_COLOR_ATTACHMENT28",
+ 0x8CF3, "GL_COLOR_ATTACHMENT19",
},
{
- 0x8CFD,
- "GL_COLOR_ATTACHMENT29",
+ 0x8CF4, "GL_COLOR_ATTACHMENT20",
},
{
- 0x8CFE,
- "GL_COLOR_ATTACHMENT30",
+ 0x8CF5, "GL_COLOR_ATTACHMENT21",
},
{
- 0x8CFF,
- "GL_COLOR_ATTACHMENT31",
+ 0x8CF6, "GL_COLOR_ATTACHMENT22",
},
{
- 0x8D00,
- "GL_DEPTH_ATTACHMENT",
+ 0x8CF7, "GL_COLOR_ATTACHMENT23",
},
{
- 0x8D20,
- "GL_STENCIL_ATTACHMENT",
+ 0x8CF8, "GL_COLOR_ATTACHMENT24",
},
{
- 0x8D40,
- "GL_FRAMEBUFFER",
+ 0x8CF9, "GL_COLOR_ATTACHMENT25",
},
{
- 0x8D41,
- "GL_RENDERBUFFER",
+ 0x8CFA, "GL_COLOR_ATTACHMENT26",
},
{
- 0x8D42,
- "GL_RENDERBUFFER_WIDTH",
+ 0x8CFB, "GL_COLOR_ATTACHMENT27",
},
{
- 0x8D43,
- "GL_RENDERBUFFER_HEIGHT",
+ 0x8CFC, "GL_COLOR_ATTACHMENT28",
},
{
- 0x8D44,
- "GL_RENDERBUFFER_INTERNAL_FORMAT",
+ 0x8CFD, "GL_COLOR_ATTACHMENT29",
},
{
- 0x8D46,
- "GL_STENCIL_INDEX1_OES",
+ 0x8CFE, "GL_COLOR_ATTACHMENT30",
},
{
- 0x8D47,
- "GL_STENCIL_INDEX4_OES",
+ 0x8CFF, "GL_COLOR_ATTACHMENT31",
},
{
- 0x8D48,
- "GL_STENCIL_INDEX8",
+ 0x8D00, "GL_DEPTH_ATTACHMENT",
},
{
- 0x8D50,
- "GL_RENDERBUFFER_RED_SIZE",
+ 0x8D20, "GL_STENCIL_ATTACHMENT",
},
{
- 0x8D51,
- "GL_RENDERBUFFER_GREEN_SIZE",
+ 0x8D40, "GL_FRAMEBUFFER",
},
{
- 0x8D52,
- "GL_RENDERBUFFER_BLUE_SIZE",
+ 0x8D41, "GL_RENDERBUFFER",
},
{
- 0x8D53,
- "GL_RENDERBUFFER_ALPHA_SIZE",
+ 0x8D42, "GL_RENDERBUFFER_WIDTH",
},
{
- 0x8D54,
- "GL_RENDERBUFFER_DEPTH_SIZE",
+ 0x8D43, "GL_RENDERBUFFER_HEIGHT",
},
{
- 0x8D55,
- "GL_RENDERBUFFER_STENCIL_SIZE",
+ 0x8D44, "GL_RENDERBUFFER_INTERNAL_FORMAT",
},
{
- 0x8D56,
- "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE",
+ 0x8D46, "GL_STENCIL_INDEX1_OES",
},
{
- 0x8D57,
- "GL_MAX_SAMPLES_ANGLE",
+ 0x8D47, "GL_STENCIL_INDEX4_OES",
},
{
- 0x8D61,
- "GL_HALF_FLOAT_OES",
+ 0x8D48, "GL_STENCIL_INDEX8",
},
{
- 0x8D62,
- "GL_RGB565",
+ 0x8D50, "GL_RENDERBUFFER_RED_SIZE",
},
{
- 0x8D64,
- "GL_ETC1_RGB8_OES",
+ 0x8D51, "GL_RENDERBUFFER_GREEN_SIZE",
},
{
- 0x8D65,
- "GL_TEXTURE_EXTERNAL_OES",
+ 0x8D52, "GL_RENDERBUFFER_BLUE_SIZE",
},
{
- 0x8D66,
- "GL_SAMPLER_EXTERNAL_OES",
+ 0x8D53, "GL_RENDERBUFFER_ALPHA_SIZE",
},
{
- 0x8D67,
- "GL_TEXTURE_BINDING_EXTERNAL_OES",
+ 0x8D54, "GL_RENDERBUFFER_DEPTH_SIZE",
},
{
- 0x8D68,
- "GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES",
+ 0x8D55, "GL_RENDERBUFFER_STENCIL_SIZE",
},
{
- 0x8D69,
- "GL_PRIMITIVE_RESTART_FIXED_INDEX",
+ 0x8D56, "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_ANGLE",
},
{
- 0x8D6A,
- "GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT",
+ 0x8D57, "GL_MAX_SAMPLES_ANGLE",
},
{
- 0x8D6B,
- "GL_MAX_ELEMENT_INDEX",
+ 0x8D61, "GL_HALF_FLOAT_OES",
},
{
- 0x8D6C,
- "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT",
+ 0x8D62, "GL_RGB565",
},
{
- 0x8D70,
- "GL_RGBA32UI",
+ 0x8D64, "GL_ETC1_RGB8_OES",
},
{
- 0x8D71,
- "GL_RGB32UI",
+ 0x8D65, "GL_TEXTURE_EXTERNAL_OES",
},
{
- 0x8D76,
- "GL_RGBA16UI",
+ 0x8D66, "GL_SAMPLER_EXTERNAL_OES",
},
{
- 0x8D77,
- "GL_RGB16UI",
+ 0x8D67, "GL_TEXTURE_BINDING_EXTERNAL_OES",
},
{
- 0x8D7C,
- "GL_RGBA8UI",
+ 0x8D68, "GL_REQUIRED_TEXTURE_IMAGE_UNITS_OES",
},
{
- 0x8D7D,
- "GL_RGB8UI",
+ 0x8D69, "GL_PRIMITIVE_RESTART_FIXED_INDEX",
},
{
- 0x8D82,
- "GL_RGBA32I",
+ 0x8D6A, "GL_ANY_SAMPLES_PASSED_CONSERVATIVE_EXT",
},
{
- 0x8D83,
- "GL_RGB32I",
+ 0x8D6B, "GL_MAX_ELEMENT_INDEX",
},
{
- 0x8D88,
- "GL_RGBA16I",
+ 0x8D6C, "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SAMPLES_EXT",
},
{
- 0x8D89,
- "GL_RGB16I",
+ 0x8D70, "GL_RGBA32UI",
},
{
- 0x8D8E,
- "GL_RGBA8I",
+ 0x8D71, "GL_RGB32UI",
},
{
- 0x8D8F,
- "GL_RGB8I",
+ 0x8D76, "GL_RGBA16UI",
},
{
- 0x8D94,
- "GL_RED_INTEGER",
+ 0x8D77, "GL_RGB16UI",
},
{
- 0x8D98,
- "GL_RGB_INTEGER",
+ 0x8D7C, "GL_RGBA8UI",
},
{
- 0x8D99,
- "GL_RGBA_INTEGER",
+ 0x8D7D, "GL_RGB8UI",
},
{
- 0x8D9F,
- "GL_INT_2_10_10_10_REV",
+ 0x8D82, "GL_RGBA32I",
},
{
- 0x8DA7,
- "GL_FRAMEBUFFER_ATTACHMENT_LAYERED_OES",
+ 0x8D83, "GL_RGB32I",
},
{
- 0x8DA8,
- "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_OES",
+ 0x8D88, "GL_RGBA16I",
},
{
- 0x8DAD,
- "GL_FLOAT_32_UNSIGNED_INT_24_8_REV",
+ 0x8D89, "GL_RGB16I",
},
{
- 0x8DB9,
- "GL_FRAMEBUFFER_SRGB_EXT",
+ 0x8D8E, "GL_RGBA8I",
},
{
- 0x8DC1,
- "GL_SAMPLER_2D_ARRAY",
+ 0x8D8F, "GL_RGB8I",
},
{
- 0x8DC2,
- "GL_SAMPLER_BUFFER_OES",
+ 0x8D94, "GL_RED_INTEGER",
},
{
- 0x8DC4,
- "GL_SAMPLER_2D_ARRAY_SHADOW_NV",
+ 0x8D98, "GL_RGB_INTEGER",
},
{
- 0x8DC5,
- "GL_SAMPLER_CUBE_SHADOW_NV",
+ 0x8D99, "GL_RGBA_INTEGER",
},
{
- 0x8DC6,
- "GL_UNSIGNED_INT_VEC2",
+ 0x8D9F, "GL_INT_2_10_10_10_REV",
},
{
- 0x8DC7,
- "GL_UNSIGNED_INT_VEC3",
+ 0x8DA7, "GL_FRAMEBUFFER_ATTACHMENT_LAYERED_OES",
},
{
- 0x8DC8,
- "GL_UNSIGNED_INT_VEC4",
+ 0x8DA8, "GL_FRAMEBUFFER_INCOMPLETE_LAYER_TARGETS_OES",
},
{
- 0x8DCA,
- "GL_INT_SAMPLER_2D",
+ 0x8DAD, "GL_FLOAT_32_UNSIGNED_INT_24_8_REV",
},
{
- 0x8DCB,
- "GL_INT_SAMPLER_3D",
+ 0x8DB9, "GL_FRAMEBUFFER_SRGB_EXT",
},
{
- 0x8DCC,
- "GL_INT_SAMPLER_CUBE",
+ 0x8DBB, "GL_COMPRESSED_RED_RGTC1_EXT",
},
{
- 0x8DCF,
- "GL_INT_SAMPLER_2D_ARRAY",
+ 0x8DBC, "GL_COMPRESSED_SIGNED_RED_RGTC1_EXT",
},
{
- 0x8DD0,
- "GL_INT_SAMPLER_BUFFER_OES",
+ 0x8DBD, "GL_COMPRESSED_RED_GREEN_RGTC2_EXT",
},
{
- 0x8DD2,
- "GL_UNSIGNED_INT_SAMPLER_2D",
+ 0x8DBE, "GL_COMPRESSED_SIGNED_RED_GREEN_RGTC2_EXT",
},
{
- 0x8DD3,
- "GL_UNSIGNED_INT_SAMPLER_3D",
+ 0x8DC1, "GL_SAMPLER_2D_ARRAY",
},
{
- 0x8DD4,
- "GL_UNSIGNED_INT_SAMPLER_CUBE",
+ 0x8DC2, "GL_SAMPLER_BUFFER_OES",
},
{
- 0x8DD7,
- "GL_UNSIGNED_INT_SAMPLER_2D_ARRAY",
+ 0x8DC4, "GL_SAMPLER_2D_ARRAY_SHADOW_NV",
},
{
- 0x8DD8,
- "GL_UNSIGNED_INT_SAMPLER_BUFFER_OES",
+ 0x8DC5, "GL_SAMPLER_CUBE_SHADOW_NV",
},
{
- 0x8DD9,
- "GL_GEOMETRY_SHADER_OES",
+ 0x8DC6, "GL_UNSIGNED_INT_VEC2",
},
{
- 0x8DDF,
- "GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_OES",
+ 0x8DC7, "GL_UNSIGNED_INT_VEC3",
},
{
- 0x8DE0,
- "GL_MAX_GEOMETRY_OUTPUT_VERTICES_OES",
+ 0x8DC8, "GL_UNSIGNED_INT_VEC4",
},
{
- 0x8DE1,
- "GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_OES",
+ 0x8DCA, "GL_INT_SAMPLER_2D",
},
{
- 0x8DF0,
- "GL_LOW_FLOAT",
+ 0x8DCB, "GL_INT_SAMPLER_3D",
},
{
- 0x8DF1,
- "GL_MEDIUM_FLOAT",
+ 0x8DCC, "GL_INT_SAMPLER_CUBE",
},
{
- 0x8DF2,
- "GL_HIGH_FLOAT",
+ 0x8DCF, "GL_INT_SAMPLER_2D_ARRAY",
},
{
- 0x8DF3,
- "GL_LOW_INT",
+ 0x8DD0, "GL_INT_SAMPLER_BUFFER_OES",
},
{
- 0x8DF4,
- "GL_MEDIUM_INT",
+ 0x8DD2, "GL_UNSIGNED_INT_SAMPLER_2D",
},
{
- 0x8DF5,
- "GL_HIGH_INT",
+ 0x8DD3, "GL_UNSIGNED_INT_SAMPLER_3D",
},
{
- 0x8DF6,
- "GL_UNSIGNED_INT_10_10_10_2_OES",
+ 0x8DD4, "GL_UNSIGNED_INT_SAMPLER_CUBE",
},
{
- 0x8DF7,
- "GL_INT_10_10_10_2_OES",
+ 0x8DD7, "GL_UNSIGNED_INT_SAMPLER_2D_ARRAY",
},
{
- 0x8DF8,
- "GL_SHADER_BINARY_FORMATS",
+ 0x8DD8, "GL_UNSIGNED_INT_SAMPLER_BUFFER_OES",
},
{
- 0x8DF9,
- "GL_NUM_SHADER_BINARY_FORMATS",
+ 0x8DD9, "GL_GEOMETRY_SHADER_OES",
},
{
- 0x8DFA,
- "GL_SHADER_COMPILER",
+ 0x8DDF, "GL_MAX_GEOMETRY_UNIFORM_COMPONENTS_OES",
},
{
- 0x8DFB,
- "GL_MAX_VERTEX_UNIFORM_VECTORS",
+ 0x8DE0, "GL_MAX_GEOMETRY_OUTPUT_VERTICES_OES",
},
{
- 0x8DFC,
- "GL_MAX_VARYING_VECTORS",
+ 0x8DE1, "GL_MAX_GEOMETRY_TOTAL_OUTPUT_COMPONENTS_OES",
},
{
- 0x8DFD,
- "GL_MAX_FRAGMENT_UNIFORM_VECTORS",
+ 0x8DF0, "GL_LOW_FLOAT",
},
{
- 0x8E13,
- "GL_QUERY_WAIT_NV",
+ 0x8DF1, "GL_MEDIUM_FLOAT",
},
{
- 0x8E14,
- "GL_QUERY_NO_WAIT_NV",
+ 0x8DF2, "GL_HIGH_FLOAT",
},
{
- 0x8E15,
- "GL_QUERY_BY_REGION_WAIT_NV",
+ 0x8DF3, "GL_LOW_INT",
},
{
- 0x8E16,
- "GL_QUERY_BY_REGION_NO_WAIT_NV",
+ 0x8DF4, "GL_MEDIUM_INT",
},
{
- 0x8E1B,
- "GL_POLYGON_OFFSET_CLAMP_EXT",
+ 0x8DF5, "GL_HIGH_INT",
},
{
- 0x8E1E,
- "GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_OES",
+ 0x8DF6, "GL_UNSIGNED_INT_10_10_10_2_OES",
},
{
- 0x8E1F,
- "GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_OES",
+ 0x8DF7, "GL_INT_10_10_10_2_OES",
},
{
- 0x8E20,
- "GL_COLOR_SAMPLES_NV",
+ 0x8DF8, "GL_SHADER_BINARY_FORMATS",
},
{
- 0x8E22,
- "GL_TRANSFORM_FEEDBACK",
+ 0x8DF9, "GL_NUM_SHADER_BINARY_FORMATS",
},
{
- 0x8E23,
- "GL_TRANSFORM_FEEDBACK_PAUSED",
+ 0x8DFA, "GL_SHADER_COMPILER",
},
{
- 0x8E24,
- "GL_TRANSFORM_FEEDBACK_ACTIVE",
+ 0x8DFB, "GL_MAX_VERTEX_UNIFORM_VECTORS",
},
{
- 0x8E25,
- "GL_TRANSFORM_FEEDBACK_BINDING",
+ 0x8DFC, "GL_MAX_VARYING_VECTORS",
},
{
- 0x8E28,
- "GL_TIMESTAMP_EXT",
+ 0x8DFD, "GL_MAX_FRAGMENT_UNIFORM_VECTORS",
},
{
- 0x8E2C,
- "GL_DEPTH_COMPONENT16_NONLINEAR_NV",
+ 0x8E13, "GL_QUERY_WAIT_NV",
},
{
- 0x8E42,
- "GL_TEXTURE_SWIZZLE_R",
+ 0x8E14, "GL_QUERY_NO_WAIT_NV",
},
{
- 0x8E43,
- "GL_TEXTURE_SWIZZLE_G",
+ 0x8E15, "GL_QUERY_BY_REGION_WAIT_NV",
},
{
- 0x8E44,
- "GL_TEXTURE_SWIZZLE_B",
+ 0x8E16, "GL_QUERY_BY_REGION_NO_WAIT_NV",
},
{
- 0x8E45,
- "GL_TEXTURE_SWIZZLE_A",
+ 0x8E1B, "GL_POLYGON_OFFSET_CLAMP_EXT",
},
{
- 0x8E4D,
- "GL_FIRST_VERTEX_CONVENTION_OES",
+ 0x8E1E, "GL_MAX_COMBINED_TESS_CONTROL_UNIFORM_COMPONENTS_OES",
},
{
- 0x8E4E,
- "GL_LAST_VERTEX_CONVENTION_OES",
+ 0x8E1F, "GL_MAX_COMBINED_TESS_EVALUATION_UNIFORM_COMPONENTS_OES",
},
{
- 0x8E50,
- "GL_SAMPLE_LOCATION_NV",
+ 0x8E20, "GL_COLOR_SAMPLES_NV",
},
{
- 0x8E51,
- "GL_SAMPLE_MASK",
+ 0x8E22, "GL_TRANSFORM_FEEDBACK",
},
{
- 0x8E52,
- "GL_SAMPLE_MASK_VALUE",
+ 0x8E23, "GL_TRANSFORM_FEEDBACK_PAUSED",
},
{
- 0x8E59,
- "GL_MAX_SAMPLE_MASK_WORDS",
+ 0x8E24, "GL_TRANSFORM_FEEDBACK_ACTIVE",
},
{
- 0x8E5A,
- "GL_MAX_GEOMETRY_SHADER_INVOCATIONS_OES",
+ 0x8E25, "GL_TRANSFORM_FEEDBACK_BINDING",
},
{
- 0x8E5B,
- "GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES",
+ 0x8E28, "GL_TIMESTAMP_EXT",
},
{
- 0x8E5C,
- "GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES",
+ 0x8E2C, "GL_DEPTH_COMPONENT16_NONLINEAR_NV",
},
{
- 0x8E5D,
- "GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES",
+ 0x8E42, "GL_TEXTURE_SWIZZLE_R",
},
{
- 0x8E5E,
- "GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET",
+ 0x8E43, "GL_TEXTURE_SWIZZLE_G",
},
{
- 0x8E5F,
- "GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET",
+ 0x8E44, "GL_TEXTURE_SWIZZLE_B",
},
{
- 0x8E72,
- "GL_PATCH_VERTICES_OES",
+ 0x8E45, "GL_TEXTURE_SWIZZLE_A",
},
{
- 0x8E75,
- "GL_TESS_CONTROL_OUTPUT_VERTICES_OES",
+ 0x8E4D, "GL_FIRST_VERTEX_CONVENTION_OES",
},
{
- 0x8E76,
- "GL_TESS_GEN_MODE_OES",
+ 0x8E4E, "GL_LAST_VERTEX_CONVENTION_OES",
},
{
- 0x8E77,
- "GL_TESS_GEN_SPACING_OES",
+ 0x8E50, "GL_SAMPLE_LOCATION_NV",
},
{
- 0x8E78,
- "GL_TESS_GEN_VERTEX_ORDER_OES",
+ 0x8E51, "GL_SAMPLE_MASK",
},
{
- 0x8E79,
- "GL_TESS_GEN_POINT_MODE_OES",
+ 0x8E52, "GL_SAMPLE_MASK_VALUE",
},
{
- 0x8E7A,
- "GL_ISOLINES_OES",
+ 0x8E59, "GL_MAX_SAMPLE_MASK_WORDS",
},
{
- 0x8E7B,
- "GL_FRACTIONAL_ODD_OES",
+ 0x8E5A, "GL_MAX_GEOMETRY_SHADER_INVOCATIONS_OES",
},
{
- 0x8E7C,
- "GL_FRACTIONAL_EVEN_OES",
+ 0x8E5B, "GL_MIN_FRAGMENT_INTERPOLATION_OFFSET_OES",
},
{
- 0x8E7D,
- "GL_MAX_PATCH_VERTICES_OES",
+ 0x8E5C, "GL_MAX_FRAGMENT_INTERPOLATION_OFFSET_OES",
},
{
- 0x8E7E,
- "GL_MAX_TESS_GEN_LEVEL_OES",
+ 0x8E5D, "GL_FRAGMENT_INTERPOLATION_OFFSET_BITS_OES",
},
{
- 0x8E7F,
- "GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_OES",
+ 0x8E5E, "GL_MIN_PROGRAM_TEXTURE_GATHER_OFFSET",
},
{
- 0x8E80,
- "GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_OES",
+ 0x8E5F, "GL_MAX_PROGRAM_TEXTURE_GATHER_OFFSET",
},
{
- 0x8E81,
- "GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_OES",
+ 0x8E72, "GL_PATCH_VERTICES_OES",
},
{
- 0x8E82,
- "GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_OES",
+ 0x8E75, "GL_TESS_CONTROL_OUTPUT_VERTICES_OES",
},
{
- 0x8E83,
- "GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_OES",
+ 0x8E76, "GL_TESS_GEN_MODE_OES",
},
{
- 0x8E84,
- "GL_MAX_TESS_PATCH_COMPONENTS_OES",
+ 0x8E77, "GL_TESS_GEN_SPACING_OES",
},
{
- 0x8E85,
- "GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_OES",
+ 0x8E78, "GL_TESS_GEN_VERTEX_ORDER_OES",
},
{
- 0x8E86,
- "GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_OES",
+ 0x8E79, "GL_TESS_GEN_POINT_MODE_OES",
},
{
- 0x8E87,
- "GL_TESS_EVALUATION_SHADER_OES",
+ 0x8E7A, "GL_ISOLINES_OES",
},
{
- 0x8E88,
- "GL_TESS_CONTROL_SHADER_OES",
+ 0x8E7B, "GL_FRACTIONAL_ODD_OES",
},
{
- 0x8E89,
- "GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_OES",
+ 0x8E7C, "GL_FRACTIONAL_EVEN_OES",
},
{
- 0x8E8A,
- "GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_OES",
+ 0x8E7D, "GL_MAX_PATCH_VERTICES_OES",
},
{
- 0x8ED0,
- "GL_COVERAGE_COMPONENT_NV",
+ 0x8E7E, "GL_MAX_TESS_GEN_LEVEL_OES",
},
{
- 0x8ED1,
- "GL_COVERAGE_COMPONENT4_NV",
+ 0x8E7F, "GL_MAX_TESS_CONTROL_UNIFORM_COMPONENTS_OES",
},
{
- 0x8ED2,
- "GL_COVERAGE_ATTACHMENT_NV",
+ 0x8E80, "GL_MAX_TESS_EVALUATION_UNIFORM_COMPONENTS_OES",
},
{
- 0x8ED3,
- "GL_COVERAGE_BUFFERS_NV",
+ 0x8E81, "GL_MAX_TESS_CONTROL_TEXTURE_IMAGE_UNITS_OES",
},
{
- 0x8ED4,
- "GL_COVERAGE_SAMPLES_NV",
+ 0x8E82, "GL_MAX_TESS_EVALUATION_TEXTURE_IMAGE_UNITS_OES",
},
{
- 0x8ED5,
- "GL_COVERAGE_ALL_FRAGMENTS_NV",
+ 0x8E83, "GL_MAX_TESS_CONTROL_OUTPUT_COMPONENTS_OES",
},
{
- 0x8ED6,
- "GL_COVERAGE_EDGE_FRAGMENTS_NV",
+ 0x8E84, "GL_MAX_TESS_PATCH_COMPONENTS_OES",
},
{
- 0x8ED7,
- "GL_COVERAGE_AUTOMATIC_NV",
+ 0x8E85, "GL_MAX_TESS_CONTROL_TOTAL_OUTPUT_COMPONENTS_OES",
},
{
- 0x8F10,
- "GL_INCLUSIVE_EXT",
+ 0x8E86, "GL_MAX_TESS_EVALUATION_OUTPUT_COMPONENTS_OES",
},
{
- 0x8F11,
- "GL_EXCLUSIVE_EXT",
+ 0x8E87, "GL_TESS_EVALUATION_SHADER_OES",
},
{
- 0x8F12,
- "GL_WINDOW_RECTANGLE_EXT",
+ 0x8E88, "GL_TESS_CONTROL_SHADER_OES",
},
{
- 0x8F13,
- "GL_WINDOW_RECTANGLE_MODE_EXT",
+ 0x8E89, "GL_MAX_TESS_CONTROL_UNIFORM_BLOCKS_OES",
},
{
- 0x8F14,
- "GL_MAX_WINDOW_RECTANGLES_EXT",
+ 0x8E8A, "GL_MAX_TESS_EVALUATION_UNIFORM_BLOCKS_OES",
},
{
- 0x8F15,
- "GL_NUM_WINDOW_RECTANGLES_EXT",
+ 0x8E8C, "GL_COMPRESSED_RGBA_BPTC_UNORM_EXT",
},
{
- 0x8F36,
- "GL_COPY_READ_BUFFER_NV",
+ 0x8E8D, "GL_COMPRESSED_SRGB_ALPHA_BPTC_UNORM_EXT",
},
{
- 0x8F37,
- "GL_COPY_WRITE_BUFFER_NV",
+ 0x8E8E, "GL_COMPRESSED_RGB_BPTC_SIGNED_FLOAT_EXT",
},
{
- 0x8F38,
- "GL_MAX_IMAGE_UNITS",
+ 0x8E8F, "GL_COMPRESSED_RGB_BPTC_UNSIGNED_FLOAT_EXT",
},
{
- 0x8F39,
- "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES",
+ 0x8ED0, "GL_COVERAGE_COMPONENT_NV",
},
{
- 0x8F3A,
- "GL_IMAGE_BINDING_NAME",
+ 0x8ED1, "GL_COVERAGE_COMPONENT4_NV",
},
{
- 0x8F3B,
- "GL_IMAGE_BINDING_LEVEL",
+ 0x8ED2, "GL_COVERAGE_ATTACHMENT_NV",
},
{
- 0x8F3C,
- "GL_IMAGE_BINDING_LAYERED",
+ 0x8ED3, "GL_COVERAGE_BUFFERS_NV",
},
{
- 0x8F3D,
- "GL_IMAGE_BINDING_LAYER",
+ 0x8ED4, "GL_COVERAGE_SAMPLES_NV",
},
{
- 0x8F3E,
- "GL_IMAGE_BINDING_ACCESS",
+ 0x8ED5, "GL_COVERAGE_ALL_FRAGMENTS_NV",
},
{
- 0x8F3F,
- "GL_DRAW_INDIRECT_BUFFER",
+ 0x8ED6, "GL_COVERAGE_EDGE_FRAGMENTS_NV",
},
{
- 0x8F43,
- "GL_DRAW_INDIRECT_BUFFER_BINDING",
+ 0x8ED7, "GL_COVERAGE_AUTOMATIC_NV",
},
{
- 0x8F4F,
- "GL_VERTEX_BINDING_BUFFER",
+ 0x8F10, "GL_INCLUSIVE_EXT",
},
{
- 0x8F60,
- "GL_MALI_SHADER_BINARY_ARM",
+ 0x8F11, "GL_EXCLUSIVE_EXT",
},
{
- 0x8F61,
- "GL_MALI_PROGRAM_BINARY_ARM",
+ 0x8F12, "GL_WINDOW_RECTANGLE_EXT",
},
{
- 0x8F63,
- "GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT",
+ 0x8F13, "GL_WINDOW_RECTANGLE_MODE_EXT",
},
{
- 0x8F64,
- "GL_SHADER_PIXEL_LOCAL_STORAGE_EXT",
+ 0x8F14, "GL_MAX_WINDOW_RECTANGLES_EXT",
},
{
- 0x8F65,
- "GL_FETCH_PER_SAMPLE_ARM",
+ 0x8F15, "GL_NUM_WINDOW_RECTANGLES_EXT",
},
{
- 0x8F66,
- "GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM",
+ 0x8F36, "GL_COPY_READ_BUFFER_NV",
},
{
- 0x8F67,
- "GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_SIZE_EXT",
+ 0x8F37, "GL_COPY_WRITE_BUFFER_NV",
},
{
- 0x8F69,
- "GL_TEXTURE_ASTC_DECODE_PRECISION_EXT",
+ 0x8F38, "GL_MAX_IMAGE_UNITS",
},
{
- 0x8F94,
- "GL_R8_SNORM",
+ 0x8F39, "GL_MAX_COMBINED_SHADER_OUTPUT_RESOURCES",
},
{
- 0x8F95,
- "GL_RG8_SNORM",
+ 0x8F3A, "GL_IMAGE_BINDING_NAME",
},
{
- 0x8F96,
- "GL_RGB8_SNORM",
+ 0x8F3B, "GL_IMAGE_BINDING_LEVEL",
},
{
- 0x8F97,
- "GL_RGBA8_SNORM",
+ 0x8F3C, "GL_IMAGE_BINDING_LAYERED",
},
{
- 0x8F98,
- "GL_R16_SNORM_EXT",
+ 0x8F3D, "GL_IMAGE_BINDING_LAYER",
},
{
- 0x8F99,
- "GL_RG16_SNORM_EXT",
+ 0x8F3E, "GL_IMAGE_BINDING_ACCESS",
},
{
- 0x8F9A,
- "GL_RGB16_SNORM_EXT",
+ 0x8F3F, "GL_DRAW_INDIRECT_BUFFER",
},
{
- 0x8F9B,
- "GL_RGBA16_SNORM_EXT",
+ 0x8F43, "GL_DRAW_INDIRECT_BUFFER_BINDING",
},
{
- 0x8F9C,
- "GL_SIGNED_NORMALIZED",
+ 0x8F4F, "GL_VERTEX_BINDING_BUFFER",
},
{
- 0x8FA0,
- "GL_PERFMON_GLOBAL_MODE_QCOM",
+ 0x8F60, "GL_MALI_SHADER_BINARY_ARM",
},
{
- 0x8FB0,
- "GL_BINNING_CONTROL_HINT_QCOM",
+ 0x8F61, "GL_MALI_PROGRAM_BINARY_ARM",
},
{
- 0x8FB1,
- "GL_CPU_OPTIMIZED_QCOM",
+ 0x8F63, "GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_FAST_SIZE_EXT",
},
{
- 0x8FB2,
- "GL_GPU_OPTIMIZED_QCOM",
+ 0x8F64, "GL_SHADER_PIXEL_LOCAL_STORAGE_EXT",
},
{
- 0x8FB3,
- "GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM",
+ 0x8F65, "GL_FETCH_PER_SAMPLE_ARM",
},
{
- 0x8FBB,
- "GL_GPU_DISJOINT_EXT",
+ 0x8F66, "GL_FRAGMENT_SHADER_FRAMEBUFFER_FETCH_MRT_ARM",
},
{
- 0x8FBD,
- "GL_SR8_EXT",
+ 0x8F67, "GL_MAX_SHADER_PIXEL_LOCAL_STORAGE_SIZE_EXT",
},
{
- 0x8FBE,
- "GL_SRG8_EXT",
+ 0x8F69, "GL_TEXTURE_ASTC_DECODE_PRECISION_EXT",
},
{
- 0x8FC4,
- "GL_SHADER_BINARY_VIV",
+ 0x8F94, "GL_R8_SNORM",
},
{
- 0x8FE0,
- "GL_INT8_NV",
+ 0x8F95, "GL_RG8_SNORM",
},
{
- 0x8FE1,
- "GL_INT8_VEC2_NV",
+ 0x8F96, "GL_RGB8_SNORM",
},
{
- 0x8FE2,
- "GL_INT8_VEC3_NV",
+ 0x8F97, "GL_RGBA8_SNORM",
},
{
- 0x8FE3,
- "GL_INT8_VEC4_NV",
+ 0x8F98, "GL_R16_SNORM_EXT",
},
{
- 0x8FE4,
- "GL_INT16_NV",
+ 0x8F99, "GL_RG16_SNORM_EXT",
},
{
- 0x8FE5,
- "GL_INT16_VEC2_NV",
+ 0x8F9A, "GL_RGB16_SNORM_EXT",
},
{
- 0x8FE6,
- "GL_INT16_VEC3_NV",
+ 0x8F9B, "GL_RGBA16_SNORM_EXT",
},
{
- 0x8FE7,
- "GL_INT16_VEC4_NV",
+ 0x8F9C, "GL_SIGNED_NORMALIZED",
},
{
- 0x8FE9,
- "GL_INT64_VEC2_NV",
+ 0x8FA0, "GL_PERFMON_GLOBAL_MODE_QCOM",
},
{
- 0x8FEA,
- "GL_INT64_VEC3_NV",
+ 0x8FB0, "GL_BINNING_CONTROL_HINT_QCOM",
},
{
- 0x8FEB,
- "GL_INT64_VEC4_NV",
+ 0x8FB1, "GL_CPU_OPTIMIZED_QCOM",
},
{
- 0x8FEC,
- "GL_UNSIGNED_INT8_NV",
+ 0x8FB2, "GL_GPU_OPTIMIZED_QCOM",
},
{
- 0x8FED,
- "GL_UNSIGNED_INT8_VEC2_NV",
+ 0x8FB3, "GL_RENDER_DIRECT_TO_FRAMEBUFFER_QCOM",
},
{
- 0x8FEE,
- "GL_UNSIGNED_INT8_VEC3_NV",
+ 0x8FBB, "GL_GPU_DISJOINT_EXT",
},
{
- 0x8FEF,
- "GL_UNSIGNED_INT8_VEC4_NV",
+ 0x8FBD, "GL_SR8_EXT",
},
{
- 0x8FF0,
- "GL_UNSIGNED_INT16_NV",
+ 0x8FBE, "GL_SRG8_EXT",
},
{
- 0x8FF1,
- "GL_UNSIGNED_INT16_VEC2_NV",
+ 0x8FBF, "GL_TEXTURE_FORMAT_SRGB_OVERRIDE_EXT",
},
{
- 0x8FF2,
- "GL_UNSIGNED_INT16_VEC3_NV",
+ 0x8FC4, "GL_SHADER_BINARY_VIV",
},
{
- 0x8FF3,
- "GL_UNSIGNED_INT16_VEC4_NV",
+ 0x8FE0, "GL_INT8_NV",
},
{
- 0x8FF5,
- "GL_UNSIGNED_INT64_VEC2_NV",
+ 0x8FE1, "GL_INT8_VEC2_NV",
},
{
- 0x8FF6,
- "GL_UNSIGNED_INT64_VEC3_NV",
+ 0x8FE2, "GL_INT8_VEC3_NV",
},
{
- 0x8FF7,
- "GL_UNSIGNED_INT64_VEC4_NV",
+ 0x8FE3, "GL_INT8_VEC4_NV",
},
{
- 0x8FF8,
- "GL_FLOAT16_NV",
+ 0x8FE4, "GL_INT16_NV",
},
{
- 0x8FF9,
- "GL_FLOAT16_VEC2_NV",
+ 0x8FE5, "GL_INT16_VEC2_NV",
},
{
- 0x8FFA,
- "GL_FLOAT16_VEC3_NV",
+ 0x8FE6, "GL_INT16_VEC3_NV",
},
{
- 0x8FFB,
- "GL_FLOAT16_VEC4_NV",
+ 0x8FE7, "GL_INT16_VEC4_NV",
},
{
- 0x9009,
- "GL_TEXTURE_CUBE_MAP_ARRAY_OES",
+ 0x8FE9, "GL_INT64_VEC2_NV",
},
{
- 0x900A,
- "GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_OES",
+ 0x8FEA, "GL_INT64_VEC3_NV",
},
{
- 0x900C,
- "GL_SAMPLER_CUBE_MAP_ARRAY_OES",
+ 0x8FEB, "GL_INT64_VEC4_NV",
},
{
- 0x900D,
- "GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_OES",
+ 0x8FEC, "GL_UNSIGNED_INT8_NV",
},
{
- 0x900E,
- "GL_INT_SAMPLER_CUBE_MAP_ARRAY_OES",
+ 0x8FED, "GL_UNSIGNED_INT8_VEC2_NV",
},
{
- 0x900F,
- "GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_OES",
+ 0x8FEE, "GL_UNSIGNED_INT8_VEC3_NV",
},
{
- 0x904D,
- "GL_IMAGE_2D",
+ 0x8FEF, "GL_UNSIGNED_INT8_VEC4_NV",
},
{
- 0x904E,
- "GL_IMAGE_3D",
+ 0x8FF0, "GL_UNSIGNED_INT16_NV",
},
{
- 0x9050,
- "GL_IMAGE_CUBE",
+ 0x8FF1, "GL_UNSIGNED_INT16_VEC2_NV",
},
{
- 0x9051,
- "GL_IMAGE_BUFFER_OES",
+ 0x8FF2, "GL_UNSIGNED_INT16_VEC3_NV",
},
{
- 0x9053,
- "GL_IMAGE_2D_ARRAY",
+ 0x8FF3, "GL_UNSIGNED_INT16_VEC4_NV",
},
{
- 0x9054,
- "GL_IMAGE_CUBE_MAP_ARRAY_OES",
+ 0x8FF5, "GL_UNSIGNED_INT64_VEC2_NV",
},
{
- 0x9058,
- "GL_INT_IMAGE_2D",
+ 0x8FF6, "GL_UNSIGNED_INT64_VEC3_NV",
},
{
- 0x9059,
- "GL_INT_IMAGE_3D",
+ 0x8FF7, "GL_UNSIGNED_INT64_VEC4_NV",
},
{
- 0x905B,
- "GL_INT_IMAGE_CUBE",
+ 0x8FF8, "GL_FLOAT16_NV",
},
{
- 0x905C,
- "GL_INT_IMAGE_BUFFER_OES",
+ 0x8FF9, "GL_FLOAT16_VEC2_NV",
},
{
- 0x905E,
- "GL_INT_IMAGE_2D_ARRAY",
+ 0x8FFA, "GL_FLOAT16_VEC3_NV",
},
{
- 0x905F,
- "GL_INT_IMAGE_CUBE_MAP_ARRAY_OES",
+ 0x8FFB, "GL_FLOAT16_VEC4_NV",
},
{
- 0x9063,
- "GL_UNSIGNED_INT_IMAGE_2D",
+ 0x9009, "GL_TEXTURE_CUBE_MAP_ARRAY_OES",
},
{
- 0x9064,
- "GL_UNSIGNED_INT_IMAGE_3D",
+ 0x900A, "GL_TEXTURE_BINDING_CUBE_MAP_ARRAY_OES",
},
{
- 0x9066,
- "GL_UNSIGNED_INT_IMAGE_CUBE",
+ 0x900C, "GL_SAMPLER_CUBE_MAP_ARRAY_OES",
},
{
- 0x9067,
- "GL_UNSIGNED_INT_IMAGE_BUFFER_OES",
+ 0x900D, "GL_SAMPLER_CUBE_MAP_ARRAY_SHADOW_OES",
},
{
- 0x9069,
- "GL_UNSIGNED_INT_IMAGE_2D_ARRAY",
+ 0x900E, "GL_INT_SAMPLER_CUBE_MAP_ARRAY_OES",
},
{
- 0x906A,
- "GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_OES",
+ 0x900F, "GL_UNSIGNED_INT_SAMPLER_CUBE_MAP_ARRAY_OES",
},
{
- 0x906E,
- "GL_IMAGE_BINDING_FORMAT",
+ 0x901C, "GL_FACTOR_MIN_AMD",
},
{
- 0x906F,
- "GL_RGB10_A2UI",
+ 0x901D, "GL_FACTOR_MAX_AMD",
},
{
- 0x9070,
- "GL_PATH_FORMAT_SVG_NV",
+ 0x904D, "GL_IMAGE_2D",
},
{
- 0x9071,
- "GL_PATH_FORMAT_PS_NV",
+ 0x904E, "GL_IMAGE_3D",
},
{
- 0x9072,
- "GL_STANDARD_FONT_NAME_NV",
+ 0x9050, "GL_IMAGE_CUBE",
},
{
- 0x9073,
- "GL_SYSTEM_FONT_NAME_NV",
+ 0x9051, "GL_IMAGE_BUFFER_OES",
},
{
- 0x9074,
- "GL_FILE_NAME_NV",
+ 0x9053, "GL_IMAGE_2D_ARRAY",
},
{
- 0x9075,
- "GL_PATH_STROKE_WIDTH_NV",
+ 0x9054, "GL_IMAGE_CUBE_MAP_ARRAY_OES",
},
{
- 0x9076,
- "GL_PATH_END_CAPS_NV",
+ 0x9058, "GL_INT_IMAGE_2D",
},
{
- 0x9077,
- "GL_PATH_INITIAL_END_CAP_NV",
+ 0x9059, "GL_INT_IMAGE_3D",
},
{
- 0x9078,
- "GL_PATH_TERMINAL_END_CAP_NV",
+ 0x905B, "GL_INT_IMAGE_CUBE",
},
{
- 0x9079,
- "GL_PATH_JOIN_STYLE_NV",
+ 0x905C, "GL_INT_IMAGE_BUFFER_OES",
},
{
- 0x907A,
- "GL_PATH_MITER_LIMIT_NV",
+ 0x905E, "GL_INT_IMAGE_2D_ARRAY",
},
{
- 0x907B,
- "GL_PATH_DASH_CAPS_NV",
+ 0x905F, "GL_INT_IMAGE_CUBE_MAP_ARRAY_OES",
},
{
- 0x907C,
- "GL_PATH_INITIAL_DASH_CAP_NV",
+ 0x9063, "GL_UNSIGNED_INT_IMAGE_2D",
},
{
- 0x907D,
- "GL_PATH_TERMINAL_DASH_CAP_NV",
+ 0x9064, "GL_UNSIGNED_INT_IMAGE_3D",
},
{
- 0x907E,
- "GL_PATH_DASH_OFFSET_NV",
+ 0x9066, "GL_UNSIGNED_INT_IMAGE_CUBE",
},
{
- 0x907F,
- "GL_PATH_CLIENT_LENGTH_NV",
+ 0x9067, "GL_UNSIGNED_INT_IMAGE_BUFFER_OES",
},
{
- 0x907a,
- "GL_PATH_MITER_LIMIT_CHROMIUM",
+ 0x9069, "GL_UNSIGNED_INT_IMAGE_2D_ARRAY",
},
{
- 0x9080,
- "GL_PATH_FILL_MODE_NV",
+ 0x906A, "GL_UNSIGNED_INT_IMAGE_CUBE_MAP_ARRAY_OES",
},
{
- 0x9081,
- "GL_PATH_FILL_MASK_NV",
+ 0x906E, "GL_IMAGE_BINDING_FORMAT",
},
{
- 0x9082,
- "GL_PATH_FILL_COVER_MODE_NV",
+ 0x906F, "GL_RGB10_A2UI",
},
{
- 0x9083,
- "GL_PATH_STROKE_COVER_MODE_NV",
+ 0x9070, "GL_PATH_FORMAT_SVG_NV",
},
{
- 0x9084,
- "GL_PATH_STROKE_MASK_NV",
+ 0x9071, "GL_PATH_FORMAT_PS_NV",
},
{
- 0x9086,
- "GL_PATH_STROKE_BOUND_CHROMIUM",
+ 0x9072, "GL_STANDARD_FONT_NAME_NV",
},
{
- 0x9088,
- "GL_COUNT_UP_NV",
+ 0x9073, "GL_SYSTEM_FONT_NAME_NV",
},
{
- 0x9089,
- "GL_COUNT_DOWN_NV",
+ 0x9074, "GL_FILE_NAME_NV",
},
{
- 0x908A,
- "GL_PATH_OBJECT_BOUNDING_BOX_NV",
+ 0x9075, "GL_PATH_STROKE_WIDTH_NV",
},
{
- 0x908B,
- "GL_CONVEX_HULL_NV",
+ 0x9076, "GL_PATH_END_CAPS_NV",
},
{
- 0x908D,
- "GL_BOUNDING_BOX_NV",
+ 0x9077, "GL_PATH_INITIAL_END_CAP_NV",
},
{
- 0x908E,
- "GL_TRANSLATE_X_NV",
+ 0x9078, "GL_PATH_TERMINAL_END_CAP_NV",
},
{
- 0x908F,
- "GL_TRANSLATE_Y_NV",
+ 0x9079, "GL_PATH_JOIN_STYLE_NV",
},
{
- 0x9090,
- "GL_TRANSLATE_2D_NV",
+ 0x907A, "GL_PATH_MITER_LIMIT_NV",
},
{
- 0x9091,
- "GL_TRANSLATE_3D_NV",
+ 0x907B, "GL_PATH_DASH_CAPS_NV",
},
{
- 0x9092,
- "GL_AFFINE_2D_NV",
+ 0x907C, "GL_PATH_INITIAL_DASH_CAP_NV",
},
{
- 0x9094,
- "GL_AFFINE_3D_NV",
+ 0x907D, "GL_PATH_TERMINAL_DASH_CAP_NV",
},
{
- 0x9096,
- "GL_TRANSPOSE_AFFINE_2D_NV",
+ 0x907E, "GL_PATH_DASH_OFFSET_NV",
},
{
- 0x9098,
- "GL_TRANSPOSE_AFFINE_3D_NV",
+ 0x907F, "GL_PATH_CLIENT_LENGTH_NV",
},
{
- 0x909A,
- "GL_UTF8_NV",
+ 0x907a, "GL_PATH_MITER_LIMIT_CHROMIUM",
},
{
- 0x909B,
- "GL_UTF16_NV",
+ 0x9080, "GL_PATH_FILL_MODE_NV",
},
{
- 0x909C,
- "GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV",
+ 0x9081, "GL_PATH_FILL_MASK_NV",
},
{
- 0x909D,
- "GL_PATH_COMMAND_COUNT_NV",
+ 0x9082, "GL_PATH_FILL_COVER_MODE_NV",
},
{
- 0x909E,
- "GL_PATH_COORD_COUNT_NV",
+ 0x9083, "GL_PATH_STROKE_COVER_MODE_NV",
},
{
- 0x909F,
- "GL_PATH_DASH_ARRAY_COUNT_NV",
+ 0x9084, "GL_PATH_STROKE_MASK_NV",
},
{
- 0x90A0,
- "GL_PATH_COMPUTED_LENGTH_NV",
+ 0x9086, "GL_PATH_STROKE_BOUND_CHROMIUM",
},
{
- 0x90A1,
- "GL_PATH_FILL_BOUNDING_BOX_NV",
+ 0x9088, "GL_COUNT_UP_NV",
},
{
- 0x90A2,
- "GL_PATH_STROKE_BOUNDING_BOX_NV",
+ 0x9089, "GL_COUNT_DOWN_NV",
},
{
- 0x90A3,
- "GL_SQUARE_NV",
+ 0x908A, "GL_PATH_OBJECT_BOUNDING_BOX_NV",
},
{
- 0x90A4,
- "GL_ROUND_NV",
+ 0x908B, "GL_CONVEX_HULL_NV",
},
{
- 0x90A5,
- "GL_TRIANGULAR_NV",
+ 0x908D, "GL_BOUNDING_BOX_NV",
},
{
- 0x90A6,
- "GL_BEVEL_NV",
+ 0x908E, "GL_TRANSLATE_X_NV",
},
{
- 0x90A7,
- "GL_MITER_REVERT_NV",
+ 0x908F, "GL_TRANSLATE_Y_NV",
},
{
- 0x90A8,
- "GL_MITER_TRUNCATE_NV",
+ 0x9090, "GL_TRANSLATE_2D_NV",
},
{
- 0x90A9,
- "GL_SKIP_MISSING_GLYPH_NV",
+ 0x9091, "GL_TRANSLATE_3D_NV",
},
{
- 0x90AA,
- "GL_USE_MISSING_GLYPH_NV",
+ 0x9092, "GL_AFFINE_2D_NV",
},
{
- 0x90AB,
- "GL_PATH_ERROR_POSITION_NV",
+ 0x9094, "GL_AFFINE_3D_NV",
},
{
- 0x90AD,
- "GL_ACCUM_ADJACENT_PAIRS_NV",
+ 0x9096, "GL_TRANSPOSE_AFFINE_2D_NV",
},
{
- 0x90AE,
- "GL_ADJACENT_PAIRS_NV",
+ 0x9098, "GL_TRANSPOSE_AFFINE_3D_NV",
},
{
- 0x90AF,
- "GL_FIRST_TO_REST_NV",
+ 0x909A, "GL_UTF8_NV",
},
{
- 0x90B0,
- "GL_PATH_GEN_MODE_NV",
+ 0x909B, "GL_UTF16_NV",
},
{
- 0x90B1,
- "GL_PATH_GEN_COEFF_NV",
+ 0x909C, "GL_BOUNDING_BOX_OF_BOUNDING_BOXES_NV",
},
{
- 0x90B3,
- "GL_PATH_GEN_COMPONENTS_NV",
+ 0x909D, "GL_PATH_COMMAND_COUNT_NV",
},
{
- 0x90B4,
- "GL_PATH_DASH_OFFSET_RESET_NV",
+ 0x909E, "GL_PATH_COORD_COUNT_NV",
},
{
- 0x90B5,
- "GL_MOVE_TO_RESETS_NV",
+ 0x909F, "GL_PATH_DASH_ARRAY_COUNT_NV",
},
{
- 0x90B6,
- "GL_MOVE_TO_CONTINUES_NV",
+ 0x90A0, "GL_PATH_COMPUTED_LENGTH_NV",
},
{
- 0x90B7,
- "GL_PATH_STENCIL_FUNC_NV",
+ 0x90A1, "GL_PATH_FILL_BOUNDING_BOX_NV",
},
{
- 0x90B8,
- "GL_PATH_STENCIL_REF_NV",
+ 0x90A2, "GL_PATH_STROKE_BOUNDING_BOX_NV",
},
{
- 0x90B9,
- "GL_PATH_STENCIL_VALUE_MASK_NV",
+ 0x90A3, "GL_SQUARE_NV",
},
{
- 0x90BD,
- "GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV",
+ 0x90A4, "GL_ROUND_NV",
},
{
- 0x90BE,
- "GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV",
+ 0x90A5, "GL_TRIANGULAR_NV",
},
{
- 0x90BF,
- "GL_PATH_COVER_DEPTH_FUNC_NV",
+ 0x90A6, "GL_BEVEL_NV",
},
{
- 0x90C7,
- "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE",
+ 0x90A7, "GL_MITER_REVERT_NV",
},
{
- 0x90C8,
- "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE",
+ 0x90A8, "GL_MITER_TRUNCATE_NV",
},
{
- 0x90C9,
- "GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS",
+ 0x90A9, "GL_SKIP_MISSING_GLYPH_NV",
},
{
- 0x90CA,
- "GL_MAX_VERTEX_IMAGE_UNIFORMS",
+ 0x90AA, "GL_USE_MISSING_GLYPH_NV",
},
{
- 0x90CB,
- "GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_OES",
+ 0x90AB, "GL_PATH_ERROR_POSITION_NV",
},
{
- 0x90CC,
- "GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_OES",
+ 0x90AD, "GL_ACCUM_ADJACENT_PAIRS_NV",
},
{
- 0x90CD,
- "GL_MAX_GEOMETRY_IMAGE_UNIFORMS_OES",
+ 0x90AE, "GL_ADJACENT_PAIRS_NV",
},
{
- 0x90CE,
- "GL_MAX_FRAGMENT_IMAGE_UNIFORMS",
+ 0x90AF, "GL_FIRST_TO_REST_NV",
},
{
- 0x90CF,
- "GL_MAX_COMBINED_IMAGE_UNIFORMS",
+ 0x90B0, "GL_PATH_GEN_MODE_NV",
},
{
- 0x90D2,
- "GL_SHADER_STORAGE_BUFFER",
+ 0x90B1, "GL_PATH_GEN_COEFF_NV",
},
{
- 0x90D3,
- "GL_SHADER_STORAGE_BUFFER_BINDING",
+ 0x90B3, "GL_PATH_GEN_COMPONENTS_NV",
},
{
- 0x90D4,
- "GL_SHADER_STORAGE_BUFFER_START",
+ 0x90B4, "GL_PATH_DASH_OFFSET_RESET_NV",
},
{
- 0x90D5,
- "GL_SHADER_STORAGE_BUFFER_SIZE",
+ 0x90B5, "GL_MOVE_TO_RESETS_NV",
},
{
- 0x90D6,
- "GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS",
+ 0x90B6, "GL_MOVE_TO_CONTINUES_NV",
},
{
- 0x90D7,
- "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_OES",
+ 0x90B7, "GL_PATH_STENCIL_FUNC_NV",
},
{
- 0x90D8,
- "GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_OES",
+ 0x90B8, "GL_PATH_STENCIL_REF_NV",
},
{
- 0x90D9,
- "GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_OES",
+ 0x90B9, "GL_PATH_STENCIL_VALUE_MASK_NV",
},
{
- 0x90DA,
- "GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS",
+ 0x90BD, "GL_PATH_STENCIL_DEPTH_OFFSET_FACTOR_NV",
},
{
- 0x90DB,
- "GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS",
+ 0x90BE, "GL_PATH_STENCIL_DEPTH_OFFSET_UNITS_NV",
},
{
- 0x90DC,
- "GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS",
+ 0x90BF, "GL_PATH_COVER_DEPTH_FUNC_NV",
},
{
- 0x90DD,
- "GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS",
+ 0x90C7, "GL_IMAGE_FORMAT_COMPATIBILITY_TYPE",
},
{
- 0x90DE,
- "GL_MAX_SHADER_STORAGE_BLOCK_SIZE",
+ 0x90C8, "GL_IMAGE_FORMAT_COMPATIBILITY_BY_SIZE",
},
{
- 0x90DF,
- "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT",
+ 0x90C9, "GL_IMAGE_FORMAT_COMPATIBILITY_BY_CLASS",
},
{
- 0x90EA,
- "GL_DEPTH_STENCIL_TEXTURE_MODE",
+ 0x90CA, "GL_MAX_VERTEX_IMAGE_UNIFORMS",
},
{
- 0x90EB,
- "GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS",
+ 0x90CB, "GL_MAX_TESS_CONTROL_IMAGE_UNIFORMS_OES",
},
{
- 0x90EE,
- "GL_DISPATCH_INDIRECT_BUFFER",
+ 0x90CC, "GL_MAX_TESS_EVALUATION_IMAGE_UNIFORMS_OES",
},
{
- 0x90EF,
- "GL_DISPATCH_INDIRECT_BUFFER_BINDING",
+ 0x90CD, "GL_MAX_GEOMETRY_IMAGE_UNIFORMS_OES",
},
{
- 0x90F0,
- "GL_COLOR_ATTACHMENT_EXT",
+ 0x90CE, "GL_MAX_FRAGMENT_IMAGE_UNIFORMS",
},
{
- 0x90F1,
- "GL_MULTIVIEW_EXT",
+ 0x90CF, "GL_MAX_COMBINED_IMAGE_UNIFORMS",
},
{
- 0x90F2,
- "GL_MAX_MULTIVIEW_BUFFERS_EXT",
+ 0x90D2, "GL_SHADER_STORAGE_BUFFER",
},
{
- 0x90F3,
- "GL_CONTEXT_ROBUST_ACCESS_KHR",
+ 0x90D3, "GL_SHADER_STORAGE_BUFFER_BINDING",
},
{
- 0x90a3,
- "GL_SQUARE_CHROMIUM",
+ 0x90D4, "GL_SHADER_STORAGE_BUFFER_START",
},
{
- 0x90a4,
- "GL_ROUND_CHROMIUM",
+ 0x90D5, "GL_SHADER_STORAGE_BUFFER_SIZE",
},
{
- 0x9100,
- "GL_TEXTURE_2D_MULTISAMPLE",
+ 0x90D6, "GL_MAX_VERTEX_SHADER_STORAGE_BLOCKS",
},
{
- 0x9102,
- "GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES",
+ 0x90D7, "GL_MAX_GEOMETRY_SHADER_STORAGE_BLOCKS_OES",
},
{
- 0x9104,
- "GL_TEXTURE_BINDING_2D_MULTISAMPLE",
+ 0x90D8, "GL_MAX_TESS_CONTROL_SHADER_STORAGE_BLOCKS_OES",
},
{
- 0x9105,
- "GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES",
+ 0x90D9, "GL_MAX_TESS_EVALUATION_SHADER_STORAGE_BLOCKS_OES",
},
{
- 0x9106,
- "GL_TEXTURE_SAMPLES",
+ 0x90DA, "GL_MAX_FRAGMENT_SHADER_STORAGE_BLOCKS",
},
{
- 0x9107,
- "GL_TEXTURE_FIXED_SAMPLE_LOCATIONS",
+ 0x90DB, "GL_MAX_COMPUTE_SHADER_STORAGE_BLOCKS",
},
{
- 0x9108,
- "GL_SAMPLER_2D_MULTISAMPLE",
+ 0x90DC, "GL_MAX_COMBINED_SHADER_STORAGE_BLOCKS",
},
{
- 0x9109,
- "GL_INT_SAMPLER_2D_MULTISAMPLE",
+ 0x90DD, "GL_MAX_SHADER_STORAGE_BUFFER_BINDINGS",
},
{
- 0x910A,
- "GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE",
+ 0x90DE, "GL_MAX_SHADER_STORAGE_BLOCK_SIZE",
},
{
- 0x910B,
- "GL_SAMPLER_2D_MULTISAMPLE_ARRAY_OES",
+ 0x90DF, "GL_SHADER_STORAGE_BUFFER_OFFSET_ALIGNMENT",
},
{
- 0x910C,
- "GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES",
+ 0x90EA, "GL_DEPTH_STENCIL_TEXTURE_MODE",
},
{
- 0x910D,
- "GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES",
+ 0x90EB, "GL_MAX_COMPUTE_WORK_GROUP_INVOCATIONS",
},
{
- 0x910E,
- "GL_MAX_COLOR_TEXTURE_SAMPLES",
+ 0x90EE, "GL_DISPATCH_INDIRECT_BUFFER",
},
{
- 0x910F,
- "GL_MAX_DEPTH_TEXTURE_SAMPLES",
+ 0x90EF, "GL_DISPATCH_INDIRECT_BUFFER_BINDING",
},
{
- 0x9110,
- "GL_MAX_INTEGER_SAMPLES",
+ 0x90F0, "GL_COLOR_ATTACHMENT_EXT",
},
{
- 0x9111,
- "GL_MAX_SERVER_WAIT_TIMEOUT_APPLE",
+ 0x90F1, "GL_MULTIVIEW_EXT",
},
{
- 0x9112,
- "GL_OBJECT_TYPE_APPLE",
+ 0x90F2, "GL_MAX_MULTIVIEW_BUFFERS_EXT",
},
{
- 0x9113,
- "GL_SYNC_CONDITION_APPLE",
+ 0x90F3, "GL_CONTEXT_ROBUST_ACCESS_KHR",
},
{
- 0x9114,
- "GL_SYNC_STATUS_APPLE",
+ 0x90a3, "GL_SQUARE_CHROMIUM",
},
{
- 0x9115,
- "GL_SYNC_FLAGS_APPLE",
+ 0x90a4, "GL_ROUND_CHROMIUM",
},
{
- 0x9116,
- "GL_SYNC_FENCE_APPLE",
+ 0x9100, "GL_TEXTURE_2D_MULTISAMPLE",
},
{
- 0x9117,
- "GL_SYNC_GPU_COMMANDS_COMPLETE_APPLE",
+ 0x9102, "GL_TEXTURE_2D_MULTISAMPLE_ARRAY_OES",
},
{
- 0x9118,
- "GL_UNSIGNALED_APPLE",
+ 0x9104, "GL_TEXTURE_BINDING_2D_MULTISAMPLE",
},
{
- 0x9119,
- "GL_SIGNALED_APPLE",
+ 0x9105, "GL_TEXTURE_BINDING_2D_MULTISAMPLE_ARRAY_OES",
},
{
- 0x911A,
- "GL_ALREADY_SIGNALED_APPLE",
+ 0x9106, "GL_TEXTURE_SAMPLES",
},
{
- 0x911B,
- "GL_TIMEOUT_EXPIRED_APPLE",
+ 0x9107, "GL_TEXTURE_FIXED_SAMPLE_LOCATIONS",
},
{
- 0x911C,
- "GL_CONDITION_SATISFIED_APPLE",
+ 0x9108, "GL_SAMPLER_2D_MULTISAMPLE",
},
{
- 0x911D,
- "GL_WAIT_FAILED_APPLE",
+ 0x9109, "GL_INT_SAMPLER_2D_MULTISAMPLE",
},
{
- 0x911F,
- "GL_BUFFER_ACCESS_FLAGS",
+ 0x910A, "GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE",
},
{
- 0x9120,
- "GL_BUFFER_MAP_LENGTH",
+ 0x910B, "GL_SAMPLER_2D_MULTISAMPLE_ARRAY_OES",
},
{
- 0x9121,
- "GL_BUFFER_MAP_OFFSET",
+ 0x910C, "GL_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES",
},
{
- 0x9122,
- "GL_MAX_VERTEX_OUTPUT_COMPONENTS",
+ 0x910D, "GL_UNSIGNED_INT_SAMPLER_2D_MULTISAMPLE_ARRAY_OES",
},
{
- 0x9123,
- "GL_MAX_GEOMETRY_INPUT_COMPONENTS_OES",
+ 0x910E, "GL_MAX_COLOR_TEXTURE_SAMPLES",
},
{
- 0x9124,
- "GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_OES",
+ 0x910F, "GL_MAX_DEPTH_TEXTURE_SAMPLES",
},
{
- 0x9125,
- "GL_MAX_FRAGMENT_INPUT_COMPONENTS",
+ 0x9110, "GL_MAX_INTEGER_SAMPLES",
},
{
- 0x912F,
- "GL_TEXTURE_IMMUTABLE_FORMAT_EXT",
+ 0x9111, "GL_MAX_SERVER_WAIT_TIMEOUT_APPLE",
},
{
- 0x9130,
- "GL_SGX_PROGRAM_BINARY_IMG",
+ 0x9112, "GL_OBJECT_TYPE_APPLE",
},
{
- 0x9133,
- "GL_RENDERBUFFER_SAMPLES_IMG",
+ 0x9113, "GL_SYNC_CONDITION_APPLE",
},
{
- 0x9134,
- "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG",
+ 0x9114, "GL_SYNC_STATUS_APPLE",
},
{
- 0x9135,
- "GL_MAX_SAMPLES_IMG",
+ 0x9115, "GL_SYNC_FLAGS_APPLE",
},
{
- 0x9136,
- "GL_TEXTURE_SAMPLES_IMG",
+ 0x9116, "GL_SYNC_FENCE_APPLE",
},
{
- 0x9137,
- "GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG",
+ 0x9117, "GL_SYNC_GPU_COMMANDS_COMPLETE_APPLE",
},
{
- 0x9138,
- "GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG",
+ 0x9118, "GL_UNSIGNALED_APPLE",
},
{
- 0x9139,
- "GL_CUBIC_IMG",
+ 0x9119, "GL_SIGNALED_APPLE",
},
{
- 0x913A,
- "GL_CUBIC_MIPMAP_NEAREST_IMG",
+ 0x911A, "GL_ALREADY_SIGNALED_APPLE",
},
{
- 0x913B,
- "GL_CUBIC_MIPMAP_LINEAR_IMG",
+ 0x911B, "GL_TIMEOUT_EXPIRED_APPLE",
},
{
- 0x913C,
- "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_AND_DOWNSAMPLE_IMG",
+ 0x911C, "GL_CONDITION_SATISFIED_APPLE",
},
{
- 0x913D,
- "GL_NUM_DOWNSAMPLE_SCALES_IMG",
+ 0x911D, "GL_WAIT_FAILED_APPLE",
},
{
- 0x913E,
- "GL_DOWNSAMPLE_SCALES_IMG",
+ 0x911F, "GL_BUFFER_ACCESS_FLAGS",
},
{
- 0x913F,
- "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG",
+ 0x9120, "GL_BUFFER_MAP_LENGTH",
},
{
- 0x9143,
- "GL_MAX_DEBUG_MESSAGE_LENGTH_KHR",
+ 0x9121, "GL_BUFFER_MAP_OFFSET",
},
{
- 0x9144,
- "GL_MAX_DEBUG_LOGGED_MESSAGES_KHR",
+ 0x9122, "GL_MAX_VERTEX_OUTPUT_COMPONENTS",
},
{
- 0x9145,
- "GL_DEBUG_LOGGED_MESSAGES_KHR",
+ 0x9123, "GL_MAX_GEOMETRY_INPUT_COMPONENTS_OES",
},
{
- 0x9146,
- "GL_DEBUG_SEVERITY_HIGH_KHR",
+ 0x9124, "GL_MAX_GEOMETRY_OUTPUT_COMPONENTS_OES",
},
{
- 0x9147,
- "GL_DEBUG_SEVERITY_MEDIUM_KHR",
+ 0x9125, "GL_MAX_FRAGMENT_INPUT_COMPONENTS",
},
{
- 0x9148,
- "GL_DEBUG_SEVERITY_LOW_KHR",
+ 0x912F, "GL_TEXTURE_IMMUTABLE_FORMAT_EXT",
},
{
- 0x9151,
- "GL_BUFFER_OBJECT_EXT",
+ 0x9130, "GL_SGX_PROGRAM_BINARY_IMG",
},
{
- 0x9153,
- "GL_QUERY_OBJECT_EXT",
+ 0x9133, "GL_RENDERBUFFER_SAMPLES_IMG",
},
{
- 0x9154,
- "GL_VERTEX_ARRAY_OBJECT_EXT",
+ 0x9134, "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_IMG",
},
{
- 0x9195,
- "GL_VIRTUAL_PAGE_SIZE_X_EXT",
+ 0x9135, "GL_MAX_SAMPLES_IMG",
},
{
- 0x9196,
- "GL_VIRTUAL_PAGE_SIZE_Y_EXT",
+ 0x9136, "GL_TEXTURE_SAMPLES_IMG",
},
{
- 0x9197,
- "GL_VIRTUAL_PAGE_SIZE_Z_EXT",
+ 0x9137, "GL_COMPRESSED_RGBA_PVRTC_2BPPV2_IMG",
},
{
- 0x9198,
- "GL_MAX_SPARSE_TEXTURE_SIZE_EXT",
+ 0x9138, "GL_COMPRESSED_RGBA_PVRTC_4BPPV2_IMG",
},
{
- 0x9199,
- "GL_MAX_SPARSE_3D_TEXTURE_SIZE_EXT",
+ 0x9139, "GL_CUBIC_IMG",
},
{
- 0x919A,
- "GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_EXT",
+ 0x913A, "GL_CUBIC_MIPMAP_NEAREST_IMG",
},
{
- 0x919D,
- "GL_TEXTURE_BUFFER_OFFSET_OES",
+ 0x913B, "GL_CUBIC_MIPMAP_LINEAR_IMG",
},
{
- 0x919E,
- "GL_TEXTURE_BUFFER_SIZE_OES",
+ 0x913C, "GL_FRAMEBUFFER_INCOMPLETE_MULTISAMPLE_AND_DOWNSAMPLE_IMG",
},
{
- 0x919F,
- "GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_OES",
+ 0x913D, "GL_NUM_DOWNSAMPLE_SCALES_IMG",
},
{
- 0x91A6,
- "GL_TEXTURE_SPARSE_EXT",
+ 0x913E, "GL_DOWNSAMPLE_SCALES_IMG",
},
{
- 0x91A7,
- "GL_VIRTUAL_PAGE_SIZE_INDEX_EXT",
+ 0x913F, "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_SCALE_IMG",
},
{
- 0x91A8,
- "GL_NUM_VIRTUAL_PAGE_SIZES_EXT",
+ 0x9143, "GL_MAX_DEBUG_MESSAGE_LENGTH_KHR",
},
{
- 0x91A9,
- "GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_EXT",
+ 0x9144, "GL_MAX_DEBUG_LOGGED_MESSAGES_KHR",
},
{
- 0x91AA,
- "GL_NUM_SPARSE_LEVELS_EXT",
+ 0x9145, "GL_DEBUG_LOGGED_MESSAGES_KHR",
},
{
- 0x91B9,
- "GL_COMPUTE_SHADER",
+ 0x9146, "GL_DEBUG_SEVERITY_HIGH_KHR",
},
{
- 0x91BB,
- "GL_MAX_COMPUTE_UNIFORM_BLOCKS",
+ 0x9147, "GL_DEBUG_SEVERITY_MEDIUM_KHR",
},
{
- 0x91BC,
- "GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS",
+ 0x9148, "GL_DEBUG_SEVERITY_LOW_KHR",
},
{
- 0x91BD,
- "GL_MAX_COMPUTE_IMAGE_UNIFORMS",
+ 0x9151, "GL_BUFFER_OBJECT_EXT",
},
{
- 0x91BE,
- "GL_MAX_COMPUTE_WORK_GROUP_COUNT",
+ 0x9153, "GL_QUERY_OBJECT_EXT",
},
{
- 0x91BF,
- "GL_MAX_COMPUTE_WORK_GROUP_SIZE",
+ 0x9154, "GL_VERTEX_ARRAY_OBJECT_EXT",
},
{
- 0x9243,
- "GL_UNPACK_COLORSPACE_CONVERSION_CHROMIUM",
+ 0x9195, "GL_VIRTUAL_PAGE_SIZE_X_EXT",
},
{
- 0x9244,
- "GL_BIND_GENERATES_RESOURCE_CHROMIUM",
+ 0x9196, "GL_VIRTUAL_PAGE_SIZE_Y_EXT",
},
{
- 0x9245,
- "GL_OVERLAY_TRANSFORM_NONE_CHROMIUM",
+ 0x9197, "GL_VIRTUAL_PAGE_SIZE_Z_EXT",
},
{
- 0x9246,
- "GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM",
+ 0x9198, "GL_MAX_SPARSE_TEXTURE_SIZE_EXT",
},
{
- 0x9247,
- "GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM",
+ 0x9199, "GL_MAX_SPARSE_3D_TEXTURE_SIZE_EXT",
},
{
- 0x9248,
- "GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM",
+ 0x919A, "GL_MAX_SPARSE_ARRAY_TEXTURE_LAYERS_EXT",
},
{
- 0x9249,
- "GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM",
+ 0x919D, "GL_TEXTURE_BUFFER_OFFSET_OES",
},
{
- 0x924A,
- "GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM",
+ 0x919E, "GL_TEXTURE_BUFFER_SIZE_OES",
},
{
- 0x9250,
- "GL_SHADER_BINARY_DMP",
+ 0x919F, "GL_TEXTURE_BUFFER_OFFSET_ALIGNMENT_OES",
},
{
- 0x9251,
- "GL_SMAPHS30_PROGRAM_BINARY_DMP",
+ 0x91A6, "GL_TEXTURE_SPARSE_EXT",
},
{
- 0x9252,
- "GL_SMAPHS_PROGRAM_BINARY_DMP",
+ 0x91A7, "GL_VIRTUAL_PAGE_SIZE_INDEX_EXT",
},
{
- 0x9253,
- "GL_DMP_PROGRAM_BINARY_DMP",
+ 0x91A8, "GL_NUM_VIRTUAL_PAGE_SIZES_EXT",
},
{
- 0x9260,
- "GL_GCCSO_SHADER_BINARY_FJ",
+ 0x91A9, "GL_SPARSE_TEXTURE_FULL_ARRAY_CUBE_MIPMAPS_EXT",
},
{
- 0x9270,
- "GL_COMPRESSED_R11_EAC",
+ 0x91AA, "GL_NUM_SPARSE_LEVELS_EXT",
},
{
- 0x9271,
- "GL_COMPRESSED_SIGNED_R11_EAC",
+ 0x91B0, "GL_MAX_SHADER_COMPILER_THREADS_KHR",
},
{
- 0x9272,
- "GL_COMPRESSED_RG11_EAC",
+ 0x91B1, "GL_COMPLETION_STATUS_KHR",
},
{
- 0x9273,
- "GL_COMPRESSED_SIGNED_RG11_EAC",
+ 0x91B2, "GL_RENDERBUFFER_STORAGE_SAMPLES_AMD",
},
{
- 0x9274,
- "GL_COMPRESSED_RGB8_ETC2",
+ 0x91B3, "GL_MAX_COLOR_FRAMEBUFFER_SAMPLES_AMD",
},
{
- 0x9275,
- "GL_COMPRESSED_SRGB8_ETC2",
+ 0x91B4, "GL_MAX_COLOR_FRAMEBUFFER_STORAGE_SAMPLES_AMD",
},
{
- 0x9276,
- "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2",
+ 0x91B5, "GL_MAX_DEPTH_STENCIL_FRAMEBUFFER_SAMPLES_AMD",
},
{
- 0x9277,
- "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2",
+ 0x91B6, "GL_NUM_SUPPORTED_MULTISAMPLE_MODES_AMD",
},
{
- 0x9278,
- "GL_COMPRESSED_RGBA8_ETC2_EAC",
+ 0x91B7, "GL_SUPPORTED_MULTISAMPLE_MODES_AMD",
},
{
- 0x9279,
- "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC",
+ 0x91B9, "GL_COMPUTE_SHADER",
},
{
- 0x9280,
- "GL_BLEND_PREMULTIPLIED_SRC_NV",
+ 0x91BB, "GL_MAX_COMPUTE_UNIFORM_BLOCKS",
},
{
- 0x9281,
- "GL_BLEND_OVERLAP_NV",
+ 0x91BC, "GL_MAX_COMPUTE_TEXTURE_IMAGE_UNITS",
},
{
- 0x9282,
- "GL_UNCORRELATED_NV",
+ 0x91BD, "GL_MAX_COMPUTE_IMAGE_UNIFORMS",
},
{
- 0x9283,
- "GL_DISJOINT_NV",
+ 0x91BE, "GL_MAX_COMPUTE_WORK_GROUP_COUNT",
},
{
- 0x9284,
- "GL_CONJOINT_NV",
+ 0x91BF, "GL_MAX_COMPUTE_WORK_GROUP_SIZE",
},
{
- 0x9285,
- "GL_BLEND_ADVANCED_COHERENT_KHR",
+ 0x9243, "GL_UNPACK_COLORSPACE_CONVERSION_CHROMIUM",
},
{
- 0x9286,
- "GL_SRC_NV",
+ 0x9244, "GL_BIND_GENERATES_RESOURCE_CHROMIUM",
},
{
- 0x9287,
- "GL_DST_NV",
+ 0x9245, "GL_OVERLAY_TRANSFORM_NONE_CHROMIUM",
},
{
- 0x9288,
- "GL_SRC_OVER_NV",
+ 0x9246, "GL_OVERLAY_TRANSFORM_FLIP_HORIZONTAL_CHROMIUM",
},
{
- 0x9289,
- "GL_DST_OVER_NV",
+ 0x9247, "GL_OVERLAY_TRANSFORM_FLIP_VERTICAL_CHROMIUM",
},
{
- 0x928A,
- "GL_SRC_IN_NV",
+ 0x9248, "GL_OVERLAY_TRANSFORM_ROTATE_90_CHROMIUM",
},
{
- 0x928B,
- "GL_DST_IN_NV",
+ 0x9249, "GL_OVERLAY_TRANSFORM_ROTATE_180_CHROMIUM",
},
{
- 0x928C,
- "GL_SRC_OUT_NV",
+ 0x924A, "GL_OVERLAY_TRANSFORM_ROTATE_270_CHROMIUM",
},
{
- 0x928D,
- "GL_DST_OUT_NV",
+ 0x9250, "GL_SHADER_BINARY_DMP",
},
{
- 0x928E,
- "GL_SRC_ATOP_NV",
+ 0x9251, "GL_SMAPHS30_PROGRAM_BINARY_DMP",
},
{
- 0x928F,
- "GL_DST_ATOP_NV",
+ 0x9252, "GL_SMAPHS_PROGRAM_BINARY_DMP",
},
{
- 0x9291,
- "GL_PLUS_NV",
+ 0x9253, "GL_DMP_PROGRAM_BINARY_DMP",
},
{
- 0x9292,
- "GL_PLUS_DARKER_NV",
+ 0x9260, "GL_GCCSO_SHADER_BINARY_FJ",
},
{
- 0x9294,
- "GL_MULTIPLY_KHR",
+ 0x9270, "GL_COMPRESSED_R11_EAC",
},
{
- 0x9295,
- "GL_SCREEN_KHR",
+ 0x9271, "GL_COMPRESSED_SIGNED_R11_EAC",
},
{
- 0x9296,
- "GL_OVERLAY_KHR",
+ 0x9272, "GL_COMPRESSED_RG11_EAC",
},
{
- 0x9297,
- "GL_DARKEN_KHR",
+ 0x9273, "GL_COMPRESSED_SIGNED_RG11_EAC",
},
{
- 0x9298,
- "GL_LIGHTEN_KHR",
+ 0x9274, "GL_COMPRESSED_RGB8_ETC2",
},
{
- 0x9299,
- "GL_COLORDODGE_KHR",
+ 0x9275, "GL_COMPRESSED_SRGB8_ETC2",
},
{
- 0x929A,
- "GL_COLORBURN_KHR",
+ 0x9276, "GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2",
},
{
- 0x929B,
- "GL_HARDLIGHT_KHR",
+ 0x9277, "GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2",
},
{
- 0x929C,
- "GL_SOFTLIGHT_KHR",
+ 0x9278, "GL_COMPRESSED_RGBA8_ETC2_EAC",
},
{
- 0x929E,
- "GL_DIFFERENCE_KHR",
+ 0x9279, "GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC",
},
{
- 0x929F,
- "GL_MINUS_NV",
+ 0x9280, "GL_BLEND_PREMULTIPLIED_SRC_NV",
},
{
- 0x92A0,
- "GL_EXCLUSION_KHR",
+ 0x9281, "GL_BLEND_OVERLAP_NV",
},
{
- 0x92A1,
- "GL_CONTRAST_NV",
+ 0x9282, "GL_UNCORRELATED_NV",
},
{
- 0x92A3,
- "GL_INVERT_RGB_NV",
+ 0x9283, "GL_DISJOINT_NV",
},
{
- 0x92A4,
- "GL_LINEARDODGE_NV",
+ 0x9284, "GL_CONJOINT_NV",
},
{
- 0x92A5,
- "GL_LINEARBURN_NV",
+ 0x9285, "GL_BLEND_ADVANCED_COHERENT_KHR",
},
{
- 0x92A6,
- "GL_VIVIDLIGHT_NV",
+ 0x9286, "GL_SRC_NV",
},
{
- 0x92A7,
- "GL_LINEARLIGHT_NV",
+ 0x9287, "GL_DST_NV",
},
{
- 0x92A8,
- "GL_PINLIGHT_NV",
+ 0x9288, "GL_SRC_OVER_NV",
},
{
- 0x92A9,
- "GL_HARDMIX_NV",
+ 0x9289, "GL_DST_OVER_NV",
},
{
- 0x92AD,
- "GL_HSL_HUE_KHR",
+ 0x928A, "GL_SRC_IN_NV",
},
{
- 0x92AE,
- "GL_HSL_SATURATION_KHR",
+ 0x928B, "GL_DST_IN_NV",
},
{
- 0x92AF,
- "GL_HSL_COLOR_KHR",
+ 0x928C, "GL_SRC_OUT_NV",
},
{
- 0x92B0,
- "GL_HSL_LUMINOSITY_KHR",
+ 0x928D, "GL_DST_OUT_NV",
},
{
- 0x92B1,
- "GL_PLUS_CLAMPED_NV",
+ 0x928E, "GL_SRC_ATOP_NV",
},
{
- 0x92B2,
- "GL_PLUS_CLAMPED_ALPHA_NV",
+ 0x928F, "GL_DST_ATOP_NV",
},
{
- 0x92B3,
- "GL_MINUS_CLAMPED_NV",
+ 0x9291, "GL_PLUS_NV",
},
{
- 0x92B4,
- "GL_INVERT_OVG_NV",
+ 0x9292, "GL_PLUS_DARKER_NV",
},
{
- 0x92BE,
- "GL_PRIMITIVE_BOUNDING_BOX_OES",
+ 0x9294, "GL_MULTIPLY_KHR",
},
{
- 0x92C0,
- "GL_ATOMIC_COUNTER_BUFFER",
+ 0x9295, "GL_SCREEN_KHR",
},
{
- 0x92C1,
- "GL_ATOMIC_COUNTER_BUFFER_BINDING",
+ 0x9296, "GL_OVERLAY_KHR",
},
{
- 0x92C2,
- "GL_ATOMIC_COUNTER_BUFFER_START",
+ 0x9297, "GL_DARKEN_KHR",
},
{
- 0x92C3,
- "GL_ATOMIC_COUNTER_BUFFER_SIZE",
+ 0x9298, "GL_LIGHTEN_KHR",
},
{
- 0x92CC,
- "GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS",
+ 0x9299, "GL_COLORDODGE_KHR",
},
{
- 0x92CD,
- "GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_OES",
+ 0x929A, "GL_COLORBURN_KHR",
},
{
- 0x92CE,
- "GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_OES",
+ 0x929B, "GL_HARDLIGHT_KHR",
},
{
- 0x92CF,
- "GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_OES",
+ 0x929C, "GL_SOFTLIGHT_KHR",
},
{
- 0x92D0,
- "GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS",
+ 0x929E, "GL_DIFFERENCE_KHR",
},
{
- 0x92D1,
- "GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS",
+ 0x929F, "GL_MINUS_NV",
},
{
- 0x92D2,
- "GL_MAX_VERTEX_ATOMIC_COUNTERS",
+ 0x92A0, "GL_EXCLUSION_KHR",
},
{
- 0x92D3,
- "GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_OES",
+ 0x92A1, "GL_CONTRAST_NV",
},
{
- 0x92D4,
- "GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_OES",
+ 0x92A3, "GL_INVERT_RGB_NV",
},
{
- 0x92D5,
- "GL_MAX_GEOMETRY_ATOMIC_COUNTERS_OES",
+ 0x92A4, "GL_LINEARDODGE_NV",
},
{
- 0x92D6,
- "GL_MAX_FRAGMENT_ATOMIC_COUNTERS",
+ 0x92A5, "GL_LINEARBURN_NV",
},
{
- 0x92D7,
- "GL_MAX_COMBINED_ATOMIC_COUNTERS",
+ 0x92A6, "GL_VIVIDLIGHT_NV",
},
{
- 0x92D8,
- "GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE",
+ 0x92A7, "GL_LINEARLIGHT_NV",
},
{
- 0x92D9,
- "GL_ACTIVE_ATOMIC_COUNTER_BUFFERS",
+ 0x92A8, "GL_PINLIGHT_NV",
},
{
- 0x92DB,
- "GL_UNSIGNED_INT_ATOMIC_COUNTER",
+ 0x92A9, "GL_HARDMIX_NV",
},
{
- 0x92DC,
- "GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS",
+ 0x92AD, "GL_HSL_HUE_KHR",
},
{
- 0x92DD,
- "GL_FRAGMENT_COVERAGE_TO_COLOR_NV",
+ 0x92AE, "GL_HSL_SATURATION_KHR",
},
{
- 0x92DE,
- "GL_FRAGMENT_COVERAGE_COLOR_NV",
+ 0x92AF, "GL_HSL_COLOR_KHR",
},
{
- 0x92E0,
- "GL_DEBUG_OUTPUT_KHR",
+ 0x92B0, "GL_HSL_LUMINOSITY_KHR",
},
{
- 0x92E1,
- "GL_UNIFORM",
+ 0x92B1, "GL_PLUS_CLAMPED_NV",
},
{
- 0x92E2,
- "GL_UNIFORM_BLOCK",
+ 0x92B2, "GL_PLUS_CLAMPED_ALPHA_NV",
},
{
- 0x92E3,
- "GL_PROGRAM_INPUT",
+ 0x92B3, "GL_MINUS_CLAMPED_NV",
},
{
- 0x92E4,
- "GL_PROGRAM_OUTPUT",
+ 0x92B4, "GL_INVERT_OVG_NV",
},
{
- 0x92E5,
- "GL_BUFFER_VARIABLE",
+ 0x92BE, "GL_PRIMITIVE_BOUNDING_BOX_OES",
},
{
- 0x92E6,
- "GL_SHADER_STORAGE_BLOCK",
+ 0x92C0, "GL_ATOMIC_COUNTER_BUFFER",
},
{
- 0x92E7,
- "GL_IS_PER_PATCH_OES",
+ 0x92C1, "GL_ATOMIC_COUNTER_BUFFER_BINDING",
},
{
- 0x92F4,
- "GL_TRANSFORM_FEEDBACK_VARYING",
+ 0x92C2, "GL_ATOMIC_COUNTER_BUFFER_START",
},
{
- 0x92F5,
- "GL_ACTIVE_RESOURCES",
+ 0x92C3, "GL_ATOMIC_COUNTER_BUFFER_SIZE",
},
{
- 0x92F6,
- "GL_MAX_NAME_LENGTH",
+ 0x92CC, "GL_MAX_VERTEX_ATOMIC_COUNTER_BUFFERS",
},
{
- 0x92F7,
- "GL_MAX_NUM_ACTIVE_VARIABLES",
+ 0x92CD, "GL_MAX_TESS_CONTROL_ATOMIC_COUNTER_BUFFERS_OES",
},
{
- 0x92F9,
- "GL_NAME_LENGTH",
+ 0x92CE, "GL_MAX_TESS_EVALUATION_ATOMIC_COUNTER_BUFFERS_OES",
},
{
- 0x92FA,
- "GL_TYPE",
+ 0x92CF, "GL_MAX_GEOMETRY_ATOMIC_COUNTER_BUFFERS_OES",
},
{
- 0x92FB,
- "GL_ARRAY_SIZE",
+ 0x92D0, "GL_MAX_FRAGMENT_ATOMIC_COUNTER_BUFFERS",
},
{
- 0x92FC,
- "GL_OFFSET",
+ 0x92D1, "GL_MAX_COMBINED_ATOMIC_COUNTER_BUFFERS",
},
{
- 0x92FD,
- "GL_BLOCK_INDEX",
+ 0x92D2, "GL_MAX_VERTEX_ATOMIC_COUNTERS",
},
{
- 0x92FE,
- "GL_ARRAY_STRIDE",
+ 0x92D3, "GL_MAX_TESS_CONTROL_ATOMIC_COUNTERS_OES",
},
{
- 0x92FF,
- "GL_MATRIX_STRIDE",
+ 0x92D4, "GL_MAX_TESS_EVALUATION_ATOMIC_COUNTERS_OES",
},
{
- 0x9300,
- "GL_IS_ROW_MAJOR",
+ 0x92D5, "GL_MAX_GEOMETRY_ATOMIC_COUNTERS_OES",
},
{
- 0x9301,
- "GL_ATOMIC_COUNTER_BUFFER_INDEX",
+ 0x92D6, "GL_MAX_FRAGMENT_ATOMIC_COUNTERS",
},
{
- 0x9302,
- "GL_BUFFER_BINDING",
+ 0x92D7, "GL_MAX_COMBINED_ATOMIC_COUNTERS",
},
{
- 0x9303,
- "GL_BUFFER_DATA_SIZE",
+ 0x92D8, "GL_MAX_ATOMIC_COUNTER_BUFFER_SIZE",
},
{
- 0x9304,
- "GL_NUM_ACTIVE_VARIABLES",
+ 0x92D9, "GL_ACTIVE_ATOMIC_COUNTER_BUFFERS",
},
{
- 0x9305,
- "GL_ACTIVE_VARIABLES",
+ 0x92DB, "GL_UNSIGNED_INT_ATOMIC_COUNTER",
},
{
- 0x9306,
- "GL_REFERENCED_BY_VERTEX_SHADER",
+ 0x92DC, "GL_MAX_ATOMIC_COUNTER_BUFFER_BINDINGS",
},
{
- 0x9307,
- "GL_REFERENCED_BY_TESS_CONTROL_SHADER_OES",
+ 0x92DD, "GL_FRAGMENT_COVERAGE_TO_COLOR_NV",
},
{
- 0x9308,
- "GL_REFERENCED_BY_TESS_EVALUATION_SHADER_OES",
+ 0x92DE, "GL_FRAGMENT_COVERAGE_COLOR_NV",
},
{
- 0x9309,
- "GL_REFERENCED_BY_GEOMETRY_SHADER_OES",
+ 0x92E0, "GL_DEBUG_OUTPUT_KHR",
},
{
- 0x930A,
- "GL_REFERENCED_BY_FRAGMENT_SHADER",
+ 0x92E1, "GL_UNIFORM",
},
{
- 0x930B,
- "GL_REFERENCED_BY_COMPUTE_SHADER",
+ 0x92E2, "GL_UNIFORM_BLOCK",
},
{
- 0x930C,
- "GL_TOP_LEVEL_ARRAY_SIZE",
+ 0x92E3, "GL_PROGRAM_INPUT",
},
{
- 0x930D,
- "GL_TOP_LEVEL_ARRAY_STRIDE",
+ 0x92E4, "GL_PROGRAM_OUTPUT",
},
{
- 0x930E,
- "GL_LOCATION",
+ 0x92E5, "GL_BUFFER_VARIABLE",
},
{
- 0x930F,
- "GL_LOCATION_INDEX_EXT",
+ 0x92E6, "GL_SHADER_STORAGE_BLOCK",
},
{
- 0x9310,
- "GL_FRAMEBUFFER_DEFAULT_WIDTH",
+ 0x92E7, "GL_IS_PER_PATCH_OES",
},
{
- 0x9311,
- "GL_FRAMEBUFFER_DEFAULT_HEIGHT",
+ 0x92F4, "GL_TRANSFORM_FEEDBACK_VARYING",
},
{
- 0x9312,
- "GL_FRAMEBUFFER_DEFAULT_LAYERS_OES",
+ 0x92F5, "GL_ACTIVE_RESOURCES",
},
{
- 0x9313,
- "GL_FRAMEBUFFER_DEFAULT_SAMPLES",
+ 0x92F6, "GL_MAX_NAME_LENGTH",
},
{
- 0x9314,
- "GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS",
+ 0x92F7, "GL_MAX_NUM_ACTIVE_VARIABLES",
},
{
- 0x9315,
- "GL_MAX_FRAMEBUFFER_WIDTH",
+ 0x92F9, "GL_NAME_LENGTH",
},
{
- 0x9316,
- "GL_MAX_FRAMEBUFFER_HEIGHT",
+ 0x92FA, "GL_TYPE",
},
{
- 0x9317,
- "GL_MAX_FRAMEBUFFER_LAYERS_OES",
+ 0x92FB, "GL_ARRAY_SIZE",
},
{
- 0x9318,
- "GL_MAX_FRAMEBUFFER_SAMPLES",
+ 0x92FC, "GL_OFFSET",
},
{
- 0x9327,
- "GL_RASTER_MULTISAMPLE_EXT",
+ 0x92FD, "GL_BLOCK_INDEX",
},
{
- 0x9328,
- "GL_RASTER_SAMPLES_EXT",
+ 0x92FE, "GL_ARRAY_STRIDE",
},
{
- 0x9329,
- "GL_MAX_RASTER_SAMPLES_EXT",
+ 0x92FF, "GL_MATRIX_STRIDE",
},
{
- 0x932A,
- "GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT",
+ 0x9300, "GL_IS_ROW_MAJOR",
},
{
- 0x932B,
- "GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT",
+ 0x9301, "GL_ATOMIC_COUNTER_BUFFER_INDEX",
},
{
- 0x932C,
- "GL_EFFECTIVE_RASTER_SAMPLES_EXT",
+ 0x9302, "GL_BUFFER_BINDING",
},
{
- 0x932D,
- "GL_DEPTH_SAMPLES_NV",
+ 0x9303, "GL_BUFFER_DATA_SIZE",
},
{
- 0x932E,
- "GL_STENCIL_SAMPLES_NV",
+ 0x9304, "GL_NUM_ACTIVE_VARIABLES",
},
{
- 0x932F,
- "GL_MIXED_DEPTH_SAMPLES_SUPPORTED_NV",
+ 0x9305, "GL_ACTIVE_VARIABLES",
},
{
- 0x9330,
- "GL_MIXED_STENCIL_SAMPLES_SUPPORTED_NV",
+ 0x9306, "GL_REFERENCED_BY_VERTEX_SHADER",
},
{
- 0x9331,
- "GL_COVERAGE_MODULATION_TABLE_NV",
+ 0x9307, "GL_REFERENCED_BY_TESS_CONTROL_SHADER_OES",
},
{
- 0x9332,
- "GL_COVERAGE_MODULATION_NV",
+ 0x9308, "GL_REFERENCED_BY_TESS_EVALUATION_SHADER_OES",
},
{
- 0x9333,
- "GL_COVERAGE_MODULATION_TABLE_SIZE_NV",
+ 0x9309, "GL_REFERENCED_BY_GEOMETRY_SHADER_OES",
},
{
- 0x933C,
- "GL_FILL_RECTANGLE_NV",
+ 0x930A, "GL_REFERENCED_BY_FRAGMENT_SHADER",
},
{
- 0x933D,
- "GL_SAMPLE_LOCATION_SUBPIXEL_BITS_NV",
+ 0x930B, "GL_REFERENCED_BY_COMPUTE_SHADER",
},
{
- 0x933E,
- "GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_NV",
+ 0x930C, "GL_TOP_LEVEL_ARRAY_SIZE",
},
{
- 0x933F,
- "GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_NV",
+ 0x930D, "GL_TOP_LEVEL_ARRAY_STRIDE",
},
{
- 0x9340,
- "GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_NV",
+ 0x930E, "GL_LOCATION",
},
{
- 0x9341,
- "GL_PROGRAMMABLE_SAMPLE_LOCATION_NV",
+ 0x930F, "GL_LOCATION_INDEX_EXT",
},
{
- 0x9342,
- "GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_NV",
+ 0x9310, "GL_FRAMEBUFFER_DEFAULT_WIDTH",
},
{
- 0x9343,
- "GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_NV",
+ 0x9311, "GL_FRAMEBUFFER_DEFAULT_HEIGHT",
},
{
- 0x9346,
- "GL_CONSERVATIVE_RASTERIZATION_NV",
+ 0x9312, "GL_FRAMEBUFFER_DEFAULT_LAYERS_OES",
},
{
- 0x9347,
- "GL_SUBPIXEL_PRECISION_BIAS_X_BITS_NV",
+ 0x9313, "GL_FRAMEBUFFER_DEFAULT_SAMPLES",
},
{
- 0x9348,
- "GL_SUBPIXEL_PRECISION_BIAS_Y_BITS_NV",
+ 0x9314, "GL_FRAMEBUFFER_DEFAULT_FIXED_SAMPLE_LOCATIONS",
},
{
- 0x9349,
- "GL_MAX_SUBPIXEL_PRECISION_BIAS_BITS_NV",
+ 0x9315, "GL_MAX_FRAMEBUFFER_WIDTH",
},
{
- 0x9350,
- "GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV",
+ 0x9316, "GL_MAX_FRAMEBUFFER_HEIGHT",
},
{
- 0x9351,
- "GL_VIEWPORT_SWIZZLE_NEGATIVE_X_NV",
+ 0x9317, "GL_MAX_FRAMEBUFFER_LAYERS_OES",
},
{
- 0x9352,
- "GL_VIEWPORT_SWIZZLE_POSITIVE_Y_NV",
+ 0x9318, "GL_MAX_FRAMEBUFFER_SAMPLES",
},
{
- 0x9353,
- "GL_VIEWPORT_SWIZZLE_NEGATIVE_Y_NV",
+ 0x9327, "GL_RASTER_MULTISAMPLE_EXT",
},
{
- 0x9354,
- "GL_VIEWPORT_SWIZZLE_POSITIVE_Z_NV",
+ 0x9328, "GL_RASTER_SAMPLES_EXT",
},
{
- 0x9355,
- "GL_VIEWPORT_SWIZZLE_NEGATIVE_Z_NV",
+ 0x9329, "GL_MAX_RASTER_SAMPLES_EXT",
},
{
- 0x9356,
- "GL_VIEWPORT_SWIZZLE_POSITIVE_W_NV",
+ 0x932A, "GL_RASTER_FIXED_SAMPLE_LOCATIONS_EXT",
},
{
- 0x9357,
- "GL_VIEWPORT_SWIZZLE_NEGATIVE_W_NV",
+ 0x932B, "GL_MULTISAMPLE_RASTERIZATION_ALLOWED_EXT",
},
{
- 0x9358,
- "GL_VIEWPORT_SWIZZLE_X_NV",
+ 0x932C, "GL_EFFECTIVE_RASTER_SAMPLES_EXT",
},
{
- 0x9359,
- "GL_VIEWPORT_SWIZZLE_Y_NV",
+ 0x932D, "GL_DEPTH_SAMPLES_NV",
},
{
- 0x935A,
- "GL_VIEWPORT_SWIZZLE_Z_NV",
+ 0x932E, "GL_STENCIL_SAMPLES_NV",
},
{
- 0x935B,
- "GL_VIEWPORT_SWIZZLE_W_NV",
+ 0x932F, "GL_MIXED_DEPTH_SAMPLES_SUPPORTED_NV",
},
{
- 0x9368,
- "GL_FONT_GLYPHS_AVAILABLE_NV",
+ 0x9330, "GL_MIXED_STENCIL_SAMPLES_SUPPORTED_NV",
},
{
- 0x9369,
- "GL_FONT_TARGET_UNAVAILABLE_NV",
+ 0x9331, "GL_COVERAGE_MODULATION_TABLE_NV",
},
{
- 0x936A,
- "GL_FONT_UNAVAILABLE_NV",
+ 0x9332, "GL_COVERAGE_MODULATION_NV",
},
{
- 0x936B,
- "GL_FONT_UNINTELLIGIBLE_NV",
+ 0x9333, "GL_COVERAGE_MODULATION_TABLE_SIZE_NV",
},
{
- 0x936C,
- "GL_STANDARD_FONT_FORMAT_NV",
+ 0x933C, "GL_FILL_RECTANGLE_NV",
},
{
- 0x936D,
- "GL_FRAGMENT_INPUT_NV",
+ 0x933D, "GL_SAMPLE_LOCATION_SUBPIXEL_BITS_NV",
},
{
- 0x9371,
- "GL_MULTISAMPLES_NV",
+ 0x933E, "GL_SAMPLE_LOCATION_PIXEL_GRID_WIDTH_NV",
},
{
- 0x9372,
- "GL_SUPERSAMPLE_SCALE_X_NV",
+ 0x933F, "GL_SAMPLE_LOCATION_PIXEL_GRID_HEIGHT_NV",
},
{
- 0x9373,
- "GL_SUPERSAMPLE_SCALE_Y_NV",
+ 0x9340, "GL_PROGRAMMABLE_SAMPLE_LOCATION_TABLE_SIZE_NV",
},
{
- 0x9374,
- "GL_CONFORMANT_NV",
+ 0x9341, "GL_PROGRAMMABLE_SAMPLE_LOCATION_NV",
},
{
- 0x9380,
- "GL_NUM_SAMPLE_COUNTS",
+ 0x9342, "GL_FRAMEBUFFER_PROGRAMMABLE_SAMPLE_LOCATIONS_NV",
},
{
- 0x93A0,
- "GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE",
+ 0x9343, "GL_FRAMEBUFFER_SAMPLE_LOCATION_PIXEL_GRID_NV",
},
{
- 0x93A1,
- "GL_BGRA8_EXT",
+ 0x9346, "GL_CONSERVATIVE_RASTERIZATION_NV",
},
{
- 0x93A2,
- "GL_TEXTURE_USAGE_ANGLE",
+ 0x9347, "GL_SUBPIXEL_PRECISION_BIAS_X_BITS_NV",
},
{
- 0x93A3,
- "GL_FRAMEBUFFER_ATTACHMENT_ANGLE",
+ 0x9348, "GL_SUBPIXEL_PRECISION_BIAS_Y_BITS_NV",
},
{
- 0x93A4,
- "GL_PACK_REVERSE_ROW_ORDER_ANGLE",
+ 0x9349, "GL_MAX_SUBPIXEL_PRECISION_BIAS_BITS_NV",
},
{
- 0x93A6,
- "GL_PROGRAM_BINARY_ANGLE",
+ 0x9350, "GL_VIEWPORT_SWIZZLE_POSITIVE_X_NV",
},
{
- 0x93B0,
- "GL_COMPRESSED_RGBA_ASTC_4x4_KHR",
+ 0x9351, "GL_VIEWPORT_SWIZZLE_NEGATIVE_X_NV",
},
{
- 0x93B1,
- "GL_COMPRESSED_RGBA_ASTC_5x4_KHR",
+ 0x9352, "GL_VIEWPORT_SWIZZLE_POSITIVE_Y_NV",
},
{
- 0x93B2,
- "GL_COMPRESSED_RGBA_ASTC_5x5_KHR",
+ 0x9353, "GL_VIEWPORT_SWIZZLE_NEGATIVE_Y_NV",
},
{
- 0x93B3,
- "GL_COMPRESSED_RGBA_ASTC_6x5_KHR",
+ 0x9354, "GL_VIEWPORT_SWIZZLE_POSITIVE_Z_NV",
},
{
- 0x93B4,
- "GL_COMPRESSED_RGBA_ASTC_6x6_KHR",
+ 0x9355, "GL_VIEWPORT_SWIZZLE_NEGATIVE_Z_NV",
},
{
- 0x93B5,
- "GL_COMPRESSED_RGBA_ASTC_8x5_KHR",
+ 0x9356, "GL_VIEWPORT_SWIZZLE_POSITIVE_W_NV",
},
{
- 0x93B6,
- "GL_COMPRESSED_RGBA_ASTC_8x6_KHR",
+ 0x9357, "GL_VIEWPORT_SWIZZLE_NEGATIVE_W_NV",
},
{
- 0x93B7,
- "GL_COMPRESSED_RGBA_ASTC_8x8_KHR",
+ 0x9358, "GL_VIEWPORT_SWIZZLE_X_NV",
},
{
- 0x93B8,
- "GL_COMPRESSED_RGBA_ASTC_10x5_KHR",
+ 0x9359, "GL_VIEWPORT_SWIZZLE_Y_NV",
},
{
- 0x93B9,
- "GL_COMPRESSED_RGBA_ASTC_10x6_KHR",
+ 0x935A, "GL_VIEWPORT_SWIZZLE_Z_NV",
},
{
- 0x93BA,
- "GL_COMPRESSED_RGBA_ASTC_10x8_KHR",
+ 0x935B, "GL_VIEWPORT_SWIZZLE_W_NV",
},
{
- 0x93BB,
- "GL_COMPRESSED_RGBA_ASTC_10x10_KHR",
+ 0x935C, "GL_CLIP_ORIGIN_EXT",
},
{
- 0x93BC,
- "GL_COMPRESSED_RGBA_ASTC_12x10_KHR",
+ 0x935D, "GL_CLIP_DEPTH_MODE_EXT",
},
{
- 0x93BD,
- "GL_COMPRESSED_RGBA_ASTC_12x12_KHR",
+ 0x935E, "GL_NEGATIVE_ONE_TO_ONE_EXT",
},
{
- 0x93C0,
- "GL_COMPRESSED_RGBA_ASTC_3x3x3_OES",
+ 0x935F, "GL_ZERO_TO_ONE_EXT",
},
{
- 0x93C1,
- "GL_COMPRESSED_RGBA_ASTC_4x3x3_OES",
+ 0x9366, "GL_TEXTURE_REDUCTION_MODE_EXT",
},
{
- 0x93C2,
- "GL_COMPRESSED_RGBA_ASTC_4x4x3_OES",
+ 0x9367, "GL_WEIGHTED_AVERAGE_EXT",
},
{
- 0x93C3,
- "GL_COMPRESSED_RGBA_ASTC_4x4x4_OES",
+ 0x9368, "GL_FONT_GLYPHS_AVAILABLE_NV",
},
{
- 0x93C4,
- "GL_COMPRESSED_RGBA_ASTC_5x4x4_OES",
+ 0x9369, "GL_FONT_TARGET_UNAVAILABLE_NV",
},
{
- 0x93C5,
- "GL_COMPRESSED_RGBA_ASTC_5x5x4_OES",
+ 0x936A, "GL_FONT_UNAVAILABLE_NV",
},
{
- 0x93C6,
- "GL_COMPRESSED_RGBA_ASTC_5x5x5_OES",
+ 0x936B, "GL_FONT_UNINTELLIGIBLE_NV",
},
{
- 0x93C7,
- "GL_COMPRESSED_RGBA_ASTC_6x5x5_OES",
+ 0x936C, "GL_STANDARD_FONT_FORMAT_NV",
},
{
- 0x93C8,
- "GL_COMPRESSED_RGBA_ASTC_6x6x5_OES",
+ 0x936D, "GL_FRAGMENT_INPUT_NV",
},
{
- 0x93C9,
- "GL_COMPRESSED_RGBA_ASTC_6x6x6_OES",
+ 0x9371, "GL_MULTISAMPLES_NV",
},
{
- 0x93D0,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR",
+ 0x9372, "GL_SUPERSAMPLE_SCALE_X_NV",
},
{
- 0x93D1,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR",
+ 0x9373, "GL_SUPERSAMPLE_SCALE_Y_NV",
},
{
- 0x93D2,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR",
+ 0x9374, "GL_CONFORMANT_NV",
},
{
- 0x93D3,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR",
+ 0x937C, "GL_VIEWPORT_POSITION_W_SCALE_NV",
},
{
- 0x93D4,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR",
+ 0x937D, "GL_VIEWPORT_POSITION_W_SCALE_X_COEFF_NV",
},
{
- 0x93D5,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR",
+ 0x937E, "GL_VIEWPORT_POSITION_W_SCALE_Y_COEFF_NV",
},
{
- 0x93D6,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR",
+ 0x9380, "GL_NUM_SAMPLE_COUNTS",
},
{
- 0x93D7,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR",
+ 0x93A0, "GL_TRANSLATED_SHADER_SOURCE_LENGTH_ANGLE",
},
{
- 0x93D8,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR",
+ 0x93A1, "GL_BGRA8_EXT",
},
{
- 0x93D9,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR",
+ 0x93A2, "GL_TEXTURE_USAGE_ANGLE",
},
{
- 0x93DA,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR",
+ 0x93A3, "GL_FRAMEBUFFER_ATTACHMENT_ANGLE",
},
{
- 0x93DB,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR",
+ 0x93A4, "GL_PACK_REVERSE_ROW_ORDER_ANGLE",
},
{
- 0x93DC,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR",
+ 0x93A6, "GL_PROGRAM_BINARY_ANGLE",
},
{
- 0x93DD,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR",
+ 0x93B0, "GL_COMPRESSED_RGBA_ASTC_4x4_KHR",
},
{
- 0x93E0,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES",
+ 0x93B1, "GL_COMPRESSED_RGBA_ASTC_5x4_KHR",
},
{
- 0x93E1,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES",
+ 0x93B2, "GL_COMPRESSED_RGBA_ASTC_5x5_KHR",
},
{
- 0x93E2,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES",
+ 0x93B3, "GL_COMPRESSED_RGBA_ASTC_6x5_KHR",
},
{
- 0x93E3,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES",
+ 0x93B4, "GL_COMPRESSED_RGBA_ASTC_6x6_KHR",
},
{
- 0x93E4,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES",
+ 0x93B5, "GL_COMPRESSED_RGBA_ASTC_8x5_KHR",
},
{
- 0x93E5,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES",
+ 0x93B6, "GL_COMPRESSED_RGBA_ASTC_8x6_KHR",
},
{
- 0x93E6,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES",
+ 0x93B7, "GL_COMPRESSED_RGBA_ASTC_8x8_KHR",
},
{
- 0x93E7,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES",
+ 0x93B8, "GL_COMPRESSED_RGBA_ASTC_10x5_KHR",
},
{
- 0x93E8,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES",
+ 0x93B9, "GL_COMPRESSED_RGBA_ASTC_10x6_KHR",
},
{
- 0x93E9,
- "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES",
+ 0x93BA, "GL_COMPRESSED_RGBA_ASTC_10x8_KHR",
},
{
- 0x93F0,
- "GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2_IMG",
+ 0x93BB, "GL_COMPRESSED_RGBA_ASTC_10x10_KHR",
},
{
- 0x93F1,
- "GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2_IMG",
+ 0x93BC, "GL_COMPRESSED_RGBA_ASTC_12x10_KHR",
},
{
- 0x94F0,
- "GL_PERFQUERY_COUNTER_EVENT_INTEL",
+ 0x93BD, "GL_COMPRESSED_RGBA_ASTC_12x12_KHR",
},
{
- 0x94F1,
- "GL_PERFQUERY_COUNTER_DURATION_NORM_INTEL",
+ 0x93C0, "GL_COMPRESSED_RGBA_ASTC_3x3x3_OES",
},
{
- 0x94F2,
- "GL_PERFQUERY_COUNTER_DURATION_RAW_INTEL",
+ 0x93C1, "GL_COMPRESSED_RGBA_ASTC_4x3x3_OES",
},
{
- 0x94F3,
- "GL_PERFQUERY_COUNTER_THROUGHPUT_INTEL",
+ 0x93C2, "GL_COMPRESSED_RGBA_ASTC_4x4x3_OES",
},
{
- 0x94F4,
- "GL_PERFQUERY_COUNTER_RAW_INTEL",
+ 0x93C3, "GL_COMPRESSED_RGBA_ASTC_4x4x4_OES",
},
{
- 0x94F5,
- "GL_PERFQUERY_COUNTER_TIMESTAMP_INTEL",
+ 0x93C4, "GL_COMPRESSED_RGBA_ASTC_5x4x4_OES",
},
{
- 0x94F8,
- "GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL",
+ 0x93C5, "GL_COMPRESSED_RGBA_ASTC_5x5x4_OES",
},
{
- 0x94F9,
- "GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL",
+ 0x93C6, "GL_COMPRESSED_RGBA_ASTC_5x5x5_OES",
},
{
- 0x94FA,
- "GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL",
+ 0x93C7, "GL_COMPRESSED_RGBA_ASTC_6x5x5_OES",
},
{
- 0x94FB,
- "GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL",
+ 0x93C8, "GL_COMPRESSED_RGBA_ASTC_6x6x5_OES",
},
{
- 0x94FC,
- "GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL",
+ 0x93C9, "GL_COMPRESSED_RGBA_ASTC_6x6x6_OES",
},
{
- 0x94FD,
- "GL_PERFQUERY_QUERY_NAME_LENGTH_MAX_INTEL",
+ 0x93D0, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4_KHR",
},
{
- 0x94FE,
- "GL_PERFQUERY_COUNTER_NAME_LENGTH_MAX_INTEL",
+ 0x93D1, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4_KHR",
},
{
- 0x94FF,
- "GL_PERFQUERY_COUNTER_DESC_LENGTH_MAX_INTEL",
+ 0x93D2, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5_KHR",
},
{
- 0x9500,
- "GL_PERFQUERY_GPA_EXTENDED_COUNTERS_INTEL",
+ 0x93D3, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5_KHR",
},
{
- 0x954D,
- "GL_CONSERVATIVE_RASTER_MODE_NV",
+ 0x93D4, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR",
},
{
- 0x954E,
- "GL_CONSERVATIVE_RASTER_MODE_POST_SNAP_NV",
+ 0x93D5, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x5_KHR",
},
{
- 0x954F,
- "GL_CONSERVATIVE_RASTER_MODE_PRE_SNAP_TRIANGLES_NV",
+ 0x93D6, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x6_KHR",
},
{
- 0x9630,
- "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR",
+ 0x93D7, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_8x8_KHR",
},
{
- 0x9631,
- "GL_MAX_VIEWS_OVR",
+ 0x93D8, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR",
},
{
- 0x9632,
- "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR",
+ 0x93D9, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR",
},
{
- 0x9633,
- "GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR",
+ 0x93DA, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x8_KHR",
},
{
- 0x9650,
- "GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_FAST_SIZE_EXT",
+ 0x93DB, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR",
},
{
- 0x9651,
- "GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_SIZE_EXT",
+ 0x93DC, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR",
},
{
- 0x9652,
- "GL_FRAMEBUFFER_INCOMPLETE_INSUFFICIENT_SHADER_COMBINED_LOCAL_STORAGE_"
- "EXT",
+ 0x93DD, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR",
+ },
+ {
+ 0x93E0, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_3x3x3_OES",
+ },
+ {
+ 0x93E1, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x3x3_OES",
+ },
+ {
+ 0x93E2, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x3_OES",
+ },
+ {
+ 0x93E3, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_4x4x4_OES",
+ },
+ {
+ 0x93E4, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x4x4_OES",
+ },
+ {
+ 0x93E5, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x4_OES",
+ },
+ {
+ 0x93E6, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_5x5x5_OES",
+ },
+ {
+ 0x93E7, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x5x5_OES",
+ },
+ {
+ 0x93E8, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x5_OES",
+ },
+ {
+ 0x93E9, "GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6x6_OES",
+ },
+ {
+ 0x93F0, "GL_COMPRESSED_SRGB_ALPHA_PVRTC_2BPPV2_IMG",
+ },
+ {
+ 0x93F1, "GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV2_IMG",
+ },
+ {
+ 0x94F0, "GL_PERFQUERY_COUNTER_EVENT_INTEL",
+ },
+ {
+ 0x94F1, "GL_PERFQUERY_COUNTER_DURATION_NORM_INTEL",
+ },
+ {
+ 0x94F2, "GL_PERFQUERY_COUNTER_DURATION_RAW_INTEL",
+ },
+ {
+ 0x94F3, "GL_PERFQUERY_COUNTER_THROUGHPUT_INTEL",
+ },
+ {
+ 0x94F4, "GL_PERFQUERY_COUNTER_RAW_INTEL",
+ },
+ {
+ 0x94F5, "GL_PERFQUERY_COUNTER_TIMESTAMP_INTEL",
+ },
+ {
+ 0x94F8, "GL_PERFQUERY_COUNTER_DATA_UINT32_INTEL",
+ },
+ {
+ 0x94F9, "GL_PERFQUERY_COUNTER_DATA_UINT64_INTEL",
+ },
+ {
+ 0x94FA, "GL_PERFQUERY_COUNTER_DATA_FLOAT_INTEL",
+ },
+ {
+ 0x94FB, "GL_PERFQUERY_COUNTER_DATA_DOUBLE_INTEL",
+ },
+ {
+ 0x94FC, "GL_PERFQUERY_COUNTER_DATA_BOOL32_INTEL",
+ },
+ {
+ 0x94FD, "GL_PERFQUERY_QUERY_NAME_LENGTH_MAX_INTEL",
+ },
+ {
+ 0x94FE, "GL_PERFQUERY_COUNTER_NAME_LENGTH_MAX_INTEL",
+ },
+ {
+ 0x94FF, "GL_PERFQUERY_COUNTER_DESC_LENGTH_MAX_INTEL",
+ },
+ {
+ 0x9500, "GL_PERFQUERY_GPA_EXTENDED_COUNTERS_INTEL",
+ },
+ {
+ 0x9530, "GL_LAYOUT_DEPTH_READ_ONLY_STENCIL_ATTACHMENT_EXT",
+ },
+ {
+ 0x9531, "GL_LAYOUT_DEPTH_ATTACHMENT_STENCIL_READ_ONLY_EXT",
+ },
+ {
+ 0x954D, "GL_CONSERVATIVE_RASTER_MODE_NV",
+ },
+ {
+ 0x954E, "GL_CONSERVATIVE_RASTER_MODE_POST_SNAP_NV",
+ },
+ {
+ 0x954F, "GL_CONSERVATIVE_RASTER_MODE_PRE_SNAP_TRIANGLES_NV",
+ },
+ {
+ 0x9550, "GL_CONSERVATIVE_RASTER_MODE_PRE_SNAP_NV",
},
{
- 0xC0,
- "GL_SHARED_EDGE_NV",
+ 0x9580, "GL_TEXTURE_TILING_EXT",
},
{
- 0xE8,
- "GL_ROUNDED_RECT_NV",
+ 0x9581, "GL_DEDICATED_MEMORY_OBJECT_EXT",
+ },
+ {
+ 0x9582, "GL_NUM_TILING_TYPES_EXT",
+ },
+ {
+ 0x9583, "GL_TILING_TYPES_EXT",
+ },
+ {
+ 0x9584, "GL_OPTIMAL_TILING_EXT",
+ },
+ {
+ 0x9585, "GL_LINEAR_TILING_EXT",
+ },
+ {
+ 0x9586, "GL_HANDLE_TYPE_OPAQUE_FD_EXT",
+ },
+ {
+ 0x9587, "GL_HANDLE_TYPE_OPAQUE_WIN32_EXT",
+ },
+ {
+ 0x9588, "GL_HANDLE_TYPE_OPAQUE_WIN32_KMT_EXT",
+ },
+ {
+ 0x9589, "GL_HANDLE_TYPE_D3D12_TILEPOOL_EXT",
+ },
+ {
+ 0x958A, "GL_HANDLE_TYPE_D3D12_RESOURCE_EXT",
+ },
+ {
+ 0x958B, "GL_HANDLE_TYPE_D3D11_IMAGE_EXT",
+ },
+ {
+ 0x958C, "GL_HANDLE_TYPE_D3D11_IMAGE_KMT_EXT",
+ },
+ {
+ 0x958D, "GL_LAYOUT_GENERAL_EXT",
+ },
+ {
+ 0x958E, "GL_LAYOUT_COLOR_ATTACHMENT_EXT",
+ },
+ {
+ 0x958F, "GL_LAYOUT_DEPTH_STENCIL_ATTACHMENT_EXT",
+ },
+ {
+ 0x9590, "GL_LAYOUT_DEPTH_STENCIL_READ_ONLY_EXT",
+ },
+ {
+ 0x9591, "GL_LAYOUT_SHADER_READ_ONLY_EXT",
+ },
+ {
+ 0x9592, "GL_LAYOUT_TRANSFER_SRC_EXT",
+ },
+ {
+ 0x9593, "GL_LAYOUT_TRANSFER_DST_EXT",
+ },
+ {
+ 0x9594, "GL_HANDLE_TYPE_D3D12_FENCE_EXT",
+ },
+ {
+ 0x9595, "GL_D3D12_FENCE_VALUE_EXT",
+ },
+ {
+ 0x9596, "GL_NUM_DEVICE_UUIDS_EXT",
+ },
+ {
+ 0x9597, "GL_DEVICE_UUID_EXT",
+ },
+ {
+ 0x9598, "GL_DRIVER_UUID_EXT",
+ },
+ {
+ 0x9599, "GL_DEVICE_LUID_EXT",
+ },
+ {
+ 0x959A, "GL_DEVICE_NODE_MASK_EXT",
+ },
+ {
+ 0x959B, "GL_PROTECTED_MEMORY_OBJECT_EXT",
+ },
+ {
+ 0x9630, "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_NUM_VIEWS_OVR",
+ },
+ {
+ 0x9631, "GL_MAX_VIEWS_OVR",
+ },
+ {
+ 0x9632, "GL_FRAMEBUFFER_ATTACHMENT_TEXTURE_BASE_VIEW_INDEX_OVR",
+ },
+ {
+ 0x9633, "GL_FRAMEBUFFER_INCOMPLETE_VIEW_TARGETS_OVR",
+ },
+ {
+ 0x9650, "GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_FAST_SIZE_EXT",
+ },
+ {
+ 0x9651, "GL_MAX_SHADER_COMBINED_LOCAL_STORAGE_SIZE_EXT",
+ },
+ {
+ 0x9652,
+ "GL_FRAMEBUFFER_INCOMPLETE_INSUFFICIENT_SHADER_COMBINED_LOCAL_STORAGE_"
+ "EXT",
},
{
- 0xE9,
- "GL_RELATIVE_ROUNDED_RECT_NV",
+ 0x96A2, "GL_FRAMEBUFFER_FETCH_NONCOHERENT_QCOM",
},
{
- 0xEA,
- "GL_ROUNDED_RECT2_NV",
+ 0xC0, "GL_SHARED_EDGE_NV",
},
{
- 0xEB,
- "GL_RELATIVE_ROUNDED_RECT2_NV",
+ 0xE8, "GL_ROUNDED_RECT_NV",
},
{
- 0xEC,
- "GL_ROUNDED_RECT4_NV",
+ 0xE9, "GL_RELATIVE_ROUNDED_RECT_NV",
},
{
- 0xED,
- "GL_RELATIVE_ROUNDED_RECT4_NV",
+ 0xEA, "GL_ROUNDED_RECT2_NV",
},
{
- 0xEE,
- "GL_ROUNDED_RECT8_NV",
+ 0xEB, "GL_RELATIVE_ROUNDED_RECT2_NV",
},
{
- 0xEF,
- "GL_RELATIVE_ROUNDED_RECT8_NV",
+ 0xEC, "GL_ROUNDED_RECT4_NV",
},
{
- 0xF0,
- "GL_RESTART_PATH_NV",
+ 0xED, "GL_RELATIVE_ROUNDED_RECT4_NV",
},
{
- 0xF2,
- "GL_DUP_FIRST_CUBIC_CURVE_TO_NV",
+ 0xEE, "GL_ROUNDED_RECT8_NV",
},
{
- 0xF4,
- "GL_DUP_LAST_CUBIC_CURVE_TO_NV",
+ 0xEF, "GL_RELATIVE_ROUNDED_RECT8_NV",
},
{
- 0xF6,
- "GL_RECT_NV",
+ 0xF0, "GL_RESTART_PATH_NV",
},
{
- 0xF7,
- "GL_RELATIVE_RECT_NV",
+ 0xF2, "GL_DUP_FIRST_CUBIC_CURVE_TO_NV",
},
{
- 0xF8,
- "GL_CIRCULAR_CCW_ARC_TO_NV",
+ 0xF4, "GL_DUP_LAST_CUBIC_CURVE_TO_NV",
},
{
- 0xFA,
- "GL_CIRCULAR_CW_ARC_TO_NV",
+ 0xF6, "GL_RECT_NV",
},
{
- 0xFC,
- "GL_CIRCULAR_TANGENT_ARC_TO_NV",
+ 0xF7, "GL_RELATIVE_RECT_NV",
},
{
- 0xFE,
- "GL_ARC_TO_NV",
+ 0xF8, "GL_CIRCULAR_CCW_ARC_TO_NV",
},
{
- 0xFF,
- "GL_RELATIVE_ARC_TO_NV",
+ 0xFA, "GL_CIRCULAR_CW_ARC_TO_NV",
},
{
- 0xFFFFFFFF,
- "GL_ALL_SHADER_BITS_EXT",
+ 0xFC, "GL_CIRCULAR_TANGENT_ARC_TO_NV",
},
{
- 1,
- "GL_GLES_PROTOTYPES",
+ 0xFE, "GL_ARC_TO_NV",
},
{
- 16,
- "GL_MAILBOX_SIZE_CHROMIUM",
+ 0xFF, "GL_RELATIVE_ARC_TO_NV",
},
{
- 24,
- "GL_SYNC_TOKEN_SIZE_CHROMIUM",
+ 0xFFFFFFFF, "GL_ALL_SHADER_BITS_EXT",
},
};
diff --git a/chromium/ui/gl/gl_gl_api_implementation.cc b/chromium/ui/gl/gl_gl_api_implementation.cc
index 2313b1f238e..dd97b99a53a 100644
--- a/chromium/ui/gl/gl_gl_api_implementation.cc
+++ b/chromium/ui/gl/gl_gl_api_implementation.cc
@@ -80,25 +80,6 @@ static inline GLenum GetTexInternalFormat(const GLVersionInfo* version,
}
}
- if (type == GL_FLOAT && version->is_angle && version->is_es &&
- version->major_version == 2) {
- // It's possible that the texture is using a sized internal format, and
- // ANGLE exposing GLES2 API doesn't support those.
- // TODO(oetuaho@nvidia.com): Remove these conversions once ANGLE has the
- // support.
- // http://code.google.com/p/angleproject/issues/detail?id=556
- switch (format) {
- case GL_RGBA:
- gl_internal_format = GL_RGBA;
- break;
- case GL_RGB:
- gl_internal_format = GL_RGB;
- break;
- default:
- break;
- }
- }
-
if (version->IsAtLeastGL(2, 1) || version->IsAtLeastGLES(3, 0)) {
switch (internal_format) {
case GL_SRGB_EXT:
diff --git a/chromium/ui/gl/gl_image.cc b/chromium/ui/gl/gl_image.cc
index 8525c6c95b9..48b5a04d5aa 100644
--- a/chromium/ui/gl/gl_image.cc
+++ b/chromium/ui/gl/gl_image.cc
@@ -19,4 +19,21 @@ GLImage::Type GLImage::GetType() const {
return Type::NONE;
}
+#if defined(OS_ANDROID)
+std::unique_ptr<GLImage::ScopedHardwareBuffer> GLImage::GetAHardwareBuffer() {
+ return nullptr;
+}
+
+GLImage::ScopedHardwareBuffer::ScopedHardwareBuffer(
+ base::android::ScopedHardwareBufferHandle handle,
+ base::ScopedFD fence_fd)
+ : handle_(std::move(handle)), fence_fd_(std::move(fence_fd)) {}
+
+GLImage::ScopedHardwareBuffer::~ScopedHardwareBuffer() = default;
+
+base::ScopedFD GLImage::ScopedHardwareBuffer::TakeFence() {
+ return std::move(fence_fd_);
+}
+#endif
+
} // namespace gl
diff --git a/chromium/ui/gl/gl_image.h b/chromium/ui/gl/gl_image.h
index ecf8f011256..640ad8edaf1 100644
--- a/chromium/ui/gl/gl_image.h
+++ b/chromium/ui/gl/gl_image.h
@@ -11,6 +11,7 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "build/build_config.h"
#include "ui/gfx/color_space.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
@@ -21,6 +22,12 @@
#include "ui/gfx/overlay_transform.h"
#include "ui/gl/gl_export.h"
+#if defined(OS_ANDROID)
+#include <android/hardware_buffer.h>
+#include "base/android/scoped_hardware_buffer_handle.h"
+#include "base/files/scoped_file.h"
+#endif
+
namespace base {
namespace trace_event {
class ProcessMemoryDump;
@@ -104,6 +111,30 @@ class GL_EXPORT GLImage : public base::RefCounted<GLImage> {
// removed. https://crbug.com/581777#c36
virtual bool EmulatingRGB() const;
+#if defined(OS_ANDROID)
+ class GL_EXPORT ScopedHardwareBuffer {
+ public:
+ ScopedHardwareBuffer(base::android::ScopedHardwareBufferHandle handle,
+ base::ScopedFD fence_fd);
+ virtual ~ScopedHardwareBuffer();
+
+ AHardwareBuffer* buffer() const { return handle_.get(); }
+ base::ScopedFD TakeFence();
+
+ private:
+ base::android::ScopedHardwareBufferHandle handle_;
+ base::ScopedFD fence_fd_;
+ };
+
+ // Provides the buffer backing this image, if it is backed by an
+ // AHardwareBuffer. The ScopedHardwareBuffer returned may include a fence
+ // which will be signaled when all pending work for the buffer has been
+ // finished and it can be safely read from.
+ // The buffer is guaranteed to be valid until the lifetime of the object
+ // returned.
+ virtual std::unique_ptr<ScopedHardwareBuffer> GetAHardwareBuffer();
+#endif
+
// An identifier for subclasses. Necessary for safe downcasting.
enum class Type { NONE, MEMORY, IOSURFACE, DXGI_IMAGE };
virtual Type GetType() const;
diff --git a/chromium/ui/gl/gl_image_ahardwarebuffer.cc b/chromium/ui/gl/gl_image_ahardwarebuffer.cc
index 273f3acb181..89e97dcf894 100644
--- a/chromium/ui/gl/gl_image_ahardwarebuffer.cc
+++ b/chromium/ui/gl/gl_image_ahardwarebuffer.cc
@@ -15,6 +15,7 @@ GLImageAHardwareBuffer::~GLImageAHardwareBuffer() {}
bool GLImageAHardwareBuffer::Initialize(AHardwareBuffer* buffer,
bool preserved) {
+ handle_ = base::android::ScopedHardwareBufferHandle::Create(buffer);
EGLint attribs[] = {EGL_IMAGE_PRESERVED_KHR, preserved ? EGL_TRUE : EGL_FALSE,
EGL_NONE};
EGLClientBuffer client_buffer = eglGetNativeClientBufferANDROID(buffer);
@@ -54,4 +55,11 @@ void GLImageAHardwareBuffer::OnMemoryDump(
uint64_t process_tracing_id,
const std::string& dump_name) {}
+std::unique_ptr<GLImage::ScopedHardwareBuffer>
+GLImageAHardwareBuffer::GetAHardwareBuffer() {
+ return std::make_unique<ScopedHardwareBuffer>(
+ base::android::ScopedHardwareBufferHandle::Create(handle_.get()),
+ base::ScopedFD());
+}
+
} // namespace gl
diff --git a/chromium/ui/gl/gl_image_ahardwarebuffer.h b/chromium/ui/gl/gl_image_ahardwarebuffer.h
index a6245263ad6..c2241dbcc7c 100644
--- a/chromium/ui/gl/gl_image_ahardwarebuffer.h
+++ b/chromium/ui/gl/gl_image_ahardwarebuffer.h
@@ -5,6 +5,7 @@
#ifndef UI_GL_GL_IMAGE_AHARDWAREBUFFER_H_
#define UI_GL_GL_IMAGE_AHARDWAREBUFFER_H_
+#include "base/android/scoped_hardware_buffer_handle.h"
#include "base/macros.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_export.h"
@@ -37,11 +38,14 @@ class GL_EXPORT GLImageAHardwareBuffer : public GLImageEGL {
void OnMemoryDump(base::trace_event::ProcessMemoryDump* pmd,
uint64_t process_tracing_id,
const std::string& dump_name) override;
+ std::unique_ptr<ScopedHardwareBuffer> GetAHardwareBuffer() override;
protected:
~GLImageAHardwareBuffer() override;
private:
+ base::android::ScopedHardwareBufferHandle handle_;
+
DISALLOW_COPY_AND_ASSIGN(GLImageAHardwareBuffer);
};
diff --git a/chromium/ui/gl/gl_image_io_surface.mm b/chromium/ui/gl/gl_image_io_surface.mm
index 2bfff150064..5c84656101d 100644
--- a/chromium/ui/gl/gl_image_io_surface.mm
+++ b/chromium/ui/gl/gl_image_io_surface.mm
@@ -78,11 +78,6 @@ GLenum TextureFormat(gfx::BufferFormat format) {
// OpenGL ES 3.0, for the case) support only GL_RGBA (the hardware ignores
// the alpha channel anyway), see https://crbug.com/797347.
return GL_RGBA;
- case gfx::BufferFormat::ATC:
- case gfx::BufferFormat::ATCIA:
- case gfx::BufferFormat::DXT1:
- case gfx::BufferFormat::DXT5:
- case gfx::BufferFormat::ETC1:
case gfx::BufferFormat::BGR_565:
case gfx::BufferFormat::RGBA_4444:
case gfx::BufferFormat::RGBX_8888:
@@ -113,11 +108,6 @@ GLenum DataFormat(gfx::BufferFormat format) {
return GL_RGBA;
case gfx::BufferFormat::UYVY_422:
return GL_YCBCR_422_APPLE;
- case gfx::BufferFormat::ATC:
- case gfx::BufferFormat::ATCIA:
- case gfx::BufferFormat::DXT1:
- case gfx::BufferFormat::DXT5:
- case gfx::BufferFormat::ETC1:
case gfx::BufferFormat::BGR_565:
case gfx::BufferFormat::RGBA_4444:
case gfx::BufferFormat::RGBX_8888:
@@ -149,11 +139,6 @@ GLenum DataType(gfx::BufferFormat format) {
return GL_HALF_APPLE;
case gfx::BufferFormat::UYVY_422:
return GL_UNSIGNED_SHORT_8_8_APPLE;
- case gfx::BufferFormat::ATC:
- case gfx::BufferFormat::ATCIA:
- case gfx::BufferFormat::DXT1:
- case gfx::BufferFormat::DXT5:
- case gfx::BufferFormat::ETC1:
case gfx::BufferFormat::BGR_565:
case gfx::BufferFormat::RGBA_4444:
case gfx::BufferFormat::RGBX_8888:
@@ -514,11 +499,6 @@ bool GLImageIOSurface::ValidFormat(gfx::BufferFormat format) {
return true;
case gfx::BufferFormat::R_16:
case gfx::BufferFormat::RG_88:
- case gfx::BufferFormat::ATC:
- case gfx::BufferFormat::ATCIA:
- case gfx::BufferFormat::DXT1:
- case gfx::BufferFormat::DXT5:
- case gfx::BufferFormat::ETC1:
case gfx::BufferFormat::BGR_565:
case gfx::BufferFormat::RGBA_4444:
case gfx::BufferFormat::RGBX_8888:
diff --git a/chromium/ui/gl/gl_image_io_surface_egl.mm b/chromium/ui/gl/gl_image_io_surface_egl.mm
index b637ecc3e61..690af44dffe 100644
--- a/chromium/ui/gl/gl_image_io_surface_egl.mm
+++ b/chromium/ui/gl/gl_image_io_surface_egl.mm
@@ -50,11 +50,6 @@ InternalFormatType BufferFormatToInternalFormatType(gfx::BufferFormat format) {
case gfx::BufferFormat::BGRX_1010102:
NOTIMPLEMENTED();
return {GL_NONE, GL_NONE};
- case gfx::BufferFormat::ATC:
- case gfx::BufferFormat::ATCIA:
- case gfx::BufferFormat::DXT1:
- case gfx::BufferFormat::DXT5:
- case gfx::BufferFormat::ETC1:
case gfx::BufferFormat::BGR_565:
case gfx::BufferFormat::RGBA_4444:
case gfx::BufferFormat::RGBX_8888:
diff --git a/chromium/ui/gl/gl_image_memory.cc b/chromium/ui/gl/gl_image_memory.cc
index 3b44a540293..26bc08d82cd 100644
--- a/chromium/ui/gl/gl_image_memory.cc
+++ b/chromium/ui/gl/gl_image_memory.cc
@@ -23,11 +23,6 @@ namespace {
bool ValidInternalFormat(unsigned internalformat) {
switch (internalformat) {
- case GL_ATC_RGB_AMD:
- case GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD:
- case GL_COMPRESSED_RGB_S3TC_DXT1_EXT:
- case GL_COMPRESSED_RGBA_S3TC_DXT5_EXT:
- case GL_ETC1_RGB8_OES:
case GL_RED:
case GL_RG:
case GL_RGB:
@@ -40,50 +35,8 @@ bool ValidInternalFormat(unsigned internalformat) {
}
}
-bool IsCompressedFormat(gfx::BufferFormat format) {
- switch (format) {
- case gfx::BufferFormat::ATC:
- case gfx::BufferFormat::ATCIA:
- case gfx::BufferFormat::DXT1:
- case gfx::BufferFormat::DXT5:
- case gfx::BufferFormat::ETC1:
- return true;
- case gfx::BufferFormat::R_8:
- case gfx::BufferFormat::R_16:
- case gfx::BufferFormat::RG_88:
- case gfx::BufferFormat::BGR_565:
- case gfx::BufferFormat::RGBA_4444:
- case gfx::BufferFormat::RGBX_8888:
- case gfx::BufferFormat::RGBA_8888:
- case gfx::BufferFormat::BGRX_8888:
- case gfx::BufferFormat::BGRX_1010102:
- case gfx::BufferFormat::RGBX_1010102:
- case gfx::BufferFormat::BGRA_8888:
- case gfx::BufferFormat::RGBA_F16:
- return false;
- case gfx::BufferFormat::YVU_420:
- case gfx::BufferFormat::YUV_420_BIPLANAR:
- case gfx::BufferFormat::UYVY_422:
- NOTREACHED();
- return false;
- }
-
- NOTREACHED();
- return false;
-}
-
GLenum TextureFormat(gfx::BufferFormat format) {
switch (format) {
- case gfx::BufferFormat::ATC:
- return GL_ATC_RGB_AMD;
- case gfx::BufferFormat::ATCIA:
- return GL_ATC_RGBA_INTERPOLATED_ALPHA_AMD;
- case gfx::BufferFormat::DXT1:
- return GL_COMPRESSED_RGB_S3TC_DXT1_EXT;
- case gfx::BufferFormat::DXT5:
- return GL_COMPRESSED_RGBA_S3TC_DXT5_EXT;
- case gfx::BufferFormat::ETC1:
- return GL_ETC1_RGB8_OES;
case gfx::BufferFormat::R_8:
return GL_RED;
case gfx::BufferFormat::R_16:
@@ -132,11 +85,6 @@ GLenum DataFormat(gfx::BufferFormat format) {
case gfx::BufferFormat::R_8:
case gfx::BufferFormat::R_16:
case gfx::BufferFormat::RG_88:
- case gfx::BufferFormat::ATC:
- case gfx::BufferFormat::ATCIA:
- case gfx::BufferFormat::DXT1:
- case gfx::BufferFormat::DXT5:
- case gfx::BufferFormat::ETC1:
return TextureFormat(format);
case gfx::BufferFormat::YVU_420:
case gfx::BufferFormat::YUV_420_BIPLANAR:
@@ -169,11 +117,6 @@ GLenum DataType(gfx::BufferFormat format) {
case gfx::BufferFormat::BGRX_1010102:
case gfx::BufferFormat::RGBX_1010102:
return GL_UNSIGNED_INT_2_10_10_10_REV;
- case gfx::BufferFormat::ATC:
- case gfx::BufferFormat::ATCIA:
- case gfx::BufferFormat::DXT1:
- case gfx::BufferFormat::DXT5:
- case gfx::BufferFormat::ETC1:
case gfx::BufferFormat::YVU_420:
case gfx::BufferFormat::YUV_420_BIPLANAR:
case gfx::BufferFormat::UYVY_422:
@@ -203,11 +146,6 @@ GLint DataRowLength(size_t stride, gfx::BufferFormat format) {
return base::checked_cast<GLint>(stride) / 8;
case gfx::BufferFormat::R_8:
return base::checked_cast<GLint>(stride);
- case gfx::BufferFormat::ATC:
- case gfx::BufferFormat::ATCIA:
- case gfx::BufferFormat::DXT1:
- case gfx::BufferFormat::DXT5:
- case gfx::BufferFormat::ETC1:
case gfx::BufferFormat::YVU_420:
case gfx::BufferFormat::YUV_420_BIPLANAR:
case gfx::BufferFormat::UYVY_422:
@@ -335,12 +273,6 @@ std::unique_ptr<uint8_t[]> GLES2Data(const gfx::Size& size,
*data_row_length = size.width();
return gles2_data;
}
- case gfx::BufferFormat::ATC:
- case gfx::BufferFormat::ATCIA:
- case gfx::BufferFormat::DXT1:
- case gfx::BufferFormat::DXT5:
- case gfx::BufferFormat::ETC1:
- return nullptr; // No data conversion needed
case gfx::BufferFormat::YVU_420:
case gfx::BufferFormat::YUV_420_BIPLANAR:
case gfx::BufferFormat::UYVY_422:
@@ -391,8 +323,6 @@ bool GLImageMemory::Initialize(const unsigned char* memory,
DCHECK(memory);
DCHECK(!memory_);
- DCHECK(!IsCompressedFormat(format) || size_.width() % 4 == 0);
- DCHECK(!IsCompressedFormat(format) || size_.height() % 4 == 0);
memory_ = memory;
format_ = format;
stride_ = stride;
@@ -419,32 +349,25 @@ bool GLImageMemory::CopyTexImage(unsigned target) {
if (target == GL_TEXTURE_EXTERNAL_OES)
return false;
- if (IsCompressedFormat(format_)) {
- glCompressedTexImage2D(
- target, 0, TextureFormat(format_), size_.width(), size_.height(), 0,
- static_cast<GLsizei>(BufferSizeForBufferFormat(size_, format_)),
- memory_);
- } else {
- GLenum data_format = DataFormat(format_);
- GLenum data_type = DataType(format_);
- GLint data_row_length = DataRowLength(stride_, format_);
- std::unique_ptr<uint8_t[]> gles2_data;
-
- if (GLContext::GetCurrent()->GetVersionInfo()->is_es) {
- gles2_data = GLES2Data(size_, format_, stride_, memory_, &data_format,
- &data_type, &data_row_length);
- }
+ GLenum data_format = DataFormat(format_);
+ GLenum data_type = DataType(format_);
+ GLint data_row_length = DataRowLength(stride_, format_);
+ std::unique_ptr<uint8_t[]> gles2_data;
- if (data_row_length != size_.width())
- glPixelStorei(GL_UNPACK_ROW_LENGTH, data_row_length);
+ if (GLContext::GetCurrent()->GetVersionInfo()->is_es) {
+ gles2_data = GLES2Data(size_, format_, stride_, memory_, &data_format,
+ &data_type, &data_row_length);
+ }
- glTexImage2D(target, 0, TextureFormat(format_), size_.width(),
- size_.height(), 0, data_format, data_type,
- gles2_data ? gles2_data.get() : memory_);
+ if (data_row_length != size_.width())
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, data_row_length);
- if (data_row_length != size_.width())
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
- }
+ glTexImage2D(target, 0, TextureFormat(format_), size_.width(), size_.height(),
+ 0, data_format, data_type,
+ gles2_data ? gles2_data.get() : memory_);
+
+ if (data_row_length != size_.width())
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
return true;
}
@@ -464,37 +387,25 @@ bool GLImageMemory::CopyTexSubImage(unsigned target,
return false;
const uint8_t* data = memory_ + rect.y() * stride_;
- if (IsCompressedFormat(format_)) {
- // Height must be a multiple of 4.
- if (rect.height() % 4)
- return false;
-
- glCompressedTexSubImage2D(
- target, 0, offset.x(), offset.y(), rect.width(), rect.height(),
- DataFormat(format_),
- static_cast<GLsizei>(BufferSizeForBufferFormat(rect.size(), format_)),
- data);
- } else {
- GLenum data_format = DataFormat(format_);
- GLenum data_type = DataType(format_);
- GLint data_row_length = DataRowLength(stride_, format_);
- std::unique_ptr<uint8_t[]> gles2_data;
-
- if (GLContext::GetCurrent()->GetVersionInfo()->is_es) {
- gles2_data = GLES2Data(rect.size(), format_, stride_, data, &data_format,
- &data_type, &data_row_length);
- }
+ GLenum data_format = DataFormat(format_);
+ GLenum data_type = DataType(format_);
+ GLint data_row_length = DataRowLength(stride_, format_);
+ std::unique_ptr<uint8_t[]> gles2_data;
+
+ if (GLContext::GetCurrent()->GetVersionInfo()->is_es) {
+ gles2_data = GLES2Data(rect.size(), format_, stride_, data, &data_format,
+ &data_type, &data_row_length);
+ }
- if (data_row_length != rect.width())
- glPixelStorei(GL_UNPACK_ROW_LENGTH, data_row_length);
+ if (data_row_length != rect.width())
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, data_row_length);
- glTexSubImage2D(target, 0, offset.x(), offset.y(), rect.width(),
- rect.height(), data_format, data_type,
- gles2_data ? gles2_data.get() : data);
+ glTexSubImage2D(target, 0, offset.x(), offset.y(), rect.width(),
+ rect.height(), data_format, data_type,
+ gles2_data ? gles2_data.get() : data);
- if (data_row_length != rect.width())
- glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
- }
+ if (data_row_length != rect.width())
+ glPixelStorei(GL_UNPACK_ROW_LENGTH, 0);
return true;
}
@@ -523,11 +434,6 @@ unsigned GLImageMemory::GetInternalFormatForTesting(gfx::BufferFormat format) {
// static
bool GLImageMemory::ValidFormat(gfx::BufferFormat format) {
switch (format) {
- case gfx::BufferFormat::ATC:
- case gfx::BufferFormat::ATCIA:
- case gfx::BufferFormat::DXT1:
- case gfx::BufferFormat::DXT5:
- case gfx::BufferFormat::ETC1:
case gfx::BufferFormat::R_8:
case gfx::BufferFormat::R_16:
case gfx::BufferFormat::RG_88:
diff --git a/chromium/ui/gl/gl_image_native_pixmap.cc b/chromium/ui/gl/gl_image_native_pixmap.cc
index 13f9c3febb3..9ab046fa7bb 100644
--- a/chromium/ui/gl/gl_image_native_pixmap.cc
+++ b/chromium/ui/gl/gl_image_native_pixmap.cc
@@ -89,11 +89,6 @@ EGLint FourCC(gfx::BufferFormat format) {
return DRM_FORMAT_YVU420;
case gfx::BufferFormat::YUV_420_BIPLANAR:
return DRM_FORMAT_NV12;
- case gfx::BufferFormat::ATC:
- case gfx::BufferFormat::ATCIA:
- case gfx::BufferFormat::DXT1:
- case gfx::BufferFormat::DXT5:
- case gfx::BufferFormat::ETC1:
case gfx::BufferFormat::RGBA_4444:
case gfx::BufferFormat::BGRX_1010102:
case gfx::BufferFormat::RGBA_F16:
@@ -316,7 +311,7 @@ gfx::NativePixmapHandle GLImageNativePixmap::ExportHandle() {
// scoped_fd.release() transfers ownership to the caller so it will not
// call close when going out of scope. base::FileDescriptor never closes
// the fd when going out of scope. The auto_close flag is just a hint for
- // the user. When true it means the user has ownership of it so he is
+ // the user. When true it means the user has ownership of it so they are
// responsible for closing the fd.
handle.fds.emplace_back(
base::FileDescriptor(scoped_fd.release(), true /* auto_close */));
@@ -412,11 +407,6 @@ unsigned GLImageNativePixmap::GetInternalFormatForTesting(
return GL_RGB_YCRCB_420_CHROMIUM;
case gfx::BufferFormat::YUV_420_BIPLANAR:
return GL_RGB_YCBCR_420V_CHROMIUM;
- case gfx::BufferFormat::ATC:
- case gfx::BufferFormat::ATCIA:
- case gfx::BufferFormat::DXT1:
- case gfx::BufferFormat::DXT5:
- case gfx::BufferFormat::ETC1:
case gfx::BufferFormat::RGBA_4444:
case gfx::BufferFormat::BGRX_1010102:
case gfx::BufferFormat::RGBA_F16:
@@ -444,11 +434,6 @@ bool GLImageNativePixmap::ValidFormat(gfx::BufferFormat format) {
case gfx::BufferFormat::YVU_420:
case gfx::BufferFormat::YUV_420_BIPLANAR:
return true;
- case gfx::BufferFormat::ATC:
- case gfx::BufferFormat::ATCIA:
- case gfx::BufferFormat::DXT1:
- case gfx::BufferFormat::DXT5:
- case gfx::BufferFormat::ETC1:
case gfx::BufferFormat::RGBA_4444:
case gfx::BufferFormat::BGRX_1010102:
case gfx::BufferFormat::RGBA_F16:
diff --git a/chromium/ui/gl/gl_image_native_pixmap_unittest.cc b/chromium/ui/gl/gl_image_native_pixmap_unittest.cc
index 9cc799c509c..49ed7027f17 100644
--- a/chromium/ui/gl/gl_image_native_pixmap_unittest.cc
+++ b/chromium/ui/gl/gl_image_native_pixmap_unittest.cc
@@ -107,6 +107,8 @@ using GLImageTestTypes = testing::Types<
GLImageNativePixmapTestDelegate<gfx::BufferFormat::BGRX_8888>,
GLImageNativePixmapTestDelegate<gfx::BufferFormat::BGRA_8888>>;
+#if !defined(MEMORY_SANITIZER)
+// Fails under MSAN: crbug.com/886995
INSTANTIATE_TYPED_TEST_CASE_P(GLImageNativePixmap,
GLImageTest,
GLImageTestTypes);
@@ -118,6 +120,7 @@ INSTANTIATE_TYPED_TEST_CASE_P(GLImageNativePixmap,
INSTANTIATE_TYPED_TEST_CASE_P(GLImageNativePixmap,
GLImageNativePixmapToDmabufTest,
GLImageTestTypes);
+#endif
} // namespace
diff --git a/chromium/ui/gl/gl_mock_autogen_egl.h b/chromium/ui/gl/gl_mock_autogen_egl.h
index 4718f66c85b..fac8c3197e1 100644
--- a/chromium/ui/gl/gl_mock_autogen_egl.h
+++ b/chromium/ui/gl/gl_mock_autogen_egl.h
@@ -167,23 +167,6 @@ MOCK_METHOD6(PostSubBufferNV,
EGLint y,
EGLint width,
EGLint height));
-MOCK_METHOD2(ProgramCacheGetAttribANGLE,
- EGLint(EGLDisplay dpy, EGLenum attrib));
-MOCK_METHOD5(ProgramCachePopulateANGLE,
- void(EGLDisplay dpy,
- const void* key,
- EGLint keysize,
- const void* binary,
- EGLint binarysize));
-MOCK_METHOD6(ProgramCacheQueryANGLE,
- void(EGLDisplay dpy,
- EGLint index,
- void* key,
- EGLint* keysize,
- void* binary,
- EGLint* binarysize));
-MOCK_METHOD3(ProgramCacheResizeANGLE,
- EGLint(EGLDisplay dpy, EGLint limit, EGLenum mode));
MOCK_METHOD0(QueryAPI, EGLenum());
MOCK_METHOD4(QueryContext,
EGLBoolean(EGLDisplay dpy,
@@ -215,6 +198,10 @@ MOCK_METHOD4(QuerySurfacePointerANGLE,
MOCK_METHOD3(ReleaseTexImage,
EGLBoolean(EGLDisplay dpy, EGLSurface surface, EGLint buffer));
MOCK_METHOD0(ReleaseThread, EGLBoolean());
+MOCK_METHOD3(SetBlobCacheFuncsANDROID,
+ void(EGLDisplay dpy,
+ EGLSetBlobFuncANDROID set,
+ EGLGetBlobFuncANDROID get));
MOCK_METHOD4(StreamAttribKHR,
EGLBoolean(EGLDisplay dpy,
EGLStreamKHR stream,
diff --git a/chromium/ui/gl/gl_mock_autogen_gl.h b/chromium/ui/gl/gl_mock_autogen_gl.h
index f5a8375436e..37c95a26582 100644
--- a/chromium/ui/gl/gl_mock_autogen_gl.h
+++ b/chromium/ui/gl/gl_mock_autogen_gl.h
@@ -103,8 +103,6 @@ MOCK_METHOD4(
ColorMask,
void(GLboolean red, GLboolean green, GLboolean blue, GLboolean alpha));
MOCK_METHOD1(CompileShader, void(GLuint shader));
-MOCK_METHOD2(CompressedCopyTextureCHROMIUM,
- void(GLuint sourceId, GLuint destId));
MOCK_METHOD8(CompressedTexImage2D,
void(GLenum target,
GLint level,
@@ -870,6 +868,7 @@ MOCK_METHOD4(MapBufferRange,
GLbitfield access));
MOCK_METHOD2(MatrixLoadfEXT, void(GLenum matrixMode, const GLfloat* m));
MOCK_METHOD1(MatrixLoadIdentityEXT, void(GLenum matrixMode));
+MOCK_METHOD1(MaxShaderCompilerThreadsKHR, void(GLuint count));
MOCK_METHOD1(MemoryBarrierByRegion, void(GLbitfield barriers));
MOCK_METHOD1(MemoryBarrierEXT, void(GLbitfield barriers));
MOCK_METHOD1(MinSampleShading, void(GLfloat value));
diff --git a/chromium/ui/gl/gl_share_group.cc b/chromium/ui/gl/gl_share_group.cc
index 94708c09202..e9386c4b03d 100644
--- a/chromium/ui/gl/gl_share_group.cc
+++ b/chromium/ui/gl/gl_share_group.cc
@@ -42,9 +42,7 @@ void* GLShareGroup::GetHandle() {
}
GLContext* GLShareGroup::GetContext() {
- for (ContextSet::iterator it = contexts_.begin();
- it != contexts_.end();
- ++it) {
+ for (auto it = contexts_.begin(); it != contexts_.end(); ++it) {
if ((*it)->GetHandle())
return *it;
}
diff --git a/chromium/ui/gl/gl_stub_autogen_gl.h b/chromium/ui/gl/gl_stub_autogen_gl.h
index a2b558328c0..3f30f249b80 100644
--- a/chromium/ui/gl/gl_stub_autogen_gl.h
+++ b/chromium/ui/gl/gl_stub_autogen_gl.h
@@ -118,8 +118,6 @@ void glColorMaskFn(GLboolean red,
GLboolean blue,
GLboolean alpha) override {}
void glCompileShaderFn(GLuint shader) override {}
-void glCompressedCopyTextureCHROMIUMFn(GLuint sourceId,
- GLuint destId) override {}
void glCompressedTexImage2DFn(GLenum target,
GLint level,
GLenum internalformat,
@@ -878,6 +876,7 @@ void* glMapBufferRangeFn(GLenum target,
GLbitfield access) override;
void glMatrixLoadfEXTFn(GLenum matrixMode, const GLfloat* m) override {}
void glMatrixLoadIdentityEXTFn(GLenum matrixMode) override {}
+void glMaxShaderCompilerThreadsKHRFn(GLuint count) override {}
void glMemoryBarrierByRegionFn(GLbitfield barriers) override {}
void glMemoryBarrierEXTFn(GLbitfield barriers) override {}
void glMinSampleShadingFn(GLfloat value) override {}
diff --git a/chromium/ui/gl/gl_surface_egl.cc b/chromium/ui/gl/gl_surface_egl.cc
index 00cdf20fd2b..bb5e68bc4ff 100644
--- a/chromium/ui/gl/gl_surface_egl.cc
+++ b/chromium/ui/gl/gl_surface_egl.cc
@@ -16,6 +16,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
+#include "base/stl_util.h"
#include "base/strings/string_number_conversions.h"
#include "base/sys_info.h"
#include "base/trace_event/trace_event.h"
@@ -492,10 +493,8 @@ EGLConfig ChooseConfig(GLSurfaceFormat format, bool surfaceless) {
void AddInitDisplay(std::vector<DisplayType>* init_displays,
DisplayType display_type) {
// Make sure to not add the same display type twice.
- if (std::find(init_displays->begin(), init_displays->end(), display_type) ==
- init_displays->end()) {
+ if (!base::ContainsValue(*init_displays, display_type))
init_displays->push_back(display_type);
- }
}
const char* GetDebugMessageTypeString(EGLint source) {
@@ -1484,9 +1483,14 @@ bool NativeViewGLSurfaceEGL::GetFrameTimestampInfoIfAvailable(
if (presentation_time_ns == EGL_TIMESTAMP_PENDING_ANDROID) {
return false;
}
- *presentation_time = base::TimeTicks() +
- base::TimeDelta::FromNanoseconds(presentation_time_ns);
- *presentation_flags = presentation_flags_;
+ if (presentation_time_ns == EGL_TIMESTAMP_INVALID_ANDROID) {
+ *presentation_time = base::TimeTicks::Now();
+ } else {
+ *presentation_time = base::TimeTicks() +
+ base::TimeDelta::FromNanoseconds(presentation_time_ns);
+ *presentation_flags = presentation_flags_;
+ }
+ DCHECK(!presentation_time->is_null());
return true;
}
diff --git a/chromium/ui/gl/gl_surface_egl_surface_control.cc b/chromium/ui/gl/gl_surface_egl_surface_control.cc
new file mode 100644
index 00000000000..4a7cbb99290
--- /dev/null
+++ b/chromium/ui/gl/gl_surface_egl_surface_control.cc
@@ -0,0 +1,250 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/gl/gl_surface_egl_surface_control.h"
+
+#include "base/threading/thread_task_runner_handle.h"
+#include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/gl/gl_fence_android_native_fence_sync.h"
+#include "ui/gl/gl_image_ahardwarebuffer.h"
+
+namespace gl {
+namespace {
+
+constexpr char kSurfaceName[] = "ChromeSurface";
+
+} // namespace
+
+GLSurfaceEGLSurfaceControl::GLSurfaceEGLSurfaceControl(ANativeWindow* window) {
+ surface_composer_ = SurfaceComposer::Create(window);
+}
+
+GLSurfaceEGLSurfaceControl::~GLSurfaceEGLSurfaceControl() = default;
+
+bool GLSurfaceEGLSurfaceControl::Initialize(GLSurfaceFormat format) {
+ format_ = format;
+ return true;
+}
+
+void GLSurfaceEGLSurfaceControl::Destroy() {
+ pending_transaction_.reset();
+ surface_list_.clear();
+ surface_composer_.reset();
+}
+
+bool GLSurfaceEGLSurfaceControl::Resize(const gfx::Size& size,
+ float scale_factor,
+ ColorSpace color_space,
+ bool has_alpha) {
+ // Resizing requires resizing the SurfaceView in the browser.
+ return true;
+}
+
+bool GLSurfaceEGLSurfaceControl::IsOffscreen() {
+ return false;
+}
+
+gfx::SwapResult GLSurfaceEGLSurfaceControl::SwapBuffers(
+ const PresentationCallback& callback) {
+ NOTREACHED();
+ return gfx::SwapResult::SWAP_FAILED;
+}
+
+void GLSurfaceEGLSurfaceControl::SwapBuffersAsync(
+ const SwapCompletionCallback& completion_callback,
+ const PresentationCallback& presentation_callback) {
+ CommitPendingTransaction(completion_callback, presentation_callback);
+}
+
+gfx::SwapResult GLSurfaceEGLSurfaceControl::CommitOverlayPlanes(
+ const PresentationCallback& callback) {
+ NOTREACHED();
+ return gfx::SwapResult::SWAP_FAILED;
+}
+
+void GLSurfaceEGLSurfaceControl::CommitOverlayPlanesAsync(
+ const SwapCompletionCallback& completion_callback,
+ const PresentationCallback& presentation_callback) {
+ CommitPendingTransaction(completion_callback, presentation_callback);
+}
+
+void GLSurfaceEGLSurfaceControl::CommitPendingTransaction(
+ const SwapCompletionCallback& completion_callback,
+ const PresentationCallback& present_callback) {
+ DCHECK(pending_transaction_);
+
+ // Release resources for the current frame once the next frame is acked.
+ ResourceRefs resources_to_release;
+ resources_to_release.swap(current_frame_resources_);
+ current_frame_resources_.clear();
+
+ // Track resources to be owned by the framework after this transaction.
+ current_frame_resources_.swap(pending_frame_resources_);
+ pending_frame_resources_.clear();
+
+ pending_transaction_->Apply();
+ pending_transaction_.reset();
+
+ DCHECK_GE(surface_list_.size(), pending_surfaces_count_);
+ surface_list_.resize(pending_surfaces_count_);
+ pending_surfaces_count_ = 0u;
+
+ // TODO(khushalsagar): Send the legit timestamp when hooking up transaction
+ // acks.
+ constexpr int64_t kRefreshIntervalInMicroseconds =
+ base::Time::kMicrosecondsPerSecond / 60;
+ gfx::PresentationFeedback feedback(
+ base::TimeTicks::Now(),
+ base::TimeDelta::FromMicroseconds(kRefreshIntervalInMicroseconds),
+ 0 /* flags */);
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(OnTransactionAck, feedback, present_callback,
+ completion_callback, std::move(resources_to_release)));
+}
+
+gfx::Size GLSurfaceEGLSurfaceControl::GetSize() {
+ return gfx::Size(0, 0);
+}
+
+bool GLSurfaceEGLSurfaceControl::OnMakeCurrent(GLContext* context) {
+ return true;
+}
+
+bool GLSurfaceEGLSurfaceControl::ScheduleOverlayPlane(
+ int z_order,
+ gfx::OverlayTransform transform,
+ GLImage* image,
+ const gfx::Rect& bounds_rect,
+ const gfx::RectF& crop_rect,
+ bool enable_blend,
+ std::unique_ptr<gfx::GpuFence> gpu_fence) {
+ if (!pending_transaction_)
+ pending_transaction_.emplace();
+
+ bool uninitialized = false;
+ if (pending_surfaces_count_ == surface_list_.size()) {
+ uninitialized = true;
+ surface_list_.emplace_back(surface_composer_.get());
+ }
+ pending_surfaces_count_++;
+ auto& surface_state = surface_list_.at(pending_surfaces_count_ - 1);
+
+ if (uninitialized || surface_state.z_order != z_order) {
+ surface_state.z_order = z_order;
+ pending_transaction_->SetZOrder(surface_state.surface, z_order);
+ }
+
+ if (uninitialized || surface_state.transform != transform) {
+ surface_state.transform = transform;
+ // TODO(khushalsagar): Forward the transform once the NDK API is in place.
+ }
+
+ AHardwareBuffer* hardware_buffer = nullptr;
+ base::ScopedFD fence_fd;
+ auto scoped_hardware_buffer = image->GetAHardwareBuffer();
+ if (scoped_hardware_buffer) {
+ hardware_buffer = scoped_hardware_buffer->buffer();
+ fence_fd = scoped_hardware_buffer->TakeFence();
+ pending_frame_resources_.push_back(std::move(scoped_hardware_buffer));
+ }
+
+ if (uninitialized || surface_state.hardware_buffer != hardware_buffer) {
+ surface_state.hardware_buffer = hardware_buffer;
+
+ if (!fence_fd.is_valid() && gpu_fence && surface_state.hardware_buffer) {
+ auto fence_handle =
+ gfx::CloneHandleForIPC(gpu_fence->GetGpuFenceHandle());
+ DCHECK(!fence_handle.is_null());
+ fence_fd = base::ScopedFD(fence_handle.native_fd.fd);
+ }
+
+ pending_transaction_->SetBuffer(surface_state.surface,
+ surface_state.hardware_buffer,
+ std::move(fence_fd));
+ }
+
+ if (uninitialized || surface_state.bounds_rect != bounds_rect) {
+ surface_state.bounds_rect = bounds_rect;
+ pending_transaction_->SetPosition(surface_state.surface, bounds_rect.x(),
+ bounds_rect.y());
+ pending_transaction_->SetSize(surface_state.surface, bounds_rect.width(),
+ bounds_rect.height());
+ }
+
+ // TODO(khushalsagar): Currently the framework refuses to the draw the buffer
+ // if the crop rect doesn't exactly match the buffer size. Update when fixed.
+ /*gfx::Rect enclosed_crop_rect = gfx::ToEnclosedRect(crop_rect);
+ if (uninitialized || surface_state.crop_rect != enclosed_crop_rect) {
+ surface_state.crop_rect = enclosed_crop_rect;
+ pending_transaction_->SetCropRect(
+ surface_state.surface, enclosed_crop_rect.x(), enclosed_crop_rect.y(),
+ enclosed_crop_rect.right(), enclosed_crop_rect.bottom());
+ }*/
+
+ bool opaque = !enable_blend;
+ if (uninitialized || surface_state.opaque != opaque) {
+ surface_state.opaque = opaque;
+ pending_transaction_->SetOpaque(surface_state.surface, opaque);
+ }
+
+ return true;
+}
+
+bool GLSurfaceEGLSurfaceControl::IsSurfaceless() const {
+ return true;
+}
+
+void* GLSurfaceEGLSurfaceControl::GetHandle() {
+ return nullptr;
+}
+
+bool GLSurfaceEGLSurfaceControl::SupportsAsyncSwap() {
+ return true;
+}
+
+bool GLSurfaceEGLSurfaceControl::SupportsPlaneGpuFences() const {
+ return true;
+}
+
+bool GLSurfaceEGLSurfaceControl::SupportsPresentationCallback() {
+ return true;
+}
+
+bool GLSurfaceEGLSurfaceControl::SupportsSwapBuffersWithBounds() {
+ // TODO(khushalsagar): Add support for partial swap.
+ return false;
+}
+
+bool GLSurfaceEGLSurfaceControl::SupportsCommitOverlayPlanes() {
+ return true;
+}
+
+// static
+void GLSurfaceEGLSurfaceControl::OnTransactionAck(
+ const gfx::PresentationFeedback& feedback,
+ const PresentationCallback& present_callback,
+ const SwapCompletionCallback& completion_callback,
+ ResourceRefs resources) {
+ completion_callback.Run(gfx::SwapResult::SWAP_ACK, nullptr);
+ present_callback.Run(feedback);
+ resources.clear();
+}
+
+GLSurfaceEGLSurfaceControl::SurfaceState::SurfaceState(
+ SurfaceComposer* composer)
+ : surface(composer,
+ SurfaceComposer::SurfaceContentType::kAHardwareBuffer,
+ kSurfaceName) {}
+
+GLSurfaceEGLSurfaceControl::SurfaceState::SurfaceState() = default;
+GLSurfaceEGLSurfaceControl::SurfaceState::SurfaceState(SurfaceState&& other) =
+ default;
+GLSurfaceEGLSurfaceControl::SurfaceState&
+GLSurfaceEGLSurfaceControl::SurfaceState::operator=(SurfaceState&& other) =
+ default;
+
+GLSurfaceEGLSurfaceControl::SurfaceState::~SurfaceState() = default;
+
+} // namespace gl
diff --git a/chromium/ui/gl/gl_surface_egl_surface_control.h b/chromium/ui/gl/gl_surface_egl_surface_control.h
new file mode 100644
index 00000000000..dcfea68b7e7
--- /dev/null
+++ b/chromium/ui/gl/gl_surface_egl_surface_control.h
@@ -0,0 +1,121 @@
+// 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_GL_GL_SURFACE_EGL_SURFACE_CONTROL_H_
+#define UI_GL_GL_SURFACE_EGL_SURFACE_CONTROL_H_
+
+#include <android/native_window.h>
+
+#include "base/android/scoped_hardware_buffer_handle.h"
+#include "base/memory/weak_ptr.h"
+#include "base/optional.h"
+#include "ui/gl/android/android_surface_composer_compat.h"
+#include "ui/gl/gl_export.h"
+#include "ui/gl/gl_surface_egl.h"
+
+namespace gl {
+
+class GL_EXPORT GLSurfaceEGLSurfaceControl : public gl::GLSurfaceEGL {
+ public:
+ explicit GLSurfaceEGLSurfaceControl(ANativeWindow* window);
+
+ // GLSurface implementation.
+ bool Initialize(gl::GLSurfaceFormat format) override;
+ void Destroy() override;
+ bool Resize(const gfx::Size& size,
+ float scale_factor,
+ ColorSpace color_space,
+ bool has_alpha) override;
+ bool IsOffscreen() override;
+ gfx::SwapResult SwapBuffers(const PresentationCallback& callback) override;
+ void SwapBuffersAsync(
+ const SwapCompletionCallback& completion_callback,
+ const PresentationCallback& presentation_callback) override;
+ gfx::SwapResult CommitOverlayPlanes(
+ const PresentationCallback& callback) override;
+ void CommitOverlayPlanesAsync(
+ const SwapCompletionCallback& completion_callback,
+ const PresentationCallback& presentation_callback) override;
+ gfx::Size GetSize() override;
+ bool OnMakeCurrent(gl::GLContext* context) override;
+ bool ScheduleOverlayPlane(int z_order,
+ gfx::OverlayTransform transform,
+ gl::GLImage* image,
+ const gfx::Rect& bounds_rect,
+ const gfx::RectF& crop_rect,
+ bool enable_blend,
+ std::unique_ptr<gfx::GpuFence> gpu_fence) override;
+ bool IsSurfaceless() const override;
+ void* GetHandle() override;
+
+ bool SupportsAsyncSwap() override;
+ bool SupportsPlaneGpuFences() const override;
+ bool SupportsPresentationCallback() override;
+ bool SupportsSwapBuffersWithBounds() override;
+ bool SupportsCommitOverlayPlanes() override;
+
+ private:
+ ~GLSurfaceEGLSurfaceControl() override;
+
+ struct SurfaceState {
+ SurfaceState();
+ explicit SurfaceState(gl::SurfaceComposer* composer);
+ ~SurfaceState();
+
+ SurfaceState(SurfaceState&& other);
+ SurfaceState& operator=(SurfaceState&& other);
+
+ int z_order = 0;
+ gfx::OverlayTransform transform = gfx::OVERLAY_TRANSFORM_INVALID;
+ AHardwareBuffer* hardware_buffer = nullptr;
+ gfx::Rect bounds_rect;
+ gfx::Rect crop_rect;
+ bool opaque = true;
+
+ gl::SurfaceComposer::Surface surface;
+ };
+
+ using ResourceRefs =
+ std::vector<std::unique_ptr<GLImage::ScopedHardwareBuffer>>;
+
+ void CommitPendingTransaction(
+ const SwapCompletionCallback& completion_callback,
+ const PresentationCallback& callback);
+
+ static void OnTransactionAck(
+ const gfx::PresentationFeedback& feedback,
+ const PresentationCallback& present_callback,
+ const SwapCompletionCallback& completion_callback,
+ ResourceRefs resources);
+
+ // Holds the surface state changes made since the last call to SwapBuffers.
+ base::Optional<gl::SurfaceComposer::Transaction> pending_transaction_;
+
+ // The list of Surfaces and the corresponding state. The initial
+ // |pending_surfaces_count_| surfaces in this list are surfaces with state
+ // mutated since the last SwapBuffers with the updates collected in
+ // |pending_transaction_|.
+ // On the next SwapBuffers, the updates in the transaction are applied
+ // atomically and any surfaces in |surface_list_| which are not reused in this
+ // frame are destroyed.
+ std::vector<SurfaceState> surface_list_;
+ size_t pending_surfaces_count_ = 0u;
+
+ // Resources in the pending frame, for which updates are being
+ // collected in |pending_transaction_|. These are resources for which the
+ // pending transaction has a ref but they have not been applied and
+ // transferred to the framework.
+ ResourceRefs pending_frame_resources_;
+
+ // Resources in the current frame sent to the framework. The
+ // framework is assumed to retain ownership of these resources until the next
+ // frame update.
+ ResourceRefs current_frame_resources_;
+
+ std::unique_ptr<gl::SurfaceComposer> surface_composer_;
+};
+
+} // namespace gl
+
+#endif // UI_GL_GL_SURFACE_EGL_SURFACE_CONTROL_H_
diff --git a/chromium/ui/gl/gl_surface_egl_unittest.cc b/chromium/ui/gl/gl_surface_egl_unittest.cc
index b8788771500..b397b43705f 100644
--- a/chromium/ui/gl/gl_surface_egl_unittest.cc
+++ b/chromium/ui/gl/gl_surface_egl_unittest.cc
@@ -23,6 +23,8 @@ namespace {
class GLSurfaceEGLTest : public testing::Test {};
+#if !defined(MEMORY_SANITIZER)
+// Fails under MSAN: crbug.com/886995
TEST(GLSurfaceEGLTest, SurfaceFormatTest) {
GLSurfaceTestSupport::InitializeOneOffImplementation(
GLImplementation::kGLImplementationEGLGLES2, true);
@@ -46,6 +48,7 @@ TEST(GLSurfaceEGLTest, SurfaceFormatTest) {
eglGetConfigAttrib(surface->GetDisplay(), config, EGL_SAMPLES, &attrib);
EXPECT_EQ(0, attrib);
}
+#endif
#if defined(OS_WIN)
diff --git a/chromium/ui/gl/gpu_timing_fake.cc b/chromium/ui/gl/gpu_timing_fake.cc
index 4a3fc2ee571..f446617799f 100644
--- a/chromium/ui/gl/gpu_timing_fake.cc
+++ b/chromium/ui/gl/gpu_timing_fake.cc
@@ -223,7 +223,7 @@ void GPUTimingFake::FakeGLGetQueryObjectuiv(GLuint id, GLenum pname,
GLuint* params) {
switch (pname) {
case GL_QUERY_RESULT_AVAILABLE: {
- std::map<GLuint, QueryResult>::iterator it = query_results_.find(id);
+ auto it = query_results_.find(id);
if (it != query_results_.end() && it->second.value_ <= current_gl_time_)
*params = 1;
else
@@ -262,7 +262,7 @@ void GPUTimingFake::FakeGLGetQueryObjectui64v(GLuint id, GLenum pname,
GLuint64* params) {
switch (pname) {
case GL_QUERY_RESULT: {
- std::map<GLuint, QueryResult>::iterator it = query_results_.find(id);
+ auto it = query_results_.find(id);
ASSERT_TRUE(it != query_results_.end());
switch (it->second.type_) {
case QueryResult::kQueryResultType_TimeStamp:
diff --git a/chromium/ui/gl/init/BUILD.gn b/chromium/ui/gl/init/BUILD.gn
index d708e6c468b..b66913884f7 100644
--- a/chromium/ui/gl/init/BUILD.gn
+++ b/chromium/ui/gl/init/BUILD.gn
@@ -4,6 +4,7 @@
import("//build/config/jumbo.gni")
import("//build/config/ui.gni")
+import("//ui/gl/features.gni")
jumbo_component("init") {
output_name = "gl_init"
@@ -38,6 +39,10 @@ jumbo_component("init") {
"gl_factory_android.cc",
"gl_initializer_android.cc",
]
+
+ if (use_static_angle) {
+ deps += [ "//third_party/angle:libEGL_static" ]
+ }
} else if (is_win && !use_ozone) {
sources += [
"gl_factory_win.cc",
diff --git a/chromium/ui/gl/init/create_gr_gl_interface.cc b/chromium/ui/gl/init/create_gr_gl_interface.cc
index 005e6eb758c..598b98cdfd9 100644
--- a/chromium/ui/gl/init/create_gr_gl_interface.cc
+++ b/chromium/ui/gl/init/create_gr_gl_interface.cc
@@ -5,6 +5,7 @@
#include "ui/gl/init/create_gr_gl_interface.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_version_info.h"
+#include "ui/gl/progress_reporter.h"
namespace gl {
namespace init {
@@ -12,11 +13,33 @@ namespace init {
namespace {
template <typename R, typename... Args>
-GrGLFunction<R (*)(Args...)> bind(R (gl::GLApi::*func)(Args...),
- gl::GLApi* api) {
+GrGLFunction<R GR_GL_FUNCTION_TYPE(Args...)> bind(R (gl::GLApi::*func)(Args...),
+ gl::GLApi* api) {
return [func, api](Args... args) { return (api->*func)(args...); };
}
+class ScopedProgressReporter {
+ public:
+ ScopedProgressReporter(gl::ProgressReporter* progress_reporter)
+ : progress_reporter_(progress_reporter) {}
+ ~ScopedProgressReporter() { progress_reporter_->ReportProgress(); }
+
+ private:
+ gl::ProgressReporter* progress_reporter_;
+};
+
+template <typename R, typename... Args>
+GrGLFunction<R GR_GL_FUNCTION_TYPE(Args...)> bind_slow(
+ R(GL_BINDING_CALL* func)(Args...),
+ gl::ProgressReporter* progress_reporter) {
+ if (!progress_reporter)
+ return func;
+ return [func, progress_reporter](Args... args) {
+ ScopedProgressReporter scoped_reporter(progress_reporter);
+ return func(args...);
+ };
+};
+
const GLubyte* GetStringHook(const char* version_string, GLenum name) {
switch (name) {
case GL_VERSION:
@@ -47,7 +70,8 @@ const char* kBlacklistExtensions[] = {
sk_sp<GrGLInterface> CreateGrGLInterface(
const gl::GLVersionInfo& version_info,
- bool use_version_es2) {
+ bool use_version_es2,
+ gl::ProgressReporter* progress_reporter) {
// Can't fake ES with desktop GL.
use_version_es2 &= version_info.is_es;
@@ -63,7 +87,7 @@ sk_sp<GrGLInterface> CreateGrGLInterface(
// by the bindings (GL 4.1 or ES 3.0), and blacklist extensions that skia
// handles but bindings don't.
// TODO(piman): add bindings for missing entrypoints.
- GrGLFunction<GrGLGetStringProc> get_string;
+ GrGLFunction<GrGLGetStringFn> get_string;
const bool apply_version_override = use_version_es2 ||
version_info.IsAtLeastGL(4, 2) ||
version_info.IsAtLeastGLES(3, 1);
@@ -119,17 +143,23 @@ sk_sp<GrGLInterface> CreateGrGLInterface(
// functions->fClearTexSubImage = nullptr;
functions->fColorMask = gl->glColorMaskFn;
- functions->fCompileShader = gl->glCompileShaderFn;
- functions->fCompressedTexImage2D = gl->glCompressedTexImage2DFn;
- functions->fCompressedTexSubImage2D = gl->glCompressedTexSubImage2DFn;
- functions->fCopyTexSubImage2D = gl->glCopyTexSubImage2DFn;
+ functions->fCompileShader =
+ bind_slow(gl->glCompileShaderFn, progress_reporter);
+ functions->fCompressedTexImage2D =
+ bind_slow(gl->glCompressedTexImage2DFn, progress_reporter);
+ functions->fCompressedTexSubImage2D =
+ bind_slow(gl->glCompressedTexSubImage2DFn, progress_reporter);
+ functions->fCopyTexSubImage2D =
+ bind_slow(gl->glCopyTexSubImage2DFn, progress_reporter);
functions->fCreateProgram = gl->glCreateProgramFn;
functions->fCreateShader = gl->glCreateShaderFn;
functions->fCullFace = gl->glCullFaceFn;
- functions->fDeleteBuffers = gl->glDeleteBuffersARBFn;
- functions->fDeleteProgram = gl->glDeleteProgramFn;
+ functions->fDeleteBuffers =
+ bind_slow(gl->glDeleteBuffersARBFn, progress_reporter);
+ functions->fDeleteProgram =
+ bind_slow(gl->glDeleteProgramFn, progress_reporter);
functions->fDeleteQueries = gl->glDeleteQueriesFn;
- functions->fDeleteShader = gl->glDeleteShaderFn;
+ functions->fDeleteShader = bind_slow(gl->glDeleteShaderFn, progress_reporter);
functions->fDeleteTextures = gl->glDeleteTexturesFn;
functions->fDepthMask = gl->glDepthMaskFn;
functions->fDisable = gl->glDisableFn;
@@ -151,8 +181,8 @@ sk_sp<GrGLInterface> CreateGrGLInterface(
functions->fEnable = gl->glEnableFn;
functions->fEnableVertexAttribArray = gl->glEnableVertexAttribArrayFn;
functions->fEndQuery = gl->glEndQueryFn;
- functions->fFinish = gl->glFinishFn;
- functions->fFlush = gl->glFlushFn;
+ functions->fFinish = bind_slow(gl->glFinishFn, progress_reporter);
+ functions->fFlush = bind_slow(gl->glFlushFn, progress_reporter);
functions->fFrontFace = gl->glFrontFaceFn;
functions->fGenBuffers = gl->glGenBuffersARBFn;
functions->fGetBufferParameteriv = gl->glGetBufferParameterivFn;
@@ -179,7 +209,7 @@ sk_sp<GrGLInterface> CreateGrGLInterface(
functions->fGetUniformLocation = gl->glGetUniformLocationFn;
functions->fIsTexture = gl->glIsTextureFn;
functions->fLineWidth = gl->glLineWidthFn;
- functions->fLinkProgram = gl->glLinkProgramFn;
+ functions->fLinkProgram = bind_slow(gl->glLinkProgramFn, progress_reporter);
functions->fMapBuffer = gl->glMapBufferFn;
// GL 4.3 or GL_ARB_multi_draw_indirect or ES+GL_EXT_multi_draw_indirect
@@ -206,7 +236,7 @@ sk_sp<GrGLInterface> CreateGrGLInterface(
functions->fStencilOpSeparate = gl->glStencilOpSeparateFn;
functions->fTexBuffer = gl->glTexBufferFn;
functions->fTexBufferRange = gl->glTexBufferRangeFn;
- functions->fTexImage2D = gl->glTexImage2DFn;
+ functions->fTexImage2D = bind_slow(gl->glTexImage2DFn, progress_reporter);
functions->fTexParameteri = gl->glTexParameteriFn;
functions->fTexParameteriv = gl->glTexParameterivFn;
functions->fTexStorage2D = gl->glTexStorage2DEXTFn;
@@ -266,7 +296,8 @@ sk_sp<GrGLInterface> CreateGrGLInterface(
functions->fBindFramebuffer = gl->glBindFramebufferEXTFn;
functions->fFramebufferTexture2D = gl->glFramebufferTexture2DEXTFn;
functions->fCheckFramebufferStatus = gl->glCheckFramebufferStatusEXTFn;
- functions->fDeleteFramebuffers = gl->glDeleteFramebuffersEXTFn;
+ functions->fDeleteFramebuffers =
+ bind_slow(gl->glDeleteFramebuffersEXTFn, progress_reporter);
functions->fRenderbufferStorage = gl->glRenderbufferStorageEXTFn;
functions->fGenRenderbuffers = gl->glGenRenderbuffersEXTFn;
functions->fDeleteRenderbuffers = gl->glDeleteRenderbuffersEXTFn;
diff --git a/chromium/ui/gl/init/create_gr_gl_interface.h b/chromium/ui/gl/init/create_gr_gl_interface.h
index 4b23ee7fe90..9243fbea018 100644
--- a/chromium/ui/gl/init/create_gr_gl_interface.h
+++ b/chromium/ui/gl/init/create_gr_gl_interface.h
@@ -11,6 +11,7 @@
namespace gl {
struct GLVersionInfo;
+class ProgressReporter;
}
namespace gl {
@@ -20,7 +21,8 @@ namespace init {
// GL bindings.
GL_INIT_EXPORT sk_sp<GrGLInterface> CreateGrGLInterface(
const gl::GLVersionInfo& version_info,
- bool use_version_es2);
+ bool use_version_es2,
+ gl::ProgressReporter* progress_reporter = nullptr);
} // namespace init
} // namespace gl
diff --git a/chromium/ui/gl/init/gl_initializer_android.cc b/chromium/ui/gl/init/gl_initializer_android.cc
index 46ec1c7e0a9..22660c9207d 100644
--- a/chromium/ui/gl/init/gl_initializer_android.cc
+++ b/chromium/ui/gl/init/gl_initializer_android.cc
@@ -24,13 +24,17 @@ namespace init {
namespace {
-bool InitializeStaticEGLInternal() {
#if BUILDFLAG(USE_STATIC_ANGLE)
+bool InitializeStaticANGLEEGLInternal() {
#pragma push_macro("eglGetProcAddress")
#undef eglGetProcAddress
SetGLGetProcAddressProc(&eglGetProcAddress);
#pragma pop_macro("eglGetProcAddress")
-#else // BUILDFLAG(USE_STATIC_ANGLE)
+ return true;
+}
+#endif // BUILDFLAG(USE_STATIC_ANGLE)
+
+bool InitializeStaticNativeEGLInternal() {
base::NativeLibrary gles_library = LoadLibraryAndPrintError("libGLESv2.so");
if (!gles_library)
return false;
@@ -54,7 +58,32 @@ bool InitializeStaticEGLInternal() {
SetGLGetProcAddressProc(get_proc_address);
AddGLNativeLibrary(egl_library);
AddGLNativeLibrary(gles_library);
+
+ return true;
+}
+
+bool InitializeStaticEGLInternal() {
+ bool initialized = false;
+
+#if BUILDFLAG(USE_STATIC_ANGLE)
+ const base::CommandLine* command_line =
+ base::CommandLine::ForCurrentProcess();
+ // Use ANGLE if it is requested via the --use-gl=angle flag and it is
+ // statically linked
+ if (command_line->GetSwitchValueASCII(switches::kUseGL) ==
+ kGLImplementationANGLEName) {
+ initialized = InitializeStaticANGLEEGLInternal();
+ }
#endif // BUILDFLAG(USE_STATIC_ANGLE)
+
+ if (!initialized) {
+ initialized = InitializeStaticNativeEGLInternal();
+ }
+
+ if (!initialized) {
+ return false;
+ }
+
SetGLImplementation(kGLImplementationEGLGLES2);
InitializeStaticGLBindingsGL();
diff --git a/chromium/ui/gl/progress_reporter.h b/chromium/ui/gl/progress_reporter.h
new file mode 100644
index 00000000000..5ebcfe01e98
--- /dev/null
+++ b/chromium/ui/gl/progress_reporter.h
@@ -0,0 +1,22 @@
+// Copyright (c) 2016 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_PROGRESS_REPORTER_H_
+#define UI_GL_PROGRESS_REPORTER_H_
+
+namespace gl {
+
+// ProgressReporter is used by ContextGroup and GrGLInterface to report when it
+// is making forward progress in execution, delaying activation of the watchdog
+// timeout.
+class ProgressReporter {
+ public:
+ virtual ~ProgressReporter() = default;
+
+ virtual void ReportProgress() = 0;
+};
+
+} // namespace gl
+
+#endif // UI_GL_PROGRESS_REPORTER_H_
diff --git a/chromium/ui/gl/trace_util.cc b/chromium/ui/gl/trace_util.cc
index cd8b41fec0e..45a8dfafd52 100644
--- a/chromium/ui/gl/trace_util.cc
+++ b/chromium/ui/gl/trace_util.cc
@@ -10,34 +10,33 @@
namespace gl {
base::trace_event::MemoryAllocatorDumpGuid GetGLTextureClientGUIDForTracing(
- uint64_t share_group_guid,
+ uint64_t context_group_tracing_id,
uint32_t texture_id) {
return base::trace_event::MemoryAllocatorDumpGuid(
base::StringPrintf("gl-texture-client-x-process/%" PRIx64 "/%d",
- share_group_guid, texture_id));
+ context_group_tracing_id, texture_id));
}
base::trace_event::MemoryAllocatorDumpGuid GetGLTextureServiceGUIDForTracing(
- uint64_t share_group_guid,
uint32_t texture_id) {
return base::trace_event::MemoryAllocatorDumpGuid(
- base::StringPrintf("gl-texture-service-x-process/%" PRIx64 "/%d",
- share_group_guid, texture_id));
+ base::StringPrintf("gl-texture-service-x-process/%d", texture_id));
}
base::trace_event::MemoryAllocatorDumpGuid GetGLBufferGUIDForTracing(
- uint64_t share_group_guid,
+ uint64_t context_group_tracing_id,
uint32_t buffer_id) {
- return base::trace_event::MemoryAllocatorDumpGuid(base::StringPrintf(
- "gl-buffer-x-process/%" PRIx64 "/%d", share_group_guid, buffer_id));
+ return base::trace_event::MemoryAllocatorDumpGuid(
+ base::StringPrintf("gl-buffer-x-process/%" PRIx64 "/%d",
+ context_group_tracing_id, buffer_id));
}
base::trace_event::MemoryAllocatorDumpGuid GetGLRenderbufferGUIDForTracing(
- uint64_t share_group_guid,
+ uint64_t context_group_tracing_id,
uint32_t renderbuffer_id) {
return base::trace_event::MemoryAllocatorDumpGuid(
base::StringPrintf("gl-renderbuffer-x-process/%" PRIx64 "/%d",
- share_group_guid, renderbuffer_id));
+ context_group_tracing_id, renderbuffer_id));
}
base::trace_event::MemoryAllocatorDumpGuid GetGLTextureRasterGUIDForTracing(
diff --git a/chromium/ui/gl/trace_util.h b/chromium/ui/gl/trace_util.h
index 1cc3f0c4b37..2284c6153b2 100644
--- a/chromium/ui/gl/trace_util.h
+++ b/chromium/ui/gl/trace_util.h
@@ -13,19 +13,18 @@
namespace gl {
GL_EXPORT base::trace_event::MemoryAllocatorDumpGuid
-GetGLTextureClientGUIDForTracing(uint64_t share_group_guid,
+GetGLTextureClientGUIDForTracing(uint64_t context_group_tracing_id,
uint32_t texture_client_id);
GL_EXPORT base::trace_event::MemoryAllocatorDumpGuid
-GetGLRenderbufferGUIDForTracing(uint64_t share_group_guid,
+GetGLRenderbufferGUIDForTracing(uint64_t context_group_tracing_id,
uint32_t renderbuffer_id);
GL_EXPORT base::trace_event::MemoryAllocatorDumpGuid
-GetGLTextureServiceGUIDForTracing(uint64_t share_group_guid,
- uint32_t texture_service_id);
+GetGLTextureServiceGUIDForTracing(uint32_t texture_service_id);
GL_EXPORT base::trace_event::MemoryAllocatorDumpGuid GetGLBufferGUIDForTracing(
- uint64_t share_group_guid,
+ uint64_t context_group_tracing_id,
uint32_t buffer_id);
GL_EXPORT base::trace_event::MemoryAllocatorDumpGuid
diff --git a/chromium/ui/keyboard/BUILD.gn b/chromium/ui/keyboard/BUILD.gn
index deaa465f4d6..f478b0b0910 100644
--- a/chromium/ui/keyboard/BUILD.gn
+++ b/chromium/ui/keyboard/BUILD.gn
@@ -55,8 +55,10 @@ jumbo_component("keyboard") {
defines = [ "KEYBOARD_IMPLEMENTATION" ]
deps = [
+ ":mojom",
":resources",
"//base",
+ "//chromeos",
"//services/metrics/public/cpp:ukm_builders",
"//ui/aura",
"//ui/base",
@@ -139,10 +141,7 @@ build_closure("inputview") {
mojom("mojom") {
sources = [
- "keyboard.mojom",
- ]
- deps = [
- "//ui/gfx/geometry/mojo",
+ "public/keyboard_config.mojom",
]
}
@@ -160,11 +159,12 @@ test("keyboard_unittests") {
deps = [
":keyboard",
+ ":mojom",
":test_support",
"//base",
"//base/test:test_support",
"//components/ukm:test_support",
- "//mojo/core/embedder",
+ "//services/service_manager/public/cpp",
"//testing/gmock",
"//testing/gtest",
"//ui/aura:test_support",
diff --git a/chromium/ui/keyboard/DEPS b/chromium/ui/keyboard/DEPS
index 97e3446ef1c..286a31b2fd2 100644
--- a/chromium/ui/keyboard/DEPS
+++ b/chromium/ui/keyboard/DEPS
@@ -1,6 +1,9 @@
include_rules = [
+ "+chromeos/chromeos_features.h",
"+components/ukm",
+ "+mojo/public",
"+services/metrics/public/cpp",
+ "+services/service_manager/public",
"+ui/aura",
"+ui/base",
"+ui/compositor",
diff --git a/chromium/ui/keyboard/keyboard.mojom b/chromium/ui/keyboard/keyboard.mojom
deleted file mode 100644
index 5850df46a45..00000000000
--- a/chromium/ui/keyboard/keyboard.mojom
+++ /dev/null
@@ -1,25 +0,0 @@
-// Copyright 2016 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 keyboard.mojom;
-
-import "ui/gfx/geometry/mojo/geometry.mojom";
-
-interface KeyboardObserver {
- // Sent any time state changes in the keyboard.
- OnKeyboardStateChanged(bool is_enabled,
- bool is_visible,
- uint64 display_id,
- gfx.mojom.Rect bounds);
-};
-
-interface Keyboard {
- // TODO(sky): needs display id.
- Show();
- Hide();
-
- // Adds an observer. OnKeyboardStateChanged() is immediately called to give
- // the initial state.
- AddObserver(KeyboardObserver observer);
-};
diff --git a/chromium/ui/keyboard/keyboard_controller.cc b/chromium/ui/keyboard/keyboard_controller.cc
index 4093ebd2006..a2adfbf40c9 100644
--- a/chromium/ui/keyboard/keyboard_controller.cc
+++ b/chromium/ui/keyboard/keyboard_controller.cc
@@ -13,6 +13,7 @@
#include "base/metrics/histogram_macros.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
+#include "ui/aura/client/aura_constants.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
@@ -36,6 +37,7 @@
#include "ui/keyboard/display_util.h"
#include "ui/keyboard/keyboard_controller_observer.h"
#include "ui/keyboard/keyboard_layout_manager.h"
+#include "ui/keyboard/keyboard_switches.h"
#include "ui/keyboard/keyboard_ui.h"
#include "ui/keyboard/keyboard_util.h"
#include "ui/keyboard/notification_manager.h"
@@ -46,10 +48,12 @@
#include "ui/ozone/public/ozone_platform.h"
#include "ui/wm/core/window_animations.h"
+namespace keyboard {
+
namespace {
// Owned by ash::Shell.
-keyboard::KeyboardController* g_keyboard_controller = nullptr;
+KeyboardController* g_keyboard_controller = nullptr;
constexpr int kHideKeyboardDelayMs = 100;
@@ -65,43 +69,36 @@ constexpr int kReportLingeringStateDelayMs = 5000;
constexpr int kTransientBlurThresholdMs = 3500;
// State transition diagram (document linked from crbug.com/719905)
-bool isAllowedStateTransition(keyboard::KeyboardControllerState from,
- keyboard::KeyboardControllerState to) {
- static const std::set<std::pair<keyboard::KeyboardControllerState,
- keyboard::KeyboardControllerState>>
+bool IsAllowedStateTransition(KeyboardControllerState from,
+ KeyboardControllerState to) {
+ static const std::set<
+ std::pair<KeyboardControllerState, KeyboardControllerState>>
kAllowedStateTransition = {
// The initial ShowKeyboard scenario
// INITIAL -> LOADING_EXTENSION -> HIDDEN -> SHOWN.
- {keyboard::KeyboardControllerState::UNKNOWN,
- keyboard::KeyboardControllerState::INITIAL},
- {keyboard::KeyboardControllerState::INITIAL,
- keyboard::KeyboardControllerState::LOADING_EXTENSION},
- {keyboard::KeyboardControllerState::LOADING_EXTENSION,
- keyboard::KeyboardControllerState::HIDDEN},
- {keyboard::KeyboardControllerState::HIDDEN,
- keyboard::KeyboardControllerState::SHOWN},
+ {KeyboardControllerState::UNKNOWN, KeyboardControllerState::INITIAL},
+ {KeyboardControllerState::INITIAL,
+ KeyboardControllerState::LOADING_EXTENSION},
+ {KeyboardControllerState::LOADING_EXTENSION,
+ KeyboardControllerState::HIDDEN},
+ {KeyboardControllerState::HIDDEN, KeyboardControllerState::SHOWN},
// Hide scenario
// SHOWN -> WILL_HIDE -> HIDDEN.
- {keyboard::KeyboardControllerState::SHOWN,
- keyboard::KeyboardControllerState::WILL_HIDE},
- {keyboard::KeyboardControllerState::WILL_HIDE,
- keyboard::KeyboardControllerState::HIDDEN},
+ {KeyboardControllerState::SHOWN, KeyboardControllerState::WILL_HIDE},
+ {KeyboardControllerState::WILL_HIDE, KeyboardControllerState::HIDDEN},
// Focus transition scenario
// SHOWN -> WILL_HIDE -> SHOWN.
- {keyboard::KeyboardControllerState::WILL_HIDE,
- keyboard::KeyboardControllerState::SHOWN},
+ {KeyboardControllerState::WILL_HIDE, KeyboardControllerState::SHOWN},
// HideKeyboard can be called at anytime for example on shutdown.
- {keyboard::KeyboardControllerState::SHOWN,
- keyboard::KeyboardControllerState::HIDDEN},
+ {KeyboardControllerState::SHOWN, KeyboardControllerState::HIDDEN},
// Return to INITIAL when keyboard is disabled.
- {keyboard::KeyboardControllerState::LOADING_EXTENSION,
- keyboard::KeyboardControllerState::INITIAL},
- {keyboard::KeyboardControllerState::HIDDEN,
- keyboard::KeyboardControllerState::INITIAL},
+ {KeyboardControllerState::LOADING_EXTENSION,
+ KeyboardControllerState::INITIAL},
+ {KeyboardControllerState::HIDDEN, KeyboardControllerState::INITIAL},
};
return kAllowedStateTransition.count(std::make_pair(from, to)) == 1;
};
@@ -117,21 +114,21 @@ void SetTouchEventLogging(bool enable) {
controller->SetTouchEventLoggingEnabled(enable);
}
-std::string StateToStr(keyboard::KeyboardControllerState state) {
+std::string StateToStr(KeyboardControllerState state) {
switch (state) {
- case keyboard::KeyboardControllerState::UNKNOWN:
+ case KeyboardControllerState::UNKNOWN:
return "UNKNOWN";
- case keyboard::KeyboardControllerState::SHOWN:
+ case KeyboardControllerState::SHOWN:
return "SHOWN";
- case keyboard::KeyboardControllerState::LOADING_EXTENSION:
+ case KeyboardControllerState::LOADING_EXTENSION:
return "LOADING_EXTENSION";
- case keyboard::KeyboardControllerState::WILL_HIDE:
+ case KeyboardControllerState::WILL_HIDE:
return "WILL_HIDE";
- case keyboard::KeyboardControllerState::HIDDEN:
+ case KeyboardControllerState::HIDDEN:
return "HIDDEN";
- case keyboard::KeyboardControllerState::INITIAL:
+ case KeyboardControllerState::INITIAL:
return "INITIAL";
- case keyboard::KeyboardControllerState::COUNT:
+ case KeyboardControllerState::COUNT:
NOTREACHED();
}
NOTREACHED() << "Unknownstate: " << static_cast<int>(state);
@@ -139,9 +136,20 @@ std::string StateToStr(keyboard::KeyboardControllerState state) {
return "";
}
-} // namespace
+// An enumeration of different keyboard control events that should be logged.
+enum KeyboardControlEvent {
+ KEYBOARD_CONTROL_SHOW = 0,
+ KEYBOARD_CONTROL_HIDE_AUTO,
+ KEYBOARD_CONTROL_HIDE_USER,
+ KEYBOARD_CONTROL_MAX,
+};
-namespace keyboard {
+void LogKeyboardControlEvent(KeyboardControlEvent event) {
+ UMA_HISTOGRAM_ENUMERATION("VirtualKeyboard.KeyboardControlEvent", event,
+ KEYBOARD_CONTROL_MAX);
+}
+
+} // namespace
// Observer for both keyboard show and hide animations. It should be owned by
// KeyboardController.
@@ -170,7 +178,8 @@ class CallbackAnimationObserver : public ui::ImplicitAnimationObserver {
};
KeyboardController::KeyboardController()
- : weak_factory_report_lingering_state_(this),
+ : ime_observer_(this),
+ weak_factory_report_lingering_state_(this),
weak_factory_will_hide_(this) {
DCHECK_EQ(g_keyboard_controller, nullptr);
g_keyboard_controller = this;
@@ -178,14 +187,25 @@ KeyboardController::KeyboardController()
KeyboardController::~KeyboardController() {
DCHECK(g_keyboard_controller);
- DCHECK(!enabled())
- << "Keyboard must be disabled before KeyboardController is destroyed";
+ DCHECK(!ui_)
+ << "Keyboard UI must be destroyed before KeyboardController is destroyed";
g_keyboard_controller = nullptr;
}
+// static
+KeyboardController* KeyboardController::Get() {
+ DCHECK(g_keyboard_controller);
+ return g_keyboard_controller;
+}
+
+// static
+bool KeyboardController::HasInstance() {
+ return g_keyboard_controller;
+}
+
void KeyboardController::EnableKeyboard(std::unique_ptr<KeyboardUI> ui,
KeyboardLayoutDelegate* delegate) {
- if (enabled())
+ if (ui_)
DisableKeyboard();
ui_ = std::move(ui);
@@ -195,16 +215,16 @@ void KeyboardController::EnableKeyboard(std::unique_ptr<KeyboardUI> ui,
show_on_keyboard_window_load_ = false;
keyboard_locked_ = false;
state_ = KeyboardControllerState::UNKNOWN;
- ui_->GetInputMethod()->AddObserver(this);
ui_->SetController(this);
SetContainerBehaviorInternal(ContainerType::FULL_WIDTH);
ChangeState(KeyboardControllerState::INITIAL);
visual_bounds_in_screen_ = gfx::Rect();
time_of_last_blur_ = base::Time::UnixEpoch();
+ UpdateInputMethodObserver();
}
void KeyboardController::DisableKeyboard() {
- if (!enabled())
+ if (!ui_)
return;
if (parent_container_)
@@ -222,7 +242,7 @@ void KeyboardController::DisableKeyboard() {
container_behavior_.reset();
animation_observer_.reset();
- ui_->GetInputMethod()->RemoveObserver(this);
+ ime_observer_.RemoveAll();
for (KeyboardControllerObserver& observer : observer_list_)
observer.OnKeyboardDisabled();
ui_->SetController(nullptr);
@@ -236,8 +256,7 @@ void KeyboardController::ActivateKeyboardInContainer(aura::Window* parent) {
// Observe changes to root window bounds.
parent_container_->GetRootWindow()->AddObserver(this);
- // TODO(https://crbug.com/845780): Investigate whether this does anything.
- OnTextInputStateChanged(ui_->GetInputMethod()->GetTextInputClient());
+ UpdateInputMethodObserver();
if (GetKeyboardWindow()) {
DCHECK(!GetKeyboardWindow()->parent());
@@ -259,17 +278,6 @@ void KeyboardController::DeactivateKeyboard() {
parent_container_ = nullptr;
}
-// static
-KeyboardController* KeyboardController::Get() {
- DCHECK(g_keyboard_controller);
- return g_keyboard_controller;
-}
-
-// static
-bool KeyboardController::HasInstance() {
- return g_keyboard_controller;
-}
-
aura::Window* KeyboardController::GetKeyboardWindow() const {
return ui_ && ui_->HasKeyboardWindow() ? ui_->GetKeyboardWindow() : nullptr;
}
@@ -278,22 +286,26 @@ aura::Window* KeyboardController::GetRootWindow() {
return parent_container_ ? parent_container_->GetRootWindow() : nullptr;
}
+// private
void KeyboardController::NotifyKeyboardBoundsChanging(
const gfx::Rect& new_bounds) {
visual_bounds_in_screen_ = new_bounds;
- if (ui_->HasKeyboardWindow() && ui_->GetKeyboardWindow()->IsVisible()) {
+ aura::Window* window = GetKeyboardWindow();
+ if (window && window->IsVisible()) {
const gfx::Rect occluded_bounds_in_screen = GetWorkspaceOccludedBounds();
notification_manager_.SendNotifications(
container_behavior_->OccludedBoundsAffectWorkspaceLayout(), new_bounds,
occluded_bounds_in_screen, observer_list_);
- if (keyboard::IsKeyboardOverscrollEnabled())
+ if (IsKeyboardOverscrollEnabled())
ui_->InitInsets(occluded_bounds_in_screen);
else
ui_->ResetInsets();
} else {
visual_bounds_in_screen_ = gfx::Rect();
}
+
+ EnsureCaretInWorkArea(GetWorkspaceOccludedBounds());
}
void KeyboardController::MoveKeyboard(const gfx::Rect& new_bounds) {
@@ -329,6 +341,16 @@ void KeyboardController::NotifyKeyboardWindowLoaded() {
}
}
+void KeyboardController::Reload() {
+ if (!GetKeyboardWindow())
+ return;
+
+ // A reload should never try to show virtual keyboard. If keyboard is not
+ // visible before reload, it should stay invisible after reload.
+ show_on_keyboard_window_load_ = false;
+ ui_->ReloadKeyboardIfNeeded();
+}
+
void KeyboardController::AddObserver(KeyboardControllerObserver* observer) {
observer_list_.AddObserver(observer);
}
@@ -346,6 +368,54 @@ ui::TextInputClient* KeyboardController::GetTextInputClient() {
return ui_->GetInputMethod()->GetTextInputClient();
}
+bool KeyboardController::InsertText(const base::string16& text) {
+ if (!ui_)
+ return false;
+
+ ui::InputMethod* input_method = ui_->GetInputMethod();
+ if (!input_method)
+ return false;
+
+ ui::TextInputClient* tic = input_method->GetTextInputClient();
+ if (!tic || tic->GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
+ return false;
+
+ tic->InsertText(text);
+
+ return true;
+}
+
+bool KeyboardController::UpdateKeyboardConfig(
+ const mojom::KeyboardConfig& config) {
+ if (config.Equals(keyboard_config_))
+ return false;
+ keyboard_config_ = config;
+ if (IsEnabled())
+ NotifyKeyboardConfigChanged();
+ return true;
+}
+
+bool KeyboardController::IsKeyboardOverscrollEnabled() const {
+ if (!keyboard::IsKeyboardEnabled())
+ return false;
+
+ // Users of the sticky accessibility on-screen keyboard are likely to be using
+ // mouse input, which may interfere with overscrolling.
+ if (IsEnabled() && !IsOverscrollAllowed())
+ return false;
+
+ // If overscroll enabled behavior is set, use it instead. Currently
+ // login / out-of-box disable keyboard overscroll. http://crbug.com/363635
+ if (keyboard_config_.overscroll_behavior !=
+ mojom::KeyboardOverscrollBehavior::kDefault) {
+ return keyboard_config_.overscroll_behavior ==
+ mojom::KeyboardOverscrollBehavior::kEnabled;
+ }
+
+ return !base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableVirtualKeyboardOverscroll);
+}
+
void KeyboardController::MoveToDisplayWithTransition(
display::Display display,
gfx::Rect new_bounds_in_local) {
@@ -354,10 +424,12 @@ void KeyboardController::MoveToDisplayWithTransition(
HideKeyboardTemporarilyForTransition();
}
+// private
void KeyboardController::HideKeyboard(HideReason reason) {
TRACE_EVENT0("vk", "HideKeyboard");
switch (state_) {
+ case KeyboardControllerState::UNKNOWN:
case KeyboardControllerState::INITIAL:
case KeyboardControllerState::HIDDEN:
return;
@@ -374,12 +446,11 @@ void KeyboardController::HideKeyboard(HideReason reason) {
case HIDE_REASON_SYSTEM_EXPLICIT:
case HIDE_REASON_SYSTEM_IMPLICIT:
case HIDE_REASON_SYSTEM_TEMPORARY:
- keyboard::LogKeyboardControlEvent(
- keyboard::KEYBOARD_CONTROL_HIDE_AUTO);
+ LogKeyboardControlEvent(KEYBOARD_CONTROL_HIDE_AUTO);
break;
case HIDE_REASON_USER_EXPLICIT:
- keyboard::LogKeyboardControlEvent(
- keyboard::KEYBOARD_CONTROL_HIDE_USER);
+ case HIDE_REASON_USER_IMPLICIT:
+ LogKeyboardControlEvent(KEYBOARD_CONTROL_HIDE_USER);
break;
}
@@ -393,6 +464,7 @@ void KeyboardController::HideKeyboard(HideReason reason) {
case HIDE_REASON_SYSTEM_TEMPORARY:
case HIDE_REASON_SYSTEM_EXPLICIT:
case HIDE_REASON_USER_EXPLICIT:
+ case HIDE_REASON_USER_IMPLICIT:
time_of_last_blur_ = base::Time::UnixEpoch();
break;
}
@@ -422,11 +494,10 @@ void KeyboardController::HideKeyboard(HideReason reason) {
for (KeyboardControllerObserver& observer : observer_list_)
observer.OnKeyboardHidden(reason == HIDE_REASON_SYSTEM_TEMPORARY);
- ui_->EnsureCaretInWorkArea(gfx::Rect());
break;
}
- default:
+ case KeyboardControllerState::COUNT:
NOTREACHED();
}
}
@@ -435,6 +506,11 @@ void KeyboardController::HideKeyboardByUser() {
HideKeyboard(HIDE_REASON_USER_EXPLICIT);
}
+void KeyboardController::HideKeyboardImplicitlyByUser() {
+ if (!keyboard_locked())
+ HideKeyboard(HIDE_REASON_USER_IMPLICIT);
+}
+
void KeyboardController::HideKeyboardTemporarilyForTransition() {
HideKeyboard(HIDE_REASON_SYSTEM_TEMPORARY);
}
@@ -461,6 +537,7 @@ void KeyboardController::DismissVirtualKeyboard() {
HideKeyboardByUser();
}
+// private
void KeyboardController::HideAnimationFinished() {
if (state_ == KeyboardControllerState::HIDDEN) {
if (queued_container_type_) {
@@ -482,15 +559,16 @@ void KeyboardController::HideAnimationFinished() {
}
}
+// private
void KeyboardController::ShowAnimationFinished() {
MarkKeyboardLoadFinished();
// Notify observers after animation finished to prevent reveal desktop
// background during animation.
NotifyKeyboardBoundsChanging(GetKeyboardWindow()->bounds());
- ui_->EnsureCaretInWorkArea(GetWorkspaceOccludedBounds());
}
+// private
void KeyboardController::SetContainerBehaviorInternal(
const ContainerType type) {
// Reset the hit test event targeter because the hit test bounds will
@@ -524,6 +602,16 @@ void KeyboardController::ShowKeyboardInDisplay(
ShowKeyboardInternal(display);
}
+void KeyboardController::LoadKeyboardWindowInBackground() {
+ // ShowKeyboardInternal may trigger RootControllerWindow::ActiveKeyboard which
+ // will cause LoadKeyboardWindowInBackground to potentially run even though
+ // the keyboard has been initialized.
+ if (state_ != KeyboardControllerState::INITIAL)
+ return;
+
+ PopulateKeyboardContent(display::Display(), false);
+}
+
void KeyboardController::OnWindowAddedToRootWindow(aura::Window* window) {
container_behavior_->SetCanonicalBounds(GetKeyboardWindow(),
GetRootWindow()->bounds());
@@ -545,13 +633,10 @@ void KeyboardController::OnWindowBoundsChanged(
NotifyKeyboardBoundsChanging(new_bounds);
}
-void KeyboardController::Reload() {
- if (ui_->HasKeyboardWindow()) {
- // A reload should never try to show virtual keyboard. If keyboard is not
- // visible before reload, it should stay invisible after reload.
- show_on_keyboard_window_load_ = false;
- ui_->ReloadKeyboardIfNeeded();
- }
+void KeyboardController::OnInputMethodDestroyed(
+ const ui::InputMethod* input_method) {
+ ime_observer_.RemoveAll();
+ OnTextInputStateChanged(nullptr);
}
void KeyboardController::OnTextInputStateChanged(
@@ -609,23 +694,14 @@ void KeyboardController::ShowKeyboardIfWithinTransientBlurThreshold() {
void KeyboardController::OnShowVirtualKeyboardIfEnabled() {
// Calling |ShowKeyboardInternal| may move the keyboard to another display.
- if (IsKeyboardEnabled() && !keyboard_locked())
+ if (keyboard::IsKeyboardEnabled() && !keyboard_locked())
ShowKeyboardInternal(display::Display());
}
-void KeyboardController::LoadKeyboardWindowInBackground() {
- // ShowKeyboardInternal may trigger RootControllerWindow::ActiveKeyboard which
- // will cause LoadKeyboardWindowInBackground to potentially run even though
- // the keyboard has been initialized.
- if (state_ != KeyboardControllerState::INITIAL)
- return;
-
- PopulateKeyboardContent(display::Display(), false);
-}
-
void KeyboardController::ShowKeyboardInternal(const display::Display& display) {
- keyboard::MarkKeyboardLoadStarted();
+ MarkKeyboardLoadStarted();
PopulateKeyboardContent(display, true);
+ UpdateInputMethodObserver();
}
void KeyboardController::PopulateKeyboardContent(
@@ -637,13 +713,15 @@ void KeyboardController::PopulateKeyboardContent(
if (parent_container_->children().empty()) {
DCHECK_EQ(state_, KeyboardControllerState::INITIAL);
+ // TODO(https://crbug.com/845780): This call will create and load the
+ // virtual keyboard window. Redesign the KeyboardUI interface so that
+ // loading is explicit.
aura::Window* keyboard_window = ui_->GetKeyboardWindow();
keyboard_window->AddPreTargetHandler(&event_filter_);
keyboard_window->AddObserver(this);
parent_container_->AddChild(keyboard_window);
}
- DCHECK(ui_->HasKeyboardWindow());
if (layout_delegate_ != nullptr) {
if (display.is_valid())
layout_delegate_->MoveKeyboardToDisplay(display);
@@ -651,7 +729,8 @@ void KeyboardController::PopulateKeyboardContent(
layout_delegate_->MoveKeyboardToTouchableDisplay();
}
- aura::Window* keyboard_window = ui_->GetKeyboardWindow();
+ aura::Window* keyboard_window = GetKeyboardWindow();
+ DCHECK(keyboard_window);
DCHECK_EQ(parent_container_, keyboard_window->parent());
switch (state_) {
@@ -670,7 +749,7 @@ void KeyboardController::PopulateKeyboardContent(
switch (state_) {
case KeyboardControllerState::INITIAL:
- DCHECK_EQ(ui_->GetKeyboardWindow()->bounds().height(), 0);
+ DCHECK_EQ(keyboard_window->bounds().height(), 0);
show_on_keyboard_window_load_ = show_keyboard;
ChangeState(KeyboardControllerState::LOADING_EXTENSION);
return;
@@ -687,7 +766,7 @@ void KeyboardController::PopulateKeyboardContent(
// are at begin states for animation.
container_behavior_->InitializeShowAnimationStartingState(keyboard_window);
- keyboard::LogKeyboardControlEvent(keyboard::KEYBOARD_CONTROL_SHOW);
+ LogKeyboardControlEvent(KEYBOARD_CONTROL_SHOW);
RecordUkmKeyboardShown();
ui::LayerAnimator* container_animator =
@@ -729,7 +808,7 @@ void KeyboardController::NotifyKeyboardConfigChanged() {
void KeyboardController::CheckStateTransition(KeyboardControllerState prev,
KeyboardControllerState next) {
std::stringstream error_message;
- const bool valid_transition = isAllowedStateTransition(prev, next);
+ const bool valid_transition = IsAllowedStateTransition(prev, next);
if (!valid_transition)
error_message << "Unexpected transition";
@@ -783,7 +862,7 @@ void KeyboardController::ReportLingeringState() {
}
gfx::Rect KeyboardController::GetWorkspaceOccludedBounds() const {
- if (!enabled())
+ if (!ui_)
return gfx::Rect();
const gfx::Rect visual_bounds_in_window(visual_bounds_in_screen_.size());
@@ -798,7 +877,7 @@ gfx::Rect KeyboardController::GetKeyboardLockScreenOffsetBounds() const {
// Overscroll is generally dependent on lock state, however, its behavior
// temporarily overridden by a static field in certain lock screen contexts.
// Furthermore, floating keyboard should never affect layout.
- if (!keyboard::IsKeyboardOverscrollEnabled() &&
+ if (!IsKeyboardOverscrollEnabled() &&
container_behavior_->GetType() != ContainerType::FLOATING &&
container_behavior_->GetType() != ContainerType::FULLSCREEN) {
return visual_bounds_in_screen_;
@@ -866,6 +945,15 @@ void KeyboardController::SetContainerType(
}
}
+ui::InputMethod* KeyboardController::GetInputMethodForTest() {
+ return ui_->GetInputMethod();
+}
+
+void KeyboardController::EnsureCaretInWorkAreaForTest(
+ const gfx::Rect& occluded_bounds) {
+ EnsureCaretInWorkArea(occluded_bounds);
+}
+
void KeyboardController::RecordUkmKeyboardShown() {
ui::TextInputClient* text_input_client = GetTextInputClient();
if (!text_input_client)
@@ -882,7 +970,7 @@ bool KeyboardController::SetDraggableArea(const gfx::Rect& rect) {
bool KeyboardController::DisplayVirtualKeyboard() {
// Calling |ShowKeyboardInternal| may move the keyboard to another display.
- if (IsKeyboardEnabled() && !keyboard_locked()) {
+ if (keyboard::IsKeyboardEnabled() && !keyboard_locked()) {
ShowKeyboardInternal(display::Display());
return true;
}
@@ -899,7 +987,65 @@ void KeyboardController::RemoveObserver(
}
bool KeyboardController::IsKeyboardVisible() {
- return state_ == KeyboardControllerState::SHOWN;
+ if (state_ == KeyboardControllerState::SHOWN) {
+ DCHECK(IsEnabled());
+ return true;
+ }
+ return false;
+}
+
+void KeyboardController::UpdateInputMethodObserver() {
+ ui::InputMethod* ime = ui_->GetInputMethod();
+
+ // IME could be null during initialization. Ignoring the case is okay because
+ // UpdateInputMethodObserver() will be called later on.
+ if (!ime)
+ return;
+
+ if (ime_observer_.IsObserving(ime))
+ return;
+
+ // Only observes the current active IME.
+ ime_observer_.RemoveAll();
+ ime_observer_.Add(ime);
+
+ // TODO(https://crbug.com/845780): Investigate whether this does anything.
+ OnTextInputStateChanged(ime->GetTextInputClient());
+}
+
+void KeyboardController::EnsureCaretInWorkArea(
+ const gfx::Rect& occluded_bounds) {
+ ui::InputMethod* ime = ui_->GetInputMethod();
+ if (!ime)
+ return;
+
+ TRACE_EVENT0("vk", "EnsureCaretInWorkArea");
+
+ if (IsOverscrollAllowed()) {
+ ime->SetOnScreenKeyboardBounds(occluded_bounds);
+ } else if (ime->GetTextInputClient()) {
+ ime->GetTextInputClient()->EnsureCaretNotInRect(occluded_bounds);
+ }
+}
+
+void KeyboardController::MarkKeyboardLoadStarted() {
+ if (!keyboard_load_time_logged_)
+ keyboard_load_time_start_ = base::Time::Now();
+}
+
+void KeyboardController::MarkKeyboardLoadFinished() {
+ // Possible to get a load finished without a start if navigating directly to
+ // chrome://keyboard.
+ if (keyboard_load_time_start_.is_null())
+ return;
+
+ if (keyboard_load_time_logged_)
+ return;
+
+ // Log the delta only once.
+ UMA_HISTOGRAM_TIMES("VirtualKeyboard.InitLatency.FirstLoad",
+ base::Time::Now() - keyboard_load_time_start_);
+ keyboard_load_time_logged_ = true;
}
} // namespace keyboard
diff --git a/chromium/ui/keyboard/keyboard_controller.h b/chromium/ui/keyboard/keyboard_controller.h
index bac50bc898f..94e0b6c85dc 100644
--- a/chromium/ui/keyboard/keyboard_controller.h
+++ b/chromium/ui/keyboard/keyboard_controller.h
@@ -9,6 +9,7 @@
#include "base/macros.h"
#include "base/observer_list.h"
+#include "base/scoped_observer.h"
#include "base/time/time.h"
#include "ui/aura/window_observer.h"
#include "ui/base/ime/input_method_keyboard_controller.h"
@@ -24,8 +25,8 @@
#include "ui/keyboard/keyboard_export.h"
#include "ui/keyboard/keyboard_layout_delegate.h"
#include "ui/keyboard/keyboard_ukm_recorder.h"
-#include "ui/keyboard/keyboard_util.h"
#include "ui/keyboard/notification_manager.h"
+#include "ui/keyboard/public/keyboard_config.mojom.h"
#include "ui/keyboard/queued_container_type.h"
#include "ui/keyboard/queued_display_change.h"
@@ -35,7 +36,7 @@ class Window;
namespace ui {
class InputMethod;
class TextInputClient;
-}
+} // namespace ui
namespace keyboard {
@@ -71,10 +72,19 @@ class KEYBOARD_EXPORT KeyboardController
public aura::WindowObserver,
public ui::InputMethodKeyboardController {
public:
-
KeyboardController();
~KeyboardController() override;
+ // Retrieves the active keyboard controller. Guaranteed to not be null while
+ // there is an ash::Shell.
+ // TODO(stevenjb/shuchen/shend): Remove all access from src/chrome.
+ // https://crbug.com/843332.
+ static KeyboardController* Get();
+
+ // Returns true if there is a valid KeyboardController instance (e.g. while
+ // there is an ash::Shell).
+ static bool HasInstance();
+
// Enables the virtual keyboard with a specified |ui| and |delegate|.
// Disables and re-enables the keyboard if it is already enabled.
void EnableKeyboard(std::unique_ptr<KeyboardUI> ui,
@@ -103,6 +113,16 @@ class KEYBOARD_EXPORT KeyboardController
// null if the keyboard has not been attached to any root window.
aura::Window* GetRootWindow();
+ // Moves an already loaded keyboard.
+ void MoveKeyboard(const gfx::Rect& new_bounds);
+
+ // Sets the bounds of the keyboard window.
+ void SetKeyboardWindowBounds(const gfx::Rect& new_bounds);
+
+ // Called by KeyboardUI when the keyboard window has loaded. Shows
+ // the keyboard if show_on_keyboard_window_load_ is true.
+ void NotifyKeyboardWindowLoaded();
+
// Reloads the content of the keyboard. No-op if the keyboard content is not
// loaded yet.
void Reload();
@@ -112,19 +132,40 @@ class KEYBOARD_EXPORT KeyboardController
bool HasObserver(KeyboardControllerObserver* observer) const;
void RemoveObserver(KeyboardControllerObserver* observer);
- KeyboardUI* ui() { return ui_.get(); }
-
// Gets the currently focused text input client.
ui::TextInputClient* GetTextInputClient();
+ // Insert |text| into the active TextInputClient if there is one. Returns true
+ // if |text| was successfully inserted.
+ bool InsertText(const base::string16& text);
+
+ // Updates |keyboard_config_| with |config|. Returns |false| if there is no
+ // change, otherwise returns true and notifies observers if this is enabled().
+ bool UpdateKeyboardConfig(const mojom::KeyboardConfig& config);
+ const mojom::KeyboardConfig& keyboard_config() { return keyboard_config_; }
+
+ // Returns true if keyboard overscroll is enabled.
+ bool IsKeyboardOverscrollEnabled() const;
+
void set_keyboard_locked(bool lock) { keyboard_locked_ = lock; }
bool keyboard_locked() const { return keyboard_locked_; }
+ void MoveToDisplayWithTransition(display::Display display,
+ gfx::Rect new_bounds_in_local);
+
// Hide the keyboard because the user has chosen to specifically hide the
// keyboard, such as pressing the dismiss button.
+ // TODO(https://crbug.com/845780): Rename this to
+ // HideKeyboardExplicitlyByUser.
+ // TODO(https://crbug.com/845780): Audit and switch callers to
+ // HideKeyboardImplicitlyByUser where appropriate.
void HideKeyboardByUser();
+ // Hide the keyboard as a secondary effect of a user action, such as tapping
+ // the shelf. The keyboard should not hide if it's locked.
+ void HideKeyboardImplicitlyByUser();
+
// Hide the keyboard due to some internally generated change to change the
// state of the keyboard. For example, moving from the docked keyboard to the
// floating keyboard.
@@ -144,21 +185,13 @@ class KEYBOARD_EXPORT KeyboardController
// |lock| is true.
void ShowKeyboard(bool lock);
- // Loads the keyboard window in the background, but does not display
- // the keyboard.
- void LoadKeyboardWindowInBackground();
-
// Force the keyboard to show up in the specific display if not showing and
// lock the keyboard
void ShowKeyboardInDisplay(const display::Display& display);
- // Retrieves the active keyboard controller. Guaranteed to not be null while
- // there is an ash::Shell.
- static KeyboardController* Get();
-
- // Returns true if there is a valid KeyboardController instance (e.g. while
- // there is an ash::Shell).
- static bool HasInstance();
+ // Loads the keyboard window in the background, but does not display
+ // the keyboard.
+ void LoadKeyboardWindowInBackground();
// Returns the bounds in screen for the visible portion of the keyboard. An
// empty rectangle will get returned when the keyboard is hidden.
@@ -182,8 +215,6 @@ class KEYBOARD_EXPORT KeyboardController
// Does not do anything if there is no keyboard window.
void SetHitTestBounds(const std::vector<gfx::Rect>& bounds);
- KeyboardControllerState GetStateForTest() const { return state_; }
-
ContainerType GetActiveContainerType() const {
return container_behavior_->GetType();
}
@@ -195,16 +226,14 @@ class KEYBOARD_EXPORT KeyboardController
// container behavior.
bool IsOverscrollAllowed() const;
- // Whether the keyboard is enabled.
- bool enabled() const { return ui_ != nullptr; }
+ // Whether the keyboard has been enabled, i.e. EnableKeyboard() has been
+ // called.
+ bool IsEnabled() const { return ui_ != nullptr; }
// Handle mouse and touch events on the keyboard. The effects of this method
// will not stop propagation to the keyboard extension.
bool HandlePointerEvent(const ui::LocatedEvent& event);
- // Moves an already loaded keyboard.
- void MoveKeyboard(const gfx::Rect& new_bounds);
-
// Sets the active container type. If the keyboard is currently shown, this
// will trigger a hide animation and a subsequent show animation. Otherwise
// the ContainerBehavior change is synchronous.
@@ -215,13 +244,6 @@ class KEYBOARD_EXPORT KeyboardController
// Sets floating keyboard draggable rect.
bool SetDraggableArea(const gfx::Rect& rect);
- void MoveToDisplayWithTransition(display::Display display,
- gfx::Rect new_bounds_in_local);
-
- // Called by KeyboardUI when the keyboard window has loaded. Shows
- // the keyboard if show_on_keyboard_window_load_ is true.
- void NotifyKeyboardWindowLoaded();
-
// InputMethodKeyboardController overrides.
bool DisplayVirtualKeyboard() override;
void DismissVirtualKeyboard() override;
@@ -231,14 +253,14 @@ class KEYBOARD_EXPORT KeyboardController
ui::InputMethodKeyboardControllerObserver* observer) override;
bool IsKeyboardVisible() override;
+ KeyboardControllerState GetStateForTest() const { return state_; }
+ ui::InputMethod* GetInputMethodForTest();
+ void EnsureCaretInWorkAreaForTest(const gfx::Rect& occluded_bounds);
+
private:
// For access to Observer methods for simulation.
friend class KeyboardControllerTest;
- // For access to NotifyKeyboardConfigChanged
- friend bool keyboard::UpdateKeyboardConfig(
- const keyboard::KeyboardConfig& config);
-
// Different ways to hide the keyboard.
enum HideReason {
// System initiated due to an active event, where the user does not want
@@ -259,9 +281,14 @@ class KEYBOARD_EXPORT KeyboardController
// floating)
HIDE_REASON_SYSTEM_TEMPORARY,
- // User initiated.
+ // User explicitly hiding the keyboard via the close button. Also hides
+ // locked keyboards.
HIDE_REASON_USER_EXPLICIT,
+ // Keyboard is hidden as an indirect consequence of some user action.
+ // Examples include opening the window overview mode, or tapping on the
+ // shelf status area. Does not hide locked keyboards.
+ HIDE_REASON_USER_IMPLICIT,
};
// aura::WindowObserver overrides
@@ -275,13 +302,10 @@ class KEYBOARD_EXPORT KeyboardController
void OnBlur() override {}
void OnCaretBoundsChanged(const ui::TextInputClient* client) override {}
void OnFocus() override {}
- void OnInputMethodDestroyed(const ui::InputMethod* input_method) override {}
+ void OnInputMethodDestroyed(const ui::InputMethod* input_method) override;
void OnTextInputStateChanged(const ui::TextInputClient* client) override;
void OnShowVirtualKeyboardIfEnabled() override;
- // Sets the bounds of the keyboard window.
- void SetKeyboardWindowBounds(const gfx::Rect& new_bounds);
-
// Show virtual keyboard immediately with animation.
void ShowKeyboardInternal(const display::Display& display);
void PopulateKeyboardContent(const display::Display& display,
@@ -327,8 +351,25 @@ class KEYBOARD_EXPORT KeyboardController
// Records that keyboard was shown on the currently focused UKM source.
void RecordUkmKeyboardShown();
+ // Ensures that the current IME is observed if it is changed.
+ void UpdateInputMethodObserver();
+
+ // Ensures caret in current work area (not occluded by virtual keyboard
+ // window).
+ void EnsureCaretInWorkArea(const gfx::Rect& occluded_bounds);
+
+ // Marks that the keyboard load has started. This is used to measure the time
+ // it takes to fully load the keyboard. This should be called before
+ // MarkKeyboardLoadFinished.
+ void MarkKeyboardLoadStarted();
+
+ // Marks that the keyboard load has ended. This finishes measuring that the
+ // keyboard is loaded.
+ void MarkKeyboardLoadFinished();
+
std::unique_ptr<KeyboardUI> ui_;
- KeyboardLayoutDelegate* layout_delegate_;
+ KeyboardLayoutDelegate* layout_delegate_ = nullptr;
+ ScopedObserver<ui::InputMethod, ui::InputMethodObserver> ime_observer_;
// Container window that the keyboard window is a child of.
aura::Window* parent_container_ = nullptr;
@@ -344,10 +385,10 @@ class KEYBOARD_EXPORT KeyboardController
std::unique_ptr<QueuedDisplayChange> queued_display_change_;
// If true, show the keyboard window when it loads.
- bool show_on_keyboard_window_load_;
+ bool show_on_keyboard_window_load_ = false;
// If true, the keyboard is always visible even if no window has input focus.
- bool keyboard_locked_;
+ bool keyboard_locked_ = false;
KeyboardEventFilter event_filter_;
base::ObserverList<KeyboardControllerObserver>::Unchecked observer_list_;
@@ -357,7 +398,10 @@ class KEYBOARD_EXPORT KeyboardController
// keyboard window. If not, this should be empty.
gfx::Rect visual_bounds_in_screen_;
- KeyboardControllerState state_;
+ KeyboardControllerState state_ = KeyboardControllerState::UNKNOWN;
+
+ // Keyboard configuration associated with the controller.
+ mojom::KeyboardConfig keyboard_config_;
NotificationManager notification_manager_;
@@ -365,6 +409,9 @@ class KEYBOARD_EXPORT KeyboardController
DisplayUtil display_util_;
+ bool keyboard_load_time_logged_ = false;
+ base::Time keyboard_load_time_start_;
+
base::WeakPtrFactory<KeyboardController> weak_factory_report_lingering_state_;
base::WeakPtrFactory<KeyboardController> weak_factory_will_hide_;
diff --git a/chromium/ui/keyboard/keyboard_controller_observer.h b/chromium/ui/keyboard/keyboard_controller_observer.h
index 217417b0a5a..f3ffe74a35d 100644
--- a/chromium/ui/keyboard/keyboard_controller_observer.h
+++ b/chromium/ui/keyboard/keyboard_controller_observer.h
@@ -67,8 +67,9 @@ class KEYBOARD_EXPORT KeyboardControllerObserver {
virtual void OnKeyboardAppearanceChanged(
const KeyboardStateDescriptor& state) {}
- // Called when the keyboard was disabled (e.g. when user switches convertible
- // to laptop mode)
+ // Called when the keyboard is effectively disabled (i.e. when the UI / window
+ // is destroyed, not when keyboard::IsKeyboardEnabled() changes), e.g. when
+ // user switches convertible to laptop mode or the active user changes.
virtual void OnKeyboardDisabled() {}
// Called when the keyboard has been hidden and the hiding animation finished
diff --git a/chromium/ui/keyboard/keyboard_controller_unittest.cc b/chromium/ui/keyboard/keyboard_controller_unittest.cc
index 12854f0bec9..afcc0822f8d 100644
--- a/chromium/ui/keyboard/keyboard_controller_unittest.cc
+++ b/chromium/ui/keyboard/keyboard_controller_unittest.cc
@@ -185,7 +185,6 @@ class KeyboardControllerTest : public aura::test::AuraTestBase,
aura::test::AuraTestBase::TearDown();
}
- KeyboardUI* ui() { return controller_.ui(); }
KeyboardController& controller() { return controller_; }
KeyboardLayoutDelegate* layout_delegate() { return layout_delegate_.get(); }
@@ -243,14 +242,14 @@ class KeyboardControllerTest : public aura::test::AuraTestBase,
}
void SetFocus(ui::TextInputClient* client) {
- ui::InputMethod* input_method = ui()->GetInputMethod();
+ ui::InputMethod* input_method = controller().GetInputMethodForTest();
input_method->SetFocusedTextInputClient(client);
if (client && client->GetTextInputType() != ui::TEXT_INPUT_TYPE_NONE &&
client->GetTextInputMode() != ui::TEXT_INPUT_MODE_NONE) {
input_method->ShowVirtualKeyboardIfEnabled();
- if (controller_.ui()->GetKeyboardWindow()->bounds().height() == 0) {
+ if (controller().GetKeyboardWindow()->bounds().height() == 0) {
// Set initial bounds for test keyboard window.
- controller_.ui()->GetKeyboardWindow()->SetBounds(
+ controller().GetKeyboardWindow()->SetBounds(
KeyboardBoundsFromRootBounds(root_window()->bounds(),
kDefaultVirtualKeyboardHeight));
// Simulate the keyboard contents finish loading
@@ -262,9 +261,9 @@ class KeyboardControllerTest : public aura::test::AuraTestBase,
bool WillHideKeyboard() { return controller_.WillHideKeyboard(); }
bool ShouldEnableInsets(aura::Window* window) {
- aura::Window* contents_window = controller_.ui()->GetKeyboardWindow();
+ aura::Window* contents_window = controller().GetKeyboardWindow();
return (contents_window->GetRootWindow() == window->GetRootWindow() &&
- keyboard::IsKeyboardOverscrollEnabled() &&
+ controller_.IsKeyboardOverscrollEnabled() &&
contents_window->IsVisible() && controller_.IsKeyboardVisible());
}
@@ -458,17 +457,17 @@ TEST_F(KeyboardControllerTest, CheckOverscrollInsetDuringVisibilityChange) {
ui::DummyTextInputClient no_input_client(ui::TEXT_INPUT_TYPE_NONE);
// Enable touch keyboard / overscroll mode to test insets.
- EXPECT_TRUE(keyboard::IsKeyboardOverscrollEnabled());
+ EXPECT_TRUE(controller().IsKeyboardOverscrollEnabled());
SetFocus(&input_client);
SetFocus(&no_input_client);
// Insets should not be enabled for new windows while keyboard is in the
// process of hiding when overscroll is enabled.
- EXPECT_FALSE(ShouldEnableInsets(ui()->GetKeyboardWindow()));
+ EXPECT_FALSE(ShouldEnableInsets(controller().GetKeyboardWindow()));
// Cancel keyboard hide.
SetFocus(&input_client);
// Insets should be enabled for new windows as hide was cancelled.
- EXPECT_TRUE(ShouldEnableInsets(ui()->GetKeyboardWindow()));
+ EXPECT_TRUE(ShouldEnableInsets(controller().GetKeyboardWindow()));
}
TEST_F(KeyboardControllerTest, AlwaysVisibleWhenLocked) {
@@ -579,7 +578,7 @@ class KeyboardControllerAnimationTest : public KeyboardControllerTest {
}
protected:
- aura::Window* keyboard_window() { return ui()->GetKeyboardWindow(); }
+ aura::Window* keyboard_window() { return controller().GetKeyboardWindow(); }
private:
DISALLOW_COPY_AND_ASSIGN(KeyboardControllerAnimationTest);
@@ -711,7 +710,7 @@ TEST_F(KeyboardControllerAnimationTest,
ShowKeyboard();
RunAnimationForLayer(layer);
- ASSERT_TRUE(controller().ui());
+ ASSERT_TRUE(keyboard_window());
controller().DeactivateKeyboard();
@@ -795,7 +794,8 @@ TEST_F(KeyboardControllerAnimationTest, FloatingKeyboardEnsureCaretInWorkArea) {
EXPECT_TRUE(keyboard_window()->IsVisible());
// Unfocus from the MockTextInputClient before destroying it.
- ui()->GetInputMethod()->DetachTextInputClient(&mock_input_client);
+ controller().GetInputMethodForTest()->DetachTextInputClient(
+ &mock_input_client);
}
// Checks DisableKeyboard() doesn't clear the observer list.
diff --git a/chromium/ui/keyboard/keyboard_event_filter.cc b/chromium/ui/keyboard/keyboard_event_filter.cc
index dd59c566c7d..1d903f21679 100644
--- a/chromium/ui/keyboard/keyboard_event_filter.cc
+++ b/chromium/ui/keyboard/keyboard_event_filter.cc
@@ -32,7 +32,7 @@ void KeyboardEventFilter::OnTouchEvent(ui::TouchEvent* event) {
void KeyboardEventFilter::ProcessPointerEvent(ui::LocatedEvent* event) {
auto* controller = KeyboardController::Get();
- if (controller->enabled() && controller->HandlePointerEvent(*event))
+ if (controller->IsEnabled() && controller->HandlePointerEvent(*event))
event->SetHandled();
}
diff --git a/chromium/ui/keyboard/keyboard_layout_manager.cc b/chromium/ui/keyboard/keyboard_layout_manager.cc
index 32d34a504dd..59af679b08f 100644
--- a/chromium/ui/keyboard/keyboard_layout_manager.cc
+++ b/chromium/ui/keyboard/keyboard_layout_manager.cc
@@ -8,7 +8,6 @@
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/keyboard/keyboard_controller.h"
-#include "ui/keyboard/keyboard_util.h"
namespace keyboard {
diff --git a/chromium/ui/keyboard/keyboard_switches.cc b/chromium/ui/keyboard/keyboard_switches.cc
index 32a4beec533..224cb1c35b1 100644
--- a/chromium/ui/keyboard/keyboard_switches.cc
+++ b/chromium/ui/keyboard/keyboard_switches.cc
@@ -8,8 +8,6 @@ namespace keyboard {
namespace switches {
const char kDisableInputView[] = "disable-input-view";
-const char kEnableExperimentalInputViewFeatures[] =
- "enable-experimental-input-view-features";
const char kDisableVoiceInput[] = "disable-voice-input";
const char kDisableGestureTyping[] = "disable-gesture-typing";
const char kDisableGestureEditing[] = "disable-gesture-editing";
diff --git a/chromium/ui/keyboard/keyboard_switches.h b/chromium/ui/keyboard/keyboard_switches.h
index d3a88cd0ed3..bde216b0a3a 100644
--- a/chromium/ui/keyboard/keyboard_switches.h
+++ b/chromium/ui/keyboard/keyboard_switches.h
@@ -17,9 +17,6 @@ KEYBOARD_EXPORT extern const char kDisableInputView[];
// Disables voice input.
KEYBOARD_EXPORT extern const char kDisableVoiceInput[];
-// Enables experimental features for IME extensions.
-KEYBOARD_EXPORT extern const char kEnableExperimentalInputViewFeatures[];
-
// Flag which disables gesture typing for the virtual keyboard.
KEYBOARD_EXPORT extern const char kDisableGestureTyping[];
diff --git a/chromium/ui/keyboard/keyboard_ui.cc b/chromium/ui/keyboard/keyboard_ui.cc
index bf591ed04cd..16d24e63da9 100644
--- a/chromium/ui/keyboard/keyboard_ui.cc
+++ b/chromium/ui/keyboard/keyboard_ui.cc
@@ -29,20 +29,6 @@ void KeyboardUI::HideKeyboardWindow() {
GetKeyboardWindow()->Hide();
}
-void KeyboardUI::EnsureCaretInWorkArea(const gfx::Rect& occluded_bounds) {
- if (!GetInputMethod())
- return;
-
- TRACE_EVENT0("vk", "EnsureCaretInWorkArea");
-
- if (keyboard_controller_->IsOverscrollAllowed()) {
- GetInputMethod()->SetOnScreenKeyboardBounds(occluded_bounds);
- } else if (GetInputMethod()->GetTextInputClient()) {
- GetInputMethod()->GetTextInputClient()->EnsureCaretNotInRect(
- occluded_bounds);
- }
-}
-
void KeyboardUI::SetController(KeyboardController* controller) {
keyboard_controller_ = controller;
}
diff --git a/chromium/ui/keyboard/keyboard_ui.h b/chromium/ui/keyboard/keyboard_ui.h
index 08fc72af382..a96fc780c49 100644
--- a/chromium/ui/keyboard/keyboard_ui.h
+++ b/chromium/ui/keyboard/keyboard_ui.h
@@ -52,15 +52,6 @@ class KEYBOARD_EXPORT KeyboardUI {
// the visibility change.
virtual void HideKeyboardWindow();
- // Ensures caret in current work area (not occluded by virtual keyboard
- // window).
- virtual void EnsureCaretInWorkArea(const gfx::Rect& occluded_bounds);
-
- // KeyboardController owns the KeyboardUI instance so KeyboardUI subclasses
- // should not take ownership of the |controller|. |controller| can be null
- // when KeyboardController is destroying.
- virtual void SetController(KeyboardController* controller);
-
// Reloads virtual keyboard URL if the current keyboard's web content URL is
// different. The URL can be different if user switch from password field to
// any other type input field.
@@ -79,6 +70,9 @@ class KEYBOARD_EXPORT KeyboardUI {
// Resets insets for affected windows.
virtual void ResetInsets() = 0;
+ // |controller| may be null when KeyboardController is being destroyed.
+ void SetController(KeyboardController* controller);
+
protected:
KeyboardController* keyboard_controller() { return keyboard_controller_; }
diff --git a/chromium/ui/keyboard/keyboard_util.cc b/chromium/ui/keyboard/keyboard_util.cc
index 875c7d59eae..3e3020fcaab 100644
--- a/chromium/ui/keyboard/keyboard_util.cc
+++ b/chromium/ui/keyboard/keyboard_util.cc
@@ -7,28 +7,18 @@
#include <string>
#include "base/command_line.h"
-#include "base/feature_list.h"
-#include "base/lazy_instance.h"
-#include "base/logging.h"
#include "base/metrics/histogram_macros.h"
-#include "base/strings/string16.h"
-#include "ui/aura/client/aura_constants.h"
#include "ui/aura/window_tree_host.h"
+#include "ui/base/ime/constants.h"
#include "ui/base/ime/input_method.h"
-#include "ui/base/ime/input_method_base.h"
#include "ui/base/ime/text_input_client.h"
-#include "ui/base/ime/text_input_flags.h"
-#include "ui/base/ui_base_features.h"
-#include "ui/base/ui_base_switches.h"
#include "ui/events/event_sink.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/dom/keycode_converter.h"
#include "ui/events/keycodes/keyboard_code_conversion.h"
-#include "ui/keyboard/keyboard_controller.h"
#include "ui/keyboard/keyboard_switches.h"
-#include "ui/keyboard/keyboard_ui.h"
namespace keyboard {
@@ -47,43 +37,18 @@ void SendProcessKeyEvent(ui::EventType type,
CHECK(!details.dispatcher_destroyed);
}
-bool g_keyboard_load_time_logged = false;
-base::LazyInstance<base::Time>::DestructorAtExit g_keyboard_load_time_start =
- LAZY_INSTANCE_INITIALIZER;
-
-struct keyboard::KeyboardConfig g_keyboard_config;
-
bool g_accessibility_keyboard_enabled = false;
-bool g_hotrod_keyboard_enabled = false;
-
bool g_keyboard_enabled_from_shelf = false;
bool g_touch_keyboard_enabled = false;
KeyboardState g_requested_keyboard_state = KEYBOARD_STATE_AUTO;
-KeyboardOverscrolOverride g_keyboard_overscroll_override =
- KEYBOARD_OVERSCROLL_OVERRIDE_NONE;
-
KeyboardShowOverride g_keyboard_show_override = KEYBOARD_SHOW_OVERRIDE_NONE;
} // namespace
-bool UpdateKeyboardConfig(const KeyboardConfig& keyboard_config) {
- if (g_keyboard_config == keyboard_config)
- return false;
- g_keyboard_config = keyboard_config;
- auto* controller = KeyboardController::Get();
- if (controller->enabled())
- controller->NotifyKeyboardConfigChanged();
- return true;
-}
-
-const KeyboardConfig& GetKeyboardConfig() {
- return g_keyboard_config;
-}
-
void SetAccessibilityKeyboardEnabled(bool enabled) {
g_accessibility_keyboard_enabled = enabled;
}
@@ -92,14 +57,6 @@ bool GetAccessibilityKeyboardEnabled() {
return g_accessibility_keyboard_enabled;
}
-void SetHotrodKeyboardEnabled(bool enabled) {
- g_hotrod_keyboard_enabled = enabled;
-}
-
-bool GetHotrodKeyboardEnabled() {
- return g_hotrod_keyboard_enabled;
-}
-
void SetKeyboardEnabledFromShelf(bool enabled) {
g_keyboard_enabled_from_shelf = enabled;
}
@@ -120,10 +77,6 @@ void SetRequestedKeyboardState(KeyboardState state) {
g_requested_keyboard_state = state;
}
-KeyboardState GetKeyboardRequestedState() {
- return g_requested_keyboard_state;
-}
-
std::string GetKeyboardLayout() {
// TODO(bshe): layout string is currently hard coded. We should use more
// standard keyboard layouts.
@@ -155,97 +108,8 @@ bool IsKeyboardEnabled() {
g_requested_keyboard_state == KEYBOARD_STATE_ENABLED;
}
-bool IsKeyboardVisible() {
- auto* keyboard_controller = keyboard::KeyboardController::Get();
- return keyboard_controller->enabled() &&
- keyboard_controller->IsKeyboardVisible();
-}
-
-bool IsKeyboardOverscrollEnabled() {
- if (!IsKeyboardEnabled())
- return false;
-
- // Users of the sticky accessibility on-screen keyboard are likely to be using
- // mouse input, which may interfere with overscrolling.
- if (keyboard::KeyboardController::Get()->enabled() &&
- !keyboard::KeyboardController::Get()->IsOverscrollAllowed())
- return false;
-
- // If overscroll enabled override is set, use it instead. Currently
- // login / out-of-box disable keyboard overscroll. http://crbug.com/363635
- if (g_keyboard_overscroll_override != KEYBOARD_OVERSCROLL_OVERRIDE_NONE) {
- return g_keyboard_overscroll_override ==
- KEYBOARD_OVERSCROLL_OVERRIDE_ENABLED;
- }
-
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableVirtualKeyboardOverscroll)) {
- return false;
- }
- return true;
-}
-
-void SetKeyboardOverscrollOverride(KeyboardOverscrolOverride override) {
- g_keyboard_overscroll_override = override;
-}
-
-void SetKeyboardShowOverride(KeyboardShowOverride override) {
- g_keyboard_show_override = override;
-}
-
-bool IsInputViewEnabled() {
- return !base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableInputView);
-}
-
-bool IsExperimentalInputViewEnabled() {
- return base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableExperimentalInputViewFeatures);
-}
-
-bool IsFloatingVirtualKeyboardEnabled() {
- return base::FeatureList::IsEnabled(features::kEnableFloatingVirtualKeyboard);
-}
-
-bool IsFullscreenHandwritingVirtualKeyboardEnabled() {
- return base::FeatureList::IsEnabled(
- features::kEnableFullscreenHandwritingVirtualKeyboard);
-}
-
-bool IsStylusVirtualKeyboardEnabled() {
- return base::FeatureList::IsEnabled(features::kEnableStylusVirtualKeyboard);
-}
-
-bool IsVirtualKeyboardMdUiEnabled() {
- return base::FeatureList::IsEnabled(features::kEnableVirtualKeyboardMdUi);
-}
-
-bool IsGestureTypingEnabled() {
- return !base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableGestureTyping);
-}
-
-bool IsGestureEditingEnabled() {
- return !base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableGestureEditing);
-}
-
-bool InsertText(const base::string16& text) {
- auto* controller = KeyboardController::Get();
- if (!controller->enabled())
- return false;
-
- ui::InputMethod* input_method = controller->ui()->GetInputMethod();
- if (!input_method)
- return false;
-
- ui::TextInputClient* tic = input_method->GetTextInputClient();
- if (!tic || tic->GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
- return false;
-
- tic->InsertText(text);
-
- return true;
+void SetKeyboardShowOverride(KeyboardShowOverride show_override) {
+ g_keyboard_show_override = show_override;
}
bool SendKeyEvent(const std::string type,
@@ -307,6 +171,12 @@ bool SendKeyEvent(const std::string type,
code,
dom_code,
modifiers);
+
+ // Marks the simulated key event is from the Virtual Keyboard.
+ ui::Event::Properties properties;
+ properties[ui::kPropertyFromVK] = std::vector<uint8_t>();
+ event.SetProperties(properties);
+
ui::EventDispatchDetails details =
host->event_sink()->OnEventFromSource(&event);
CHECK(!details.dispatcher_destroyed);
@@ -314,29 +184,4 @@ bool SendKeyEvent(const std::string type,
return true;
}
-void MarkKeyboardLoadStarted() {
- if (!g_keyboard_load_time_logged)
- g_keyboard_load_time_start.Get() = base::Time::Now();
-}
-
-void MarkKeyboardLoadFinished() {
- // Possible to get a load finished without a start if navigating directly to
- // chrome://keyboard.
- if (g_keyboard_load_time_start.Get().is_null())
- return;
-
- if (!g_keyboard_load_time_logged) {
- // Log the delta only once.
- UMA_HISTOGRAM_TIMES(
- "VirtualKeyboard.InitLatency.FirstLoad",
- base::Time::Now() - g_keyboard_load_time_start.Get());
- g_keyboard_load_time_logged = true;
- }
-}
-
-void LogKeyboardControlEvent(KeyboardControlEvent event) {
- UMA_HISTOGRAM_ENUMERATION("VirtualKeyboard.KeyboardControlEvent", event,
- KEYBOARD_CONTROL_MAX);
-}
-
} // namespace keyboard
diff --git a/chromium/ui/keyboard/keyboard_util.h b/chromium/ui/keyboard/keyboard_util.h
index 44caaf4a205..740259d2967 100644
--- a/chromium/ui/keyboard/keyboard_util.h
+++ b/chromium/ui/keyboard/keyboard_util.h
@@ -10,47 +10,16 @@
#include "base/strings/string16.h"
#include "ui/keyboard/keyboard_export.h"
+// Global utility functions for the virtual keyboard.
+// TODO(stevenjb/shuchen/shend): Many of these are accessed from both Chrome
+// and Ash. We need to remove any Chrome dependencies. htpps://crbug.com/843332
+
namespace aura {
class WindowTreeHost;
}
namespace keyboard {
-// For virtual keyboard IME extension.
-struct KeyboardConfig {
- bool auto_complete = true;
- bool auto_correct = true;
- bool auto_capitalize = true;
- bool handwriting = true;
- bool spell_check = true;
- // It denotes the preferred value, and can be true even if there is no actual
- // audio input device.
- bool voice_input = true;
-
- bool operator==(const keyboard::KeyboardConfig& rhs) const {
- return auto_complete == rhs.auto_complete &&
- auto_correct == rhs.auto_correct &&
- auto_capitalize == rhs.auto_capitalize &&
- handwriting == rhs.handwriting && spell_check == rhs.spell_check &&
- voice_input == rhs.voice_input;
- }
-};
-
-// An enumeration of different keyboard control events that should be logged.
-enum KeyboardControlEvent {
- KEYBOARD_CONTROL_SHOW = 0,
- KEYBOARD_CONTROL_HIDE_AUTO,
- KEYBOARD_CONTROL_HIDE_USER,
- KEYBOARD_CONTROL_MAX,
-};
-
-// An enumeration of keyboard overscroll override value.
-enum KeyboardOverscrolOverride {
- KEYBOARD_OVERSCROLL_OVERRIDE_DISABLED = 0,
- KEYBOARD_OVERSCROLL_OVERRIDE_ENABLED,
- KEYBOARD_OVERSCROLL_OVERRIDE_NONE,
-};
-
// An enumeration of keyboard policy settings.
enum KeyboardShowOverride {
KEYBOARD_SHOW_OVERRIDE_DISABLED = 0,
@@ -68,14 +37,6 @@ enum KeyboardState {
KEYBOARD_STATE_DISABLED,
};
-// Updates the current keyboard config with the given config is they are
-// different, notifying to observers. Returns whether update happened.
-KEYBOARD_EXPORT bool UpdateKeyboardConfig(
- const keyboard::KeyboardConfig& keyboard_config);
-
-// Gets the current virtual keyboard IME config.
-KEYBOARD_EXPORT const keyboard::KeyboardConfig& GetKeyboardConfig();
-
// Sets the state of the a11y onscreen keyboard.
KEYBOARD_EXPORT void SetAccessibilityKeyboardEnabled(bool enabled);
@@ -112,22 +73,9 @@ KEYBOARD_EXPORT std::string GetKeyboardLayout();
// Returns true if the virtual keyboard is enabled.
KEYBOARD_EXPORT bool IsKeyboardEnabled();
-// Returns true if the virtual keyboard is currently visible.
-KEYBOARD_EXPORT bool IsKeyboardVisible();
-
-// Returns true if keyboard overscroll mode is enabled.
-KEYBOARD_EXPORT bool IsKeyboardOverscrollEnabled();
-
-// Sets temporary keyboard overscroll override.
-KEYBOARD_EXPORT void SetKeyboardOverscrollOverride(
- KeyboardOverscrolOverride override);
-
// Sets policy override on whether to show the keyboard.
-KEYBOARD_EXPORT void SetKeyboardShowOverride(KeyboardShowOverride override);
-
-// Returns true if an IME extension can specify a custom input view for the
-// virtual keyboard window.
-KEYBOARD_EXPORT bool IsInputViewEnabled();
+KEYBOARD_EXPORT void SetKeyboardShowOverride(
+ KeyboardShowOverride show_override);
// Sets whehther the keyboards is in restricted state - state where advanced
// virtual keyboard features are disabled.
@@ -136,36 +84,6 @@ KEYBOARD_EXPORT void SetKeyboardRestricted(bool restricted);
// Returns whether the keyboard is in restricted state.
KEYBOARD_EXPORT bool GetKeyboardRestricted();
-// Returns true if experimental features are enabled for IME input-views.
-KEYBOARD_EXPORT bool IsExperimentalInputViewEnabled();
-
-// Returns true if floating virtual keyboard feature is enabled.
-KEYBOARD_EXPORT bool IsFloatingVirtualKeyboardEnabled();
-
-// Returns true if fullscreen handwriting virtual keyboard feature is enabled.
-KEYBOARD_EXPORT bool IsFullscreenHandwritingVirtualKeyboardEnabled();
-
-// Returns true if stylus virtual keyboard feature is enabled.
-KEYBOARD_EXPORT bool IsStylusVirtualKeyboardEnabled();
-
-// Returns true if virtual keyboard md ui feature is enabled.
-KEYBOARD_EXPORT bool IsVirtualKeyboardMdUiEnabled();
-
-// Returns true if gesture typing option is enabled for virtual keyboard.
-KEYBOARD_EXPORT bool IsGestureTypingEnabled();
-
-// Returns true if gesture editing option is enabled for virtual keyboard.
-KEYBOARD_EXPORT bool IsGestureEditingEnabled();
-
-// Returns true if voice input is not disabled for the keyboard by the command
-// line switch. It's up to the client to check if there is an input device
-// available.
-KEYBOARD_EXPORT bool IsVoiceInputEnabled();
-
-// Insert |text| into the active TextInputClient if there is one. Returns true
-// if |text| was successfully inserted.
-KEYBOARD_EXPORT bool InsertText(const base::string16& text);
-
// Sends a fabricated key event, where |type| is the event type, |key_value|
// is the unicode value of the character, |key_code| is the legacy key code
// value, |key_name| is the name of the key as defined in the DOM3 key event
@@ -179,18 +97,6 @@ KEYBOARD_EXPORT bool SendKeyEvent(std::string type,
int modifiers,
aura::WindowTreeHost* host);
-// Marks that the keyboard load has started. This is used to measure the time it
-// takes to fully load the keyboard. This should be called before
-// MarkKeyboardLoadFinished.
-KEYBOARD_EXPORT void MarkKeyboardLoadStarted();
-
-// Marks that the keyboard load has ended. This finishes measuring that the
-// keyboard is loaded.
-KEYBOARD_EXPORT void MarkKeyboardLoadFinished();
-
-// Logs the keyboard control event as a UMA stat.
-void LogKeyboardControlEvent(KeyboardControlEvent event);
-
} // namespace keyboard
#endif // UI_KEYBOARD_KEYBOARD_UTIL_H_
diff --git a/chromium/ui/keyboard/keyboard_util_unittest.cc b/chromium/ui/keyboard/keyboard_util_unittest.cc
index ed5df410df1..5361b06259b 100644
--- a/chromium/ui/keyboard/keyboard_util_unittest.cc
+++ b/chromium/ui/keyboard/keyboard_util_unittest.cc
@@ -8,6 +8,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/keyboard/keyboard_controller.h"
#include "ui/keyboard/keyboard_ui.h"
+#include "ui/keyboard/keyboard_util.h"
#include "ui/keyboard/test/keyboard_test_util.h"
namespace keyboard {
@@ -125,33 +126,38 @@ TEST_F(KeyboardUtilTest, HideKeyboardWhenTouchEnabled) {
TEST_F(KeyboardUtilTest, UpdateKeyboardConfig) {
ResetAllFlags();
- keyboard::KeyboardConfig config = keyboard::GetKeyboardConfig();
+ auto config = keyboard_controller_.keyboard_config();
EXPECT_TRUE(config.spell_check);
- EXPECT_FALSE(keyboard::UpdateKeyboardConfig(config));
+ EXPECT_FALSE(keyboard_controller_.UpdateKeyboardConfig(config));
config.spell_check = false;
- EXPECT_TRUE(keyboard::UpdateKeyboardConfig(config));
- EXPECT_FALSE(keyboard::GetKeyboardConfig().spell_check);
+ EXPECT_TRUE(keyboard_controller_.UpdateKeyboardConfig(config));
+ EXPECT_FALSE(keyboard_controller_.keyboard_config().spell_check);
- EXPECT_FALSE(keyboard::UpdateKeyboardConfig(config));
+ EXPECT_FALSE(keyboard_controller_.UpdateKeyboardConfig(config));
}
TEST_F(KeyboardUtilTest, IsOverscrollEnabled) {
ResetAllFlags();
// Return false when keyboard is disabled.
- EXPECT_FALSE(keyboard::IsKeyboardOverscrollEnabled());
+ EXPECT_FALSE(keyboard_controller_.IsKeyboardOverscrollEnabled());
// Enable the virtual keyboard.
keyboard::SetTouchKeyboardEnabled(true);
- EXPECT_TRUE(keyboard::IsKeyboardOverscrollEnabled());
+ EXPECT_TRUE(keyboard_controller_.IsKeyboardOverscrollEnabled());
+
+ // Set overscroll enabled state.
+ auto config = keyboard::KeyboardController::Get()->keyboard_config();
+ config.overscroll_behavior =
+ keyboard::mojom::KeyboardOverscrollBehavior::kDisabled;
+ keyboard::KeyboardController::Get()->UpdateKeyboardConfig(config);
+ EXPECT_FALSE(keyboard_controller_.IsKeyboardOverscrollEnabled());
- // Override overscroll enabled state.
- keyboard::SetKeyboardOverscrollOverride(
- KEYBOARD_OVERSCROLL_OVERRIDE_DISABLED);
- EXPECT_FALSE(keyboard::IsKeyboardOverscrollEnabled());
- keyboard::SetKeyboardOverscrollOverride(KEYBOARD_OVERSCROLL_OVERRIDE_NONE);
- EXPECT_TRUE(keyboard::IsKeyboardOverscrollEnabled());
+ config.overscroll_behavior =
+ keyboard::mojom::KeyboardOverscrollBehavior::kDefault;
+ keyboard::KeyboardController::Get()->UpdateKeyboardConfig(config);
+ EXPECT_TRUE(keyboard_controller_.IsKeyboardOverscrollEnabled());
// Set keyboard_locked() to true.
ui::DummyInputMethod input_method;
@@ -159,7 +165,7 @@ TEST_F(KeyboardUtilTest, IsOverscrollEnabled) {
std::make_unique<TestKeyboardUI>(&input_method), nullptr);
keyboard_controller_.set_keyboard_locked(true);
EXPECT_TRUE(keyboard_controller_.keyboard_locked());
- EXPECT_FALSE(keyboard::IsKeyboardOverscrollEnabled());
+ EXPECT_FALSE(keyboard_controller_.IsKeyboardOverscrollEnabled());
keyboard_controller_.DisableKeyboard();
}
diff --git a/chromium/ui/keyboard/public/OWNERS b/chromium/ui/keyboard/public/OWNERS
new file mode 100644
index 00000000000..08850f42120
--- /dev/null
+++ b/chromium/ui/keyboard/public/OWNERS
@@ -0,0 +1,2 @@
+per-file *.mojom=set noparent
+per-file *.mojom=file://ipc/SECURITY_OWNERS
diff --git a/chromium/ui/keyboard/public/keyboard_config.mojom b/chromium/ui/keyboard/public/keyboard_config.mojom
new file mode 100644
index 00000000000..1c37f572c43
--- /dev/null
+++ b/chromium/ui/keyboard/public/keyboard_config.mojom
@@ -0,0 +1,40 @@
+// 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.
+
+module keyboard.mojom;
+
+// Determines how the keyboard overscroll enabled state is set,
+enum KeyboardOverscrollBehavior {
+ // Use the default behavior.
+ kDefault,
+
+ // Enable keyboard overscroll if allowed.
+ kEnabled,
+
+ // Do not enable keyboard overscroll.
+ kDisabled,
+};
+
+struct KeyboardConfig {
+ // Whether the virtual keyboard can provide auto-complete.
+ bool auto_complete = true;
+
+ // Whether the virtual keyboard can provide auto-correct.
+ bool auto_correct = true;
+
+ // Whether the virtual keyboard can provide auto-capitalization.
+ bool auto_capitalize = true;
+
+ // Whether the virtual keyboard can provide input via handwriting recognition.
+ bool handwriting = true;
+
+ // Whether the virtual keyboard can provide spell-check.
+ bool spell_check = true;
+
+ // Whether the virtual keyboard can provide voice input.
+ bool voice_input = true;
+
+ // Whether overscroll is currently allowed by the active keyboard container.
+ KeyboardOverscrollBehavior overscroll_behavior = kDefault;
+};
diff --git a/chromium/ui/latency/frame_metrics.cc b/chromium/ui/latency/frame_metrics.cc
index 7a1c5ed049a..27f26b9de71 100644
--- a/chromium/ui/latency/frame_metrics.cc
+++ b/chromium/ui/latency/frame_metrics.cc
@@ -8,6 +8,7 @@
#include <limits>
#include <vector>
+#include "base/bit_cast.h"
#include "base/trace_event/trace_event.h"
#include "base/trace_event/trace_event_argument.h"
@@ -18,7 +19,7 @@ namespace {
// How often to report results.
// This needs to be short enough to avoid overflow in the accumulators.
constexpr base::TimeDelta kDefaultReportPeriod =
- base::TimeDelta::FromMinutes(1);
+ base::TimeDelta::FromSeconds(1);
// Gives the histogram for skips the highest precision just above a
// skipped:produced ratio of 1.
@@ -308,10 +309,10 @@ void FrameMetrics::AddFrameDisplayed(base::TimeTicks source_timestamp,
latency.InMicroseconds() * kFixedPointMultiplierLatency;
latency_analyzer_.AddSample(CapValue(latency_value), kLatencySampleWeight);
- // Only calculate velocity if there's enough history.
- if (latencies_added_ >= 1) {
- base::TimeDelta latency_delta = latency - latency_prev_;
- base::TimeDelta source_duration = source_timestamp - source_timestamp_prev_;
+ base::TimeDelta latency_delta = latency - latency_prev_;
+ base::TimeDelta source_duration = source_timestamp - source_timestamp_prev_;
+ // Only calculate speed if there's enough history.
+ if (latencies_added_ >= 1 && settings_.is_frame_latency_speed_on()) {
int64_t latency_velocity =
(latency_delta * kFixedPointMultiplierLatencySpeed) / source_duration;
@@ -319,35 +320,29 @@ void FrameMetrics::AddFrameDisplayed(base::TimeTicks source_timestamp,
// entries to avoid overflow in the accumulators just in case.
latency_speed_analyzer_.AddSample(CapValue(latency_velocity),
CapDuration(source_duration));
+ }
- // Only calculate acceleration if there's enough history.
- if (latencies_added_ >= 2) {
- base::TimeDelta source_duration_average =
- (source_duration + source_duration_prev_) / 2;
- int64_t latency_acceleration =
- (((latency_delta * kFixedPointMultiplierLatencyAcceleration) /
- source_duration) -
- ((latency_delta_prev_ * kFixedPointMultiplierLatencyAcceleration) /
- source_duration_prev_)) /
- source_duration_average.InMicroseconds();
- latency_acceleration_analyzer_.AddSample(
- CapValue(latency_acceleration), CapDuration(source_duration_average));
- }
-
- // Update history.
+ // Only calculate acceleration if there's enough history.
+ if (latencies_added_ >= 2 && settings_.is_frame_latency_acceleration_on()) {
+ base::TimeDelta source_duration_average =
+ (source_duration + source_duration_prev_) / 2;
+ int64_t latency_acceleration =
+ (((latency_delta * kFixedPointMultiplierLatencyAcceleration) /
+ source_duration) -
+ ((latency_delta_prev_ * kFixedPointMultiplierLatencyAcceleration) /
+ source_duration_prev_)) /
+ source_duration_average.InMicroseconds();
+ latency_acceleration_analyzer_.AddSample(
+ CapValue(latency_acceleration), CapDuration(source_duration_average));
+ }
+ // Update history.
+ if (latencies_added_ >= 1) {
source_duration_prev_ = source_duration;
latency_delta_prev_ = latency_delta;
}
-
- // Update history.
source_timestamp_prev_ = source_timestamp;
latency_prev_ = latency;
latencies_added_++;
-
- bool tracing_enabled = 0;
- TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategories, &tracing_enabled);
- if (tracing_enabled)
- TraceStats();
}
void FrameMetrics::Reset() {
@@ -366,8 +361,10 @@ void FrameMetrics::Reset() {
frame_skips_analyzer_.Reset();
latency_analyzer_.Reset();
- latency_speed_analyzer_.Reset();
- latency_acceleration_analyzer_.Reset();
+ if (settings_.is_frame_latency_speed_on())
+ latency_speed_analyzer_.Reset();
+ if (settings_.is_frame_latency_acceleration_on())
+ latency_acceleration_analyzer_.Reset();
}
// Reset analyzers, but don't reset resent latency history so we can get
@@ -379,6 +376,11 @@ void FrameMetrics::Reset() {
void FrameMetrics::StartNewReportPeriod() {
TRACE_EVENT0(kTraceCategories, "FrameMetrics::StartNewReportPeriod");
+ bool tracing_enabled = 0;
+ TRACE_EVENT_CATEGORY_GROUP_ENABLED(kTraceCategories, &tracing_enabled);
+ if (tracing_enabled)
+ TraceStats();
+
time_since_start_of_report_period_ = base::TimeDelta();
frames_produced_since_start_of_report_period_ = 0;
@@ -388,6 +390,27 @@ void FrameMetrics::StartNewReportPeriod() {
latency_acceleration_analyzer_.StartNewReportPeriod();
}
+double FrameMetrics::FastApproximateSqrt(double x) {
+ if (x <= 0)
+ return 0;
+ // Basically performs x*fastinvSqrt(x) - using high precision (3 steps)
+ double y = x;
+ double xhalf = 0.5f * x;
+ float xf = static_cast<float>(x);
+ int32_t i = bit_cast<int32_t>(xf);
+ // Magic Number for initial guess. Reference:
+ // http://www.lomont.org/Math/Papers/2003/InvSqrt.pdf.
+ i = 0x5f3759df - (i >> 1);
+ x = static_cast<double>(bit_cast<float>(i));
+ // Newton step.
+ x = x * (1.5 - xhalf * x * x);
+ // Newton step.
+ x = x * (1.5 - xhalf * x * x);
+ // Newton step.
+ x = x * (1.5 - xhalf * x * x);
+ return y * x;
+}
+
namespace {
// FrameMetricsTraceData delegates tracing logic to TracedValue in a deferred
@@ -417,13 +440,17 @@ class FrameMetricsTraceData
latency.AsValueInto(&state);
state.EndDictionary();
- state.BeginDictionary("Speed");
- speed.AsValueInto(&state);
- state.EndDictionary();
+ if (settings.is_frame_latency_speed_on()) {
+ state.BeginDictionary("Speed");
+ speed.AsValueInto(&state);
+ state.EndDictionary();
+ }
- state.BeginDictionary("Acceleration");
- acceleration.AsValueInto(&state);
- state.EndDictionary();
+ if (settings.is_frame_latency_acceleration_on()) {
+ state.BeginDictionary("Acceleration");
+ acceleration.AsValueInto(&state);
+ state.EndDictionary();
+ }
state.AppendAsTraceFormat(out);
}
@@ -447,8 +474,10 @@ void FrameMetrics::TraceStats() const {
trace_data->settings = settings_;
frame_skips_analyzer_.ComputeSummary(&trace_data->skips);
latency_analyzer_.ComputeSummary(&trace_data->latency);
- latency_speed_analyzer_.ComputeSummary(&trace_data->speed);
- latency_acceleration_analyzer_.ComputeSummary(&trace_data->acceleration);
+ if (settings_.is_frame_latency_speed_on())
+ latency_speed_analyzer_.ComputeSummary(&trace_data->speed);
+ if (settings_.is_frame_latency_acceleration_on())
+ latency_acceleration_analyzer_.ComputeSummary(&trace_data->acceleration);
}
TRACE_EVENT_INSTANT1(kTraceCategories, "FrameMetrics",
TRACE_EVENT_SCOPE_THREAD, "Info", std::move(trace_data));
diff --git a/chromium/ui/latency/frame_metrics.h b/chromium/ui/latency/frame_metrics.h
index d680541c26b..d0f6f351d6b 100644
--- a/chromium/ui/latency/frame_metrics.h
+++ b/chromium/ui/latency/frame_metrics.h
@@ -73,6 +73,18 @@ struct FrameMetricsSettings {
trace_results_every_frame(trace_results_every_frame),
max_window_size(max_window_size) {}
+ void set_is_frame_latency_speed_on(bool is_speed_on) {
+ is_frame_latency_speed_on_ = is_speed_on;
+ }
+ void set_is_frame_latency_acceleration_on(bool is_acceleration_on) {
+ is_frame_latency_acceleration_on_ = is_acceleration_on;
+ }
+
+ bool is_frame_latency_speed_on() const { return is_frame_latency_speed_on_; }
+ bool is_frame_latency_acceleration_on() const {
+ return is_frame_latency_acceleration_on_;
+ }
+
// Source configuration.
FrameMetricsSource source;
FrameMetricsSourceThread source_thread;
@@ -86,6 +98,13 @@ struct FrameMetricsSettings {
size_t max_window_size;
void AsValueInto(base::trace_event::TracedValue* state) const;
+
+ private:
+ // Switch for frame latency speed measurements control.
+ bool is_frame_latency_speed_on_ = false;
+
+ // Switch for frame latency acceleration measurements control.
+ bool is_frame_latency_acceleration_on_ = false;
};
// Calculates all metrics for a frame source.
@@ -103,15 +122,22 @@ class FrameMetrics : public SkippedFrameTracker::Client {
void Reset();
// AddFrameProduced should be called every time a source produces a frame.
- // The information added here affects the number of frames skipped.
- // Note: If the FrameMetrics class is hooked up to an optional
- // SkippedFrameTracker, the client should not call this directly.
+ // |source_timestamp| is when frame time in BeginFrameArgs(i.e. when the frame
+ // is produced); |amount_produced| is the expected time interval between 2
+ // consecutive frames; |amount_skipped| is number of frame skipped before
+ // producing this frame multiplies by the interval, i.e., if 1 frame is
+ // skipped in 30 fps setting, then |amount_skipped| is 33.33ms; if 1 frame is
+ // skipped in 60FPS setting, then the |amount_skipped| is 16.67ms. Note: If
+ // the FrameMetrics class is hooked up to an optional SkippedFrameTracker, the
+ // client should not call this directly.
void AddFrameProduced(base::TimeTicks source_timestamp,
base::TimeDelta amount_produced,
base::TimeDelta amount_skipped) override;
// AddFrameDisplayed should be called whenever a frame causes damage and
- // we know when the result became visible on the display.
+ // we know when the result became visible on the display. |source_timestamp|
+ // is when frame time in BeginFrameArgs(i.e. when the frame is produced);
+ // |display_timestamp| is when the frame is displayed on screen.
// This will affect all latency derived metrics, including latency speed,
// latency acceleration, and latency itself.
// If a frame is produced but not displayed, do not call this; there was
@@ -120,17 +146,25 @@ class FrameMetrics : public SkippedFrameTracker::Client {
void AddFrameDisplayed(base::TimeTicks source_timestamp,
base::TimeTicks display_timestamp);
+ // Compute the square root by using method described in paper:
+ // http://www.lomont.org/Math/Papers/2003/InvSqrt.pdf.
+ // It finds a result within 0.0001 and 0.1 of the true square root for |x| <
+ // 100 and |x| < 2^15 respectively. It's more than 2 times faster for Nexus 4
+ // and other lower end android devices and ~3-5% faster on desktop. Crash when
+ // x is less than 0.
+ static double FastApproximateSqrt(double x);
+
protected:
void TraceStats() const;
// virtual for testing.
virtual base::TimeDelta ReportPeriod();
- // Starts a new reporting period that resets the various accumulators
- // and memory of worst regions encountered, but does not destroy recent
- // sample history in the windowed analyzers and in the derivatives
- // for latency speed and latency acceleration. This avoids small gaps
- // in coverage when starting a new reporting period.
+ // Starts a new reporting period after |kDefaultReportPeriod| time that resets
+ // the various accumulators and memory of worst regions encountered, but does
+ // not destroy recent sample history in the windowed analyzers and in the
+ // derivatives for latency speed and latency acceleration. This avoids small
+ // gaps in coverage when starting a new reporting period.
void StartNewReportPeriod();
FrameMetricsSettings settings_;
diff --git a/chromium/ui/latency/frame_metrics_test_common.h b/chromium/ui/latency/frame_metrics_test_common.h
index c48e81452b4..5ee17c4c89b 100644
--- a/chromium/ui/latency/frame_metrics_test_common.h
+++ b/chromium/ui/latency/frame_metrics_test_common.h
@@ -15,10 +15,8 @@
// Some convenience macros for checking expected error.
#define EXPECT_ABS_LT(a, b) EXPECT_LT(std::abs(a), std::abs(b))
#define EXPECT_ABS_LE(a, b) EXPECT_LE(std::abs(a), std::abs(b))
-#define EXPECT_NEAR_SMR(expected, actual, weight) \
- EXPECT_NEAR(expected, actual, MaxErrorSMR(expected, weight))
-#define EXPECT_NEAR_VARIANCE_OF_ROOT(expected, actual, mean, weight) \
- EXPECT_NEAR(expected, actual, MaxErrorSMR(mean, weight));
+#define EXPECT_NEAR_SQRT_APPROX(expected, actual) \
+ EXPECT_NEAR(expected, actual, MaxErrorSQRTApprox(expected, actual))
namespace ui {
namespace frame_metrics {
@@ -76,21 +74,6 @@ void AddPatternHelper(SharedWindowedAnalyzerClient* shared_client,
}
}
-// Same as AddPatternHelper, but uses each value (+1) as its own weight.
-// The "Cubed" name comes from the fact that the squared_accumulator
-// for the RMS will effectively be a "cubed accumulator".
-template <typename AnalyzerType>
-void AddCubedPatternHelper(SharedWindowedAnalyzerClient* shared_client,
- AnalyzerType* analyzer,
- const std::vector<uint32_t>& values) {
- for (auto i : values) {
- shared_client->window_begin += base::TimeDelta::FromMicroseconds(1);
- shared_client->window_end += base::TimeDelta::FromMicroseconds(1);
- // weight is i+1 to avoid divide by zero.
- AddSamplesHelper(analyzer, i, i + 1, 1);
- }
-}
-
// Mean and RMS can be exact for most values, however SMR loses a bit of
// precision internally when accumulating the roots. Make sure the SMR
// precision is at least within .5 (i.e. rounded to the nearest integer
@@ -99,8 +82,8 @@ void AddCubedPatternHelper(SharedWindowedAnalyzerClient* shared_client,
// between ~5 and ~13 decimal places.
// The precision should be even better when the sample's |weight| > 1 since
// the implementation should only do any rounding after scaling by weight.
-inline double MaxErrorSMR(double expected_value, uint64_t weight) {
- return std::max(.5, 1e-8 * expected_value / weight);
+inline double MaxErrorSQRTApprox(double expected_value, double value) {
+ return std::max(0.5, std::max(expected_value, value) * 1e-3);
}
// This class initializes the ratio boundaries on construction in a way that
diff --git a/chromium/ui/latency/frame_metrics_unittest.cc b/chromium/ui/latency/frame_metrics_unittest.cc
index dd142de6571..55f43a7aecf 100644
--- a/chromium/ui/latency/frame_metrics_unittest.cc
+++ b/chromium/ui/latency/frame_metrics_unittest.cc
@@ -5,6 +5,7 @@
#include "ui/latency/frame_metrics.h"
#include "base/bind.h"
+#include "base/rand_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/latency/frame_metrics_test_common.h"
@@ -131,7 +132,10 @@ class FrameMetricsTest : public testing::Test {
FrameMetricsTest()
: settings(ui::FrameMetricsSource::UnitTest,
ui::FrameMetricsSourceThread::Unknown,
- ui::FrameMetricsCompileTarget::Unknown) {}
+ ui::FrameMetricsCompileTarget::Unknown) {
+ settings.set_is_frame_latency_speed_on(true);
+ settings.set_is_frame_latency_acceleration_on(true);
+ }
void SetUp() override {
// Make sure we don't get an unexpected call to StartNewReportPeriod.
@@ -237,15 +241,13 @@ TEST_F(FrameMetricsTest, PerfectLatencyScores) {
TestStreamAnalysis r = LatencyAnalysis();
EXPECT_DOUBLE_EQ(latency.InSecondsF(), r.mean);
- EXPECT_DOUBLE_EQ(latency.InSecondsF(), r.rms);
- EXPECT_NEAR_SMR(r.smr, latency.InSecondsF(), produced.InMicroseconds());
+ EXPECT_NEAR_SQRT_APPROX(latency.InSecondsF(), r.rms);
+ EXPECT_NEAR_SQRT_APPROX(r.smr, latency.InSecondsF());
EXPECT_EQ(0, r.std_dev);
- EXPECT_NEAR_VARIANCE_OF_ROOT(0, r.variance_of_roots, 0,
- produced.InMicroseconds());
+ EXPECT_NEAR_SQRT_APPROX(0, r.variance_of_roots);
EXPECT_DOUBLE_EQ(latency.InSecondsF(), r.worst_mean.value);
- EXPECT_DOUBLE_EQ(latency.InSecondsF(), r.worst_rms.value);
- EXPECT_NEAR_SMR(r.worst_smr.value, latency.InSecondsF(),
- produced.InMicroseconds());
+ EXPECT_NEAR_SQRT_APPROX(latency.InSecondsF(), r.worst_rms.value);
+ EXPECT_NEAR_SQRT_APPROX(r.worst_smr.value, latency.InSecondsF());
}
// Apply a saw tooth pattern to the frame skips with values that are easy to
@@ -273,8 +275,8 @@ TEST_F(FrameMetricsTest, SawToothShapedSkips) {
const double expected_skip_to_produce_rms =
std::sqrt(expected_skip_to_produce_mean_square);
const double expected_skip_rms = SkipTransform(expected_skip_to_produce_rms);
- EXPECT_EQ(expected_skip_rms, r.rms);
- EXPECT_EQ(expected_skip_rms, r.worst_rms.value);
+ EXPECT_NEAR_SQRT_APPROX(expected_skip_rms, r.rms);
+ EXPECT_NEAR_SQRT_APPROX(expected_skip_rms, r.worst_rms.value);
const double expected_expected_skip_to_produce_mean_root = (0 + 1.0) / 2;
const double expected_expected_skip_to_produce_smr =
@@ -282,13 +284,13 @@ TEST_F(FrameMetricsTest, SawToothShapedSkips) {
expected_expected_skip_to_produce_mean_root;
const double expected_skip_smr =
SkipTransform(expected_expected_skip_to_produce_smr);
- EXPECT_EQ(expected_skip_smr, r.smr);
- EXPECT_EQ(expected_skip_smr, r.worst_smr.value);
+ EXPECT_NEAR_SQRT_APPROX(expected_skip_smr, r.smr);
+ EXPECT_NEAR_SQRT_APPROX(expected_skip_smr, r.worst_smr.value);
const double expected_skip_to_produce_std_dev = (0.5 + 0.5) / 2;
const double expected_skip_std_dev =
SkipTransform(expected_skip_to_produce_std_dev);
- EXPECT_EQ(expected_skip_std_dev, r.std_dev);
+ EXPECT_NEAR_SQRT_APPROX(expected_skip_std_dev, r.std_dev);
const double expected_skip_to_produce_std_dev_of_roots = (0.5 + 0.5) / 2;
const double expected_skip_to_produce_variance_of_roots =
@@ -296,7 +298,7 @@ TEST_F(FrameMetricsTest, SawToothShapedSkips) {
expected_skip_to_produce_std_dev_of_roots;
const double expected_skip_variance_of_roots =
SkipTransform(expected_skip_to_produce_variance_of_roots);
- EXPECT_EQ(expected_skip_variance_of_roots, r.variance_of_roots);
+ EXPECT_NEAR_SQRT_APPROX(expected_skip_variance_of_roots, r.variance_of_roots);
}
// Apply a saw tooth pattern to the latency with values that are easy to
@@ -319,34 +321,35 @@ TEST_F(FrameMetricsTest, SawToothShapedLatency) {
const double expected_latency_mean_square = (100.0 * 100 + 36 * 36) / 2;
const double expected_latency_rms = std::sqrt(expected_latency_mean_square);
- EXPECT_DOUBLE_EQ(expected_latency_rms, r.rms);
- EXPECT_DOUBLE_EQ(expected_latency_rms, r.worst_rms.value);
+ EXPECT_NEAR_SQRT_APPROX(expected_latency_rms, r.rms);
+ EXPECT_NEAR_SQRT_APPROX(expected_latency_rms, r.worst_rms.value);
const double expected_latency_mean_root = (10.0 + 6) / 2;
const double expected_latency_smr =
expected_latency_mean_root * expected_latency_mean_root;
- EXPECT_DOUBLE_EQ(expected_latency_smr, r.smr);
- EXPECT_DOUBLE_EQ(expected_latency_smr, r.worst_smr.value);
+ EXPECT_NEAR_SQRT_APPROX(expected_latency_smr, r.smr);
+ EXPECT_NEAR_SQRT_APPROX(expected_latency_smr, r.worst_smr.value);
const double expected_latency_std_dev = (100.0 - 36) / 2;
- EXPECT_DOUBLE_EQ(expected_latency_std_dev, r.std_dev);
+ EXPECT_NEAR_SQRT_APPROX(expected_latency_std_dev, r.std_dev);
const double expected_latency_std_dev_of_roots = (10.0 - 6) / 2;
const double expected_latency_variance_of_roots =
expected_latency_std_dev_of_roots * expected_latency_std_dev_of_roots;
- EXPECT_DOUBLE_EQ(expected_latency_variance_of_roots, r.variance_of_roots);
+ EXPECT_NEAR_SQRT_APPROX(expected_latency_variance_of_roots,
+ r.variance_of_roots);
// Verify latency speed, where mean, RMS, SMR, etc. should be equal.
r = SpeedAnalysis();
const double expected_speed = 64;
EXPECT_DOUBLE_EQ(expected_speed, r.mean);
- EXPECT_DOUBLE_EQ(expected_speed, r.rms);
- EXPECT_DOUBLE_EQ(expected_speed, r.smr);
+ EXPECT_NEAR_SQRT_APPROX(expected_speed, r.rms);
+ EXPECT_NEAR_SQRT_APPROX(expected_speed, r.smr);
EXPECT_DOUBLE_EQ(0, r.std_dev);
- EXPECT_DOUBLE_EQ(0, r.variance_of_roots);
+ EXPECT_NEAR_SQRT_APPROX(0, r.variance_of_roots);
EXPECT_DOUBLE_EQ(expected_speed, r.worst_mean.value);
- EXPECT_DOUBLE_EQ(expected_speed, r.worst_rms.value);
- EXPECT_DOUBLE_EQ(expected_speed, r.worst_smr.value);
+ EXPECT_NEAR_SQRT_APPROX(expected_speed, r.worst_rms.value);
+ EXPECT_NEAR_SQRT_APPROX(expected_speed, r.worst_smr.value);
// Verify latency accelleration, where mean, RMS, SMR, etc. should be equal.
// The slack is relatively large since the frame durations are so long, which
@@ -839,9 +842,9 @@ void FrameMetricsTest::StartNewReportPeriodAvoidsOverflowTest(
TEST_F(FrameMetricsTest, StartNewReportPeriodAvoidsOverflowForSkips) {
base::TimeDelta produced = base::TimeDelta::FromMicroseconds(1);
base::TimeDelta latency = base::TimeDelta::FromMilliseconds(1);
- base::TimeDelta skipped = base::TimeDelta::FromSeconds(66);
+ base::TimeDelta skipped = base::TimeDelta::FromSeconds(2);
- frame_metrics->UseDefaultReportPeriodScaled(4);
+ frame_metrics->UseDefaultReportPeriodScaled(7);
StartNewReportPeriodAvoidsOverflowTest(produced, skipped, latency, latency,
kSkipSaturationMin,
&FrameMetricsTest::SkipAnalysis);
@@ -886,6 +889,30 @@ TEST_F(FrameMetricsTest, StartNewReportPeriodAvoidsOverflowForAcceleration) {
&FrameMetricsTest::AccelerationAnalysis);
}
+// Test the accuracy of the Newton's approximate square root calculation.
+// Since suqare_rooot is always used on small numbers in cc, this test only test
+// accuracy of small |x| value. A random number |x| between (0 - 100) is
+// generated, Test if the difference of square roots obtained from
+// FastApproximateSqrt and std::sqrt is less than |error_rage| (0.0001);
+TEST_F(FrameMetricsTest, SquareRootApproximation) {
+ const double slack = 0.001;
+ for (int i = 0; i < 3; i++) {
+ int x = base::RandInt(0, 100);
+ double sol1 = std::sqrt(x);
+ double sol2 = FrameMetrics::FastApproximateSqrt(x);
+ EXPECT_NEAR(sol1, sol2, slack)
+ << "failed to give a good approximate square root of " << x;
+ }
+
+ for (int i = 0; i < 3; i++) {
+ double x = double{base::RandUint64()} / base::RandomBitGenerator::max();
+ double sol1 = std::sqrt(x);
+ double sol2 = FrameMetrics::FastApproximateSqrt(x);
+ EXPECT_NEAR(sol1, sol2, slack)
+ << "failed to give a good approximate square root of " << x;
+ }
+}
+
} // namespace
} // namespace frame_metrics
} // namespace ui
diff --git a/chromium/ui/latency/latency_info.cc b/chromium/ui/latency/latency_info.cc
index 089a3a9527f..aa09366e00f 100644
--- a/chromium/ui/latency/latency_info.cc
+++ b/chromium/ui/latency/latency_info.cc
@@ -283,7 +283,7 @@ void LatencyInfo::AddLatencyNumberWithTimestampImpl(
"trace_id", trace_id_);
}
- LatencyMap::iterator it = latency_components_.find(component);
+ auto it = latency_components_.find(component);
DCHECK(it == latency_components_.end());
latency_components_[component] = time;
@@ -327,7 +327,7 @@ LatencyInfo::AsTraceableData() {
bool LatencyInfo::FindLatency(LatencyComponentType type,
base::TimeTicks* output) const {
- LatencyMap::const_iterator it = latency_components_.find(type);
+ auto it = latency_components_.find(type);
if (it == latency_components_.end())
return false;
if (output)
diff --git a/chromium/ui/latency/latency_tracker.cc b/chromium/ui/latency/latency_tracker.cc
index 35c320bb5f4..ef6ce7210cd 100644
--- a/chromium/ui/latency/latency_tracker.cc
+++ b/chromium/ui/latency/latency_tracker.cc
@@ -322,26 +322,31 @@ void LatencyTracker::ComputeEndToEndLatencyHistograms(
}
base::TimeTicks renderer_swap_timestamp;
- bool found_component =
+ bool found_renderer_swap_component =
latency.FindLatency(ui::INPUT_EVENT_LATENCY_RENDERER_SWAP_COMPONENT,
&renderer_swap_timestamp);
- DCHECK_AND_RETURN_ON_FAIL(found_component);
-
- UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2(
- "Event.Latency." + scroll_name + "." + input_modality +
- ".HandledToRendererSwap2_" + thread_name,
- rendering_scheduled_timestamp, renderer_swap_timestamp);
base::TimeTicks browser_received_swap_timestamp;
- found_component =
+ bool found_received_frame_component =
latency.FindLatency(ui::DISPLAY_COMPOSITOR_RECEIVED_FRAME_COMPONENT,
&browser_received_swap_timestamp);
- DCHECK_AND_RETURN_ON_FAIL(found_component);
+ DCHECK_AND_RETURN_ON_FAIL(found_received_frame_component);
- UMA_HISTOGRAM_SCROLL_LATENCY_SHORT_2(
- "Event.Latency." + scroll_name + "." + input_modality +
- ".RendererSwapToBrowserNotified2",
- renderer_swap_timestamp, browser_received_swap_timestamp);
+ // If we're committing to the active tree, there will never be a renderer
+ // swap. In this case, don't record the two histogram values for the periods
+ // surrounding the renderer swap. We could assign the total time to one or the
+ // other of them, but that would likely skew statistics.
+ if (found_renderer_swap_component) {
+ UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2(
+ "Event.Latency." + scroll_name + "." + input_modality +
+ ".HandledToRendererSwap2_" + thread_name,
+ rendering_scheduled_timestamp, renderer_swap_timestamp);
+
+ UMA_HISTOGRAM_SCROLL_LATENCY_SHORT_2(
+ "Event.Latency." + scroll_name + "." + input_modality +
+ ".RendererSwapToBrowserNotified2",
+ renderer_swap_timestamp, browser_received_swap_timestamp);
+ }
UMA_HISTOGRAM_SCROLL_LATENCY_LONG_2(
"Event.Latency." + scroll_name + "." + input_modality +
diff --git a/chromium/ui/latency/mojo/BUILD.gn b/chromium/ui/latency/mojo/BUILD.gn
index e8e2ba300ca..17c27b18f64 100644
--- a/chromium/ui/latency/mojo/BUILD.gn
+++ b/chromium/ui/latency/mojo/BUILD.gn
@@ -11,7 +11,6 @@ mojom("interfaces") {
public_deps = [
"//mojo/public/mojom/base",
- "//ui/gfx/geometry/mojo",
]
}
diff --git a/chromium/ui/latency/mojo/DEPS b/chromium/ui/latency/mojo/DEPS
index 77a276283fe..733587edbfe 100644
--- a/chromium/ui/latency/mojo/DEPS
+++ b/chromium/ui/latency/mojo/DEPS
@@ -1,5 +1,4 @@
include_rules = [
"+mojo/public",
- "+ui/gfx/geometry/mojo",
"+ui/latency",
]
diff --git a/chromium/ui/latency/mojo/latency_info.mojom b/chromium/ui/latency/mojo/latency_info.mojom
index a39a8ed7a3c..ee082c716b5 100644
--- a/chromium/ui/latency/mojo/latency_info.mojom
+++ b/chromium/ui/latency/mojo/latency_info.mojom
@@ -5,7 +5,6 @@
module ui.mojom;
import "mojo/public/mojom/base/time.mojom";
-import "ui/gfx/geometry/mojo/geometry.mojom";
enum LatencyComponentType {
// ---------------------------BEGIN COMPONENT-------------------------------
diff --git a/chromium/ui/latency/mojo/latency_info.typemap b/chromium/ui/latency/mojo/latency_info.typemap
index 53c9bf68ed7..4450bfe7530 100644
--- a/chromium/ui/latency/mojo/latency_info.typemap
+++ b/chromium/ui/latency/mojo/latency_info.typemap
@@ -13,7 +13,6 @@ sources = [
"latency_info_struct_traits.h",
]
public_deps = [
- "//ui/gfx/geometry/mojo:struct_traits",
"//ui/latency",
]
deps = [
diff --git a/chromium/ui/latency/mojo/latency_info_struct_traits.h b/chromium/ui/latency/mojo/latency_info_struct_traits.h
index e668e4dbca1..00ab6f2069f 100644
--- a/chromium/ui/latency/mojo/latency_info_struct_traits.h
+++ b/chromium/ui/latency/mojo/latency_info_struct_traits.h
@@ -5,7 +5,6 @@
#ifndef UI_LATENCY_MOJO_LATENCY_INFO_STRUCT_TRAITS_H_
#define UI_LATENCY_MOJO_LATENCY_INFO_STRUCT_TRAITS_H_
-#include "ui/gfx/geometry/mojo/geometry_struct_traits.h"
#include "ui/latency/latency_info.h"
#include "ui/latency/mojo/latency_info.mojom-shared.h"
diff --git a/chromium/ui/latency/stream_analyzer.cc b/chromium/ui/latency/stream_analyzer.cc
index 0453e27570f..2623e46adf0 100644
--- a/chromium/ui/latency/stream_analyzer.cc
+++ b/chromium/ui/latency/stream_analyzer.cc
@@ -4,6 +4,8 @@
#include "ui/latency/stream_analyzer.h"
+#include "ui/latency/frame_metrics.h"
+
namespace ui {
StreamAnalysis::StreamAnalysis() = default;
@@ -89,8 +91,9 @@ void StreamAnalyzer::AddSample(const uint32_t value, const uint32_t weight) {
DCHECK_GT(weight, 0u);
const uint64_t weighted_value = static_cast<uint64_t>(weight) * value;
- const uint64_t weighted_root = weight * std::sqrt(static_cast<double>(value) *
- kFixedPointRootMultiplier);
+ const uint64_t weighted_root =
+ weight * FrameMetrics::FastApproximateSqrt(static_cast<double>(value) *
+ kFixedPointRootMultiplier);
const Accumulator96b weighted_square(value, weight);
// Verify overflow isn't an issue.
@@ -128,7 +131,7 @@ double StreamAnalyzer::ComputeMean() const {
double StreamAnalyzer::ComputeRMS() const {
double mean_square = square_accumulator_.ToDouble() / total_weight_;
- double result = std::sqrt(mean_square);
+ double result = FrameMetrics::FastApproximateSqrt(mean_square);
return client_->TransformResult(result);
}
@@ -152,7 +155,7 @@ double StreamAnalyzer::VarianceHelper(double accum, double square_accum) const {
double StreamAnalyzer::ComputeStdDev() const {
double variance =
VarianceHelper(accumulator_, square_accumulator_.ToDouble());
- double std_dev = std::sqrt(variance);
+ double std_dev = FrameMetrics::FrameMetrics::FastApproximateSqrt(variance);
return client_->TransformResult(std_dev);
}
diff --git a/chromium/ui/latency/stream_analyzer_unittest.cc b/chromium/ui/latency/stream_analyzer_unittest.cc
index 08410961907..5aca77c7610 100644
--- a/chromium/ui/latency/stream_analyzer_unittest.cc
+++ b/chromium/ui/latency/stream_analyzer_unittest.cc
@@ -44,6 +44,7 @@ class StreamAnalyzerTest : public testing::Test {
};
TEST_F(StreamAnalyzerTest, AllResultsTheSame) {
+ const double approx_sqrt_error = 0.0001;
// Try adding a single sample vs. multiple samples.
for (size_t samples : {1u, 100u}) {
// A power of 2 sweep for both the value and weight dimensions.
@@ -57,17 +58,18 @@ TEST_F(StreamAnalyzerTest, AllResultsTheSame) {
uint64_t expected_value =
value * TestStreamAnalyzerClient::result_scale;
EXPECT_EQ(expected_value, analyzer_->ComputeMean());
- EXPECT_EQ(expected_value, analyzer_->ComputeRMS());
- EXPECT_NEAR_SMR(analyzer_->ComputeSMR(), expected_value, weight);
- EXPECT_DOUBLE_EQ(0, analyzer_->ComputeStdDev());
- EXPECT_NEAR_VARIANCE_OF_ROOT(0, analyzer_->ComputeVarianceOfRoots(),
- expected_value, weight);
+ EXPECT_NEAR_SQRT_APPROX(expected_value, analyzer_->ComputeRMS());
+ EXPECT_NEAR_SQRT_APPROX(analyzer_->ComputeSMR(), expected_value);
+ EXPECT_NEAR_SQRT_APPROX(0, analyzer_->ComputeStdDev());
+ EXPECT_NEAR(0, analyzer_->ComputeVarianceOfRoots(),
+ approx_sqrt_error * value);
// Verify values are forwarded to the WindowedAnalyzer.
EXPECT_EQ(expected_value, analyzer_->window().ComputeWorstMean().value);
- EXPECT_EQ(expected_value, analyzer_->window().ComputeWorstRMS().value);
- EXPECT_NEAR_SMR(expected_value,
- analyzer_->window().ComputeWorstSMR().value, weight);
+ EXPECT_NEAR_SQRT_APPROX(expected_value,
+ analyzer_->window().ComputeWorstRMS().value);
+ EXPECT_NEAR_SQRT_APPROX(expected_value,
+ analyzer_->window().ComputeWorstSMR().value);
}
}
}
@@ -83,17 +85,18 @@ TEST_F(StreamAnalyzerTest, AllResultsTheSame) {
uint64_t expected_value = value * TestStreamAnalyzerClient::result_scale;
// Makes sure our precision is good enough.
EXPECT_EQ(expected_value, analyzer_->ComputeMean());
- EXPECT_EQ(expected_value, analyzer_->ComputeRMS());
- EXPECT_NEAR_SMR(expected_value, analyzer_->ComputeSMR(), weight);
- EXPECT_DOUBLE_EQ(0, analyzer_->ComputeStdDev());
- EXPECT_NEAR_VARIANCE_OF_ROOT(0, analyzer_->ComputeVarianceOfRoots(),
- expected_value, weight);
+ EXPECT_NEAR_SQRT_APPROX(expected_value, analyzer_->ComputeRMS());
+ EXPECT_NEAR_SQRT_APPROX(expected_value, analyzer_->ComputeSMR());
+ EXPECT_NEAR_SQRT_APPROX(0, analyzer_->ComputeStdDev());
+ EXPECT_NEAR(0, analyzer_->ComputeVarianceOfRoots(),
+ approx_sqrt_error * value);
// Verify values are forwarded to the WindowedAnalyzer.
EXPECT_EQ(expected_value, analyzer_->window().ComputeWorstMean().value);
- EXPECT_EQ(expected_value, analyzer_->window().ComputeWorstRMS().value);
- EXPECT_NEAR_SMR(expected_value,
- analyzer_->window().ComputeWorstSMR().value, weight);
+ EXPECT_NEAR_SQRT_APPROX(expected_value,
+ analyzer_->window().ComputeWorstRMS().value);
+ EXPECT_NEAR_SQRT_APPROX(expected_value,
+ analyzer_->window().ComputeWorstSMR().value);
}
}
}
@@ -133,11 +136,12 @@ TEST_F(StreamAnalyzerTest, AllResultsDifferent) {
for (size_t i = 0; i < 1000; i++) {
AddPatternHelper(&shared_client_, analyzer(), pattern49, kSampleWeight);
EXPECT_DOUBLE_EQ(expected_mean, analyzer_->ComputeMean());
- EXPECT_NEAR_SMR(expected_smr, analyzer_->ComputeSMR(), kSampleWeight);
- EXPECT_DOUBLE_EQ(expected_rms, analyzer_->ComputeRMS());
- EXPECT_DOUBLE_EQ(expected_std_dev, analyzer_->ComputeStdDev());
- EXPECT_DOUBLE_EQ(expected_variance_of_roots,
- analyzer_->ComputeVarianceOfRoots());
+ // since each value creates a difference of 0.001, the result should
+ EXPECT_NEAR_SQRT_APPROX(expected_smr, analyzer_->ComputeSMR());
+ EXPECT_NEAR_SQRT_APPROX(expected_rms, analyzer_->ComputeRMS());
+ EXPECT_NEAR_SQRT_APPROX(expected_std_dev, analyzer_->ComputeStdDev());
+ EXPECT_NEAR_SQRT_APPROX(expected_variance_of_roots,
+ analyzer_->ComputeVarianceOfRoots());
}
thresholds = analyzer_->ComputeThresholds();
ASSERT_EQ(3u, thresholds.size());
@@ -158,11 +162,11 @@ TEST_F(StreamAnalyzerTest, AllResultsDifferent) {
}
thresholds = analyzer_->ComputeThresholds();
EXPECT_DOUBLE_EQ(expected_mean, analyzer_->ComputeMean());
- EXPECT_NEAR_SMR(expected_smr, analyzer_->ComputeSMR(), kSampleWeight);
- EXPECT_DOUBLE_EQ(expected_rms, analyzer_->ComputeRMS());
- EXPECT_DOUBLE_EQ(expected_std_dev, analyzer_->ComputeStdDev());
- EXPECT_DOUBLE_EQ(expected_variance_of_roots,
- analyzer_->ComputeVarianceOfRoots());
+ EXPECT_NEAR_SQRT_APPROX(expected_smr, analyzer_->ComputeSMR());
+ EXPECT_NEAR_SQRT_APPROX(expected_rms, analyzer_->ComputeRMS());
+ EXPECT_NEAR_SQRT_APPROX(expected_std_dev, analyzer_->ComputeStdDev());
+ EXPECT_NEAR_SQRT_APPROX(expected_variance_of_roots,
+ analyzer_->ComputeVarianceOfRoots());
EXPECT_EQ(client_.TransformResult(thresholds_[0]), thresholds[0].threshold);
EXPECT_EQ(client_.TransformResult(thresholds_[1]), thresholds[1].threshold);
EXPECT_EQ(client_.TransformResult(thresholds_[2]), thresholds[2].threshold);
@@ -180,11 +184,11 @@ TEST_F(StreamAnalyzerTest, AllResultsDifferent) {
}
thresholds = analyzer_->ComputeThresholds();
EXPECT_DOUBLE_EQ(expected_mean, analyzer_->ComputeMean());
- EXPECT_NEAR_SMR(expected_smr, analyzer_->ComputeSMR(), kSampleWeight);
- EXPECT_DOUBLE_EQ(expected_rms, analyzer_->ComputeRMS());
- EXPECT_DOUBLE_EQ(expected_std_dev, analyzer_->ComputeStdDev());
- EXPECT_DOUBLE_EQ(expected_variance_of_roots,
- analyzer_->ComputeVarianceOfRoots());
+ EXPECT_NEAR_SQRT_APPROX(expected_smr, analyzer_->ComputeSMR());
+ EXPECT_NEAR_SQRT_APPROX(expected_rms, analyzer_->ComputeRMS());
+ EXPECT_NEAR_SQRT_APPROX(expected_std_dev, analyzer_->ComputeStdDev());
+ EXPECT_NEAR_SQRT_APPROX(expected_variance_of_roots,
+ analyzer_->ComputeVarianceOfRoots());
EXPECT_EQ(client_.TransformResult(thresholds_[0]), thresholds[0].threshold);
EXPECT_EQ(client_.TransformResult(thresholds_[1]), thresholds[1].threshold);
EXPECT_EQ(client_.TransformResult(thresholds_[2]), thresholds[2].threshold);
@@ -295,7 +299,7 @@ TEST_F(StreamAnalyzerTest, Precision) {
double expected_rms = client_.TransformResult(std::sqrt(mean_square));
EXPECT_ABS_LT(expected_rms * .001,
expected_rms - naive_analyzer.ComputeRMS());
- EXPECT_DOUBLE_EQ(expected_rms, analyzer_->ComputeRMS());
+ EXPECT_NEAR_SQRT_APPROX(expected_rms, analyzer_->ComputeRMS());
double large_value_root = std::sqrt(large_value_f) * large_weight;
double small_value_root = std::sqrt(small_value_f) * small_weight;
@@ -304,7 +308,7 @@ TEST_F(StreamAnalyzerTest, Precision) {
double expected_smr = client_.TransformResult(mean_root * mean_root);
EXPECT_ABS_LT(expected_smr * .001,
expected_smr - naive_analyzer.ComputeSMR());
- EXPECT_NEAR_SMR(expected_smr, analyzer_->ComputeSMR(), 1);
+ EXPECT_NEAR_SQRT_APPROX(expected_smr, analyzer_->ComputeSMR());
}
} // namespace
diff --git a/chromium/ui/latency/windowed_analyzer.cc b/chromium/ui/latency/windowed_analyzer.cc
index a78d003532c..cd718d87a4d 100644
--- a/chromium/ui/latency/windowed_analyzer.cc
+++ b/chromium/ui/latency/windowed_analyzer.cc
@@ -4,6 +4,8 @@
#include "ui/latency/windowed_analyzer.h"
+#include "ui/latency/frame_metrics.h"
+
namespace ui {
void FrameRegionResult::AsValueInto(
@@ -57,9 +59,10 @@ void WindowedAnalyzer::AddSample(uint32_t value,
accumulator_ -= static_cast<uint64_t>(old_weight) * old_value;
// Casting the whole rhs is important to ensure rounding happens at a place
// equivalent to when it was added.
- root_accumulator_ -= static_cast<uint64_t>(
- old_weight *
- std::sqrt(static_cast<uint64_t>(old_value) << kFixedPointRootShift));
+ root_accumulator_ -=
+ static_cast<uint64_t>(old_weight * FrameMetrics::FastApproximateSqrt(
+ static_cast<uint64_t>(old_value)
+ << kFixedPointRootShift));
square_accumulator_.Subtract(Accumulator96b(old_value, old_weight));
}
@@ -107,7 +110,8 @@ FrameRegionResult WindowedAnalyzer::ComputeWorstRMS() const {
} else {
UpdateWorst(square_accumulator_, &result, true);
}
- result.value = client_->TransformResult(std::sqrt(result.value));
+ result.value =
+ client_->TransformResult(FrameMetrics::FastApproximateSqrt(result.value));
return result;
}
diff --git a/chromium/ui/latency/windowed_analyzer_unittest.cc b/chromium/ui/latency/windowed_analyzer_unittest.cc
index 71b42480548..5aa05034910 100644
--- a/chromium/ui/latency/windowed_analyzer_unittest.cc
+++ b/chromium/ui/latency/windowed_analyzer_unittest.cc
@@ -6,6 +6,7 @@
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/latency/fixed_point.h"
#include "ui/latency/frame_metrics_test_common.h"
namespace ui {
@@ -35,10 +36,11 @@ TEST(FrameMetricsWindowedAnalyzerTest, AllResultsTheSame) {
value * TestWindowedAnalyzerClient::result_scale;
EXPECT_EQ(analyzer.ComputeWorstMean().value, expected_value)
<< value << " x " << weight;
- EXPECT_EQ(analyzer.ComputeWorstRMS().value, expected_value)
+ EXPECT_NEAR_SQRT_APPROX(analyzer.ComputeWorstRMS().value,
+ expected_value)
<< value << " x " << weight;
- EXPECT_NEAR_SMR(analyzer.ComputeWorstSMR().value, expected_value,
- weight)
+ EXPECT_NEAR_SQRT_APPROX(analyzer.ComputeWorstSMR().value,
+ expected_value)
<< value << " x " << weight;
}
}
@@ -57,9 +59,9 @@ TEST(FrameMetricsWindowedAnalyzerTest, AllResultsTheSame) {
// Makes sure our precision is good enough.
EXPECT_EQ(analyzer.ComputeWorstMean().value, expected_value)
<< value << " x " << weight;
- EXPECT_EQ(analyzer.ComputeWorstRMS().value, expected_value)
+ EXPECT_NEAR_SQRT_APPROX(analyzer.ComputeWorstRMS().value, expected_value)
<< value << " x " << weight;
- EXPECT_NEAR_SMR(analyzer.ComputeWorstSMR().value, expected_value, weight)
+ EXPECT_NEAR_SQRT_APPROX(analyzer.ComputeWorstSMR().value, expected_value)
<< value << " x " << weight;
}
}
@@ -125,12 +127,12 @@ TEST(FrameMetricsWindowedAnalyzerTest, AllResultsDifferent) {
EXPECT_EQ(worst_mean_client.window_end, worst_mean.window_end);
FrameRegionResult worst_smr = analyzer.ComputeWorstSMR();
- EXPECT_NEAR_SMR(expected_worst_smr, worst_smr.value, kSampleWeight);
+ EXPECT_NEAR_SQRT_APPROX(expected_worst_smr, worst_smr.value);
EXPECT_EQ(worst_smr_client.window_begin, worst_smr.window_begin);
EXPECT_EQ(worst_smr_client.window_end, worst_smr.window_end);
FrameRegionResult worst_rms = analyzer.ComputeWorstRMS();
- EXPECT_DOUBLE_EQ(expected_worst_rms, worst_rms.value);
+ EXPECT_NEAR_SQRT_APPROX(expected_worst_rms, worst_rms.value);
EXPECT_EQ(worst_rms_client.window_begin, worst_rms.window_begin);
EXPECT_EQ(worst_rms_client.window_end, worst_rms.window_end);
}
@@ -159,12 +161,12 @@ TEST(FrameMetricsWindowedAnalyzerTest, SmallSampleSize) {
EXPECT_EQ(short_client.window_end, worst_mean.window_end);
FrameRegionResult worst_smr = analyzer.ComputeWorstSMR();
- EXPECT_NEAR_SMR(expected_initial_value, worst_smr.value, kSampleWeight);
+ EXPECT_NEAR_SQRT_APPROX(expected_initial_value, worst_smr.value);
EXPECT_EQ(short_client.window_begin, worst_smr.window_begin);
EXPECT_EQ(short_client.window_end, worst_smr.window_end);
FrameRegionResult worst_rms = analyzer.ComputeWorstRMS();
- EXPECT_DOUBLE_EQ(expected_initial_value, worst_rms.value);
+ EXPECT_NEAR_SQRT_APPROX(expected_initial_value, worst_rms.value);
EXPECT_EQ(short_client.window_begin, worst_rms.window_begin);
EXPECT_EQ(short_client.window_end, worst_rms.window_end);
}
@@ -196,12 +198,12 @@ TEST(FrameMetricsWindowedAnalyzerTest, BadFirstSamples) {
EXPECT_EQ(short_client.window_end, worst_mean.window_end);
worst_smr = analyzer.ComputeWorstSMR();
- EXPECT_NEAR_SMR(expected_initial_value, worst_smr.value, kSampleWeight);
+ EXPECT_NEAR_SQRT_APPROX(expected_initial_value, worst_smr.value);
EXPECT_EQ(short_client.window_begin, worst_smr.window_begin);
EXPECT_EQ(short_client.window_end, worst_smr.window_end);
worst_rms = analyzer.ComputeWorstRMS();
- EXPECT_DOUBLE_EQ(expected_initial_value, worst_rms.value);
+ EXPECT_NEAR_SQRT_APPROX(expected_initial_value, worst_rms.value);
EXPECT_EQ(short_client.window_begin, worst_rms.window_begin);
EXPECT_EQ(short_client.window_end, worst_rms.window_end);
@@ -222,12 +224,12 @@ TEST(FrameMetricsWindowedAnalyzerTest, BadFirstSamples) {
EXPECT_EQ(long_client.window_end, worst_mean.window_end);
worst_smr = analyzer.ComputeWorstSMR();
- EXPECT_NEAR_SMR(expected_final_value, worst_smr.value, kSampleWeight);
+ EXPECT_NEAR_SQRT_APPROX(expected_final_value, worst_smr.value);
EXPECT_EQ(long_client.window_begin, worst_smr.window_begin);
EXPECT_EQ(long_client.window_end, worst_smr.window_end);
worst_rms = analyzer.ComputeWorstRMS();
- EXPECT_DOUBLE_EQ(expected_final_value, worst_rms.value);
+ EXPECT_NEAR_SQRT_APPROX(expected_final_value, worst_rms.value);
EXPECT_EQ(long_client.window_begin, worst_rms.window_begin);
EXPECT_EQ(long_client.window_end, worst_rms.window_end);
}
@@ -257,12 +259,12 @@ TEST(FrameMetricsWindowedAnalyzerTest, ResetWorstValues) {
EXPECT_EQ(initial_client.window_end, worst_mean.window_end);
worst_smr = analyzer.ComputeWorstSMR();
- EXPECT_NEAR_SMR(expected_initial_value, worst_smr.value, kSampleWeight);
+ EXPECT_NEAR_SQRT_APPROX(expected_initial_value, worst_smr.value);
EXPECT_EQ(initial_client.window_begin, worst_smr.window_begin);
EXPECT_EQ(initial_client.window_end, worst_smr.window_end);
worst_rms = analyzer.ComputeWorstRMS();
- EXPECT_DOUBLE_EQ(expected_initial_value, worst_rms.value);
+ EXPECT_NEAR_SQRT_APPROX(expected_initial_value, worst_rms.value);
EXPECT_EQ(initial_client.window_begin, worst_rms.window_begin);
EXPECT_EQ(initial_client.window_end, worst_rms.window_end);
@@ -277,12 +279,12 @@ TEST(FrameMetricsWindowedAnalyzerTest, ResetWorstValues) {
EXPECT_EQ(initial_client.window_end, worst_mean.window_end);
worst_smr = analyzer.ComputeWorstSMR();
- EXPECT_NEAR_SMR(expected_initial_value, worst_smr.value, kSampleWeight);
+ EXPECT_NEAR_SQRT_APPROX(expected_initial_value, worst_smr.value);
EXPECT_EQ(initial_client.window_begin, worst_smr.window_begin);
EXPECT_EQ(initial_client.window_end, worst_smr.window_end);
worst_rms = analyzer.ComputeWorstRMS();
- EXPECT_DOUBLE_EQ(expected_initial_value, worst_rms.value);
+ EXPECT_NEAR_SQRT_APPROX(expected_initial_value, worst_rms.value);
EXPECT_EQ(initial_client.window_begin, worst_rms.window_begin);
EXPECT_EQ(initial_client.window_end, worst_rms.window_end);
@@ -308,12 +310,12 @@ TEST(FrameMetricsWindowedAnalyzerTest, ResetWorstValues) {
EXPECT_EQ(final_client.window_end, worst_mean.window_end);
worst_smr = analyzer.ComputeWorstSMR();
- EXPECT_NEAR_SMR(expected_final_value, worst_smr.value, kSampleWeight);
+ EXPECT_NEAR_SQRT_APPROX(expected_final_value, worst_smr.value);
EXPECT_EQ(final_client.window_begin, worst_smr.window_begin);
EXPECT_EQ(final_client.window_end, worst_smr.window_end);
worst_rms = analyzer.ComputeWorstRMS();
- EXPECT_DOUBLE_EQ(expected_final_value, worst_rms.value);
+ EXPECT_NEAR_SQRT_APPROX(expected_final_value, worst_rms.value);
EXPECT_EQ(final_client.window_begin, worst_rms.window_begin);
EXPECT_EQ(final_client.window_end, worst_rms.window_end);
}
@@ -351,6 +353,22 @@ class WindowedAnalyzerNaive {
naive_total_weight_ += weight;
}
+ // Same as AddPatternHelper, but uses each value (+1) as its own weight.
+ // The "Cubed" name comes from the fact that the squared_accumulator
+ // for the RMS will effectively be a "cubed accumulator".
+ void AddCubedPatternHelper(SharedWindowedAnalyzerClient* shared_client,
+ const std::vector<uint32_t>& values) {
+ for (auto i : values) {
+ shared_client->window_begin += base::TimeDelta::FromMicroseconds(1);
+ shared_client->window_end += base::TimeDelta::FromMicroseconds(1);
+ uint64_t weighted_value = (i * (i + 1));
+ uint64_t updated_value = static_cast<uint64_t>(i);
+ uint64_t weighted_root = (i + 1) * std::sqrt(updated_value << 32);
+ Accumulator96b weighted_square(i, (i + 1));
+ AddSample(i, (i + 1), weighted_value, weighted_root, weighted_square);
+ }
+ }
+
struct Sample {
uint32_t value;
uint32_t weight;
@@ -412,8 +430,8 @@ void TestNoAccumulatedPrecisionError(uint32_t big_value,
double naive_root_accumulator_prev = 0;
double naive_square_accumulator_prev = 0;
for (size_t i = 1; i <= kRuns; i++) {
- AddCubedPatternHelper(&shared_client_naive, &analyzer_naive, pattern_bad);
- AddCubedPatternHelper(&shared_client_naive, &analyzer_naive, pattern_clear);
+ analyzer_naive.AddCubedPatternHelper(&shared_client_naive, pattern_bad);
+ analyzer_naive.AddCubedPatternHelper(&shared_client_naive, pattern_clear);
EXPECT_EQ(0, analyzer_naive.naive_accumulator_);
EXPECT_ABS_LT(naive_root_accumulator_prev,
analyzer_naive.naive_root_accumulator_);
@@ -427,15 +445,6 @@ void TestNoAccumulatedPrecisionError(uint32_t big_value,
analyzer_naive.naive_root_accumulator_);
EXPECT_ABS_LE(naive_square_error_floor * kRuns,
analyzer_naive.naive_square_accumulator_);
-
- // Verify actual implementation has no error.
- for (size_t i = 1; i <= kRuns; i++) {
- AddCubedPatternHelper(&shared_client_impl, &analyzer_impl, pattern_bad);
- AddCubedPatternHelper(&shared_client_impl, &analyzer_impl, pattern_clear);
- EXPECT_EQ(0, analyzer_impl.CurrentAccumulator());
- EXPECT_EQ(0, analyzer_impl.CurrentRootAccumulator());
- EXPECT_EQ(0, analyzer_impl.CurrentSquareAccumulator());
- }
}
// This is a synthetic example that is just outside the dynamic range of a
diff --git a/chromium/ui/login/account_picker/md_user_pod_template.html b/chromium/ui/login/account_picker/md_user_pod_template.html
index 29b2ade6b78..965870022f7 100644
--- a/chromium/ui/login/account_picker/md_user_pod_template.html
+++ b/chromium/ui/login/account_picker/md_user_pod_template.html
@@ -50,7 +50,8 @@
</div>
<if expr="chromeos">
<div class="pin-container pin-disabled pin-tag">
- <pin-keyboard enable-password hide-input></pin-keyboard>
+ <pin-keyboard enable-password hide-input enable-placeholder>
+ </pin-keyboard>
</div>
</if>
<div class="main-pane">
diff --git a/chromium/ui/login/account_picker/user_pod_template.html b/chromium/ui/login/account_picker/user_pod_template.html
index 9d233226952..367374fca85 100644
--- a/chromium/ui/login/account_picker/user_pod_template.html
+++ b/chromium/ui/login/account_picker/user_pod_template.html
@@ -34,7 +34,7 @@
</div>
<if expr="chromeos">
<div class="pin-container pin-disabled pin-tag">
- <pin-keyboard enable-password hide-input></pin-keyboard>
+ <pin-keyboard enable-password hide-input enable-placeholder></pin-keyboard>
</div>
</if>
<div class="main-pane">
diff --git a/chromium/ui/login/display_manager.js b/chromium/ui/login/display_manager.js
index 7a948a1565a..53ef9909a6b 100644
--- a/chromium/ui/login/display_manager.js
+++ b/chromium/ui/login/display_manager.js
@@ -25,8 +25,6 @@
/** @const */ var SCREEN_ERROR_MESSAGE = 'error-message';
/** @const */ var SCREEN_TPM_ERROR = 'tpm-error-message';
/** @const */ var SCREEN_PASSWORD_CHANGED = 'password-changed';
-/** @const */ var SCREEN_CREATE_SUPERVISED_USER_FLOW =
- 'supervised-user-creation';
/** @const */ var SCREEN_APP_LAUNCH_SPLASH = 'app-launch-splash';
/** @const */ var SCREEN_ARC_KIOSK_SPLASH = 'arc-kiosk-splash';
/** @const */ var SCREEN_CONFIRM_PASSWORD = 'confirm-password';
@@ -73,7 +71,7 @@
GAIA_SIGNIN: 1,
ACCOUNT_PICKER: 2,
WRONG_HWID_WARNING: 3,
- SUPERVISED_USER_CREATION_FLOW: 4,
+ DEPRECATED_SUPERVISED_USER_CREATION_FLOW: 4,
SAML_PASSWORD_CONFIRM: 5,
PASSWORD_CHANGED: 6,
ENROLLMENT: 7,
@@ -85,7 +83,6 @@
UNKNOWN: 'ui-state-unknown',
UPDATE: 'ui-state-update',
SIGNIN: 'ui-state-signin',
- SUPERVISED_USER_CREATION_FLOW: 'ui-state-supervised',
KIOSK_MODE: 'ui-state-kiosk-mode',
LOCAL_STATE_ERROR: 'ui-state-local-state-error',
AUTO_ENROLLMENT_ERROR: 'ui-state-auto-enrollment-error',
@@ -273,9 +270,9 @@ cr.define('cr.ui.login', function() {
/**
* Stored OOBE configuration for newly registered screens.
- * @type {dictionary}
+ * @type {!OobeTypes.OobeConfiguration}
*/
- oobe_configuration_: {},
+ oobe_configuration_: undefined,
/**
* Detects multi-tap gesture that invokes demo mode setup in OOBE.
@@ -415,7 +412,7 @@ cr.define('cr.ui.login', function() {
/**
* Returns current OOBE configuration.
- * @return {dictionary}
+ * @return {!OobeTypes.OobeConfiguration}
*/
getOobeConfiguration: function() {
return this.oobe_configuration_;
@@ -796,8 +793,8 @@ cr.define('cr.ui.login', function() {
$('header-sections').appendChild(header);
this.appendButtons_(el.buttons, screenId);
- if (el.updateOobeConfiguration)
- el.updateOobeConfiguration(oobe_configuration_);
+ if (el.updateOobeConfiguration && this.oobe_configuration_)
+ el.updateOobeConfiguration(this.oobe_configuration_);
},
/**
@@ -879,16 +876,16 @@ cr.define('cr.ui.login', function() {
/**
* Updates Oobe configuration for screens.
- * @param {dictionary} configuration OOBE configuration.
+ * @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);
}
- this.oobe_configuration_ = configuration;
},
/**
@@ -1263,13 +1260,6 @@ cr.define('cr.ui.login', function() {
};
/**
- * Shows dialog to create a supervised user.
- */
- DisplayManager.showSupervisedUserCreationScreen = function() {
- login.SupervisedUserCreationScreen.show();
- };
-
- /**
* Shows TPM error screen.
*/
DisplayManager.showTpmError = function() {
diff --git a/chromium/ui/message_center/BUILD.gn b/chromium/ui/message_center/BUILD.gn
index d165deb5c79..99243819620 100644
--- a/chromium/ui/message_center/BUILD.gn
+++ b/chromium/ui/message_center/BUILD.gn
@@ -144,8 +144,6 @@ jumbo_component("message_center") {
"views/popup_alignment_delegate.h",
"views/proportional_image_view.cc",
"views/proportional_image_view.h",
- "views/slidable_message_view.cc",
- "views/slidable_message_view.h",
"views/slide_out_controller.cc",
"views/slide_out_controller.h",
]
diff --git a/chromium/ui/message_center/message_center_impl.cc b/chromium/ui/message_center/message_center_impl.cc
index c6f7e14a82c..1c113d6d4e1 100644
--- a/chromium/ui/message_center/message_center_impl.cc
+++ b/chromium/ui/message_center/message_center_impl.cc
@@ -64,8 +64,7 @@ void MessageCenterImpl::AddNotificationBlocker(NotificationBlocker* blocker) {
void MessageCenterImpl::RemoveNotificationBlocker(
NotificationBlocker* blocker) {
DCHECK_CALLED_ON_VALID_THREAD(thread_checker_);
- std::vector<NotificationBlocker*>::iterator iter =
- std::find(blockers_.begin(), blockers_.end(), blocker);
+ auto iter = std::find(blockers_.begin(), blockers_.end(), blocker);
if (iter == blockers_.end())
return;
blocker->RemoveObserver(this);
diff --git a/chromium/ui/message_center/message_center_impl_unittest.cc b/chromium/ui/message_center/message_center_impl_unittest.cc
index 430c2ce1e48..6d85eb7ed32 100644
--- a/chromium/ui/message_center/message_center_impl_unittest.cc
+++ b/chromium/ui/message_center/message_center_impl_unittest.cc
@@ -291,8 +291,7 @@ class TotalNotificationBlocker : public PopupNotificationBlocker {
bool PopupNotificationsContain(
const NotificationList::PopupNotifications& popups,
const std::string& id) {
- for (NotificationList::PopupNotifications::const_iterator iter =
- popups.begin(); iter != popups.end(); ++iter) {
+ for (auto iter = popups.begin(); iter != popups.end(); ++iter) {
if ((*iter)->id() == id)
return true;
}
@@ -303,8 +302,7 @@ bool PopupNotificationsContain(
bool NotificationsContain(
const NotificationList::Notifications& notifications,
const std::string& id) {
- for (NotificationList::Notifications::const_iterator iter =
- notifications.begin(); iter != notifications.end(); ++iter) {
+ for (auto iter = notifications.begin(); iter != notifications.end(); ++iter) {
if ((*iter)->id() == id)
return true;
}
diff --git a/chromium/ui/message_center/message_center_stats_collector.cc b/chromium/ui/message_center/message_center_stats_collector.cc
index 076da87c8f7..4f3faa699ad 100644
--- a/chromium/ui/message_center/message_center_stats_collector.cc
+++ b/chromium/ui/message_center/message_center_stats_collector.cc
@@ -61,7 +61,7 @@ void MessageCenterStatsCollector::OnNotificationAdded(
const std::string& notification_id) {
stats_[notification_id] = NotificationStats(notification_id);
- StatsCollection::iterator iter = stats_.find(notification_id);
+ auto iter = stats_.find(notification_id);
DCHECK(iter != stats_.end());
stats_[notification_id].CollectAction(NOTIFICATION_ACTION_ADD);
@@ -70,7 +70,7 @@ void MessageCenterStatsCollector::OnNotificationAdded(
void MessageCenterStatsCollector::OnNotificationRemoved(
const std::string& notification_id,
bool by_user) {
- StatsCollection::iterator iter = stats_.find(notification_id);
+ auto iter = stats_.find(notification_id);
if (iter == stats_.end())
return;
NotificationStats& notification_stat = iter->second;
@@ -83,7 +83,7 @@ void MessageCenterStatsCollector::OnNotificationRemoved(
void MessageCenterStatsCollector::OnNotificationUpdated(
const std::string& notification_id) {
- StatsCollection::iterator iter = stats_.find(notification_id);
+ auto iter = stats_.find(notification_id);
if (iter == stats_.end())
return;
NotificationStats& notification_stat = iter->second;
@@ -95,7 +95,7 @@ void MessageCenterStatsCollector::OnNotificationClicked(
const std::string& notification_id,
const base::Optional<int>& button_index,
const base::Optional<base::string16>& reply) {
- StatsCollection::iterator iter = stats_.find(notification_id);
+ auto iter = stats_.find(notification_id);
if (iter == stats_.end())
return;
NotificationStats& notification_stat = iter->second;
@@ -112,7 +112,7 @@ void MessageCenterStatsCollector::OnNotificationSettingsClicked(bool handled) {
void MessageCenterStatsCollector::OnNotificationDisplayed(
const std::string& notification_id,
const DisplaySource source) {
- StatsCollection::iterator iter = stats_.find(notification_id);
+ auto iter = stats_.find(notification_id);
if (iter == stats_.end())
return;
NotificationStats& notification_stat = iter->second;
diff --git a/chromium/ui/message_center/notification_list_unittest.cc b/chromium/ui/message_center/notification_list_unittest.cc
index 227681ff283..71432f104a3 100644
--- a/chromium/ui/message_center/notification_list_unittest.cc
+++ b/chromium/ui/message_center/notification_list_unittest.cc
@@ -118,8 +118,7 @@ class NotificationListTest : public testing::Test {
bool IsInNotifications(const NotificationList::Notifications& notifications,
const std::string& id) {
- for (NotificationList::Notifications::const_iterator iter =
- notifications.begin(); iter != notifications.end(); ++iter) {
+ for (auto iter = notifications.begin(); iter != notifications.end(); ++iter) {
if ((*iter)->id() == id)
return true;
}
@@ -305,14 +304,12 @@ TEST_F(NotificationListTest, OldPopupShouldNotBeHidden) {
// one should come earlier in the popup list. It means, the last element
// of |popups| should be the firstly added one, and so on.
EXPECT_EQ(kMaxVisiblePopupNotifications, popups.size());
- NotificationList::PopupNotifications::const_reverse_iterator iter =
- popups.rbegin();
+ auto iter = popups.rbegin();
for (size_t i = 0; i < kMaxVisiblePopupNotifications; ++i, ++iter) {
EXPECT_EQ(ids[i], (*iter)->id()) << i;
}
- for (NotificationList::PopupNotifications::const_iterator iter =
- popups.begin(); iter != popups.end(); ++iter) {
+ for (auto iter = popups.begin(); iter != popups.end(); ++iter) {
notification_list_->MarkSinglePopupAsShown((*iter)->id(), false);
}
popups.clear();
@@ -346,8 +343,7 @@ TEST_F(NotificationListTest, Priority) {
NotificationList::Notifications notifications =
notification_list_->GetVisibleNotifications(blockers_);
- for (NotificationList::Notifications::const_iterator iter =
- notifications.begin(); iter != notifications.end(); ++iter) {
+ for (auto iter = notifications.begin(); iter != notifications.end(); ++iter) {
notification_list_->RemoveNotification((*iter)->id());
}
@@ -582,7 +578,7 @@ TEST_F(NotificationListTest, NotificationOrderAndPriority) {
// Popups: latest comes first.
NotificationList::PopupNotifications popups = GetPopups();
EXPECT_EQ(3u, popups.size());
- NotificationList::PopupNotifications::const_iterator iter = popups.begin();
+ auto iter = popups.begin();
EXPECT_EQ(default_id, (*iter)->id());
iter++;
EXPECT_EQ(high_id, (*iter)->id());
@@ -594,8 +590,7 @@ TEST_F(NotificationListTest, NotificationOrderAndPriority) {
const NotificationList::Notifications notifications =
notification_list_->GetVisibleNotifications(blockers_);
EXPECT_EQ(3u, notifications.size());
- NotificationList::Notifications::const_iterator iter =
- notifications.begin();
+ auto iter = notifications.begin();
EXPECT_EQ(max_id, (*iter)->id());
iter++;
EXPECT_EQ(high_id, (*iter)->id());
@@ -625,7 +620,7 @@ TEST_F(NotificationListTest, MarkSinglePopupAsShown) {
// The notifications in the NotificationCenter are unaffected by popups shown.
NotificationList::Notifications notifications =
notification_list_->GetVisibleNotifications(blockers_);
- NotificationList::Notifications::const_iterator iter = notifications.begin();
+ auto iter = notifications.begin();
EXPECT_EQ(id3, (*iter)->id());
iter++;
EXPECT_EQ(id2, (*iter)->id());
diff --git a/chromium/ui/message_center/popup_timers_controller.cc b/chromium/ui/message_center/popup_timers_controller.cc
index 359f1049129..0c5eeadf3fd 100644
--- a/chromium/ui/message_center/popup_timers_controller.cc
+++ b/chromium/ui/message_center/popup_timers_controller.cc
@@ -98,8 +98,7 @@ void PopupTimersController::OnNotificationUpdated(const std::string& id) {
return;
}
- NotificationList::PopupNotifications::const_iterator iter =
- popup_notifications.begin();
+ auto iter = popup_notifications.begin();
for (; iter != popup_notifications.end(); ++iter) {
if ((*iter)->id() == id)
break;
diff --git a/chromium/ui/message_center/public/cpp/features.cc b/chromium/ui/message_center/public/cpp/features.cc
index 220a51220b1..079e49bfdf5 100644
--- a/chromium/ui/message_center/public/cpp/features.cc
+++ b/chromium/ui/message_center/public/cpp/features.cc
@@ -15,7 +15,4 @@ const base::Feature kNewStyleNotifications {
#endif
};
-const base::Feature kNotificationSwipeControl{
- "NotificationSwipeControl", base::FEATURE_DISABLED_BY_DEFAULT};
-
} // namespace message_center
diff --git a/chromium/ui/message_center/public/cpp/features.h b/chromium/ui/message_center/public/cpp/features.h
index 14a3fc2a563..dadaddbb22e 100644
--- a/chromium/ui/message_center/public/cpp/features.h
+++ b/chromium/ui/message_center/public/cpp/features.h
@@ -14,10 +14,6 @@ namespace message_center {
// should be used.
MESSAGE_CENTER_PUBLIC_EXPORT extern const base::Feature kNewStyleNotifications;
-// Whether the swipe control on notifications should be enabled.
-MESSAGE_CENTER_PUBLIC_EXPORT extern const base::Feature
- kNotificationSwipeControl;
-
} // namespace message_center
#endif // UI_MESSAGE_CENTER_PUBLIC_CPP_FEATURES_H_
diff --git a/chromium/ui/message_center/views/message_popup_view.cc b/chromium/ui/message_center/views/message_popup_view.cc
index 877abffae71..ebae9ce9f20 100644
--- a/chromium/ui/message_center/views/message_popup_view.cc
+++ b/chromium/ui/message_center/views/message_popup_view.cc
@@ -31,7 +31,7 @@ namespace message_center {
MessagePopupView::MessagePopupView(const Notification& notification,
PopupAlignmentDelegate* alignment_delegate,
MessagePopupCollection* popup_collection)
- : message_view_(MessageViewFactory::Create(notification, true)),
+ : message_view_(MessageViewFactory::Create(notification)),
alignment_delegate_(alignment_delegate),
popup_collection_(popup_collection),
a11y_feedback_on_init_(
diff --git a/chromium/ui/message_center/views/message_view.cc b/chromium/ui/message_center/views/message_view.cc
index 46e73a822c1..a3782fe4bb0 100644
--- a/chromium/ui/message_center/views/message_view.cc
+++ b/chromium/ui/message_center/views/message_view.cc
@@ -6,10 +6,12 @@
#include "base/feature_list.h"
#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/simple_menu_model.h"
+#include "ui/compositor/paint_recorder.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/image/image_skia_operations.h"
@@ -29,13 +31,15 @@
#include "ui/views/focus/focus_manager.h"
#include "ui/views/widget/widget.h"
+#if defined(OS_WIN)
+#include "ui/base/win/shell.h"
+#endif
+
namespace message_center {
namespace {
-const SkColor kBorderColor = SkColorSetARGB(0x1F, 0x0, 0x0, 0x0);
-const int kShadowCornerRadius = 0;
-const int kShadowElevation = 2;
+constexpr SkColor kBorderColor = SkColorSetARGB(0x1F, 0x0, 0x0, 0x0);
// Creates a text for spoken feedback from the data contained in the
// notification.
@@ -55,8 +59,12 @@ base::string16 CreateAccessibleName(const Notification& notification) {
return base::JoinString(accessible_lines, base::ASCIIToUTF16("\n"));
}
-bool ShouldRoundMessageViewCorners() {
- return base::FeatureList::IsEnabled(message_center::kNewStyleNotifications);
+bool ShouldShowAeroShadowBorder() {
+#if defined(OS_WIN)
+ return ui::win::IsAeroGlassEnabled();
+#else
+ return false;
+#endif
}
} // namespace
@@ -72,22 +80,22 @@ MessageView::MessageView(const Notification& notification)
SetPaintToLayer();
layer()->SetFillsBoundsOpaquely(false);
- // Create the opaque background that's above the view's shadow.
- background_view_ = new views::View();
-
- // ChromeOS rounds the corners of the message view. TODO(estade): should we do
- // this for all platforms?
- if (ShouldRoundMessageViewCorners())
- UpdateCornerRadius(kNotificationCornerRadius, kNotificationCornerRadius);
- else
- UpdateCornerRadius(0, 0);
-
- AddChildView(background_view_);
-
focus_painter_ = views::Painter::CreateSolidFocusPainter(
kFocusBorderColor, gfx::Insets(0, 0, 1, 1));
UpdateWithNotification(notification);
+
+ UpdateCornerRadius(0, 0);
+
+ // If Aero is enabled, set shadow border.
+ if (ShouldShowAeroShadowBorder()) {
+ const auto& shadow = gfx::ShadowDetails::Get(2, 0);
+ gfx::Insets ninebox_insets = gfx::ShadowValue::GetBlurRegion(shadow.values);
+ SetBorder(views::CreateBorderPainter(
+ views::Painter::CreateImagePainter(shadow.ninebox_image,
+ ninebox_insets),
+ -gfx::ShadowValue::GetMargin(shadow.values)));
+ }
}
MessageView::~MessageView() {
@@ -111,23 +119,9 @@ void MessageView::SetIsNested() {
// Update enability since it might be changed by "is_nested" flag.
slide_out_controller_.set_slide_mode(CalculateSlideMode());
- if (ShouldRoundMessageViewCorners()) {
- SetBorder(views::CreateRoundedRectBorder(
- kNotificationBorderThickness, kNotificationCornerRadius, kBorderColor));
- } else {
- const auto& shadow =
- gfx::ShadowDetails::Get(kShadowElevation, kShadowCornerRadius);
- gfx::Insets ninebox_insets =
- gfx::ShadowValue::GetBlurRegion(shadow.values) +
- gfx::Insets(kShadowCornerRadius);
- SetBorder(views::CreateBorderPainter(
- views::Painter::CreateImagePainter(shadow.ninebox_image,
- ninebox_insets),
- -gfx::ShadowValue::GetMargin(shadow.values)));
- }
+ SetBorder(views::CreateRoundedRectBorder(
+ kNotificationBorderThickness, kNotificationCornerRadius, kBorderColor));
- if (!base::FeatureList::IsEnabled(message_center::kNotificationSwipeControl))
- return;
auto* control_buttons_view = GetControlButtonsView();
if (control_buttons_view) {
int control_button_count =
@@ -183,7 +177,7 @@ void MessageView::SetManuallyExpandedOrCollapsed(bool value) {
}
void MessageView::UpdateCornerRadius(int top_radius, int bottom_radius) {
- background_view_->SetBackground(views::CreateBackgroundFromPainter(
+ SetBackground(views::CreateBackgroundFromPainter(
std::make_unique<NotificationBackgroundPainter>(top_radius,
bottom_radius)));
SchedulePaint();
@@ -248,9 +242,23 @@ bool MessageView::OnKeyReleased(const ui::KeyEvent& event) {
return true;
}
+void MessageView::PaintChildren(const views::PaintInfo& paint_info) {
+ views::View::PaintChildren(paint_info);
+
+ // Paint focus ring on top of all the children.
+ ui::PaintRecorder recorder(paint_info.context(), size());
+ views::Painter::PaintFocusPainter(this, recorder.canvas(),
+ focus_painter_.get());
+}
+
void MessageView::OnPaint(gfx::Canvas* canvas) {
- views::View::OnPaint(canvas);
- views::Painter::PaintFocusPainter(this, canvas, focus_painter_.get());
+ if (ShouldShowAeroShadowBorder()) {
+ // If the border is shadow, paint border first.
+ OnPaintBorder(canvas);
+ OnPaintBackground(canvas);
+ } else {
+ views::View::OnPaint(canvas);
+ }
}
void MessageView::OnFocus() {
@@ -265,15 +273,6 @@ void MessageView::OnBlur() {
SchedulePaint();
}
-void MessageView::Layout() {
- views::View::Layout();
-
- gfx::Rect content_bounds = GetContentsBounds();
-
- // Background.
- background_view_->SetBoundsRect(content_bounds);
-}
-
const char* MessageView::GetClassName() const {
return kViewClassName;
}
@@ -409,8 +408,8 @@ void MessageView::OnSnoozeButtonPressed(const ui::Event& event) {
}
void MessageView::SetDrawBackgroundAsActive(bool active) {
- background_view_->background()->SetNativeControlColor(
- active ? kHoveredButtonBackgroundColor : kNotificationBackgroundColor);
+ background()->SetNativeControlColor(active ? kHoveredButtonBackgroundColor
+ : kNotificationBackgroundColor);
SchedulePaint();
}
diff --git a/chromium/ui/message_center/views/message_view.h b/chromium/ui/message_center/views/message_view.h
index 32d006b2217..49138c6780b 100644
--- a/chromium/ui/message_center/views/message_view.h
+++ b/chromium/ui/message_center/views/message_view.h
@@ -111,10 +111,10 @@ class MESSAGE_CENTER_EXPORT MessageView : public views::InkDropHostView,
void OnMouseReleased(const ui::MouseEvent& event) override;
bool OnKeyPressed(const ui::KeyEvent& event) override;
bool OnKeyReleased(const ui::KeyEvent& event) override;
+ void PaintChildren(const views::PaintInfo& paint_info) override;
void OnPaint(gfx::Canvas* canvas) override;
void OnFocus() override;
void OnBlur() override;
- void Layout() override;
void OnGestureEvent(ui::GestureEvent* event) override;
void RemovedFromWidget() override;
void AddedToWidget() override;
@@ -155,11 +155,9 @@ class MESSAGE_CENTER_EXPORT MessageView : public views::InkDropHostView,
virtual void UpdateControlButtonsVisibility() = 0;
- // Changes the background color being used by |background_view_| and schedules
- // a paint.
+ // Changes the background color and schedules a paint.
virtual void SetDrawBackgroundAsActive(bool active);
- views::View* background_view() { return background_view_; }
views::ScrollView* scroller() { return scroller_; }
bool is_nested() const { return is_nested_; }
@@ -171,7 +169,6 @@ class MESSAGE_CENTER_EXPORT MessageView : public views::InkDropHostView,
SlideOutController::SlideMode CalculateSlideMode() const;
std::string notification_id_;
- views::View* background_view_ = nullptr; // Owned by views hierarchy.
views::ScrollView* scroller_ = nullptr;
base::string16 accessible_name_;
diff --git a/chromium/ui/message_center/views/message_view_factory.cc b/chromium/ui/message_center/views/message_view_factory.cc
index 07ed14273ea..ce4ef494d27 100644
--- a/chromium/ui/message_center/views/message_view_factory.cc
+++ b/chromium/ui/message_center/views/message_view_factory.cc
@@ -12,10 +12,6 @@
#include "ui/message_center/views/notification_view.h"
#include "ui/message_center/views/notification_view_md.h"
-#if defined(OS_WIN)
-#include "ui/base/win/shell.h"
-#endif
-
namespace message_center {
namespace {
@@ -26,8 +22,7 @@ base::LazyInstance<MessageViewFactory::CustomMessageViewFactoryFunction>::Leaky
} // namespace
// static
-MessageView* MessageViewFactory::Create(const Notification& notification,
- bool top_level) {
+MessageView* MessageViewFactory::Create(const Notification& notification) {
MessageView* notification_view = nullptr;
switch (notification.type()) {
case NOTIFICATION_TYPE_BASE_FORMAT:
@@ -56,21 +51,6 @@ MessageView* MessageViewFactory::Create(const Notification& notification,
<< ". Falling back to simple notification type.";
notification_view = new NotificationView(notification);
}
-
-#if defined(OS_LINUX)
- // Don't create shadows for notification toasts on Linux or CrOS.
- if (top_level)
- return notification_view;
-#endif
-
-#if defined(OS_WIN)
- // Don't create shadows for notifications on Windows under classic theme.
- if (top_level && !ui::win::IsAeroGlassEnabled()) {
- return notification_view;
- }
-#endif // OS_WIN
-
- notification_view->SetIsNested();
return notification_view;
}
diff --git a/chromium/ui/message_center/views/message_view_factory.h b/chromium/ui/message_center/views/message_view_factory.h
index 883257ebff7..30c8520fdcd 100644
--- a/chromium/ui/message_center/views/message_view_factory.h
+++ b/chromium/ui/message_center/views/message_view_factory.h
@@ -27,7 +27,7 @@ class MESSAGE_CENTER_EXPORT MessageViewFactory {
typedef base::Callback<std::unique_ptr<MessageView>(const Notification&)>
CustomMessageViewFactoryFunction;
- static MessageView* Create(const Notification& notification, bool top_level);
+ static MessageView* Create(const Notification& notification);
// Sets the function that will be invoked to create a custom notification
// view. This should be a repeating callback. It's an error to attempt to show
diff --git a/chromium/ui/message_center/views/notification_background_painter.cc b/chromium/ui/message_center/views/notification_background_painter.cc
index 691d24933bd..1e33c6f30c0 100644
--- a/chromium/ui/message_center/views/notification_background_painter.cc
+++ b/chromium/ui/message_center/views/notification_background_painter.cc
@@ -9,14 +9,15 @@
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/skia_util.h"
-#include "ui/message_center/public/cpp/message_center_constants.h"
namespace message_center {
NotificationBackgroundPainter::NotificationBackgroundPainter(int top_radius,
- int bottom_radius)
+ int bottom_radius,
+ SkColor color)
: top_radius_(SkIntToScalar(top_radius)),
- bottom_radius_(SkIntToScalar(bottom_radius)) {}
+ bottom_radius_(SkIntToScalar(bottom_radius)),
+ color_(color) {}
NotificationBackgroundPainter::~NotificationBackgroundPainter() = default;
@@ -37,7 +38,7 @@ void NotificationBackgroundPainter::Paint(gfx::Canvas* canvas,
cc::PaintFlags flags;
flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kFill_Style);
- flags.setColor(kNotificationBackgroundColor);
+ flags.setColor(color_);
canvas->DrawPath(path, flags);
}
diff --git a/chromium/ui/message_center/views/notification_background_painter.h b/chromium/ui/message_center/views/notification_background_painter.h
index aba4f1d70bc..a31dd1ffec5 100644
--- a/chromium/ui/message_center/views/notification_background_painter.h
+++ b/chromium/ui/message_center/views/notification_background_painter.h
@@ -6,6 +6,7 @@
#define UI_MESSAGE_CENTER_VIEWS_NOTIFICATION_BACKGROUND_PAINTER_H_
#include "ui/message_center/message_center_export.h"
+#include "ui/message_center/public/cpp/message_center_constants.h"
#include "ui/views/painter.h"
namespace message_center {
@@ -16,12 +17,13 @@ namespace message_center {
class MESSAGE_CENTER_EXPORT NotificationBackgroundPainter
: public views::Painter {
public:
- NotificationBackgroundPainter(int top_radius, int bottom_radius);
+ NotificationBackgroundPainter(int top_radius,
+ int bottom_radius,
+ SkColor color = kNotificationBackgroundColor);
~NotificationBackgroundPainter() override;
// views::Painter
gfx::Size GetMinimumSize() const override;
-
void Paint(gfx::Canvas* canvas, const gfx::Size& size) override;
void set_insets(const gfx::Insets& insets) { insets_ = insets; }
@@ -29,6 +31,7 @@ class MESSAGE_CENTER_EXPORT NotificationBackgroundPainter
private:
const SkScalar top_radius_;
const SkScalar bottom_radius_;
+ const SkColor color_;
gfx::Insets insets_;
diff --git a/chromium/ui/message_center/views/notification_view_md.cc b/chromium/ui/message_center/views/notification_view_md.cc
index 3c6a29187d8..c27bfd96816 100644
--- a/chromium/ui/message_center/views/notification_view_md.cc
+++ b/chromium/ui/message_center/views/notification_view_md.cc
@@ -28,6 +28,7 @@
#include "ui/message_center/public/cpp/notification_types.h"
#include "ui/message_center/vector_icons.h"
#include "ui/message_center/views/bounded_label.h"
+#include "ui/message_center/views/notification_background_painter.h"
#include "ui/message_center/views/notification_control_buttons_view.h"
#include "ui/message_center/views/notification_header_view.h"
#include "ui/message_center/views/padded_button.h"
@@ -549,8 +550,6 @@ NotificationViewMD::NotificationViewMD(const Notification& notification)
action_buttons_row_->SetLayoutManager(std::make_unique<views::BoxLayout>(
views::BoxLayout::kHorizontal, kActionsRowPadding,
kActionsRowHorizontalSpacing));
- action_buttons_row_->SetBackground(
- views::CreateSolidBackground(kActionsRowBackgroundColor));
action_buttons_row_->SetVisible(false);
actions_row_->AddChildView(action_buttons_row_);
@@ -570,6 +569,8 @@ NotificationViewMD::NotificationViewMD(const Notification& notification)
// textfield click in native notification.
// - To make it look similar to ArcNotificationContentView::EventForwarder.
AddPreTargetHandler(click_activator_.get());
+
+ UpdateCornerRadius(kNotificationCornerRadius, kNotificationCornerRadius);
}
NotificationViewMD::~NotificationViewMD() {
@@ -1231,6 +1232,13 @@ void NotificationViewMD::UpdateControlButtonsVisibility() {
control_buttons_view_->SetVisible(target_visibility);
}
+void NotificationViewMD::UpdateCornerRadius(int top_radius, int bottom_radius) {
+ MessageView::UpdateCornerRadius(top_radius, bottom_radius);
+ action_buttons_row_->SetBackground(views::CreateBackgroundFromPainter(
+ std::make_unique<NotificationBackgroundPainter>(
+ 0, bottom_radius, kActionsRowBackgroundColor)));
+}
+
NotificationControlButtonsView* NotificationViewMD::GetControlButtonsView()
const {
return control_buttons_view_.get();
diff --git a/chromium/ui/message_center/views/notification_view_md.h b/chromium/ui/message_center/views/notification_view_md.h
index c51c1abe6ee..4ead77eeb3c 100644
--- a/chromium/ui/message_center/views/notification_view_md.h
+++ b/chromium/ui/message_center/views/notification_view_md.h
@@ -188,6 +188,7 @@ class MESSAGE_CENTER_EXPORT NotificationViewMD
void UpdateWithNotification(const Notification& notification) override;
void ButtonPressed(views::Button* sender, const ui::Event& event) override;
void UpdateControlButtonsVisibility() override;
+ void UpdateCornerRadius(int top_radius, int bottom_radius) override;
NotificationControlButtonsView* GetControlButtonsView() const override;
bool IsExpanded() const override;
void SetExpanded(bool expanded) override;
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 e30fac2465c..b39c64ce3b2 100644
--- a/chromium/ui/message_center/views/notification_view_md_unittest.cc
+++ b/chromium/ui/message_center/views/notification_view_md_unittest.cc
@@ -130,7 +130,7 @@ class NotificationViewMDTest
void UpdateNotificationViews(const Notification& notification);
float GetNotificationSlideAmount() const;
- bool IsRemoved(const std::string& notification_id) const;
+ bool IsRemovedAfterIdle(const std::string& notification_id) const;
void DispatchGesture(const ui::GestureEventDetails& details);
void BeginScroll();
void EndScroll();
@@ -284,8 +284,9 @@ float NotificationViewMDTest::GetNotificationSlideAmount() const {
.x();
}
-bool NotificationViewMDTest::IsRemoved(
+bool NotificationViewMDTest::IsRemovedAfterIdle(
const std::string& notification_id) const {
+ base::RunLoop().RunUntilIdle();
return !MessageCenter::Get()->FindVisibleNotificationById(notification_id);
}
@@ -591,22 +592,22 @@ TEST_F(NotificationViewMDTest, SlideOut) {
ui::ScopedAnimationDurationScaleMode zero_duration_scope(
ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
- EXPECT_FALSE(IsRemoved(kDefaultNotificationId));
+ EXPECT_FALSE(IsRemovedAfterIdle(kDefaultNotificationId));
BeginScroll();
ScrollBy(-10);
- EXPECT_FALSE(IsRemoved(kDefaultNotificationId));
+ EXPECT_FALSE(IsRemovedAfterIdle(kDefaultNotificationId));
EXPECT_EQ(-10.f, GetNotificationSlideAmount());
EndScroll();
- EXPECT_FALSE(IsRemoved(kDefaultNotificationId));
+ EXPECT_FALSE(IsRemovedAfterIdle(kDefaultNotificationId));
EXPECT_EQ(0.f, GetNotificationSlideAmount());
BeginScroll();
ScrollBy(-200);
- EXPECT_FALSE(IsRemoved(kDefaultNotificationId));
+ EXPECT_FALSE(IsRemovedAfterIdle(kDefaultNotificationId));
EXPECT_EQ(-200.f, GetNotificationSlideAmount());
EndScroll();
- EXPECT_TRUE(IsRemoved(kDefaultNotificationId));
+ EXPECT_TRUE(IsRemovedAfterIdle(kDefaultNotificationId));
}
TEST_F(NotificationViewMDTest, SlideOutNested) {
@@ -615,18 +616,18 @@ TEST_F(NotificationViewMDTest, SlideOutNested) {
BeginScroll();
ScrollBy(-10);
- EXPECT_FALSE(IsRemoved(kDefaultNotificationId));
+ EXPECT_FALSE(IsRemovedAfterIdle(kDefaultNotificationId));
EXPECT_EQ(-10.f, GetNotificationSlideAmount());
EndScroll();
- EXPECT_FALSE(IsRemoved(kDefaultNotificationId));
+ EXPECT_FALSE(IsRemovedAfterIdle(kDefaultNotificationId));
EXPECT_EQ(0.f, GetNotificationSlideAmount());
BeginScroll();
ScrollBy(-200);
- EXPECT_FALSE(IsRemoved(kDefaultNotificationId));
+ EXPECT_FALSE(IsRemovedAfterIdle(kDefaultNotificationId));
EXPECT_EQ(-200.f, GetNotificationSlideAmount());
EndScroll();
- EXPECT_TRUE(IsRemoved(kDefaultNotificationId));
+ EXPECT_TRUE(IsRemovedAfterIdle(kDefaultNotificationId));
}
TEST_F(NotificationViewMDTest, DisableSlideForcibly) {
@@ -637,20 +638,20 @@ TEST_F(NotificationViewMDTest, DisableSlideForcibly) {
BeginScroll();
ScrollBy(-10);
- EXPECT_FALSE(IsRemoved(kDefaultNotificationId));
+ EXPECT_FALSE(IsRemovedAfterIdle(kDefaultNotificationId));
EXPECT_EQ(0.f, GetNotificationSlideAmount());
EndScroll();
- EXPECT_FALSE(IsRemoved(kDefaultNotificationId));
+ EXPECT_FALSE(IsRemovedAfterIdle(kDefaultNotificationId));
EXPECT_EQ(0.f, GetNotificationSlideAmount());
notification_view()->DisableSlideForcibly(false);
BeginScroll();
ScrollBy(-10);
- EXPECT_FALSE(IsRemoved(kDefaultNotificationId));
+ EXPECT_FALSE(IsRemovedAfterIdle(kDefaultNotificationId));
EXPECT_EQ(-10.f, GetNotificationSlideAmount());
EndScroll();
- EXPECT_FALSE(IsRemoved(kDefaultNotificationId));
+ EXPECT_FALSE(IsRemovedAfterIdle(kDefaultNotificationId));
}
// Pinning notification is ChromeOS only feature.
@@ -666,10 +667,10 @@ TEST_F(NotificationViewMDTest, SlideOutPinned) {
BeginScroll();
ScrollBy(-200);
- EXPECT_FALSE(IsRemoved(kDefaultNotificationId));
+ EXPECT_FALSE(IsRemovedAfterIdle(kDefaultNotificationId));
EXPECT_LT(-200.f, GetNotificationSlideAmount());
EndScroll();
- EXPECT_FALSE(IsRemoved(kDefaultNotificationId));
+ EXPECT_FALSE(IsRemovedAfterIdle(kDefaultNotificationId));
}
TEST_F(NotificationViewMDTest, Pinned) {
@@ -707,10 +708,10 @@ TEST_F(NotificationViewMDTest, FixedViewMode) {
BeginScroll();
ScrollBy(-200);
- EXPECT_FALSE(IsRemoved(notification_id));
+ EXPECT_FALSE(IsRemovedAfterIdle(notification_id));
EXPECT_EQ(0.f, GetNotificationSlideAmount());
EndScroll();
- EXPECT_FALSE(IsRemoved(notification_id));
+ EXPECT_FALSE(IsRemovedAfterIdle(notification_id));
EXPECT_EQ(MessageView::Mode::SETTING, notification_view()->GetMode());
}
diff --git a/chromium/ui/message_center/views/notification_view_unittest.cc b/chromium/ui/message_center/views/notification_view_unittest.cc
index 8a5890a165a..b79aae0c2c0 100644
--- a/chromium/ui/message_center/views/notification_view_unittest.cc
+++ b/chromium/ui/message_center/views/notification_view_unittest.cc
@@ -128,8 +128,8 @@ class NotificationViewTest : public views::ViewsTestBase {
std::copy(notification_view()->action_buttons_.begin(),
notification_view()->action_buttons_.end(),
std::back_inserter(vertical_order));
- std::vector<views::View*>::iterator current = vertical_order.begin();
- std::vector<views::View*>::iterator last = current++;
+ auto current = vertical_order.begin();
+ auto last = current++;
while (current != vertical_order.end()) {
gfx::Point last_point = (*last)->origin();
views::View::ConvertPointToTarget(
@@ -165,7 +165,8 @@ class NotificationViewTest : public views::ViewsTestBase {
.x();
}
- bool IsRemoved(const std::string& notification_id) const {
+ bool IsRemovedAfterIdle(const std::string& notification_id) const {
+ base::RunLoop().RunUntilIdle();
return !MessageCenter::Get()->FindVisibleNotificationById(notification_id);
}
@@ -625,18 +626,18 @@ TEST_F(NotificationViewTest, SlideOut) {
BeginScroll();
ScrollBy(-10);
- EXPECT_FALSE(IsRemoved(notification_id));
+ EXPECT_FALSE(IsRemovedAfterIdle(notification_id));
EXPECT_EQ(-10.f, GetNotificationSlideAmount());
EndScroll();
- EXPECT_FALSE(IsRemoved(notification_id));
+ EXPECT_FALSE(IsRemovedAfterIdle(notification_id));
EXPECT_EQ(0.f, GetNotificationSlideAmount());
BeginScroll();
ScrollBy(-200);
- EXPECT_FALSE(IsRemoved(notification_id));
+ EXPECT_FALSE(IsRemovedAfterIdle(notification_id));
EXPECT_EQ(-200.f, GetNotificationSlideAmount());
EndScroll();
- EXPECT_TRUE(IsRemoved(notification_id));
+ EXPECT_TRUE(IsRemovedAfterIdle(notification_id));
}
TEST_F(NotificationViewTest, SlideOutNested) {
@@ -648,18 +649,18 @@ TEST_F(NotificationViewTest, SlideOutNested) {
BeginScroll();
ScrollBy(-10);
- EXPECT_FALSE(IsRemoved(notification_id));
+ EXPECT_FALSE(IsRemovedAfterIdle(notification_id));
EXPECT_EQ(-10.f, GetNotificationSlideAmount());
EndScroll();
- EXPECT_FALSE(IsRemoved(notification_id));
+ EXPECT_FALSE(IsRemovedAfterIdle(notification_id));
EXPECT_EQ(0.f, GetNotificationSlideAmount());
BeginScroll();
ScrollBy(-200);
- EXPECT_FALSE(IsRemoved(notification_id));
+ EXPECT_FALSE(IsRemovedAfterIdle(notification_id));
EXPECT_EQ(-200.f, GetNotificationSlideAmount());
EndScroll();
- EXPECT_TRUE(IsRemoved(notification_id));
+ EXPECT_TRUE(IsRemovedAfterIdle(notification_id));
}
// Pinning notification is ChromeOS only feature.
@@ -676,10 +677,10 @@ TEST_F(NotificationViewTest, SlideOutPinned) {
BeginScroll();
ScrollBy(-200);
- EXPECT_FALSE(IsRemoved(notification_id));
+ EXPECT_FALSE(IsRemovedAfterIdle(notification_id));
EXPECT_LT(-200.f, GetNotificationSlideAmount());
EndScroll();
- EXPECT_FALSE(IsRemoved(notification_id));
+ EXPECT_FALSE(IsRemovedAfterIdle(notification_id));
}
TEST_F(NotificationViewTest, PopupsCantPin) {
@@ -701,11 +702,11 @@ TEST_F(NotificationViewTest, PopupsCantPin) {
BeginScroll();
ScrollBy(-200);
- EXPECT_FALSE(IsRemoved(notification_id));
+ EXPECT_FALSE(IsRemovedAfterIdle(notification_id));
EXPECT_TRUE(shown_as_popup(notification_id));
EXPECT_EQ(-200.f, GetNotificationSlideAmount());
EndScroll();
- EXPECT_FALSE(IsRemoved(notification_id));
+ EXPECT_FALSE(IsRemovedAfterIdle(notification_id));
EXPECT_FALSE(shown_as_popup(notification_id));
}
diff --git a/chromium/ui/message_center/views/slidable_message_view.cc b/chromium/ui/message_center/views/slidable_message_view.cc
deleted file mode 100644
index aef4f35bbef..00000000000
--- a/chromium/ui/message_center/views/slidable_message_view.cc
+++ /dev/null
@@ -1,67 +0,0 @@
-// Copyright (c) 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/message_center/views/slidable_message_view.h"
-
-#include "ui/message_center/public/cpp/features.h"
-#include "ui/message_center/public/cpp/message_center_constants.h"
-#include "ui/message_center/views/message_view.h"
-#include "ui/views/background.h"
-#include "ui/views/layout/fill_layout.h"
-#include "ui/views/view.h"
-
-namespace message_center {
-
-SlidableMessageView::SlidableMessageView(MessageView* message_view)
- : message_view_(message_view) {
- SetFocusBehavior(views::View::FocusBehavior::NEVER);
-
- // Draw on its own layer to allow bound animation.
- SetPaintToLayer();
- layer()->SetFillsBoundsOpaquely(false);
- if (base::FeatureList::IsEnabled(message_center::kNotificationSwipeControl))
- SetBackground(views::CreateSolidBackground(kSwipeControlBackgroundColor));
-
- SetLayoutManager(std::make_unique<views::FillLayout>());
-
- // TODO(crbug.com/840497): Add button container child view.
-
- message_view_->AddSlideObserver(this);
- AddChildView(message_view);
-}
-
-SlidableMessageView::~SlidableMessageView() = default;
-
-void SlidableMessageView::OnSlideChanged(const std::string& notification_id) {
- // TODO(crbug.com/840497): Show/hide control buttons.
-}
-
-void SlidableMessageView::CloseSwipeControl() {
- message_view_->CloseSwipeControl();
-}
-
-void SlidableMessageView::ChildPreferredSizeChanged(views::View* child) {
- PreferredSizeChanged();
- InvalidateLayout();
-}
-
-void SlidableMessageView::ChildVisibilityChanged(views::View* child) {
- PreferredSizeChanged();
- InvalidateLayout();
-}
-
-void SlidableMessageView::UpdateWithNotification(
- const Notification& notification) {
- message_view_->UpdateWithNotification(notification);
-}
-
-gfx::Size SlidableMessageView::CalculatePreferredSize() const {
- return message_view_->GetPreferredSize();
-}
-
-int SlidableMessageView::GetHeightForWidth(int width) const {
- return message_view_->GetHeightForWidth(width);
-}
-
-} // namespace message_center
diff --git a/chromium/ui/message_center/views/slidable_message_view.h b/chromium/ui/message_center/views/slidable_message_view.h
deleted file mode 100644
index 4811123a1c2..00000000000
--- a/chromium/ui/message_center/views/slidable_message_view.h
+++ /dev/null
@@ -1,74 +0,0 @@
-// Copyright (c) 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_MESSAGE_CENTER_VIEWS_SLIDABLE_MESSAGE_VIEW_H_
-#define UI_MESSAGE_CENTER_VIEWS_SLIDABLE_MESSAGE_VIEW_H_
-
-#include "ui/message_center/views/message_view.h"
-#include "ui/views/view.h"
-
-namespace message_center {
-
-class MESSAGE_CENTER_EXPORT SlidableMessageView
- : public views::View,
- public MessageView::SlideObserver {
- public:
- SlidableMessageView(message_center::MessageView* message_view);
- ~SlidableMessageView() override;
-
- MessageView* GetMessageView() const { return message_view_; }
-
- // MessageView::SlideObserver
- void OnSlideChanged(const std::string& notification_id) override;
-
- void SetExpanded(bool expanded) {
- return message_view_->SetExpanded(expanded);
- }
-
- bool IsExpanded() const { return message_view_->IsExpanded(); }
-
- bool IsAutoExpandingAllowed() const {
- return message_view_->IsAutoExpandingAllowed();
- }
-
- bool IsCloseButtonFocused() const {
- return message_view_->IsCloseButtonFocused();
- }
-
- bool IsManuallyExpandedOrCollapsed() const {
- return message_view_->IsManuallyExpandedOrCollapsed();
- }
-
- void SetManuallyExpandedOrCollapsed(bool value) {
- return message_view_->SetManuallyExpandedOrCollapsed(value);
- }
-
- // Updates this view with the new data contained in the notification.
- void UpdateWithNotification(const Notification& notification);
-
- std::string notification_id() const {
- return message_view_->notification_id();
- }
-
- MessageView::Mode GetMode() const { return message_view_->GetMode(); }
-
- void CloseSwipeControl();
-
- void StartDismissAnimation();
-
- // views::View
- void ChildPreferredSizeChanged(views::View* child) override;
- void ChildVisibilityChanged(views::View* child) override;
- gfx::Size CalculatePreferredSize() const override;
- int GetHeightForWidth(int width) const override;
-
- private:
- MessageView* message_view_;
- // TODO(crbug.com/840497): Add child view containing settings and snooze
- // buttons.
-};
-
-} // namespace message_center
-
-#endif // UI_MESSAGE_CENTER_VIEWS_SLIDABLE_MESSAGE_VIEW_H_
diff --git a/chromium/ui/message_center/views/slide_out_controller.cc b/chromium/ui/message_center/views/slide_out_controller.cc
index c42f6779713..f338931e7fc 100644
--- a/chromium/ui/message_center/views/slide_out_controller.cc
+++ b/chromium/ui/message_center/views/slide_out_controller.cc
@@ -160,7 +160,13 @@ void SlideOutController::SlideOutAndClose(int direction) {
void SlideOutController::OnImplicitAnimationsCompleted() {
delegate_->OnSlideChanged();
- delegate_->OnSlideOut();
+
+ // OnImplicitAnimationsCompleted is called from BeginMainFrame, so we should
+ // delay operation that might result in deletion of LayerTreeHost.
+ // https://crbug.com/895883
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE,
+ base::BindOnce(&Delegate::OnSlideOut, base::Unretained(delegate_)));
}
void SlideOutController::EnableSwipeControl(int button_count) {
diff --git a/chromium/ui/message_center/views/slide_out_controller.h b/chromium/ui/message_center/views/slide_out_controller.h
index 40c77b145f8..61048583093 100644
--- a/chromium/ui/message_center/views/slide_out_controller.h
+++ b/chromium/ui/message_center/views/slide_out_controller.h
@@ -53,6 +53,7 @@ class MESSAGE_CENTER_EXPORT SlideOutController
// Enables the swipe control. Buttons will appea behind the view as user
// slides it partially and it's kept open after the gesture.
void EnableSwipeControl(int button_count);
+ float GetGestureAmount() const { return gesture_amount_; }
// Moves slide back to the center position to closes the swipe control.
// Effective only when swipe control is enabled by EnableSwipeControl().
diff --git a/chromium/ui/native_theme/common_theme.cc b/chromium/ui/native_theme/common_theme.cc
index accf8288582..6b4f08797ba 100644
--- a/chromium/ui/native_theme/common_theme.cc
+++ b/chromium/ui/native_theme/common_theme.cc
@@ -24,18 +24,13 @@ SkColor GetAuraColor(NativeTheme::ColorId color_id,
switch (color_id) {
case NativeTheme::kColorId_ButtonEnabledColor:
case NativeTheme::kColorId_ButtonHoverColor:
- return SK_ColorBLACK;
case NativeTheme::kColorId_MenuBorderColor:
case NativeTheme::kColorId_MenuSeparatorColor:
- return SK_ColorBLACK;
case NativeTheme::kColorId_SeparatorColor:
- return SK_ColorBLACK;
- case NativeTheme::kColorId_FocusedBorderColor:
- return gfx::kGoogleBlue900;
case NativeTheme::kColorId_UnfocusedBorderColor:
- return SK_ColorBLACK;
case NativeTheme::kColorId_TabBottomBorder:
return SK_ColorBLACK;
+ case NativeTheme::kColorId_FocusedBorderColor:
case NativeTheme::kColorId_ProminentButtonColor:
return gfx::kGoogleBlue900;
default:
@@ -44,7 +39,7 @@ SkColor GetAuraColor(NativeTheme::ColorId color_id,
}
// Second wave of MD colors (colors that only appear in secondary UI).
- static const SkColor kPrimaryTextColor = SK_ColorBLACK;
+ constexpr SkColor kPrimaryTextColor = gfx::kGoogleGrey900;
switch (color_id) {
// Labels
@@ -74,96 +69,22 @@ SkColor GetAuraColor(NativeTheme::ColorId color_id,
}
// Shared constant for disabled text.
- static const SkColor kDisabledTextColor = SkColorSetRGB(0xA1, 0xA1, 0x92);
+ constexpr SkColor kDisabledTextColor = SkColorSetRGB(0xA1, 0xA1, 0x92);
- // Dialogs:
- static const SkColor kDialogBackgroundColor = SK_ColorWHITE;
// Buttons:
- static const SkColor kButtonEnabledColor = gfx::kChromeIconGrey;
- static const SkColor kProminentButtonColor = gfx::kGoogleBlue500;
- static const SkColor kProminentButtonTextColor = SK_ColorWHITE;
- static const SkColor kBlueButtonTextColor = SK_ColorWHITE;
- static const SkColor kBlueButtonShadowColor = SkColorSetRGB(0x53, 0x8C, 0xEA);
- // MenuItem:
- static const SkColor kTouchableMenuItemLabelColor =
- SkColorSetRGB(0x20, 0x21, 0x24);
- static const SkColor kActionableSubmenuVerticalSeparatorColor =
- SkColorSetARGB(0x24, 0x20, 0x21, 0x24);
- static const SkColor kMenuBackgroundColor = SK_ColorWHITE;
- static const SkColor kMenuHighlightBackgroundColor =
- SkColorSetA(SK_ColorBLACK, 0x14);
- static const SkColor kSelectedMenuItemForegroundColor = SK_ColorBLACK;
- static const SkColor kMenuBorderColor = SkColorSetRGB(0xBA, 0xBA, 0xBA);
- static const SkColor kMenuSeparatorColor = SkColorSetRGB(0xE9, 0xE9, 0xE9);
- static const SkColor kEnabledMenuItemForegroundColor = SK_ColorBLACK;
- static const SkColor kMenuItemMinorTextColor =
- SkColorSetA(SK_ColorBLACK, 0x89);
- // Separator:
- static const SkColor kSeparatorColor = SkColorSetRGB(0xE9, 0xE9, 0xE9);
- // Link:
- static const SkColor kLinkEnabledColor = gfx::kGoogleBlue700;
+ constexpr SkColor kButtonEnabledColor = gfx::kChromeIconGrey;
// Text selection colors:
- static const SkColor kTextSelectionBackgroundFocused =
+ constexpr SkColor kTextSelectionBackgroundFocused =
SkColorSetARGB(0x54, 0x60, 0xA8, 0xEB);
static const SkColor kTextSelectionColor = color_utils::AlphaBlend(
SK_ColorBLACK, kTextSelectionBackgroundFocused, 0xdd);
- // Textfield:
- static const SkColor kTextfieldDefaultColor = SK_ColorBLACK;
- static const SkColor kTextfieldDefaultBackground = SK_ColorWHITE;
- static const SkColor kTextfieldReadOnlyColor = kDisabledTextColor;
- static const SkColor kTextfieldReadOnlyBackground = SK_ColorWHITE;
- // Results tables:
- static const SkColor kResultsTableText = SK_ColorBLACK;
- static const SkColor kResultsTableDimmedText =
- SkColorSetRGB(0x64, 0x64, 0x64);
- static const SkColor kResultsTableHoveredBackground = color_utils::AlphaBlend(
- kTextSelectionBackgroundFocused, kTextfieldDefaultBackground, 0x40);
- const SkColor kPositiveTextColor = SkColorSetRGB(0x0b, 0x80, 0x43);
- const SkColor kNegativeTextColor = SkColorSetRGB(0xc5, 0x39, 0x29);
- static const SkColor kResultsTablePositiveText = color_utils::AlphaBlend(
- kPositiveTextColor, kTextfieldDefaultBackground, 0xDD);
- static const SkColor kResultsTablePositiveHoveredText =
- color_utils::AlphaBlend(kPositiveTextColor,
- kResultsTableHoveredBackground, 0xDD);
- static const SkColor kResultsTablePositiveSelectedText =
- color_utils::AlphaBlend(kPositiveTextColor,
- kTextSelectionBackgroundFocused, 0xDD);
- static const SkColor kResultsTableNegativeText = color_utils::AlphaBlend(
- kNegativeTextColor, kTextfieldDefaultBackground, 0xDD);
- static const SkColor kResultsTableNegativeHoveredText =
- color_utils::AlphaBlend(kNegativeTextColor,
- kResultsTableHoveredBackground, 0xDD);
- static const SkColor kResultsTableNegativeSelectedText =
- color_utils::AlphaBlend(kNegativeTextColor,
- kTextSelectionBackgroundFocused, 0xDD);
- // Tooltip:
- static const SkColor kTooltipBackground = SkColorSetA(SK_ColorBLACK, 0xCC);
- static const SkColor kTooltipTextColor = SkColorSetA(SK_ColorWHITE, 0xDE);
- // Tree:
- static const SkColor kTreeBackground = SK_ColorWHITE;
- static const SkColor kTreeTextColor = SK_ColorBLACK;
- static const SkColor kTreeSelectedTextColor = SK_ColorBLACK;
- static const SkColor kTreeSelectionBackgroundColor =
- SkColorSetRGB(0xEE, 0xEE, 0xEE);
- // Table:
- static const SkColor kTableBackground = SK_ColorWHITE;
- static const SkColor kTableTextColor = SK_ColorBLACK;
- static const SkColor kTableSelectedTextColor = SK_ColorBLACK;
- static const SkColor kTableSelectionBackgroundColor =
- SkColorSetRGB(0xEE, 0xEE, 0xEE);
- static const SkColor kTableGroupingIndicatorColor =
- SkColorSetRGB(0xCC, 0xCC, 0xCC);
- // Material spinner/throbber:
- static const SkColor kThrobberSpinningColor = gfx::kGoogleBlue600;
- static const SkColor kThrobberWaitingColor = SkColorSetRGB(0xA6, 0xA6, 0xA6);
- static const SkColor kThrobberLightColor = SkColorSetRGB(0xF4, 0xF8, 0xFD);
switch (color_id) {
// Dialogs
case NativeTheme::kColorId_WindowBackground:
case NativeTheme::kColorId_DialogBackground:
case NativeTheme::kColorId_BubbleBackground:
- return kDialogBackgroundColor;
+ return SK_ColorWHITE;
// Buttons
case NativeTheme::kColorId_ButtonEnabledColor:
@@ -174,13 +95,13 @@ SkColor GetAuraColor(NativeTheme::ColorId color_id,
case NativeTheme::kColorId_BlueButtonDisabledColor:
case NativeTheme::kColorId_BlueButtonPressedColor:
case NativeTheme::kColorId_BlueButtonHoverColor:
- return kBlueButtonTextColor;
+ return SK_ColorWHITE;
case NativeTheme::kColorId_BlueButtonShadowColor:
- return kBlueButtonShadowColor;
+ return SkColorSetRGB(0x53, 0x8C, 0xEA);
case NativeTheme::kColorId_ProminentButtonColor:
- return kProminentButtonColor;
+ return gfx::kGoogleBlue500;
case NativeTheme::kColorId_TextOnProminentButtonColor:
- return kProminentButtonTextColor;
+ return SK_ColorWHITE;
case NativeTheme::kColorId_ButtonPressedShade:
return SK_ColorTRANSPARENT;
case NativeTheme::kColorId_ButtonDisabledColor:
@@ -188,25 +109,24 @@ SkColor GetAuraColor(NativeTheme::ColorId color_id,
// MenuItem
case NativeTheme::kColorId_TouchableMenuItemLabelColor:
- return kTouchableMenuItemLabelColor;
+ return gfx::kGoogleGrey900;
case NativeTheme::kColorId_ActionableSubmenuVerticalSeparatorColor:
- return kActionableSubmenuVerticalSeparatorColor;
+ return SkColorSetA(gfx::kGoogleGrey900, 0x24);
case NativeTheme::kColorId_SelectedMenuItemForegroundColor:
- return kSelectedMenuItemForegroundColor;
+ case NativeTheme::kColorId_EnabledMenuItemForegroundColor:
+ return SK_ColorBLACK;
case NativeTheme::kColorId_MenuBorderColor:
- return kMenuBorderColor;
+ return SkColorSetRGB(0xBA, 0xBA, 0xBA);
case NativeTheme::kColorId_MenuSeparatorColor:
- return kMenuSeparatorColor;
+ return SkColorSetRGB(0xE9, 0xE9, 0xE9);
case NativeTheme::kColorId_MenuBackgroundColor:
- return kMenuBackgroundColor;
+ return SK_ColorWHITE;
case NativeTheme::kColorId_FocusedMenuItemBackgroundColor:
- return kMenuHighlightBackgroundColor;
- case NativeTheme::kColorId_EnabledMenuItemForegroundColor:
- return kEnabledMenuItemForegroundColor;
+ return SkColorSetA(SK_ColorBLACK, 0x14);
case NativeTheme::kColorId_DisabledMenuItemForegroundColor:
return kDisabledTextColor;
case NativeTheme::kColorId_MenuItemMinorTextColor:
- return kMenuItemMinorTextColor;
+ return SkColorSetA(SK_ColorBLACK, 0x89);
// Label
case NativeTheme::kColorId_LabelEnabledColor:
@@ -226,11 +146,11 @@ SkColor GetAuraColor(NativeTheme::ColorId color_id,
case NativeTheme::kColorId_LinkEnabled:
case NativeTheme::kColorId_LinkPressed:
- return kLinkEnabledColor;
+ return gfx::kGoogleBlue700;
// Separator
case NativeTheme::kColorId_SeparatorColor:
- return kSeparatorColor;
+ return SkColorSetRGB(0xE9, 0xE9, 0xE9);
// TabbedPane
case NativeTheme::kColorId_TabTitleColorActive:
@@ -242,13 +162,12 @@ SkColor GetAuraColor(NativeTheme::ColorId color_id,
// Textfield
case NativeTheme::kColorId_TextfieldDefaultColor:
- return kTextfieldDefaultColor;
+ return SK_ColorBLACK;
case NativeTheme::kColorId_TextfieldDefaultBackground:
- return kTextfieldDefaultBackground;
- case NativeTheme::kColorId_TextfieldReadOnlyColor:
- return kTextfieldReadOnlyColor;
case NativeTheme::kColorId_TextfieldReadOnlyBackground:
- return kTextfieldReadOnlyBackground;
+ return SK_ColorWHITE;
+ case NativeTheme::kColorId_TextfieldReadOnlyColor:
+ return kDisabledTextColor;
case NativeTheme::kColorId_TextfieldSelectionColor:
return kTextSelectionColor;
case NativeTheme::kColorId_TextfieldSelectionBackgroundFocused:
@@ -256,35 +175,33 @@ SkColor GetAuraColor(NativeTheme::ColorId color_id,
// Tooltip
case NativeTheme::kColorId_TooltipBackground:
- return kTooltipBackground;
+ return SkColorSetA(SK_ColorBLACK, 0xCC);
case NativeTheme::kColorId_TooltipText:
- return kTooltipTextColor;
+ return SkColorSetA(SK_ColorWHITE, 0xDE);
// Tree
case NativeTheme::kColorId_TreeBackground:
- return kTreeBackground;
+ return SK_ColorWHITE;
case NativeTheme::kColorId_TreeText:
- return kTreeTextColor;
case NativeTheme::kColorId_TreeSelectedText:
case NativeTheme::kColorId_TreeSelectedTextUnfocused:
- return kTreeSelectedTextColor;
+ return SK_ColorBLACK;
case NativeTheme::kColorId_TreeSelectionBackgroundFocused:
case NativeTheme::kColorId_TreeSelectionBackgroundUnfocused:
- return kTreeSelectionBackgroundColor;
+ return SkColorSetRGB(0xEE, 0xEE, 0xEE);
// Table
case NativeTheme::kColorId_TableBackground:
- return kTableBackground;
+ return SK_ColorWHITE;
case NativeTheme::kColorId_TableText:
- return kTableTextColor;
case NativeTheme::kColorId_TableSelectedText:
case NativeTheme::kColorId_TableSelectedTextUnfocused:
- return kTableSelectedTextColor;
+ return SK_ColorBLACK;
case NativeTheme::kColorId_TableSelectionBackgroundFocused:
case NativeTheme::kColorId_TableSelectionBackgroundUnfocused:
- return kTableSelectionBackgroundColor;
+ return SkColorSetRGB(0xEE, 0xEE, 0xEE);
case NativeTheme::kColorId_TableGroupingIndicatorColor:
- return kTableGroupingIndicatorColor;
+ return SkColorSetRGB(0xCC, 0xCC, 0xCC);
// Table Header
case NativeTheme::kColorId_TableHeaderText:
@@ -304,47 +221,23 @@ SkColor GetAuraColor(NativeTheme::ColorId color_id,
// Results Tables
case NativeTheme::kColorId_ResultsTableNormalBackground:
- return kTextfieldDefaultBackground;
+ return SK_ColorWHITE;
case NativeTheme::kColorId_ResultsTableHoveredBackground:
return SkColorSetA(base_theme->GetSystemColor(
NativeTheme::kColorId_ResultsTableNormalText),
0x0D);
- case NativeTheme::kColorId_ResultsTableSelectedBackground:
- return SkColorSetA(base_theme->GetSystemColor(
- NativeTheme::kColorId_ResultsTableNormalText),
- 0x14);
case NativeTheme::kColorId_ResultsTableNormalText:
- case NativeTheme::kColorId_ResultsTableHoveredText:
- case NativeTheme::kColorId_ResultsTableSelectedText:
- return kResultsTableText;
- case NativeTheme::kColorId_ResultsTableNormalDimmedText:
- case NativeTheme::kColorId_ResultsTableHoveredDimmedText:
- case NativeTheme::kColorId_ResultsTableSelectedDimmedText:
- return kResultsTableDimmedText;
- case NativeTheme::kColorId_ResultsTableNormalUrl:
- case NativeTheme::kColorId_ResultsTableHoveredUrl:
- case NativeTheme::kColorId_ResultsTableSelectedUrl:
- return base_theme->GetSystemColor(NativeTheme::kColorId_LinkEnabled);
- case NativeTheme::kColorId_ResultsTablePositiveText:
- return kResultsTablePositiveText;
- case NativeTheme::kColorId_ResultsTablePositiveHoveredText:
- return kResultsTablePositiveHoveredText;
- case NativeTheme::kColorId_ResultsTablePositiveSelectedText:
- return kResultsTablePositiveSelectedText;
- case NativeTheme::kColorId_ResultsTableNegativeText:
- return kResultsTableNegativeText;
- case NativeTheme::kColorId_ResultsTableNegativeHoveredText:
- return kResultsTableNegativeHoveredText;
- case NativeTheme::kColorId_ResultsTableNegativeSelectedText:
- return kResultsTableNegativeSelectedText;
+ return SK_ColorBLACK;
+ case NativeTheme::kColorId_ResultsTableDimmedText:
+ return SkColorSetRGB(0x64, 0x64, 0x64);
// Material spinner/throbber
case NativeTheme::kColorId_ThrobberSpinningColor:
- return kThrobberSpinningColor;
+ return gfx::kGoogleBlue600;
case NativeTheme::kColorId_ThrobberWaitingColor:
- return kThrobberWaitingColor;
+ return SkColorSetRGB(0xA6, 0xA6, 0xA6);
case NativeTheme::kColorId_ThrobberLightColor:
- return kThrobberLightColor;
+ return SkColorSetRGB(0xF4, 0xF8, 0xFD);
// Alert icon colors
case NativeTheme::kColorId_AlertSeverityLow:
diff --git a/chromium/ui/native_theme/native_theme.h b/chromium/ui/native_theme/native_theme.h
index 36ead2eed3c..b2284ad5da7 100644
--- a/chromium/ui/native_theme/native_theme.h
+++ b/chromium/ui/native_theme/native_theme.h
@@ -368,26 +368,8 @@ class NATIVE_THEME_EXPORT NativeTheme {
// Results Tables, such as the omnibox.
kColorId_ResultsTableNormalBackground,
kColorId_ResultsTableHoveredBackground,
- kColorId_ResultsTableSelectedBackground,
kColorId_ResultsTableNormalText,
- kColorId_ResultsTableHoveredText,
- kColorId_ResultsTableSelectedText,
- kColorId_ResultsTableNormalDimmedText,
- kColorId_ResultsTableHoveredDimmedText,
- kColorId_ResultsTableSelectedDimmedText,
- kColorId_ResultsTableNormalUrl,
- kColorId_ResultsTableHoveredUrl,
- kColorId_ResultsTableSelectedUrl,
- // Positive text refers to good (often rendered in green) text, such as the
- // stock value went up.
- kColorId_ResultsTablePositiveText,
- kColorId_ResultsTablePositiveHoveredText,
- kColorId_ResultsTablePositiveSelectedText,
- // Negative text refers to something alarming (often rendered in red), such
- // as the stock value went down.
- kColorId_ResultsTableNegativeText,
- kColorId_ResultsTableNegativeHoveredText,
- kColorId_ResultsTableNegativeSelectedText,
+ kColorId_ResultsTableDimmedText,
// Colors for the material spinner (aka throbber).
kColorId_ThrobberSpinningColor,
kColorId_ThrobberWaitingColor,
diff --git a/chromium/ui/native_theme/native_theme_android.cc b/chromium/ui/native_theme/native_theme_android.cc
index cd6bc1d04aa..3ddb6434ec4 100644
--- a/chromium/ui/native_theme/native_theme_android.cc
+++ b/chromium/ui/native_theme/native_theme_android.cc
@@ -29,8 +29,8 @@ NativeTheme* NativeTheme::GetInstanceForNativeUi() {
// static
NativeThemeAndroid* NativeThemeAndroid::instance() {
- CR_DEFINE_STATIC_LOCAL(NativeThemeAndroid, s_native_theme, ());
- return &s_native_theme;
+ static base::NoDestructor<NativeThemeAndroid> s_native_theme;
+ return s_native_theme.get();
}
gfx::Size NativeThemeAndroid::GetPartSize(Part part,
diff --git a/chromium/ui/native_theme/native_theme_android.h b/chromium/ui/native_theme/native_theme_android.h
index 52b42e59b72..5736f9712ea 100644
--- a/chromium/ui/native_theme/native_theme_android.h
+++ b/chromium/ui/native_theme/native_theme_android.h
@@ -6,6 +6,7 @@
#define UI_NATIVE_THEME_NATIVE_THEME_ANDROID_H_
#include "base/macros.h"
+#include "base/no_destructor.h"
#include "ui/native_theme/native_theme_base.h"
namespace ui {
@@ -21,6 +22,7 @@ class NativeThemeAndroid : public NativeThemeBase {
protected:
friend class NativeTheme;
+ friend class base::NoDestructor<NativeThemeAndroid>;
static NativeThemeAndroid* instance();
// NativeThemeBase:
diff --git a/chromium/ui/native_theme/native_theme_aura.cc b/chromium/ui/native_theme/native_theme_aura.cc
index e5ec3bb2013..4409bb629bb 100644
--- a/chromium/ui/native_theme/native_theme_aura.cc
+++ b/chromium/ui/native_theme/native_theme_aura.cc
@@ -88,15 +88,15 @@ NativeThemeAura::~NativeThemeAura() {}
// static
NativeThemeAura* NativeThemeAura::instance() {
- CR_DEFINE_STATIC_LOCAL(NativeThemeAura, s_native_theme, (false));
- return &s_native_theme;
+ static base::NoDestructor<NativeThemeAura> s_native_theme(false);
+ return s_native_theme.get();
}
// static
NativeThemeAura* NativeThemeAura::web_instance() {
- CR_DEFINE_STATIC_LOCAL(NativeThemeAura, s_native_theme_for_web,
- (IsOverlayScrollbarEnabled()));
- return &s_native_theme_for_web;
+ static base::NoDestructor<NativeThemeAura> s_native_theme_for_web(
+ IsOverlayScrollbarEnabled());
+ return s_native_theme_for_web.get();
}
// This implementation returns hardcoded colors.
diff --git a/chromium/ui/native_theme/native_theme_aura.h b/chromium/ui/native_theme/native_theme_aura.h
index eeebd051e3c..86185143513 100644
--- a/chromium/ui/native_theme/native_theme_aura.h
+++ b/chromium/ui/native_theme/native_theme_aura.h
@@ -6,6 +6,7 @@
#define UI_NATIVE_THEME_NATIVE_THEME_AURA_H_
#include "base/macros.h"
+#include "base/no_destructor.h"
#include "ui/native_theme/native_theme_base.h"
namespace ui {
@@ -15,6 +16,7 @@ class NATIVE_THEME_EXPORT NativeThemeAura : public NativeThemeBase {
protected:
friend class NativeTheme;
friend class NativeThemeAuraTest;
+ friend class base::NoDestructor<NativeThemeAura>;
explicit NativeThemeAura(bool use_overlay_scrollbars);
~NativeThemeAura() override;
diff --git a/chromium/ui/native_theme/native_theme_dark_aura.cc b/chromium/ui/native_theme/native_theme_dark_aura.cc
index 885cba0ac53..6ab77cd84e7 100644
--- a/chromium/ui/native_theme/native_theme_dark_aura.cc
+++ b/chromium/ui/native_theme/native_theme_dark_aura.cc
@@ -9,27 +9,14 @@
namespace ui {
NativeThemeDarkAura* NativeThemeDarkAura::instance() {
- CR_DEFINE_STATIC_LOCAL(NativeThemeDarkAura, s_native_theme, ());
- return &s_native_theme;
+ static base::NoDestructor<NativeThemeDarkAura> s_native_theme;
+ return s_native_theme.get();
}
SkColor NativeThemeDarkAura::GetSystemColor(ColorId color_id) const {
- static const SkColor kPrimaryTextColor = SK_ColorWHITE;
-
- static const SkColor kButtonEnabledColor = SK_ColorWHITE;
-
- static const SkColor kTextfieldDefaultColor = SK_ColorWHITE;
- static const SkColor kTextfieldDefaultBackground =
- SkColorSetRGB(0x62, 0x62, 0x62);
- static const SkColor kTextSelectionBackgroundFocused =
+ constexpr SkColor kTextSelectionBackgroundFocused =
SkColorSetA(gfx::kGoogleBlue700, 0xCC);
- static const SkColor kResultsTableNormalBackground =
- SkColorSetRGB(0x28, 0x28, 0x28);
- static const SkColor kResultsTableText = SK_ColorWHITE;
- static const SkColor kResultsTableDimmedText =
- SkColorSetA(kResultsTableText, 0x80);
-
switch (color_id) {
// Window
case kColorId_WindowBackground:
@@ -39,14 +26,14 @@ SkColor NativeThemeDarkAura::GetSystemColor(ColorId color_id) const {
// Button
case kColorId_ButtonEnabledColor:
- return kButtonEnabledColor;
+ return SK_ColorWHITE;
case kColorId_ProminentButtonColor:
return gfx::kGoogleBlue600;
// Label
case kColorId_LabelEnabledColor:
case kColorId_LabelTextSelectionColor:
- return kPrimaryTextColor;
+ return SK_ColorWHITE;
case kColorId_LabelTextSelectionBackgroundFocused:
return kTextSelectionBackgroundFocused;
@@ -58,23 +45,19 @@ SkColor NativeThemeDarkAura::GetSystemColor(ColorId color_id) const {
// Textfield
case kColorId_TextfieldDefaultColor:
case kColorId_TextfieldSelectionColor:
- return kTextfieldDefaultColor;
+ return SK_ColorWHITE;
case kColorId_TextfieldDefaultBackground:
- return kTextfieldDefaultBackground;
+ return SkColorSetRGB(0x62, 0x62, 0x62);
case kColorId_TextfieldSelectionBackgroundFocused:
return kTextSelectionBackgroundFocused;
// Results Tables
case kColorId_ResultsTableNormalBackground:
- return kResultsTableNormalBackground;
+ return SkColorSetRGB(0x28, 0x28, 0x28);
case kColorId_ResultsTableNormalText:
- case kColorId_ResultsTableHoveredText:
- case kColorId_ResultsTableSelectedText:
- return kResultsTableText;
- case kColorId_ResultsTableNormalDimmedText:
- case kColorId_ResultsTableHoveredDimmedText:
- case kColorId_ResultsTableSelectedDimmedText:
- return kResultsTableDimmedText;
+ return SK_ColorWHITE;
+ case kColorId_ResultsTableDimmedText:
+ return SkColorSetA(GetSystemColor(kColorId_ResultsTableNormalText), 0x80);
// FocusableBorder
case kColorId_FocusedBorderColor:
@@ -93,10 +76,6 @@ SkColor NativeThemeDarkAura::GetSystemColor(ColorId color_id) const {
case kColorId_TextOnProminentButtonColor:
case kColorId_ButtonPressedShade:
case kColorId_ResultsTableHoveredBackground:
- case kColorId_ResultsTableSelectedBackground:
- case kColorId_ResultsTableNormalUrl:
- case kColorId_ResultsTableHoveredUrl:
- case kColorId_ResultsTableSelectedUrl:
return NativeThemeAura::GetSystemColor(color_id);
// Any other color is not defined and shouldn't be used in a dark theme.
@@ -142,12 +121,6 @@ SkColor NativeThemeDarkAura::GetSystemColor(ColorId color_id) const {
case kColorId_TableHeaderText:
case kColorId_TableHeaderBackground:
case kColorId_TableHeaderSeparator:
- case kColorId_ResultsTablePositiveText:
- case kColorId_ResultsTablePositiveHoveredText:
- case kColorId_ResultsTablePositiveSelectedText:
- case kColorId_ResultsTableNegativeText:
- case kColorId_ResultsTableNegativeHoveredText:
- case kColorId_ResultsTableNegativeSelectedText:
case kColorId_SeparatorColor:
case kColorId_ThrobberSpinningColor:
case kColorId_ThrobberWaitingColor:
diff --git a/chromium/ui/native_theme/native_theme_dark_aura.h b/chromium/ui/native_theme/native_theme_dark_aura.h
index a014d7338f7..980df049507 100644
--- a/chromium/ui/native_theme/native_theme_dark_aura.h
+++ b/chromium/ui/native_theme/native_theme_dark_aura.h
@@ -6,6 +6,7 @@
#define UI_NATIVE_THEME_NATIVE_THEME_DARK_AURA_H_
#include "base/macros.h"
+#include "base/no_destructor.h"
#include "ui/native_theme/native_theme_aura.h"
namespace ui {
@@ -20,6 +21,8 @@ class NATIVE_THEME_EXPORT NativeThemeDarkAura : public NativeThemeAura {
SkColor GetSystemColor(ColorId color_id) const override;
private:
+ friend class base::NoDestructor<NativeThemeDarkAura>;
+
NativeThemeDarkAura();
~NativeThemeDarkAura() override;
diff --git a/chromium/ui/native_theme/native_theme_mac.h b/chromium/ui/native_theme/native_theme_mac.h
index 478afb67fca..83007af4466 100644
--- a/chromium/ui/native_theme/native_theme_mac.h
+++ b/chromium/ui/native_theme/native_theme_mac.h
@@ -6,6 +6,7 @@
#define UI_NATIVE_THEME_NATIVE_THEME_MAC_H_
#include "base/macros.h"
+#include "base/no_destructor.h"
#include "ui/native_theme/native_theme_base.h"
#include "ui/native_theme/native_theme_export.h"
@@ -60,6 +61,7 @@ class NATIVE_THEME_EXPORT NativeThemeMac : public NativeThemeBase {
protected:
friend class NativeTheme;
+ friend class base::NoDestructor<NativeThemeMac>;
static NativeThemeMac* instance();
private:
diff --git a/chromium/ui/native_theme/native_theme_mac.mm b/chromium/ui/native_theme/native_theme_mac.mm
index eb567ffcf31..17036c74f8f 100644
--- a/chromium/ui/native_theme/native_theme_mac.mm
+++ b/chromium/ui/native_theme/native_theme_mac.mm
@@ -99,8 +99,8 @@ NativeTheme* NativeTheme::GetInstanceForNativeUi() {
// static
NativeThemeMac* NativeThemeMac::instance() {
- CR_DEFINE_STATIC_LOCAL(NativeThemeMac, s_native_theme, ());
- return &s_native_theme;
+ static base::NoDestructor<NativeThemeMac> s_native_theme;
+ return s_native_theme.get();
}
// static
diff --git a/chromium/ui/native_theme/native_theme_win.cc b/chromium/ui/native_theme/native_theme_win.cc
index 839974db22b..c0344b4337d 100644
--- a/chromium/ui/native_theme/native_theme_win.cc
+++ b/chromium/ui/native_theme/native_theme_win.cc
@@ -157,8 +157,8 @@ void NativeThemeWin::CloseHandles() {
// static
NativeThemeWin* NativeThemeWin::instance() {
- CR_DEFINE_STATIC_LOCAL(NativeThemeWin, s_native_theme, ());
- return &s_native_theme;
+ static base::NoDestructor<NativeThemeWin> s_native_theme;
+ return s_native_theme.get();
}
gfx::Size NativeThemeWin::GetPartSize(Part part,
@@ -416,21 +416,16 @@ void NativeThemeWin::PaintDirect(SkCanvas* destination_canvas,
}
SkColor NativeThemeWin::GetSystemColor(ColorId color_id) const {
- // TODO: Obtain the correct colors using GetSysColor.
+ // TODO: Obtain the correct colors for these using GetSysColor.
// Button:
- const SkColor kButtonHoverColor = SkColorSetRGB(6, 45, 117);
- const SkColor kProminentButtonColorInvert = gfx::kGoogleBlue300;
+ constexpr SkColor kButtonHoverColor = SkColorSetRGB(6, 45, 117);
+ constexpr SkColor kProminentButtonColorInvert = gfx::kGoogleBlue300;
// MenuItem:
- const SkColor kMenuSchemeHighlightBackgroundColorInvert =
+ constexpr SkColor kMenuSchemeHighlightBackgroundColorInvert =
SkColorSetRGB(0x30, 0x30, 0x30);
- // Table:
- const SkColor kPositiveTextColor = SkColorSetRGB(0x0b, 0x80, 0x43);
- const SkColor kNegativeTextColor = SkColorSetRGB(0xc5, 0x39, 0x29);
- // Results Tables:
- const SkColor kResultsTableUrlColor = gfx::kGoogleBlue700;
- const SkColor kResultsTableSelectedUrlColor = SK_ColorWHITE;
// Label:
- const SkColor kLabelTextSelectionBackgroundFocusedColor = gfx::kGoogleBlue700;
+ constexpr SkColor kLabelTextSelectionBackgroundFocusedColor =
+ gfx::kGoogleBlue700;
switch (color_id) {
// Windows
@@ -444,7 +439,6 @@ SkColor NativeThemeWin::GetSystemColor(ColorId color_id) const {
// FocusableBorder
case kColorId_FocusedBorderColor:
- break;
case kColorId_UnfocusedBorderColor:
break;
@@ -523,57 +517,11 @@ SkColor NativeThemeWin::GetSystemColor(ColorId color_id) const {
case kColorId_ResultsTableHoveredBackground:
return color_utils::AlphaBlend(system_colors_[COLOR_HIGHLIGHT],
system_colors_[COLOR_WINDOW], 0x40);
- case kColorId_ResultsTableSelectedBackground:
- return system_colors_[COLOR_HIGHLIGHT];
case kColorId_ResultsTableNormalText:
return system_colors_[COLOR_WINDOWTEXT];
- case kColorId_ResultsTableHoveredText:
- return color_utils::GetReadableColor(
- system_colors_[COLOR_WINDOWTEXT],
- GetSystemColor(kColorId_ResultsTableHoveredBackground));
- case kColorId_ResultsTableSelectedText:
- return system_colors_[COLOR_HIGHLIGHTTEXT];
- case kColorId_ResultsTableNormalDimmedText:
+ case kColorId_ResultsTableDimmedText:
return color_utils::AlphaBlend(system_colors_[COLOR_WINDOWTEXT],
system_colors_[COLOR_WINDOW], 0x80);
- case kColorId_ResultsTableHoveredDimmedText:
- return color_utils::AlphaBlend(
- system_colors_[COLOR_WINDOWTEXT],
- GetSystemColor(kColorId_ResultsTableHoveredBackground), 0x80);
- case kColorId_ResultsTableSelectedDimmedText:
- return color_utils::AlphaBlend(system_colors_[COLOR_HIGHLIGHTTEXT],
- system_colors_[COLOR_HIGHLIGHT], 0x80);
- case kColorId_ResultsTableNormalUrl:
- return color_utils::GetReadableColor(kResultsTableUrlColor,
- system_colors_[COLOR_WINDOW]);
- case kColorId_ResultsTableHoveredUrl:
- return color_utils::PickContrastingColor(
- kResultsTableUrlColor, kResultsTableSelectedUrlColor,
- GetSystemColor(kColorId_ResultsTableHoveredBackground));
- case kColorId_ResultsTableSelectedUrl:
- return color_utils::PickContrastingColor(
- kResultsTableUrlColor, kResultsTableSelectedUrlColor,
- system_colors_[COLOR_HIGHLIGHT]);
- case kColorId_ResultsTablePositiveText:
- return color_utils::GetReadableColor(kPositiveTextColor,
- system_colors_[COLOR_WINDOW]);
- case kColorId_ResultsTablePositiveHoveredText:
- return color_utils::GetReadableColor(
- kPositiveTextColor,
- GetSystemColor(kColorId_ResultsTableHoveredBackground));
- case kColorId_ResultsTablePositiveSelectedText:
- return color_utils::GetReadableColor(kPositiveTextColor,
- system_colors_[COLOR_HIGHLIGHT]);
- case kColorId_ResultsTableNegativeText:
- return color_utils::GetReadableColor(kNegativeTextColor,
- system_colors_[COLOR_WINDOW]);
- case kColorId_ResultsTableNegativeHoveredText:
- return color_utils::GetReadableColor(
- kNegativeTextColor,
- GetSystemColor(kColorId_ResultsTableHoveredBackground));
- case kColorId_ResultsTableNegativeSelectedText:
- return color_utils::GetReadableColor(kNegativeTextColor,
- system_colors_[COLOR_HIGHLIGHT]);
default:
break;
}
@@ -666,7 +614,7 @@ void NativeThemeWin::PaintIndirect(cc::PaintCanvas* destination_canvas,
// To work-around this, mark all pixels with a placeholder value, to detect
// which pixels get touched by the paint operation. After paint, set any
// pixels that have alpha 0 to opaque and placeholders to fully-transparent.
- const SkColor placeholder = SkColorSetARGB(1, 0, 0, 0);
+ constexpr SkColor placeholder = SkColorSetARGB(1, 0, 0, 0);
offscreen_canvas->clear(placeholder);
// Offset destination rects to have origin (0,0).
diff --git a/chromium/ui/native_theme/native_theme_win.h b/chromium/ui/native_theme/native_theme_win.h
index ab7f78cfcbd..9ee7350fa64 100644
--- a/chromium/ui/native_theme/native_theme_win.h
+++ b/chromium/ui/native_theme/native_theme_win.h
@@ -18,6 +18,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/no_destructor.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/sys_color_change_listener.h"
@@ -82,6 +83,7 @@ class NATIVE_THEME_EXPORT NativeThemeWin : public NativeTheme,
protected:
friend class NativeTheme;
+ friend class base::NoDestructor<NativeThemeWin>;
// Gets our singleton instance.
static NativeThemeWin* instance();
diff --git a/chromium/ui/ozone/common/linux/OWNERS b/chromium/ui/ozone/common/linux/OWNERS
index 363a93a5f95..d047913b027 100644
--- a/chromium/ui/ozone/common/linux/OWNERS
+++ b/chromium/ui/ozone/common/linux/OWNERS
@@ -1,2 +1,3 @@
dcastagna@chromium.org
dnicoara@chromium.org
+msisov@igalia.com
diff --git a/chromium/ui/ozone/common/linux/gbm_buffer.h b/chromium/ui/ozone/common/linux/gbm_buffer.h
index 12c13bb2d67..c6e0daceafb 100644
--- a/chromium/ui/ozone/common/linux/gbm_buffer.h
+++ b/chromium/ui/ozone/common/linux/gbm_buffer.h
@@ -7,10 +7,13 @@
#include <inttypes.h>
+#include "third_party/skia/include/core/SkRefCnt.h"
#include "ui/gfx/buffer_types.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/native_pixmap_handle.h"
+class SkSurface;
+
namespace ui {
class GbmBuffer {
@@ -34,6 +37,7 @@ class GbmBuffer {
virtual size_t GetPlaneSize(size_t plane) const = 0;
virtual uint32_t GetHandle() const = 0;
virtual gfx::NativePixmapHandle ExportHandle() const = 0;
+ virtual sk_sp<SkSurface> GetSurface() = 0;
};
} // namespace ui
diff --git a/chromium/ui/ozone/common/linux/gbm_wrapper.cc b/chromium/ui/ozone/common/linux/gbm_wrapper.cc
index d05fe026143..ba55b0e5685 100644
--- a/chromium/ui/ozone/common/linux/gbm_wrapper.cc
+++ b/chromium/ui/ozone/common/linux/gbm_wrapper.cc
@@ -7,6 +7,7 @@
#include <gbm.h>
#include "base/posix/eintr_wrapper.h"
+#include "third_party/skia/include/core/SkSurface.h"
#include "ui/gfx/buffer_format_util.h"
#include "ui/ozone/common/linux/drm_util_linux.h"
#include "ui/ozone/common/linux/gbm_buffer.h"
@@ -31,7 +32,10 @@ class Buffer final : public ui::GbmBuffer {
size_(size),
planes_(std::move(planes)) {}
- ~Buffer() override { gbm_bo_destroy(bo_); }
+ ~Buffer() override {
+ DCHECK(!mmap_data_);
+ gbm_bo_destroy(bo_);
+ }
uint32_t GetFormat() const override { return format_; }
uint64_t GetFormatModifier() const override { return format_modifier_; }
@@ -97,8 +101,24 @@ class Buffer final : public ui::GbmBuffer {
return handle;
}
+ sk_sp<SkSurface> GetSurface() override {
+ DCHECK(!mmap_data_);
+ uint32_t stride;
+ void* addr;
+ addr = gbm_bo_map(bo_, 0, 0, gbm_bo_get_width(bo_), gbm_bo_get_height(bo_),
+ GBM_BO_TRANSFER_READ_WRITE, &stride, &mmap_data_, 0);
+
+ if (!addr)
+ return nullptr;
+ SkImageInfo info =
+ SkImageInfo::MakeN32Premul(size_.width(), size_.height());
+ return SkSurface::MakeRasterDirectReleaseProc(info, addr, stride,
+ &Buffer::UnmapGbmBo, this);
+ }
+
private:
gbm_bo* bo_ = nullptr;
+ void* mmap_data_ = nullptr;
uint32_t format_ = 0;
uint64_t format_modifier_ = 0;
@@ -110,6 +130,12 @@ class Buffer final : public ui::GbmBuffer {
std::vector<gfx::NativePixmapPlane> planes_;
+ static void UnmapGbmBo(void* pixels, void* context) {
+ Buffer* buffer = static_cast<Buffer*>(context);
+ gbm_bo_unmap(buffer->bo_, buffer->mmap_data_);
+ buffer->mmap_data_ = nullptr;
+ }
+
DISALLOW_COPY_AND_ASSIGN(Buffer);
};
diff --git a/chromium/ui/ozone/demo/BUILD.gn b/chromium/ui/ozone/demo/BUILD.gn
index e76631b05d4..5b7e6059daf 100644
--- a/chromium/ui/ozone/demo/BUILD.gn
+++ b/chromium/ui/ozone/demo/BUILD.gn
@@ -39,7 +39,7 @@ source_set("ozone_demo_lib") {
]
if (is_fuchsia) {
- deps += [ "//third_party/fuchsia-sdk:policy" ]
+ deps += [ "//third_party/fuchsia-sdk/sdk:policy" ]
}
}
@@ -101,11 +101,13 @@ executable("skia_demo") {
if (is_fuchsia) {
fuchsia_package("ozone_demo_pkg") {
+ testonly = true
binary = ":ozone_demo"
package_name_override = "ozone_demo"
}
fuchsia_package_runner("ozone_demo_fuchsia") {
+ testonly = true
package = ":ozone_demo_pkg"
package_name_override = "ozone_demo"
}
diff --git a/chromium/ui/ozone/demo/demo_window.cc b/chromium/ui/ozone/demo/demo_window.cc
index a3397d5fad1..38deff0067c 100644
--- a/chromium/ui/ozone/demo/demo_window.cc
+++ b/chromium/ui/ozone/demo/demo_window.cc
@@ -66,16 +66,16 @@ gfx::Size DemoWindow::GetSize() {
}
void DemoWindow::Start() {
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE,
- base::BindOnce(&DemoWindow::StartOnGpu, weak_ptr_factory_.GetWeakPtr()));
+ StartRendererIfNecessary();
}
void DemoWindow::Quit() {
window_manager_->Quit();
}
-void DemoWindow::OnBoundsChanged(const gfx::Rect& new_bounds) {}
+void DemoWindow::OnBoundsChanged(const gfx::Rect& new_bounds) {
+ StartRendererIfNecessary();
+}
void DemoWindow::OnDamageRect(const gfx::Rect& damaged_region) {}
@@ -105,7 +105,9 @@ void DemoWindow::OnAcceleratedWidgetDestroyed() {
void DemoWindow::OnActivationChanged(bool active) {}
-void DemoWindow::StartOnGpu() {
+void DemoWindow::StartRendererIfNecessary() {
+ if (renderer_ || GetSize().IsEmpty())
+ return;
renderer_ =
renderer_factory_->CreateRenderer(GetAcceleratedWidget(), GetSize());
if (!renderer_->Initialize())
diff --git a/chromium/ui/ozone/demo/demo_window.h b/chromium/ui/ozone/demo/demo_window.h
index 720ac4cd808..a0be6aead25 100644
--- a/chromium/ui/ozone/demo/demo_window.h
+++ b/chromium/ui/ozone/demo/demo_window.h
@@ -47,7 +47,7 @@ class DemoWindow : public PlatformWindowDelegate {
private:
// Since we pretend to have a GPU process, we should also pretend to
// initialize the GPU resources via a posted task.
- void StartOnGpu();
+ void StartRendererIfNecessary();
WindowManager* window_manager_; // Not owned.
RendererFactory* renderer_factory_; // Not owned.
diff --git a/chromium/ui/ozone/demo/simple_renderer_factory.cc b/chromium/ui/ozone/demo/simple_renderer_factory.cc
index 7345ab9d467..328cfe419e0 100644
--- a/chromium/ui/ozone/demo/simple_renderer_factory.cc
+++ b/chromium/ui/ozone/demo/simple_renderer_factory.cc
@@ -18,6 +18,7 @@
#if BUILDFLAG(ENABLE_VULKAN)
#include "gpu/vulkan/init/vulkan_factory.h"
+#include "gpu/vulkan/vulkan_surface.h"
#include "ui/ozone/demo/vulkan_overlay_renderer.h"
#include "ui/ozone/demo/vulkan_renderer.h"
#endif
@@ -102,7 +103,10 @@ std::unique_ptr<Renderer> SimpleRendererFactory::CreateRenderer(
std::move(overlay_surface), surface_factory_ozone,
vulkan_implementation_.get(), widget, size);
}
- return std::make_unique<VulkanRenderer>(vulkan_implementation_.get(),
+ std::unique_ptr<gpu::VulkanSurface> vulkan_surface =
+ vulkan_implementation_->CreateViewSurface(widget);
+ return std::make_unique<VulkanRenderer>(std::move(vulkan_surface),
+ vulkan_implementation_.get(),
widget, size);
}
#endif
diff --git a/chromium/ui/ozone/demo/vulkan_overlay_renderer.cc b/chromium/ui/ozone/demo/vulkan_overlay_renderer.cc
index 4bfc3167c75..5f4d6125b0c 100644
--- a/chromium/ui/ozone/demo/vulkan_overlay_renderer.cc
+++ b/chromium/ui/ozone/demo/vulkan_overlay_renderer.cc
@@ -15,7 +15,6 @@
#include "gpu/vulkan/vulkan_device_queue.h"
#include "gpu/vulkan/vulkan_function_pointers.h"
#include "gpu/vulkan/vulkan_implementation.h"
-#include "gpu/vulkan/vulkan_render_pass.h"
#include "gpu/vulkan/vulkan_surface.h"
#include "gpu/vulkan/vulkan_swap_chain.h"
#include "ui/display/types/display_snapshot.h"
@@ -48,6 +47,7 @@ VulkanOverlayRenderer::VulkanOverlayRenderer(
VulkanOverlayRenderer::~VulkanOverlayRenderer() {
DestroyBuffers();
+ DestroyRenderPass();
command_pool_->Destroy();
command_pool_.reset();
device_queue_->Destroy();
@@ -64,35 +64,44 @@ bool VulkanOverlayRenderer::Initialize() {
}
VkAttachmentDescription render_pass_attachments[] = {{
- .format = VK_FORMAT_B8G8R8A8_SRGB,
- .samples = VK_SAMPLE_COUNT_1_BIT,
- .loadOp = VK_ATTACHMENT_LOAD_OP_CLEAR,
- .storeOp = VK_ATTACHMENT_STORE_OP_STORE,
- .initialLayout = VK_IMAGE_LAYOUT_UNDEFINED,
- .finalLayout = VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
+ /* .flags = */ 0,
+ /* .format = */ VK_FORMAT_B8G8R8A8_SRGB,
+ /* .samples = */ VK_SAMPLE_COUNT_1_BIT,
+ /* .loadOp = */ VK_ATTACHMENT_LOAD_OP_CLEAR,
+ /* .storeOp = */ VK_ATTACHMENT_STORE_OP_STORE,
+ /* .stencilLoadOp = */ VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ /* .stencilStoreOp = */ VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ /* .initialLayout = */ VK_IMAGE_LAYOUT_UNDEFINED,
+ /* .finalLayout = */ VK_IMAGE_LAYOUT_PRESENT_SRC_KHR,
}};
VkAttachmentReference color_attachment_references[] = {
- {.attachment = 0, .layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}};
+ {/* .attachment = */ 0,
+ /* .layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}};
VkSubpassDescription render_pass_subpasses[] = {{
- .pipelineBindPoint = VK_PIPELINE_BIND_POINT_GRAPHICS,
- .inputAttachmentCount = 0,
- .colorAttachmentCount = base::size(color_attachment_references),
- .pColorAttachments = color_attachment_references,
- .pResolveAttachments = nullptr,
- .pDepthStencilAttachment = nullptr,
- .preserveAttachmentCount = 0,
- .pPreserveAttachments = nullptr,
+ /* .flags = */ 0,
+ /* .pipelineBindPoint = */ VK_PIPELINE_BIND_POINT_GRAPHICS,
+ /* .inputAttachmentCount = */ 0,
+ /* .pInputAttachments = */ nullptr,
+ /* .colorAttachmentCount = */ base::size(color_attachment_references),
+ /* .pColorAttachments = */ color_attachment_references,
+ /* .pResolveAttachments = */ nullptr,
+ /* .pDepthStencilAttachment = */ nullptr,
+ /* .preserveAttachmentCount = */ 0,
+ /* .pPreserveAttachments = */ nullptr,
}};
VkRenderPassCreateInfo render_pass_create_info = {
- .sType = VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
- .attachmentCount = base::size(render_pass_attachments),
- .pAttachments = render_pass_attachments,
- .subpassCount = base::size(render_pass_subpasses),
- .pSubpasses = render_pass_subpasses,
- .dependencyCount = 0,
+ /* .sType = */ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
+ /* .pNext = */ nullptr,
+ /* .flags = */ 0,
+ /* .attachmentCount = */ base::size(render_pass_attachments),
+ /* .pAttachments = */ render_pass_attachments,
+ /* .subpassCount = */ base::size(render_pass_subpasses),
+ /* .pSubpasses = */ render_pass_subpasses,
+ /* .dependencyCount = */ 0,
+ /* .pDependencies = */ nullptr,
};
CHECK_EQ(vkCreateRenderPass(device_queue_->GetVulkanDevice(),
@@ -109,6 +118,14 @@ bool VulkanOverlayRenderer::Initialize() {
return true;
}
+void VulkanOverlayRenderer::DestroyRenderPass() {
+ if (render_pass_ == VK_NULL_HANDLE)
+ return;
+
+ vkDestroyRenderPass(device_queue_->GetVulkanDevice(), render_pass_, nullptr);
+ render_pass_ = VK_NULL_HANDLE;
+}
+
void VulkanOverlayRenderer::DestroyBuffers() {
VkDevice vk_device = device_queue_->GetVulkanDevice();
@@ -146,7 +163,7 @@ void VulkanOverlayRenderer::RenderFrame() {
TRACE_EVENT0("ozone", "VulkanOverlayRenderer::RenderFrame");
VkClearValue clear_value = {
- .color = {.float32 = {.5f, 1.f - NextFraction(), .5f, 1.f}}};
+ /* .color = */ {/* .float32 = */ {.5f, 1.f - NextFraction(), .5f, 1.f}}};
const Buffer& buffer = *buffers_[next_buffer_];
next_buffer_++;
@@ -159,14 +176,26 @@ void VulkanOverlayRenderer::RenderFrame() {
{
gpu::ScopedSingleUseCommandBufferRecorder recorder(command_buffer);
- VkRenderPassBeginInfo begin_info = {};
- begin_info.sType = VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO;
- begin_info.renderPass = render_pass_;
- begin_info.framebuffer = buffer.vk_framebuffer();
- begin_info.renderArea.extent.width = buffer.size().width();
- begin_info.renderArea.extent.height = buffer.size().height();
- begin_info.clearValueCount = 1;
- begin_info.pClearValues = &clear_value;
+ VkRenderPassBeginInfo begin_info = {
+ /* .sType = */ VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
+ /* .pNext = */ nullptr,
+ /* .renderPass = */ render_pass_,
+ /* .framebuffer = */ buffer.vk_framebuffer(),
+ /* .renderArea = */
+ {
+ /* .offset = */ {
+ /* .x = */ 0,
+ /* .y = */ 0,
+ },
+ /* .extent = */
+ {
+ /* .width = */ buffer.size().width(),
+ /* .height = */ buffer.size().height(),
+ },
+ },
+ /* .clearValueCount = */ 1,
+ /* .pClearValues = */ &clear_value,
+ };
vkCmdBeginRenderPass(recorder.handle(), &begin_info,
VK_SUBPASS_CONTENTS_INLINE);
@@ -303,25 +332,27 @@ VulkanOverlayRenderer::Buffer::Create(
}
VkImageViewCreateInfo vk_image_view_create_info = {
- .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
- .image = vk_image,
- .viewType = VK_IMAGE_VIEW_TYPE_2D,
- .format = VK_FORMAT_B8G8R8A8_SRGB,
- .components =
- {
- .r = VK_COMPONENT_SWIZZLE_IDENTITY,
- .b = VK_COMPONENT_SWIZZLE_IDENTITY,
- .g = VK_COMPONENT_SWIZZLE_IDENTITY,
- .a = VK_COMPONENT_SWIZZLE_IDENTITY,
- },
- .subresourceRange =
- {
- .aspectMask = VK_IMAGE_ASPECT_COLOR_BIT,
- .baseMipLevel = 0,
- .levelCount = 1,
- .baseArrayLayer = 0,
- .layerCount = 1,
- },
+ /* .sType = */ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+ /* .pNext = */ nullptr,
+ /* .flags = */ 0,
+ /* .image = */ vk_image,
+ /* .viewType = */ VK_IMAGE_VIEW_TYPE_2D,
+ /* .format = */ VK_FORMAT_B8G8R8A8_SRGB,
+ /* .components = */
+ {
+ /* .r = */ VK_COMPONENT_SWIZZLE_IDENTITY,
+ /* .b = */ VK_COMPONENT_SWIZZLE_IDENTITY,
+ /* .g = */ VK_COMPONENT_SWIZZLE_IDENTITY,
+ /* .a = */ VK_COMPONENT_SWIZZLE_IDENTITY,
+ },
+ /* .subresourceRange = */
+ {
+ /* .aspectMask = */ VK_IMAGE_ASPECT_COLOR_BIT,
+ /* .baseMipLevel = */ 0,
+ /* .levelCount = */ 1,
+ /* .baseArrayLayer = */ 0,
+ /* .layerCount = */ 1,
+ },
};
VkResult result;
@@ -332,13 +363,15 @@ VulkanOverlayRenderer::Buffer::Create(
LOG(FATAL) << "Failed to create a Vulkan image view.";
}
VkFramebufferCreateInfo vk_framebuffer_create_info = {
- .sType = VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
- .renderPass = vk_render_pass,
- .attachmentCount = 1,
- .pAttachments = &vk_image_view,
- .width = size.width(),
- .height = size.height(),
- .layers = 1,
+ /* .sType = */ VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
+ /* .pNext = */ nullptr,
+ /* .flags = */ 0,
+ /* .renderPass = */ vk_render_pass,
+ /* .attachmentCount = */ 1,
+ /* .pAttachments = */ &vk_image_view,
+ /* .width = */ size.width(),
+ /* .height = */ size.height(),
+ /* .layers = */ 1,
};
VkFramebuffer vk_framebuffer = VK_NULL_HANDLE;
diff --git a/chromium/ui/ozone/demo/vulkan_overlay_renderer.h b/chromium/ui/ozone/demo/vulkan_overlay_renderer.h
index 8a8a7c575ca..37b75125198 100644
--- a/chromium/ui/ozone/demo/vulkan_overlay_renderer.h
+++ b/chromium/ui/ozone/demo/vulkan_overlay_renderer.h
@@ -89,6 +89,7 @@ class VulkanOverlayRenderer : public RendererBase {
const VkFence fence_;
};
+ void DestroyRenderPass();
void DestroyBuffers();
void RecreateBuffers();
void RenderFrame();
@@ -111,7 +112,7 @@ class VulkanOverlayRenderer : public RendererBase {
std::unique_ptr<gpu::VulkanCommandPool> command_pool_;
std::unique_ptr<OverlaySurface> overlay_surface_;
- VkRenderPass render_pass_;
+ VkRenderPass render_pass_ = VK_NULL_HANDLE;
base::WeakPtrFactory<VulkanOverlayRenderer> weak_ptr_factory_;
diff --git a/chromium/ui/ozone/demo/vulkan_renderer.cc b/chromium/ui/ozone/demo/vulkan_renderer.cc
index 89cbc215b0c..9a69457e318 100644
--- a/chromium/ui/ozone/demo/vulkan_renderer.cc
+++ b/chromium/ui/ozone/demo/vulkan_renderer.cc
@@ -11,97 +11,196 @@
#include "base/trace_event/trace_event.h"
#include "gpu/vulkan/init/vulkan_factory.h"
#include "gpu/vulkan/vulkan_command_buffer.h"
+#include "gpu/vulkan/vulkan_command_pool.h"
#include "gpu/vulkan/vulkan_device_queue.h"
+#include "gpu/vulkan/vulkan_function_pointers.h"
#include "gpu/vulkan/vulkan_implementation.h"
-#include "gpu/vulkan/vulkan_render_pass.h"
#include "gpu/vulkan/vulkan_surface.h"
#include "gpu/vulkan/vulkan_swap_chain.h"
namespace ui {
-VulkanRenderer::VulkanRenderer(gpu::VulkanImplementation* vulkan_implementation,
+VulkanRenderer::VulkanRenderer(std::unique_ptr<gpu::VulkanSurface> surface,
+ gpu::VulkanImplementation* vulkan_implementation,
gfx::AcceleratedWidget widget,
const gfx::Size& size)
: RendererBase(widget, size),
vulkan_implementation_(vulkan_implementation),
+ surface_(std::move(surface)),
+ size_(size),
weak_ptr_factory_(this) {}
VulkanRenderer::~VulkanRenderer() {
- surface_->Finish();
- render_pass_->Destroy();
+ DestroyFramebuffers();
+ DestroyRenderPass();
surface_->Destroy();
surface_.reset();
+ command_pool_->Destroy();
+ command_pool_.reset();
device_queue_->Destroy();
device_queue_.reset();
}
bool VulkanRenderer::Initialize() {
+ TRACE_EVENT1("ozone", "VulkanRenderer::Initialize", "widget", widget_);
+
device_queue_ = gpu::CreateVulkanDeviceQueue(
vulkan_implementation_,
gpu::VulkanDeviceQueue::GRAPHICS_QUEUE_FLAG |
gpu::VulkanDeviceQueue::PRESENTATION_SUPPORT_QUEUE_FLAG);
- CHECK(device_queue_);
-
- surface_ = vulkan_implementation_->CreateViewSurface(widget_);
- if (!surface_)
- LOG(FATAL) << "Vulkan surface not supported by platform";
- CHECK(surface_->Initialize(device_queue_.get(),
- gpu::VulkanSurface::DEFAULT_SURFACE_FORMAT));
-
- gpu::VulkanRenderPass::RenderPassData render_pass_data;
-
- render_pass_data.attachments.resize(1);
- gpu::VulkanRenderPass::AttachmentData* attachment =
- &render_pass_data.attachments[0];
- attachment->attachment_type =
- gpu::VulkanRenderPass::AttachmentType::ATTACHMENT_TYPE_SWAP_IMAGE;
- attachment->sample_count = VK_SAMPLE_COUNT_1_BIT;
- attachment->load_op = VK_ATTACHMENT_LOAD_OP_CLEAR;
- attachment->store_op = VK_ATTACHMENT_STORE_OP_STORE;
- attachment->stencil_load_op = VK_ATTACHMENT_LOAD_OP_DONT_CARE;
- attachment->stencil_store_op = VK_ATTACHMENT_STORE_OP_DONT_CARE;
- attachment->start_layout =
- gpu::VulkanRenderPass::ImageLayoutType::IMAGE_LAYOUT_UNDEFINED;
- attachment->end_layout =
- gpu::VulkanRenderPass::ImageLayoutType::IMAGE_LAYOUT_TYPE_PRESENT;
-
- render_pass_data.subpass_datas.resize(1);
- gpu::VulkanRenderPass::SubpassData* subpass_data =
- &render_pass_data.subpass_datas[0];
-
- subpass_data->subpass_attachments.resize(1);
- gpu::VulkanRenderPass::SubpassAttachment* subpass_attachment =
- &subpass_data->subpass_attachments[0];
- subpass_attachment->attachment_index = 0;
- subpass_attachment->subpass_layout =
- gpu::VulkanRenderPass::ImageLayoutType::IMAGE_LAYOUT_TYPE_IMAGE_VIEW;
-
- gpu::VulkanSwapChain* swap_chain = surface_->GetSwapChain();
- CHECK(render_pass_data.ValidateData(swap_chain));
-
- render_pass_ = std::make_unique<gpu::VulkanRenderPass>(device_queue_.get());
- CHECK(render_pass_->Initialize(swap_chain, render_pass_data));
+ if (!device_queue_) {
+ LOG(FATAL) << "Failed to init device queue";
+ }
+
+ if (!surface_->Initialize(device_queue_.get(),
+ gpu::VulkanSurface::DEFAULT_SURFACE_FORMAT)) {
+ LOG(FATAL) << "Failed to init surface";
+ }
+
+ VkAttachmentDescription render_pass_attachments[] = {{
+ /* .flags = */ 0,
+ /* .format = */ surface_->surface_format().format,
+ /* .samples = */ VK_SAMPLE_COUNT_1_BIT,
+ /* .loadOp = */ VK_ATTACHMENT_LOAD_OP_CLEAR,
+ /* .storeOp = */ VK_ATTACHMENT_STORE_OP_STORE,
+ /* .stencilLoadOp = */ VK_ATTACHMENT_LOAD_OP_DONT_CARE,
+ /* .stencilStoreOp = */ VK_ATTACHMENT_STORE_OP_DONT_CARE,
+ /* .initialLayout = */ VK_IMAGE_LAYOUT_UNDEFINED,
+ /* .finalLayout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
+ }};
+
+ VkAttachmentReference color_attachment_references[] = {
+ {/* .attachment = */ 0,
+ /* .layout = */ VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL}};
+
+ VkSubpassDescription render_pass_subpasses[] = {{
+ /* .flags = */ 0,
+ /* .pipelineBindPoint = */ VK_PIPELINE_BIND_POINT_GRAPHICS,
+ /* .inputAttachmentCount = */ 0,
+ /* .pInputAttachments = */ nullptr,
+ /* .colorAttachmentCount = */ base::size(color_attachment_references),
+ /* .pColorAttachments = */ color_attachment_references,
+ /* .pResolveAttachments = */ nullptr,
+ /* .pDepthStencilAttachment = */ nullptr,
+ /* .preserveAttachmentCount = */ 0,
+ /* .pPreserveAttachments = */ nullptr,
+ }};
+
+ VkRenderPassCreateInfo render_pass_create_info = {
+ /* .sType = */ VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
+ /* .pNext = */ nullptr,
+ /* .flags = */ 0,
+ /* .attachmentCount = */ base::size(render_pass_attachments),
+ /* .pAttachments = */ render_pass_attachments,
+ /* .subpassCount = */ base::size(render_pass_subpasses),
+ /* .pSubpasses = */ render_pass_subpasses,
+ /* .dependencyCount = */ 0,
+ /* .pDependencies = */ nullptr,
+ };
+
+ CHECK_EQ(vkCreateRenderPass(device_queue_->GetVulkanDevice(),
+ &render_pass_create_info, nullptr, &render_pass_),
+ VK_SUCCESS);
+
+ command_pool_ = std::make_unique<gpu::VulkanCommandPool>(device_queue_.get());
+ CHECK(command_pool_->Initialize());
+
+ RecreateFramebuffers();
// Schedule the initial render.
PostRenderFrameTask();
return true;
}
+void VulkanRenderer::DestroyRenderPass() {
+ if (render_pass_ == VK_NULL_HANDLE)
+ return;
+
+ vkDestroyRenderPass(device_queue_->GetVulkanDevice(), render_pass_, nullptr);
+ render_pass_ = VK_NULL_HANDLE;
+}
+
+void VulkanRenderer::DestroyFramebuffers() {
+ VkDevice vk_device = device_queue_->GetVulkanDevice();
+
+ VkResult result = vkQueueWaitIdle(device_queue_->GetVulkanQueue());
+ CHECK_EQ(result, VK_SUCCESS);
+
+ for (std::unique_ptr<Framebuffer>& framebuffer : framebuffers_) {
+ if (!framebuffer)
+ continue;
+
+ framebuffer->command_buffer()->Destroy();
+ vkDestroyFramebuffer(vk_device, framebuffer->vk_framebuffer(), nullptr);
+ vkDestroyImageView(vk_device, framebuffer->vk_image_view(), nullptr);
+ framebuffer.reset();
+ }
+}
+
+void VulkanRenderer::RecreateFramebuffers() {
+ TRACE_EVENT0("ozone", "VulkanRenderer::RecreateFramebuffers");
+
+ DestroyFramebuffers();
+
+ surface_->SetSize(size_);
+
+ gpu::VulkanSwapChain* vulkan_swap_chain = surface_->GetSwapChain();
+ const uint32_t num_images = vulkan_swap_chain->num_images();
+ framebuffers_.resize(num_images);
+
+ for (uint32_t image = 0; image < num_images; ++image) {
+ framebuffers_[image] =
+ Framebuffer::Create(device_queue_.get(), command_pool_.get(),
+ render_pass_, surface_.get(), image);
+ CHECK(framebuffers_[image]);
+ }
+}
+
void VulkanRenderer::RenderFrame() {
TRACE_EVENT0("ozone", "VulkanRenderer::RenderFrame");
- VkClearValue clear_value = {.color = {{.5f, 1.f - NextFraction(), .5f, 1.f}}};
- render_pass_->SetClearValue(0, clear_value);
+ VkClearValue clear_value = {
+ /* .color = */ {/* .float32 = */ {.5f, 1.f - NextFraction(), .5f, 1.f}}};
+
+ gpu::VulkanSwapChain* vulkan_swap_chain = surface_->GetSwapChain();
+ const uint32_t image = vulkan_swap_chain->current_image();
+ const Framebuffer& framebuffer = *framebuffers_[image];
+
+ gpu::VulkanCommandBuffer& command_buffer = *framebuffer.command_buffer();
- gpu::VulkanCommandBuffer* command_buffer =
- surface_->GetSwapChain()->GetCurrentCommandBuffer();
{
- gpu::ScopedSingleUseCommandBufferRecorder recorder(*command_buffer);
- render_pass_->BeginRenderPass(recorder, true);
- render_pass_->EndRenderPass(recorder);
+ gpu::ScopedSingleUseCommandBufferRecorder recorder(command_buffer);
+
+ VkRenderPassBeginInfo begin_info = {
+ /* .sType = */ VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
+ /* .pNext = */ nullptr,
+ /* .renderPass = */ render_pass_,
+ /* .framebuffer = */ framebuffer.vk_framebuffer(),
+ /* .renderArea = */
+ {
+ /* .offset = */ {
+ /* .x = */ 0,
+ /* .y = */ 0,
+ },
+ /* .extent = */
+ {
+ /* .width = */ vulkan_swap_chain->size().width(),
+ /* .height = */ vulkan_swap_chain->size().height(),
+ },
+ },
+ /* .clearValueCount = */ 1,
+ /* .pClearValues = */ &clear_value,
+ };
+
+ vkCmdBeginRenderPass(recorder.handle(), &begin_info,
+ VK_SUBPASS_CONTENTS_INLINE);
+
+ vkCmdEndRenderPass(recorder.handle());
}
- CHECK_EQ(surface_->SwapBuffers(), gfx::SwapResult::SWAP_ACK);
+ CHECK(command_buffer.Submit(0, nullptr, 0, nullptr));
+
+ vulkan_swap_chain->SwapBuffers();
PostRenderFrameTask();
}
@@ -112,4 +211,80 @@ void VulkanRenderer::PostRenderFrameTask() {
weak_ptr_factory_.GetWeakPtr()));
}
+VulkanRenderer::Framebuffer::Framebuffer(
+ VkImageView vk_image_view,
+ VkFramebuffer vk_framebuffer,
+ std::unique_ptr<gpu::VulkanCommandBuffer> command_buffer)
+ : vk_image_view_(vk_image_view),
+ vk_framebuffer_(vk_framebuffer),
+ command_buffer_(std::move(command_buffer)) {}
+
+VulkanRenderer::Framebuffer::~Framebuffer() {}
+
+std::unique_ptr<VulkanRenderer::Framebuffer>
+VulkanRenderer::Framebuffer::Create(gpu::VulkanDeviceQueue* vulkan_device_queue,
+ gpu::VulkanCommandPool* vulkan_command_pool,
+ VkRenderPass vk_render_pass,
+ gpu::VulkanSurface* vulkan_surface,
+ uint32_t vulkan_swap_chain_image_index) {
+ gpu::VulkanSwapChain* vulkan_swap_chain = vulkan_surface->GetSwapChain();
+ const VkDevice vk_device = vulkan_device_queue->GetVulkanDevice();
+ VkImageViewCreateInfo vk_image_view_create_info = {
+ /* .sType = */ VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
+ /* .pNext = */ nullptr,
+ /* .flags = */ 0,
+ /* .image = */ vulkan_swap_chain->GetImage(vulkan_swap_chain_image_index),
+ /* .viewType = */ VK_IMAGE_VIEW_TYPE_2D,
+ /* .format = */ vulkan_surface->surface_format().format,
+ /* .components = */
+ {
+ /* .r = */ VK_COMPONENT_SWIZZLE_IDENTITY,
+ /* .b = */ VK_COMPONENT_SWIZZLE_IDENTITY,
+ /* .g = */ VK_COMPONENT_SWIZZLE_IDENTITY,
+ /* .a = */ VK_COMPONENT_SWIZZLE_IDENTITY,
+ },
+ /* .subresourceRange = */
+ {
+ /* .aspectMask = */ VK_IMAGE_ASPECT_COLOR_BIT,
+ /* .baseMipLevel = */ 0,
+ /* .levelCount = */ 1,
+ /* .baseArrayLayer = */ 0,
+ /* .layerCount = */ 1,
+ },
+ };
+
+ VkResult result;
+ VkImageView vk_image_view = VK_NULL_HANDLE;
+ result = vkCreateImageView(vk_device, &vk_image_view_create_info, nullptr,
+ &vk_image_view);
+ if (result != VK_SUCCESS) {
+ LOG(FATAL) << "Failed to create a Vulkan image view.";
+ }
+ VkFramebufferCreateInfo vk_framebuffer_create_info = {
+ /* .sType = */ VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
+ /* .pNext = */ nullptr,
+ /* .flags = */ 0,
+ /* .renderPass = */ vk_render_pass,
+ /* .attachmentCount = */ 1,
+ /* .pAttachments = */ &vk_image_view,
+ /* .width = */ vulkan_swap_chain->size().width(),
+ /* .height = */ vulkan_swap_chain->size().height(),
+ /* .layers = */ 1,
+ };
+
+ VkFramebuffer vk_framebuffer = VK_NULL_HANDLE;
+ result = vkCreateFramebuffer(vk_device, &vk_framebuffer_create_info, nullptr,
+ &vk_framebuffer);
+ if (result != VK_SUCCESS) {
+ LOG(FATAL) << "Failed to create a Vulkan framebuffer.";
+ }
+
+ auto command_buffer = std::make_unique<gpu::VulkanCommandBuffer>(
+ vulkan_device_queue, vulkan_command_pool, true /* primary */);
+ CHECK(command_buffer->Initialize());
+
+ return std::make_unique<VulkanRenderer::Framebuffer>(
+ vk_image_view, vk_framebuffer, std::move(command_buffer));
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/demo/vulkan_renderer.h b/chromium/ui/ozone/demo/vulkan_renderer.h
index f372affc550..cd7e6554a9a 100644
--- a/chromium/ui/ozone/demo/vulkan_renderer.h
+++ b/chromium/ui/ozone/demo/vulkan_renderer.h
@@ -5,16 +5,21 @@
#ifndef UI_OZONE_DEMO_VULKAN_RENDERER_H_
#define UI_OZONE_DEMO_VULKAN_RENDERER_H_
+#include <vulkan/vulkan.h>
+
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
+#include "ui/gfx/buffer_types.h"
+#include "ui/gfx/presentation_feedback.h"
#include "ui/gfx/swap_result.h"
#include "ui/ozone/demo/renderer_base.h"
namespace gpu {
class VulkanDeviceQueue;
class VulkanImplementation;
-class VulkanRenderPass;
+class VulkanCommandBuffer;
+class VulkanCommandPool;
class VulkanSurface;
} // namespace gpu
@@ -22,7 +27,8 @@ namespace ui {
class VulkanRenderer : public RendererBase {
public:
- VulkanRenderer(gpu::VulkanImplementation* vulkan_instance,
+ VulkanRenderer(std::unique_ptr<gpu::VulkanSurface> surface,
+ gpu::VulkanImplementation* vulkan_instance,
gfx::AcceleratedWidget widget,
const gfx::Size& size);
~VulkanRenderer() override;
@@ -31,13 +37,47 @@ class VulkanRenderer : public RendererBase {
bool Initialize() override;
private:
+ class Framebuffer {
+ public:
+ Framebuffer(VkImageView vk_image_view,
+ VkFramebuffer vk_framebuffer,
+ std::unique_ptr<gpu::VulkanCommandBuffer> command_buffer);
+ ~Framebuffer();
+
+ static std::unique_ptr<Framebuffer> Create(
+ gpu::VulkanDeviceQueue* vulkan_device_queue,
+ gpu::VulkanCommandPool* vulkan_command_pool,
+ VkRenderPass vk_render_pass,
+ gpu::VulkanSurface* vulkan_surface,
+ uint32_t vulkan_swap_chain_image_index);
+
+ VkImageView vk_image_view() const { return vk_image_view_; }
+ VkFramebuffer vk_framebuffer() const { return vk_framebuffer_; }
+ gpu::VulkanCommandBuffer* command_buffer() const {
+ return command_buffer_.get();
+ }
+
+ private:
+ const VkImageView vk_image_view_;
+ const VkFramebuffer vk_framebuffer_;
+ const std::unique_ptr<gpu::VulkanCommandBuffer> command_buffer_;
+ };
+
+ void DestroyRenderPass();
+ void DestroyFramebuffers();
+ void RecreateFramebuffers();
void RenderFrame();
void PostRenderFrameTask();
+ std::vector<std::unique_ptr<Framebuffer>> framebuffers_;
+
gpu::VulkanImplementation* const vulkan_implementation_;
std::unique_ptr<gpu::VulkanDeviceQueue> device_queue_;
+ std::unique_ptr<gpu::VulkanCommandPool> command_pool_;
std::unique_ptr<gpu::VulkanSurface> surface_;
- std::unique_ptr<gpu::VulkanRenderPass> render_pass_;
+ gfx::Size size_;
+
+ VkRenderPass render_pass_ = VK_NULL_HANDLE;
base::WeakPtrFactory<VulkanRenderer> weak_ptr_factory_;
diff --git a/chromium/ui/ozone/platform/drm/BUILD.gn b/chromium/ui/ozone/platform/drm/BUILD.gn
index 832a6c00ead..e1bfe916873 100644
--- a/chromium/ui/ozone/platform/drm/BUILD.gn
+++ b/chromium/ui/ozone/platform/drm/BUILD.gn
@@ -26,10 +26,6 @@ source_set("gbm") {
"common/scoped_drm_types.h",
"gpu/crtc_controller.cc",
"gpu/crtc_controller.h",
- "gpu/drm_buffer.cc",
- "gpu/drm_buffer.h",
- "gpu/drm_console_buffer.cc",
- "gpu/drm_console_buffer.h",
"gpu/drm_device.cc",
"gpu/drm_device.h",
"gpu/drm_device_generator.cc",
@@ -38,6 +34,8 @@ source_set("gbm") {
"gpu/drm_device_manager.h",
"gpu/drm_display.cc",
"gpu/drm_display.h",
+ "gpu/drm_dumb_buffer.cc",
+ "gpu/drm_dumb_buffer.h",
"gpu/drm_framebuffer.cc",
"gpu/drm_framebuffer.h",
"gpu/drm_gpu_display_manager.cc",
@@ -54,8 +52,6 @@ source_set("gbm") {
"gpu/drm_thread_message_proxy.h",
"gpu/drm_thread_proxy.cc",
"gpu/drm_thread_proxy.h",
- "gpu/drm_vsync_provider.cc",
- "gpu/drm_vsync_provider.h",
"gpu/drm_window.cc",
"gpu/drm_window.h",
"gpu/drm_window_proxy.cc",
@@ -64,8 +60,6 @@ source_set("gbm") {
"gpu/gbm_overlay_surface.h",
"gpu/gbm_pixmap.cc",
"gpu/gbm_pixmap.h",
- "gpu/gbm_surface.cc",
- "gpu/gbm_surface.h",
"gpu/gbm_surface_factory.cc",
"gpu/gbm_surface_factory.h",
"gpu/gbm_surfaceless.cc",
diff --git a/chromium/ui/ozone/platform/drm/gpu/crtc_controller.cc b/chromium/ui/ozone/platform/drm/gpu/crtc_controller.cc
index 3c0dc26eee0..aea5c918d4d 100644
--- a/chromium/ui/ozone/platform/drm/gpu/crtc_controller.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/crtc_controller.cc
@@ -7,8 +7,8 @@
#include "base/logging.h"
#include "base/time/time.h"
#include "ui/gfx/presentation_feedback.h"
-#include "ui/ozone/platform/drm/gpu/drm_buffer.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h"
+#include "ui/ozone/platform/drm/gpu/drm_dumb_buffer.h"
#include "ui/ozone/platform/drm/gpu/drm_framebuffer.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane.h"
#include "ui/ozone/platform/drm/gpu/page_flip_request.h"
@@ -53,6 +53,12 @@ bool CrtcController::Modeset(const DrmOverlayPlane& plane,
mode_ = mode;
is_disabled_ = false;
+ // Hold modeset buffer until page flip. This fixes a crash on entering
+ // hardware mirror mode in some circumstances (bug 888553).
+ // TODO(spang): Fix this better by changing how mirrors are set up (bug
+ // 899352).
+ modeset_framebuffer_ = plane.buffer;
+
return true;
}
@@ -107,6 +113,10 @@ void CrtcController::MoveCursor(const gfx::Point& location) {
drm_->MoveCursor(crtc_, location);
}
+void CrtcController::OnPageFlipComplete() {
+ modeset_framebuffer_ = nullptr;
+}
+
void CrtcController::DisableCursor() {
if (!drm_->SetCursor(crtc_, 0, gfx::Size())) {
PLOG(ERROR) << "drmModeSetCursor: device " << drm_->device_path().value()
diff --git a/chromium/ui/ozone/platform/drm/gpu/crtc_controller.h b/chromium/ui/ozone/platform/drm/gpu/crtc_controller.h
index b0162614eef..670ed0dd41c 100644
--- a/chromium/ui/ozone/platform/drm/gpu/crtc_controller.h
+++ b/chromium/ui/ozone/platform/drm/gpu/crtc_controller.h
@@ -20,7 +20,6 @@
namespace ui {
-class DrmBuffer;
class DrmDevice;
// Wrapper around a CRTC.
@@ -64,18 +63,22 @@ class CrtcController {
void SetCursor(uint32_t handle, const gfx::Size& size);
void MoveCursor(const gfx::Point& location);
+ void OnPageFlipComplete();
+
private:
void DisableCursor();
const scoped_refptr<DrmDevice> drm_;
- uint32_t crtc_;
+ const uint32_t crtc_;
// TODO(dnicoara) Add support for hardware mirroring (multiple connectors).
- uint32_t connector_;
+ const uint32_t connector_;
drmModeModeInfo mode_ = {};
+ scoped_refptr<DrmFramebuffer> modeset_framebuffer_;
+
// Keeps track of the CRTC state. If a surface has been bound, then the value
// is set to false. Otherwise it is true.
bool is_disabled_ = true;
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_buffer.cc b/chromium/ui/ozone/platform/drm/gpu/drm_buffer.cc
deleted file mode 100644
index 63f53ee3822..00000000000
--- a/chromium/ui/ozone/platform/drm/gpu/drm_buffer.cc
+++ /dev/null
@@ -1,64 +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/ozone/platform/drm/gpu/drm_buffer.h"
-
-#include <drm_fourcc.h>
-
-#include "base/logging.h"
-#include "third_party/skia/include/core/SkSurface.h"
-#include "ui/ozone/platform/drm/gpu/drm_device.h"
-
-namespace ui {
-
-namespace {
-
-} // namespace
-
-DrmBuffer::DrmBuffer(const scoped_refptr<DrmDevice>& drm) : drm_(drm) {
-}
-
-DrmBuffer::~DrmBuffer() {
- if (mmap_base_ && !drm_->UnmapDumbBuffer(mmap_base_, mmap_size_))
- PLOG(ERROR) << "DrmBuffer: UnmapDumbBuffer: handle " << handle_;
-
- if (handle_ && !drm_->DestroyDumbBuffer(handle_))
- PLOG(ERROR) << "DrmBuffer: DestroyDumbBuffer: handle " << handle_;
-}
-
-bool DrmBuffer::Initialize(const SkImageInfo& info) {
- if (!drm_->CreateDumbBuffer(info, &handle_, &stride_)) {
- PLOG(ERROR) << "DrmBuffer: CreateDumbBuffer: width " << info.width()
- << " height " << info.height();
- return false;
- }
-
- mmap_size_ = info.computeByteSize(stride_);
- if (!drm_->MapDumbBuffer(handle_, mmap_size_, &mmap_base_)) {
- PLOG(ERROR) << "DrmBuffer: MapDumbBuffer: handle " << handle_;
- return false;
- }
-
- surface_ = SkSurface::MakeRasterDirect(info, mmap_base_, stride_);
- if (!surface_) {
- LOG(ERROR) << "DrmBuffer: Failed to create SkSurface: handle " << handle_;
- return false;
- }
-
- return true;
-}
-
-SkCanvas* DrmBuffer::GetCanvas() const {
- return surface_->getCanvas();
-}
-
-uint32_t DrmBuffer::GetHandle() const {
- return handle_;
-}
-
-gfx::Size DrmBuffer::GetSize() const {
- return gfx::Size(surface_->width(), surface_->height());
-}
-
-} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_console_buffer.cc b/chromium/ui/ozone/platform/drm/gpu/drm_console_buffer.cc
deleted file mode 100644
index 05b7f129610..00000000000
--- a/chromium/ui/ozone/platform/drm/gpu/drm_console_buffer.cc
+++ /dev/null
@@ -1,53 +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/ozone/platform/drm/gpu/drm_console_buffer.h"
-
-#include <sys/mman.h>
-#include <xf86drmMode.h>
-
-#include "ui/ozone/platform/drm/common/scoped_drm_types.h"
-#include "ui/ozone/platform/drm/gpu/drm_device.h"
-
-namespace ui {
-
-DrmConsoleBuffer::DrmConsoleBuffer(const scoped_refptr<DrmDevice>& drm,
- uint32_t framebuffer)
- : drm_(drm), framebuffer_(framebuffer) {
-}
-
-DrmConsoleBuffer::~DrmConsoleBuffer() {
- if (mmap_base_)
- if (munmap(mmap_base_, mmap_size_))
- PLOG(ERROR) << "munmap";
-
- if (handle_ && !drm_->CloseBufferHandle(handle_))
- PLOG(ERROR) << "DrmConsoleBuffer: CloseBufferHandle: handle " << handle_;
-}
-
-bool DrmConsoleBuffer::Initialize() {
- ScopedDrmFramebufferPtr fb(drm_->GetFramebuffer(framebuffer_));
-
- if (!fb)
- return false;
-
- handle_ = fb->handle;
- stride_ = fb->pitch;
- SkImageInfo info = SkImageInfo::MakeN32Premul(fb->width, fb->height);
-
- mmap_size_ = info.computeByteSize(stride_);
-
- if (!drm_->MapDumbBuffer(fb->handle, mmap_size_, &mmap_base_)) {
- mmap_base_ = NULL;
- return false;
- }
-
- surface_ = SkSurface::MakeRasterDirect(info, mmap_base_, stride_);
- if (!surface_)
- return false;
-
- return true;
-}
-
-} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_console_buffer.h b/chromium/ui/ozone/platform/drm/gpu/drm_console_buffer.h
deleted file mode 100644
index 2c432930e27..00000000000
--- a/chromium/ui/ozone/platform/drm/gpu/drm_console_buffer.h
+++ /dev/null
@@ -1,63 +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_OZONE_PLATFORM_DRM_GPU_DRM_CONSOLE_BUFFER_H_
-#define UI_OZONE_PLATFORM_DRM_GPU_DRM_CONSOLE_BUFFER_H_
-
-#include <stddef.h>
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "third_party/skia/include/core/SkImage.h"
-#include "third_party/skia/include/core/SkSurface.h"
-
-class SkCanvas;
-
-namespace ui {
-
-class DrmDevice;
-
-// Wrapper for the console buffer. This is the buffer that is allocated by
-// default by the system and is used when no application is controlling the
-// CRTC. Keeps track of the native properties of the buffer and wraps the pixel
-// memory into a SkSurface which can be used to draw into using Skia.
-class DrmConsoleBuffer {
- public:
- DrmConsoleBuffer(const scoped_refptr<DrmDevice>& drm, uint32_t framebuffer);
- ~DrmConsoleBuffer();
-
- SkCanvas* canvas() { return surface_->getCanvas(); }
- sk_sp<SkImage> image() { return surface_->makeImageSnapshot(); }
-
- // Memory map the backing pixels and wrap them in |surface_|.
- bool Initialize();
-
- protected:
- scoped_refptr<DrmDevice> drm_;
-
- // Wrapper around the native pixel memory.
- sk_sp<SkSurface> surface_;
-
- // Length of a row of pixels.
- uint32_t stride_ = 0;
-
- // Buffer handle used by the DRM allocator.
- uint32_t handle_ = 0;
-
- // Buffer ID used by the DRM modesettings API.
- uint32_t framebuffer_ = 0;
-
- // Memory map base address.
- void* mmap_base_ = nullptr;
-
- // Memory map size.
- size_t mmap_size_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(DrmConsoleBuffer);
-};
-
-} // namespace ui
-
-#endif // UI_OZONE_PLATFORM_DRM_GPU_DRM_CONSOLE_BUFFER_H_
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_device.cc b/chromium/ui/ozone/platform/drm/gpu/drm_device.cc
index 5b737f6d44a..f555f84c1a8 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_device.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_device.cc
@@ -260,10 +260,10 @@ bool DrmDevice::Initialize() {
// Use atomic only if kernel allows it.
is_atomic_ = SetCapability(DRM_CLIENT_CAP_ATOMIC, 1);
if (is_atomic_)
- plane_manager_.reset(new HardwareDisplayPlaneManagerAtomic());
+ plane_manager_.reset(new HardwareDisplayPlaneManagerAtomic(this));
else
- plane_manager_.reset(new HardwareDisplayPlaneManagerLegacy());
- if (!plane_manager_->Initialize(this)) {
+ plane_manager_.reset(new HardwareDisplayPlaneManagerLegacy(this));
+ if (!plane_manager_->Initialize()) {
LOG(ERROR) << "Failed to initialize the plane manager for "
<< device_path_.value();
plane_manager_.reset();
@@ -384,20 +384,6 @@ bool DrmDevice::PageFlip(uint32_t crtc_id,
return false;
}
-bool DrmDevice::PageFlipOverlay(uint32_t crtc_id,
- uint32_t framebuffer,
- const gfx::Rect& location,
- const gfx::Rect& source,
- int overlay_plane) {
- DCHECK(file_.IsValid());
- TRACE_EVENT2("drm", "DrmDevice::PageFlipOverlay", "crtc", crtc_id,
- "framebuffer", framebuffer);
- return !drmModeSetPlane(file_.GetPlatformFile(), overlay_plane, crtc_id,
- framebuffer, 0, location.x(), location.y(),
- location.width(), location.height(), source.x(),
- source.y(), source.width(), source.height());
-}
-
ScopedDrmFramebufferPtr DrmDevice::GetFramebuffer(uint32_t framebuffer) {
DCHECK(file_.IsValid());
TRACE_EVENT1("drm", "DrmDevice::GetFramebuffer", "framebuffer", framebuffer);
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_device.h b/chromium/ui/ozone/platform/drm/gpu/drm_device.h
index 1e3cfcef247..1e62f1891c9 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_device.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_device.h
@@ -147,15 +147,6 @@ class DrmDevice : public base::RefCountedThreadSafe<DrmDevice> {
uint32_t framebuffer,
scoped_refptr<PageFlipRequest> page_flip_request);
- // Schedule an overlay to be show during the page flip for CRTC |crtc_id|.
- // |source| location from |framebuffer| will be shown on overlay
- // |overlay_plane|, in the bounds specified by |location| on the screen.
- virtual bool PageFlipOverlay(uint32_t crtc_id,
- uint32_t framebuffer,
- const gfx::Rect& location,
- const gfx::Rect& source,
- int overlay_plane);
-
// Returns the list of all planes available on this DRM device.
virtual ScopedDrmPlaneResPtr GetPlaneResources();
@@ -266,20 +257,20 @@ class DrmDevice : public base::RefCountedThreadSafe<DrmDevice> {
const base::FilePath device_path_;
// DRM device.
- base::File file_;
+ const base::File file_;
std::unique_ptr<PageFlipManager> page_flip_manager_;
// Watcher for |fd_| listening for page flip events.
std::unique_ptr<IOWatcher> watcher_;
- bool is_primary_device_;
+ const bool is_primary_device_;
bool is_atomic_ = false;
bool allow_addfb2_modifiers_ = false;
- std::unique_ptr<GbmDevice> gbm_;
+ const std::unique_ptr<GbmDevice> gbm_;
DISALLOW_COPY_AND_ASSIGN(DrmDevice);
};
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_device_manager.cc b/chromium/ui/ozone/platform/drm/gpu/drm_device_manager.cc
index b165fe18be9..6b3214aad24 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_device_manager.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_device_manager.cc
@@ -54,8 +54,10 @@ bool DrmDeviceManager::AddDrmDevice(const base::FilePath& path,
return false;
}
- if (!primary_device_)
+ if (!primary_device_) {
+ VLOG(1) << "Primary DRM device added: " << path;
primary_device_ = device;
+ }
devices_.push_back(device);
return true;
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_device_manager.h b/chromium/ui/ozone/platform/drm/gpu/drm_device_manager.h
index f780063fb9e..f34170a3f58 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_device_manager.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_device_manager.h
@@ -50,7 +50,7 @@ class DrmDeviceManager {
const DrmDeviceVector& GetDrmDevices() const;
private:
- std::unique_ptr<DrmDeviceGenerator> drm_device_generator_;
+ const std::unique_ptr<DrmDeviceGenerator> drm_device_generator_;
DrmDeviceVector devices_;
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_display.h b/chromium/ui/ozone/platform/drm/gpu/drm_display.h
index b7ad5bde172..2ffc4d2e235 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_display.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_display.h
@@ -57,7 +57,7 @@ class DrmDisplay {
ScreenManager* screen_manager_; // Not owned.
int64_t display_id_ = -1;
- scoped_refptr<DrmDevice> drm_;
+ const scoped_refptr<DrmDevice> drm_;
uint32_t crtc_ = 0;
uint32_t connector_ = 0;
std::vector<drmModeModeInfo> modes_;
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_dumb_buffer.cc b/chromium/ui/ozone/platform/drm/gpu/drm_dumb_buffer.cc
new file mode 100644
index 00000000000..889fca40606
--- /dev/null
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_dumb_buffer.cc
@@ -0,0 +1,101 @@
+// 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/ozone/platform/drm/gpu/drm_dumb_buffer.h"
+
+#include <drm_fourcc.h>
+#include <xf86drmMode.h>
+
+#include "base/logging.h"
+#include "third_party/skia/include/core/SkSurface.h"
+#include "ui/ozone/platform/drm/gpu/drm_device.h"
+
+namespace ui {
+
+namespace {
+
+bool DestroyDumbBuffer(const scoped_refptr<DrmDevice>& drm_device,
+ uint32_t handle,
+ DrmDumbBuffer::HandleCloser handle_closer) {
+ switch (handle_closer) {
+ case DrmDumbBuffer::HandleCloser::DESTROY_DUMB:
+ return drm_device->DestroyDumbBuffer(handle);
+ case DrmDumbBuffer::HandleCloser::GEM_CLOSE:
+ return drm_device->CloseBufferHandle(handle);
+ }
+}
+
+} // namespace
+
+DrmDumbBuffer::DrmDumbBuffer(const scoped_refptr<DrmDevice>& drm) : drm_(drm) {}
+
+DrmDumbBuffer::~DrmDumbBuffer() {
+ if (mmap_base_ && !drm_->UnmapDumbBuffer(mmap_base_, mmap_size_))
+ PLOG(ERROR) << "DrmDumbBuffer: UnmapDumbBuffer: handle " << handle_;
+
+ if (handle_ && !DestroyDumbBuffer(drm_, handle_, handle_closer_))
+ PLOG(ERROR) << "DrmDumbBuffer: DestroyDumbBuffer: handle " << handle_;
+}
+
+bool DrmDumbBuffer::Initialize(const SkImageInfo& info) {
+ DCHECK(!handle_);
+
+ if (!drm_->CreateDumbBuffer(info, &handle_, &stride_)) {
+ PLOG(ERROR) << "DrmDumbBuffer: CreateDumbBuffer: width " << info.width()
+ << " height " << info.height();
+ return false;
+ }
+
+ handle_closer_ = HandleCloser::DESTROY_DUMB;
+
+ return MapDumbBuffer(info);
+}
+
+bool DrmDumbBuffer::InitializeFromFramebuffer(uint32_t framebuffer_id) {
+ DCHECK(!handle_);
+
+ ScopedDrmFramebufferPtr framebuffer(drm_->GetFramebuffer(framebuffer_id));
+ if (!framebuffer)
+ return false;
+
+ handle_ = framebuffer->handle;
+ stride_ = framebuffer->pitch;
+ SkImageInfo info =
+ SkImageInfo::MakeN32Premul(framebuffer->width, framebuffer->height);
+
+ handle_closer_ = HandleCloser::GEM_CLOSE;
+
+ return MapDumbBuffer(info);
+}
+
+SkCanvas* DrmDumbBuffer::GetCanvas() const {
+ return surface_->getCanvas();
+}
+
+uint32_t DrmDumbBuffer::GetHandle() const {
+ return handle_;
+}
+
+gfx::Size DrmDumbBuffer::GetSize() const {
+ return gfx::Size(surface_->width(), surface_->height());
+}
+
+bool DrmDumbBuffer::MapDumbBuffer(const SkImageInfo& info) {
+ mmap_size_ = info.computeByteSize(stride_);
+ if (!drm_->MapDumbBuffer(handle_, mmap_size_, &mmap_base_)) {
+ PLOG(ERROR) << "DrmDumbBuffer: MapDumbBuffer: handle " << handle_;
+ return false;
+ }
+
+ surface_ = SkSurface::MakeRasterDirect(info, mmap_base_, stride_);
+ if (!surface_) {
+ LOG(ERROR) << "DrmDumbBuffer: Failed to create SkSurface: handle "
+ << handle_;
+ return false;
+ }
+
+ return true;
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_buffer.h b/chromium/ui/ozone/platform/drm/gpu/drm_dumb_buffer.h
index 233bf14fd80..689ffb14e02 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_buffer.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_dumb_buffer.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_OZONE_PLATFORM_DRM_GPU_DRM_BUFFER_H_
-#define UI_OZONE_PLATFORM_DRM_GPU_DRM_BUFFER_H_
+#ifndef UI_OZONE_PLATFORM_DRM_GPU_DRM_DUMB_BUFFER_H_
+#define UI_OZONE_PLATFORM_DRM_GPU_DRM_DUMB_BUFFER_H_
#include <stddef.h>
#include <stdint.h>
@@ -23,22 +23,33 @@ class DrmDevice;
// Wrapper for a DRM allocated buffer. Keeps track of the native properties of
// the buffer and wraps the pixel memory into a SkSurface which can be used to
// draw into using Skia.
-class DrmBuffer {
+class DrmDumbBuffer {
public:
- DrmBuffer(const scoped_refptr<DrmDevice>& drm);
- ~DrmBuffer();
+ enum class HandleCloser {
+ DESTROY_DUMB,
+ GEM_CLOSE,
+ };
- // Allocates the backing pixels and wraps them in |surface_|. |info| is used
- // to describe the buffer characteristics (size, color format).
+ DrmDumbBuffer(const scoped_refptr<DrmDevice>& drm);
+ ~DrmDumbBuffer();
+
+ // Allocates a new dumb buffer, maps it, and wraps it in an SkSurface.
+ // |info| determines the buffer characteristics (size, color format).
bool Initialize(const SkImageInfo& info);
+ // Imports an existing framebuffer, maps it, and wraps it in an SkSurface.
+ bool InitializeFromFramebuffer(uint32_t framebuffer_id);
+
SkCanvas* GetCanvas() const;
+ SkSurface* surface() const { return surface_.get(); }
uint32_t GetHandle() const;
gfx::Size GetSize() const;
uint32_t stride() const { return stride_; }
- protected:
+ private:
+ bool MapDumbBuffer(const SkImageInfo& info);
+
const scoped_refptr<DrmDevice> drm_;
// Length of a row of pixels.
@@ -47,6 +58,9 @@ class DrmBuffer {
// Buffer handle used by the DRM allocator.
uint32_t handle_ = 0;
+ // Method of closing |handle_|.
+ HandleCloser handle_closer_ = HandleCloser::DESTROY_DUMB;
+
// Base address for memory mapping.
void* mmap_base_ = 0;
@@ -56,9 +70,9 @@ class DrmBuffer {
// Wrapper around the native pixel memory.
sk_sp<SkSurface> surface_;
- DISALLOW_COPY_AND_ASSIGN(DrmBuffer);
+ DISALLOW_COPY_AND_ASSIGN(DrmDumbBuffer);
};
} // namespace ui
-#endif // UI_OZONE_PLATFORM_DRM_GPU_DRM_BUFFER_H_
+#endif // UI_OZONE_PLATFORM_DRM_GPU_DRM_DUMB_BUFFER_H_
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_framebuffer.h b/chromium/ui/ozone/platform/drm/gpu/drm_framebuffer.h
index bb5e6e34b0b..bf8831a9c76 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_framebuffer.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_framebuffer.h
@@ -80,17 +80,17 @@ class DrmFramebuffer : public base::RefCountedThreadSafe<DrmFramebuffer> {
private:
~DrmFramebuffer();
- scoped_refptr<DrmDevice> drm_device_;
+ const scoped_refptr<DrmDevice> drm_device_;
- uint32_t framebuffer_id_ = 0;
- uint32_t framebuffer_pixel_format_ = 0;
+ const uint32_t framebuffer_id_;
+ const uint32_t framebuffer_pixel_format_;
// If |opaque_framebuffer_pixel_format_| differs from
// |framebuffer_pixel_format_| the following member is set to a valid fb,
// otherwise it is set to 0.
- uint32_t opaque_framebuffer_id_ = 0;
- uint32_t opaque_framebuffer_pixel_format_ = 0;
- uint64_t format_modifier_ = 0;
- gfx::Size size_;
+ const uint32_t opaque_framebuffer_id_;
+ const uint32_t opaque_framebuffer_pixel_format_;
+ const uint64_t format_modifier_;
+ const gfx::Size size_;
friend class base::RefCountedThreadSafe<DrmFramebuffer>;
};
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h b/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h
index ccfbd9f412b..25ae9a0b919 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h
@@ -67,8 +67,8 @@ class DrmGpuDisplayManager {
const std::vector<std::unique_ptr<DrmDisplay>>& new_displays,
const std::vector<std::unique_ptr<DrmDisplay>>& old_displays) const;
- ScreenManager* screen_manager_; // Not owned.
- DrmDeviceManager* drm_device_manager_; // Not owned.
+ ScreenManager* const screen_manager_; // Not owned.
+ DrmDeviceManager* const drm_device_manager_; // Not owned.
std::vector<std::unique_ptr<DrmDisplay>> displays_;
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.h b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.h
index 50306509785..0d7bbdaabf5 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_overlay_validator.h
@@ -27,7 +27,7 @@ class DrmOverlayValidator {
const DrmOverlayPlaneList& last_used_planes);
private:
- DrmWindow* window_; // Not owned.
+ DrmWindow* const window_; // Not owned.
DISALLOW_COPY_AND_ASSIGN(DrmOverlayValidator);
};
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 c2a99d74911..7aa42855b80 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
@@ -115,9 +115,9 @@ void DrmOverlayValidatorTest::SetUp() {
gbm_ = gbm.get();
drm_ = new ui::MockDrmDevice(std::move(gbm));
- CrtcState crtc_state = {.planes = {
- {.formats = {DRM_FORMAT_XRGB8888}},
- }};
+ CrtcState crtc_state = {/* .planes = */ {
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ }};
InitializeDrmState({crtc_state});
screen_manager_.reset(new ui::ScreenManager());
@@ -205,7 +205,7 @@ void DrmOverlayValidatorTest::InitializeDrmState(
}
crtc_plane_properties[plane_idx].properties.push_back(
- {.id = pair.first, .value = value});
+ {/* .id = */ pair.first, /* .value = */ value});
}
}
@@ -279,11 +279,11 @@ TEST_F(DrmOverlayValidatorTest, OverlayFormat_XRGB) {
plane_list_.back().display_bounds = overlay_rect_;
CrtcState state = {
- .planes =
- {
- {.formats = {DRM_FORMAT_XRGB8888, DRM_FORMAT_UYVY}},
- {.formats = {DRM_FORMAT_XRGB8888}},
- },
+ /* .planes = */
+ {
+ {/* .formats = */ {DRM_FORMAT_XRGB8888, DRM_FORMAT_UYVY}},
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ },
};
InitializeDrmState(std::vector<CrtcState>(1, state));
@@ -308,11 +308,11 @@ TEST_F(DrmOverlayValidatorTest, OverlayFormat_YUV) {
AddPlane(overlay_params_.back());
CrtcState state = {
- .planes =
- {
- {.formats = {DRM_FORMAT_XRGB8888}},
- {.formats = {DRM_FORMAT_XRGB8888, DRM_FORMAT_UYVY}},
- },
+ /* .planes = */
+ {
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ {/* .formats = */ {DRM_FORMAT_XRGB8888, DRM_FORMAT_UYVY}},
+ },
};
InitializeDrmState(std::vector<CrtcState>(1, state));
@@ -334,11 +334,11 @@ TEST_F(DrmOverlayValidatorTest, RejectYUVBuffersIfNotSupported) {
AddPlane(overlay_params_.back());
CrtcState state = {
- .planes =
- {
- {.formats = {DRM_FORMAT_XRGB8888}},
- {.formats = {DRM_FORMAT_XRGB8888}},
- },
+ /* .planes = */
+ {
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ },
};
InitializeDrmState(std::vector<CrtcState>(1, state));
@@ -354,18 +354,18 @@ TEST_F(DrmOverlayValidatorTest,
RejectYUVBuffersIfNotSupported_MirroredControllers) {
std::vector<CrtcState> crtc_states = {
{
- .planes =
- {
- {.formats = {DRM_FORMAT_XRGB8888}},
- {.formats = {DRM_FORMAT_XRGB8888, DRM_FORMAT_UYVY}},
- },
+ /* .planes = */
+ {
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ {/* .formats = */ {DRM_FORMAT_XRGB8888, DRM_FORMAT_UYVY}},
+ },
},
{
- .planes =
- {
- {.formats = {DRM_FORMAT_XRGB8888}},
- {.formats = {DRM_FORMAT_XRGB8888, DRM_FORMAT_UYVY}},
- },
+ /* .planes = */
+ {
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ {/* .formats = */ {DRM_FORMAT_XRGB8888, DRM_FORMAT_UYVY}},
+ },
},
};
InitializeDrmState(crtc_states);
@@ -421,18 +421,18 @@ TEST_F(DrmOverlayValidatorTest,
TEST_F(DrmOverlayValidatorTest, OptimalFormatXRGB_MirroredControllers) {
std::vector<CrtcState> crtc_states = {
{
- .planes =
- {
- {.formats = {DRM_FORMAT_XRGB8888}},
- {.formats = {DRM_FORMAT_XRGB8888, DRM_FORMAT_UYVY}},
- },
+ /* .planes = */
+ {
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ {/* .formats = */ {DRM_FORMAT_XRGB8888, DRM_FORMAT_UYVY}},
+ },
},
{
- .planes =
- {
- {.formats = {DRM_FORMAT_XRGB8888}},
- {.formats = {DRM_FORMAT_XRGB8888, DRM_FORMAT_UYVY}},
- },
+ /* .planes = */
+ {
+ {/* .formats = */ {DRM_FORMAT_XRGB8888}},
+ {/* .formats = */ {DRM_FORMAT_XRGB8888, DRM_FORMAT_UYVY}},
+ },
},
};
InitializeDrmState(crtc_states);
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc b/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc
index 15b6ac3c7ac..09a96c43baa 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc
@@ -19,9 +19,9 @@
#include "ui/ozone/common/linux/gbm_device.h"
#include "ui/ozone/common/linux/gbm_wrapper.h"
#include "ui/ozone/platform/drm/common/drm_util.h"
-#include "ui/ozone/platform/drm/gpu/drm_buffer.h"
#include "ui/ozone/platform/drm/gpu/drm_device_generator.h"
#include "ui/ozone/platform/drm/gpu/drm_device_manager.h"
+#include "ui/ozone/platform/drm/gpu/drm_dumb_buffer.h"
#include "ui/ozone/platform/drm/gpu/drm_gpu_display_manager.h"
#include "ui/ozone/platform/drm/gpu/drm_window.h"
#include "ui/ozone/platform/drm/gpu/drm_window_proxy.h"
@@ -152,7 +152,7 @@ void DrmThread::CreateBuffer(gfx::AcceleratedWidget widget,
std::unique_ptr<GbmBuffer>* buffer,
scoped_refptr<DrmFramebuffer>* framebuffer) {
scoped_refptr<ui::DrmDevice> drm = device_manager_->GetDrmDevice(widget);
- DCHECK(drm);
+ CHECK(drm) << "No devices available for buffer allocation.";
DrmWindow* window = screen_manager_->GetWindow(widget);
uint32_t flags = BufferUsageToGbmFlags(usage);
@@ -244,17 +244,6 @@ void DrmThread::OnPlanesReadyForPageFlip(
}
}
-void DrmThread::GetVSyncParameters(
- gfx::AcceleratedWidget widget,
- const gfx::VSyncProvider::UpdateVSyncCallback& callback) {
- DrmWindow* window = screen_manager_->GetWindow(widget);
- // No need to call the callback if there isn't a window since the vsync
- // provider doesn't require the callback to be called if there isn't a vsync
- // data source.
- if (window)
- window->GetVSyncParameters(callback);
-}
-
void DrmThread::IsDeviceAtomic(gfx::AcceleratedWidget widget, bool* is_atomic) {
scoped_refptr<ui::DrmDevice> drm_device =
device_manager_->GetDrmDevice(widget);
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_thread.h b/chromium/ui/ozone/platform/drm/gpu/drm_thread.h
index 79685b1e029..c6fcabc3a89 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_thread.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_thread.h
@@ -90,9 +90,6 @@ class DrmThread : public base::Thread,
std::vector<DrmOverlayPlane> planes,
SwapCompletionOnceCallback submission_callback,
PresentationOnceCallback presentation_callback);
- void GetVSyncParameters(
- gfx::AcceleratedWidget widget,
- const gfx::VSyncProvider::UpdateVSyncCallback& callback);
void IsDeviceAtomic(gfx::AcceleratedWidget widget, bool* is_atomic);
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.h b/chromium/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.h
index f21fd244d7a..970a645eda4 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.h
@@ -94,7 +94,7 @@ class DrmThreadMessageProxy : public IPC::MessageFilter,
display::HDCPState state) const;
void OnSetHDCPStateCallback(int64_t display_id, bool success) const;
- DrmThread* drm_thread_;
+ DrmThread* drm_thread_ = nullptr;
IPC::Sender* sender_ = nullptr;
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_vsync_provider.cc b/chromium/ui/ozone/platform/drm/gpu/drm_vsync_provider.cc
deleted file mode 100644
index 4b153e21255..00000000000
--- a/chromium/ui/ozone/platform/drm/gpu/drm_vsync_provider.cc
+++ /dev/null
@@ -1,34 +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/ozone/platform/drm/gpu/drm_vsync_provider.h"
-
-#include "ui/ozone/platform/drm/gpu/drm_window_proxy.h"
-
-namespace ui {
-
-DrmVSyncProvider::DrmVSyncProvider(DrmWindowProxy* window) : window_(window) {}
-
-DrmVSyncProvider::~DrmVSyncProvider() {
-}
-
-void DrmVSyncProvider::GetVSyncParameters(const UpdateVSyncCallback& callback) {
- window_->GetVSyncParameters(callback);
-}
-
-bool DrmVSyncProvider::GetVSyncParametersIfAvailable(
- base::TimeTicks* timebase,
- base::TimeDelta* interval) {
- return false;
-}
-
-bool DrmVSyncProvider::SupportGetVSyncParametersIfAvailable() const {
- return false;
-}
-
-bool DrmVSyncProvider::IsHWClock() const {
- return true;
-}
-
-} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_vsync_provider.h b/chromium/ui/ozone/platform/drm/gpu/drm_vsync_provider.h
deleted file mode 100644
index d0ec9a6e142..00000000000
--- a/chromium/ui/ozone/platform/drm/gpu/drm_vsync_provider.h
+++ /dev/null
@@ -1,35 +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_OZONE_PLATFORM_IMPL_DRM_VSYNC_PROVIDER_H_
-#define UI_OZONE_PLATFORM_IMPL_DRM_VSYNC_PROVIDER_H_
-
-#include "base/macros.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/gfx/vsync_provider.h"
-
-namespace ui {
-
-class DrmWindowProxy;
-
-class DrmVSyncProvider : public gfx::VSyncProvider {
- public:
- DrmVSyncProvider(DrmWindowProxy* window);
- ~DrmVSyncProvider() override;
-
- void GetVSyncParameters(const UpdateVSyncCallback& callback) override;
- bool GetVSyncParametersIfAvailable(base::TimeTicks* timebase,
- base::TimeDelta* interval) override;
- bool SupportGetVSyncParametersIfAvailable() const override;
- bool IsHWClock() const override;
-
- private:
- DrmWindowProxy* window_;
-
- DISALLOW_COPY_AND_ASSIGN(DrmVSyncProvider);
-};
-
-} // namespace ui
-
-#endif // UI_OZONE_PLATFORM_IMPL_DRM_VSYNC_PROVIDER_H_
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_window.cc b/chromium/ui/ozone/platform/drm/gpu/drm_window.cc
index 04f31690b85..c2aadb98bf1 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_window.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_window.cc
@@ -18,9 +18,9 @@
#include "ui/ozone/common/gpu/ozone_gpu_message_params.h"
#include "ui/ozone/platform/drm/common/drm_util.h"
#include "ui/ozone/platform/drm/gpu/crtc_controller.h"
-#include "ui/ozone/platform/drm/gpu/drm_buffer.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h"
#include "ui/ozone/platform/drm/gpu/drm_device_manager.h"
+#include "ui/ozone/platform/drm/gpu/drm_dumb_buffer.h"
#include "ui/ozone/platform/drm/gpu/drm_overlay_validator.h"
#include "ui/ozone/platform/drm/gpu/screen_manager.h"
@@ -137,21 +137,6 @@ const DrmOverlayPlane* DrmWindow::GetLastModesetBuffer() {
return DrmOverlayPlane::GetPrimaryPlane(last_submitted_planes_);
}
-void DrmWindow::GetVSyncParameters(
- const gfx::VSyncProvider::UpdateVSyncCallback& callback) const {
- if (!controller_)
- return;
-
- // If we're in mirror mode the 2 CRTCs should have similar modes with the same
- // refresh rates.
- CrtcController* crtc = controller_->crtc_controllers()[0].get();
- const base::TimeTicks last_flip = controller_->GetTimeOfLastFlip();
- if (last_flip == base::TimeTicks() || crtc->mode().vrefresh == 0)
- return; // The value is invalid, so we can't update the parameters.
- callback.Run(last_flip,
- base::TimeDelta::FromSeconds(1) / crtc->mode().vrefresh);
-}
-
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 b44d416de4f..ad34c452b9a 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_window.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_window.h
@@ -27,7 +27,6 @@ class Rect;
namespace ui {
-class DrmBuffer;
class DrmDeviceManager;
class DrmOverlayValidator;
class HardwareDisplayController;
@@ -88,17 +87,20 @@ class DrmWindow {
// Returns the last buffer associated with this window.
const DrmOverlayPlane* GetLastModesetBuffer();
- void GetVSyncParameters(
- const gfx::VSyncProvider::UpdateVSyncCallback& callback) const;
-
private:
// Draw next frame in an animated cursor.
void OnCursorAnimationTimeout();
- gfx::AcceleratedWidget widget_;
+ void UpdateCursorImage();
+ void UpdateCursorLocation();
+
+ // Draw the last set cursor & update the cursor plane.
+ void ResetCursor();
+
+ const gfx::AcceleratedWidget widget_;
- DrmDeviceManager* device_manager_; // Not owned.
- ScreenManager* screen_manager_; // Not owned.
+ DrmDeviceManager* const device_manager_; // Not owned.
+ ScreenManager* const screen_manager_; // Not owned.
// The current bounds of the window.
gfx::Rect bounds_;
@@ -108,12 +110,6 @@ class DrmWindow {
HardwareDisplayController* controller_ = nullptr;
std::unique_ptr<DrmOverlayValidator> overlay_validator_;
- void UpdateCursorImage();
- void UpdateCursorLocation();
-
- // Draw the last set cursor & update the cursor plane.
- void ResetCursor();
-
base::RepeatingTimer cursor_timer_;
std::vector<SkBitmap> cursor_bitmaps_;
gfx::Point cursor_location_;
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_window_proxy.cc b/chromium/ui/ozone/platform/drm/gpu/drm_window_proxy.cc
index bde6d1dda8a..ce35578edd2 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_window_proxy.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_window_proxy.cc
@@ -34,14 +34,6 @@ void DrmWindowProxy::SchedulePageFlip(
CreateSafeOnceCallback(std::move(presentation_callback))));
}
-void DrmWindowProxy::GetVSyncParameters(
- const gfx::VSyncProvider::UpdateVSyncCallback& callback) {
- drm_thread_->task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&DrmThread::GetVSyncParameters,
- base::Unretained(drm_thread_), widget_,
- CreateSafeCallback(callback)));
-}
-
bool DrmWindowProxy::SupportsGpuFences() const {
bool is_atomic = false;
PostSyncTask(
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_window_proxy.h b/chromium/ui/ozone/platform/drm/gpu/drm_window_proxy.h
index 080561f83cd..303051c1c25 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_window_proxy.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_window_proxy.h
@@ -28,15 +28,12 @@ class DrmWindowProxy {
SwapCompletionOnceCallback submission_callback,
PresentationOnceCallback presentation_callback);
- void GetVSyncParameters(
- const gfx::VSyncProvider::UpdateVSyncCallback& callback);
-
bool SupportsGpuFences() const;
private:
- gfx::AcceleratedWidget widget_;
+ const gfx::AcceleratedWidget widget_;
- DrmThread* drm_thread_;
+ DrmThread* const drm_thread_;
DISALLOW_COPY_AND_ASSIGN(DrmWindowProxy);
};
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_overlay_surface.h b/chromium/ui/ozone/platform/drm/gpu/gbm_overlay_surface.h
index a827ee08294..abde483b459 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_overlay_surface.h
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_overlay_surface.h
@@ -49,7 +49,7 @@ class GbmOverlaySurface : public OverlaySurface {
std::unique_ptr<gfx::GpuFence> out_fence);
void OnPresentation(const gfx::PresentationFeedback& presentation_feedback);
- std::unique_ptr<DrmWindowProxy> window_;
+ const std::unique_ptr<DrmWindowProxy> window_;
Frame unsubmitted_frame_;
Frame submitted_frame_;
Frame presented_frame_;
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_pixmap.h b/chromium/ui/ozone/platform/drm/gpu/gbm_pixmap.h
index 41194f7cdb4..91b9b93f222 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_pixmap.h
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_pixmap.h
@@ -50,9 +50,9 @@ class GbmPixmap : public gfx::NativePixmap {
private:
~GbmPixmap() override;
- GbmSurfaceFactory* surface_manager_;
- std::unique_ptr<GbmBuffer> buffer_;
- scoped_refptr<DrmFramebuffer> framebuffer_;
+ GbmSurfaceFactory* const surface_manager_;
+ const std::unique_ptr<GbmBuffer> buffer_;
+ const scoped_refptr<DrmFramebuffer> framebuffer_;
DISALLOW_COPY_AND_ASSIGN(GbmPixmap);
};
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_surface.cc b/chromium/ui/ozone/platform/drm/gpu/gbm_surface.cc
deleted file mode 100644
index 8588a55d7ac..00000000000
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_surface.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-// Copyright 2016 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/drm/gpu/gbm_surface.h"
-
-#include <utility>
-
-#include "base/logging.h"
-#include "ui/display/types/display_snapshot.h"
-#include "ui/gfx/gpu_fence.h"
-#include "ui/gfx/gpu_fence_handle.h"
-#include "ui/gfx/native_pixmap.h"
-#include "ui/gl/gl_image_native_pixmap.h"
-#include "ui/gl/gl_surface_egl.h"
-#include "ui/ozone/platform/drm/gpu/drm_window_proxy.h"
-#include "ui/ozone/platform/drm/gpu/gbm_surface_factory.h"
-
-namespace ui {
-
-GbmSurface::GbmSurface(GbmSurfaceFactory* surface_factory,
- std::unique_ptr<DrmWindowProxy> window,
- gfx::AcceleratedWidget widget)
- : GbmSurfaceless(surface_factory, std::move(window), widget) {
- for (auto& texture : textures_)
- texture = 0;
-}
-
-unsigned int GbmSurface::GetBackingFramebufferObject() {
- return fbo_;
-}
-
-bool GbmSurface::OnMakeCurrent(gl::GLContext* context) {
- DCHECK(!context_ || context == context_);
- context_ = context;
- if (!fbo_) {
- glGenFramebuffersEXT(1, &fbo_);
- if (!fbo_)
- return false;
- glGenTextures(arraysize(textures_), textures_);
- if (!CreatePixmaps())
- return false;
- }
- BindFramebuffer();
- glBindFramebufferEXT(GL_FRAMEBUFFER, fbo_);
- return SurfacelessEGL::OnMakeCurrent(context);
-}
-
-bool GbmSurface::Resize(const gfx::Size& size,
- float scale_factor,
- ColorSpace color_space,
- bool has_alpha) {
- if (size == GetSize())
- return true;
- // Alpha value isn't actually used in allocating buffers yet, so always use
- // true instead.
- return GbmSurfaceless::Resize(size, scale_factor, color_space, true) &&
- CreatePixmaps();
-}
-
-bool GbmSurface::SupportsPostSubBuffer() {
- return false;
-}
-
-void GbmSurface::SwapBuffersAsync(
- const SwapCompletionCallback& completion_callback,
- const PresentationCallback& presentation_callback) {
- if (!images_[current_surface_]->ScheduleOverlayPlane(
- widget(), 0, gfx::OverlayTransform::OVERLAY_TRANSFORM_NONE,
- gfx::Rect(GetSize()), gfx::RectF(1, 1), /* enable_blend */ false,
- /* gpu_fence */ nullptr)) {
- completion_callback.Run(gfx::SwapResult::SWAP_FAILED, nullptr);
- // Notify the caller, the buffer is never presented on a screen.
- presentation_callback.Run(gfx::PresentationFeedback::Failure());
- return;
- }
- GbmSurfaceless::SwapBuffersAsync(completion_callback, presentation_callback);
- current_surface_ ^= 1;
- BindFramebuffer();
-}
-
-void GbmSurface::Destroy() {
- if (!context_)
- return;
- scoped_refptr<gl::GLContext> previous_context = gl::GLContext::GetCurrent();
- scoped_refptr<GLSurface> previous_surface;
-
- bool was_current = previous_context && previous_context->IsCurrent(nullptr) &&
- GLSurface::GetCurrent() == this;
- if (!was_current) {
- // Only take a reference to previous surface if it's not |this|
- // because otherwise we can take a self reference from our own dtor.
- previous_surface = GLSurface::GetCurrent();
- context_->MakeCurrent(this);
- }
-
- glBindFramebufferEXT(GL_FRAMEBUFFER, 0);
- if (fbo_) {
- glDeleteTextures(arraysize(textures_), textures_);
- for (auto& texture : textures_)
- texture = 0;
- glDeleteFramebuffersEXT(1, &fbo_);
- fbo_ = 0;
- }
- for (auto& image : images_)
- image = nullptr;
-
- if (!was_current) {
- if (previous_context) {
- previous_context->MakeCurrent(previous_surface.get());
- } else {
- context_->ReleaseCurrent(this);
- }
- }
-}
-
-bool GbmSurface::IsSurfaceless() const {
- return false;
-}
-
-GbmSurface::~GbmSurface() {
- Destroy();
-}
-
-void GbmSurface::BindFramebuffer() {
- gl::ScopedFramebufferBinder fb(fbo_);
- glFramebufferTexture2DEXT(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D,
- textures_[current_surface_], 0);
-}
-
-bool GbmSurface::CreatePixmaps() {
- if (!fbo_)
- return true;
- for (size_t i = 0; i < arraysize(textures_); i++) {
- scoped_refptr<gfx::NativePixmap> pixmap =
- surface_factory()->CreateNativePixmap(
- widget(), GetSize(), display::DisplaySnapshot::PrimaryFormat(),
- gfx::BufferUsage::SCANOUT);
- if (!pixmap)
- return false;
- scoped_refptr<gl::GLImageNativePixmap> image =
- new gl::GLImageNativePixmap(GetSize(), GL_BGRA_EXT);
- if (!image->Initialize(pixmap.get(),
- display::DisplaySnapshot::PrimaryFormat()))
- return false;
- images_[i] = image;
- // Bind image to texture.
- gl::ScopedTextureBinder binder(GL_TEXTURE_2D, textures_[i]);
- if (!images_[i]->BindTexImage(GL_TEXTURE_2D))
- return false;
- }
- return true;
-}
-
-} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_surface.h b/chromium/ui/ozone/platform/drm/gpu/gbm_surface.h
deleted file mode 100644
index be90a6dff8b..00000000000
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_surface.h
+++ /dev/null
@@ -1,60 +0,0 @@
-// Copyright 2016 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_DRM_GPU_GBM_SURFACE_H_
-#define UI_OZONE_PLATFORM_DRM_GPU_GBM_SURFACE_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/memory/ref_counted.h"
-#include "ui/gl/gl_context.h"
-#include "ui/gl/gl_image.h"
-#include "ui/ozone/platform/drm/gpu/gbm_surfaceless.h"
-
-namespace ui {
-
-class DrmWindowProxy;
-class GbmSurfaceFactory;
-
-// A GLSurface for GBM Ozone platform provides surface-like semantics
-// implemented through surfaceless. A framebuffer is bound automatically.
-class GbmSurface : public GbmSurfaceless {
- public:
- GbmSurface(GbmSurfaceFactory* surface_factory,
- std::unique_ptr<DrmWindowProxy> window,
- gfx::AcceleratedWidget widget);
-
- // gl::GLSurface:
- unsigned int GetBackingFramebufferObject() override;
- bool OnMakeCurrent(gl::GLContext* context) override;
- bool Resize(const gfx::Size& size,
- float scale_factor,
- ColorSpace color_space,
- bool has_alpha) override;
- bool SupportsPostSubBuffer() override;
- void SwapBuffersAsync(
- const SwapCompletionCallback& completion_callback,
- const PresentationCallback& presentation_callback) override;
- void Destroy() override;
- bool IsSurfaceless() const override;
-
- private:
- ~GbmSurface() override;
-
- void BindFramebuffer();
- bool CreatePixmaps();
-
- scoped_refptr<gl::GLContext> context_;
- GLuint fbo_ = 0;
- GLuint textures_[2];
- scoped_refptr<gl::GLImage> images_[2];
- int current_surface_ = 0;
-
- DISALLOW_COPY_AND_ASSIGN(GbmSurface);
-};
-
-} // namespace ui
-
-#endif // UI_OZONE_PLATFORM_DRM_GPU_GBM_SURFACE_H_
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc b/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc
index fc0315c3056..dffec5db847 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.cc
@@ -21,7 +21,6 @@
#include "ui/ozone/platform/drm/gpu/drm_window_proxy.h"
#include "ui/ozone/platform/drm/gpu/gbm_overlay_surface.h"
#include "ui/ozone/platform/drm/gpu/gbm_pixmap.h"
-#include "ui/ozone/platform/drm/gpu/gbm_surface.h"
#include "ui/ozone/platform/drm/gpu/gbm_surfaceless.h"
#include "ui/ozone/platform/drm/gpu/proxy_helpers.h"
#include "ui/ozone/platform/drm/gpu/screen_manager.h"
@@ -64,9 +63,7 @@ class GLOzoneEGLGbm : public GLOzoneEGL {
scoped_refptr<gl::GLSurface> CreateViewGLSurface(
gfx::AcceleratedWidget window) override {
- return gl::InitializeGLSurface(new GbmSurface(
- surface_factory_, drm_thread_proxy_->CreateDrmWindowProxy(window),
- window));
+ return nullptr;
}
scoped_refptr<gl::GLSurface> CreateSurfacelessViewGLSurface(
@@ -183,13 +180,23 @@ scoped_refptr<gfx::NativePixmap> GbmSurfaceFactory::CreateNativePixmapForVulkan(
base::ScopedFD vk_image_fd(dup(buffer->GetPlaneFd(0)));
DCHECK(vk_image_fd.is_valid());
+ // TODO(spang): Fix this for formats other than gfx::BufferFormat::BGRA_8888
+ DCHECK_EQ(format, display::DisplaySnapshot::PrimaryFormat());
+ VkFormat vk_format = VK_FORMAT_B8G8R8A8_SRGB;
+
VkDmaBufImageCreateInfo dma_buf_image_create_info = {
- .sType = static_cast<VkStructureType>(
+ /* .sType = */ static_cast<VkStructureType>(
VK_STRUCTURE_TYPE_DMA_BUF_IMAGE_CREATE_INFO_INTEL),
- .fd = vk_image_fd.release(),
- .format = VK_FORMAT_B8G8R8A8_SRGB,
- .extent = (VkExtent3D){size.width(), size.height(), 1},
- .strideInBytes = buffer->GetPlaneStride(0),
+ /* .pNext = */ nullptr,
+ /* .fd = */ vk_image_fd.release(),
+ /* .format = */ vk_format,
+ /* .extent = */
+ {
+ /* .width = */ size.width(),
+ /* .height = */ size.height(),
+ /* .depth = */ 1,
+ },
+ /* .strideInBytes = */ buffer->GetPlaneStride(0),
};
VkResult result =
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 17ade46e881..c12508523b1 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.h
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_surface_factory.h
@@ -87,7 +87,7 @@ class GbmSurfaceFactory : public SurfaceFactoryOzone {
base::ThreadChecker thread_checker_;
- DrmThreadProxy* drm_thread_proxy_;
+ DrmThreadProxy* const drm_thread_proxy_;
std::map<gfx::AcceleratedWidget, GbmSurfaceless*> widget_to_surface_map_;
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc b/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
index fdd70fd8fbe..6ee9357e8cc 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.cc
@@ -15,7 +15,6 @@
#include "ui/ozone/common/egl_util.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h"
#include "ui/ozone/platform/drm/gpu/drm_framebuffer.h"
-#include "ui/ozone/platform/drm/gpu/drm_vsync_provider.h"
#include "ui/ozone/platform/drm/gpu/drm_window_proxy.h"
#include "ui/ozone/platform/drm/gpu/gbm_surface_factory.h"
@@ -54,9 +53,6 @@ void GbmSurfaceless::QueueOverlayPlane(DrmOverlayPlane plane) {
bool GbmSurfaceless::Initialize(gl::GLSurfaceFormat format) {
if (!SurfacelessEGL::Initialize(format))
return false;
- vsync_provider_ = std::make_unique<DrmVSyncProvider>(window_.get());
- if (!vsync_provider_)
- return false;
return true;
}
@@ -84,10 +80,6 @@ bool GbmSurfaceless::IsOffscreen() {
return false;
}
-gfx::VSyncProvider* GbmSurfaceless::GetVSyncProvider() {
- return vsync_provider_.get();
-}
-
bool GbmSurfaceless::SupportsPresentationCallback() {
return true;
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.h b/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.h
index 31ba0d3f784..8923a624a59 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.h
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_surfaceless.h
@@ -45,7 +45,6 @@ class GbmSurfaceless : public gl::SurfacelessEGL {
bool enable_blend,
std::unique_ptr<gfx::GpuFence> gpu_fence) override;
bool IsOffscreen() override;
- gfx::VSyncProvider* GetVSyncProvider() override;
bool SupportsPresentationCallback() override;
bool SupportsAsyncSwap() override;
bool SupportsPostSubBuffer() override;
@@ -98,16 +97,16 @@ class GbmSurfaceless : public gl::SurfacelessEGL {
std::unique_ptr<gfx::GpuFence> out_fence);
void OnPresentation(const gfx::PresentationFeedback& feedback);
- GbmSurfaceFactory* surface_factory_;
- std::unique_ptr<DrmWindowProxy> window_;
+ GbmSurfaceFactory* const surface_factory_;
+ const std::unique_ptr<DrmWindowProxy> window_;
std::vector<DrmOverlayPlane> planes_;
// The native surface. Deleting this is allowed to free the EGLNativeWindow.
- gfx::AcceleratedWidget widget_;
+ const gfx::AcceleratedWidget widget_;
std::unique_ptr<gfx::VSyncProvider> vsync_provider_;
std::vector<std::unique_ptr<PendingFrame>> unsubmitted_frames_;
std::unique_ptr<PendingFrame> submitted_frame_;
- bool has_implicit_external_sync_;
+ const bool has_implicit_external_sync_;
bool last_swap_buffers_result_ = true;
bool supports_plane_gpu_fences_ = false;
bool use_egl_fence_sync_ = true;
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 19a1b42bd36..297ff19a6df 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
@@ -21,8 +21,8 @@
#include "ui/gfx/swap_result.h"
#include "ui/ozone/platform/drm/common/drm_util.h"
#include "ui/ozone/platform/drm/gpu/crtc_controller.h"
-#include "ui/ozone/platform/drm/gpu/drm_buffer.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h"
+#include "ui/ozone/platform/drm/gpu/drm_dumb_buffer.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane.h"
#include "ui/ozone/platform/drm/gpu/page_flip_request.h"
@@ -42,7 +42,7 @@ void CompletePageFlip(
std::move(callback).Run(presentation_feedback);
}
-void DrawCursor(DrmBuffer* cursor, const SkBitmap& image) {
+void DrawCursor(DrmDumbBuffer* cursor, const SkBitmap& image) {
SkRect damage;
image.getBounds(&damage);
@@ -309,13 +309,9 @@ gfx::Size HardwareDisplayController::GetModeSize() const {
crtc_controllers_[0]->mode().vdisplay);
}
-uint32_t HardwareDisplayController::GetRefreshRate() const {
- // If there are multiple CRTCs they should all have the same size.
- return crtc_controllers_[0]->mode().vrefresh;
-}
-
base::TimeDelta HardwareDisplayController::GetRefreshInterval() const {
- uint32_t vrefresh = GetRefreshRate();
+ // If there are multiple CRTCs they should all have the same refresh rate.
+ float vrefresh = ModeRefreshRate(crtc_controllers_[0]->mode());
return vrefresh ? base::TimeDelta::FromSeconds(1) / vrefresh
: base::TimeDelta();
}
@@ -338,6 +334,8 @@ void HardwareDisplayController::OnPageFlipComplete(
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_)
+ controller->OnPageFlipComplete();
page_flip_request_ = nullptr;
}
@@ -359,7 +357,7 @@ void HardwareDisplayController::AllocateCursorBuffers() {
SkImageInfo info = SkImageInfo::MakeN32Premul(max_cursor_size.width(),
max_cursor_size.height());
for (size_t i = 0; i < arraysize(cursor_buffers_); ++i) {
- cursor_buffers_[i] = std::make_unique<DrmBuffer>(GetDrmDevice());
+ cursor_buffers_[i] = std::make_unique<DrmDumbBuffer>(GetDrmDevice());
// Don't register a framebuffer for cursors since they are special (they
// aren't modesetting buffers and drivers may fail to register them due to
// their small sizes).
@@ -370,7 +368,7 @@ void HardwareDisplayController::AllocateCursorBuffers() {
}
}
-DrmBuffer* HardwareDisplayController::NextCursorBuffer() {
+DrmDumbBuffer* HardwareDisplayController::NextCursorBuffer() {
++cursor_frontbuffer_;
cursor_frontbuffer_ %= base::size(cursor_buffers_);
return cursor_buffers_[cursor_frontbuffer_].get();
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 c232ee54326..1031f12cb09 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h
@@ -31,7 +31,7 @@ namespace ui {
class CrtcController;
class DrmFramebuffer;
-class DrmBuffer;
+class DrmDumbBuffer;
class DrmDevice;
// The HDCOz will handle modesettings and scannout operations for hardware
@@ -156,7 +156,6 @@ class HardwareDisplayController {
gfx::Point origin() const { return origin_; }
void set_origin(const gfx::Point& origin) { origin_ = origin; }
- uint32_t GetRefreshRate() const;
base::TimeDelta GetRefreshInterval() const;
base::TimeTicks GetTimeOfLastFlip() const;
@@ -176,7 +175,7 @@ class HardwareDisplayController {
scoped_refptr<PageFlipRequest> page_flip_request,
std::unique_ptr<gfx::GpuFence>* out_fence);
void AllocateCursorBuffers();
- DrmBuffer* NextCursorBuffer();
+ DrmDumbBuffer* NextCursorBuffer();
void UpdateCursorImage();
void UpdateCursorLocation();
void ResetCursor();
@@ -195,10 +194,10 @@ class HardwareDisplayController {
DrmOverlayPlaneList current_planes_;
base::TimeTicks time_of_last_flip_;
- std::unique_ptr<DrmBuffer> cursor_buffers_[2];
+ std::unique_ptr<DrmDumbBuffer> cursor_buffers_[2];
gfx::Point cursor_location_;
int cursor_frontbuffer_ = 0;
- DrmBuffer* current_cursor_ = nullptr;
+ DrmDumbBuffer* current_cursor_ = nullptr;
bool is_disabled_;
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 662d7232d19..28c210a8222 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
@@ -141,7 +141,8 @@ void HardwareDisplayControllerTest::InitializeDrmDevice(bool use_atomic) {
else if (pair.first == kInFormatsPropId)
value = kInFormatsBlobPropId;
- plane.properties.push_back({.id = pair.first, .value = value});
+ plane.properties.push_back(
+ {/* .id = */ pair.first, /*.value = */ value});
};
drm_->SetPropertyBlob(ui::MockDrmDevice::AllocateInFormatsBlob(
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane.h b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane.h
index 80609c61417..58c4dafc88e 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane.h
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane.h
@@ -70,7 +70,7 @@ class HardwareDisplayPlane {
DrmDevice::Property plane_ctm;
};
- uint32_t id_;
+ const uint32_t id_;
uint32_t crtc_mask_ = 0;
Properties properties_ = {};
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 7b711d134d3..69a2c6bd3b4 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
@@ -49,15 +49,13 @@ HardwareDisplayPlaneManager::CrtcState::~CrtcState() = default;
HardwareDisplayPlaneManager::CrtcState::CrtcState(CrtcState&&) = default;
-HardwareDisplayPlaneManager::HardwareDisplayPlaneManager() : drm_(nullptr) {
-}
+HardwareDisplayPlaneManager::HardwareDisplayPlaneManager(DrmDevice* drm)
+ : drm_(drm) {}
HardwareDisplayPlaneManager::~HardwareDisplayPlaneManager() {
}
-bool HardwareDisplayPlaneManager::Initialize(DrmDevice* drm) {
- drm_ = drm;
-
+bool HardwareDisplayPlaneManager::Initialize() {
// Try to get all of the planes if possible, so we don't have to try to
// discover hidden primary planes.
#if defined(DRM_CLIENT_CAP_UNIVERSAL_PLANES)
@@ -65,10 +63,10 @@ bool HardwareDisplayPlaneManager::Initialize(DrmDevice* drm) {
drm_->SetCapability(DRM_CLIENT_CAP_UNIVERSAL_PLANES, 1);
#endif
- if (!InitializeCrtcState(drm))
+ if (!InitializeCrtcState())
return false;
- if (!InitializePlanes(drm))
+ if (!InitializePlanes())
return false;
std::sort(planes_.begin(), planes_.end(),
@@ -304,8 +302,8 @@ bool HardwareDisplayPlaneManager::SetGammaCorrection(
return CommitGammaCorrection(*crtc_props);
}
-bool HardwareDisplayPlaneManager::InitializeCrtcState(DrmDevice* drm) {
- ScopedDrmResourcesPtr resources(drm->GetResources());
+bool HardwareDisplayPlaneManager::InitializeCrtcState() {
+ ScopedDrmResourcesPtr resources(drm_->GetResources());
if (!resources) {
PLOG(ERROR) << "Failed to get resources.";
return false;
@@ -318,7 +316,7 @@ bool HardwareDisplayPlaneManager::InitializeCrtcState(DrmDevice* drm) {
state.properties.id = resources->crtcs[i];
ScopedDrmObjectPropertyPtr props(
- drm->GetObjectProperties(resources->crtcs[i], DRM_MODE_OBJECT_CRTC));
+ drm_->GetObjectProperties(resources->crtcs[i], DRM_MODE_OBJECT_CRTC));
if (!props) {
PLOG(ERROR) << "Failed to get CRTC properties for crtc_id="
<< state.properties.id;
@@ -327,16 +325,16 @@ bool HardwareDisplayPlaneManager::InitializeCrtcState(DrmDevice* drm) {
// These properties are optional. If they don't exist we can tell by the
// invalid ID.
- GetDrmPropertyForName(drm, props.get(), "CTM", &state.properties.ctm);
- GetDrmPropertyForName(drm, props.get(), "GAMMA_LUT",
+ GetDrmPropertyForName(drm_, props.get(), "CTM", &state.properties.ctm);
+ GetDrmPropertyForName(drm_, props.get(), "GAMMA_LUT",
&state.properties.gamma_lut);
- GetDrmPropertyForName(drm, props.get(), "GAMMA_LUT_SIZE",
+ GetDrmPropertyForName(drm_, props.get(), "GAMMA_LUT_SIZE",
&state.properties.gamma_lut_size);
- GetDrmPropertyForName(drm, props.get(), "DEGAMMA_LUT",
+ GetDrmPropertyForName(drm_, props.get(), "DEGAMMA_LUT",
&state.properties.degamma_lut);
- GetDrmPropertyForName(drm, props.get(), "DEGAMMA_LUT_SIZE",
+ GetDrmPropertyForName(drm_, props.get(), "DEGAMMA_LUT_SIZE",
&state.properties.degamma_lut_size);
- GetDrmPropertyForName(drm, props.get(), "OUT_FENCE_PTR",
+ GetDrmPropertyForName(drm_, props.get(), "OUT_FENCE_PTR",
&state.properties.out_fence_ptr);
num_crtcs_with_out_fence_ptr += (state.properties.out_fence_ptr.id != 0);
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 e60ddb68960..e4de8f55139 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
@@ -56,12 +56,12 @@ struct HardwareDisplayPlaneList {
class HardwareDisplayPlaneManager {
public:
- HardwareDisplayPlaneManager();
+ HardwareDisplayPlaneManager(DrmDevice* drm);
virtual ~HardwareDisplayPlaneManager();
// This parses information from the drm driver, adding any new planes
// or crtcs found.
- bool Initialize(DrmDevice* drm);
+ bool Initialize();
// Clears old frame state out. Must be called before any AssignOverlayPlanes
// calls.
@@ -159,9 +159,9 @@ class HardwareDisplayPlaneManager {
DISALLOW_COPY_AND_ASSIGN(CrtcState);
};
- bool InitializeCrtcState(DrmDevice* drm);
+ bool InitializeCrtcState();
- virtual bool InitializePlanes(DrmDevice* drm) = 0;
+ virtual bool InitializePlanes() = 0;
virtual bool SetPlaneData(HardwareDisplayPlaneList* plane_list,
HardwareDisplayPlane* hw_plane,
@@ -199,7 +199,7 @@ class HardwareDisplayPlaneManager {
// Object containing the connection to the graphics device and wraps the API
// calls to control it. Not owned.
- DrmDevice* drm_;
+ DrmDevice* const drm_;
bool has_universal_planes_ = false;
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 c5d93398039..fe898efb2e6 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
@@ -51,8 +51,9 @@ std::unique_ptr<gfx::GpuFence> CreateMergedGpuFenceFromFDs(
} // namespace
-HardwareDisplayPlaneManagerAtomic::HardwareDisplayPlaneManagerAtomic() {
-}
+HardwareDisplayPlaneManagerAtomic::HardwareDisplayPlaneManagerAtomic(
+ DrmDevice* drm)
+ : HardwareDisplayPlaneManager(drm) {}
HardwareDisplayPlaneManagerAtomic::~HardwareDisplayPlaneManagerAtomic() {
}
@@ -247,8 +248,8 @@ bool HardwareDisplayPlaneManagerAtomic::SetPlaneData(
return true;
}
-bool HardwareDisplayPlaneManagerAtomic::InitializePlanes(DrmDevice* drm) {
- ScopedDrmPlaneResPtr plane_resources = drm->GetPlaneResources();
+bool HardwareDisplayPlaneManagerAtomic::InitializePlanes() {
+ ScopedDrmPlaneResPtr plane_resources = drm_->GetPlaneResources();
if (!plane_resources) {
PLOG(ERROR) << "Failed to get plane resources.";
return false;
@@ -258,7 +259,7 @@ bool HardwareDisplayPlaneManagerAtomic::InitializePlanes(DrmDevice* drm) {
std::unique_ptr<HardwareDisplayPlane> plane(
CreatePlane(plane_resources->planes[i]));
- if (plane->Initialize(drm))
+ if (plane->Initialize(drm_))
planes_.push_back(std::move(plane));
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h
index 3c8d1e5089c..ae44ee124c8 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h
@@ -14,7 +14,7 @@ namespace ui {
class HardwareDisplayPlaneManagerAtomic : public HardwareDisplayPlaneManager {
public:
- HardwareDisplayPlaneManagerAtomic();
+ HardwareDisplayPlaneManagerAtomic(DrmDevice* drm);
~HardwareDisplayPlaneManagerAtomic() override;
// HardwareDisplayPlaneManager:
@@ -41,7 +41,7 @@ class HardwareDisplayPlaneManagerAtomic : public HardwareDisplayPlaneManager {
CrtcController* crtc) override;
private:
- bool InitializePlanes(DrmDevice* drm) override;
+ bool InitializePlanes() override;
std::unique_ptr<HardwareDisplayPlane> CreatePlane(uint32_t plane_id) override;
bool CommitColorMatrix(const CrtcProperties& crtc_props) override;
bool CommitGammaCorrection(const CrtcProperties& crtc_props) override;
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc
index 492d2201734..498aec547fc 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc
@@ -36,8 +36,9 @@ ui::DrmOverlayPlaneList WaitForPlaneFences(ui::DrmOverlayPlaneList planes) {
} // namespace
-HardwareDisplayPlaneManagerLegacy::HardwareDisplayPlaneManagerLegacy() {
-}
+HardwareDisplayPlaneManagerLegacy::HardwareDisplayPlaneManagerLegacy(
+ DrmDevice* drm)
+ : HardwareDisplayPlaneManager(drm) {}
HardwareDisplayPlaneManagerLegacy::~HardwareDisplayPlaneManagerLegacy() {
}
@@ -125,8 +126,8 @@ void HardwareDisplayPlaneManagerLegacy::RequestPlanesReadyCallback(
std::move(callback));
}
-bool HardwareDisplayPlaneManagerLegacy::InitializePlanes(DrmDevice* drm) {
- ScopedDrmPlaneResPtr plane_resources = drm->GetPlaneResources();
+bool HardwareDisplayPlaneManagerLegacy::InitializePlanes() {
+ ScopedDrmPlaneResPtr plane_resources = drm_->GetPlaneResources();
if (!plane_resources) {
PLOG(ERROR) << "Failed to get plane resources.";
return false;
@@ -136,7 +137,7 @@ bool HardwareDisplayPlaneManagerLegacy::InitializePlanes(DrmDevice* drm) {
std::unique_ptr<HardwareDisplayPlane> plane(
CreatePlane(plane_resources->planes[i]));
- if (!plane->Initialize(drm))
+ if (!plane->Initialize(drm_))
continue;
// Overlays are not supported on the legacy path, so ignore all overlay
@@ -159,7 +160,7 @@ bool HardwareDisplayPlaneManagerLegacy::InitializePlanes(DrmDevice* drm) {
}) == planes_.end()) {
std::unique_ptr<HardwareDisplayPlane> dummy_plane(
new HardwareDisplayPlaneDummy(id, 1 << i));
- if (dummy_plane->Initialize(drm)) {
+ if (dummy_plane->Initialize(drm_)) {
planes_.push_back(std::move(dummy_plane));
}
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h
index 171f0717e87..a40413ff2d0 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h
@@ -14,7 +14,7 @@ namespace ui {
class HardwareDisplayPlaneManagerLegacy : public HardwareDisplayPlaneManager {
public:
- HardwareDisplayPlaneManagerLegacy();
+ HardwareDisplayPlaneManagerLegacy(DrmDevice* device);
~HardwareDisplayPlaneManagerLegacy() override;
// HardwareDisplayPlaneManager:
@@ -35,7 +35,7 @@ class HardwareDisplayPlaneManagerLegacy : public HardwareDisplayPlaneManager {
base::OnceCallback<void(DrmOverlayPlaneList)> callback) override;
protected:
- bool InitializePlanes(DrmDevice* drm) override;
+ bool InitializePlanes() override;
bool SetPlaneData(HardwareDisplayPlaneList* plane_list,
HardwareDisplayPlane* hw_plane,
const DrmOverlayPlane& overlay,
diff --git a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc
index 177a262ad90..ded5335acaa 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_unittest.cc
@@ -144,7 +144,8 @@ void HardwareDisplayPlaneManagerTest::InitializeDrmState(
} else if (pair.first == kInFormatsPropId) {
value = kInFormatsBlobPropId;
}
- plane_prop.properties.push_back({.id = pair.first, .value = value});
+ plane_prop.properties.push_back(
+ {/* .id = */ pair.first, /* .value = */ value});
};
plane_properties_.emplace_back(std::move(plane_prop));
@@ -365,8 +366,8 @@ TEST_P(HardwareDisplayPlaneManagerAtomicTest, SharedPlanes) {
plane_prop.id = 102;
plane_prop.crtc_mask = (1 << 0) | (1 << 1);
plane_prop.properties = {
- {.id = kTypePropId, .value = DRM_PLANE_TYPE_OVERLAY},
- {.id = kInFormatsPropId, .value = kInFormatsBlobPropId},
+ {/* .id = */ kTypePropId, /* .value = */ DRM_PLANE_TYPE_OVERLAY},
+ {/* .id = */ kInFormatsPropId, /* .value = */ kInFormatsBlobPropId},
};
plane_properties_.emplace_back(std::move(plane_prop));
fake_drm_->InitializeState(crtc_properties_, plane_properties_,
@@ -459,8 +460,10 @@ TEST_P(HardwareDisplayPlaneManagerAtomicTest, MultipleFramesDifferentPlanes) {
TEST_P(HardwareDisplayPlaneManagerAtomicTest,
SetColorCorrectionOnAllCrtcPlanes_Success) {
InitializeDrmState(/*crtc_count=*/1, /*planes_per_crtc=*/1);
- plane_properties_[0].properties.push_back({.id = kPlaneCtmId, .value = 0});
- plane_properties_[1].properties.push_back({.id = kPlaneCtmId, .value = 0});
+ plane_properties_[0].properties.push_back(
+ {/* .id = */ kPlaneCtmId, /* .value = */ 0});
+ plane_properties_[1].properties.push_back(
+ {/* .id = */ kPlaneCtmId, /* .value = */ 0});
fake_drm_->InitializeState(crtc_properties_, plane_properties_,
property_names_, use_atomic_);
@@ -485,7 +488,8 @@ TEST_P(HardwareDisplayPlaneManagerAtomicTest,
TEST_P(HardwareDisplayPlaneManagerAtomicTest,
SetColorCorrectionOnAllCrtcPlanes_OnePlaneMissingCtmProperty) {
InitializeDrmState(/*crtc_count=*/1, /*planes_per_crtc=*/2);
- plane_properties_[0].properties.push_back({.id = kPlaneCtmId, .value = 0});
+ plane_properties_[0].properties.push_back(
+ {/* .id = */ kPlaneCtmId, /* .value = */ 0});
fake_drm_->InitializeState(crtc_properties_, plane_properties_,
property_names_, use_atomic_);
@@ -497,7 +501,8 @@ TEST_P(HardwareDisplayPlaneManagerAtomicTest,
TEST_P(HardwareDisplayPlaneManagerTest, SetColorMatrix_Success) {
InitializeDrmState(/*crtc_count=*/1, /*planes_per_crtc=*/1);
- crtc_properties_[0].properties.push_back({.id = kCtmPropId, .value = 0});
+ crtc_properties_[0].properties.push_back(
+ {/* .id = */ kCtmPropId, /* .value = */ 0});
fake_drm_->InitializeState(crtc_properties_, plane_properties_,
property_names_, use_atomic_);
@@ -519,7 +524,8 @@ TEST_P(HardwareDisplayPlaneManagerTest, SetColorMatrix_Success) {
TEST_P(HardwareDisplayPlaneManagerTest, SetColorMatrix_ErrorEmptyCtm) {
InitializeDrmState(/*crtc_count=*/1, /*planes_per_crtc=*/1);
- crtc_properties_[0].properties.push_back({.id = kCtmPropId, .value = 0});
+ crtc_properties_[0].properties.push_back(
+ {/* .id = */ kCtmPropId, /* .value = */ 0});
fake_drm_->InitializeState(crtc_properties_, plane_properties_,
property_names_, use_atomic_);
@@ -537,7 +543,8 @@ TEST_P(HardwareDisplayPlaneManagerTest, SetColorMatrix_ErrorEmptyCtm) {
TEST_P(HardwareDisplayPlaneManagerTest, SetGammaCorrection_MissingDegamma) {
InitializeDrmState(/*crtc_count=*/1, /*planes_per_crtc=*/1);
- crtc_properties_[0].properties.push_back({.id = kCtmPropId, .value = 0});
+ crtc_properties_[0].properties.push_back(
+ {/* .id = */ kCtmPropId, /* .value = */ 0});
fake_drm_->InitializeState(crtc_properties_, plane_properties_,
property_names_, use_atomic_);
@@ -553,7 +560,7 @@ TEST_P(HardwareDisplayPlaneManagerTest, SetGammaCorrection_MissingDegamma) {
}
crtc_properties_[0].properties.push_back(
- {.id = kDegammaLutSizePropId, .value = 1});
+ {/* .id = */ kDegammaLutSizePropId, /* .value = */ 1});
fake_drm_->InitializeState(crtc_properties_, plane_properties_,
property_names_, /*use_atomic=*/true);
@@ -571,7 +578,8 @@ TEST_P(HardwareDisplayPlaneManagerTest, SetGammaCorrection_MissingDegamma) {
TEST_P(HardwareDisplayPlaneManagerTest, SetGammaCorrection_MissingGamma) {
InitializeDrmState(/*crtc_count=*/1, /*planes_per_crtc=*/1);
- crtc_properties_[0].properties.push_back({.id = kCtmPropId, .value = 0});
+ crtc_properties_[0].properties.push_back(
+ {/* .id = */ kCtmPropId, /* .value = */ 0});
fake_drm_->InitializeState(crtc_properties_, plane_properties_,
property_names_, use_atomic_);
@@ -587,7 +595,7 @@ TEST_P(HardwareDisplayPlaneManagerTest, SetGammaCorrection_MissingGamma) {
}
crtc_properties_[0].properties.push_back(
- {.id = kGammaLutSizePropId, .value = 1});
+ {/* .id = */ kGammaLutSizePropId, /* .value = */ 1});
fake_drm_->InitializeState(crtc_properties_, plane_properties_,
property_names_, /*use_atomic=*/true);
@@ -625,7 +633,8 @@ TEST_P(HardwareDisplayPlaneManagerTest, SetGammaCorrection_LegacyGamma) {
TEST_P(HardwareDisplayPlaneManagerTest, SetGammaCorrection_Success) {
InitializeDrmState(/*crtc_count=*/1, /*planes_per_crtc=*/1);
- crtc_properties_[0].properties.push_back({.id = kCtmPropId, .value = 0});
+ crtc_properties_[0].properties.push_back(
+ {/* .id = */ kCtmPropId, /* .value = */ 0});
fake_drm_->InitializeState(crtc_properties_, plane_properties_,
property_names_, use_atomic_);
@@ -634,12 +643,13 @@ TEST_P(HardwareDisplayPlaneManagerTest, SetGammaCorrection_Success) {
EXPECT_EQ(0, fake_drm_->get_commit_count());
crtc_properties_[0].properties.push_back(
- {.id = kDegammaLutSizePropId, .value = 1});
+ {/* .id = */ kDegammaLutSizePropId, /* .value = */ 1});
+ crtc_properties_[0].properties.push_back(
+ {/* .id = */ kDegammaLutPropId, /* .value = */ 0});
crtc_properties_[0].properties.push_back(
- {.id = kDegammaLutPropId, .value = 0});
+ {/* .id = */ kGammaLutSizePropId, /* .value = */ 1});
crtc_properties_[0].properties.push_back(
- {.id = kGammaLutSizePropId, .value = 1});
- crtc_properties_[0].properties.push_back({.id = kGammaLutPropId, .value = 0});
+ {/* .id = */ kGammaLutPropId, /* .value = */ 0});
fake_drm_->InitializeState(crtc_properties_, plane_properties_,
property_names_, use_atomic_);
@@ -712,9 +722,9 @@ TEST_P(HardwareDisplayPlaneManagerTest,
InitializationFailsIfSupportForOutFencePropertiesIsPartial) {
InitializeDrmState(/*crtc_count=*/3, /*planes_per_crtc=*/1);
crtc_properties_[0].properties.push_back(
- {.id = kOutFencePtrPropId, .value = 1});
+ {/* .id = */ kOutFencePtrPropId, /* .value = */ 1});
crtc_properties_[2].properties.push_back(
- {.id = kOutFencePtrPropId, .value = 2});
+ {/* .id = */ kOutFencePtrPropId, /* .value = */ 2});
EXPECT_FALSE(fake_drm_->InitializeStateWithResult(
crtc_properties_, plane_properties_, property_names_, use_atomic_));
@@ -724,11 +734,11 @@ TEST_P(HardwareDisplayPlaneManagerTest,
InitializationSucceedsIfSupportForOutFencePropertiesIsComplete) {
InitializeDrmState(/*crtc_count=*/3, /*planes_per_crtc=*/1);
crtc_properties_[0].properties.push_back(
- {.id = kOutFencePtrPropId, .value = 1});
+ {/* .id = */ kOutFencePtrPropId, /* .value = */ 1});
crtc_properties_[1].properties.push_back(
- {.id = kOutFencePtrPropId, .value = 2});
+ {/* .id = */ kOutFencePtrPropId, /* .value = */ 2});
crtc_properties_[2].properties.push_back(
- {.id = kOutFencePtrPropId, .value = 3});
+ {/* .id = */ kOutFencePtrPropId, /* .value = */ 3});
EXPECT_TRUE(fake_drm_->InitializeStateWithResult(
crtc_properties_, plane_properties_, property_names_, use_atomic_));
@@ -844,11 +854,13 @@ void HardwareDisplayPlaneManagerPlanesReadyTest::RequestPlanesReady(
}
void HardwareDisplayPlaneManagerPlanesReadyTest::UseLegacyManager() {
- plane_manager_ = std::make_unique<ui::HardwareDisplayPlaneManagerLegacy>();
+ plane_manager_ =
+ std::make_unique<ui::HardwareDisplayPlaneManagerLegacy>(fake_drm_.get());
}
void HardwareDisplayPlaneManagerPlanesReadyTest::UseAtomicManager() {
- plane_manager_ = std::make_unique<ui::HardwareDisplayPlaneManagerAtomic>();
+ plane_manager_ =
+ std::make_unique<ui::HardwareDisplayPlaneManagerAtomic>(fake_drm_.get());
}
TEST_F(HardwareDisplayPlaneManagerPlanesReadyTest,
@@ -926,11 +938,11 @@ class HardwareDisplayPlaneAtomicMock : public ui::HardwareDisplayPlaneAtomic {
};
TEST(HardwareDisplayPlaneManagerAtomic, EnableBlend) {
- auto plane_manager =
- std::make_unique<ui::HardwareDisplayPlaneManagerAtomic>();
auto gbm_device = std::make_unique<ui::MockGbmDevice>();
auto drm_device =
base::MakeRefCounted<ui::MockDrmDevice>(std::move(gbm_device));
+ auto plane_manager =
+ std::make_unique<ui::HardwareDisplayPlaneManagerAtomic>(drm_device.get());
ui::HardwareDisplayPlaneList plane_list;
HardwareDisplayPlaneAtomicMock hw_plane;
std::unique_ptr<ui::GbmBuffer> buffer =
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 4b7f5a46d36..e9dfffbfb41 100644
--- a/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc
@@ -84,7 +84,6 @@ MockDrmDevice::MockDrmDevice(std::unique_ptr<GbmDevice> gbm_device)
add_framebuffer_call_count_(0),
remove_framebuffer_call_count_(0),
page_flip_call_count_(0),
- overlay_flip_call_count_(0),
overlay_clear_call_count_(0),
allocate_buffer_count_(0),
set_crtc_expectation_(true),
@@ -92,7 +91,7 @@ MockDrmDevice::MockDrmDevice(std::unique_ptr<GbmDevice> gbm_device)
page_flip_expectation_(true),
create_dumb_buffer_expectation_(true),
current_framebuffer_(0) {
- plane_manager_.reset(new HardwareDisplayPlaneManagerLegacy());
+ plane_manager_.reset(new HardwareDisplayPlaneManagerLegacy(this));
}
// static
@@ -141,12 +140,12 @@ bool MockDrmDevice::InitializeStateWithResult(
plane_properties_ = plane_properties;
property_names_ = property_names;
if (use_atomic) {
- plane_manager_.reset(new HardwareDisplayPlaneManagerAtomic());
+ plane_manager_.reset(new HardwareDisplayPlaneManagerAtomic(this));
} else {
- plane_manager_.reset(new HardwareDisplayPlaneManagerLegacy());
+ plane_manager_.reset(new HardwareDisplayPlaneManagerLegacy(this));
}
- return plane_manager_->Initialize(this);
+ return plane_manager_->Initialize();
}
MockDrmDevice::~MockDrmDevice() {}
@@ -198,6 +197,7 @@ bool MockDrmDevice::SetCrtc(uint32_t crtc_id,
uint32_t framebuffer,
std::vector<uint32_t> connectors,
drmModeModeInfo* mode) {
+ crtc_fb_[crtc_id] = framebuffer;
current_framebuffer_ = framebuffer;
set_crtc_call_count_++;
return set_crtc_expectation_;
@@ -229,11 +229,24 @@ bool MockDrmDevice::AddFramebuffer2(uint32_t width,
uint32_t flags) {
add_framebuffer_call_count_++;
*framebuffer = add_framebuffer_call_count_;
+ framebuffer_ids_.insert(*framebuffer);
return add_framebuffer_expectation_;
}
bool MockDrmDevice::RemoveFramebuffer(uint32_t framebuffer) {
+ {
+ auto it = framebuffer_ids_.find(framebuffer);
+ CHECK(it != framebuffer_ids_.end());
+ framebuffer_ids_.erase(it);
+ }
remove_framebuffer_call_count_++;
+ std::vector<uint32_t> crtcs_to_clear;
+ for (auto crtc_fb : crtc_fb_) {
+ if (crtc_fb.second == framebuffer)
+ crtcs_to_clear.push_back(crtc_fb.first);
+ }
+ for (auto crtc : crtcs_to_clear)
+ crtc_fb_[crtc] = 0;
return true;
}
@@ -246,23 +259,13 @@ bool MockDrmDevice::PageFlip(uint32_t crtc_id,
scoped_refptr<PageFlipRequest> page_flip_request) {
page_flip_call_count_++;
DCHECK(page_flip_request);
+ crtc_fb_[crtc_id] = framebuffer;
current_framebuffer_ = framebuffer;
if (page_flip_expectation_)
callbacks_.push(page_flip_request->AddPageFlip());
return page_flip_expectation_;
}
-bool MockDrmDevice::PageFlipOverlay(uint32_t crtc_id,
- uint32_t framebuffer,
- const gfx::Rect& location,
- const gfx::Rect& source,
- int overlay_plane) {
- if (!framebuffer)
- overlay_clear_call_count_++;
- overlay_flip_call_count_++;
- return true;
-}
-
ScopedDrmPlanePtr MockDrmDevice::GetPlane(uint32_t plane_id) {
PlaneProperties* properties = FindObjectById(plane_id, plane_properties_);
if (!properties)
@@ -434,6 +437,11 @@ bool MockDrmDevice::SetCapability(uint64_t capability, uint64_t value) {
return true;
}
+uint32_t MockDrmDevice::GetFramebufferForCrtc(uint32_t crtc_id) const {
+ auto it = crtc_fb_.find(crtc_id);
+ return it != crtc_fb_.end() ? it->second : 0u;
+}
+
void MockDrmDevice::RunCallbacks() {
while (!callbacks_.empty()) {
PageFlipCallback callback = std::move(callbacks_.front());
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 2e705d00ad5..64279da0cfd 100644
--- a/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.h
+++ b/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.h
@@ -61,7 +61,6 @@ class MockDrmDevice : public DrmDevice {
return remove_framebuffer_call_count_;
}
int get_page_flip_call_count() const { return page_flip_call_count_; }
- int get_overlay_flip_call_count() const { return overlay_flip_call_count_; }
int get_overlay_clear_call_count() const { return overlay_clear_call_count_; }
int get_commit_count() const { return commit_count_; }
int get_set_object_property_count() const {
@@ -131,11 +130,6 @@ class MockDrmDevice : public DrmDevice {
bool PageFlip(uint32_t crtc_id,
uint32_t framebuffer,
scoped_refptr<PageFlipRequest> page_flip_request) override;
- bool PageFlipOverlay(uint32_t crtc_id,
- uint32_t framebuffer,
- const gfx::Rect& location,
- const gfx::Rect& source,
- int overlay_plane) override;
ScopedDrmPlanePtr GetPlane(uint32_t plane_id) override;
ScopedDrmPropertyPtr GetProperty(drmModeConnector* connector,
const char* name) override;
@@ -172,6 +166,7 @@ class MockDrmDevice : public DrmDevice {
uint32_t crtc_id,
const std::vector<display::GammaRampRGBEntry>& lut) override;
bool SetCapability(uint64_t capability, uint64_t value) override;
+ uint32_t GetFramebufferForCrtc(uint32_t crtc_id) const;
private:
~MockDrmDevice() override;
@@ -190,7 +185,6 @@ class MockDrmDevice : public DrmDevice {
int add_framebuffer_call_count_;
int remove_framebuffer_call_count_;
int page_flip_call_count_;
- int overlay_flip_call_count_;
int overlay_clear_call_count_;
int allocate_buffer_count_;
int commit_count_ = 0;
@@ -212,6 +206,9 @@ class MockDrmDevice : public DrmDevice {
std::map<uint32_t, ScopedDrmPropertyBlobPtr> blob_property_map_;
+ std::set<uint32_t> framebuffer_ids_;
+ std::map<uint32_t, uint32_t> crtc_fb_;
+
base::queue<PageFlipCallback> callbacks_;
std::vector<CrtcProperties> crtc_properties_;
diff --git a/chromium/ui/ozone/platform/drm/gpu/mock_gbm_device.cc b/chromium/ui/ozone/platform/drm/gpu/mock_gbm_device.cc
index d7b298f9d51..dc640dd1f38 100644
--- a/chromium/ui/ozone/platform/drm/gpu/mock_gbm_device.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/mock_gbm_device.cc
@@ -10,6 +10,7 @@
#include "base/logging.h"
#include "base/numerics/safe_math.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkSurface.h"
#include "ui/ozone/common/linux/drm_util_linux.h"
#include "ui/ozone/common/linux/gbm_buffer.h"
@@ -69,6 +70,8 @@ class MockGbmBuffer final : public ui::GbmBuffer {
return gfx::NativePixmapHandle();
}
+ sk_sp<SkSurface> GetSurface() override { return nullptr; }
+
private:
uint32_t format_ = 0;
uint64_t format_modifier_ = 0;
diff --git a/chromium/ui/ozone/platform/drm/gpu/page_flip_request.h b/chromium/ui/ozone/platform/drm/gpu/page_flip_request.h
index 2aad6034057..d24d6bbc0da 100644
--- a/chromium/ui/ozone/platform/drm/gpu/page_flip_request.h
+++ b/chromium/ui/ozone/platform/drm/gpu/page_flip_request.h
@@ -45,8 +45,7 @@ class PageFlipRequest : public base::RefCounted<PageFlipRequest> {
PresentationOnceCallback callback_;
int page_flip_count_ = 0;
- base::TimeDelta refresh_interval_;
- gfx::SwapResult result_ = gfx::SwapResult::SWAP_ACK;
+ const base::TimeDelta refresh_interval_;
DISALLOW_COPY_AND_ASSIGN(PageFlipRequest);
};
diff --git a/chromium/ui/ozone/platform/drm/gpu/screen_manager.cc b/chromium/ui/ozone/platform/drm/gpu/screen_manager.cc
index 17a2d1b50f3..5fe1773665d 100644
--- a/chromium/ui/ozone/platform/drm/gpu/screen_manager.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/screen_manager.cc
@@ -10,16 +10,18 @@
#include "base/files/platform_file.h"
#include "third_party/skia/include/core/SkCanvas.h"
+#include "third_party/skia/include/core/SkSurface.h"
#include "ui/display/types/display_snapshot.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/gpu_fence.h"
+#include "ui/gfx/skia_util.h"
#include "ui/ozone/common/linux/gbm_buffer.h"
#include "ui/ozone/platform/drm/common/drm_util.h"
#include "ui/ozone/platform/drm/gpu/crtc_controller.h"
-#include "ui/ozone/platform/drm/gpu/drm_console_buffer.h"
#include "ui/ozone/platform/drm/gpu/drm_device.h"
+#include "ui/ozone/platform/drm/gpu/drm_dumb_buffer.h"
#include "ui/ozone/platform/drm/gpu/drm_framebuffer.h"
#include "ui/ozone/platform/drm/gpu/drm_window.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_controller.h"
@@ -29,25 +31,19 @@ namespace ui {
namespace {
// Copies the contents of the saved framebuffer from the CRTCs in |controller|
-// to the new modeset buffer |buffer|.
-void FillModesetBuffer(const scoped_refptr<DrmDevice>& drm,
+// to the surface for the new modeset buffer |surface|.
+bool FillModesetBuffer(const scoped_refptr<DrmDevice>& drm,
HardwareDisplayController* controller,
- DrmFramebuffer* buffer) {
- DrmConsoleBuffer modeset_buffer(drm, buffer->opaque_framebuffer_id());
- if (!modeset_buffer.Initialize()) {
- VLOG(2) << "Failed to grab framebuffer " << buffer->opaque_framebuffer_id();
- return;
- }
-
+ SkSurface* surface,
+ uint32_t fourcc_format) {
DCHECK(!controller->crtc_controllers().empty());
CrtcController* first_crtc = controller->crtc_controllers()[0].get();
ScopedDrmCrtcPtr saved_crtc(drm->GetCrtc(first_crtc->crtc()));
if (!saved_crtc || !saved_crtc->buffer_id) {
VLOG(2) << "Crtc has no saved state or wasn't modeset";
- return;
+ return false;
}
- uint32_t fourcc_format = buffer->framebuffer_pixel_format();
const auto& modifiers = controller->GetFormatModifiers(fourcc_format);
for (const uint64_t modifier : modifiers) {
// A value of 0 means DRM_FORMAT_MOD_NONE. If the CRTC has any other
@@ -56,30 +52,32 @@ void FillModesetBuffer(const scoped_refptr<DrmDevice>& drm,
if (modifier) {
VLOG(2) << "Crtc has a modifier and we might not know how to interpret "
"the fb.";
- return;
+ return false;
}
}
// If the display controller is in mirror mode, the CRTCs should be sharing
// the same framebuffer.
- DrmConsoleBuffer saved_buffer(drm, saved_crtc->buffer_id);
- if (!saved_buffer.Initialize()) {
+ DrmDumbBuffer saved_buffer(drm);
+ if (!saved_buffer.InitializeFromFramebuffer(saved_crtc->buffer_id)) {
VLOG(2) << "Failed to grab saved framebuffer " << saved_crtc->buffer_id;
- return;
+ return false;
}
// Don't copy anything if the sizes mismatch. This can happen when the user
// changes modes.
- if (saved_buffer.canvas()->getBaseLayerSize() !=
- modeset_buffer.canvas()->getBaseLayerSize()) {
+ if (saved_buffer.GetCanvas()->getBaseLayerSize() !=
+ surface->getCanvas()->getBaseLayerSize()) {
VLOG(2) << "Previous buffer has a different size than modeset buffer";
- return;
+ return false;
}
SkPaint paint;
// Copy the source buffer. Do not perform any blending.
paint.setBlendMode(SkBlendMode::kSrc);
- modeset_buffer.canvas()->drawImage(saved_buffer.image(), 0, 0, &paint);
+ surface->getCanvas()->drawImage(saved_buffer.surface()->makeImageSnapshot(),
+ 0, 0, &paint);
+ return true;
}
CrtcController* GetCrtcController(HardwareDisplayController* controller,
@@ -345,8 +343,8 @@ void ScreenManager::UpdateControllerToWindowMapping() {
if (it != window_to_controller_map.end())
controller = it->second;
- bool should_enable =
- controller && pair.second->GetController() != controller;
+ bool should_enable = controller && pair.second->GetController() &&
+ pair.second->GetController() != controller;
pair.second->SetController(controller);
// If we're moving windows between controllers modeset the controller
@@ -400,7 +398,16 @@ DrmOverlayPlane ScreenManager::GetModesetBuffer(
LOG(ERROR) << "Failed to add framebuffer for scanout buffer";
return DrmOverlayPlane::Error();
}
- FillModesetBuffer(drm, controller, framebuffer.get());
+
+ sk_sp<SkSurface> surface = buffer->GetSurface();
+ if (!surface) {
+ VLOG(2) << "Can't get a SkSurface from the modeset gbm buffer.";
+ } else if (!FillModesetBuffer(drm, controller, surface.get(),
+ buffer->GetFormat())) {
+ // If we fail to fill the modeset buffer, clear it black to avoid displaying
+ // an uninitialized framebuffer.
+ surface->getCanvas()->clear(SK_ColorBLACK);
+ }
return DrmOverlayPlane(framebuffer, nullptr);
}
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 1d05b1d9d76..e8cae25799c 100644
--- a/chromium/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/screen_manager_unittest.cc
@@ -572,6 +572,26 @@ TEST_F(ScreenManagerTest, DISABLED_RejectBufferWithIncompatibleModifiers) {
window->Shutdown();
}
+TEST_F(ScreenManagerTest, ConfigureDisplayControllerShouldModesetOnce) {
+ std::unique_ptr<ui::DrmWindow> window(
+ new ui::DrmWindow(1, device_manager_.get(), screen_manager_.get()));
+ window->Initialize();
+ window->SetBounds(GetPrimaryBounds());
+ screen_manager_->AddWindow(1, std::move(window));
+
+ screen_manager_->AddDisplayController(drm_, kPrimaryCrtc, kPrimaryConnector);
+ screen_manager_->ConfigureDisplayController(
+ drm_, kPrimaryCrtc, kPrimaryConnector, GetPrimaryBounds().origin(),
+ kDefaultMode);
+
+ // When a window that had no controller becomes associated with a new
+ // controller, expect the crtc to be modeset once.
+ EXPECT_EQ(drm_->get_set_crtc_call_count(), 1);
+
+ window = screen_manager_->RemoveWindow(1);
+ window->Shutdown();
+}
+
TEST(ScreenManagerTest2, ShouldNotHardwareMirrorDifferentDrmDevices) {
auto gbm_device1 = std::make_unique<MockGbmDevice>();
auto drm_device1 =
@@ -681,4 +701,56 @@ TEST(ScreenManagerTest2, ShouldNotHardwareMirrorDifferentDrmDevices) {
screen_manager.RemoveWindow(3)->Shutdown();
}
+// crbug.com/888553
+TEST(ScreenManagerTest2, ShouldNotUnbindFramebufferOnJoiningMirror) {
+ auto gbm_device = std::make_unique<MockGbmDevice>();
+ auto drm_device = base::MakeRefCounted<MockDrmDevice>(std::move(gbm_device));
+ DrmDeviceManager drm_device_manager(nullptr);
+ ScreenManager screen_manager;
+
+ constexpr uint32_t kCrtc39 = 39;
+ constexpr uint32_t kConnector43 = 43;
+ constexpr uint32_t kCrtc41 = 41;
+ constexpr uint32_t kConnector46 = 46;
+
+ constexpr drmModeModeInfo kMode1080p60 = {
+ /* clock= */ 148500,
+ /* hdisplay= */ 1920,
+ /* hsync_start= */ 2008,
+ /* hsync_end= */ 2052,
+ /* htotal= */ 2200,
+ /* hskew= */ 0,
+ /* vdisplay= */ 1080,
+ /* vsync_start= */ 1084,
+ /* vsync_end= */ 1089,
+ /* vtotal= */ 1125,
+ /* vscan= */ 0,
+ /* vrefresh= */ 60,
+ /* flags= */ 0xa,
+ /* type= */ 64,
+ /* name= */ "1920x1080",
+ };
+
+ // Both displays connect at startup.
+ {
+ auto window1 =
+ std::make_unique<DrmWindow>(1, &drm_device_manager, &screen_manager);
+ window1->Initialize();
+ screen_manager.AddWindow(1, std::move(window1));
+ screen_manager.GetWindow(1)->SetBounds(gfx::Rect(0, 0, 1920, 1080));
+ screen_manager.AddDisplayController(drm_device, kCrtc39, kConnector43);
+ screen_manager.AddDisplayController(drm_device, kCrtc41, kConnector46);
+ screen_manager.ConfigureDisplayController(drm_device, kCrtc39, kConnector43,
+ gfx::Point(0, 0), kMode1080p60);
+ screen_manager.ConfigureDisplayController(drm_device, kCrtc41, kConnector46,
+ gfx::Point(0, 0), kMode1080p60);
+ }
+
+ EXPECT_NE(0u, drm_device->GetFramebufferForCrtc(kCrtc39));
+ EXPECT_NE(0u, drm_device->GetFramebufferForCrtc(kCrtc41));
+
+ // Cleanup.
+ screen_manager.RemoveWindow(1)->Shutdown();
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/gpu/vulkan_implementation_gbm.cc b/chromium/ui/ozone/platform/drm/gpu/vulkan_implementation_gbm.cc
index b517393492c..276002409b7 100644
--- a/chromium/ui/ozone/platform/drm/gpu/vulkan_implementation_gbm.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/vulkan_implementation_gbm.cc
@@ -31,7 +31,7 @@ bool VulkanImplementationGbm::InitializeVulkanInstance() {
"VK_KHR_external_fence_capabilities",
"VK_KHR_get_physical_device_properties2",
};
- if (!vulkan_instance_.Initialize(required_extensions)) {
+ if (!vulkan_instance_.Initialize(required_extensions, {})) {
vulkan_instance_.Destroy();
return false;
}
diff --git a/chromium/ui/ozone/platform/drm/host/drm_cursor.h b/chromium/ui/ozone/platform/drm/host/drm_cursor.h
index a31f27f2422..40f751db193 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_cursor.h
+++ b/chromium/ui/ozone/platform/drm/host/drm_cursor.h
@@ -111,7 +111,7 @@ class DrmCursor : public CursorDelegateEvdev {
// The bounds that the cursor is confined to in |window|.
gfx::Rect confined_bounds_;
- DrmWindowHostManager* window_manager_; // Not owned.
+ DrmWindowHostManager* const window_manager_; // Not owned.
std::unique_ptr<DrmCursorProxy> proxy_;
diff --git a/chromium/ui/ozone/platform/drm/host/drm_device_connector.h b/chromium/ui/ozone/platform/drm/host/drm_device_connector.h
index 8de058eba6d..9c2f5d9f4b1 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_device_connector.h
+++ b/chromium/ui/ozone/platform/drm/host/drm_device_connector.h
@@ -58,13 +58,13 @@ class DrmDeviceConnector : public GpuPlatformSupportHost {
bool am_running_in_ws_mode() { return !!ws_runner_; }
// This will be present if the Viz host has a service manager.
- service_manager::Connector* connector_;
+ service_manager::Connector* const connector_;
// This will be used if we are operating under content/gpu without a service
// manager.
GpuHostBindInterfaceCallback binder_callback_;
- scoped_refptr<HostDrmDevice> host_drm_device_;
+ const scoped_refptr<HostDrmDevice> host_drm_device_;
scoped_refptr<base::SingleThreadTaskRunner> ws_runner_;
DISALLOW_COPY_AND_ASSIGN(DrmDeviceConnector);
diff --git a/chromium/ui/ozone/platform/drm/host/drm_display_host.h b/chromium/ui/ozone/platform/drm/host/drm_display_host.h
index 55b5de5bf7b..1311e66db3d 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_display_host.h
+++ b/chromium/ui/ozone/platform/drm/host/drm_display_host.h
@@ -56,7 +56,7 @@ class DrmDisplayHost : public GpuThreadObserver {
// Calls all the callbacks with failure.
void ClearCallbacks();
- GpuThreadAdapter* sender_; // Not owned.
+ GpuThreadAdapter* const sender_; // Not owned.
std::unique_ptr<display::DisplaySnapshot> snapshot_;
diff --git a/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.h b/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.h
index dae7f3bbc1e..3b77e9bc79a 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.h
+++ b/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.h
@@ -98,17 +98,17 @@ class DrmDisplayHostManager : public DeviceEventObserver, GpuThreadObserver {
void NotifyDisplayDelegate() const;
- GpuThreadAdapter* proxy_; // Not owned.
- DeviceManager* device_manager_; // Not owned.
- DrmOverlayManager* overlay_manager_; // Not owned.
- InputControllerEvdev* input_controller_; // Not owned.
+ GpuThreadAdapter* const proxy_; // Not owned.
+ DeviceManager* const device_manager_; // Not owned.
+ DrmOverlayManager* const overlay_manager_; // Not owned.
+ InputControllerEvdev* const input_controller_; // Not owned.
DrmNativeDisplayDelegate* delegate_ = nullptr; // Not owned.
// File path for the primary graphics card which is opened by default in the
// GPU process. We'll avoid opening this in hotplug events since it will race
// with the GPU process trying to open it and aquire DRM master.
- base::FilePath primary_graphics_card_path_;
+ const base::FilePath primary_graphics_card_path_;
// Keeps track if there is a dummy display. This happens on initialization
// when there is no connection to the GPU to update the displays.
diff --git a/chromium/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h b/chromium/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h
index e31327b7515..45d45b8a8ef 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h
+++ b/chromium/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h
@@ -128,7 +128,7 @@ class DrmGpuPlatformSupportHost : public GpuPlatformSupportHost,
DrmDisplayHostManager* display_manager_; // Not owned.
DrmOverlayManager* overlay_manager_; // Not owned.
- DrmCursor* cursor_; // Not owned.
+ DrmCursor* const cursor_; // Not owned.
base::ObserverList<GpuThreadObserver>::Unchecked gpu_thread_observers_;
base::WeakPtr<DrmGpuPlatformSupportHost> weak_ptr_;
diff --git a/chromium/ui/ozone/platform/drm/host/drm_native_display_delegate.h b/chromium/ui/ozone/platform/drm/host/drm_native_display_delegate.h
index 843d7e3d586..ce322d3c10b 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_native_display_delegate.h
+++ b/chromium/ui/ozone/platform/drm/host/drm_native_display_delegate.h
@@ -49,7 +49,7 @@ class DrmNativeDisplayDelegate : public display::NativeDisplayDelegate {
display::FakeDisplayController* GetFakeDisplayController() override;
private:
- DrmDisplayHostManager* display_manager_; // Not owned.
+ DrmDisplayHostManager* const display_manager_; // Not owned.
base::ObserverList<display::NativeDisplayObserver>::Unchecked observers_;
diff --git a/chromium/ui/ozone/platform/drm/host/drm_overlay_candidates_host.h b/chromium/ui/ozone/platform/drm/host/drm_overlay_candidates_host.h
index 9e2c8bce831..6e591602314 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_overlay_candidates_host.h
+++ b/chromium/ui/ozone/platform/drm/host/drm_overlay_candidates_host.h
@@ -40,8 +40,8 @@ class DrmOverlayCandidatesHost : public OverlayCandidatesOzone {
void CheckOverlaySupport(OverlaySurfaceCandidateList* candidates) override;
private:
- DrmOverlayManager* overlay_manager_; // Not owned.
- gfx::AcceleratedWidget widget_;
+ DrmOverlayManager* const overlay_manager_; // Not owned.
+ const gfx::AcceleratedWidget widget_;
DISALLOW_COPY_AND_ASSIGN(DrmOverlayCandidatesHost);
};
diff --git a/chromium/ui/ozone/platform/drm/host/drm_overlay_manager.h b/chromium/ui/ozone/platform/drm/host/drm_overlay_manager.h
index 31578262453..ea39854d464 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_overlay_manager.h
+++ b/chromium/ui/ozone/platform/drm/host/drm_overlay_manager.h
@@ -70,8 +70,8 @@ class DrmOverlayManager : public OverlayManagerOzone {
// Whether we have DRM atomic capabilities and we can support HW overlays.
bool supports_overlays_ = false;
- GpuThreadAdapter* proxy_; // Not owned.
- DrmWindowHostManager* window_manager_; // Not owned.
+ GpuThreadAdapter* const proxy_; // Not owned.
+ DrmWindowHostManager* const window_manager_; // Not owned.
// List of all OverlaySurfaceCandidate instances which have been requested
// for validation and/or validated.
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 073a1ade8e8..c935c7b9f2a 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_window_host.h
+++ b/chromium/ui/ozone/platform/drm/host/drm_window_host.h
@@ -92,16 +92,16 @@ class DrmWindowHost : public PlatformWindow,
private:
void SendBoundsChange();
- PlatformWindowDelegate* delegate_; // Not owned.
- GpuThreadAdapter* sender_; // Not owned.
- EventFactoryEvdev* event_factory_; // Not owned.
- DrmCursor* cursor_; // Not owned.
- DrmWindowHostManager* window_manager_; // Not owned.
- DrmDisplayHostManager* display_manager_; // Not owned.
- DrmOverlayManager* overlay_manager_; // Not owned.
+ PlatformWindowDelegate* const delegate_; // Not owned.
+ GpuThreadAdapter* const sender_; // Not owned.
+ EventFactoryEvdev* const event_factory_; // Not owned.
+ DrmCursor* const cursor_; // Not owned.
+ DrmWindowHostManager* const window_manager_; // Not owned.
+ DrmDisplayHostManager* const display_manager_; // Not owned.
+ DrmOverlayManager* const overlay_manager_; // Not owned.
gfx::Rect bounds_;
- gfx::AcceleratedWidget widget_;
+ const gfx::AcceleratedWidget widget_;
gfx::Rect cursor_confined_bounds_;
diff --git a/chromium/ui/ozone/platform/drm/host/host_drm_device.h b/chromium/ui/ozone/platform/drm/host/host_drm_device.h
index 5ec11b186b9..3372987d2bb 100644
--- a/chromium/ui/ozone/platform/drm/host/host_drm_device.h
+++ b/chromium/ui/ozone/platform/drm/host/host_drm_device.h
@@ -151,7 +151,7 @@ class HostDrmDevice : public base::RefCountedThreadSafe<HostDrmDevice>,
DrmDisplayHostManager* display_manager_; // Not owned.
DrmOverlayManager* overlay_manager_; // Not owned.
- DrmCursor* cursor_; // Not owned.
+ DrmCursor* const cursor_; // Not owned.
std::unique_ptr<HostCursorProxy> cursor_proxy_;
diff --git a/chromium/ui/ozone/platform/scenic/BUILD.gn b/chromium/ui/ozone/platform/scenic/BUILD.gn
index 4ba231915dd..3722c13aa84 100644
--- a/chromium/ui/ozone/platform/scenic/BUILD.gn
+++ b/chromium/ui/ozone/platform/scenic/BUILD.gn
@@ -4,6 +4,10 @@
assert(is_fuchsia)
+import("//gpu/vulkan/features.gni")
+
+visibility = [ "//ui/ozone/*" ]
+
source_set("scenic") {
sources = [
"client_native_pixmap_factory_scenic.cc",
@@ -29,12 +33,12 @@ source_set("scenic") {
deps = [
"//base",
"//skia",
- "//third_party/fuchsia-sdk:gfx",
- "//third_party/fuchsia-sdk:images",
- "//third_party/fuchsia-sdk:mem",
- "//third_party/fuchsia-sdk:scenic",
- "//third_party/fuchsia-sdk:viewsv1",
- "//third_party/fuchsia-sdk:viewsv1token",
+ "//third_party/fuchsia-sdk/sdk:gfx",
+ "//third_party/fuchsia-sdk/sdk:images",
+ "//third_party/fuchsia-sdk/sdk:mem",
+ "//third_party/fuchsia-sdk/sdk:scenic",
+ "//third_party/fuchsia-sdk/sdk:viewsv1",
+ "//third_party/fuchsia-sdk/sdk:viewsv1token",
"//ui/base",
"//ui/display/manager",
"//ui/events:dom_keycode_converter",
@@ -44,4 +48,13 @@ source_set("scenic") {
"//ui/ozone/common",
"//ui/platform_window",
]
+
+ if (enable_vulkan) {
+ sources += [
+ "vulkan_implementation_scenic.cc",
+ "vulkan_implementation_scenic.h",
+ "vulkan_magma.h",
+ ]
+ defines += [ "VK_USE_PLATFORM_MAGMA_KHR" ]
+ }
}
diff --git a/chromium/ui/ozone/platform/scenic/DEPS b/chromium/ui/ozone/platform/scenic/DEPS
index 41cd997bd46..defb45e8062 100644
--- a/chromium/ui/ozone/platform/scenic/DEPS
+++ b/chromium/ui/ozone/platform/scenic/DEPS
@@ -1,3 +1,4 @@
include_rules = [
"+third_party/skia/include",
+ "+ui/base/ime",
]
diff --git a/chromium/ui/ozone/platform/scenic/ozone_platform_scenic.cc b/chromium/ui/ozone/platform/scenic/ozone_platform_scenic.cc
index 6100a7f4ff4..fde7eea29c9 100644
--- a/chromium/ui/ozone/platform/scenic/ozone_platform_scenic.cc
+++ b/chromium/ui/ozone/platform/scenic/ozone_platform_scenic.cc
@@ -4,9 +4,14 @@
#include "ui/ozone/platform/scenic/ozone_platform_scenic.h"
+#include <memory>
+#include <utility>
+#include <vector>
+
#include "base/logging.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
+#include "base/message_loop/message_loop_current.h"
#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
#include "ui/display/manager/fake_display_delegate.h"
#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
@@ -33,6 +38,7 @@ const OzonePlatform::PlatformProperties kScenicPlatformProperties(
/*needs_view_owner_request=*/true,
/*custom_frame_pref_default=*/false,
/*use_system_title_bar=*/false,
+ /*requires_mojo=*/false,
std::vector<gfx::BufferFormat>());
class ScenicPlatformEventSource : public ui::PlatformEventSource {
@@ -45,13 +51,15 @@ class ScenicPlatformEventSource : public ui::PlatformEventSource {
};
// OzonePlatform for Scenic.
-class OzonePlatformScenic : public OzonePlatform {
+class OzonePlatformScenic
+ : public OzonePlatform,
+ public base::MessageLoopCurrent::DestructionObserver {
public:
- OzonePlatformScenic() : surface_factory_(&window_manager_) {}
+ OzonePlatformScenic()
+ : window_manager_(std::make_unique<ScenicWindowManager>()),
+ surface_factory_(window_manager_.get()) {}
~OzonePlatformScenic() override = default;
- ScenicWindowManager* window_manager() { return &window_manager_; }
-
// OzonePlatform implementation.
ui::SurfaceFactoryOzone* GetSurfaceFactoryOzone() override {
return &surface_factory_;
@@ -86,7 +94,8 @@ class OzonePlatformScenic : public OzonePlatform {
return nullptr;
}
return std::make_unique<ScenicWindow>(
- &window_manager_, delegate, std::move(properties.view_owner_request));
+ window_manager_.get(), delegate,
+ std::move(properties.view_owner_request));
}
const PlatformProperties& GetPlatformProperties() override {
@@ -100,7 +109,7 @@ class OzonePlatformScenic : public OzonePlatform {
}
std::unique_ptr<PlatformScreen> CreateScreen() override {
- return window_manager_.CreateScreen();
+ return window_manager_->CreateScreen();
}
void InitializeUI(const InitParams& params) override {
@@ -113,12 +122,20 @@ class OzonePlatformScenic : public OzonePlatform {
input_controller_ = CreateStubInputController();
cursor_factory_ozone_ = std::make_unique<BitmapCursorFactoryOzone>();
gpu_platform_support_host_.reset(CreateStubGpuPlatformSupportHost());
+
+ base::MessageLoopCurrent::Get()->AddDestructionObserver(this);
}
void InitializeGPU(const InitParams& params) override {}
private:
- ScenicWindowManager window_manager_;
+ // Performs graceful cleanup tasks on main message loop teardown.
+ void Shutdown() { window_manager_.reset(); }
+
+ // base::MessageLoopCurrent::DestructionObserver implementation.
+ void WillDestroyCurrentMessageLoop() override { Shutdown(); }
+
+ std::unique_ptr<ScenicWindowManager> window_manager_;
ScenicSurfaceFactory surface_factory_;
std::unique_ptr<PlatformEventSource> platform_event_source_;
diff --git a/chromium/ui/ozone/platform/scenic/scenic_screen.h b/chromium/ui/ozone/platform/scenic/scenic_screen.h
index be61a051f4f..b55e4bafbc9 100644
--- a/chromium/ui/ozone/platform/scenic/scenic_screen.h
+++ b/chromium/ui/ozone/platform/scenic/scenic_screen.h
@@ -49,7 +49,7 @@ class ScenicScreen : public PlatformScreen {
DisplayVector displays_;
- base::ObserverList<display::DisplayObserver>::Unchecked observers_;
+ base::ObserverList<display::DisplayObserver> observers_;
base::WeakPtrFactory<ScenicScreen> weak_factory_;
diff --git a/chromium/ui/ozone/platform/scenic/scenic_session.cc b/chromium/ui/ozone/platform/scenic/scenic_session.cc
index ff23a494ee3..c29bc82cc3e 100644
--- a/chromium/ui/ozone/platform/scenic/scenic_session.cc
+++ b/chromium/ui/ozone/platform/scenic/scenic_session.cc
@@ -103,6 +103,21 @@ ScenicSession::ResourceId ScenicSession::CreateImage(
return image_id;
}
+ScenicSession::ResourceId ScenicSession::CreateImagePipe(
+ fidl::InterfaceRequest<fuchsia::images::ImagePipe> request) {
+ fuchsia::ui::gfx::ImagePipeArgs image_pipe;
+ image_pipe.image_pipe_request = std::move(request);
+
+ fuchsia::ui::gfx::ResourceArgs resource;
+ resource.set_image_pipe(std::move(image_pipe));
+
+ ResourceId image_pipe_id = AllocateResourceId();
+ EnqueueGfxCommand(
+ NewCreateResourceCommand(image_pipe_id, std::move(resource)));
+
+ return image_pipe_id;
+}
+
ScenicSession::ResourceId ScenicSession::ImportResource(
fuchsia::ui::gfx::ImportSpec spec,
zx::eventpair import_token) {
@@ -261,12 +276,12 @@ void ScenicSession::Close() {
session_listener_binding_.Unbind();
}
-void ScenicSession::OnError(fidl::StringPtr error) {
+void ScenicSession::OnScenicError(fidl::StringPtr error) {
Close();
listener_->OnScenicError(error);
}
-void ScenicSession::OnEvent(
+void ScenicSession::OnScenicEvent(
fidl::VectorPtr<fuchsia::ui::scenic::Event> events) {
listener_->OnScenicEvents(events.get());
}
diff --git a/chromium/ui/ozone/platform/scenic/scenic_session.h b/chromium/ui/ozone/platform/scenic/scenic_session.h
index 7e8b7ddfd23..ad81b47a523 100644
--- a/chromium/ui/ozone/platform/scenic/scenic_session.h
+++ b/chromium/ui/ozone/platform/scenic/scenic_session.h
@@ -59,6 +59,8 @@ class ScenicSession : public fuchsia::ui::scenic::SessionListener {
ResourceId CreateImage(ResourceId memory_id,
ResourceId memory_offset,
fuchsia::images::ImageInfo info);
+ ResourceId CreateImagePipe(
+ fidl::InterfaceRequest<fuchsia::images::ImagePipe> request);
ResourceId ImportResource(fuchsia::ui::gfx::ImportSpec spec,
zx::eventpair import_token);
ResourceId CreateEntityNode();
@@ -83,8 +85,9 @@ class ScenicSession : public fuchsia::ui::scenic::SessionListener {
private:
// fuchsia::ui::scenic::SessionListener interface.
- void OnError(fidl::StringPtr error) override;
- void OnEvent(fidl::VectorPtr<fuchsia::ui::scenic::Event> events) override;
+ void OnScenicError(fidl::StringPtr error) override;
+ void OnScenicEvent(
+ fidl::VectorPtr<fuchsia::ui::scenic::Event> events) override;
// Allocates a new unique resource id.
ResourceId AllocateResourceId();
diff --git a/chromium/ui/ozone/platform/scenic/scenic_surface_factory.cc b/chromium/ui/ozone/platform/scenic/scenic_surface_factory.cc
index 636f3a81ba4..7b444c46bdd 100644
--- a/chromium/ui/ozone/platform/scenic/scenic_surface_factory.cc
+++ b/chromium/ui/ozone/platform/scenic/scenic_surface_factory.cc
@@ -15,6 +15,10 @@
#include "ui/ozone/platform/scenic/scenic_window_canvas.h"
#include "ui/ozone/platform/scenic/scenic_window_manager.h"
+#if BUILDFLAG(ENABLE_VULKAN)
+#include "ui/ozone/platform/scenic/vulkan_implementation_scenic.h"
+#endif
+
namespace ui {
namespace {
@@ -100,4 +104,11 @@ scoped_refptr<gfx::NativePixmap> ScenicSurfaceFactory::CreateNativePixmap(
return new ScenicPixmap(widget, size, format);
}
+#if BUILDFLAG(ENABLE_VULKAN)
+std::unique_ptr<gpu::VulkanImplementation>
+ScenicSurfaceFactory::CreateVulkanImplementation() {
+ return std::make_unique<ui::VulkanImplementationScenic>(window_manager_);
+}
+#endif
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/scenic/scenic_surface_factory.h b/chromium/ui/ozone/platform/scenic/scenic_surface_factory.h
index 077b5131ba1..016b09f2378 100644
--- a/chromium/ui/ozone/platform/scenic/scenic_surface_factory.h
+++ b/chromium/ui/ozone/platform/scenic/scenic_surface_factory.h
@@ -9,6 +9,7 @@
#include <vector>
#include "base/macros.h"
+#include "gpu/vulkan/buildflags.h"
#include "ui/ozone/public/gl_ozone.h"
#include "ui/ozone/public/surface_factory_ozone.h"
@@ -33,6 +34,10 @@ class ScenicSurfaceFactory : public SurfaceFactoryOzone {
gfx::Size size,
gfx::BufferFormat format,
gfx::BufferUsage usage) override;
+#if BUILDFLAG(ENABLE_VULKAN)
+ std::unique_ptr<gpu::VulkanImplementation> CreateVulkanImplementation()
+ override;
+#endif
private:
ScenicWindowManager* const window_manager_;
diff --git a/chromium/ui/ozone/platform/scenic/scenic_window.cc b/chromium/ui/ozone/platform/scenic/scenic_window.cc
index 13b3d78d265..c8622cd46ad 100644
--- a/chromium/ui/ozone/platform/scenic/scenic_window.cc
+++ b/chromium/ui/ozone/platform/scenic/scenic_window.cc
@@ -6,6 +6,7 @@
#include <fuchsia/sys/cpp/fidl.h>
#include <algorithm>
+#include <memory>
#include <string>
#include <utility>
#include <vector>
@@ -13,7 +14,6 @@
#include "base/fuchsia/fuchsia_logging.h"
#include "ui/events/event.h"
#include "ui/events/event_constants.h"
-#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/events/keycodes/keyboard_code_conversion.h"
#include "ui/events/ozone/events_ozone.h"
#include "ui/events/platform/platform_event_source.h"
@@ -22,24 +22,6 @@
namespace ui {
-namespace {
-
-const uint32_t kUsbHidKeyboardPage = 0x07;
-
-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
-
ScenicWindow::ScenicWindow(
ScenicWindowManager* window_manager,
PlatformWindowDelegate* delegate,
@@ -48,6 +30,7 @@ ScenicWindow::ScenicWindow(
: manager_(window_manager),
delegate_(delegate),
window_id_(manager_->AddWindow(this)),
+ event_dispatcher_(this),
view_listener_binding_(this),
scenic_session_(manager_->GetScenic(), this),
input_listener_binding_(this) {
@@ -68,7 +51,7 @@ ScenicWindow::ScenicWindow(
scenic_session_.AddNodeChild(parent_node_id_, node_id_);
// Subscribe to metrics events from the parent node. These events are used to
- // get |device_pixel_ratio_| for the screen.
+ // get the device pixel ratio for the screen.
scenic_session_.SetEventMask(parent_node_id_,
fuchsia::ui::gfx::kMetricsEventMask);
@@ -82,6 +65,8 @@ ScenicWindow::ScenicWindow(
fit::bind_member(this, &ScenicWindow::OnViewError));
// Setup input event listener.
+ // TODO(crbug.com/881591): Migrate off InputConnection and use IMEService
+ // for receiving keyboard input instead.
fuchsia::sys::ServiceProviderPtr view_service_provider;
view_->GetServiceProvider(view_service_provider.NewRequest());
view_service_provider->ConnectToService(
@@ -225,6 +210,7 @@ void ScenicWindow::UpdateSize() {
scenic_session_.SetNodeShape(shape_id_, rect_id);
scenic_session_.SetNodeTranslation(shape_id_, translation);
scenic_session_.ReleaseResource(rect_id);
+ scenic_session_.Present();
delegate_->OnBoundsChanged(size_rect);
}
@@ -273,32 +259,11 @@ void ScenicWindow::OnEvent(fuchsia::ui::input::InputEvent event,
OnEventCallback callback) {
bool result = false;
- switch (event.Which()) {
- case fuchsia::ui::input::InputEvent::Tag::kPointer:
- switch (event.pointer().type) {
- case fuchsia::ui::input::PointerEventType::MOUSE:
- result = OnMouseEvent(event.pointer());
- break;
- case fuchsia::ui::input::PointerEventType::TOUCH:
- result = OnTouchEvent(event.pointer());
- break;
- case fuchsia::ui::input::PointerEventType::STYLUS:
- case fuchsia::ui::input::PointerEventType::INVERTED_STYLUS:
- NOTIMPLEMENTED() << "Stylus input is not yet supported.";
- break;
- }
- break;
-
- case fuchsia::ui::input::InputEvent::Tag::kKeyboard:
- result = OnKeyboardEvent(event.keyboard());
- break;
-
- case fuchsia::ui::input::InputEvent::Tag::kFocus:
- result = OnFocusEvent(event.focus());
- break;
-
- case fuchsia::ui::input::InputEvent::Tag::Invalid:
- break;
+ if (event.is_focus()) {
+ delegate_->OnActivationChanged(event.focus().focused);
+ result = true;
+ } else {
+ result = event_dispatcher_.ProcessEvent(event);
}
callback(result);
@@ -309,131 +274,14 @@ void ScenicWindow::OnViewError() {
delegate_->OnClosed();
}
-bool ScenicWindow::OnMouseEvent(const fuchsia::ui::input::PointerEvent& event) {
- int flags = 0;
- if (event.buttons & 1)
- flags |= EF_LEFT_MOUSE_BUTTON;
- if (event.buttons & 2)
- flags |= EF_RIGHT_MOUSE_BUTTON;
- if (event.buttons & 4)
- flags |= EF_MIDDLE_MOUSE_BUTTON;
-
- EventType event_type;
-
- switch (event.phase) {
- case fuchsia::ui::input::PointerEventPhase::DOWN:
- event_type = ET_MOUSE_PRESSED;
- break;
- case fuchsia::ui::input::PointerEventPhase::MOVE:
- event_type = flags ? ET_MOUSE_DRAGGED : ET_MOUSE_MOVED;
- break;
- case fuchsia::ui::input::PointerEventPhase::UP:
- event_type = ET_MOUSE_RELEASED;
- break;
-
- // Following phases are not expected for mouse events.
- case fuchsia::ui::input::PointerEventPhase::HOVER:
- case fuchsia::ui::input::PointerEventPhase::CANCEL:
- case fuchsia::ui::input::PointerEventPhase::ADD:
- case fuchsia::ui::input::PointerEventPhase::REMOVE:
- NOTREACHED() << "Unexpected mouse phase "
- << fidl::ToUnderlying(event.phase);
- return false;
+void ScenicWindow::DispatchEvent(ui::Event* event) {
+ if (event->IsLocatedEvent()) {
+ ui::LocatedEvent* located_event = event->AsLocatedEvent();
+ gfx::PointF location = located_event->location_f();
+ location.Scale(device_pixel_ratio_);
+ located_event->set_location_f(location);
}
-
- gfx::Point location =
- gfx::Point(event.x * device_pixel_ratio_, event.y * device_pixel_ratio_);
- ui::MouseEvent mouse_event(event_type, location, location,
- base::TimeTicks::FromZxTime(event.event_time),
- flags, 0);
- delegate_->DispatchEvent(&mouse_event);
- return true;
-}
-
-bool ScenicWindow::OnTouchEvent(const fuchsia::ui::input::PointerEvent& event) {
- EventType event_type;
-
- switch (event.phase) {
- case fuchsia::ui::input::PointerEventPhase::DOWN:
- event_type = ET_TOUCH_PRESSED;
- break;
- case fuchsia::ui::input::PointerEventPhase::MOVE:
- event_type = ET_TOUCH_MOVED;
- break;
- case fuchsia::ui::input::PointerEventPhase::CANCEL:
- event_type = ET_TOUCH_CANCELLED;
- break;
- case fuchsia::ui::input::PointerEventPhase::UP:
- event_type = ET_TOUCH_RELEASED;
- break;
- case fuchsia::ui::input::PointerEventPhase::ADD:
- case fuchsia::ui::input::PointerEventPhase::REMOVE:
- case fuchsia::ui::input::PointerEventPhase::HOVER:
- return false;
- }
-
- // TODO(crbug.com/876933): Add more detailed fields such as
- // force/orientation/tilt once they are added to PointerEvent.
- ui::PointerDetails pointer_details(ui::EventPointerType::POINTER_TYPE_TOUCH,
- event.pointer_id);
-
- gfx::Point location =
- gfx::Point(event.x * device_pixel_ratio_, event.y * device_pixel_ratio_);
- ui::TouchEvent touch_event(event_type, location,
- base::TimeTicks::FromZxTime(event.event_time),
- pointer_details);
-
- delegate_->DispatchEvent(&touch_event);
- return true;
-}
-
-bool ScenicWindow::OnKeyboardEvent(
- const fuchsia::ui::input::KeyboardEvent& event) {
- 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;
- }
-
- // Currently KeyboardEvent doesn't specify HID Usage page. |hid_usage|
- // field always contains values from the Keyboard page. See
- // https://fuchsia.atlassian.net/browse/SCN-762 .
- DomCode dom_code = KeycodeConverter::UsbKeycodeToDomCode(
- (kUsbHidKeyboardPage << 16) | 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);
-
- 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 true;
-}
-
-bool ScenicWindow::OnFocusEvent(const fuchsia::ui::input::FocusEvent& event) {
- delegate_->OnActivationChanged(event.focused);
- return true;
+ delegate_->DispatchEvent(event);
}
} // namespace ui
diff --git a/chromium/ui/ozone/platform/scenic/scenic_window.h b/chromium/ui/ozone/platform/scenic/scenic_window.h
index 912fd04fab5..9dba22b7e9b 100644
--- a/chromium/ui/ozone/platform/scenic/scenic_window.h
+++ b/chromium/ui/ozone/platform/scenic/scenic_window.h
@@ -11,6 +11,8 @@
#include <vector>
#include "base/macros.h"
+#include "ui/events/fuchsia/input_event_dispatcher.h"
+#include "ui/events/fuchsia/input_event_dispatcher_delegate.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/geometry/size_f.h"
@@ -27,7 +29,8 @@ class PlatformWindowDelegate;
class OZONE_EXPORT ScenicWindow : public PlatformWindow,
public ScenicSessionListener,
public fuchsia::ui::viewsv1::ViewListener,
- public fuchsia::ui::input::InputListener {
+ public fuchsia::ui::input::InputListener,
+ public InputEventDispatcherDelegate {
public:
// Both |window_manager| and |delegate| must outlive the ScenicWindow.
// |view_owner_request| is passed to the view managed when creating the
@@ -41,10 +44,8 @@ class OZONE_EXPORT ScenicWindow : public PlatformWindow,
ScenicSession* scenic_session() { return &scenic_session_; }
ScenicSession::ResourceId node_id() const { return node_id_; }
- float device_pixel_ratio() const { return device_pixel_ratio_; }
- // Overrides texture of the window. This is used by ScenicWindowCanvas.
- // TODO(spang): Deprecate software rendering on fuchsia.
+ // Sets texture of the window to a scenic resource.
void SetTexture(ScenicSession::ResourceId texture);
// PlatformWindow implementation.
@@ -84,22 +85,22 @@ class OZONE_EXPORT ScenicWindow : public PlatformWindow,
void OnScenicEvents(
const std::vector<fuchsia::ui::scenic::Event>& events) override;
+ // InputEventDispatcher::Delegate interface.
+ void DispatchEvent(ui::Event* event) override;
+
// Error handler for |view_|. This error normally indicates the View was
// destroyed (e.g. dropping ViewOwner).
void OnViewError();
void UpdateSize();
- // Handlers for Fuchsia input event specializations.
- bool OnMouseEvent(const fuchsia::ui::input::PointerEvent& event);
- bool OnKeyboardEvent(const fuchsia::ui::input::KeyboardEvent& event);
- bool OnTouchEvent(const fuchsia::ui::input::PointerEvent& event);
- bool OnFocusEvent(const fuchsia::ui::input::FocusEvent& event);
-
ScenicWindowManager* const manager_;
PlatformWindowDelegate* const delegate_;
gfx::AcceleratedWidget const window_id_;
+ // Dispatches Scenic input events as Chrome ui::Events.
+ InputEventDispatcher event_dispatcher_;
+
// Underlying View in the view_manager.
fuchsia::ui::viewsv1::ViewPtr view_;
fidl::Binding<fuchsia::ui::viewsv1::ViewListener> view_listener_binding_;
@@ -119,16 +120,16 @@ class OZONE_EXPORT ScenicWindow : public PlatformWindow,
ScenicSession::ResourceId shape_id_;
ScenicSession::ResourceId material_id_;
+ // The ratio used for translating device-independent coordinates to absolute
+ // pixel coordinates.
+ float device_pixel_ratio_;
+
// Current view size in DIPs.
gfx::SizeF size_dips_;
// Current view size in device pixels.
gfx::Size size_pixels_;
- // Device pixel ratio for the current device. Initialized in
- // OnPropertiesChanged().
- float device_pixel_ratio_ = 0.0;
-
// InputConnection and InputListener binding used to receive input events from
// the view.
fuchsia::ui::input::InputConnectionPtr input_connection_;
diff --git a/chromium/ui/ozone/platform/scenic/scenic_window_manager.cc b/chromium/ui/ozone/platform/scenic/scenic_window_manager.cc
index 9db874b8b28..cf900feccd1 100644
--- a/chromium/ui/ozone/platform/scenic/scenic_window_manager.cc
+++ b/chromium/ui/ozone/platform/scenic/scenic_window_manager.cc
@@ -5,6 +5,7 @@
#include "ui/ozone/platform/scenic/scenic_window_manager.h"
#include "base/fuchsia/component_context.h"
+#include "ui/ozone/platform/scenic/ozone_platform_scenic.h"
namespace ui {
@@ -22,8 +23,9 @@ fuchsia::ui::viewsv1::ViewManager* ScenicWindowManager::GetViewManager() {
if (!view_manager_) {
view_manager_ = base::fuchsia::ComponentContext::GetDefault()
->ConnectToService<fuchsia::ui::viewsv1::ViewManager>();
- view_manager_.set_error_handler(
- [this]() { LOG(FATAL) << "ViewManager connection failed."; });
+ view_manager_.set_error_handler([this]() {
+ LOG(ERROR) << "The ViewManager channel was unexpectedly terminated.";
+ });
}
return view_manager_.get();
@@ -32,8 +34,9 @@ fuchsia::ui::viewsv1::ViewManager* ScenicWindowManager::GetViewManager() {
fuchsia::ui::scenic::Scenic* ScenicWindowManager::GetScenic() {
if (!scenic_) {
GetViewManager()->GetScenic(scenic_.NewRequest());
- scenic_.set_error_handler(
- [this]() { LOG(FATAL) << "Scenic connection failed."; });
+ scenic_.set_error_handler([this]() {
+ LOG(ERROR) << "The Scenic channel was unexpectedly terminated.";
+ });
}
return scenic_.get();
}
diff --git a/chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.cc b/chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.cc
new file mode 100644
index 00000000000..a8af3f8b847
--- /dev/null
+++ b/chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.cc
@@ -0,0 +1,132 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/scenic/vulkan_implementation_scenic.h"
+
+#include <lib/zx/channel.h>
+
+#include "base/files/file_path.h"
+#include "base/fuchsia/fuchsia_logging.h"
+#include "base/native_library.h"
+#include "gpu/vulkan/vulkan_function_pointers.h"
+#include "gpu/vulkan/vulkan_instance.h"
+#include "gpu/vulkan/vulkan_surface.h"
+#include "ui/gfx/gpu_fence.h"
+#include "ui/ozone/platform/scenic/scenic_window.h"
+#include "ui/ozone/platform/scenic/scenic_window_manager.h"
+#include "ui/ozone/platform/scenic/vulkan_magma.h"
+
+namespace ui {
+
+VulkanImplementationScenic::VulkanImplementationScenic(
+ ScenicWindowManager* scenic_window_manager)
+ : scenic_window_manager_(scenic_window_manager) {}
+
+VulkanImplementationScenic::~VulkanImplementationScenic() = default;
+
+bool VulkanImplementationScenic::InitializeVulkanInstance() {
+ base::NativeLibraryLoadError error;
+ base::NativeLibrary handle =
+ base::LoadNativeLibrary(base::FilePath("libvulkan.so"), &error);
+ if (!handle) {
+ LOG(ERROR) << "Failed to load vulkan: " << error.ToString();
+ return false;
+ }
+
+ gpu::VulkanFunctionPointers* vulkan_function_pointers =
+ gpu::GetVulkanFunctionPointers();
+ vulkan_function_pointers->vulkan_loader_library_ = handle;
+ std::vector<const char*> required_extensions = {
+ VK_KHR_SURFACE_EXTENSION_NAME, VK_KHR_MAGMA_SURFACE_EXTENSION_NAME,
+ };
+ std::vector<const char*> required_layers = {
+ "VK_LAYER_GOOGLE_image_pipe_swapchain",
+ };
+ if (!vulkan_instance_.Initialize(required_extensions, required_layers)) {
+ vulkan_instance_.Destroy();
+ return false;
+ }
+
+ vkCreateMagmaSurfaceKHR_ = vkGetInstanceProcAddr(
+ vulkan_instance_.vk_instance(), "vkCreateMagmaSurfaceKHR");
+ if (!vkCreateMagmaSurfaceKHR_) {
+ vulkan_instance_.Destroy();
+ return false;
+ }
+
+ vkGetPhysicalDeviceMagmaPresentationSupportKHR_ =
+ vkGetInstanceProcAddr(vulkan_instance_.vk_instance(),
+ "vkGetPhysicalDeviceMagmaPresentationSupportKHR");
+ if (!vkGetPhysicalDeviceMagmaPresentationSupportKHR_) {
+ vulkan_instance_.Destroy();
+ return false;
+ }
+
+ return true;
+}
+
+VkInstance VulkanImplementationScenic::GetVulkanInstance() {
+ return vulkan_instance_.vk_instance();
+}
+
+std::unique_ptr<gpu::VulkanSurface>
+VulkanImplementationScenic::CreateViewSurface(gfx::AcceleratedWidget window) {
+ ScenicWindow* scenic_window = scenic_window_manager_->GetWindow(window);
+ if (!scenic_window)
+ return nullptr;
+ ScenicSession* scenic_session = scenic_window->scenic_session();
+ fuchsia::images::ImagePipePtr image_pipe;
+ ScenicSession::ResourceId image_pipe_id =
+ scenic_session->CreateImagePipe(image_pipe.NewRequest());
+ scenic_window->SetTexture(image_pipe_id);
+ scenic_session->ReleaseResource(image_pipe_id);
+ scenic_session->Present();
+
+ VkSurfaceKHR surface;
+ VkMagmaSurfaceCreateInfoKHR surface_create_info = {};
+ surface_create_info.sType = VK_STRUCTURE_TYPE_MAGMA_SURFACE_CREATE_INFO_KHR;
+ surface_create_info.imagePipeHandle =
+ image_pipe.Unbind().TakeChannel().release();
+
+ VkResult result =
+ reinterpret_cast<PFN_vkCreateMagmaSurfaceKHR>(vkCreateMagmaSurfaceKHR_)(
+ GetVulkanInstance(), &surface_create_info, nullptr, &surface);
+ if (result != VK_SUCCESS) {
+ // This shouldn't fail, and we don't know whether imagePipeHandle was closed
+ // if it does.
+ LOG(FATAL) << "vkCreateMagmaSurfaceKHR failed: " << result;
+ }
+
+ return std::make_unique<gpu::VulkanSurface>(GetVulkanInstance(), surface);
+}
+
+bool VulkanImplementationScenic::GetPhysicalDevicePresentationSupport(
+ VkPhysicalDevice physical_device,
+ const std::vector<VkQueueFamilyProperties>& queue_family_properties,
+ uint32_t queue_family_index) {
+ // TODO(spang): vkGetPhysicalDeviceMagmaPresentationSupportKHR returns false
+ // here. Use it once it is fixed.
+ NOTIMPLEMENTED();
+ return true;
+}
+
+std::vector<const char*>
+VulkanImplementationScenic::GetRequiredDeviceExtensions() {
+ return {VK_KHR_SWAPCHAIN_EXTENSION_NAME};
+}
+
+VkFence VulkanImplementationScenic::CreateVkFenceForGpuFence(
+ VkDevice vk_device) {
+ NOTIMPLEMENTED();
+ return VK_NULL_HANDLE;
+}
+
+std::unique_ptr<gfx::GpuFence>
+VulkanImplementationScenic::ExportVkFenceToGpuFence(VkDevice vk_device,
+ VkFence vk_fence) {
+ NOTIMPLEMENTED();
+ return nullptr;
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.h b/chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.h
new file mode 100644
index 00000000000..ecd61cd04f6
--- /dev/null
+++ b/chromium/ui/ozone/platform/scenic/vulkan_implementation_scenic.h
@@ -0,0 +1,49 @@
+// 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_OZONE_PLATFORM_SCENIC_VULKAN_IMPLEMENTATION_SCENIC_H_
+#define UI_OZONE_PLATFORM_SCENIC_VULKAN_IMPLEMENTATION_SCENIC_H_
+
+#include <memory>
+
+#include "gpu/vulkan/vulkan_implementation.h"
+#include "gpu/vulkan/vulkan_instance.h"
+
+namespace ui {
+
+class ScenicWindowManager;
+
+class VulkanImplementationScenic : public gpu::VulkanImplementation {
+ public:
+ VulkanImplementationScenic(ScenicWindowManager* scenic_window_manager);
+ ~VulkanImplementationScenic() override;
+
+ // VulkanImplementation:
+ bool InitializeVulkanInstance() override;
+ VkInstance GetVulkanInstance() override;
+ std::unique_ptr<gpu::VulkanSurface> CreateViewSurface(
+ gfx::AcceleratedWidget window) override;
+ bool GetPhysicalDevicePresentationSupport(
+ VkPhysicalDevice device,
+ const std::vector<VkQueueFamilyProperties>& queue_family_properties,
+ uint32_t queue_family_index) override;
+ std::vector<const char*> GetRequiredDeviceExtensions() override;
+ VkFence CreateVkFenceForGpuFence(VkDevice vk_device) override;
+ std::unique_ptr<gfx::GpuFence> ExportVkFenceToGpuFence(
+ VkDevice vk_device,
+ VkFence vk_fence) override;
+
+ private:
+ ScenicWindowManager* const scenic_window_manager_;
+ gpu::VulkanInstance vulkan_instance_;
+
+ PFN_vkVoidFunction vkCreateMagmaSurfaceKHR_ = nullptr;
+ PFN_vkVoidFunction vkGetPhysicalDeviceMagmaPresentationSupportKHR_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(VulkanImplementationScenic);
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_SCENIC_VULKAN_IMPLEMENTATION_SCENIC_H_
diff --git a/chromium/ui/ozone/platform/scenic/vulkan_magma.h b/chromium/ui/ozone/platform/scenic/vulkan_magma.h
new file mode 100644
index 00000000000..df222e83efc
--- /dev/null
+++ b/chromium/ui/ozone/platform/scenic/vulkan_magma.h
@@ -0,0 +1,159 @@
+// 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_OZONE_PLATFORM_SCENIC_VULKAN_MAGMA_H_
+#define UI_OZONE_PLATFORM_SCENIC_VULKAN_MAGMA_H_
+
+// These definitions are from
+// https://fuchsia.googlesource.com/third_party/vulkan_loader_and_validation_layers/+/master/include/vulkan/vulkan.h
+// TODO(spang): Remove these once the definitions go upstream.
+
+#include <vulkan/vulkan.h>
+
+#if !defined(VK_KHR_external_memory_fuchsia)
+#define VK_KHR_external_memory_fuchsia 1
+#define VK_KHR_EXTERNAL_MEMORY_FUCHSIA_SPEC_VERSION 1
+#define VK_KHR_EXTERNAL_MEMORY_FUCHSIA_EXTENSION_NAME \
+ "VK_KHR_external_memory_fuchsia"
+
+typedef struct VkImportMemoryFuchsiaHandleInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkExternalMemoryHandleTypeFlagBitsKHR handleType;
+ uint32_t handle;
+} VkImportMemoryFuchsiaHandleInfoKHR;
+
+typedef struct VkMemoryFuchsiaHandlePropertiesKHR {
+ VkStructureType sType;
+ void* pNext;
+ uint32_t memoryTypeBits;
+} VkMemoryFuchsiaHandlePropertiesKHR;
+
+typedef struct VkMemoryGetFuchsiaHandleInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkDeviceMemory memory;
+ VkExternalMemoryHandleTypeFlagBitsKHR handleType;
+} VkMemoryGetFuchsiaHandleInfoKHR;
+
+typedef VkResult(VKAPI_PTR* PFN_vkGetMemoryFuchsiaHandleKHR)(
+ VkDevice device,
+ const VkMemoryGetFuchsiaHandleInfoKHR* pGetFuchsiaHandleInfo,
+ uint32_t* pFuchsiaHandle);
+typedef VkResult(VKAPI_PTR* PFN_vkGetMemoryFuchsiaHandlePropertiesKHR)(
+ VkDevice device,
+ VkExternalMemoryHandleTypeFlagBitsKHR handleType,
+ uint32_t fuchsiaHandle,
+ VkMemoryFuchsiaHandlePropertiesKHR* pMemoryFuchsiaHandleProperties);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFuchsiaHandleKHR(
+ VkDevice device,
+ const VkMemoryGetFuchsiaHandleInfoKHR* pGetFuchsiaHandleInfo,
+ uint32_t* pFuchsiaHandle);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetMemoryFuchsiaHandlePropertiesKHR(
+ VkDevice device,
+ VkExternalMemoryHandleTypeFlagBitsKHR handleType,
+ uint32_t fuchsiaHandle,
+ VkMemoryFuchsiaHandlePropertiesKHR* pMemoryFuchsiaHandleProperties);
+#endif
+
+#endif // !defined(VK_KHR_external_memory_fuchsia)
+
+#if !defined(VK_KHR_external_semaphore_fuchsia)
+#define VK_KHR_external_semaphore_fuchsia 1
+#define VK_KHR_EXTERNAL_SEMAPHORE_FUCHSIA_SPEC_VERSION 1
+#define VK_KHR_EXTERNAL_SEMAPHORE_FUCHSIA_EXTENSION_NAME \
+ "VK_KHR_external_semaphore_fuchsia"
+
+typedef struct VkImportSemaphoreFuchsiaHandleInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkSemaphore semaphore;
+ VkSemaphoreImportFlagsKHR flags;
+ VkExternalSemaphoreHandleTypeFlagBitsKHR handleType;
+ uint32_t handle;
+} VkImportSemaphoreFuchsiaHandleInfoKHR;
+
+typedef struct VkSemaphoreGetFuchsiaHandleInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ VkSemaphore semaphore;
+ VkExternalSemaphoreHandleTypeFlagBitsKHR handleType;
+} VkSemaphoreGetFuchsiaHandleInfoKHR;
+
+typedef VkResult(VKAPI_PTR* PFN_vkImportSemaphoreFuchsiaHandleKHR)(
+ VkDevice device,
+ const VkImportSemaphoreFuchsiaHandleInfoKHR*
+ pImportSemaphoreFuchsiaHandleInfo);
+typedef VkResult(VKAPI_PTR* PFN_vkGetSemaphoreFuchsiaHandleKHR)(
+ VkDevice device,
+ const VkSemaphoreGetFuchsiaHandleInfoKHR* pGetFuchsiaHandleInfo,
+ uint32_t* pFuchsiaHandle);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL
+vkImportSemaphoreFuchsiaHandleKHR(VkDevice device,
+ const VkImportSemaphoreFuchsiaHandleInfoKHR*
+ pImportSemaphoreFuchsiaHandleInfo);
+
+VKAPI_ATTR VkResult VKAPI_CALL vkGetSemaphoreFuchsiaHandleKHR(
+ VkDevice device,
+ const VkSemaphoreGetFuchsiaHandleInfoKHR* pGetFuchsiaHandleInfo,
+ uint32_t* pFuchsiaHandle);
+#endif
+
+#endif // !defined(VK_KHR_external_semaphore_fuchsia)
+
+#if defined(VK_USE_PLATFORM_MAGMA_KHR) && !defined(VK_KHR_magma_surface)
+#define VK_KHR_magma_surface 1
+#define VK_KHR_MAGMA_SURFACE_SPEC_VERSION 1
+#define VK_KHR_MAGMA_SURFACE_EXTENSION_NAME "VK_KHR_magma_surface"
+
+typedef VkFlags VkMagmaSurfaceCreateFlagsKHR;
+
+typedef struct VkMagmaSurfaceCreateInfoKHR {
+ VkStructureType sType;
+ const void* pNext;
+ uint32_t imagePipeHandle;
+ uint32_t width;
+ uint32_t height;
+} VkMagmaSurfaceCreateInfoKHR;
+
+typedef VkResult(VKAPI_PTR* PFN_vkCreateMagmaSurfaceKHR)(
+ VkInstance instance,
+ const VkMagmaSurfaceCreateInfoKHR* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface);
+typedef VkBool32(VKAPI_PTR* PFN_vkGetPhysicalDeviceMagmaPresentationSupportKHR)(
+ VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex);
+
+#ifndef VK_NO_PROTOTYPES
+VKAPI_ATTR VkResult VKAPI_CALL
+vkCreateMagmaSurfaceKHR(VkInstance instance,
+ const VkMagmaSurfaceCreateInfoKHR* pCreateInfo,
+ const VkAllocationCallbacks* pAllocator,
+ VkSurfaceKHR* pSurface);
+
+VKAPI_ATTR VkBool32 VKAPI_CALL
+vkGetPhysicalDeviceMagmaPresentationSupportKHR(VkPhysicalDevice physicalDevice,
+ uint32_t queueFamilyIndex);
+#endif
+#endif // defined(VK_USE_PLATFORM_MAGMA_KHR) && !defined(VK_KHR_magma_surface)
+
+#if !defined(VK_GOOGLE_image_usage_scanout)
+
+#define VK_GOOGLE_image_usage_scanout 1
+#define VK_GOOGLE_IMAGE_USAGE_SCANOUT_SPEC_VERSION 1
+#define VK_GOOGLE_IMAGE_USAGE_SCANOUT_EXTENSION_NAME \
+ "VK_GOOGLE_image_usage_scanout"
+
+#define VK_STRUCTURE_TYPE_MAGMA_SURFACE_CREATE_INFO_KHR \
+ (static_cast<VkStructureType>(1001002000))
+
+#endif // !defined(VK_GOOGLE_image_usage_scanout)
+
+#endif // UI_OZONE_PLATFORM_MAGMA_VULKAN_MAGMA_H_
diff --git a/chromium/ui/ozone/platform/wayland/BUILD.gn b/chromium/ui/ozone/platform/wayland/BUILD.gn
index 7a846766f84..9740ad91b26 100644
--- a/chromium/ui/ozone/platform/wayland/BUILD.gn
+++ b/chromium/ui/ozone/platform/wayland/BUILD.gn
@@ -37,16 +37,22 @@ source_set("wayland") {
"wayland_data_offer.h",
"wayland_data_source.cc",
"wayland_data_source.h",
+ "wayland_input_method_context.cc",
+ "wayland_input_method_context.h",
+ "wayland_input_method_context_factory.cc",
+ "wayland_input_method_context_factory.h",
"wayland_keyboard.cc",
"wayland_keyboard.h",
- "wayland_native_display_delegate.cc",
- "wayland_native_display_delegate.h",
"wayland_object.cc",
"wayland_object.h",
"wayland_output.cc",
"wayland_output.h",
+ "wayland_output_manager.cc",
+ "wayland_output_manager.h",
"wayland_pointer.cc",
"wayland_pointer.h",
+ "wayland_screen.cc",
+ "wayland_screen.h",
"wayland_surface_factory.cc",
"wayland_surface_factory.h",
"wayland_touch.cc",
@@ -66,6 +72,9 @@ source_set("wayland") {
"xdg_surface_wrapper_v5.h",
"xdg_surface_wrapper_v6.cc",
"xdg_surface_wrapper_v6.h",
+ "zwp_text_input_wrapper.h",
+ "zwp_text_input_wrapper_v1.cc",
+ "zwp_text_input_wrapper_v1.h",
]
import("//ui/base/ui_features.gni")
@@ -85,12 +94,16 @@ source_set("wayland") {
"//third_party/minigbm",
"//third_party/wayland:wayland_client",
"//third_party/wayland-protocols:linux_dmabuf_protocol",
+ "//third_party/wayland-protocols:presentation_time_protocol",
+ "//third_party/wayland-protocols:text_input_protocol",
"//third_party/wayland-protocols:xdg_shell_protocol",
"//ui/base",
"//ui/base:ui_features",
+ "//ui/base/ime/linux",
"//ui/display/manager",
"//ui/events",
"//ui/events:dom_keycode_converter",
+ "//ui/events/keycodes:xkb",
"//ui/events/ozone:events_ozone",
"//ui/events/ozone:events_ozone_evdev",
"//ui/events/ozone:events_ozone_layout",
@@ -103,6 +116,7 @@ source_set("wayland") {
"//ui/ozone/common/linux",
"//ui/ozone/public/interfaces/wayland:wayland_interfaces",
"//ui/platform_window",
+ "//ui/platform_window/platform_window_handler",
]
defines = [ "OZONE_IMPLEMENTATION" ]
@@ -142,8 +156,10 @@ source_set("wayland_unittests") {
"fake_server.h",
"wayland_connection_unittest.cc",
"wayland_data_device_unittest.cc",
+ "wayland_input_method_context_unittest.cc",
"wayland_keyboard_unittest.cc",
"wayland_pointer_unittest.cc",
+ "wayland_screen_unittest.cc",
"wayland_surface_factory_unittest.cc",
"wayland_test.cc",
"wayland_test.h",
@@ -157,7 +173,9 @@ source_set("wayland_unittests") {
"//testing/gtest",
"//third_party/wayland:wayland_server",
"//third_party/wayland-protocols:xdg_shell_protocol",
+ "//ui/base",
"//ui/base:ui_features",
+ "//ui/base/ime/linux",
"//ui/events/ozone:events_ozone_layout",
"//ui/ozone:platform",
"//ui/ozone:test_support",
diff --git a/chromium/ui/ozone/platform/wayland/DEPS b/chromium/ui/ozone/platform/wayland/DEPS
index fde6dba3616..56a383a0459 100644
--- a/chromium/ui/ozone/platform/wayland/DEPS
+++ b/chromium/ui/ozone/platform/wayland/DEPS
@@ -1,5 +1,12 @@
include_rules = [
+ "+ui/base/hit_test.h", # UI hit test doesn't bring in all of ui/base.
"+ui/base/ui_features.h", # UI features doesn't bring in all of ui/base.
+ "+ui/base/ui_base_features.h",
+ "+ui/base/ime/composition_text.h",
+ "+ui/base/ime/linux/linux_input_method_context.h",
+ "+ui/base/ime/linux/linux_input_method_context_factory.h",
"+mojo/public",
+ "+ui/base/dragdrop/drag_drop_types.h",
+ "+ui/base/dragdrop/os_exchange_data.h",
+ "+ui/base/dragdrop/os_exchange_data_provider_aura.h",
]
-
diff --git a/chromium/ui/ozone/platform/wayland/client_native_pixmap_factory_wayland.cc b/chromium/ui/ozone/platform/wayland/client_native_pixmap_factory_wayland.cc
index d64b36694ef..110dc9f3ab2 100644
--- a/chromium/ui/ozone/platform/wayland/client_native_pixmap_factory_wayland.cc
+++ b/chromium/ui/ozone/platform/wayland/client_native_pixmap_factory_wayland.cc
@@ -25,12 +25,6 @@ class ClientNativePixmapFactoryWayland : public gfx::ClientNativePixmapFactory {
gfx::BufferUsage usage) const override {
OzonePlatform::PlatformProperties properties =
OzonePlatform::GetInstance()->GetPlatformProperties();
- if (properties.supported_buffer_formats.empty()) {
- // If the compositor did not announce supported buffer formats, do our
- // best and assume those are supported.
- return dmabuf_factory_->IsConfigurationSupported(format, usage);
- }
-
for (auto buffer_format : properties.supported_buffer_formats) {
if (buffer_format == format)
return dmabuf_factory_->IsConfigurationSupported(format, usage);
diff --git a/chromium/ui/ozone/platform/wayland/fake_server.cc b/chromium/ui/ozone/platform/wayland/fake_server.cc
index 6a63f3a7cf6..62e7f8c16c1 100644
--- a/chromium/ui/ozone/platform/wayland/fake_server.cc
+++ b/chromium/ui/ozone/platform/wayland/fake_server.cc
@@ -3,7 +3,9 @@
// found in the LICENSE file.
#include "ui/ozone/platform/wayland/fake_server.h"
+
#include <sys/socket.h>
+#include <text-input-unstable-v1-server-protocol.h>
#include <wayland-server.h>
#include <xdg-shell-unstable-v5-server-protocol.h>
#include <xdg-shell-unstable-v6-server-protocol.h>
@@ -21,11 +23,12 @@
namespace wl {
namespace {
-const uint32_t kCompositorVersion = 4;
-const uint32_t kOutputVersion = 2;
-const uint32_t kDataDeviceManagerVersion = 3;
-const uint32_t kSeatVersion = 4;
-const uint32_t kXdgShellVersion = 1;
+constexpr uint32_t kCompositorVersion = 4;
+constexpr uint32_t kOutputVersion = 2;
+constexpr uint32_t kDataDeviceManagerVersion = 3;
+constexpr uint32_t kSeatVersion = 4;
+constexpr uint32_t kTextInputManagerVersion = 1;
+constexpr uint32_t kXdgShellVersion = 1;
bool ResourceHasImplementation(wl_resource* resource,
const wl_interface* interface,
@@ -290,6 +293,15 @@ const struct zxdg_positioner_v6_interface zxdg_positioner_v6_impl = {
// wl_data_device
+void DataDeviceStartDrag(wl_client* client,
+ wl_resource* resource,
+ wl_resource* source,
+ wl_resource* origin,
+ wl_resource* icon,
+ uint32_t serial) {
+ NOTIMPLEMENTED();
+}
+
void DataDeviceSetSelection(wl_client* client,
wl_resource* resource,
wl_resource* data_source,
@@ -304,8 +316,7 @@ void DataDeviceRelease(wl_client* client, wl_resource* resource) {
}
const struct wl_data_device_interface data_device_impl = {
- nullptr /*data_device_start_drag*/, &DataDeviceSetSelection,
- &DataDeviceRelease};
+ &DataDeviceStartDrag, &DataDeviceSetSelection, &DataDeviceRelease};
// wl_data_device_manager
@@ -347,6 +358,13 @@ const struct wl_data_device_manager_interface data_device_manager_impl = {
// wl_data_offer
+void DataOfferAccept(wl_client* client,
+ wl_resource* resource,
+ uint32_t serial,
+ const char* mime_type) {
+ NOTIMPLEMENTED();
+}
+
void DataOfferReceive(wl_client* client,
wl_resource* resource,
const char* mime_type,
@@ -359,10 +377,20 @@ void DataOfferDestroy(wl_client* client, wl_resource* resource) {
wl_resource_destroy(resource);
}
+void DataOfferFinish(wl_client* client, wl_resource* resource) {
+ NOTIMPLEMENTED();
+}
+
+void DataOfferSetActions(wl_client* client,
+ wl_resource* resource,
+ uint32_t dnd_actions,
+ uint32_t preferred_action) {
+ NOTIMPLEMENTED();
+}
+
const struct wl_data_offer_interface data_offer_impl = {
- nullptr /* data_offer_accept*/, DataOfferReceive,
- nullptr /*data_offer_finish*/, DataOfferDestroy,
- nullptr /*data_offer_set_actions*/};
+ DataOfferAccept, DataOfferReceive, DataOfferDestroy, DataOfferFinish,
+ DataOfferSetActions};
// wl_data_source
@@ -376,8 +404,14 @@ void DataSourceDestroy(wl_client* client, wl_resource* resource) {
wl_resource_destroy(resource);
}
+void SetActions(wl_client* client,
+ wl_resource* resource,
+ uint32_t dnd_actions) {
+ NOTIMPLEMENTED();
+}
+
const struct wl_data_source_interface data_source_impl = {
- DataSourceOffer, DataSourceDestroy, nullptr /*data_source_set_actions*/};
+ DataSourceOffer, DataSourceDestroy, SetActions};
// wl_seat
@@ -440,6 +474,84 @@ const struct wl_touch_interface touch_impl = {
&DestroyResource, // release
};
+// zwp_text_input_v1
+
+void TextInputV1Activate(wl_client* client,
+ wl_resource* resource,
+ wl_resource* seat,
+ wl_resource* surface) {
+ static_cast<MockZwpTextInput*>(wl_resource_get_user_data(resource))
+ ->Activate(surface);
+}
+
+void TextInputV1Deactivate(wl_client* client,
+ wl_resource* resource,
+ wl_resource* seat) {
+ static_cast<MockZwpTextInput*>(wl_resource_get_user_data(resource))
+ ->Deactivate();
+}
+
+void TextInputV1ShowInputPanel(wl_client* client, wl_resource* resource) {
+ static_cast<MockZwpTextInput*>(wl_resource_get_user_data(resource))
+ ->ShowInputPanel();
+}
+
+void TextInputV1HideInputPanel(wl_client* client, wl_resource* resource) {
+ static_cast<MockZwpTextInput*>(wl_resource_get_user_data(resource))
+ ->HideInputPanel();
+}
+
+void TextInputV1Reset(wl_client* client, wl_resource* resource) {
+ static_cast<MockZwpTextInput*>(wl_resource_get_user_data(resource))->Reset();
+}
+
+void TextInputV1SetCursorRectangle(wl_client* client,
+ wl_resource* resource,
+ int32_t x,
+ int32_t y,
+ int32_t width,
+ int32_t height) {
+ static_cast<MockZwpTextInput*>(wl_resource_get_user_data(resource))
+ ->SetCursorRect(x, y, width, height);
+}
+
+const struct zwp_text_input_v1_interface zwp_text_input_v1_impl = {
+ &TextInputV1Activate, // activate
+ &TextInputV1Deactivate, // deactivate
+ &TextInputV1ShowInputPanel, // show_input_panel
+ &TextInputV1HideInputPanel, // hide_input_panel
+ &TextInputV1Reset, // reset
+ nullptr, // set_surrounding_text
+ nullptr, // set_content_type
+ &TextInputV1SetCursorRectangle, // set_cursor_rectangle
+ nullptr, // set_preferred_language
+ nullptr, // commit_state
+ nullptr, // invoke_action
+};
+
+// zwp_text_input_manager_v1
+
+void CreateTextInput(struct wl_client* client,
+ struct wl_resource* resource,
+ uint32_t id) {
+ auto* im =
+ static_cast<MockTextInputManagerV1*>(wl_resource_get_user_data(resource));
+ wl_resource* text_resource =
+ wl_resource_create(client, &zwp_text_input_v1_interface,
+ wl_resource_get_version(resource), id);
+ if (!text_resource) {
+ wl_client_post_no_memory(client);
+ return;
+ }
+ im->text_input.reset(
+ new MockZwpTextInput(text_resource, &zwp_text_input_v1_impl));
+}
+
+const struct zwp_text_input_manager_v1_interface
+ zwp_text_input_manager_v1_impl = {
+ &CreateTextInput, // create_text_input
+};
+
// xdg_surface, zxdg_surface_v6 and zxdg_toplevel shared methods.
void SetTitle(wl_client* client, wl_resource* resource, const char* title) {
@@ -450,6 +562,21 @@ void SetAppId(wl_client* client, wl_resource* resource, const char* app_id) {
GetUserDataAs<MockXdgSurface>(resource)->SetAppId(app_id);
}
+void Move(wl_client* client,
+ wl_resource* resource,
+ wl_resource* seat,
+ uint32_t serial) {
+ GetUserDataAs<MockXdgSurface>(resource)->Move(serial);
+}
+
+void Resize(wl_client* client,
+ wl_resource* resource,
+ wl_resource* seat,
+ uint32_t serial,
+ uint32_t edges) {
+ GetUserDataAs<MockXdgSurface>(resource)->Resize(serial, edges);
+}
+
void AckConfigure(wl_client* client, wl_resource* resource, uint32_t serial) {
GetUserDataAs<MockXdgSurface>(resource)->AckConfigure(serial);
}
@@ -492,8 +619,8 @@ const struct xdg_surface_interface xdg_surface_impl = {
&SetTitle, // set_title
&SetAppId, // set_app_id
nullptr, // show_window_menu
- nullptr, // move
- nullptr, // resize
+ &Move, // move
+ &Resize, // resize
&AckConfigure, // ack_configure
&SetWindowGeometry, // set_window_geometry
&SetMaximized, // set_maximized
@@ -595,8 +722,8 @@ const struct zxdg_toplevel_v6_interface zxdg_toplevel_v6_impl = {
&SetTitle, // set_title
&SetAppId, // set_app_id
nullptr, // show_window_menu
- nullptr, // move
- nullptr, // resize
+ &Move, // move
+ &Resize, // resize
nullptr, // set_max_size
nullptr, // set_min_size
&SetMaximized, // set_maximized
@@ -769,6 +896,15 @@ MockTouch::MockTouch(wl_resource* resource) : ServerObject(resource) {
MockTouch::~MockTouch() {}
+MockZwpTextInput::MockZwpTextInput(wl_resource* resource,
+ const void* implementation)
+ : ServerObject(resource) {
+ wl_resource_set_implementation(resource, implementation, this,
+ &ServerObject::OnResourceDestroyed);
+}
+
+MockZwpTextInput::~MockZwpTextInput() {}
+
MockDataOffer::MockDataOffer(wl_resource* resource)
: ServerObject(resource),
io_thread_("Worker thread"),
@@ -784,10 +920,15 @@ MockDataOffer::~MockDataOffer() {}
void MockDataOffer::Receive(const std::string& mime_type, base::ScopedFD fd) {
DCHECK(fd.is_valid());
- std::string text_utf8(kSampleClipboardText);
+ std::string text_data;
+ if (mime_type == kTextMimeTypeUtf8)
+ text_data = kSampleClipboardText;
+ else if (mime_type == kTextMimeTypeText)
+ text_data = kSampleTextForDragAndDrop;
+
io_thread_.task_runner()->PostTask(
FROM_HERE,
- base::BindOnce(&WriteDataOnWorkerThread, std::move(fd), text_utf8));
+ base::BindOnce(&WriteDataOnWorkerThread, std::move(fd), text_data));
}
void MockDataOffer::OnOffer(const std::string& mime_type) {
@@ -816,6 +957,27 @@ MockDataOffer* MockDataDevice::OnDataOffer() {
return GetUserDataAs<MockDataOffer>(data_offer_resource);
}
+void MockDataDevice::OnEnter(uint32_t serial,
+ wl_resource* surface,
+ wl_fixed_t x,
+ wl_fixed_t y,
+ MockDataOffer& data_offer) {
+ wl_data_device_send_enter(resource(), serial, surface, x, y,
+ data_offer.resource());
+}
+
+void MockDataDevice::OnLeave() {
+ wl_data_device_send_leave(resource());
+}
+
+void MockDataDevice::OnMotion(uint32_t time, wl_fixed_t x, wl_fixed_t y) {
+ wl_data_device_send_motion(resource(), time, x, y);
+}
+
+void MockDataDevice::OnDrop() {
+ wl_data_device_send_drop(resource());
+}
+
void MockDataDevice::OnSelection(MockDataOffer& data_offer) {
wl_data_device_send_selection(resource(), data_offer.resource());
}
@@ -921,7 +1083,8 @@ MockDataDeviceManager::MockDataDeviceManager()
MockDataDeviceManager::~MockDataDeviceManager() {}
MockOutput::MockOutput()
- : Global(&wl_output_interface, nullptr, kOutputVersion) {}
+ : Global(&wl_output_interface, nullptr, kOutputVersion),
+ rect_(gfx::Rect(0, 0, 800, 600)) {}
MockOutput::~MockOutput() {}
@@ -949,6 +1112,13 @@ MockXdgShellV6::MockXdgShellV6()
MockXdgShellV6::~MockXdgShellV6() {}
+MockTextInputManagerV1::MockTextInputManagerV1()
+ : Global(&zwp_text_input_manager_v1_interface,
+ &zwp_text_input_manager_v1_impl,
+ kTextInputManagerVersion) {}
+
+MockTextInputManagerV1::~MockTextInputManagerV1() {}
+
void DisplayDeleter::operator()(wl_display* display) {
wl_display_destroy(display);
}
@@ -995,6 +1165,8 @@ bool FakeServer::Start(uint32_t shell_version) {
if (!zxdg_shell_v6_.Initialize(display_.get()))
return false;
}
+ if (!zwp_text_input_manager_v1_.Initialize(display_.get()))
+ return false;
client_ = wl_client_create(display_.get(), server_fd.get());
if (!client_)
diff --git a/chromium/ui/ozone/platform/wayland/fake_server.h b/chromium/ui/ozone/platform/wayland/fake_server.h
index 7739e6d62f2..ddda5748a19 100644
--- a/chromium/ui/ozone/platform/wayland/fake_server.h
+++ b/chromium/ui/ozone/platform/wayland/fake_server.h
@@ -24,7 +24,10 @@ struct wl_resource;
namespace wl {
constexpr char kTextMimeTypeUtf8[] = "text/plain;charset=utf-8";
+constexpr char kTextMimeTypeText[] = "text/plain";
constexpr char kSampleClipboardText[] = "This is a sample text for clipboard.";
+constexpr char kSampleTextForDragAndDrop[] =
+ "This is a sample text for drag-and-drop.";
// Base class for managing the life cycle of server objects.
class ServerObject {
@@ -56,6 +59,8 @@ class MockXdgSurface : public ServerObject {
MOCK_METHOD1(SetParent, void(wl_resource* parent));
MOCK_METHOD1(SetTitle, void(const char* title));
MOCK_METHOD1(SetAppId, void(const char* app_id));
+ MOCK_METHOD1(Move, void(uint32_t serial));
+ MOCK_METHOD2(Resize, void(uint32_t serial, uint32_t edges));
MOCK_METHOD1(AckConfigure, void(uint32_t serial));
MOCK_METHOD4(SetWindowGeometry,
void(int32_t x, int32_t y, int32_t width, int32_t height));
@@ -179,6 +184,24 @@ class MockTouch : public ServerObject {
DISALLOW_COPY_AND_ASSIGN(MockTouch);
};
+// Manage zwp_text_input_v1.
+class MockZwpTextInput : public ServerObject {
+ public:
+ MockZwpTextInput(wl_resource* resource, const void* implementation);
+ ~MockZwpTextInput() override;
+
+ MOCK_METHOD0(Reset, void());
+ MOCK_METHOD1(Activate, void(wl_resource* window));
+ MOCK_METHOD0(Deactivate, void());
+ MOCK_METHOD0(ShowInputPanel, void());
+ MOCK_METHOD0(HideInputPanel, void());
+ MOCK_METHOD4(SetCursorRect,
+ void(int32_t x, int32_t y, int32_t width, int32_t height));
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockZwpTextInput);
+};
+
class MockDataOffer : public ServerObject {
public:
explicit MockDataOffer(wl_resource* resource);
@@ -222,6 +245,14 @@ class MockDataDevice : public ServerObject {
void SetSelection(MockDataSource* data_source, uint32_t serial);
MockDataOffer* OnDataOffer();
+ void OnEnter(uint32_t serial,
+ wl_resource* surface,
+ wl_fixed_t x,
+ wl_fixed_t y,
+ MockDataOffer& data_offer);
+ void OnLeave();
+ void OnMotion(uint32_t time, wl_fixed_t x, wl_fixed_t y);
+ void OnDrop();
void OnSelection(MockDataOffer& data_offer);
private:
@@ -381,6 +412,18 @@ class MockXdgShellV6 : public Global {
DISALLOW_COPY_AND_ASSIGN(MockXdgShellV6);
};
+// Manage zwp_text_input_manager_v1 object.
+class MockTextInputManagerV1 : public Global {
+ public:
+ MockTextInputManagerV1();
+ ~MockTextInputManagerV1() override;
+
+ std::unique_ptr<MockZwpTextInput> text_input;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(MockTextInputManagerV1);
+};
+
struct DisplayDeleter {
void operator()(wl_display* display);
};
@@ -410,10 +453,21 @@ class FakeServer : public base::Thread, base::MessagePumpLibevent::FdWatcher {
return resource ? T::FromResource(resource) : nullptr;
}
+ void CreateAndInitializeOutput() {
+ auto output = std::make_unique<MockOutput>();
+ output->Initialize(display());
+ globals_.push_back(std::move(output));
+ }
+
MockDataDeviceManager* data_device_manager() { return &data_device_manager_; }
MockSeat* seat() { return &seat_; }
MockXdgShell* xdg_shell() { return &xdg_shell_; }
MockOutput* output() { return &output_; }
+ MockTextInputManagerV1* text_input_manager_v1() {
+ return &zwp_text_input_manager_v1_;
+ }
+
+ wl_display* display() const { return display_.get(); }
private:
void DoPause();
@@ -438,6 +492,9 @@ class FakeServer : public base::Thread, base::MessagePumpLibevent::FdWatcher {
MockSeat seat_;
MockXdgShell xdg_shell_;
MockXdgShellV6 zxdg_shell_v6_;
+ MockTextInputManagerV1 zwp_text_input_manager_v1_;
+
+ std::vector<std::unique_ptr<Global>> globals_;
base::MessagePumpLibevent::FdWatchController controller_;
diff --git a/chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc b/chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
index 8c3d01b4839..c08798ab0f5 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
+++ b/chromium/ui/ozone/platform/wayland/gpu/gbm_pixmap_wayland.cc
@@ -103,11 +103,7 @@ int GbmPixmapWayland::GetDmaBufOffset(size_t plane) const {
}
uint64_t GbmPixmapWayland::GetDmaBufModifier(size_t plane) const {
- // TODO(msisov): figure out why returning format modifier results in
- // EGL_BAD_ALLOC.
- //
- // return gbm_bo_->get_format_modifier();
- return 0;
+ return gbm_bo_->GetFormatModifier();
}
gfx::BufferFormat GbmPixmapWayland::GetBufferFormat() const {
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 54037394b0f..ce339c395c4 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc
+++ b/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.cc
@@ -59,8 +59,6 @@ bool GbmSurfacelessWayland::IsOffscreen() {
}
bool GbmSurfacelessWayland::SupportsPresentationCallback() {
- // TODO(msisov): enable a real presentation callback for wayland. For now, we
- // just blindly say it was successful. https://crbug.com/859012.
return true;
}
@@ -69,8 +67,7 @@ bool GbmSurfacelessWayland::SupportsAsyncSwap() {
}
bool GbmSurfacelessWayland::SupportsPostSubBuffer() {
- // TODO(msisov): figure out how to enable subbuffers with wayland/dmabuf.
- return false;
+ return true;
}
gfx::SwapResult GbmSurfacelessWayland::PostSubBuffer(
@@ -135,8 +132,10 @@ void GbmSurfacelessWayland::PostSubBufferAsync(
int height,
const SwapCompletionCallback& completion_callback,
const PresentationCallback& presentation_callback) {
- // See the comment in SupportsPostSubBuffer.
- NOTREACHED();
+ PendingFrame* frame = unsubmitted_frames_.back().get();
+ frame->damage_region_ = gfx::Rect(x, y, width, height);
+
+ SwapBuffersAsync(completion_callback, presentation_callback);
}
EGLConfig GbmSurfacelessWayland::GetConfig() {
@@ -198,16 +197,13 @@ void GbmSurfacelessWayland::SubmitFrame() {
return;
}
+ auto callback =
+ base::BindOnce(&GbmSurfacelessWayland::OnScheduleBufferSwapDone,
+ weak_factory_.GetWeakPtr());
uint32_t buffer_id = planes_.back().pixmap->GetUniqueId();
- surface_factory_->ScheduleBufferSwap(widget_, buffer_id);
-
- // Check comment in ::SupportsPresentationCallback.
- OnSubmission(gfx::SwapResult::SWAP_ACK, nullptr);
- OnPresentation(
- gfx::PresentationFeedback(base::TimeTicks::Now(), base::TimeDelta(),
- gfx::PresentationFeedback::kZeroCopy));
-
- planes_.clear();
+ surface_factory_->ScheduleBufferSwap(widget_, buffer_id,
+ submitted_frame_->damage_region_,
+ std::move(callback));
}
}
@@ -224,6 +220,14 @@ void GbmSurfacelessWayland::FenceRetired(PendingFrame* frame) {
SubmitFrame();
}
+void GbmSurfacelessWayland::OnScheduleBufferSwapDone(
+ gfx::SwapResult result,
+ const gfx::PresentationFeedback& feedback) {
+ OnSubmission(result, nullptr);
+ OnPresentation(feedback);
+ planes_.clear();
+}
+
void GbmSurfacelessWayland::OnSubmission(
gfx::SwapResult result,
std::unique_ptr<gfx::GpuFence> out_fence) {
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 cc660f3936f..bfb8c9f99a1 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h
+++ b/chromium/ui/ozone/platform/wayland/gpu/gbm_surfaceless_wayland.h
@@ -68,6 +68,10 @@ class GbmSurfacelessWayland : public gl::SurfacelessEGL {
bool ready = false;
gfx::SwapResult swap_result = gfx::SwapResult::SWAP_FAILED;
+ // A region of the updated content in a corresponding frame. It's used to
+ // advice Wayland which part of a buffer is going to be updated. Passing {0,
+ // 0, 0, 0} results in a whole buffer update on the Wayland compositor side.
+ gfx::Rect damage_region_ = gfx::Rect();
std::vector<gl::GLSurfaceOverlay> overlays;
SwapCompletionCallback completion_callback;
PresentationCallback presentation_callback;
@@ -78,6 +82,8 @@ class GbmSurfacelessWayland : public gl::SurfacelessEGL {
EGLSyncKHR InsertFence(bool implicit);
void FenceRetired(PendingFrame* frame);
+ void OnScheduleBufferSwapDone(gfx::SwapResult result,
+ const gfx::PresentationFeedback& feedback);
void OnSubmission(gfx::SwapResult result,
std::unique_ptr<gfx::GpuFence> out_fence);
void OnPresentation(const gfx::PresentationFeedback& feedback);
diff --git a/chromium/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.cc b/chromium/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.cc
index 88b95156ee5..226f6d42ccf 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.cc
+++ b/chromium/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.cc
@@ -86,11 +86,15 @@ void WaylandConnectionProxy::DestroyZwpLinuxDmabufInternal(uint32_t buffer_id) {
wc_ptr_->DestroyZwpLinuxDmabuf(buffer_id);
}
-void WaylandConnectionProxy::ScheduleBufferSwap(gfx::AcceleratedWidget widget,
- uint32_t buffer_id) {
+void WaylandConnectionProxy::ScheduleBufferSwap(
+ gfx::AcceleratedWidget widget,
+ uint32_t buffer_id,
+ const gfx::Rect& damage_region,
+ wl::BufferSwapCallback callback) {
DCHECK(gpu_thread_runner_->BelongsToCurrentThread());
DCHECK(wc_ptr_);
- wc_ptr_->ScheduleBufferSwap(widget, buffer_id);
+ wc_ptr_->ScheduleBufferSwap(widget, buffer_id, damage_region,
+ std::move(callback));
}
WaylandWindow* WaylandConnectionProxy::GetWindow(
diff --git a/chromium/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.h b/chromium/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.h
index 9126716d6b9..f06f9b9aada 100644
--- a/chromium/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.h
+++ b/chromium/ui/ozone/platform/wayland/gpu/wayland_connection_proxy.h
@@ -11,6 +11,7 @@
#include "mojo/public/cpp/bindings/binding_set.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/ozone/platform/wayland/wayland_connection.h"
+#include "ui/ozone/platform/wayland/wayland_util.h"
#include "ui/ozone/public/interfaces/wayland/wayland_connection.mojom.h"
#if defined(WAYLAND_GBM)
@@ -19,6 +20,11 @@
struct wl_shm;
+namespace gfx {
+enum class SwapResult;
+class Rect;
+} // namespace gfx
+
namespace ui {
class WaylandConnection;
@@ -58,7 +64,12 @@ class WaylandConnectionProxy : public ozone::mojom::WaylandConnectionClient {
// Asks Wayland to find a wl_buffer with the |buffer_id| and schedule a
// buffer swap for a WaylandWindow, which backs the following |widget|.
- void ScheduleBufferSwap(gfx::AcceleratedWidget widget, uint32_t buffer_id);
+ // The |callback| is called once a frame callback from the Wayland server
+ // is received.
+ void ScheduleBufferSwap(gfx::AcceleratedWidget widget,
+ uint32_t buffer_id,
+ const gfx::Rect& damage_region,
+ wl::BufferSwapCallback callback);
#if defined(WAYLAND_GBM)
// Returns a gbm_device based on a DRM render node.
diff --git a/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.cc b/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.cc
index 44763577a5c..ddddd861527 100644
--- a/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.cc
+++ b/chromium/ui/ozone/platform/wayland/ozone_platform_wayland.cc
@@ -14,12 +14,14 @@
#include "ui/ozone/platform/wayland/gpu/wayland_connection_proxy.h"
#include "ui/ozone/platform/wayland/wayland_connection.h"
#include "ui/ozone/platform/wayland/wayland_connection_connector.h"
-#include "ui/ozone/platform/wayland/wayland_native_display_delegate.h"
+#include "ui/ozone/platform/wayland/wayland_input_method_context_factory.h"
+#include "ui/ozone/platform/wayland/wayland_output_manager.h"
#include "ui/ozone/platform/wayland/wayland_surface_factory.h"
#include "ui/ozone/platform/wayland/wayland_window.h"
#include "ui/ozone/public/gpu_platform_support_host.h"
#include "ui/ozone/public/input_controller.h"
#include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/platform_screen.h"
#include "ui/platform_window/platform_window_init_properties.h"
#if BUILDFLAG(USE_XKBCOMMON)
@@ -30,6 +32,7 @@
#endif
#if defined(WAYLAND_GBM)
+#include "ui/base/ui_base_features.h"
#include "ui/ozone/common/linux/gbm_wrapper.h"
#include "ui/ozone/platform/wayland/gpu/drm_render_node_handle.h"
#include "ui/ozone/platform/wayland/gpu/drm_render_node_path_finder.h"
@@ -49,6 +52,10 @@ class OzonePlatformWayland : public OzonePlatform {
// https://github.com/wayland-project/wayland-protocols/commit/76d1ae8c65739eff3434ef219c58a913ad34e988
properties_.custom_frame_pref_default = true;
properties_.use_system_title_bar = false;
+ // Ozone/Wayland relies on the mojo communication when running in
+ // !single_process.
+ // TODO(msisov, rjkroege): Remove after http://crbug.com/806092.
+ properties_.requires_mojo = true;
}
~OzonePlatformWayland() override {}
@@ -80,6 +87,15 @@ class OzonePlatformWayland : public OzonePlatform {
std::unique_ptr<PlatformWindow> CreatePlatformWindow(
PlatformWindowDelegate* delegate,
PlatformWindowInitProperties properties) override {
+ // Some unit tests may try to set custom input method context factory
+ // after InitializeUI. Thus instead of creating factory in InitializeUI
+ // it is set at this point if none exists
+ if (!LinuxInputMethodContextFactory::instance() &&
+ !wayland_input_method_context_factory_) {
+ wayland_input_method_context_factory_.reset(
+ new WaylandInputMethodContextFactory(connection_.get()));
+ }
+
auto window = std::make_unique<WaylandWindow>(delegate, connection_.get());
if (!window->Initialize(std::move(properties)))
return nullptr;
@@ -88,7 +104,14 @@ class OzonePlatformWayland : public OzonePlatform {
std::unique_ptr<display::NativeDisplayDelegate> CreateNativeDisplayDelegate()
override {
- return std::make_unique<WaylandNativeDisplayDelegate>(connection_.get());
+ return std::make_unique<display::FakeDisplayDelegate>();
+ }
+
+ std::unique_ptr<PlatformScreen> CreateScreen() override {
+ // The WaylandConnection and the WaylandOutputManager must be created before
+ // PlatformScreen.
+ DCHECK(connection_ && connection_->wayland_output_manager());
+ return connection_->wayland_output_manager()->CreateWaylandScreen();
}
void InitializeUI(const InitParams& args) override {
@@ -141,8 +164,7 @@ class OzonePlatformWayland : public OzonePlatform {
}
const PlatformProperties& GetPlatformProperties() override {
- DCHECK(connection_.get());
- if (properties_.supported_buffer_formats.empty()) {
+ if (connection_ && properties_.supported_buffer_formats.empty()) {
properties_.supported_buffer_formats =
connection_->GetSupportedBufferFormats();
}
@@ -168,6 +190,8 @@ class OzonePlatformWayland : public OzonePlatform {
std::unique_ptr<StubOverlayManager> overlay_manager_;
std::unique_ptr<InputController> input_controller_;
std::unique_ptr<GpuPlatformSupportHost> gpu_platform_support_host_;
+ std::unique_ptr<WaylandInputMethodContextFactory>
+ wayland_input_method_context_factory_;
#if BUILDFLAG(USE_XKBCOMMON)
XkbEvdevCodes xkb_evdev_code_converter_;
diff --git a/chromium/ui/ozone/platform/wayland/wayland_buffer_manager.cc b/chromium/ui/ozone/platform/wayland/wayland_buffer_manager.cc
index 3dc7a12af7e..59f2b128297 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_buffer_manager.cc
+++ b/chromium/ui/ozone/platform/wayland/wayland_buffer_manager.cc
@@ -5,8 +5,8 @@
#include "ui/ozone/platform/wayland/wayland_buffer_manager.h"
#include <drm_fourcc.h>
-
#include <linux-dmabuf-unstable-v1-client-protocol.h>
+#include <presentation-time-client-protocol.h>
#include "base/trace_event/trace_event.h"
#include "ui/ozone/common/linux/drm_util_linux.h"
@@ -15,6 +15,40 @@
namespace ui {
+namespace {
+
+uint32_t GetPresentationKindFlags(uint32_t flags) {
+ uint32_t presentation_flags = 0;
+ if (flags & WP_PRESENTATION_FEEDBACK_KIND_VSYNC)
+ presentation_flags |= gfx::PresentationFeedback::kVSync;
+ if (flags & WP_PRESENTATION_FEEDBACK_KIND_HW_CLOCK)
+ presentation_flags |= gfx::PresentationFeedback::kHWClock;
+ if (flags & WP_PRESENTATION_FEEDBACK_KIND_HW_COMPLETION)
+ presentation_flags |= gfx::PresentationFeedback::kHWCompletion;
+ if (flags & WP_PRESENTATION_FEEDBACK_KIND_ZERO_COPY)
+ presentation_flags |= gfx::PresentationFeedback::kZeroCopy;
+
+ return presentation_flags;
+}
+
+base::TimeTicks GetPresentationFeedbackTimeStamp(uint32_t tv_sec_hi,
+ uint32_t tv_sec_lo,
+ uint32_t tv_nsec) {
+ const int64_t seconds = (static_cast<int64_t>(tv_sec_hi) << 32) + tv_sec_lo;
+ const int64_t microseconds = seconds * base::Time::kMicrosecondsPerSecond +
+ tv_nsec / base::Time::kNanosecondsPerMicrosecond;
+ return base::TimeTicks() + base::TimeDelta::FromMicroseconds(microseconds);
+}
+
+} // namespace
+
+WaylandBufferManager::Buffer::Buffer() = default;
+WaylandBufferManager::Buffer::Buffer(uint32_t id,
+ zwp_linux_buffer_params_v1* zwp_params,
+ const gfx::Size& buffer_size)
+ : buffer_id(id), size(buffer_size), params(zwp_params) {}
+WaylandBufferManager::Buffer::~Buffer() = default;
+
WaylandBufferManager::WaylandBufferManager(
zwp_linux_dmabuf_v1* zwp_linux_dmabuf,
WaylandConnection* connection)
@@ -31,8 +65,7 @@ WaylandBufferManager::WaylandBufferManager(
}
WaylandBufferManager::~WaylandBufferManager() {
- DCHECK(pending_buffer_map_.empty() && params_to_id_map_.empty() &&
- buffers_.empty());
+ DCHECK(buffers_.empty());
}
bool WaylandBufferManager::CreateBuffer(base::File file,
@@ -64,14 +97,17 @@ bool WaylandBufferManager::CreateBuffer(base::File file,
DCHECK(zwp_linux_dmabuf_);
struct zwp_linux_buffer_params_v1* params =
zwp_linux_dmabuf_v1_create_params(zwp_linux_dmabuf_.get());
- params_to_id_map_.insert(
- std::pair<struct zwp_linux_buffer_params_v1*, uint32_t>(params,
- buffer_id));
+
+ std::unique_ptr<Buffer> buffer =
+ std::make_unique<Buffer>(buffer_id, params, gfx::Size(width, height));
+ buffers_.insert(std::pair<uint32_t, std::unique_ptr<Buffer>>(
+ buffer_id, std::move(buffer)));
+
uint32_t fd = file.TakePlatformFile();
for (size_t i = 0; i < planes_count; i++) {
zwp_linux_buffer_params_v1_add(params, fd, i /* plane id */, offsets[i],
- strides[i], 0 /* modifier hi */,
- 0 /* modifier lo */);
+ strides[i], modifiers[i] >> 32,
+ modifiers[i] & UINT32_MAX);
}
zwp_linux_buffer_params_v1_add_listener(params, &params_listener, this);
zwp_linux_buffer_params_v1_create(params, width, height, format, 0);
@@ -81,48 +117,37 @@ bool WaylandBufferManager::CreateBuffer(base::File file,
}
// TODO(msisov): handle buffer swap failure or success.
-bool WaylandBufferManager::SwapBuffer(gfx::AcceleratedWidget widget,
- uint32_t buffer_id) {
- TRACE_EVENT1("Wayland", "WaylandBufferManager::SwapBuffer", "Buffer id",
- buffer_id);
+bool WaylandBufferManager::ScheduleBufferSwap(gfx::AcceleratedWidget widget,
+ uint32_t buffer_id,
+ const gfx::Rect& damage_region,
+ wl::BufferSwapCallback callback) {
+ TRACE_EVENT1("Wayland", "WaylandBufferManager::ScheduleSwapBuffer",
+ "Buffer id", buffer_id);
if (!ValidateDataFromGpu(widget, buffer_id))
return false;
auto it = buffers_.find(buffer_id);
- // A buffer might not exist by this time. So, store the request and process
- // it once it is created.
if (it == buffers_.end()) {
- auto pending_buffers_it = pending_buffer_map_.find(buffer_id);
- if (pending_buffers_it != pending_buffer_map_.end()) {
- // If a buffer didn't exist and second call for a swap comes, buffer must
- // be associated with the same widget.
- DCHECK_EQ(pending_buffers_it->second, widget);
- } else {
- pending_buffer_map_.insert(
- std::pair<uint32_t, gfx::AcceleratedWidget>(buffer_id, widget));
- }
- return true;
- }
- struct wl_buffer* buffer = it->second.get();
-
- WaylandWindow* window = connection_->GetWindow(widget);
- if (!window) {
- error_message_ = "A WaylandWindow with current widget does not exist";
+ error_message_ =
+ "Buffer with " + std::to_string(buffer_id) + " id does not exist";
return false;
}
- // TODO(msisov): it would be beneficial to use real damage regions to improve
- // performance.
- //
- // TODO(msisov): also start using wl_surface_frame callbacks for better
- // performance.
- wl_surface_damage(window->surface(), 0, 0, window->GetBounds().width(),
- window->GetBounds().height());
- wl_surface_attach(window->surface(), buffer, 0, 0);
- wl_surface_commit(window->surface());
+ Buffer* buffer = it->second.get();
+ DCHECK(buffer);
- connection_->ScheduleFlush();
+ // Assign a widget to this buffer, which is used to find a corresponding
+ // WaylandWindow.
+ buffer->widget = widget;
+ buffer->buffer_swap_callback = std::move(callback);
+ buffer->damage_region = damage_region;
+
+ if (buffer->wl_buffer) {
+ // A wl_buffer might not exist by this time. Silently return.
+ // TODO: check this.
+ return SwapBuffer(buffer);
+ }
return true;
}
@@ -135,6 +160,15 @@ bool WaylandBufferManager::DestroyBuffer(uint32_t buffer_id) {
error_message_ = "Trying to destroy non-existing buffer";
return false;
}
+ // It can happen that a buffer is destroyed before a frame callback comes.
+ // Thus, just mark this as a successful swap, which is ok to do.
+ Buffer* buffer = it->second.get();
+ if (!buffer->buffer_swap_callback.is_null()) {
+ std::move(buffer->buffer_swap_callback)
+ .Run(gfx::SwapResult::SWAP_ACK,
+ gfx::PresentationFeedback(base::TimeTicks::Now(),
+ base::TimeDelta(), 0));
+ }
buffers_.erase(it);
connection_->ScheduleFlush();
@@ -143,8 +177,55 @@ bool WaylandBufferManager::DestroyBuffer(uint32_t buffer_id) {
void WaylandBufferManager::ClearState() {
buffers_.clear();
- params_to_id_map_.clear();
- pending_buffer_map_.clear();
+}
+
+// TODO(msisov): handle buffer swap failure or success.
+bool WaylandBufferManager::SwapBuffer(Buffer* buffer) {
+ TRACE_EVENT1("Wayland", "WaylandBufferManager::SwapBuffer", "Buffer id",
+ buffer->buffer_id);
+
+ WaylandWindow* window = connection_->GetWindow(buffer->widget);
+ if (!window) {
+ error_message_ = "A WaylandWindow with current widget does not exist";
+ return false;
+ }
+
+ gfx::Rect damage_region = buffer->damage_region;
+ // If the size of the damage region is empty, wl_surface_damage must be
+ // supplied with the actual size of the buffer, which is going to be
+ // committed.
+ if (damage_region.size().IsEmpty())
+ damage_region.set_size(buffer->size);
+
+ wl_surface_damage_buffer(window->surface(), damage_region.x(),
+ damage_region.y(), damage_region.width(),
+ damage_region.height());
+ wl_surface_attach(window->surface(), buffer->wl_buffer.get(), 0, 0);
+
+ static const wl_callback_listener frame_listener = {
+ WaylandBufferManager::FrameCallbackDone};
+ DCHECK(!buffer->wl_frame_callback);
+ buffer->wl_frame_callback.reset(wl_surface_frame(window->surface()));
+ wl_callback_add_listener(buffer->wl_frame_callback.get(), &frame_listener,
+ this);
+
+ // Set up presentation feedback.
+ static const wp_presentation_feedback_listener feedback_listener = {
+ WaylandBufferManager::FeedbackSyncOutput,
+ WaylandBufferManager::FeedbackPresented,
+ WaylandBufferManager::FeedbackDiscarded};
+ if (connection_->presentation()) {
+ DCHECK(!buffer->wp_presentation_feedback);
+ buffer->wp_presentation_feedback.reset(wp_presentation_feedback(
+ connection_->presentation(), window->surface()));
+ wp_presentation_feedback_add_listener(
+ buffer->wp_presentation_feedback.get(), &feedback_listener, this);
+ }
+
+ wl_surface_commit(window->surface());
+
+ connection_->ScheduleFlush();
+ return true;
}
bool WaylandBufferManager::ValidateDataFromGpu(
@@ -187,6 +268,12 @@ bool WaylandBufferManager::ValidateDataFromGpu(
if (buffer_id < 1)
reason = "Invalid buffer id: " + std::to_string(buffer_id);
+ auto it = buffers_.find(buffer_id);
+ if (it != buffers_.end()) {
+ reason = "A buffer with " + std::to_string(buffer_id) +
+ " id has already existed";
+ }
+
if (!reason.empty()) {
error_message_ = std::move(reason);
return false;
@@ -218,24 +305,27 @@ void WaylandBufferManager::CreateSucceededInternal(
struct wl_buffer* new_buffer) {
// Find which buffer id |params| belong to and store wl_buffer
// with that id.
- auto it = params_to_id_map_.find(params);
- CHECK(it != params_to_id_map_.end());
- uint32_t buffer_id = it->second;
- params_to_id_map_.erase(params);
- zwp_linux_buffer_params_v1_destroy(params);
+ Buffer* buffer = nullptr;
+ for (auto& item : buffers_) {
+ if (item.second.get()->params == params) {
+ buffer = item.second.get();
+ break;
+ }
+ }
- buffers_.insert(std::pair<uint32_t, wl::Object<wl_buffer>>(
- buffer_id, wl::Object<wl_buffer>(new_buffer)));
+ DCHECK(buffer);
+ buffer->wl_buffer.reset(new_buffer);
+ buffer->params = nullptr;
+ zwp_linux_buffer_params_v1_destroy(params);
- TRACE_EVENT1("Wayland", "WaylandBufferManager::CreateSucceeded", "Buffer id",
- buffer_id);
+ if (buffer->widget != gfx::kNullAcceleratedWidget)
+ SwapBuffer(buffer);
+}
- auto pending_buffers_it = pending_buffer_map_.find(buffer_id);
- if (pending_buffers_it != pending_buffer_map_.end()) {
- gfx::AcceleratedWidget widget = pending_buffers_it->second;
- pending_buffer_map_.erase(pending_buffers_it);
- SwapBuffer(widget, buffer_id);
- }
+void WaylandBufferManager::OnBufferSwapped(Buffer* buffer) {
+ DCHECK(!buffer->buffer_swap_callback.is_null());
+ std::move(buffer->buffer_swap_callback)
+ .Run(buffer->swap_result, std::move(buffer->feedback));
}
// static
@@ -279,4 +369,95 @@ void WaylandBufferManager::CreateFailed(
LOG(FATAL) << "zwp_linux_buffer_params.create failed";
}
+// static
+void WaylandBufferManager::FrameCallbackDone(void* data,
+ wl_callback* callback,
+ uint32_t time) {
+ WaylandBufferManager* self = static_cast<WaylandBufferManager*>(data);
+ DCHECK(self);
+ for (auto& item : self->buffers_) {
+ Buffer* buffer = item.second.get();
+ if (buffer->wl_frame_callback.get() == callback) {
+ buffer->swap_result = gfx::SwapResult::SWAP_ACK;
+ buffer->wl_frame_callback.reset();
+
+ // If presentation feedback is not supported, use fake feedback and
+ // trigger the callback.
+ if (!self->connection_->presentation()) {
+ buffer->feedback = gfx::PresentationFeedback(base::TimeTicks::Now(),
+ base::TimeDelta(), 0);
+ self->OnBufferSwapped(buffer);
+ }
+ return;
+ }
+ }
+
+ NOTREACHED();
+}
+
+// static
+void WaylandBufferManager::FeedbackSyncOutput(
+ void* data,
+ struct wp_presentation_feedback* wp_presentation_feedback,
+ struct wl_output* output) {
+ NOTIMPLEMENTED_LOG_ONCE();
+}
+
+// static
+void WaylandBufferManager::FeedbackPresented(
+ void* data,
+ struct wp_presentation_feedback* wp_presentation_feedback,
+ uint32_t tv_sec_hi,
+ uint32_t tv_sec_lo,
+ uint32_t tv_nsec,
+ uint32_t refresh,
+ uint32_t seq_hi,
+ uint32_t seq_lo,
+ uint32_t flags) {
+ WaylandBufferManager* self = static_cast<WaylandBufferManager*>(data);
+ DCHECK(self);
+
+ for (auto& item : self->buffers_) {
+ Buffer* buffer = item.second.get();
+ if (buffer->wp_presentation_feedback.get() == wp_presentation_feedback) {
+ // Frame callback must come before a feedback is presented.
+ DCHECK(!buffer->wl_frame_callback);
+
+ buffer->feedback = gfx::PresentationFeedback(
+ GetPresentationFeedbackTimeStamp(tv_sec_hi, tv_sec_lo, tv_nsec),
+ base::TimeDelta::FromNanoseconds(refresh),
+ GetPresentationKindFlags(flags));
+
+ buffer->wp_presentation_feedback.reset();
+ self->OnBufferSwapped(buffer);
+ return;
+ }
+ }
+
+ NOTREACHED();
+}
+
+// static
+void WaylandBufferManager::FeedbackDiscarded(
+ void* data,
+ struct wp_presentation_feedback* wp_presentation_feedback) {
+ WaylandBufferManager* self = static_cast<WaylandBufferManager*>(data);
+ DCHECK(self);
+
+ for (auto& item : self->buffers_) {
+ Buffer* buffer = item.second.get();
+ if (buffer->wp_presentation_feedback.get() == wp_presentation_feedback) {
+ // Frame callback must come before a feedback is presented.
+ DCHECK(!buffer->wl_frame_callback);
+ buffer->feedback = gfx::PresentationFeedback::Failure();
+
+ buffer->wp_presentation_feedback.reset();
+ self->OnBufferSwapped(buffer);
+ return;
+ }
+ }
+
+ NOTREACHED();
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/wayland_buffer_manager.h b/chromium/ui/ozone/platform/wayland/wayland_buffer_manager.h
index a12b6565bf3..f2917fd47e7 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_buffer_manager.h
+++ b/chromium/ui/ozone/platform/wayland/wayland_buffer_manager.h
@@ -11,11 +11,16 @@
#include "base/containers/flat_map.h"
#include "base/files/file.h"
#include "base/macros.h"
+#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_widget_types.h"
+#include "ui/gfx/presentation_feedback.h"
+#include "ui/gfx/swap_result.h"
#include "ui/ozone/platform/wayland/wayland_object.h"
+#include "ui/ozone/platform/wayland/wayland_util.h"
struct zwp_linux_dmabuf_v1;
struct zwp_linux_buffer_params_v1;
+struct wp_presentation_feedback;
namespace gfx {
enum class BufferFormat;
@@ -52,8 +57,13 @@ class WaylandBufferManager {
uint32_t buffer_id);
// Assigns a wl_buffer with |buffer_id| to a window with the same |widget|. On
- // error, false is returned and |error_message_| is set.
- bool SwapBuffer(gfx::AcceleratedWidget widget, uint32_t buffer_id);
+ // error, false is returned and |error_message_| is set. A |damage_region|
+ // identifies which part of the buffer is updated. If an empty region is
+ // provided, the whole buffer is updated.
+ bool ScheduleBufferSwap(gfx::AcceleratedWidget widget,
+ uint32_t buffer_id,
+ const gfx::Rect& damage_region,
+ wl::BufferSwapCallback callback);
// Destroys a buffer with |buffer_id| in |buffers_|. On error, false is
// returned and |error_message_| is set.
@@ -63,6 +73,65 @@ class WaylandBufferManager {
void ClearState();
private:
+ // This is an internal helper representation of a wayland buffer object, which
+ // the GPU process creates when CreateBuffer is called. It's used for
+ // asynchronous buffer creation and stores |params| parameter to find out,
+ // which Buffer the wl_buffer corresponds to when CreateSucceeded is called.
+ // What is more, the Buffer stores such information as a widget it is attached
+ // to, its buffer id for simplier buffer management and other members specific
+ // to this Buffer object on run-time.
+ struct Buffer {
+ Buffer();
+ Buffer(uint32_t id,
+ zwp_linux_buffer_params_v1* zwp_params,
+ const gfx::Size& buffer_size);
+ ~Buffer();
+
+ // GPU GbmPixmapWayland corresponding buffer id.
+ uint32_t buffer_id = 0;
+
+ // Actual buffer size.
+ const gfx::Size size;
+
+ // Widget to attached/being attach WaylandWindow.
+ gfx::AcceleratedWidget widget = gfx::kNullAcceleratedWidget;
+
+ // Describes the region where the pending buffer is different from the
+ // current surface contents, and where the surface therefore needs to be
+ // repainted.
+ gfx::Rect damage_region;
+
+ // A buffer swap result once the buffer is committed.
+ gfx::SwapResult swap_result;
+
+ // A feedback, which is received if a presentation feedback protocol is
+ // supported.
+ gfx::PresentationFeedback feedback;
+
+ // Params that are used to create a wl_buffer.
+ zwp_linux_buffer_params_v1* params = nullptr;
+
+ // A wl_buffer backed by a dmabuf created on the GPU side.
+ wl::Object<struct wl_buffer> wl_buffer;
+
+ // A callback, which is called once the |wl_frame_callback| from the server
+ // is received.
+ wl::BufferSwapCallback buffer_swap_callback;
+
+ // A Wayland callback, which is triggered once wl_buffer has been committed
+ // and it is right time to notify the GPU that it can start a new drawing
+ // operation.
+ wl::Object<wl_callback> wl_frame_callback;
+
+ // A presentation feedback provided by the Wayland server once frame is
+ // shown.
+ wl::Object<struct wp_presentation_feedback> wp_presentation_feedback;
+
+ DISALLOW_COPY_AND_ASSIGN(Buffer);
+ };
+
+ bool SwapBuffer(Buffer* buffer);
+
// Validates data sent from GPU. If invalid, returns false and sets an error
// message to |error_message_|.
bool ValidateDataFromGpu(const base::File& file,
@@ -80,6 +149,8 @@ class WaylandBufferManager {
void CreateSucceededInternal(struct zwp_linux_buffer_params_v1* params,
struct wl_buffer* new_buffer);
+ void OnBufferSwapped(Buffer* buffer);
+
// zwp_linux_dmabuf_v1_listener
static void Modifiers(void* data,
struct zwp_linux_dmabuf_v1* zwp_linux_dmabuf,
@@ -97,25 +168,36 @@ class WaylandBufferManager {
static void CreateFailed(void* data,
struct zwp_linux_buffer_params_v1* params);
- // Stores a wl_buffer and it's id provided by the GbmBuffer object on the
- // GPU process side.
- base::flat_map<uint32_t, wl::Object<wl_buffer>> buffers_;
-
- // A temporary params-to-buffer id map, which is used to identify which
- // id wl_buffer should be assigned when storing it in the |buffers_| map
- // during CreateSucceeded call.
- base::flat_map<struct zwp_linux_buffer_params_v1*, uint32_t>
- params_to_id_map_;
-
- // It might happen that GPU asks to swap buffers, when a wl_buffer hasn't
- // been created yet. Thus, store the request in a pending map. Once a buffer
- // is created, it will be attached to the requested WaylandWindow based on the
- // gfx::AcceleratedWidget.
- base::flat_map<uint32_t, gfx::AcceleratedWidget> pending_buffer_map_;
+ // wl_callback_listener
+ static void FrameCallbackDone(void* data,
+ wl_callback* callback,
+ uint32_t time);
+
+ // wp_presentation_feedback_listener
+ static void FeedbackSyncOutput(
+ void* data,
+ struct wp_presentation_feedback* wp_presentation_feedback,
+ struct wl_output* output);
+ static void FeedbackPresented(
+ void* data,
+ struct wp_presentation_feedback* wp_presentation_feedback,
+ uint32_t tv_sec_hi,
+ uint32_t tv_sec_lo,
+ uint32_t tv_nsec,
+ uint32_t refresh,
+ uint32_t seq_hi,
+ uint32_t seq_lo,
+ uint32_t flags);
+ static void FeedbackDiscarded(
+ void* data,
+ struct wp_presentation_feedback* wp_presentation_feedback);
// Stores announced buffer formats supported by the compositor.
std::vector<gfx::BufferFormat> supported_buffer_formats_;
+ // A container of created buffers.
+ base::flat_map<uint32_t, std::unique_ptr<Buffer>> buffers_;
+
// Set when invalid data is received from the GPU process.
std::string error_message_;
diff --git a/chromium/ui/ozone/platform/wayland/wayland_connection.cc b/chromium/ui/ozone/platform/wayland/wayland_connection.cc
index 690504fb031..d4ce8fb5668 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_connection.cc
+++ b/chromium/ui/ozone/platform/wayland/wayland_connection.cc
@@ -14,8 +14,11 @@
#include "base/message_loop/message_loop_current.h"
#include "base/strings/string_util.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "ui/gfx/swap_result.h"
#include "ui/ozone/platform/wayland/wayland_buffer_manager.h"
+#include "ui/ozone/platform/wayland/wayland_input_method_context.h"
#include "ui/ozone/platform/wayland/wayland_object.h"
+#include "ui/ozone/platform/wayland/wayland_output_manager.h"
#include "ui/ozone/platform/wayland/wayland_window.h"
static_assert(XDG_SHELL_VERSION_CURRENT == 5, "Unsupported xdg-shell version");
@@ -23,11 +26,21 @@ static_assert(XDG_SHELL_VERSION_CURRENT == 5, "Unsupported xdg-shell version");
namespace ui {
namespace {
-const uint32_t kMaxCompositorVersion = 4;
-const uint32_t kMaxLinuxDmabufVersion = 1;
-const uint32_t kMaxSeatVersion = 4;
-const uint32_t kMaxShmVersion = 1;
-const uint32_t kMaxXdgShellVersion = 1;
+constexpr uint32_t kMaxCompositorVersion = 4;
+constexpr uint32_t kMaxLinuxDmabufVersion = 1;
+constexpr uint32_t kMaxSeatVersion = 4;
+constexpr uint32_t kMaxShmVersion = 1;
+constexpr uint32_t kMaxXdgShellVersion = 1;
+constexpr uint32_t kMaxDeviceManagerVersion = 3;
+constexpr uint32_t kMaxWpPresentationVersion = 1;
+constexpr uint32_t kMaxTextInputManagerVersion = 1;
+
+std::unique_ptr<WaylandDataSource> CreateWaylandDataSource(
+ WaylandDataDeviceManager* data_device_manager,
+ WaylandConnection* connection) {
+ wl_data_source* data_source = data_device_manager->CreateSource();
+ return std::make_unique<WaylandDataSource>(data_source, connection);
+}
} // namespace
WaylandConnection::WaylandConnection()
@@ -53,9 +66,10 @@ bool WaylandConnection::Initialize() {
}
wl_registry_add_listener(registry_.get(), &registry_listener, this);
-
- while (!PrimaryOutput() || !PrimaryOutput()->is_ready())
+ while (!wayland_output_manager_ ||
+ !wayland_output_manager_->IsPrimaryOutputReady()) {
wl_display_roundtrip(display_.get());
+ }
if (!compositor_) {
LOG(ERROR) << "No wl_compositor object";
@@ -118,6 +132,15 @@ WaylandWindow* WaylandConnection::GetCurrentFocusedWindow() {
return nullptr;
}
+WaylandWindow* WaylandConnection::GetCurrentKeyboardFocusedWindow() {
+ for (auto entry : window_map_) {
+ WaylandWindow* window = entry.second;
+ if (window->has_keyboard_focus())
+ return window;
+ }
+ return nullptr;
+}
+
void WaylandConnection::AddWindow(gfx::AcceleratedWidget widget,
WaylandWindow* window) {
window_map_[widget] = window;
@@ -129,12 +152,6 @@ void WaylandConnection::RemoveWindow(gfx::AcceleratedWidget widget) {
window_map_.erase(widget);
}
-WaylandOutput* WaylandConnection::PrimaryOutput() const {
- if (!output_list_.size())
- return nullptr;
- return output_list_.front().get();
-}
-
void WaylandConnection::SetCursorBitmap(const std::vector<SkBitmap>& bitmaps,
const gfx::Point& location) {
if (!pointer_ || !pointer_->cursor())
@@ -174,10 +191,14 @@ void WaylandConnection::DestroyZwpLinuxDmabuf(uint32_t buffer_id) {
}
}
-void WaylandConnection::ScheduleBufferSwap(gfx::AcceleratedWidget widget,
- uint32_t buffer_id) {
+void WaylandConnection::ScheduleBufferSwap(
+ gfx::AcceleratedWidget widget,
+ uint32_t buffer_id,
+ const gfx::Rect& damage_region,
+ ScheduleBufferSwapCallback callback) {
DCHECK(base::MessageLoopForUI::IsCurrent());
- if (!buffer_manager_->SwapBuffer(widget, buffer_id)) {
+ if (!buffer_manager_->ScheduleBufferSwap(widget, buffer_id, damage_region,
+ std::move(callback))) {
TerminateGpuProcess(buffer_manager_->error_message());
}
}
@@ -190,9 +211,7 @@ void WaylandConnection::OfferClipboardData(
const ClipboardDelegate::DataMap& data_map,
ClipboardDelegate::OfferDataClosure callback) {
if (!data_source_) {
- wl_data_source* data_source = data_device_manager_->CreateSource();
- data_source_.reset(new WaylandDataSource(data_source));
- data_source_->set_connection(this);
+ data_source_ = CreateWaylandDataSource(data_device_manager_.get(), this);
data_source_->WriteToClipboard(data_map);
}
data_source_->UpdataDataMap(data_map);
@@ -234,6 +253,41 @@ void WaylandConnection::SetTerminateGpuCallback(
terminate_gpu_cb_ = std::move(terminate_callback);
}
+void WaylandConnection::StartDrag(const ui::OSExchangeData& data,
+ int operation) {
+ if (!drag_data_source_) {
+ drag_data_source_ =
+ CreateWaylandDataSource(data_device_manager_.get(), this);
+ }
+ drag_data_source_->Offer(data);
+ drag_data_source_->SetAction(operation);
+ data_device_->StartDrag(*(drag_data_source_->data_source()), data);
+}
+
+void WaylandConnection::FinishDragSession(uint32_t dnd_action,
+ WaylandWindow* source_window) {
+ if (source_window)
+ source_window->OnDragSessionClose(dnd_action);
+ data_device_->ResetSourceData();
+ drag_data_source_.reset();
+}
+
+void WaylandConnection::DeliverDragData(const std::string& mime_type,
+ std::string* buffer) {
+ data_device_->DeliverDragData(mime_type, buffer);
+}
+
+void WaylandConnection::RequestDragData(
+ const std::string& mime_type,
+ base::OnceCallback<void(const std::string&)> callback) {
+ data_device_->RequestDragData(mime_type, std::move(callback));
+}
+
+void WaylandConnection::ResetPointerFlags() {
+ if (pointer_)
+ pointer_->ResetFlags();
+}
+
void WaylandConnection::GetAvailableMimeTypes(
ClipboardDelegate::GetMimeTypesClosure callback) {
std::move(callback).Run(data_device_->GetAvailableMimeTypes());
@@ -287,11 +341,6 @@ void WaylandConnection::TerminateGpuProcess(std::string reason) {
buffer_manager_->ClearState();
}
-const std::vector<std::unique_ptr<WaylandOutput>>&
-WaylandConnection::GetOutputList() const {
- return output_list_;
-}
-
// static
void WaylandConnection::Global(void* data,
wl_registry* registry,
@@ -375,15 +424,17 @@ void WaylandConnection::Global(void* data,
return;
}
- if (!connection->output_list_.empty())
- NOTIMPLEMENTED() << "Multiple screens support is not implemented";
-
- connection->output_list_.push_back(base::WrapUnique(new WaylandOutput(
- connection->get_next_display_id(), output.release())));
+ if (!connection->wayland_output_manager_) {
+ connection->wayland_output_manager_ =
+ std::make_unique<WaylandOutputManager>();
+ }
+ connection->wayland_output_manager_->AddWaylandOutput(name,
+ output.release());
} else if (!connection->data_device_manager_ &&
strcmp(interface, "wl_data_device_manager") == 0) {
wl::Object<wl_data_device_manager> data_device_manager =
- wl::Bind<wl_data_device_manager>(registry, name, 1);
+ wl::Bind<wl_data_device_manager>(
+ registry, name, std::min(version, kMaxDeviceManagerVersion));
if (!data_device_manager) {
LOG(ERROR) << "Failed to bind to wl_data_device_manager global";
return;
@@ -398,6 +449,18 @@ void WaylandConnection::Global(void* data,
registry, name, std::min(version, kMaxLinuxDmabufVersion));
connection->buffer_manager_.reset(
new WaylandBufferManager(zwp_linux_dmabuf.release(), connection));
+ } else if (!connection->presentation_ &&
+ (strcmp(interface, "wp_presentation") == 0)) {
+ connection->presentation_ =
+ wl::Bind<wp_presentation>(registry, name, kMaxWpPresentationVersion);
+ } else if (!connection->text_input_manager_v1_ &&
+ strcmp(interface, "zwp_text_input_manager_v1") == 0) {
+ connection->text_input_manager_v1_ = wl::Bind<zwp_text_input_manager_v1>(
+ registry, name, std::min(version, kMaxTextInputManagerVersion));
+ if (!connection->text_input_manager_v1_) {
+ LOG(ERROR) << "Failed to bind to zwp_text_input_manager_v1 global";
+ return;
+ }
}
connection->ScheduleFlush();
@@ -407,7 +470,15 @@ void WaylandConnection::Global(void* data,
void WaylandConnection::GlobalRemove(void* data,
wl_registry* registry,
uint32_t name) {
- NOTIMPLEMENTED();
+ WaylandConnection* connection = static_cast<WaylandConnection*>(data);
+ // The Wayland protocol distinguishes global objects by unique numeric names,
+ // which the WaylandOutputManager uses as unique output ids. But, it is only
+ // possible to figure out, what global object is going to be removed on the
+ // WaylandConnection::GlobalRemove call. Thus, whatever unique |name| comes,
+ // it's forwarded to the WaylandOutputManager, which checks if such a global
+ // output object exists and removes it.
+ if (connection->wayland_output_manager_)
+ connection->wayland_output_manager_->RemoveWaylandOutput(name);
}
// static
diff --git a/chromium/ui/ozone/platform/wayland/wayland_connection.h b/chromium/ui/ozone/platform/wayland/wayland_connection.h
index 521f957e331..d2487cd967b 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_connection.h
+++ b/chromium/ui/ozone/platform/wayland/wayland_connection.h
@@ -26,8 +26,9 @@
namespace ui {
-class WaylandWindow;
class WaylandBufferManager;
+class WaylandOutputManager;
+class WaylandWindow;
class WaylandConnection : public PlatformEventSource,
public ClipboardDelegate,
@@ -60,7 +61,9 @@ class WaylandConnection : public PlatformEventSource,
// Called by the GPU and asks to attach a wl_buffer with a |buffer_id| to a
// WaylandWindow with the specified |widget|.
void ScheduleBufferSwap(gfx::AcceleratedWidget widget,
- uint32_t buffer_id) override;
+ uint32_t buffer_id,
+ const gfx::Rect& damage_region,
+ ScheduleBufferSwapCallback callback) override;
// Schedules a flush of the Wayland connection.
void ScheduleFlush();
@@ -69,20 +72,21 @@ class WaylandConnection : public PlatformEventSource,
wl_compositor* compositor() { return compositor_.get(); }
wl_subcompositor* subcompositor() { return subcompositor_.get(); }
wl_shm* shm() { return shm_.get(); }
- xdg_shell* shell() { return shell_.get(); }
- zxdg_shell_v6* shell_v6() { return shell_v6_.get(); }
+ xdg_shell* shell() const { return shell_.get(); }
+ zxdg_shell_v6* shell_v6() const { return shell_v6_.get(); }
wl_seat* seat() { return seat_.get(); }
wl_data_device* data_device() { return data_device_->data_device(); }
+ wp_presentation* presentation() const { return presentation_.get(); }
+ zwp_text_input_manager_v1* text_input_manager_v1() {
+ return text_input_manager_v1_.get();
+ }
WaylandWindow* GetWindow(gfx::AcceleratedWidget widget);
WaylandWindow* GetCurrentFocusedWindow();
+ WaylandWindow* GetCurrentKeyboardFocusedWindow();
void AddWindow(gfx::AcceleratedWidget widget, WaylandWindow* window);
void RemoveWindow(gfx::AcceleratedWidget widget);
- int64_t get_next_display_id() { return next_display_id_++; }
- const std::vector<std::unique_ptr<WaylandOutput>>& GetOutputList() const;
- WaylandOutput* PrimaryOutput() const;
-
void set_serial(uint32_t serial) { serial_ = serial; }
uint32_t serial() { return serial_; }
@@ -94,6 +98,12 @@ class WaylandConnection : public PlatformEventSource,
// Returns the current pointer, which may be null.
WaylandPointer* pointer() { return pointer_.get(); }
+ WaylandDataSource* drag_data_source() { return drag_data_source_.get(); }
+
+ WaylandOutputManager* wayland_output_manager() const {
+ return wayland_output_manager_.get();
+ }
+
// Clipboard implementation.
ClipboardDelegate* GetClipboardDelegate();
void DataSourceCancelled();
@@ -120,7 +130,34 @@ class WaylandConnection : public PlatformEventSource,
void SetTerminateGpuCallback(
base::OnceCallback<void(std::string)> terminate_gpu_cb);
+ // Starts drag with |data| to be delivered, |operation| supported by the
+ // source side initiated the dragging.
+ void StartDrag(const ui::OSExchangeData& data, int operation);
+ // Finishes drag and drop session. It happens when WaylandDataSource gets
+ // 'OnDnDFinished' or 'OnCancel', which means the drop is performed or
+ // canceled on others.
+ void FinishDragSession(uint32_t dnd_action, WaylandWindow* source_window);
+ // Delivers the data owned by Chromium which initiates drag-and-drop. |buffer|
+ // is an output parameter and it should be filled with the data corresponding
+ // to mime_type.
+ void DeliverDragData(const std::string& mime_type, std::string* buffer);
+ // Requests the data to the platform when Chromium gets drag-and-drop started
+ // by others. Once reading the data from platform is done, |callback| should
+ // be called with the data.
+ void RequestDragData(const std::string& mime_type,
+ base::OnceCallback<void(const std::string&)> callback);
+
+ // Resets flags and keyboard modifiers.
+ //
+ // This method is specially handy for cases when the WaylandPointer state is
+ // modified by a POINTER_DOWN event, but the respective POINTER_UP event is
+ // not delivered.
+ void ResetPointerFlags();
+
private:
+ // WaylandInputMethodContextFactory needs access to DispatchUiEvent
+ friend class WaylandInputMethodContextFactory;
+
void Flush();
void DispatchUiEvent(Event* event);
@@ -162,12 +199,16 @@ class WaylandConnection : public PlatformEventSource,
wl::Object<wl_shm> shm_;
wl::Object<xdg_shell> shell_;
wl::Object<zxdg_shell_v6> shell_v6_;
+ wl::Object<wp_presentation> presentation_;
+ wl::Object<zwp_text_input_manager_v1> text_input_manager_v1_;
std::unique_ptr<WaylandDataDeviceManager> data_device_manager_;
std::unique_ptr<WaylandDataDevice> data_device_;
std::unique_ptr<WaylandDataSource> data_source_;
- std::unique_ptr<WaylandPointer> pointer_;
+ std::unique_ptr<WaylandDataSource> drag_data_source_;
std::unique_ptr<WaylandKeyboard> keyboard_;
+ std::unique_ptr<WaylandOutputManager> wayland_output_manager_;
+ std::unique_ptr<WaylandPointer> pointer_;
std::unique_ptr<WaylandTouch> touch_;
// Objects that are using when GPU runs in own process.
@@ -179,9 +220,6 @@ class WaylandConnection : public PlatformEventSource,
uint32_t serial_ = 0;
- int64_t next_display_id_ = 0;
- std::vector<std::unique_ptr<WaylandOutput>> output_list_;
-
// Holds a temporary instance of the client's clipboard content
// so that we can asynchronously write to it.
ClipboardDelegate::DataMap* data_map_ = nullptr;
diff --git a/chromium/ui/ozone/platform/wayland/wayland_connection_unittest.cc b/chromium/ui/ozone/platform/wayland/wayland_connection_unittest.cc
index dea153089ed..9c6cc51d948 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_connection_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/wayland_connection_unittest.cc
@@ -8,42 +8,14 @@
#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/display/types/display_snapshot.h"
#include "ui/ozone/platform/wayland/fake_server.h"
#include "ui/ozone/platform/wayland/wayland_connection.h"
-#include "ui/ozone/platform/wayland/wayland_output.h"
namespace ui {
namespace {
-
-const uint32_t kXdgVersion5 = 5;
-const uint32_t kNumOfDisplays = 1;
-const uint32_t kWidth = 800;
-const uint32_t kHeight = 600;
-
-void CheckDisplaySize(const std::vector<display::DisplaySnapshot*>& displays) {
- ASSERT_TRUE(displays.size() == kNumOfDisplays);
-
- // TODO(msisov): add multiple displays support.
- display::DisplaySnapshot* display_snapshot = displays.front();
- ASSERT_TRUE(display_snapshot->current_mode()->size() ==
- gfx::Size(kWidth, kHeight));
+constexpr uint32_t kXdgVersion5 = 5;
}
-}
-
-class OutputObserver : public WaylandOutput::Observer {
- public:
- explicit OutputObserver(const base::Closure& closure) : closure_(closure) {}
-
- void OnOutputReadyForUse() override {
- if (!closure_.is_null())
- closure_.Run();
- }
-
- private:
- const base::Closure closure_;
-};
TEST(WaylandConnectionTest, UseUnstableVersion) {
base::MessageLoopForUI message_loop;
@@ -78,26 +50,4 @@ TEST(WaylandConnectionTest, Ping) {
server.Pause();
}
-TEST(WaylandConnectionTest, Output) {
- base::MessageLoopForUI message_loop;
- wl::FakeServer server;
- ASSERT_TRUE(server.Start(kXdgVersion5));
- server.output()->SetRect(gfx::Rect(0, 0, kWidth, kHeight));
- WaylandConnection connection;
- ASSERT_TRUE(connection.Initialize());
- connection.StartProcessingEvents();
-
- base::RunLoop run_loop;
- OutputObserver observer(run_loop.QuitClosure());
- connection.PrimaryOutput()->SetObserver(&observer);
- run_loop.Run();
-
- connection.PrimaryOutput()->GetDisplaysSnapshot(
- base::BindOnce(&CheckDisplaySize));
-
- server.Resume();
- base::RunLoop().RunUntilIdle();
- server.Pause();
-}
-
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/wayland_data_device.cc b/chromium/ui/ozone/platform/wayland/wayland_data_device.cc
index f0f144c479e..067742691e7 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_data_device.cc
+++ b/chromium/ui/ozone/platform/wayland/wayland_data_device.cc
@@ -5,10 +5,67 @@
#include "ui/ozone/platform/wayland/wayland_data_device.h"
#include "base/bind.h"
+#include "base/memory/shared_memory.h"
+#include "base/strings/string16.h"
+#include "base/strings/utf_string_conversions.h"
+#include "third_party/skia/include/core/SkBitmap.h"
+#include "third_party/skia/include/core/SkCanvas.h"
+#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/base/dragdrop/os_exchange_data.h"
+#include "ui/base/dragdrop/os_exchange_data_provider_aura.h"
#include "ui/ozone/platform/wayland/wayland_connection.h"
+#include "ui/ozone/platform/wayland/wayland_util.h"
+#include "ui/ozone/platform/wayland/wayland_window.h"
namespace ui {
+namespace {
+
+constexpr char kMimeTypeText[] = "text/plain";
+constexpr char kMimeTypeTextUTF8[] = "text/plain;charset=utf-8";
+
+int GetOperation(uint32_t source_actions, uint32_t dnd_action) {
+ uint32_t action = dnd_action != WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE
+ ? dnd_action
+ : source_actions;
+
+ int operation = DragDropTypes::DRAG_NONE;
+ if (action & WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY)
+ operation |= DragDropTypes::DRAG_COPY;
+ if (action & WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE)
+ operation |= DragDropTypes::DRAG_MOVE;
+ // TODO(jkim): Implement branch for WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK
+ if (action & WL_DATA_DEVICE_MANAGER_DND_ACTION_ASK)
+ operation |= DragDropTypes::DRAG_COPY;
+ return operation;
+}
+
+void AddStringToOSExchangeData(const std::string& data,
+ OSExchangeData* os_exchange_data) {
+ DCHECK(os_exchange_data);
+ if (data.empty())
+ return;
+
+ base::string16 string16 = base::UTF8ToUTF16(data);
+ os_exchange_data->SetString(string16);
+}
+
+void AddToOSExchangeData(const std::string& data,
+ const std::string& mime_type,
+ OSExchangeData* os_exchange_data) {
+ DCHECK(os_exchange_data);
+ if ((mime_type == kMimeTypeText || mime_type == kMimeTypeTextUTF8)) {
+ DCHECK(!os_exchange_data->HasString());
+ AddStringToOSExchangeData(data, os_exchange_data);
+ return;
+ }
+
+ // TODO(jkim): Handle other mime types as well.
+ NOTREACHED();
+}
+
+} // namespace
+
// static
const wl_callback_listener WaylandDataDevice::callback_listener_ = {
WaylandDataDevice::SyncCallback,
@@ -16,18 +73,22 @@ const wl_callback_listener WaylandDataDevice::callback_listener_ = {
WaylandDataDevice::WaylandDataDevice(WaylandConnection* connection,
wl_data_device* data_device)
- : data_device_(data_device), connection_(connection) {
+ : data_device_(data_device),
+ connection_(connection),
+ shared_memory_(new base::SharedMemory()) {
static const struct wl_data_device_listener kDataDeviceListener = {
- WaylandDataDevice::OnDataOffer,
- nullptr /*OnEnter*/,
- nullptr /*OnLeave*/,
- nullptr /*OnMotion*/,
- nullptr /*OnDrop*/,
- WaylandDataDevice::OnSelection};
+ WaylandDataDevice::OnDataOffer, WaylandDataDevice::OnEnter,
+ WaylandDataDevice::OnLeave, WaylandDataDevice::OnMotion,
+ WaylandDataDevice::OnDrop, WaylandDataDevice::OnSelection};
wl_data_device_add_listener(data_device_.get(), &kDataDeviceListener, this);
}
-WaylandDataDevice::~WaylandDataDevice() {}
+WaylandDataDevice::~WaylandDataDevice() {
+ if (!shared_memory_->handle().GetHandle())
+ return;
+ shared_memory_->Unmap();
+ shared_memory_->Close();
+}
void WaylandDataDevice::RequestSelectionData(const std::string& mime_type) {
base::ScopedFD fd = selection_offer_->Receive(mime_type);
@@ -44,6 +105,81 @@ void WaylandDataDevice::RequestSelectionData(const std::string& mime_type) {
RegisterSyncCallback();
}
+void WaylandDataDevice::RequestDragData(
+ const std::string& mime_type,
+ base::OnceCallback<void(const std::string&)> callback) {
+ base::ScopedFD fd = drag_offer_->Receive(mime_type);
+ if (!fd.is_valid()) {
+ LOG(ERROR) << "Failed to open file descriptor.";
+ return;
+ }
+
+ // Ensure there is not pending operation to be performed by the compositor,
+ // otherwise read(..) can block awaiting data to be sent to pipe.
+ read_from_fd_closure_ = base::BindOnce(&WaylandDataDevice::ReadDragDataFromFD,
+ base::Unretained(this), std::move(fd),
+ std::move(callback));
+ RegisterSyncCallback();
+}
+
+void WaylandDataDevice::DeliverDragData(const std::string& mime_type,
+ std::string* buffer) {
+ DCHECK(buffer);
+ DCHECK(source_data_);
+
+ if (mime_type != kMimeTypeText && mime_type != kMimeTypeTextUTF8)
+ return;
+
+ const OSExchangeData::FilenameToURLPolicy policy =
+ OSExchangeData::FilenameToURLPolicy::DO_NOT_CONVERT_FILENAMES;
+ // TODO(jkim): Handle other data format as well.
+ if (source_data_->HasURL(policy)) {
+ GURL url;
+ base::string16 title;
+ source_data_->GetURLAndTitle(policy, &url, &title);
+ buffer->append(url.spec());
+ return;
+ }
+
+ if (source_data_->HasString()) {
+ base::string16 data;
+ source_data_->GetString(&data);
+ buffer->append(base::UTF16ToUTF8(data));
+ return;
+ }
+}
+
+void WaylandDataDevice::StartDrag(const wl_data_source& data_source,
+ const ui::OSExchangeData& data) {
+ WaylandWindow* window = connection_->GetCurrentFocusedWindow();
+ if (!window) {
+ LOG(ERROR) << "Failed to get focused window.";
+ return;
+ }
+
+ wl_surface* surface = window->surface();
+ const SkBitmap* icon = data.provider().GetDragImage().bitmap();
+ if (icon && !icon->empty())
+ CreateDragImage(icon);
+
+ source_data_ = std::make_unique<ui::OSExchangeData>(data.provider().Clone());
+ wl_data_device_start_drag(data_device_.get(),
+ const_cast<wl_data_source*>(&data_source), surface,
+ icon_surface_.get(), connection_->serial());
+ connection_->ScheduleFlush();
+}
+
+void WaylandDataDevice::ResetSourceData() {
+ source_data_.reset();
+}
+
+std::vector<std::string> WaylandDataDevice::GetAvailableMimeTypes() {
+ if (selection_offer_)
+ return selection_offer_->GetAvailableMimeTypes();
+
+ return std::vector<std::string>();
+}
+
void WaylandDataDevice::ReadClipboardDataFromFD(base::ScopedFD fd,
const std::string& mime_type) {
std::string contents;
@@ -51,6 +187,14 @@ void WaylandDataDevice::ReadClipboardDataFromFD(base::ScopedFD fd,
connection_->SetClipboardData(contents, mime_type);
}
+void WaylandDataDevice::ReadDragDataFromFD(
+ base::ScopedFD fd,
+ base::OnceCallback<void(const std::string&)> callback) {
+ std::string contents;
+ ReadDataFromFD(std::move(fd), &contents);
+ std::move(callback).Run(contents);
+}
+
void WaylandDataDevice::RegisterSyncCallback() {
DCHECK(!sync_callback_);
sync_callback_.reset(wl_display_sync(connection_->display()));
@@ -67,11 +211,11 @@ void WaylandDataDevice::ReadDataFromFD(base::ScopedFD fd,
contents->append(buffer, length);
}
-std::vector<std::string> WaylandDataDevice::GetAvailableMimeTypes() {
- if (selection_offer_)
- return selection_offer_->GetAvailableMimeTypes();
+void WaylandDataDevice::HandleDeferredLeaveIfNeeded() {
+ if (!is_leaving_)
+ return;
- return std::vector<std::string>();
+ OnLeave(this, data_device_.get());
}
// static
@@ -84,6 +228,116 @@ void WaylandDataDevice::OnDataOffer(void* data,
self->new_offer_.reset(new WaylandDataOffer(offer));
}
+void WaylandDataDevice::OnEnter(void* data,
+ wl_data_device* data_device,
+ uint32_t serial,
+ wl_surface* surface,
+ wl_fixed_t x,
+ wl_fixed_t y,
+ wl_data_offer* offer) {
+ WaylandWindow* window =
+ static_cast<WaylandWindow*>(wl_surface_get_user_data(surface));
+ if (!window) {
+ LOG(ERROR) << "Failed to get window.";
+ return;
+ }
+
+ auto* self = static_cast<WaylandDataDevice*>(data);
+ DCHECK(self->new_offer_);
+ DCHECK(!self->drag_offer_);
+ self->drag_offer_ = std::move(self->new_offer_);
+ self->window_ = window;
+
+ // TODO(jkim): Set mime type the client can accept. Now it sets all mime types
+ // offered because current implementation doesn't decide action based on mime
+ // type.
+ const std::vector<std::string>& mime_types =
+ self->drag_offer_->GetAvailableMimeTypes();
+ for (auto mime : mime_types)
+ self->drag_offer_->Accept(serial, mime);
+
+ std::copy(mime_types.begin(), mime_types.end(),
+ std::insert_iterator<std::list<std::string>>(
+ self->unprocessed_mime_types_,
+ self->unprocessed_mime_types_.begin()));
+
+ int operation = GetOperation(self->drag_offer_->source_actions(),
+ self->drag_offer_->dnd_action());
+ gfx::PointF point(wl_fixed_to_double(x), wl_fixed_to_double(y));
+
+ // If it has |source_data_|, it means that the dragging is started from the
+ // same window and it doesn't need to read the data through Wayland.
+ if (self->source_data_) {
+ std::unique_ptr<OSExchangeData> data = std::make_unique<OSExchangeData>(
+ self->source_data_->provider().Clone());
+ self->window_->OnDragEnter(point, std::move(data), operation);
+ return;
+ }
+
+ self->window_->OnDragEnter(point, nullptr, operation);
+}
+
+void WaylandDataDevice::OnMotion(void* data,
+ wl_data_device* data_device,
+ uint32_t time,
+ wl_fixed_t x,
+ wl_fixed_t y) {
+ auto* self = static_cast<WaylandDataDevice*>(data);
+ if (!self->window_) {
+ LOG(ERROR) << "Failed to get window.";
+ return;
+ }
+
+ int operation = GetOperation(self->drag_offer_->source_actions(),
+ self->drag_offer_->dnd_action());
+ gfx::PointF point(wl_fixed_to_double(x), wl_fixed_to_double(y));
+ int client_operation = self->window_->OnDragMotion(point, time, operation);
+ self->SetOperation(client_operation);
+}
+
+void WaylandDataDevice::OnDrop(void* data, wl_data_device* data_device) {
+ auto* self = static_cast<WaylandDataDevice*>(data);
+ if (!self->window_) {
+ LOG(ERROR) << "Failed to get window.";
+ return;
+ }
+
+ // Creates buffer to receive data from Wayland.
+ self->received_data_ = std::make_unique<OSExchangeData>(
+ std::make_unique<OSExchangeDataProviderAura>());
+
+ // Starts to read the data on Drop event because read(..) API blocks
+ // awaiting data to be sent to pipe if we try to read the data on OnEnter.
+ // 'Weston' also reads data on OnDrop event and other examples do as well.
+ self->HandleNextMimeType();
+
+ // In order to guarantee all data received, it sets
+ // |is_handling_dropped_data_| and defers OnLeave event handling if it gets
+ // OnLeave event before completing to read the data.
+ self->is_handling_dropped_data_ = true;
+}
+
+void WaylandDataDevice::OnLeave(void* data, wl_data_device* data_device) {
+ // While reading data, it could get OnLeave event. We don't handle OnLeave
+ // event directly if |is_handling_dropped_data_| is set.
+ auto* self = static_cast<WaylandDataDevice*>(data);
+ if (!self->window_) {
+ LOG(ERROR) << "Failed to get window.";
+ return;
+ }
+
+ if (self->is_handling_dropped_data_) {
+ self->is_leaving_ = true;
+ return;
+ }
+
+ self->window_->OnDragLeave();
+ self->window_ = nullptr;
+ self->drag_offer_.reset();
+ self->is_handling_dropped_data_ = false;
+ self->is_leaving_ = false;
+}
+
// static
void WaylandDataDevice::OnSelection(void* data,
wl_data_device* data_device,
@@ -118,4 +372,88 @@ void WaylandDataDevice::SyncCallback(void* data,
data_device->sync_callback_.reset();
}
+void WaylandDataDevice::CreateDragImage(const SkBitmap* bitmap) {
+ DCHECK(bitmap);
+ gfx::Size size(bitmap->width(), bitmap->height());
+
+ if (size != icon_buffer_size_) {
+ wl_buffer* buffer =
+ wl::CreateSHMBuffer(size, shared_memory_.get(), connection_->shm());
+ if (!buffer)
+ return;
+
+ buffer_.reset(buffer);
+ icon_buffer_size_ = size;
+ }
+ wl::DrawBitmapToSHMB(icon_buffer_size_, *shared_memory_, *bitmap);
+
+ icon_surface_.reset(wl_compositor_create_surface(connection_->compositor()));
+ wl_surface_attach(icon_surface_.get(), buffer_.get(), 0, 0);
+ wl_surface_damage(icon_surface_.get(), 0, 0, icon_buffer_size_.width(),
+ icon_buffer_size_.height());
+ wl_surface_commit(icon_surface_.get());
+}
+
+void WaylandDataDevice::OnDragDataReceived(const std::string& contents) {
+ if (!contents.empty()) {
+ AddToOSExchangeData(contents, unprocessed_mime_types_.front(),
+ received_data_.get());
+ }
+
+ unprocessed_mime_types_.erase(unprocessed_mime_types_.begin());
+
+ // Read next data corresponding to the mime type.
+ HandleNextMimeType();
+}
+
+void WaylandDataDevice::OnDragDataCollected() {
+ unprocessed_mime_types_.clear();
+ window_->OnDragDrop(std::move(received_data_));
+ drag_offer_->FinishOffer();
+ is_handling_dropped_data_ = false;
+
+ HandleDeferredLeaveIfNeeded();
+}
+
+std::string WaylandDataDevice::SelectNextMimeType() {
+ while (!unprocessed_mime_types_.empty()) {
+ std::string& mime_type = unprocessed_mime_types_.front();
+ if ((mime_type == kMimeTypeText || mime_type == kMimeTypeTextUTF8) &&
+ !received_data_->HasString()) {
+ return mime_type;
+ }
+ // TODO(jkim): Handle other mime types as well.
+ unprocessed_mime_types_.erase(unprocessed_mime_types_.begin());
+ }
+ return std::string();
+}
+
+void WaylandDataDevice::HandleNextMimeType() {
+ std::string mime_type = SelectNextMimeType();
+ if (!mime_type.empty()) {
+ RequestDragData(mime_type,
+ base::BindOnce(&WaylandDataDevice::OnDragDataReceived,
+ base::Unretained(this)));
+ } else {
+ OnDragDataCollected();
+ }
+}
+
+void WaylandDataDevice::SetOperation(const int operation) {
+ uint32_t dnd_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
+ uint32_t preferred_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
+
+ if (operation & DragDropTypes::DRAG_COPY) {
+ dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
+ preferred_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
+ }
+
+ if (operation & DragDropTypes::DRAG_MOVE) {
+ dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
+ if (preferred_action == WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE)
+ preferred_action = WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
+ }
+ drag_offer_->SetAction(dnd_actions, preferred_action);
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/wayland_data_device.h b/chromium/ui/ozone/platform/wayland/wayland_data_device.h
index 3d1eecde15b..f0986709246 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_data_device.h
+++ b/chromium/ui/ozone/platform/wayland/wayland_data_device.h
@@ -6,23 +6,31 @@
#define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_DATA_DEVICE_H_
#include <wayland-client.h>
+#include <list>
#include <string>
#include "base/callback.h"
#include "base/files/scoped_file.h"
#include "base/macros.h"
+#include "ui/gfx/geometry/size.h"
#include "ui/ozone/platform/wayland/wayland_data_offer.h"
#include "ui/ozone/platform/wayland/wayland_object.h"
+class SkBitmap;
+
+namespace base {
+class SharedMemory;
+}
+
namespace ui {
+class OSExchangeData;
class WaylandDataOffer;
class WaylandConnection;
+class WaylandWindow;
// This class provides access to inter-client data transfer mechanisms
// such as copy-and-paste and drag-and-drop mechanisms.
-//
-// TODO(tonikitoo,msisov): Add drag&drop support.
class WaylandDataDevice {
public:
WaylandDataDevice(WaylandConnection* connection, wl_data_device* data_device);
@@ -30,23 +38,66 @@ class WaylandDataDevice {
void RequestSelectionData(const std::string& mime_type);
- wl_data_device* data_device() { return data_device_.get(); }
+ // Requests the data to the platform when Chromium gets drag-and-drop started
+ // by others. Once reading the data from platform is done, |callback| should
+ // be called with the data.
+ void RequestDragData(const std::string& mime_type,
+ base::OnceCallback<void(const std::string&)> callback);
+ // Delivers the data owned by Chromium which initiates drag-and-drop. |buffer|
+ // is an output parameter and it should be filled with the data corresponding
+ // to mime_type.
+ void DeliverDragData(const std::string& mime_type, std::string* buffer);
+ // Starts drag with |data| to be delivered, |operation| supported by the
+ // source side initiated the dragging.
+ void StartDrag(const wl_data_source& data_source,
+ const ui::OSExchangeData& data);
+ // Resets |source_data_| when the dragging is finished.
+ void ResetSourceData();
std::vector<std::string> GetAvailableMimeTypes();
+ wl_data_device* data_device() const { return data_device_.get(); }
+
private:
void ReadClipboardDataFromFD(base::ScopedFD fd, const std::string& mime_type);
+ void ReadDragDataFromFD(
+ base::ScopedFD fd,
+ base::OnceCallback<void(const std::string&)> callback);
+
// Registers display sync callback. Once it's called, it's reset.
void RegisterSyncCallback();
// Helper function to read data from fd.
void ReadDataFromFD(base::ScopedFD fd, std::string* contents);
+ // If OnLeave event occurs while it's reading drag data, it defers handling
+ // it. Once reading data is completed, it's handled.
+ void HandleDeferredLeaveIfNeeded();
+
// wl_data_device_listener callbacks
static void OnDataOffer(void* data,
wl_data_device* data_device,
wl_data_offer* id);
+
+ static void OnEnter(void* data,
+ wl_data_device* data_device,
+ uint32_t serial,
+ wl_surface* surface,
+ wl_fixed_t x,
+ wl_fixed_t y,
+ wl_data_offer* offer);
+
+ static void OnMotion(void* data,
+ struct wl_data_device* data_device,
+ uint32_t time,
+ wl_fixed_t x,
+ wl_fixed_t y);
+
+ static void OnDrop(void* data, struct wl_data_device* data_device);
+
+ static void OnLeave(void* data, struct wl_data_device* data_device);
+
// Called by the compositor when the window gets pointer or keyboard focus,
// or clipboard content changes behind the scenes.
//
@@ -57,6 +108,22 @@ class WaylandDataDevice {
static void SyncCallback(void* data, struct wl_callback* cb, uint32_t time);
+ bool CreateSHMBuffer(const gfx::Size& size);
+ void CreateDragImage(const SkBitmap* bitmap);
+
+ void OnDragDataReceived(const std::string& contents);
+ void OnDragDataCollected();
+
+ // Returns the next MIME type to be received from the source process, or an
+ // empty string if there are no more interesting MIME types left to process.
+ std::string SelectNextMimeType();
+ // If it has |unprocessed_mime_types_|, it takes the mime type in front and
+ // requests the data corresponding to the mime type to wayland.
+ void HandleNextMimeType();
+
+ // Set drag operation decided by client.
+ void SetOperation(const int operation);
+
// The wl_data_device wrapped by this WaylandDataDevice.
wl::Object<wl_data_device> data_device_;
@@ -75,11 +142,36 @@ class WaylandDataDevice {
// clipboard data is available.
std::unique_ptr<WaylandDataOffer> selection_offer_;
+ // Offer to receive data from another process via drag-and-drop, or null if no
+ // drag-and-drop from another process is in progress.
+ std::unique_ptr<WaylandDataOffer> drag_offer_;
+
+ WaylandWindow* window_ = nullptr;
+
// Make sure server has written data on the pipe, before block on read().
static const wl_callback_listener callback_listener_;
base::OnceClosure read_from_fd_closure_;
wl::Object<wl_callback> sync_callback_;
+ bool is_handling_dropped_data_ = false;
+ bool is_leaving_ = false;
+
+ std::unique_ptr<base::SharedMemory> shared_memory_;
+
+ wl::Object<wl_buffer> buffer_;
+ wl::Object<wl_surface> icon_surface_;
+ gfx::Size icon_buffer_size_;
+
+ // Mime types to be handled.
+ std::list<std::string> unprocessed_mime_types_;
+
+ // The data delivered from Wayland
+ std::unique_ptr<ui::OSExchangeData> received_data_;
+
+ // When dragging is started from Chromium, |source_data_| is forwarded to
+ // Wayland when they are ready to get the data.
+ std::unique_ptr<ui::OSExchangeData> source_data_;
+
DISALLOW_COPY_AND_ASSIGN(WaylandDataDevice);
};
diff --git a/chromium/ui/ozone/platform/wayland/wayland_data_device_unittest.cc b/chromium/ui/ozone/platform/wayland/wayland_data_device_unittest.cc
index 03c567e1bc4..f8fe5abf620 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_data_device_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/wayland_data_device_unittest.cc
@@ -5,6 +5,9 @@
#include <wayland-server.h>
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/base/dragdrop/os_exchange_data.h"
+#include "ui/events/base_event_utils.h"
#include "ui/ozone/platform/wayland/fake_server.h"
#include "ui/ozone/platform/wayland/wayland_test.h"
#include "ui/ozone/public/clipboard_delegate.h"
@@ -131,6 +134,63 @@ TEST_P(WaylandDataDeviceManagerTest, IsSelectionOwner) {
ASSERT_FALSE(clipboard_client_->IsSelectionOwner());
}
+TEST_P(WaylandDataDeviceManagerTest, StartDrag) {
+ bool restored_focus = window_->has_pointer_focus();
+ window_->set_pointer_focus(true);
+
+ // The client starts dragging.
+ std::unique_ptr<OSExchangeData> os_exchange_data =
+ std::make_unique<OSExchangeData>();
+ int operation = DragDropTypes::DRAG_COPY | DragDropTypes::DRAG_MOVE;
+ connection_->StartDrag(*os_exchange_data, operation);
+
+ WaylandDataSource::DragDataMap data;
+ data[wl::kTextMimeTypeText] = wl::kSampleTextForDragAndDrop;
+ connection_->drag_data_source()->SetDragData(data);
+
+ Sync();
+ // The server reads the data and the callback gets it.
+ data_device_manager_->data_source()->ReadData(
+ base::BindOnce([](const std::vector<uint8_t>& data) {
+ std::string string_data(data.begin(), data.end());
+ EXPECT_EQ(wl::kSampleTextForDragAndDrop, string_data);
+ }));
+
+ window_->set_pointer_focus(restored_focus);
+}
+
+TEST_P(WaylandDataDeviceManagerTest, ReceiveDrag) {
+ auto* data_offer = data_device_manager_->data_device()->OnDataOffer();
+ data_offer->OnOffer(wl::kTextMimeTypeText);
+
+ gfx::Point entered_point(10, 10);
+ // The server sends an enter event.
+ data_device_manager_->data_device()->OnEnter(
+ 1002, surface_->resource(), wl_fixed_from_int(entered_point.x()),
+ wl_fixed_from_int(entered_point.y()), *data_offer);
+
+ int64_t time =
+ (ui::EventTimeForNow() - base::TimeTicks()).InMilliseconds() & UINT32_MAX;
+ gfx::Point motion_point(11, 11);
+
+ // The server sends an motion event.
+ data_device_manager_->data_device()->OnMotion(
+ time, wl_fixed_from_int(motion_point.x()),
+ wl_fixed_from_int(motion_point.y()));
+
+ Sync();
+
+ auto callback = base::BindOnce([](const std::string& contents) {
+ EXPECT_EQ(wl::kSampleTextForDragAndDrop, contents);
+ });
+
+ // The client requests the data and gets callback with it.
+ connection_->RequestDragData(wl::kTextMimeTypeText, std::move(callback));
+ Sync();
+
+ data_device_manager_->data_device()->OnLeave();
+}
+
INSTANTIATE_TEST_CASE_P(XdgVersionV5Test,
WaylandDataDeviceManagerTest,
::testing::Values(kXdgShellV5));
diff --git a/chromium/ui/ozone/platform/wayland/wayland_data_offer.cc b/chromium/ui/ozone/platform/wayland/wayland_data_offer.cc
index e68554ef483..a3900dd2341 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_data_offer.cc
+++ b/chromium/ui/ozone/platform/wayland/wayland_data_offer.cc
@@ -30,9 +30,12 @@ void CreatePipe(base::ScopedFD* read_pipe, base::ScopedFD* write_pipe) {
} // namespace
WaylandDataOffer::WaylandDataOffer(wl_data_offer* data_offer)
- : data_offer_(data_offer) {
+ : data_offer_(data_offer),
+ source_actions_(WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE),
+ dnd_action_(WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE) {
static const struct wl_data_offer_listener kDataOfferListener = {
- WaylandDataOffer::OnOffer};
+ WaylandDataOffer::OnOffer, WaylandDataOffer::OnSourceAction,
+ WaylandDataOffer::OnAction};
wl_data_offer_add_listener(data_offer, &kDataOfferListener, this);
}
@@ -40,6 +43,23 @@ WaylandDataOffer::~WaylandDataOffer() {
data_offer_.reset();
}
+void WaylandDataOffer::SetAction(uint32_t dnd_actions,
+ uint32_t preferred_action) {
+ if (wl_data_offer_get_version(data_offer_.get()) >=
+ WL_DATA_OFFER_SET_ACTIONS_SINCE_VERSION) {
+ wl_data_offer_set_actions(data_offer_.get(), dnd_actions, preferred_action);
+ }
+}
+
+void WaylandDataOffer::Accept(uint32_t serial, const std::string& mime_type) {
+ wl_data_offer_accept(data_offer_.get(), serial, mime_type.c_str());
+}
+
+void WaylandDataOffer::Reject(uint32_t serial) {
+ // Passing a null MIME type means "reject."
+ wl_data_offer_accept(data_offer_.get(), serial, nullptr);
+}
+
void WaylandDataOffer::EnsureTextMimeTypeIfNeeded() {
if (base::ContainsValue(mime_types_, kTextPlain))
return;
@@ -76,6 +96,20 @@ base::ScopedFD WaylandDataOffer::Receive(const std::string& mime_type) {
return read_fd;
}
+void WaylandDataOffer::FinishOffer() {
+ if (wl_data_offer_get_version(data_offer_.get()) >=
+ WL_DATA_OFFER_FINISH_SINCE_VERSION)
+ wl_data_offer_finish(data_offer_.get());
+}
+
+uint32_t WaylandDataOffer::source_actions() const {
+ return source_actions_;
+}
+
+uint32_t WaylandDataOffer::dnd_action() const {
+ return dnd_action_;
+}
+
// static
void WaylandDataOffer::OnOffer(void* data,
wl_data_offer* data_offer,
@@ -84,4 +118,18 @@ void WaylandDataOffer::OnOffer(void* data,
self->mime_types_.push_back(mime_type);
}
+void WaylandDataOffer::OnSourceAction(void* data,
+ wl_data_offer* offer,
+ uint32_t source_actions) {
+ auto* self = static_cast<WaylandDataOffer*>(data);
+ self->source_actions_ = source_actions;
+}
+
+void WaylandDataOffer::OnAction(void* data,
+ wl_data_offer* offer,
+ uint32_t dnd_action) {
+ auto* self = static_cast<WaylandDataOffer*>(data);
+ self->dnd_action_ = dnd_action;
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/wayland_data_offer.h b/chromium/ui/ozone/platform/wayland/wayland_data_offer.h
index 3b9e06f23c2..a2e8170534b 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_data_offer.h
+++ b/chromium/ui/ozone/platform/wayland/wayland_data_offer.h
@@ -23,8 +23,6 @@ namespace ui {
// The offer describes the different mime types that the data can be
// converted to and provides the mechanism for transferring the data
// directly from the source client.
-//
-// TODO(tonikitoo,msisov): Add drag&drop support.
class WaylandDataOffer {
public:
// Takes ownership of data_offer.
@@ -42,20 +40,36 @@ class WaylandDataOffer {
// list of provided mime types so that Chrome clipboard's machinery
// works fine.
void EnsureTextMimeTypeIfNeeded();
+ void SetAction(uint32_t dnd_actions, uint32_t preferred_action);
+ void Accept(uint32_t serial, const std::string& mime_type);
+ void Reject(uint32_t serial);
// Creates a pipe (read & write FDs), passing the write-end of to pipe
// to the compositor (via wl_data_offer_receive) and returning the
// read-end to the pipe.
base::ScopedFD Receive(const std::string& mime_type);
+ void FinishOffer();
+ uint32_t source_actions() const;
+ uint32_t dnd_action() const;
private:
// wl_data_offer_listener callbacks.
static void OnOffer(void* data,
wl_data_offer* data_offer,
const char* mime_type);
+ // Notifies the source-side available actions
+ static void OnSourceAction(void* data,
+ wl_data_offer* offer,
+ uint32_t source_actions);
+ // Notifies the selected action
+ static void OnAction(void* data, wl_data_offer* offer, uint32_t dnd_action);
wl::Object<wl_data_offer> data_offer_;
std::vector<std::string> mime_types_;
+ // Actions offered by the data source
+ uint32_t source_actions_;
+ // Action selected by the compositor
+ uint32_t dnd_action_;
bool text_plain_mime_type_inserted_ = false;
diff --git a/chromium/ui/ozone/platform/wayland/wayland_data_source.cc b/chromium/ui/ozone/platform/wayland/wayland_data_source.cc
index 7b61ad24c02..e1fe23b6c19 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_data_source.cc
+++ b/chromium/ui/ozone/platform/wayland/wayland_data_source.cc
@@ -5,17 +5,22 @@
#include "ui/ozone/platform/wayland/wayland_data_source.h"
#include "base/files/file_util.h"
+#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/ozone/platform/wayland/wayland_connection.h"
+#include "ui/ozone/platform/wayland/wayland_window.h"
namespace ui {
+constexpr char kTextMimeType[] = "text/plain";
constexpr char kTextMimeTypeUtf8[] = "text/plain;charset=utf-8";
-WaylandDataSource::WaylandDataSource(wl_data_source* data_source)
- : data_source_(data_source) {
+WaylandDataSource::WaylandDataSource(wl_data_source* data_source,
+ WaylandConnection* connection)
+ : data_source_(data_source), connection_(connection) {
static const struct wl_data_source_listener kDataSourceListener = {
- WaylandDataSource::OnTarget, WaylandDataSource::OnSend,
- WaylandDataSource::OnCancel};
+ WaylandDataSource::OnTarget, WaylandDataSource::OnSend,
+ WaylandDataSource::OnCancel, WaylandDataSource::OnDnDDropPerformed,
+ WaylandDataSource::OnDnDFinished, WaylandDataSource::OnAction};
wl_data_source_add_listener(data_source, &kDataSourceListener, this);
}
@@ -25,7 +30,7 @@ void WaylandDataSource::WriteToClipboard(
const ClipboardDelegate::DataMap& data_map) {
for (const auto& data : data_map) {
wl_data_source_offer(data_source_.get(), data.first.c_str());
- if (strcmp(data.first.c_str(), "text/plain") == 0)
+ if (strcmp(data.first.c_str(), kTextMimeType) == 0)
wl_data_source_offer(data_source_.get(), kTextMimeTypeUtf8);
}
wl_data_device_set_selection(connection_->data_device(), data_source_.get(),
@@ -39,11 +44,39 @@ void WaylandDataSource::UpdataDataMap(
data_map_ = data_map;
}
+void WaylandDataSource::Offer(const ui::OSExchangeData& data) {
+ // TODO(jkim): Handle mime types based on data.
+ std::vector<std::string> mime_types;
+ mime_types.push_back(kTextMimeType);
+ mime_types.push_back(kTextMimeTypeUtf8);
+
+ source_window_ = connection_->GetCurrentFocusedWindow();
+ for (auto& mime_type : mime_types)
+ wl_data_source_offer(data_source_.get(), mime_type.data());
+}
+
+void WaylandDataSource::SetDragData(const DragDataMap& data_map) {
+ DCHECK(drag_data_map_.empty());
+ drag_data_map_ = data_map;
+}
+
+void WaylandDataSource::SetAction(int operation) {
+ if (wl_data_source_get_version(data_source_.get()) >=
+ WL_DATA_SOURCE_SET_ACTIONS_SINCE_VERSION) {
+ uint32_t dnd_actions = WL_DATA_DEVICE_MANAGER_DND_ACTION_NONE;
+ if (operation & DragDropTypes::DRAG_COPY)
+ dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_COPY;
+ if (operation & DragDropTypes::DRAG_MOVE)
+ dnd_actions |= WL_DATA_DEVICE_MANAGER_DND_ACTION_MOVE;
+ wl_data_source_set_actions(data_source_.get(), dnd_actions);
+ }
+}
+
// static
void WaylandDataSource::OnTarget(void* data,
wl_data_source* source,
const char* mime_type) {
- NOTIMPLEMENTED();
+ NOTIMPLEMENTED_LOG_ONCE();
}
// static
@@ -52,12 +85,18 @@ void WaylandDataSource::OnSend(void* data,
const char* mime_type,
int32_t fd) {
WaylandDataSource* self = static_cast<WaylandDataSource*>(data);
- base::Optional<std::vector<uint8_t>> mime_data;
- self->GetClipboardData(mime_type, &mime_data);
- if (!mime_data.has_value() && strcmp(mime_type, kTextMimeTypeUtf8) == 0)
- self->GetClipboardData("text/plain", &mime_data);
-
- std::string contents(mime_data->begin(), mime_data->end());
+ std::string contents;
+ if (self->source_window_) {
+ // If |source_window_| is valid when OnSend() is called, it means that DnD
+ // is working.
+ self->GetDragData(mime_type, &contents);
+ } else {
+ base::Optional<std::vector<uint8_t>> mime_data;
+ self->GetClipboardData(mime_type, &mime_data);
+ if (!mime_data.has_value() && strcmp(mime_type, kTextMimeTypeUtf8) == 0)
+ self->GetClipboardData(kTextMimeType, &mime_data);
+ contents.assign(mime_data->begin(), mime_data->end());
+ }
bool result =
base::WriteFileDescriptor(fd, contents.data(), contents.length());
DCHECK(result);
@@ -67,7 +106,30 @@ void WaylandDataSource::OnSend(void* data,
// static
void WaylandDataSource::OnCancel(void* data, wl_data_source* source) {
WaylandDataSource* self = static_cast<WaylandDataSource*>(data);
- self->connection_->DataSourceCancelled();
+ if (self->source_window_) {
+ // If it has |source_window_|, it is in the middle of 'drag and drop'. it
+ // cancels 'drag and drop'.
+ self->connection_->FinishDragSession(self->dnd_action_,
+ self->source_window_);
+ } else {
+ self->connection_->DataSourceCancelled();
+ }
+}
+
+void WaylandDataSource::OnDnDDropPerformed(void* data, wl_data_source* source) {
+ NOTIMPLEMENTED_LOG_ONCE();
+}
+
+void WaylandDataSource::OnDnDFinished(void* data, wl_data_source* source) {
+ WaylandDataSource* self = static_cast<WaylandDataSource*>(data);
+ self->connection_->FinishDragSession(self->dnd_action_, self->source_window_);
+}
+
+void WaylandDataSource::OnAction(void* data,
+ wl_data_source* source,
+ uint32_t dnd_action) {
+ WaylandDataSource* self = static_cast<WaylandDataSource*>(data);
+ self->dnd_action_ = dnd_action;
}
void WaylandDataSource::GetClipboardData(
@@ -81,4 +143,15 @@ void WaylandDataSource::GetClipboardData(
}
}
+void WaylandDataSource::GetDragData(const std::string& mime_type,
+ std::string* contents) {
+ auto it = drag_data_map_.find(mime_type);
+ if (it != drag_data_map_.end()) {
+ *contents = it->second;
+ return;
+ }
+
+ connection_->DeliverDragData(mime_type, contents);
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/wayland_data_source.h b/chromium/ui/ozone/platform/wayland/wayland_data_source.h
index 9ee33971a93..33dfeb2f912 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_data_source.h
+++ b/chromium/ui/ozone/platform/wayland/wayland_data_source.h
@@ -7,8 +7,8 @@
#include <wayland-client.h>
+#include <map>
#include <string>
-#include <unordered_map>
#include <vector>
#include "base/logging.h"
@@ -19,7 +19,9 @@
namespace ui {
+class OSExchangeData;
class WaylandConnection;
+class WaylandWindow;
// The WaylandDataSource object represents the source side of a
// WaylandDataOffer. It is created by the source client in a data
@@ -28,8 +30,11 @@ class WaylandConnection;
// transfer the data (OnSend listener).
class WaylandDataSource {
public:
+ using DragDataMap = std::map<std::string, std::string>;
+
// Takes ownership of data_source.
- explicit WaylandDataSource(wl_data_source* data_source);
+ explicit WaylandDataSource(wl_data_source* data_source,
+ WaylandConnection* connection);
~WaylandDataSource();
void set_connection(WaylandConnection* connection) {
@@ -39,6 +44,11 @@ class WaylandDataSource {
void WriteToClipboard(const ClipboardDelegate::DataMap& data_map);
void UpdataDataMap(const ClipboardDelegate::DataMap& data_map);
+ void Offer(const ui::OSExchangeData& data);
+ void SetAction(int operation);
+ void SetDragData(const DragDataMap& data_map);
+
+ const wl_data_source* data_source() const { return data_source_.get(); }
private:
static void OnTarget(void* data,
@@ -49,14 +59,22 @@ class WaylandDataSource {
const char* mime_type,
int32_t fd);
static void OnCancel(void* data, wl_data_source* source);
+ static void OnDnDDropPerformed(void* data, wl_data_source* source);
+ static void OnDnDFinished(void* data, wl_data_source* source);
+ static void OnAction(void* data, wl_data_source* source, uint32_t dnd_action);
void GetClipboardData(const std::string& mime_type,
base::Optional<std::vector<uint8_t>>* data);
+ void GetDragData(const std::string& mime_type, std::string* contents);
wl::Object<wl_data_source> data_source_;
WaylandConnection* connection_ = nullptr;
+ WaylandWindow* source_window_ = nullptr;
ClipboardDelegate::DataMap data_map_;
+ DragDataMap drag_data_map_;
+ // Action selected by the compositor
+ uint32_t dnd_action_;
DISALLOW_COPY_AND_ASSIGN(WaylandDataSource);
};
diff --git a/chromium/ui/ozone/platform/wayland/wayland_input_method_context.cc b/chromium/ui/ozone/platform/wayland/wayland_input_method_context.cc
new file mode 100644
index 00000000000..959a8e331db
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_input_method_context.cc
@@ -0,0 +1,151 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/wayland/wayland_input_method_context.h"
+
+#include "base/bind.h"
+#include "base/command_line.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/string_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "ui/base/ime/composition_text.h"
+#include "ui/events/base_event_utils.h"
+#include "ui/events/event.h"
+#include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/events/keycodes/dom/keycode_converter.h"
+#include "ui/events/keycodes/keyboard_code_conversion.h"
+#include "ui/events/keycodes/keyboard_code_conversion_xkb.h"
+#include "ui/events/ozone/layout/keyboard_layout_engine.h"
+#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
+#include "ui/gfx/range/range.h"
+#include "ui/ozone/platform/wayland/wayland_connection.h"
+#include "ui/ozone/platform/wayland/zwp_text_input_wrapper_v1.h"
+#include "ui/ozone/public/ozone_switches.h"
+
+namespace ui {
+
+namespace {
+
+constexpr int kXkbKeycodeOffset = 8;
+
+} // namespace
+
+WaylandInputMethodContext::WaylandInputMethodContext(
+ WaylandConnection* connection,
+ LinuxInputMethodContextDelegate* delegate,
+ bool is_simple,
+ const EventDispatchCallback& callback)
+ : connection_(connection),
+ delegate_(delegate),
+ is_simple_(is_simple),
+ callback_(callback),
+ text_input_(nullptr) {
+ Init();
+}
+
+WaylandInputMethodContext::~WaylandInputMethodContext() {
+ if (text_input_) {
+ text_input_->Deactivate();
+ text_input_->HideInputPanel();
+ }
+}
+
+void WaylandInputMethodContext::Init(bool initialize_for_testing) {
+ bool use_ozone_wayland_vkb =
+ initialize_for_testing ||
+ base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableWaylandIme);
+
+ // If text input instance is not created then all ime context operations
+ // are noop. This option is because in some environments someone might not
+ // want to enable ime/virtual keyboard even if it's available.
+ if (use_ozone_wayland_vkb && !is_simple_ && !text_input_ &&
+ connection_->text_input_manager_v1()) {
+ text_input_ = std::make_unique<ZWPTextInputWrapperV1>(
+ connection_->text_input_manager_v1());
+ text_input_->Initialize(connection_, this);
+ }
+}
+
+bool WaylandInputMethodContext::DispatchKeyEvent(
+ const ui::KeyEvent& key_event) {
+ return false;
+}
+
+void WaylandInputMethodContext::Reset() {
+ if (text_input_)
+ text_input_->Reset();
+}
+
+void WaylandInputMethodContext::Focus() {
+ WaylandWindow* window = connection_->GetCurrentKeyboardFocusedWindow();
+ if (!text_input_ || !window)
+ return;
+
+ text_input_->Activate(window);
+ text_input_->ShowInputPanel();
+}
+
+void WaylandInputMethodContext::Blur() {
+ if (text_input_) {
+ text_input_->Deactivate();
+ text_input_->HideInputPanel();
+ }
+}
+
+void WaylandInputMethodContext::SetCursorLocation(const gfx::Rect& rect) {
+ if (text_input_)
+ text_input_->SetCursorRect(rect);
+}
+
+void WaylandInputMethodContext::SetSurroundingText(
+ const base::string16& text,
+ const gfx::Range& selection_range) {
+ if (text_input_)
+ text_input_->SetSurroundingText(text, selection_range);
+}
+
+void WaylandInputMethodContext::OnPreeditString(const std::string& text,
+ int preedit_cursor) {
+ gfx::Range selection_range = gfx::Range::InvalidRange();
+
+ if (!selection_range.IsValid()) {
+ int cursor_pos = (preedit_cursor) ? text.length() : preedit_cursor;
+ selection_range.set_start(cursor_pos);
+ selection_range.set_end(cursor_pos);
+ }
+
+ ui::CompositionText composition_text;
+ composition_text.text = base::UTF8ToUTF16(text);
+ composition_text.selection = selection_range;
+ delegate_->OnPreeditChanged(composition_text);
+}
+
+void WaylandInputMethodContext::OnCommitString(const std::string& text) {
+ delegate_->OnCommit(base::UTF8ToUTF16(text));
+}
+
+void WaylandInputMethodContext::OnDeleteSurroundingText(int32_t index,
+ uint32_t length) {
+ delegate_->OnDeleteSurroundingText(index, length);
+}
+
+void WaylandInputMethodContext::OnKeysym(uint32_t key,
+ uint32_t state,
+ uint32_t modifiers) {
+ uint8_t flags = 0; // for now ignore modifiers
+ DomKey dom_key = NonPrintableXKeySymToDomKey(key);
+ KeyboardCode key_code = NonPrintableDomKeyToKeyboardCode(dom_key);
+ DomCode dom_code =
+ KeycodeConverter::NativeKeycodeToDomCode(key_code + kXkbKeycodeOffset);
+ if (dom_code == ui::DomCode::NONE)
+ return;
+
+ bool down = state == WL_KEYBOARD_KEY_STATE_PRESSED;
+ ui::KeyEvent event(down ? ET_KEY_PRESSED : ET_KEY_RELEASED, key_code,
+ dom_code, flags, dom_key, EventTimeForNow());
+ callback_.Run(&event);
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/wayland_input_method_context.h b/chromium/ui/ozone/platform/wayland/wayland_input_method_context.h
new file mode 100644
index 00000000000..1023ecca585
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_input_method_context.h
@@ -0,0 +1,59 @@
+// 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_OZONE_PLATFORM_WAYLAND_WAYLAND_INPUT_METHOD_CONTEXT_H_
+#define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_INPUT_METHOD_CONTEXT_H_
+
+#include "base/macros.h"
+#include "ui/base/ime/linux/linux_input_method_context.h"
+#include "ui/events/ozone/evdev/event_dispatch_callback.h"
+#include "ui/ozone/platform/wayland/zwp_text_input_wrapper.h"
+
+namespace ui {
+
+class WaylandConnection;
+class ZWPTextInputWrapper;
+
+class WaylandInputMethodContext : public LinuxInputMethodContext,
+ public ZWPTextInputWrapperClient {
+ public:
+ WaylandInputMethodContext(WaylandConnection* connection,
+ LinuxInputMethodContextDelegate* delegate,
+ bool is_simple,
+ const EventDispatchCallback& callback);
+ ~WaylandInputMethodContext() override;
+
+ void Init(bool initialize_for_testing = false);
+
+ // LinuxInputMethodContext overrides:
+ bool DispatchKeyEvent(const ui::KeyEvent& key_event) override;
+ void SetCursorLocation(const gfx::Rect& rect) override;
+ void SetSurroundingText(const base::string16& text,
+ const gfx::Range& selection_range) override;
+ void Reset() override;
+ void Focus() override;
+ void Blur() override;
+
+ // ui::ZWPTextInputWrapperClient
+ void OnPreeditString(const std::string& text, int preedit_cursor) override;
+ void OnCommitString(const std::string& text) override;
+ void OnDeleteSurroundingText(int32_t index, uint32_t length) override;
+ void OnKeysym(uint32_t key, uint32_t state, uint32_t modifiers) override;
+
+ private:
+ WaylandConnection* connection_ = nullptr; // TODO(jani) Handle this better
+
+ // Delegate interface back to IME code in ui.
+ LinuxInputMethodContextDelegate* delegate_;
+ bool is_simple_;
+ EventDispatchCallback callback_;
+
+ std::unique_ptr<ZWPTextInputWrapper> text_input_;
+
+ DISALLOW_COPY_AND_ASSIGN(WaylandInputMethodContext);
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_WAYLAND_WAYLAND_INPUT_METHOD_CONTEXT_H_
diff --git a/chromium/ui/ozone/platform/wayland/wayland_input_method_context_factory.cc b/chromium/ui/ozone/platform/wayland/wayland_input_method_context_factory.cc
new file mode 100644
index 00000000000..1eaf6fae245
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_input_method_context_factory.cc
@@ -0,0 +1,39 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/wayland/wayland_input_method_context_factory.h"
+
+#include "ui/ozone/platform/wayland/wayland_connection.h"
+#include "ui/ozone/platform/wayland/wayland_input_method_context.h"
+
+namespace ui {
+
+WaylandInputMethodContextFactory::WaylandInputMethodContextFactory(
+ WaylandConnection* connection)
+ : connection_(connection) {
+ LinuxInputMethodContextFactory::SetInstance(this);
+}
+
+WaylandInputMethodContextFactory::~WaylandInputMethodContextFactory() {
+ LinuxInputMethodContextFactory::SetInstance(nullptr);
+}
+
+std::unique_ptr<LinuxInputMethodContext>
+WaylandInputMethodContextFactory::CreateInputMethodContext(
+ LinuxInputMethodContextDelegate* delegate,
+ bool is_simple) const {
+ return CreateWaylandInputMethodContext(delegate, is_simple);
+}
+
+std::unique_ptr<WaylandInputMethodContext>
+WaylandInputMethodContextFactory::CreateWaylandInputMethodContext(
+ ui::LinuxInputMethodContextDelegate* delegate,
+ bool is_simple) const {
+ return std::make_unique<WaylandInputMethodContext>(
+ connection_, delegate, is_simple,
+ base::BindRepeating(&WaylandConnection::DispatchUiEvent,
+ base::Unretained(connection_)));
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/wayland_input_method_context_factory.h b/chromium/ui/ozone/platform/wayland/wayland_input_method_context_factory.h
new file mode 100644
index 00000000000..413f3a4a500
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_input_method_context_factory.h
@@ -0,0 +1,38 @@
+// 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_OZONE_PLATFORM_WAYLAND_WAYLAND_INPUT_METHOD_CONTEXT_FACTORY_H_
+#define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_INPUT_METHOD_CONTEXT_FACTORY_H_
+
+#include "base/macros.h"
+#include "ui/base/ime/linux/linux_input_method_context_factory.h"
+
+namespace ui {
+
+class WaylandConnection;
+class WaylandInputMethodContext;
+
+class WaylandInputMethodContextFactory : public LinuxInputMethodContextFactory {
+ public:
+ explicit WaylandInputMethodContextFactory(WaylandConnection* connection);
+ ~WaylandInputMethodContextFactory() override;
+
+ std::unique_ptr<LinuxInputMethodContext> CreateInputMethodContext(
+ ui::LinuxInputMethodContextDelegate* delegate,
+ bool is_simple) const override;
+
+ // Exposed for unit tests but also called by CreateInputMethodContext
+ std::unique_ptr<WaylandInputMethodContext> CreateWaylandInputMethodContext(
+ ui::LinuxInputMethodContextDelegate* delegate,
+ bool is_simple) const;
+
+ private:
+ WaylandConnection* connection_;
+
+ DISALLOW_COPY_AND_ASSIGN(WaylandInputMethodContextFactory);
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_WAYLAND_WAYLAND_INPUT_METHOD_CONTEXT_FACTORY_H_
diff --git a/chromium/ui/ozone/platform/wayland/wayland_input_method_context_unittest.cc b/chromium/ui/ozone/platform/wayland/wayland_input_method_context_unittest.cc
new file mode 100644
index 00000000000..666910c4110
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_input_method_context_unittest.cc
@@ -0,0 +1,140 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <text-input-unstable-v1-server-protocol.h>
+#include <wayland-server.h>
+
+#include "mojo/public/cpp/bindings/binding.h"
+#include "testing/gmock/include/gmock/gmock.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/ime/linux/linux_input_method_context.h"
+#include "ui/events/event.h"
+#include "ui/ozone/platform/wayland/fake_server.h"
+#include "ui/ozone/platform/wayland/wayland_input_method_context.h"
+#include "ui/ozone/platform/wayland/wayland_input_method_context_factory.h"
+#include "ui/ozone/platform/wayland/wayland_test.h"
+#include "ui/ozone/platform/wayland/wayland_window.h"
+
+using ::testing::SaveArg;
+using ::testing::_;
+
+namespace ui {
+
+class TestInputMethodContextDelegate : public LinuxInputMethodContextDelegate {
+ public:
+ TestInputMethodContextDelegate() {}
+ ~TestInputMethodContextDelegate() override {}
+
+ void OnCommit(const base::string16& text) override {
+ was_on_commit_called_ = true;
+ }
+ void OnPreeditChanged(const ui::CompositionText& composition_text) override {
+ was_on_preedit_changed_called_ = true;
+ }
+ void OnPreeditEnd() override {}
+ void OnPreeditStart() override {}
+ void OnDeleteSurroundingText(int32_t index, uint32_t length) override{};
+
+ bool was_on_commit_called() { return was_on_commit_called_; }
+
+ bool was_on_preedit_changed_called() {
+ return was_on_preedit_changed_called_;
+ }
+
+ private:
+ bool was_on_commit_called_ = false;
+ bool was_on_preedit_changed_called_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(TestInputMethodContextDelegate);
+};
+
+class WaylandInputMethodContextTest : public WaylandTest {
+ public:
+ WaylandInputMethodContextTest() {}
+
+ void SetUp() override {
+ WaylandTest::SetUp();
+
+ Sync();
+
+ input_method_context_delegate_ =
+ std::make_unique<TestInputMethodContextDelegate>();
+
+ WaylandInputMethodContextFactory factory(connection_.get());
+ input_method_context_ = factory.CreateWaylandInputMethodContext(
+ input_method_context_delegate_.get(), false);
+ input_method_context_->Init(true);
+ connection_->ScheduleFlush();
+
+ Sync();
+
+ zwp_text_input_ = server_.text_input_manager_v1()->text_input.get();
+ window_->set_keyboard_focus(true);
+
+ ASSERT_TRUE(connection_->text_input_manager_v1());
+ ASSERT_TRUE(zwp_text_input_);
+ }
+
+ protected:
+ std::unique_ptr<TestInputMethodContextDelegate>
+ input_method_context_delegate_;
+ std::unique_ptr<WaylandInputMethodContext> input_method_context_;
+ wl::MockZwpTextInput* zwp_text_input_ = nullptr;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WaylandInputMethodContextTest);
+};
+
+TEST_P(WaylandInputMethodContextTest, Focus) {
+ EXPECT_CALL(*zwp_text_input_, Activate(surface_->resource()));
+ EXPECT_CALL(*zwp_text_input_, ShowInputPanel());
+ input_method_context_->Focus();
+ connection_->ScheduleFlush();
+ Sync();
+}
+
+TEST_P(WaylandInputMethodContextTest, Blur) {
+ EXPECT_CALL(*zwp_text_input_, Deactivate());
+ EXPECT_CALL(*zwp_text_input_, HideInputPanel());
+ input_method_context_->Blur();
+ connection_->ScheduleFlush();
+ Sync();
+}
+
+TEST_P(WaylandInputMethodContextTest, Reset) {
+ EXPECT_CALL(*zwp_text_input_, Reset());
+ input_method_context_->Reset();
+ connection_->ScheduleFlush();
+ Sync();
+}
+
+TEST_P(WaylandInputMethodContextTest, SetCursorLocation) {
+ EXPECT_CALL(*zwp_text_input_, SetCursorRect(50, 0, 1, 1));
+ input_method_context_->SetCursorLocation(gfx::Rect(50, 0, 1, 1));
+ connection_->ScheduleFlush();
+ Sync();
+}
+
+TEST_P(WaylandInputMethodContextTest, OnPreeditChanged) {
+ zwp_text_input_v1_send_preedit_string(zwp_text_input_->resource(), 0,
+ "PreeditString", "");
+ Sync();
+ EXPECT_TRUE(input_method_context_delegate_->was_on_preedit_changed_called());
+}
+
+TEST_P(WaylandInputMethodContextTest, OnCommit) {
+ zwp_text_input_v1_send_commit_string(zwp_text_input_->resource(), 0,
+ "CommitString");
+ Sync();
+ EXPECT_TRUE(input_method_context_delegate_->was_on_commit_called());
+}
+
+INSTANTIATE_TEST_CASE_P(XdgVersionV5Test,
+ WaylandInputMethodContextTest,
+ ::testing::Values(kXdgShellV5));
+INSTANTIATE_TEST_CASE_P(XdgVersionV6Test,
+ WaylandInputMethodContextTest,
+ ::testing::Values(kXdgShellV6));
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/wayland_keyboard.cc b/chromium/ui/ozone/platform/wayland/wayland_keyboard.cc
index 396c640ddf0..b6568596683 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_keyboard.cc
+++ b/chromium/ui/ozone/platform/wayland/wayland_keyboard.cc
@@ -8,6 +8,7 @@
#include "base/files/scoped_file.h"
#include "ui/base/ui_features.h"
+#include "ui/events/base_event_utils.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
@@ -120,9 +121,8 @@ void WaylandKeyboard::Key(void* data,
key, down, false /*suppress_auto_repeat*/, device_id);
// TODO(tonikitoo,msisov): Handler 'repeat' parameter below.
- keyboard->DispatchKey(
- key, down, false /*repeat*/,
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(time), device_id);
+ keyboard->DispatchKey(key, down, false /*repeat*/, EventTimeForNow(),
+ device_id);
}
void WaylandKeyboard::Modifiers(void* data,
diff --git a/chromium/ui/ozone/platform/wayland/wayland_native_display_delegate.cc b/chromium/ui/ozone/platform/wayland/wayland_native_display_delegate.cc
deleted file mode 100644
index 029da54058b..00000000000
--- a/chromium/ui/ozone/platform/wayland/wayland_native_display_delegate.cc
+++ /dev/null
@@ -1,105 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/ozone/platform/wayland/wayland_native_display_delegate.h"
-
-#include "ui/display/types/display_snapshot.h"
-#include "ui/display/types/native_display_observer.h"
-#include "ui/ozone/platform/wayland/wayland_connection.h"
-
-namespace ui {
-
-WaylandNativeDisplayDelegate::WaylandNativeDisplayDelegate(
- WaylandConnection* connection)
- : connection_(connection) {}
-
-WaylandNativeDisplayDelegate::~WaylandNativeDisplayDelegate() {
- connection_->PrimaryOutput()->SetObserver(nullptr);
-}
-
-void WaylandNativeDisplayDelegate::Initialize() {
- // TODO(msisov): Add support for secondary output.
- WaylandOutput* primary_output = connection_->PrimaryOutput();
- if (!primary_output)
- NOTREACHED() << "Asynchronous display data fetching is not available";
-
- primary_output->SetObserver(this);
-}
-
-void WaylandNativeDisplayDelegate::TakeDisplayControl(
- display::DisplayControlCallback callback) {
- NOTREACHED();
-}
-
-void WaylandNativeDisplayDelegate::RelinquishDisplayControl(
- display::DisplayControlCallback callback) {
- NOTREACHED();
-}
-
-void WaylandNativeDisplayDelegate::GetDisplays(
- display::GetDisplaysCallback callback) {
- if (displays_ready_)
- connection_->PrimaryOutput()->GetDisplaysSnapshot(std::move(callback));
-}
-
-void WaylandNativeDisplayDelegate::Configure(
- const display::DisplaySnapshot& output,
- const display::DisplayMode* mode,
- const gfx::Point& origin,
- display::ConfigureCallback callback) {
- NOTREACHED();
-}
-
-void WaylandNativeDisplayDelegate::GetHDCPState(
- const display::DisplaySnapshot& output,
- display::GetHDCPStateCallback callback) {
- NOTREACHED();
-}
-
-void WaylandNativeDisplayDelegate::SetHDCPState(
- const display::DisplaySnapshot& output,
- display::HDCPState state,
- display::SetHDCPStateCallback callback) {
- NOTREACHED();
-}
-
-bool WaylandNativeDisplayDelegate::SetColorMatrix(
- int64_t display_id,
- const std::vector<float>& color_matrix) {
- NOTREACHED();
- return false;
-}
-
-bool WaylandNativeDisplayDelegate::SetGammaCorrection(
- int64_t display_id,
- const std::vector<display::GammaRampRGBEntry>& degamma_lut,
- const std::vector<display::GammaRampRGBEntry>& gamma_lut) {
- NOTREACHED();
- return false;
-}
-
-void WaylandNativeDisplayDelegate::AddObserver(
- display::NativeDisplayObserver* observer) {
- observers_.AddObserver(observer);
-}
-
-void WaylandNativeDisplayDelegate::RemoveObserver(
- display::NativeDisplayObserver* observer) {
- observers_.RemoveObserver(observer);
-}
-
-display::FakeDisplayController*
-WaylandNativeDisplayDelegate::GetFakeDisplayController() {
- return nullptr;
-}
-
-void WaylandNativeDisplayDelegate::OnOutputReadyForUse() {
- if (!displays_ready_)
- displays_ready_ = true;
-
- for (display::NativeDisplayObserver& observer : observers_)
- observer.OnConfigurationChanged();
-}
-
-} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/wayland_native_display_delegate.h b/chromium/ui/ozone/platform/wayland/wayland_native_display_delegate.h
deleted file mode 100644
index e0559cb3e59..00000000000
--- a/chromium/ui/ozone/platform/wayland/wayland_native_display_delegate.h
+++ /dev/null
@@ -1,65 +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_OZONE_PLATFORM_WAYLAND_WAYLAND_NATIVE_DISPLAY_DELEGATE_H_
-#define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_NATIVE_DISPLAY_DELEGATE_H_
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "base/observer_list.h"
-#include "ui/display/types/native_display_delegate.h"
-#include "ui/ozone/platform/wayland/wayland_output.h"
-
-namespace ui {
-
-class WaylandConnection;
-
-class WaylandNativeDisplayDelegate : public display::NativeDisplayDelegate,
- public WaylandOutput::Observer {
- public:
- explicit WaylandNativeDisplayDelegate(WaylandConnection* connection);
- ~WaylandNativeDisplayDelegate() override;
-
- // display::NativeDisplayDelegate overrides:
- void Initialize() override;
- void TakeDisplayControl(display::DisplayControlCallback callback) override;
- void RelinquishDisplayControl(
- display::DisplayControlCallback callback) override;
- void GetDisplays(display::GetDisplaysCallback callback) override;
- void Configure(const display::DisplaySnapshot& output,
- const display::DisplayMode* mode,
- const gfx::Point& origin,
- display::ConfigureCallback callback) override;
- void GetHDCPState(const display::DisplaySnapshot& output,
- display::GetHDCPStateCallback callback) override;
- void SetHDCPState(const display::DisplaySnapshot& output,
- display::HDCPState state,
- display::SetHDCPStateCallback callback) override;
- bool SetColorMatrix(int64_t display_id,
- const std::vector<float>& color_matrix) override;
- bool SetGammaCorrection(
- int64_t display_id,
- const std::vector<display::GammaRampRGBEntry>& degamma_lut,
- const std::vector<display::GammaRampRGBEntry>& gamma_lut) override;
- void AddObserver(display::NativeDisplayObserver* observer) override;
- void RemoveObserver(display::NativeDisplayObserver* observer) override;
- display::FakeDisplayController* GetFakeDisplayController() override;
-
- // WaylandOutput::Observer overrides:
- void OnOutputReadyForUse() override;
-
- private:
- WaylandConnection* connection_; // Not owned.
-
- base::ObserverList<display::NativeDisplayObserver>::Unchecked observers_;
-
- bool displays_ready_ = false;
-
- DISALLOW_COPY_AND_ASSIGN(WaylandNativeDisplayDelegate);
-};
-
-} // namespace ui
-
-#endif // UI_OZONE_PLATFORM_WAYLAND_WAYLAND_NATIVE_DISPLAY_DELEGATE_H_
diff --git a/chromium/ui/ozone/platform/wayland/wayland_object.cc b/chromium/ui/ozone/platform/wayland/wayland_object.cc
index ec41d326824..ed4de394dd0 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_object.cc
+++ b/chromium/ui/ozone/platform/wayland/wayland_object.cc
@@ -5,6 +5,8 @@
#include "ui/ozone/platform/wayland/wayland_object.h"
#include <linux-dmabuf-unstable-v1-client-protocol.h>
+#include <presentation-time-client-protocol.h>
+#include <text-input-unstable-v1-client-protocol.h>
#include <wayland-client.h>
#include <xdg-shell-unstable-v5-client-protocol.h>
#include <xdg-shell-unstable-v6-client-protocol.h>
@@ -40,6 +42,15 @@ void delete_touch(wl_touch* touch) {
wl_touch_destroy(touch);
}
+void delete_data_device(wl_data_device* data_device) {
+ if (wl_data_device_get_version(data_device) >=
+ WL_DATA_DEVICE_RELEASE_SINCE_VERSION) {
+ wl_data_device_release(data_device);
+ } else {
+ wl_data_device_destroy(data_device);
+ }
+}
+
} // namespace
const wl_interface* ObjectTraits<wl_buffer>::interface = &wl_buffer_interface;
@@ -62,7 +73,7 @@ void (*ObjectTraits<wl_data_device_manager>::deleter)(wl_data_device_manager*) =
const wl_interface* ObjectTraits<wl_data_device>::interface =
&wl_data_device_interface;
void (*ObjectTraits<wl_data_device>::deleter)(wl_data_device*) =
- &wl_data_device_destroy;
+ &delete_data_device;
const wl_interface* ObjectTraits<wl_data_offer>::interface =
&wl_data_offer_interface;
@@ -117,6 +128,16 @@ void (*ObjectTraits<wl_subsurface>::deleter)(wl_subsurface*) =
const wl_interface* ObjectTraits<wl_touch>::interface = &wl_touch_interface;
void (*ObjectTraits<wl_touch>::deleter)(wl_touch*) = &delete_touch;
+const wl_interface* ObjectTraits<wp_presentation>::interface =
+ &wp_presentation_interface;
+void (*ObjectTraits<wp_presentation>::deleter)(wp_presentation*) =
+ &wp_presentation_destroy;
+
+const wl_interface* ObjectTraits<struct wp_presentation_feedback>::interface =
+ &wp_presentation_feedback_interface;
+void (*ObjectTraits<struct wp_presentation_feedback>::deleter)(
+ struct wp_presentation_feedback*) = &wp_presentation_feedback_destroy;
+
const wl_interface* ObjectTraits<xdg_shell>::interface = &xdg_shell_interface;
void (*ObjectTraits<xdg_shell>::deleter)(xdg_shell*) = &xdg_shell_destroy;
@@ -157,4 +178,14 @@ const wl_interface* ObjectTraits<zxdg_positioner_v6>::interface =
void (*ObjectTraits<zxdg_positioner_v6>::deleter)(zxdg_positioner_v6*) =
&zxdg_positioner_v6_destroy;
+const wl_interface* ObjectTraits<zwp_text_input_manager_v1>::interface =
+ &zwp_text_input_manager_v1_interface;
+void (*ObjectTraits<zwp_text_input_manager_v1>::deleter)(
+ zwp_text_input_manager_v1*) = &zwp_text_input_manager_v1_destroy;
+
+const wl_interface* ObjectTraits<zwp_text_input_v1>::interface =
+ &zwp_text_input_v1_interface;
+void (*ObjectTraits<zwp_text_input_v1>::deleter)(zwp_text_input_v1*) =
+ &zwp_text_input_v1_destroy;
+
} // namespace wl
diff --git a/chromium/ui/ozone/platform/wayland/wayland_object.h b/chromium/ui/ozone/platform/wayland/wayland_object.h
index df3f16e62f3..34984d3296a 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_object.h
+++ b/chromium/ui/ozone/platform/wayland/wayland_object.h
@@ -27,6 +27,8 @@ struct wl_subcompositor;
struct wl_subsurface;
struct wl_surface;
struct wl_touch;
+struct wp_presentation;
+struct wp_presentation_feedback;
struct xdg_shell;
struct xdg_surface;
struct xdg_popup;
@@ -36,6 +38,8 @@ struct zxdg_surface_v6;
struct zxdg_toplevel_v6;
struct zxdg_popup_v6;
struct zxdg_positioner_v6;
+struct zwp_text_input_manager_v1;
+struct zwp_text_input_v1;
namespace wl {
@@ -157,6 +161,18 @@ struct ObjectTraits<wl_touch> {
};
template <>
+struct ObjectTraits<wp_presentation> {
+ static const wl_interface* interface;
+ static void (*deleter)(wp_presentation*);
+};
+
+template <>
+struct ObjectTraits<wp_presentation_feedback> {
+ static const wl_interface* interface;
+ static void (*deleter)(wp_presentation_feedback*);
+};
+
+template <>
struct ObjectTraits<xdg_shell> {
static const wl_interface* interface;
static void (*deleter)(xdg_shell*);
@@ -210,6 +226,18 @@ struct ObjectTraits<zxdg_positioner_v6> {
static void (*deleter)(zxdg_positioner_v6*);
};
+template <>
+struct ObjectTraits<zwp_text_input_manager_v1> {
+ static const wl_interface* interface;
+ static void (*deleter)(zwp_text_input_manager_v1*);
+};
+
+template <>
+struct ObjectTraits<zwp_text_input_v1> {
+ static const wl_interface* interface;
+ static void (*deleter)(zwp_text_input_v1*);
+};
+
struct Deleter {
template <typename T>
void operator()(T* obj) {
diff --git a/chromium/ui/ozone/platform/wayland/wayland_output.cc b/chromium/ui/ozone/platform/wayland/wayland_output.cc
index d9f8c44fd6c..fd14f45d633 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_output.cc
+++ b/chromium/ui/ozone/platform/wayland/wayland_output.cc
@@ -11,26 +11,32 @@
namespace ui {
-WaylandOutput::WaylandOutput(const int64_t display_id, wl_output* output)
- : display_id_(display_id), output_(output), observer_(nullptr) {
- static const wl_output_listener output_listener = {
- &WaylandOutput::OutputHandleGeometry, &WaylandOutput::OutputHandleMode,
- };
- wl_output_add_listener(output, &output_listener, this);
+namespace {
+constexpr float kDefaultScaleFactor = 1.0f;
}
-WaylandOutput::~WaylandOutput() {}
+WaylandOutput::WaylandOutput(const uint32_t output_id, wl_output* output)
+ : output_id_(output_id),
+ output_(output),
+ device_scale_factor_(kDefaultScaleFactor),
+ rect_in_physical_pixels_(gfx::Rect()) {}
+
+WaylandOutput::~WaylandOutput() = default;
-void WaylandOutput::SetObserver(Observer* observer) {
- observer_ = observer;
- if (current_mode_)
- observer_->OnOutputReadyForUse();
+void WaylandOutput::Initialize(Delegate* delegate) {
+ DCHECK(!delegate_);
+ delegate_ = delegate;
+ static const wl_output_listener output_listener = {
+ &WaylandOutput::OutputHandleGeometry, &WaylandOutput::OutputHandleMode,
+ &WaylandOutput::OutputHandleDone, &WaylandOutput::OutputHandleScale,
+ };
+ wl_output_add_listener(output_.get(), &output_listener, this);
}
-void WaylandOutput::GetDisplaysSnapshot(display::GetDisplaysCallback callback) {
- std::vector<display::DisplaySnapshot*> snapshot;
- snapshot.push_back(current_snapshot_.get());
- std::move(callback).Run(snapshot);
+void WaylandOutput::TriggerDelegateNotification() const {
+ DCHECK(!rect_in_physical_pixels_.IsEmpty());
+ delegate_->OnOutputHandleMetrics(output_id_, rect_in_physical_pixels_,
+ device_scale_factor_);
}
// static
@@ -45,13 +51,8 @@ void WaylandOutput::OutputHandleGeometry(void* data,
const char* model,
int32_t output_transform) {
WaylandOutput* wayland_output = static_cast<WaylandOutput*>(data);
- wayland_output->current_snapshot_.reset(new display::DisplaySnapshot(
- wayland_output->display_id_, gfx::Point(x, y),
- gfx::Size(physical_width, physical_height),
- display::DisplayConnectionType::DISPLAY_CONNECTION_TYPE_NONE, false,
- false, false, false, gfx::ColorSpace(), model, base::FilePath(),
- display::DisplaySnapshot::DisplayModeList(), std::vector<uint8_t>(),
- nullptr, nullptr, 0, 0, gfx::Size()));
+ if (wayland_output)
+ wayland_output->rect_in_physical_pixels_.set_origin(gfx::Point(x, y));
}
// static
@@ -61,17 +62,27 @@ void WaylandOutput::OutputHandleMode(void* data,
int32_t width,
int32_t height,
int32_t refresh) {
- WaylandOutput* output = static_cast<WaylandOutput*>(data);
+ WaylandOutput* wayland_output = static_cast<WaylandOutput*>(data);
+ if (wayland_output && (flags & WL_OUTPUT_MODE_CURRENT)) {
+ wayland_output->rect_in_physical_pixels_.set_width(width);
+ wayland_output->rect_in_physical_pixels_.set_height(height);
+ wayland_output->TriggerDelegateNotification();
+ }
+}
- if (flags & WL_OUTPUT_MODE_CURRENT) {
- std::unique_ptr<display::DisplayMode> previous_mode =
- std::move(output->current_mode_);
- output->current_mode_.reset(
- new display::DisplayMode(gfx::Size(width, height), false, refresh));
- output->current_snapshot_->set_current_mode(output->current_mode_.get());
+// static
+void WaylandOutput::OutputHandleDone(void* data, struct wl_output* wl_output) {
+ NOTIMPLEMENTED_LOG_ONCE();
+}
- if (output->observer())
- output->observer()->OnOutputReadyForUse();
+// static
+void WaylandOutput::OutputHandleScale(void* data,
+ struct wl_output* wl_output,
+ int32_t factor) {
+ WaylandOutput* wayland_output = static_cast<WaylandOutput*>(data);
+ if (wayland_output) {
+ wayland_output->device_scale_factor_ = factor;
+ wayland_output->TriggerDelegateNotification();
}
}
diff --git a/chromium/ui/ozone/platform/wayland/wayland_output.h b/chromium/ui/ozone/platform/wayland/wayland_output.h
index 94088ca16ab..ddf7946b194 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_output.h
+++ b/chromium/ui/ozone/platform/wayland/wayland_output.h
@@ -18,21 +18,27 @@ namespace ui {
// that are available to the application.
class WaylandOutput {
public:
- class Observer {
+ class Delegate {
public:
- // Will be called when wl_output is available.
- virtual void OnOutputReadyForUse() = 0;
+ virtual ~Delegate() {}
+
+ virtual void OnOutputHandleMetrics(uint32_t output_id,
+ const gfx::Rect& new_bounds,
+ int32_t scale_factor) = 0;
};
- WaylandOutput(const int64_t display_id, wl_output* output);
+ WaylandOutput(const uint32_t output_id, wl_output* output);
~WaylandOutput();
- void SetObserver(Observer* observer);
- Observer* observer() { return observer_; }
+ void Initialize(Delegate* delegate);
+
+ void TriggerDelegateNotification() const;
- bool is_ready() const { return !!current_mode_; }
+ uint32_t output_id() const { return output_id_; }
- void GetDisplaysSnapshot(display::GetDisplaysCallback callback);
+ // Tells if the output has already received physical screen dimensions in the
+ // global compositor space.
+ bool is_ready() const { return !rect_in_physical_pixels_.IsEmpty(); }
private:
// Callback functions used for setting geometric properties of the output
@@ -54,14 +60,17 @@ class WaylandOutput {
int32_t width,
int32_t height,
int32_t refresh);
+ static void OutputHandleDone(void* data, struct wl_output* wl_output);
+ static void OutputHandleScale(void* data,
+ struct wl_output* wl_output,
+ int32_t factor);
- const int64_t display_id_ = 0;
+ const uint32_t output_id_ = 0;
wl::Object<wl_output> output_;
+ float device_scale_factor_;
+ gfx::Rect rect_in_physical_pixels_;
- Observer* observer_;
-
- std::unique_ptr<display::DisplaySnapshot> current_snapshot_;
- std::unique_ptr<display::DisplayMode> current_mode_;
+ Delegate* delegate_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(WaylandOutput);
};
diff --git a/chromium/ui/ozone/platform/wayland/wayland_output_manager.cc b/chromium/ui/ozone/platform/wayland/wayland_output_manager.cc
new file mode 100644
index 00000000000..c9db25c35b4
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_output_manager.cc
@@ -0,0 +1,117 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/wayland/wayland_output_manager.h"
+
+#include "ui/ozone/platform/wayland/wayland_connection.h"
+#include "ui/ozone/platform/wayland/wayland_output.h"
+
+namespace ui {
+
+WaylandOutputManager::WaylandOutputManager() = default;
+
+WaylandOutputManager::~WaylandOutputManager() = default;
+
+bool WaylandOutputManager::IsPrimaryOutputReady() const {
+ if (output_list_.empty())
+ return false;
+
+ // The very first output in the list is always treated as a primary output.
+ const auto& primary_output = output_list_.front();
+ return primary_output->is_ready();
+}
+
+void WaylandOutputManager::AddWaylandOutput(const uint32_t output_id,
+ wl_output* output) {
+ // Make sure an output with |output_id| has not been added yet. It's very
+ // unlikely to happen, unless a compositor has a bug in the numeric names
+ // representation of global objects.
+ auto output_it = std::find_if(output_list_.begin(), output_list_.end(),
+ [output_id](const auto& output) {
+ return output->output_id() == output_id;
+ });
+ DCHECK(output_it == output_list_.end());
+ auto wayland_output = std::make_unique<WaylandOutput>(output_id, output);
+ WaylandOutput* wayland_output_ptr = wayland_output.get();
+ output_list_.push_back(std::move(wayland_output));
+
+ OnWaylandOutputAdded(output_id);
+
+ // If WaylandScreen has already been created, the output can be initialized,
+ // which results in setting up a wl_listener and getting the geometry and the
+ // scaling factor from the Wayland Compositor.
+ wayland_output_ptr->Initialize(this);
+}
+
+void WaylandOutputManager::RemoveWaylandOutput(const uint32_t output_id) {
+ auto output_it = std::find_if(output_list_.begin(), output_list_.end(),
+ [output_id](const auto& output) {
+ return output->output_id() == output_id;
+ });
+
+ // Check the comment in the WaylandConnetion::GlobalRemove.
+ if (output_it == output_list_.end())
+ return;
+
+ bool was_primary_output = IsPrimaryOutput(output_id);
+ output_list_.erase(output_it);
+
+ // If it was a primary output removed, make sure the second output, which
+ // became a primary one, announces that to observers.
+ if (was_primary_output && !output_list_.empty())
+ output_list_.front()->TriggerDelegateNotification();
+
+ OnWaylandOutputRemoved(output_id);
+}
+
+std::unique_ptr<WaylandScreen> WaylandOutputManager::CreateWaylandScreen() {
+ auto wayland_screen = std::make_unique<WaylandScreen>();
+ wayland_screen_ = wayland_screen->GetWeakPtr();
+
+ // As long as |wl_output| sends geometry and other events asynchronously (that
+ // is, the initial configuration is sent once the interface is bound), we'll
+ // have to tell each output to manually inform the delegate about available
+ // geometry, scale factor and etc, which will result in feeding the
+ // WaylandScreen with the data through OnOutputHandleGeometry and
+ // OutOutputHandleScale. All the other hot geometry and scale changes are done
+ // automatically, and the |wayland_screen_| is notified immediately about the
+ // changes.
+ if (!output_list_.empty()) {
+ for (auto& output : output_list_) {
+ OnWaylandOutputAdded(output->output_id());
+ output->TriggerDelegateNotification();
+ }
+ }
+
+ return wayland_screen;
+}
+
+void WaylandOutputManager::OnWaylandOutputAdded(uint32_t output_id) {
+ if (wayland_screen_)
+ wayland_screen_->OnOutputAdded(output_id, IsPrimaryOutput(output_id));
+}
+
+void WaylandOutputManager::OnWaylandOutputRemoved(uint32_t output_id) {
+ if (wayland_screen_)
+ wayland_screen_->OnOutputRemoved(output_id);
+}
+
+bool WaylandOutputManager::IsPrimaryOutput(uint32_t output_id) const {
+ DCHECK(!output_list_.empty());
+ // The very first object in the |output_list_| is always treated as a primary
+ // output.
+ const auto& primary_output = output_list_.front();
+ return primary_output->output_id() == output_id;
+}
+
+void WaylandOutputManager::OnOutputHandleMetrics(uint32_t output_id,
+ const gfx::Rect& new_bounds,
+ int32_t scale_factor) {
+ if (wayland_screen_) {
+ wayland_screen_->OnOutputMetricsChanged(output_id, new_bounds, scale_factor,
+ IsPrimaryOutput(output_id));
+ }
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/wayland_output_manager.h b/chromium/ui/ozone/platform/wayland/wayland_output_manager.h
new file mode 100644
index 00000000000..5fcdced8a04
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_output_manager.h
@@ -0,0 +1,59 @@
+// 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_OZONE_PLATFORM_WAYLAND_WAYLAND_OUTPUT_MANAGER_H_
+#define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_OUTPUT_MANAGER_H_
+
+#include "ui/ozone/platform/wayland/wayland_object.h"
+
+#include <memory>
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "ui/ozone/platform/wayland/wayland_output.h"
+#include "ui/ozone/platform/wayland/wayland_screen.h"
+
+struct wl_output;
+
+namespace ui {
+
+class WaylandOutput;
+
+class WaylandOutputManager : public WaylandOutput::Delegate {
+ public:
+ WaylandOutputManager();
+ ~WaylandOutputManager() override;
+
+ // The first output in the vector is always a primary output.
+ bool IsPrimaryOutputReady() const;
+
+ void AddWaylandOutput(const uint32_t output_id, wl_output* output);
+ void RemoveWaylandOutput(const uint32_t output_id);
+
+ // Creates a platform screen and feeds it with existing outputs.
+ std::unique_ptr<WaylandScreen> CreateWaylandScreen();
+
+ private:
+ void OnWaylandOutputAdded(uint32_t output_id);
+ void OnWaylandOutputRemoved(uint32_t output_id);
+
+ bool IsPrimaryOutput(uint32_t output_id) const;
+
+ // WaylandOutput::Delegate:
+ void OnOutputHandleMetrics(uint32_t output_id,
+ const gfx::Rect& new_bounds,
+ int32_t scale_factor) override;
+
+ std::vector<std::unique_ptr<WaylandOutput>> output_list_;
+
+ // Non-owned wayland screen instance.
+ base::WeakPtr<WaylandScreen> wayland_screen_;
+
+ DISALLOW_COPY_AND_ASSIGN(WaylandOutputManager);
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_WAYLAND_WAYLAND_OUTPUT_MANAGER_H_
diff --git a/chromium/ui/ozone/platform/wayland/wayland_pointer.cc b/chromium/ui/ozone/platform/wayland/wayland_pointer.cc
index 8079524d6d9..f977f636681 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_pointer.cc
+++ b/chromium/ui/ozone/platform/wayland/wayland_pointer.cc
@@ -94,8 +94,8 @@ void WaylandPointer::Motion(void* data,
pointer->location_.SetPoint(wl_fixed_to_double(surface_x),
wl_fixed_to_double(surface_y));
MouseEvent event(ET_MOUSE_MOVED, gfx::Point(), gfx::Point(),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(time),
- pointer->GetFlagsWithKeyboardModifiers(), 0);
+ EventTimeForNow(), pointer->GetFlagsWithKeyboardModifiers(),
+ 0);
event.set_location_f(pointer->location_);
event.set_root_location_f(pointer->location_);
pointer->callback_.Run(&event);
@@ -146,10 +146,8 @@ void WaylandPointer::Button(void* data,
// MouseEvent's flags should contain the button that was released too.
const int flags = pointer->GetFlagsWithKeyboardModifiers() | changed_button;
- MouseEvent event(type, gfx::Point(), gfx::Point(),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(time),
- flags, changed_button);
-
+ MouseEvent event(type, gfx::Point(), gfx::Point(), EventTimeForNow(), flags,
+ changed_button);
event.set_location_f(pointer->location_);
event.set_root_location_f(pointer->location_);
@@ -187,10 +185,8 @@ void WaylandPointer::Axis(void* data,
MouseWheelEvent::kWheelDelta);
else
return;
- MouseWheelEvent event(
- offset, gfx::Point(), gfx::Point(),
- base::TimeTicks() + base::TimeDelta::FromMilliseconds(time),
- pointer->GetFlagsWithKeyboardModifiers(), 0);
+ MouseWheelEvent event(offset, gfx::Point(), gfx::Point(), EventTimeForNow(),
+ pointer->GetFlagsWithKeyboardModifiers(), 0);
event.set_location_f(pointer->location_);
event.set_root_location_f(pointer->location_);
pointer->callback_.Run(&event);
@@ -216,4 +212,9 @@ int WaylandPointer::GetFlagsWithKeyboardModifiers() {
return flags_;
}
+void WaylandPointer::ResetFlags() {
+ flags_ = 0;
+ keyboard_modifiers_ = 0;
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/wayland_pointer.h b/chromium/ui/ozone/platform/wayland/wayland_pointer.h
index 50f60f4a903..0c398d19a83 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_pointer.h
+++ b/chromium/ui/ozone/platform/wayland/wayland_pointer.h
@@ -27,6 +27,7 @@ class WaylandPointer {
}
int GetFlagsWithKeyboardModifiers();
+ void ResetFlags();
WaylandCursor* cursor() { return cursor_.get(); }
diff --git a/chromium/ui/ozone/platform/wayland/wayland_screen.cc b/chromium/ui/ozone/platform/wayland/wayland_screen.cc
new file mode 100644
index 00000000000..98ef35e3f61
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_screen.cc
@@ -0,0 +1,107 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/wayland/wayland_screen.h"
+
+#include "ui/display/display.h"
+#include "ui/display/display_finder.h"
+#include "ui/display/display_observer.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace ui {
+
+WaylandScreen::WaylandScreen() : weak_factory_(this) {}
+
+WaylandScreen::~WaylandScreen() = default;
+
+void WaylandScreen::OnOutputAdded(uint32_t output_id, bool is_primary) {
+ display::Display new_display(output_id);
+ display_list_.AddDisplay(std::move(new_display),
+ is_primary
+ ? display::DisplayList::Type::PRIMARY
+ : display::DisplayList::Type::NOT_PRIMARY);
+}
+
+void WaylandScreen::OnOutputRemoved(uint32_t output_id) {
+ display_list_.RemoveDisplay(output_id);
+}
+
+void WaylandScreen::OnOutputMetricsChanged(uint32_t output_id,
+ const gfx::Rect& new_bounds,
+ float device_pixel_ratio,
+ bool is_primary) {
+ display::Display changed_display(output_id);
+ changed_display.set_device_scale_factor(device_pixel_ratio);
+ changed_display.set_bounds(new_bounds);
+ changed_display.set_work_area(new_bounds);
+
+ display_list_.UpdateDisplay(
+ changed_display, is_primary ? display::DisplayList::Type::PRIMARY
+ : display::DisplayList::Type::NOT_PRIMARY);
+}
+
+base::WeakPtr<WaylandScreen> WaylandScreen::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
+const std::vector<display::Display>& WaylandScreen::GetAllDisplays() const {
+ return display_list_.displays();
+}
+
+display::Display WaylandScreen::GetPrimaryDisplay() const {
+ auto iter = display_list_.GetPrimaryDisplayIterator();
+ if (iter == display_list_.displays().end())
+ return display::Display::GetDefaultDisplay();
+ return *iter;
+}
+
+display::Display WaylandScreen::GetDisplayForAcceleratedWidget(
+ gfx::AcceleratedWidget widget) const {
+ // TODO(msisov): implement wl_surface_listener::enter and
+ // wl_surface_listener::leave for a wl_surface to know what surface the window
+ // is located on.
+ //
+ // https://crbug.com/890271
+ NOTIMPLEMENTED_LOG_ONCE();
+ return GetPrimaryDisplay();
+}
+
+gfx::Point WaylandScreen::GetCursorScreenPoint() const {
+ NOTIMPLEMENTED_LOG_ONCE();
+ return gfx::Point();
+}
+
+gfx::AcceleratedWidget WaylandScreen::GetAcceleratedWidgetAtScreenPoint(
+ const gfx::Point& point) const {
+ // TODO(msisov): implement this once wl_surface_listener::enter and ::leave
+ // are used.
+ //
+ // https://crbug.com/890271
+ NOTIMPLEMENTED_LOG_ONCE();
+ return gfx::kNullAcceleratedWidget;
+}
+
+display::Display WaylandScreen::GetDisplayNearestPoint(
+ const gfx::Point& point) const {
+ NOTIMPLEMENTED_LOG_ONCE();
+ return GetPrimaryDisplay();
+}
+
+display::Display WaylandScreen::GetDisplayMatching(
+ const gfx::Rect& match_rect) const {
+ // TODO(msisov): https://crbug.com/890272
+ NOTIMPLEMENTED_LOG_ONCE();
+ return GetPrimaryDisplay();
+}
+
+void WaylandScreen::AddObserver(display::DisplayObserver* observer) {
+ display_list_.AddObserver(observer);
+}
+
+void WaylandScreen::RemoveObserver(display::DisplayObserver* observer) {
+ display_list_.RemoveObserver(observer);
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/wayland_screen.h b/chromium/ui/ozone/platform/wayland/wayland_screen.h
new file mode 100644
index 00000000000..f2de8d4dbb9
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_screen.h
@@ -0,0 +1,62 @@
+// 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_OZONE_PLATFORM_WAYLAND_WAYLAND_SCREEN_H_
+#define UI_OZONE_PLATFORM_WAYLAND_WAYLAND_SCREEN_H_
+
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
+#include "base/observer_list.h"
+#include "ui/display/display_list.h"
+#include "ui/ozone/platform/wayland/wayland_output.h"
+#include "ui/ozone/public/ozone_platform.h"
+#include "ui/ozone/public/platform_screen.h"
+
+namespace ui {
+
+// A PlatformScreen implementation for Wayland.
+class WaylandScreen : public PlatformScreen {
+ public:
+ WaylandScreen();
+ ~WaylandScreen() override;
+
+ void OnOutputAdded(uint32_t output_id, bool is_primary);
+ void OnOutputRemoved(uint32_t output_id);
+ void OnOutputMetricsChanged(uint32_t output_id,
+ const gfx::Rect& bounds,
+ float device_pixel_ratio,
+ bool is_primary);
+
+ base::WeakPtr<WaylandScreen> GetWeakPtr();
+
+ // display::Screen implementation.
+ const std::vector<display::Display>& GetAllDisplays() const override;
+ display::Display GetPrimaryDisplay() const override;
+ display::Display GetDisplayForAcceleratedWidget(
+ gfx::AcceleratedWidget widget) const override;
+ gfx::Point GetCursorScreenPoint() const override;
+ gfx::AcceleratedWidget GetAcceleratedWidgetAtScreenPoint(
+ const gfx::Point& point) const override;
+ display::Display GetDisplayNearestPoint(
+ const gfx::Point& point) const override;
+ display::Display GetDisplayMatching(
+ const gfx::Rect& match_rect) const override;
+ void AddObserver(display::DisplayObserver* observer) override;
+ void RemoveObserver(display::DisplayObserver* observer) override;
+
+ private:
+ display::DisplayList display_list_;
+
+ base::ObserverList<display::DisplayObserver> observers_;
+
+ base::WeakPtrFactory<WaylandScreen> weak_factory_;
+
+ DISALLOW_COPY_AND_ASSIGN(WaylandScreen);
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_WAYLAND_WAYLAND_SCREEN_H_
diff --git a/chromium/ui/ozone/platform/wayland/wayland_screen_unittest.cc b/chromium/ui/ozone/platform/wayland/wayland_screen_unittest.cc
new file mode 100644
index 00000000000..7eb9350f298
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/wayland_screen_unittest.cc
@@ -0,0 +1,187 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include <wayland-server.h>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/display/display_observer.h"
+#include "ui/ozone/platform/wayland/fake_server.h"
+#include "ui/ozone/platform/wayland/wayland_connection.h"
+#include "ui/ozone/platform/wayland/wayland_output_manager.h"
+#include "ui/ozone/platform/wayland/wayland_screen.h"
+#include "ui/ozone/platform/wayland/wayland_test.h"
+
+namespace ui {
+
+namespace {
+
+constexpr uint32_t kNumberOfDisplays = 1;
+constexpr uint32_t kOutputWidth = 1024;
+constexpr uint32_t kOutputHeight = 768;
+
+class TestDisplayObserver : public display::DisplayObserver {
+ public:
+ TestDisplayObserver() {}
+ ~TestDisplayObserver() override {}
+
+ display::Display GetDisplay() { return std::move(display_); }
+ uint32_t GetAndClearChangedMetrics() {
+ uint32_t changed_metrics = changed_metrics_;
+ changed_metrics_ = 0;
+ return changed_metrics;
+ }
+
+ // display::DisplayObserver:
+ void OnDisplayAdded(const display::Display& new_display) override {
+ display_ = new_display;
+ }
+
+ void OnDisplayRemoved(const display::Display& old_display) override {
+ display_ = old_display;
+ }
+
+ void OnDisplayMetricsChanged(const display::Display& display,
+ uint32_t changed_metrics) override {
+ changed_metrics_ = changed_metrics;
+ display_ = display;
+ }
+
+ private:
+ uint32_t changed_metrics_ = 0;
+ display::Display display_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestDisplayObserver);
+};
+
+} // namespace
+
+class WaylandScreenTest : public WaylandTest {
+ public:
+ WaylandScreenTest() {}
+ ~WaylandScreenTest() override {}
+
+ void SetUp() override {
+ output_ = server_.output();
+ output_->SetRect(gfx::Rect(0, 0, kOutputWidth, kOutputHeight));
+
+ WaylandTest::SetUp();
+
+ output_manager_ = connection_->wayland_output_manager();
+ ASSERT_TRUE(output_manager_);
+ }
+
+ protected:
+ wl::MockOutput* output_ = nullptr;
+ WaylandOutputManager* output_manager_ = nullptr;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(WaylandScreenTest);
+};
+
+// Tests whether a primary output has been initialized before PlatformScreen is
+// created.
+TEST_P(WaylandScreenTest, OutputBaseTest) {
+ EXPECT_TRUE(output_manager_->IsPrimaryOutputReady());
+
+ std::unique_ptr<WaylandScreen> platform_screen =
+ output_manager_->CreateWaylandScreen();
+
+ // Ensure there is only one display, which is the primary one.
+ auto& all_displays = platform_screen->GetAllDisplays();
+ EXPECT_EQ(all_displays.size(), kNumberOfDisplays);
+
+ // Ensure the size property of the primary display.
+ EXPECT_EQ(platform_screen->GetPrimaryDisplay().bounds(),
+ gfx::Rect(0, 0, kOutputWidth, kOutputHeight));
+}
+
+TEST_P(WaylandScreenTest, MultipleOutputsAddedAndRemoved) {
+ EXPECT_TRUE(output_manager_->IsPrimaryOutputReady());
+ std::unique_ptr<WaylandScreen> platform_screen =
+ output_manager_->CreateWaylandScreen();
+
+ TestDisplayObserver observer;
+ platform_screen->AddObserver(&observer);
+
+ // Add a second display.
+ server_.CreateAndInitializeOutput();
+
+ Sync();
+
+ // Ensure that second display is not a primary one and have a different id.
+ int64_t added_display_id = observer.GetDisplay().id();
+ EXPECT_NE(platform_screen->GetPrimaryDisplay().id(), added_display_id);
+
+ // Remove the second output.
+ output_manager_->RemoveWaylandOutput(added_display_id);
+
+ Sync();
+
+ // Ensure that removed display has correct id.
+ int64_t removed_display_id = observer.GetDisplay().id();
+ EXPECT_EQ(added_display_id, removed_display_id);
+
+ // Create another display again.
+ server_.CreateAndInitializeOutput();
+
+ Sync();
+
+ // The newly added display is not a primary yet.
+ added_display_id = observer.GetDisplay().id();
+ EXPECT_NE(platform_screen->GetPrimaryDisplay().id(), added_display_id);
+
+ // Make sure the geometry changes are sent by syncing one more time again.
+ Sync();
+
+ int64_t old_primary_display_id = platform_screen->GetPrimaryDisplay().id();
+ output_manager_->RemoveWaylandOutput(old_primary_display_id);
+
+ // Ensure that previously added display is now a primary one.
+ EXPECT_EQ(platform_screen->GetPrimaryDisplay().id(), added_display_id);
+ // Ensure that the removed display was the one, which was a primary display.
+ EXPECT_EQ(observer.GetDisplay().id(), old_primary_display_id);
+}
+
+TEST_P(WaylandScreenTest, OutputPropertyChanges) {
+ std::unique_ptr<WaylandScreen> platform_screen =
+ output_manager_->CreateWaylandScreen();
+ TestDisplayObserver observer;
+ platform_screen->AddObserver(&observer);
+
+ const gfx::Rect new_rect(0, 0, 800, 600);
+ wl_output_send_geometry(output_->resource(), new_rect.x(), new_rect.y(),
+ 0 /* physical_width */, 0 /* physical_height */,
+ 0 /* subpixel */, "unkown_make", "unknown_model",
+ 0 /* transform */);
+ wl_output_send_mode(output_->resource(), WL_OUTPUT_MODE_CURRENT,
+ new_rect.width(), new_rect.height(), 0 /* refresh */);
+
+ Sync();
+
+ uint32_t changed_values = 0;
+ changed_values |= display::DisplayObserver::DISPLAY_METRIC_BOUNDS;
+ changed_values |= display::DisplayObserver::DISPLAY_METRIC_WORK_AREA;
+ EXPECT_EQ(observer.GetAndClearChangedMetrics(), changed_values);
+ EXPECT_EQ(observer.GetDisplay().bounds(), new_rect);
+
+ const float new_scale_value = 2.0f;
+ wl_output_send_scale(output_->resource(), new_scale_value);
+
+ Sync();
+
+ changed_values = 0;
+ changed_values |=
+ display::DisplayObserver::DISPLAY_METRIC_DEVICE_SCALE_FACTOR;
+ EXPECT_EQ(observer.GetAndClearChangedMetrics(), changed_values);
+ EXPECT_EQ(observer.GetDisplay().device_scale_factor(), new_scale_value);
+}
+
+INSTANTIATE_TEST_CASE_P(XdgVersionV5Test,
+ WaylandScreenTest,
+ ::testing::Values(kXdgShellV5));
+INSTANTIATE_TEST_CASE_P(XdgVersionV6Test,
+ WaylandScreenTest,
+ ::testing::Values(kXdgShellV6));
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/wayland_surface_factory.cc b/chromium/ui/ozone/platform/wayland/wayland_surface_factory.cc
index 751d7c2913d..a5b1dec0d3b 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_surface_factory.cc
+++ b/chromium/ui/ozone/platform/wayland/wayland_surface_factory.cc
@@ -231,9 +231,13 @@ GbmSurfacelessWayland* WaylandSurfaceFactory::GetSurface(
return it->second;
}
-void WaylandSurfaceFactory::ScheduleBufferSwap(gfx::AcceleratedWidget widget,
- uint32_t buffer_id) {
- connection_->ScheduleBufferSwap(widget, buffer_id);
+void WaylandSurfaceFactory::ScheduleBufferSwap(
+ gfx::AcceleratedWidget widget,
+ uint32_t buffer_id,
+ const gfx::Rect& damage_region,
+ wl::BufferSwapCallback callback) {
+ connection_->ScheduleBufferSwap(widget, buffer_id, damage_region,
+ std::move(callback));
}
std::unique_ptr<SurfaceOzoneCanvas>
diff --git a/chromium/ui/ozone/platform/wayland/wayland_surface_factory.h b/chromium/ui/ozone/platform/wayland/wayland_surface_factory.h
index 3b569890eac..d20c3f903b8 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_surface_factory.h
+++ b/chromium/ui/ozone/platform/wayland/wayland_surface_factory.h
@@ -7,17 +7,21 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "ui/gl/gl_surface.h"
-#include "ui/ozone/public/surface_factory_ozone.h"
-
#include "base/posix/eintr_wrapper.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/sequenced_task_runner_handle.h"
+#include "ui/gl/gl_surface.h"
+#include "ui/ozone/platform/wayland/wayland_util.h"
+#include "ui/ozone/public/surface_factory_ozone.h"
+
+namespace gfx {
+class Rect;
+} // namespace gfx
namespace ui {
-class WaylandConnectionProxy;
class GbmSurfacelessWayland;
+class WaylandConnectionProxy;
class WaylandSurfaceFactory : public SurfaceFactoryOzone {
public:
@@ -25,7 +29,10 @@ class WaylandSurfaceFactory : public SurfaceFactoryOzone {
~WaylandSurfaceFactory() override;
// These methods are used, when a dmabuf based approach is used.
- void ScheduleBufferSwap(gfx::AcceleratedWidget widget, uint32_t buffer_id);
+ void ScheduleBufferSwap(gfx::AcceleratedWidget widget,
+ uint32_t buffer_id,
+ const gfx::Rect& damage_region_,
+ wl::BufferSwapCallback callback);
void RegisterSurface(gfx::AcceleratedWidget widget,
GbmSurfacelessWayland* surface);
void UnregisterSurface(gfx::AcceleratedWidget widget);
diff --git a/chromium/ui/ozone/platform/wayland/wayland_util.cc b/chromium/ui/ozone/platform/wayland/wayland_util.cc
index 1ad2b556fb5..0cd05346df8 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_util.cc
+++ b/chromium/ui/ozone/platform/wayland/wayland_util.cc
@@ -4,10 +4,15 @@
#include "ui/ozone/platform/wayland/wayland_util.h"
+#include <xdg-shell-unstable-v5-client-protocol.h>
+#include <xdg-shell-unstable-v6-client-protocol.h>
+
#include "base/memory/shared_memory.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkSurface.h"
+#include "ui/base/hit_test.h"
#include "ui/gfx/skia_util.h"
+#include "ui/ozone/platform/wayland/wayland_connection.h"
namespace wl {
@@ -16,6 +21,84 @@ namespace {
const uint32_t kShmFormat = WL_SHM_FORMAT_ARGB8888;
const SkColorType kColorType = kBGRA_8888_SkColorType;
+uint32_t IdentifyDirectionV5(int hittest) {
+ uint32_t direction = 0;
+ switch (hittest) {
+ case HTBOTTOM:
+ direction = xdg_surface_resize_edge::XDG_SURFACE_RESIZE_EDGE_BOTTOM;
+ break;
+ case HTBOTTOMLEFT:
+ direction = xdg_surface_resize_edge::XDG_SURFACE_RESIZE_EDGE_BOTTOM_LEFT;
+ break;
+ case HTBOTTOMRIGHT:
+ direction = xdg_surface_resize_edge::XDG_SURFACE_RESIZE_EDGE_BOTTOM_RIGHT;
+ break;
+ case HTLEFT:
+ direction = xdg_surface_resize_edge::XDG_SURFACE_RESIZE_EDGE_LEFT;
+ break;
+ case HTRIGHT:
+ direction = xdg_surface_resize_edge::XDG_SURFACE_RESIZE_EDGE_RIGHT;
+ break;
+ case HTTOP:
+ direction = xdg_surface_resize_edge::XDG_SURFACE_RESIZE_EDGE_TOP;
+ break;
+ case HTTOPLEFT:
+ direction = xdg_surface_resize_edge::XDG_SURFACE_RESIZE_EDGE_TOP_LEFT;
+ break;
+ case HTTOPRIGHT:
+ direction = xdg_surface_resize_edge::XDG_SURFACE_RESIZE_EDGE_TOP_RIGHT;
+ break;
+ default:
+ direction = xdg_surface_resize_edge::XDG_SURFACE_RESIZE_EDGE_NONE;
+ break;
+ ;
+ }
+ return direction;
+}
+
+uint32_t IdentifyDirectionV6(int hittest) {
+ uint32_t direction = 0;
+ switch (hittest) {
+ case HTBOTTOM:
+ direction =
+ zxdg_toplevel_v6_resize_edge::ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM;
+ break;
+ case HTBOTTOMLEFT:
+ direction = zxdg_toplevel_v6_resize_edge::
+ ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM_LEFT;
+ break;
+ case HTBOTTOMRIGHT:
+ direction = zxdg_toplevel_v6_resize_edge::
+ ZXDG_TOPLEVEL_V6_RESIZE_EDGE_BOTTOM_RIGHT;
+ break;
+ case HTLEFT:
+ direction =
+ zxdg_toplevel_v6_resize_edge::ZXDG_TOPLEVEL_V6_RESIZE_EDGE_LEFT;
+ break;
+ case HTRIGHT:
+ direction =
+ zxdg_toplevel_v6_resize_edge::ZXDG_TOPLEVEL_V6_RESIZE_EDGE_RIGHT;
+ break;
+ case HTTOP:
+ direction =
+ zxdg_toplevel_v6_resize_edge::ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP;
+ break;
+ case HTTOPLEFT:
+ direction =
+ zxdg_toplevel_v6_resize_edge::ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP_LEFT;
+ break;
+ case HTTOPRIGHT:
+ direction =
+ zxdg_toplevel_v6_resize_edge::ZXDG_TOPLEVEL_V6_RESIZE_EDGE_TOP_RIGHT;
+ break;
+ default:
+ direction =
+ zxdg_toplevel_v6_resize_edge::ZXDG_TOPLEVEL_V6_RESIZE_EDGE_NONE;
+ break;
+ }
+ return direction;
+}
+
} // namespace
wl_buffer* CreateSHMBuffer(const gfx::Size& size,
@@ -68,4 +151,12 @@ void DrawBitmapToSHMB(const gfx::Size& size,
canvas->drawBitmapRect(bitmap, damage, nullptr);
}
+uint32_t IdentifyDirection(const ui::WaylandConnection& connection,
+ int hittest) {
+ if (connection.shell_v6())
+ return IdentifyDirectionV6(hittest);
+ DCHECK(connection.shell());
+ return IdentifyDirectionV5(hittest);
+}
+
} // namespace wl
diff --git a/chromium/ui/ozone/platform/wayland/wayland_util.h b/chromium/ui/ozone/platform/wayland/wayland_util.h
index 0b77426698b..2a2db3aba1d 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_util.h
+++ b/chromium/ui/ozone/platform/wayland/wayland_util.h
@@ -7,6 +7,9 @@
#include <wayland-client.h>
+#include <stdint.h>
+
+#include "base/callback.h"
#include "base/macros.h"
#include "ui/ozone/platform/wayland/wayland_object.h"
@@ -16,12 +19,22 @@ namespace base {
class SharedMemory;
}
+namespace ui {
+class WaylandConnection;
+}
+
namespace gfx {
class Size;
+enum class SwapResult;
+struct PresentationFeedback;
}
namespace wl {
+// Corresponds to mojom::WaylandConnection::ScheduleBufferSwapCallback.
+using BufferSwapCallback =
+ base::OnceCallback<void(gfx::SwapResult, const gfx::PresentationFeedback&)>;
+
wl_buffer* CreateSHMBuffer(const gfx::Size& size,
base::SharedMemory* shared_memory,
wl_shm* shm);
@@ -29,6 +42,11 @@ void DrawBitmapToSHMB(const gfx::Size& size,
const base::SharedMemory& shared_memory,
const SkBitmap& bitmap);
+// Identifies the direction of the "hittest" for Wayland. |connection|
+// is used to identify whether values from shell v5 or v6 must be used.
+uint32_t IdentifyDirection(const ui::WaylandConnection& connection,
+ int hittest);
+
} // namespace wl
#endif // UI_OZONE_PLATFORM_WAYLAND_WAYLAND_UTIL_H_
diff --git a/chromium/ui/ozone/platform/wayland/wayland_window.cc b/chromium/ui/ozone/platform/wayland/wayland_window.cc
index c0d8847a028..27ddd18e8cd 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_window.cc
+++ b/chromium/ui/ozone/platform/wayland/wayland_window.cc
@@ -8,9 +8,12 @@
#include "base/bind.h"
#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
+#include "ui/base/dragdrop/os_exchange_data.h"
+#include "ui/base/hit_test.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/events/ozone/events_ozone.h"
+#include "ui/gfx/geometry/point_f.h"
#include "ui/ozone/platform/wayland/wayland_connection.h"
#include "ui/ozone/platform/wayland/wayland_pointer.h"
#include "ui/ozone/platform/wayland/xdg_popup_wrapper_v5.h"
@@ -71,7 +74,11 @@ WaylandWindow::WaylandWindow(PlatformWindowDelegate* delegate,
: delegate_(delegate),
connection_(connection),
xdg_shell_objects_factory_(new XDGShellObjectFactory()),
- state_(PlatformWindowState::PLATFORM_WINDOW_STATE_NORMAL) {}
+ state_(PlatformWindowState::PLATFORM_WINDOW_STATE_NORMAL) {
+ // Set a class property key, which allows |this| to be used for interactive
+ // events, e.g. move or resize.
+ SetWmMoveResizeHandler(this, AsWmMoveResizeHandler());
+}
WaylandWindow::~WaylandWindow() {
PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
@@ -194,7 +201,24 @@ void WaylandWindow::ApplyPendingBounds() {
connection_->ScheduleFlush();
}
+void WaylandWindow::DispatchHostWindowDragMovement(
+ int hittest,
+ const gfx::Point& pointer_location) {
+ DCHECK(xdg_surface_);
+
+ connection_->ResetPointerFlags();
+ if (hittest == HTCAPTION)
+ xdg_surface_->SurfaceMove(connection_);
+ else
+ xdg_surface_->SurfaceResize(connection_, hittest);
+
+ connection_->ScheduleFlush();
+}
+
void WaylandWindow::Show() {
+ if (!is_tooltip_) // Tooltip windows should not get keyboard focus
+ set_keyboard_focus(true);
+
if (xdg_surface_)
return;
if (is_tooltip_) {
@@ -510,6 +534,31 @@ void WaylandWindow::OnCloseRequest() {
delegate_->OnCloseRequest();
}
+void WaylandWindow::OnDragEnter(const gfx::PointF& point,
+ std::unique_ptr<OSExchangeData> data,
+ int operation) {
+ NOTIMPLEMENTED_LOG_ONCE();
+}
+
+int WaylandWindow::OnDragMotion(const gfx::PointF& point,
+ uint32_t time,
+ int operation) {
+ NOTIMPLEMENTED_LOG_ONCE();
+ return 0;
+}
+
+void WaylandWindow::OnDragDrop(std::unique_ptr<OSExchangeData> data) {
+ NOTIMPLEMENTED_LOG_ONCE();
+}
+
+void WaylandWindow::OnDragLeave() {
+ NOTIMPLEMENTED_LOG_ONCE();
+}
+
+void WaylandWindow::OnDragSessionClose(uint32_t dnd_action) {
+ NOTIMPLEMENTED_LOG_ONCE();
+}
+
bool WaylandWindow::IsMinimized() const {
return state_ == PlatformWindowState::PLATFORM_WINDOW_STATE_MINIMIZED;
}
@@ -542,4 +591,8 @@ WaylandWindow* WaylandWindow::GetParentWindow(
return parent_window;
}
+WmMoveResizeHandler* WaylandWindow::AsWmMoveResizeHandler() {
+ return static_cast<WmMoveResizeHandler*>(this);
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/wayland_window.h b/chromium/ui/ozone/platform/wayland/wayland_window.h
index d652e896aef..e1cb0f6b85d 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_window.h
+++ b/chromium/ui/ozone/platform/wayland/wayland_window.h
@@ -12,10 +12,16 @@
#include "ui/ozone/platform/wayland/wayland_object.h"
#include "ui/platform_window/platform_window.h"
#include "ui/platform_window/platform_window_delegate.h"
+#include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h"
+
+namespace gfx {
+class PointF;
+}
namespace ui {
class BitmapCursorOzone;
+class OSExchangeData;
class PlatformWindowDelegate;
class WaylandConnection;
class XDGPopupWrapper;
@@ -27,7 +33,9 @@ namespace {
class XDGShellObjectFactory;
} // namespace
-class WaylandWindow : public PlatformWindow, public PlatformEventDispatcher {
+class WaylandWindow : public PlatformWindow,
+ public PlatformEventDispatcher,
+ public WmMoveResizeHandler {
public:
WaylandWindow(PlatformWindowDelegate* delegate,
WaylandConnection* connection);
@@ -52,6 +60,8 @@ class WaylandWindow : public PlatformWindow, public PlatformEventDispatcher {
// Set whether this window has keyboard focus and should dispatch key events.
void set_keyboard_focus(bool focus) { has_keyboard_focus_ = focus; }
+ bool has_keyboard_focus() const { return has_keyboard_focus_; }
+
// Set whether this window has touch focus and should dispatch touch events.
void set_touch_focus(bool focus) { has_touch_focus_ = focus; }
@@ -66,6 +76,11 @@ class WaylandWindow : public PlatformWindow, public PlatformEventDispatcher {
bool is_active() const { return is_active_; }
+ // WmMoveResizeHandler
+ void DispatchHostWindowDragMovement(
+ int hittest,
+ const gfx::Point& pointer_location) override;
+
// PlatformWindow
void Show() override;
void Hide() override;
@@ -101,6 +116,14 @@ class WaylandWindow : public PlatformWindow, public PlatformEventDispatcher {
void OnCloseRequest();
+ void OnDragEnter(const gfx::PointF& point,
+ std::unique_ptr<OSExchangeData> data,
+ int operation);
+ int OnDragMotion(const gfx::PointF& point, uint32_t time, int operation);
+ void OnDragDrop(std::unique_ptr<OSExchangeData> data);
+ void OnDragLeave();
+ void OnDragSessionClose(uint32_t dnd_action);
+
private:
bool IsMinimized() const;
bool IsMaximized() const;
@@ -116,6 +139,8 @@ class WaylandWindow : public PlatformWindow, public PlatformEventDispatcher {
// Gets a parent window for this window.
WaylandWindow* GetParentWindow(gfx::AcceleratedWidget parent_widget);
+ WmMoveResizeHandler* AsWmMoveResizeHandler();
+
PlatformWindowDelegate* delegate_;
WaylandConnection* connection_;
WaylandWindow* parent_window_ = nullptr;
diff --git a/chromium/ui/ozone/platform/wayland/wayland_window_unittest.cc b/chromium/ui/ozone/platform/wayland/wayland_window_unittest.cc
index 2d885e35ac9..a97b92ebc94 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_window_unittest.cc
+++ b/chromium/ui/ozone/platform/wayland/wayland_window_unittest.cc
@@ -13,10 +13,12 @@
#include "base/strings/utf_string_conversions.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/hit_test.h"
#include "ui/events/base_event_utils.h"
#include "ui/events/event.h"
#include "ui/ozone/platform/wayland/fake_server.h"
#include "ui/ozone/platform/wayland/wayland_test.h"
+#include "ui/ozone/platform/wayland/wayland_util.h"
#include "ui/ozone/test/mock_platform_window_delegate.h"
#include "ui/platform_window/platform_window_init_properties.h"
@@ -132,6 +134,17 @@ class WaylandWindowTest : public WaylandTest {
return window;
}
+ void InitializeWithSupportedHitTestValues(std::vector<int>* hit_tests) {
+ hit_tests->push_back(static_cast<int>(HTBOTTOM));
+ hit_tests->push_back(static_cast<int>(HTBOTTOMLEFT));
+ hit_tests->push_back(static_cast<int>(HTBOTTOMRIGHT));
+ hit_tests->push_back(static_cast<int>(HTLEFT));
+ hit_tests->push_back(static_cast<int>(HTRIGHT));
+ hit_tests->push_back(static_cast<int>(HTTOP));
+ hit_tests->push_back(static_cast<int>(HTTOPLEFT));
+ hit_tests->push_back(static_cast<int>(HTTOPRIGHT));
+ }
+
wl::MockXdgSurface* xdg_surface_;
MouseEvent test_mouse_event_;
@@ -649,6 +662,25 @@ TEST_P(WaylandWindowTest, CanDispatchEventToMenuWindowNested) {
Sync();
}
+TEST_P(WaylandWindowTest, DispatchWindowMove) {
+ EXPECT_CALL(*GetXdgSurface(), Move(_));
+ window_->DispatchHostWindowDragMovement(HTCAPTION, gfx::Point());
+}
+
+// Makes sure hit tests are converted into right edges.
+TEST_P(WaylandWindowTest, DispatchWindowResize) {
+ std::vector<int> hit_test_values;
+ InitializeWithSupportedHitTestValues(&hit_test_values);
+
+ for (const int value : hit_test_values) {
+ {
+ uint32_t direction = wl::IdentifyDirection(*(connection_.get()), value);
+ EXPECT_CALL(*GetXdgSurface(), Resize(_, Eq(direction)));
+ window_->DispatchHostWindowDragMovement(value, gfx::Point());
+ }
+ }
+}
+
INSTANTIATE_TEST_CASE_P(XdgVersionV5Test,
WaylandWindowTest,
::testing::Values(kXdgShellV5));
diff --git a/chromium/ui/ozone/platform/wayland/xdg_surface_wrapper_v5.cc b/chromium/ui/ozone/platform/wayland/xdg_surface_wrapper_v5.cc
index eb8f289f019..7f9cdf85ad2 100644
--- a/chromium/ui/ozone/platform/wayland/xdg_surface_wrapper_v5.cc
+++ b/chromium/ui/ozone/platform/wayland/xdg_surface_wrapper_v5.cc
@@ -7,7 +7,9 @@
#include <xdg-shell-unstable-v5-client-protocol.h>
#include "base/strings/utf_string_conversions.h"
+#include "ui/base/hit_test.h"
#include "ui/ozone/platform/wayland/wayland_connection.h"
+#include "ui/ozone/platform/wayland/wayland_util.h"
#include "ui/ozone/platform/wayland/wayland_window.h"
namespace ui {
@@ -53,20 +55,15 @@ void XDGSurfaceWrapperV5::SetMinimized() {
}
void XDGSurfaceWrapperV5::SurfaceMove(WaylandConnection* connection) {
- NOTIMPLEMENTED();
+ xdg_surface_move(xdg_surface_.get(), connection->seat(),
+ connection->serial());
}
void XDGSurfaceWrapperV5::SurfaceResize(WaylandConnection* connection,
uint32_t hittest) {
- // TODO(msisov): implement resizing.
- /*
- * int direction;
- * if (!IdentifyDirection(hittest, &direction))
- * return;
- * xdg_surface_resize(xdg_surface_.get(), connection->seat(),
- * connection->serial(), direction);
- */
- NOTIMPLEMENTED();
+ xdg_surface_resize(xdg_surface_.get(), connection->seat(),
+ connection->serial(),
+ wl::IdentifyDirection(*connection, hittest));
}
void XDGSurfaceWrapperV5::SetTitle(const base::string16& title) {
diff --git a/chromium/ui/ozone/platform/wayland/xdg_surface_wrapper_v6.cc b/chromium/ui/ozone/platform/wayland/xdg_surface_wrapper_v6.cc
index 14ab84344cf..f913d208b63 100644
--- a/chromium/ui/ozone/platform/wayland/xdg_surface_wrapper_v6.cc
+++ b/chromium/ui/ozone/platform/wayland/xdg_surface_wrapper_v6.cc
@@ -7,7 +7,9 @@
#include <xdg-shell-unstable-v6-client-protocol.h>
#include "base/strings/utf_string_conversions.h"
+#include "ui/base/hit_test.h"
#include "ui/ozone/platform/wayland/wayland_connection.h"
+#include "ui/ozone/platform/wayland/wayland_util.h"
#include "ui/ozone/platform/wayland/wayland_window.h"
namespace ui {
@@ -82,20 +84,17 @@ void XDGSurfaceWrapperV6::SetMinimized() {
}
void XDGSurfaceWrapperV6::SurfaceMove(WaylandConnection* connection) {
- NOTIMPLEMENTED();
+ DCHECK(zxdg_toplevel_v6_);
+ zxdg_toplevel_v6_move(zxdg_toplevel_v6_.get(), connection->seat(),
+ connection->serial());
}
void XDGSurfaceWrapperV6::SurfaceResize(WaylandConnection* connection,
uint32_t hittest) {
- // TODO(msisov): implement resizing.
- /*
- * int direction;
- * if (!IdentifyDirection(hittest, &direction))
- * return;
- * xdg_surface_resize(xdg_surface_.get(), connection->seat(),
- * connection->serial(), direction);
- */
- NOTIMPLEMENTED();
+ DCHECK(zxdg_toplevel_v6_);
+ zxdg_toplevel_v6_resize(zxdg_toplevel_v6_.get(), connection->seat(),
+ connection->serial(),
+ wl::IdentifyDirection(*connection, hittest));
}
void XDGSurfaceWrapperV6::SetTitle(const base::string16& title) {
diff --git a/chromium/ui/ozone/platform/wayland/zwp_text_input_wrapper.h b/chromium/ui/ozone/platform/wayland/zwp_text_input_wrapper.h
new file mode 100644
index 00000000000..8b11a95b779
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/zwp_text_input_wrapper.h
@@ -0,0 +1,74 @@
+// 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_OZONE_PLATFORM_WAYLAND_ZWP_TEXT_INPUT_WRAPPER_H_
+#define UI_OZONE_PLATFORM_WAYLAND_ZWP_TEXT_INPUT_WRAPPER_H_
+
+#include "ui/ozone/platform/wayland/wayland_object.h"
+
+#include "base/strings/string16.h"
+
+namespace gfx {
+class Rect;
+class Range;
+} // namespace gfx
+
+namespace ui {
+
+class WaylandConnection;
+class WaylandWindow;
+
+// Client interface which handles wayland text input callbacks
+class ZWPTextInputWrapperClient {
+ public:
+ virtual ~ZWPTextInputWrapperClient() {}
+
+ // Called when a new composing text (pre-edit) should be set around the
+ // current cursor position. Any previously set composing text should
+ // be removed.
+ virtual void OnPreeditString(const std::string& text,
+ int32_t preedit_cursor) = 0;
+
+ // Called when a complete input sequence has been entered. The text to
+ // commit could be either just a single character after a key press or the
+ // result of some composing (pre-edit).
+ virtual void OnCommitString(const std::string& text) = 0;
+
+ // Called when client needs to delete all or part of the text surrounding
+ // the cursor
+ virtual void OnDeleteSurroundingText(int32_t index, uint32_t length) = 0;
+
+ // Notify when a key event was sent. Key events should not be used
+ // for normal text input operations, which should be done with
+ // commit_string, delete_surrounding_text, etc.
+ virtual void OnKeysym(uint32_t key, uint32_t state, uint32_t modifiers) = 0;
+};
+
+// A wrapper around different versions of wayland text input protocols.
+// Wayland compositors support various different text input protocols which
+// all from Chromium point of view provide the functionality needed by Chromium
+// IME. This interface collects the functionality behind one wrapper API.
+class ZWPTextInputWrapper {
+ public:
+ virtual ~ZWPTextInputWrapper() {}
+
+ virtual void Initialize(WaylandConnection* connection,
+ ZWPTextInputWrapperClient* client) = 0;
+
+ virtual void Reset() = 0;
+
+ virtual void Activate(WaylandWindow* window) = 0;
+ virtual void Deactivate() = 0;
+
+ virtual void ShowInputPanel() = 0;
+ virtual void HideInputPanel() = 0;
+
+ virtual void SetCursorRect(const gfx::Rect& rect) = 0;
+ virtual void SetSurroundingText(const base::string16& text,
+ const gfx::Range& selection_range) = 0;
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_WAYLAND_ZWP_TEXT_INPUT_WRAPPER_H_
diff --git a/chromium/ui/ozone/platform/wayland/zwp_text_input_wrapper_v1.cc b/chromium/ui/ozone/platform/wayland/zwp_text_input_wrapper_v1.cc
new file mode 100644
index 00000000000..4a12ace4011
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/zwp_text_input_wrapper_v1.cc
@@ -0,0 +1,197 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/ozone/platform/wayland/zwp_text_input_wrapper_v1.h"
+
+#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/wayland_connection.h"
+#include "ui/ozone/platform/wayland/wayland_window.h"
+
+namespace ui {
+
+ZWPTextInputWrapperV1::ZWPTextInputWrapperV1(
+ zwp_text_input_manager_v1* text_input_manager)
+ : client_(nullptr) {
+ static const zwp_text_input_v1_listener text_input_listener = {
+ &ZWPTextInputWrapperV1::OnEnter, // text_input_enter,
+ &ZWPTextInputWrapperV1::OnLeave, // text_input_leave,
+ &ZWPTextInputWrapperV1::OnModifiersMap, // text_input_modifiers_map,
+ &ZWPTextInputWrapperV1::
+ OnInputPanelState, // text_input_input_panel_state,
+ &ZWPTextInputWrapperV1::OnPreeditString, // text_input_preedit_string,
+ &ZWPTextInputWrapperV1::OnPreeditStyling, // text_input_preedit_styling,
+ &ZWPTextInputWrapperV1::OnPreeditCursor, // text_input_preedit_cursor,
+ &ZWPTextInputWrapperV1::OnCommitString, // text_input_commit_string,
+ &ZWPTextInputWrapperV1::OnCursorPosition, // text_input_cursor_position,
+ &ZWPTextInputWrapperV1::
+ OnDeleteSurroundingText, // text_input_delete_surrounding_text,
+ &ZWPTextInputWrapperV1::OnKeysym, // text_input_keysym,
+ &ZWPTextInputWrapperV1::OnLanguage, // text_input_language,
+ &ZWPTextInputWrapperV1::OnTextDirection, // text_input_text_direction
+ };
+ ResetInputEventState();
+
+ zwp_text_input_v1* text_input =
+ zwp_text_input_manager_v1_create_text_input(text_input_manager);
+ obj_ = wl::Object<zwp_text_input_v1>(text_input);
+
+ zwp_text_input_v1_add_listener(text_input, &text_input_listener, this);
+}
+
+ZWPTextInputWrapperV1::~ZWPTextInputWrapperV1() {}
+
+void ZWPTextInputWrapperV1::Initialize(WaylandConnection* connection,
+ ZWPTextInputWrapperClient* client) {
+ connection_ = connection;
+ client_ = client;
+}
+
+void ZWPTextInputWrapperV1::Reset() {
+ ResetInputEventState();
+ zwp_text_input_v1_reset(obj_.get());
+}
+
+void ZWPTextInputWrapperV1::Activate(WaylandWindow* window) {
+ zwp_text_input_v1_activate(obj_.get(), connection_->seat(),
+ window->surface());
+}
+
+void ZWPTextInputWrapperV1::Deactivate() {
+ zwp_text_input_v1_deactivate(obj_.get(), connection_->seat());
+}
+
+void ZWPTextInputWrapperV1::ShowInputPanel() {
+ zwp_text_input_v1_show_input_panel(obj_.get());
+}
+
+void ZWPTextInputWrapperV1::HideInputPanel() {
+ zwp_text_input_v1_hide_input_panel(obj_.get());
+}
+
+void ZWPTextInputWrapperV1::SetCursorRect(const gfx::Rect& rect) {
+ zwp_text_input_v1_set_cursor_rectangle(obj_.get(), rect.x(), rect.y(),
+ rect.width(), rect.height());
+}
+
+void ZWPTextInputWrapperV1::SetSurroundingText(
+ const base::string16& text,
+ const gfx::Range& selection_range) {
+ const std::string text_utf8 = base::UTF16ToUTF8(text);
+ zwp_text_input_v1_set_surrounding_text(obj_.get(), text_utf8.c_str(),
+ selection_range.start(),
+ selection_range.end());
+}
+
+void ZWPTextInputWrapperV1::ResetInputEventState() {
+ preedit_cursor_ = -1;
+}
+
+void ZWPTextInputWrapperV1::OnEnter(void* data,
+ struct zwp_text_input_v1* text_input,
+ struct wl_surface* surface) {
+ NOTIMPLEMENTED_LOG_ONCE();
+}
+
+void ZWPTextInputWrapperV1::OnLeave(void* data,
+ struct zwp_text_input_v1* text_input) {
+ NOTIMPLEMENTED_LOG_ONCE();
+}
+
+void ZWPTextInputWrapperV1::OnModifiersMap(void* data,
+ struct zwp_text_input_v1* text_input,
+ struct wl_array* map) {
+ NOTIMPLEMENTED_LOG_ONCE();
+}
+
+void ZWPTextInputWrapperV1::OnInputPanelState(
+ void* data,
+ struct zwp_text_input_v1* text_input,
+ uint32_t state) {
+ NOTIMPLEMENTED_LOG_ONCE();
+}
+
+void ZWPTextInputWrapperV1::OnPreeditString(
+ void* data,
+ struct zwp_text_input_v1* text_input,
+ uint32_t serial,
+ const char* text,
+ const char* commit) {
+ ZWPTextInputWrapperV1* wti = static_cast<ZWPTextInputWrapperV1*>(data);
+ wti->ResetInputEventState();
+ wti->client_->OnPreeditString(std::string(text), wti->preedit_cursor_);
+}
+
+void ZWPTextInputWrapperV1::OnPreeditStyling(
+ void* data,
+ struct zwp_text_input_v1* text_input,
+ uint32_t index,
+ uint32_t length,
+ uint32_t style) {
+ NOTIMPLEMENTED_LOG_ONCE();
+}
+
+void ZWPTextInputWrapperV1::OnPreeditCursor(
+ void* data,
+ struct zwp_text_input_v1* text_input,
+ int32_t index) {
+ ZWPTextInputWrapperV1* wti = static_cast<ZWPTextInputWrapperV1*>(data);
+ wti->preedit_cursor_ = index;
+}
+
+void ZWPTextInputWrapperV1::OnCommitString(void* data,
+ struct zwp_text_input_v1* text_input,
+ uint32_t serial,
+ const char* text) {
+ ZWPTextInputWrapperV1* wti = static_cast<ZWPTextInputWrapperV1*>(data);
+ wti->ResetInputEventState();
+ wti->client_->OnCommitString(std::string(text));
+}
+
+void ZWPTextInputWrapperV1::OnCursorPosition(
+ void* data,
+ struct zwp_text_input_v1* text_input,
+ int32_t index,
+ int32_t anchor) {
+ NOTIMPLEMENTED_LOG_ONCE();
+}
+
+void ZWPTextInputWrapperV1::OnDeleteSurroundingText(
+ void* data,
+ struct zwp_text_input_v1* text_input,
+ int32_t index,
+ uint32_t length) {
+ ZWPTextInputWrapperV1* wti = static_cast<ZWPTextInputWrapperV1*>(data);
+ wti->client_->OnDeleteSurroundingText(index, length);
+}
+
+void ZWPTextInputWrapperV1::OnKeysym(void* data,
+ struct zwp_text_input_v1* text_input,
+ uint32_t serial,
+ uint32_t time,
+ uint32_t key,
+ uint32_t state,
+ uint32_t modifiers) {
+ ZWPTextInputWrapperV1* wti = static_cast<ZWPTextInputWrapperV1*>(data);
+ wti->client_->OnKeysym(key, state, modifiers);
+}
+
+void ZWPTextInputWrapperV1::OnLanguage(void* data,
+ struct zwp_text_input_v1* text_input,
+ uint32_t serial,
+ const char* language) {
+ NOTIMPLEMENTED_LOG_ONCE();
+}
+
+void ZWPTextInputWrapperV1::OnTextDirection(
+ void* data,
+ struct zwp_text_input_v1* text_input,
+ uint32_t serial,
+ uint32_t direction) {
+ NOTIMPLEMENTED_LOG_ONCE();
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/wayland/zwp_text_input_wrapper_v1.h b/chromium/ui/ozone/platform/wayland/zwp_text_input_wrapper_v1.h
new file mode 100644
index 00000000000..62cfaa629e9
--- /dev/null
+++ b/chromium/ui/ozone/platform/wayland/zwp_text_input_wrapper_v1.h
@@ -0,0 +1,106 @@
+// 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_OZONE_PLATFORM_WAYLAND_ZWP_TEXT_INPUT_WRAPPER_V1_H_
+#define UI_OZONE_PLATFORM_WAYLAND_ZWP_TEXT_INPUT_WRAPPER_V1_H_
+
+#include <text-input-unstable-v1-client-protocol.h>
+#include <string>
+
+#include "ui/ozone/platform/wayland/zwp_text_input_wrapper.h"
+
+namespace gfx {
+class Rect;
+}
+
+namespace ui {
+
+class WaylandConnection;
+class WaylandWindow;
+
+class ZWPTextInputWrapperV1 : public ZWPTextInputWrapper {
+ public:
+ explicit ZWPTextInputWrapperV1(zwp_text_input_manager_v1* text_input_manager);
+ ~ZWPTextInputWrapperV1() override;
+
+ void Initialize(WaylandConnection* connection,
+ ZWPTextInputWrapperClient* client) override;
+
+ void Reset() override;
+
+ void Activate(WaylandWindow* window) override;
+ void Deactivate() override;
+
+ void ShowInputPanel() override;
+ void HideInputPanel() override;
+
+ void SetCursorRect(const gfx::Rect& rect) override;
+ void SetSurroundingText(const base::string16& text,
+ const gfx::Range& selection_range) override;
+
+ private:
+ void ResetInputEventState();
+
+ // zwp_text_input_v1_listener
+ static void OnEnter(void* data,
+ struct zwp_text_input_v1* text_input,
+ struct wl_surface* surface);
+ static void OnLeave(void* data, struct zwp_text_input_v1* text_input);
+ static void OnModifiersMap(void* data,
+ struct zwp_text_input_v1* text_input,
+ struct wl_array* map);
+ static void OnInputPanelState(void* data,
+ struct zwp_text_input_v1* text_input,
+ uint32_t state);
+ static void OnPreeditString(void* data,
+ struct zwp_text_input_v1* text_input,
+ uint32_t serial,
+ const char* text,
+ const char* commit);
+ static void OnPreeditStyling(void* data,
+ struct zwp_text_input_v1* text_input,
+ uint32_t index,
+ uint32_t length,
+ uint32_t style);
+ static void OnPreeditCursor(void* data,
+ struct zwp_text_input_v1* text_input,
+ int32_t index);
+ static void OnCommitString(void* data,
+ struct zwp_text_input_v1* text_input,
+ uint32_t serial,
+ const char* text);
+ static void OnCursorPosition(void* data,
+ struct zwp_text_input_v1* text_input,
+ int32_t index,
+ int32_t anchor);
+ static void OnDeleteSurroundingText(void* data,
+ struct zwp_text_input_v1* text_input,
+ int32_t index,
+ uint32_t length);
+ static void OnKeysym(void* data,
+ struct zwp_text_input_v1* text_input,
+ uint32_t serial,
+ uint32_t time,
+ uint32_t key,
+ uint32_t state,
+ uint32_t modifiers);
+ static void OnLanguage(void* data,
+ struct zwp_text_input_v1* text_input,
+ uint32_t serial,
+ const char* language);
+ static void OnTextDirection(void* data,
+ struct zwp_text_input_v1* text_input,
+ uint32_t serial,
+ uint32_t direction);
+
+ WaylandConnection* connection_ = nullptr;
+ wl::Object<zwp_text_input_v1> obj_;
+ ZWPTextInputWrapperClient* client_;
+
+ int32_t preedit_cursor_;
+};
+
+} // namespace ui
+
+#endif // UI_OZONE_PLATFORM_WAYLAND_ZWP_TEXT_INPUT_WRAPPER_V1_H_
diff --git a/chromium/ui/ozone/public/input_controller.cc b/chromium/ui/ozone/public/input_controller.cc
index 7ee1a3712b6..4ba1521c530 100644
--- a/chromium/ui/ozone/public/input_controller.cc
+++ b/chromium/ui/ozone/public/input_controller.cc
@@ -5,10 +5,8 @@
#include "ui/ozone/public/input_controller.h"
#include "base/callback.h"
-#include "base/compiler_specific.h"
#include "base/logging.h"
#include "base/macros.h"
-#include "base/memory/ptr_util.h"
namespace ui {
@@ -16,146 +14,55 @@ namespace {
class StubInputController : public InputController {
public:
- StubInputController();
- ~StubInputController() override;
+ StubInputController() = default;
+ ~StubInputController() override = default;
// InputController:
- bool HasMouse() override;
- bool HasTouchpad() override;
- bool IsCapsLockEnabled() override;
- void SetCapsLockEnabled(bool enabled) override;
- void SetNumLockEnabled(bool enabled) override;
- bool IsAutoRepeatEnabled() override;
- void SetAutoRepeatEnabled(bool enabled) override;
+ bool HasMouse() override { return false; }
+ bool HasTouchpad() override { return false; }
+ bool IsCapsLockEnabled() override { return false; }
+ void SetCapsLockEnabled(bool enabled) override {}
+ void SetNumLockEnabled(bool enabled) override {}
+ bool IsAutoRepeatEnabled() override { return true; }
+ void SetAutoRepeatEnabled(bool enabled) override {}
void SetAutoRepeatRate(const base::TimeDelta& delay,
- const base::TimeDelta& interval) override;
+ const base::TimeDelta& interval) override {}
void GetAutoRepeatRate(base::TimeDelta* delay,
- base::TimeDelta* interval) override;
- void SetCurrentLayoutByName(const std::string& layout_name) override;
- void SetTouchEventLoggingEnabled(bool enabled) override;
- void SetTouchpadSensitivity(int value) override;
- void SetTapToClick(bool enabled) override;
- void SetThreeFingerClick(bool enabled) override;
- void SetTapDragging(bool enabled) override;
- void SetNaturalScroll(bool enabled) override;
- void SetMouseSensitivity(int value) override;
- void SetPrimaryButtonRight(bool right) override;
- void SetMouseReverseScroll(bool enabled) override;
- void SetTapToClickPaused(bool state) override;
- void GetTouchDeviceStatus(GetTouchDeviceStatusReply reply) override;
+ base::TimeDelta* interval) override {}
+ void SetCurrentLayoutByName(const std::string& layout_name) override {}
+ void SetTouchEventLoggingEnabled(bool enabled) override {
+ NOTIMPLEMENTED_LOG_ONCE();
+ }
+ void SetTouchpadSensitivity(int value) override {}
+ void SetTapToClick(bool enabled) override {}
+ void SetThreeFingerClick(bool enabled) override {}
+ void SetTapDragging(bool enabled) override {}
+ void SetNaturalScroll(bool enabled) override {}
+ void SetMouseSensitivity(int value) override {}
+ void SetPrimaryButtonRight(bool right) override {}
+ void SetMouseReverseScroll(bool enabled) override {}
+ void SetTapToClickPaused(bool state) override {}
+ void GetTouchDeviceStatus(GetTouchDeviceStatusReply reply) override {
+ std::move(reply).Run(std::string());
+ }
void GetTouchEventLog(const base::FilePath& out_dir,
- GetTouchEventLogReply reply) override;
- void SetInternalTouchpadEnabled(bool enabled) override;
- bool IsInternalTouchpadEnabled() const override;
- void SetTouchscreensEnabled(bool enabled) override;
+ GetTouchEventLogReply reply) override {
+ std::move(reply).Run(std::vector<base::FilePath>());
+ }
+ void SetInternalTouchpadEnabled(bool enabled) override {}
+ bool IsInternalTouchpadEnabled() const override { return false; }
+ void SetTouchscreensEnabled(bool enabled) override {}
void SetInternalKeyboardFilter(bool enable_filter,
- std::vector<DomCode> allowed_keys) override;
+ std::vector<DomCode> allowed_keys) override {}
private:
DISALLOW_COPY_AND_ASSIGN(StubInputController);
};
-StubInputController::StubInputController() {
-}
-
-StubInputController::~StubInputController() {
-}
-
-bool StubInputController::HasMouse() {
- return false;
-}
-
-bool StubInputController::HasTouchpad() {
- return false;
-}
-
-bool StubInputController::IsCapsLockEnabled() {
- return false;
-}
-
-void StubInputController::SetCapsLockEnabled(bool enabled) {
-}
-
-void StubInputController::SetNumLockEnabled(bool enabled) {
-}
-
-bool StubInputController::IsAutoRepeatEnabled() {
- return true;
-}
-
-void StubInputController::SetAutoRepeatEnabled(bool enabled) {
-}
-
-void StubInputController::SetAutoRepeatRate(const base::TimeDelta& delay,
- const base::TimeDelta& interval) {
-}
-
-void StubInputController::GetAutoRepeatRate(base::TimeDelta* delay,
- base::TimeDelta* interval) {
-}
-
-void StubInputController::SetCurrentLayoutByName(
- const std::string& layout_name) {}
-
-void StubInputController::SetTouchpadSensitivity(int value) {
-}
-
-void StubInputController::SetTouchEventLoggingEnabled(bool enabled) {
- NOTIMPLEMENTED();
-}
-
-void StubInputController::SetTapToClick(bool enabled) {
-}
-
-void StubInputController::SetThreeFingerClick(bool enabled) {
-}
-
-void StubInputController::SetTapDragging(bool enabled) {
-}
-
-void StubInputController::SetNaturalScroll(bool enabled) {
-}
-
-void StubInputController::SetMouseSensitivity(int value) {
-}
-
-void StubInputController::SetPrimaryButtonRight(bool right) {
-}
-
-void StubInputController::SetMouseReverseScroll(bool enabled) {
-}
-
-void StubInputController::SetTapToClickPaused(bool state) {
-}
-
-void StubInputController::GetTouchDeviceStatus(
- GetTouchDeviceStatusReply reply) {
- std::move(reply).Run(std::string());
-}
-
-void StubInputController::GetTouchEventLog(const base::FilePath& out_dir,
- GetTouchEventLogReply reply) {
- std::move(reply).Run(std::vector<base::FilePath>());
-}
-
-void StubInputController::SetInternalTouchpadEnabled(bool enabled) {
-}
-
-bool StubInputController::IsInternalTouchpadEnabled() const {
- return false;
-}
-
-void StubInputController::SetTouchscreensEnabled(bool enabled) {}
-
-void StubInputController::SetInternalKeyboardFilter(
- bool enable_filter,
- std::vector<DomCode> allowed_keys) {
-}
-
} // namespace
std::unique_ptr<InputController> CreateStubInputController() {
- return base::WrapUnique(new StubInputController);
+ return std::make_unique<StubInputController>();
}
} // namespace ui
diff --git a/chromium/ui/ozone/public/interfaces/wayland/BUILD.gn b/chromium/ui/ozone/public/interfaces/wayland/BUILD.gn
index c6f2360d026..9ee493e1731 100644
--- a/chromium/ui/ozone/public/interfaces/wayland/BUILD.gn
+++ b/chromium/ui/ozone/public/interfaces/wayland/BUILD.gn
@@ -11,6 +11,7 @@ mojom("wayland_interfaces") {
public_deps = [
"//mojo/public/mojom/base",
+ "//ui/gfx/geometry/mojo",
"//ui/gfx/mojo",
]
}
diff --git a/chromium/ui/ozone/public/interfaces/wayland/wayland_connection.mojom b/chromium/ui/ozone/public/interfaces/wayland/wayland_connection.mojom
index fde5b12974e..a3993ccb15c 100644
--- a/chromium/ui/ozone/public/interfaces/wayland/wayland_connection.mojom
+++ b/chromium/ui/ozone/public/interfaces/wayland/wayland_connection.mojom
@@ -6,7 +6,10 @@ module ui.ozone.mojom;
import "mojo/public/mojom/base/file.mojom";
import "mojo/public/mojom/base/file_path.mojom";
+import "ui/gfx/geometry/mojo/geometry.mojom";
import "ui/gfx/mojo/accelerated_widget.mojom";
+import "ui/gfx/mojo/presentation_feedback.mojom";
+import "ui/gfx/mojo/swap_result.mojom";
// Used by the GPU for communication with a WaylandConnection on the browser
// process.
@@ -26,7 +29,10 @@ interface WaylandConnection {
DestroyZwpLinuxDmabuf(uint32 buffer_id);
// Swaps wl_buffers for a WaylandWindow with the following |widget|.
- ScheduleBufferSwap(gfx.mojom.AcceleratedWidget widget, uint32 buffer_id);
+ ScheduleBufferSwap(gfx.mojom.AcceleratedWidget widget, uint32 buffer_id,
+ gfx.mojom.Rect damage_region)
+ => (gfx.mojom.SwapResult swap_result,
+ gfx.mojom.PresentationFeedback feedback);
};
// Used by the browser process to provide the GPU process with a mojo ptr to a
diff --git a/chromium/ui/ozone/public/ozone_platform.cc b/chromium/ui/ozone/public/ozone_platform.cc
index aae41ff19ef..ec543bc9c10 100644
--- a/chromium/ui/ozone/public/ozone_platform.cc
+++ b/chromium/ui/ozone/public/ozone_platform.cc
@@ -41,10 +41,12 @@ OzonePlatform::PlatformProperties::PlatformProperties(
bool needs_request,
bool custom_frame_default,
bool can_use_system_title_bar,
+ bool requires_mojo_for_ipc,
std::vector<gfx::BufferFormat> buffer_formats)
: needs_view_owner_request(needs_request),
custom_frame_pref_default(custom_frame_default),
use_system_title_bar(can_use_system_title_bar),
+ requires_mojo(requires_mojo_for_ipc),
supported_buffer_formats(buffer_formats) {}
OzonePlatform::PlatformProperties::~PlatformProperties() = default;
diff --git a/chromium/ui/ozone/public/ozone_platform.h b/chromium/ui/ozone/public/ozone_platform.h
index da9f46aa764..f1058530501 100644
--- a/chromium/ui/ozone/public/ozone_platform.h
+++ b/chromium/ui/ozone/public/ozone_platform.h
@@ -91,6 +91,7 @@ class OZONE_EXPORT OzonePlatform {
PlatformProperties(bool needs_request,
bool custom_frame_default,
bool can_use_system_title_bar,
+ bool requires_mojo_for_ipc,
std::vector<gfx::BufferFormat> buffer_formats);
~PlatformProperties();
PlatformProperties(const PlatformProperties& other);
@@ -108,6 +109,10 @@ class OZONE_EXPORT OzonePlatform {
// supported.
bool use_system_title_bar = false;
+ // Determines if the platform requires mojo communication for the IPC.
+ // Currently used only by the Ozone/Wayland platform.
+ bool requires_mojo = false;
+
// Wayland only: carries buffer formats supported by a Wayland server.
std::vector<gfx::BufferFormat> supported_buffer_formats;
};
diff --git a/chromium/ui/ozone/public/ozone_switches.cc b/chromium/ui/ozone/public/ozone_switches.cc
index 0a9b3ab32a0..7bec0b7ef22 100644
--- a/chromium/ui/ozone/public/ozone_switches.cc
+++ b/chromium/ui/ozone/public/ozone_switches.cc
@@ -12,4 +12,7 @@ const char kOzonePlatform[] = "ozone-platform";
// Specify location for image dumps.
const char kOzoneDumpFile[] = "ozone-dump-file";
+// Try to enable wayland input method editor.
+const char kEnableWaylandIme[] = "enable-wayland-ime";
+
} // namespace switches
diff --git a/chromium/ui/ozone/public/ozone_switches.h b/chromium/ui/ozone/public/ozone_switches.h
index b062e67fcfb..d7e7d8a9256 100644
--- a/chromium/ui/ozone/public/ozone_switches.h
+++ b/chromium/ui/ozone/public/ozone_switches.h
@@ -14,6 +14,8 @@ OZONE_BASE_EXPORT extern const char kOzonePlatform[];
OZONE_BASE_EXPORT extern const char kOzoneDumpFile[];
+OZONE_BASE_EXPORT extern const char kEnableWaylandIme[];
+
} // namespace switches
#endif // UI_OZONE_PUBLIC_OZONE_SWITCHES_H_
diff --git a/chromium/ui/platform_window/BUILD.gn b/chromium/ui/platform_window/BUILD.gn
index dbfac36279a..af5ef67e875 100644
--- a/chromium/ui/platform_window/BUILD.gn
+++ b/chromium/ui/platform_window/BUILD.gn
@@ -24,7 +24,7 @@ source_set("platform_window") {
if (is_fuchsia) {
public_deps = [
- "//third_party/fuchsia-sdk:viewsv1token",
+ "//third_party/fuchsia-sdk/sdk:viewsv1token",
]
}
}
diff --git a/chromium/ui/platform_window/DEPS b/chromium/ui/platform_window/DEPS
index 0e42d64275f..b51da65b022 100644
--- a/chromium/ui/platform_window/DEPS
+++ b/chromium/ui/platform_window/DEPS
@@ -1,5 +1,4 @@
include_rules = [
- "+ui/base/cursor",
- "+ui/base/ime",
+ "+ui/base",
"+ui/gfx",
]
diff --git a/chromium/ui/platform_window/android/java/src/org/chromium/ui/PlatformImeControllerAndroid.java b/chromium/ui/platform_window/android/java/src/org/chromium/ui/PlatformImeControllerAndroid.java
new file mode 100644
index 00000000000..e81c1e7ef86
--- /dev/null
+++ b/chromium/ui/platform_window/android/java/src/org/chromium/ui/PlatformImeControllerAndroid.java
@@ -0,0 +1,107 @@
+// 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.
+
+package org.chromium.ui;
+
+import android.content.Context;
+import android.view.inputmethod.BaseInputConnection;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+import android.view.inputmethod.InputMethodManager;
+
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+
+/**
+ * Exposes IME related code to native code.
+ */
+@JNINamespace("ui")
+class PlatformImeControllerAndroid {
+ private int mInputType;
+ private int mInputFlags;
+ private String mText = "";
+ private int mSelectionStart;
+ private int mSelectionEnd;
+ private int mCompositionStart;
+ private int mCompositionEnd;
+
+ private final PlatformWindowAndroid mWindow;
+ private final long mNativeHandle;
+ private final InputMethodManager mInputMethodManager;
+ private InputConnection mInputConnection;
+
+ PlatformImeControllerAndroid(PlatformWindowAndroid window, long nativeHandle) {
+ mWindow = window;
+ mNativeHandle = nativeHandle;
+ mInputMethodManager = (InputMethodManager) mWindow.getContext().getSystemService(
+ Context.INPUT_METHOD_SERVICE);
+ assert mNativeHandle != 0;
+ nativeInit(mNativeHandle);
+ }
+
+ boolean isTextEditorType() {
+ return mInputType != 0;
+ }
+
+ InputConnection onCreateInputConnection(EditorInfo outAttrs) {
+ if (mInputType == 0) {
+ // Although onCheckIsTextEditor will return false in this case, the EditorInfo
+ // is still used by the InputMethodService. Need to make sure the IME doesn't
+ // enter fullscreen mode.
+ outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_FULLSCREEN;
+ }
+
+ // TODO(penghuang): Support full editor.
+ final boolean fullEditor = false;
+ mInputConnection = new BaseInputConnection(mWindow, fullEditor);
+ outAttrs.actionLabel = null;
+ // TODO(penghuang): Pass blink text input type to Android framework.
+ outAttrs.inputType =
+ EditorInfo.TYPE_CLASS_TEXT | EditorInfo.TYPE_TEXT_VARIATION_WEB_EDIT_TEXT;
+ outAttrs.imeOptions = EditorInfo.IME_FLAG_NO_EXTRACT_UI | EditorInfo.IME_FLAG_NO_FULLSCREEN
+ | EditorInfo.IME_ACTION_GO;
+ return mInputConnection;
+ }
+
+ @CalledByNative
+ private void updateTextInputState(int textInputType, int textInputFlags, String text,
+ int selectionStart, int selectionEnd, int compositionStart, int compositionEnd) {
+ mInputType = textInputType;
+ mInputFlags = textInputFlags;
+ mText = text;
+ mSelectionStart = selectionStart;
+ mSelectionEnd = selectionEnd;
+ mCompositionStart = compositionStart;
+ mCompositionEnd = compositionEnd;
+ // Update keyboard visibility
+ if (mInputType == 0) {
+ dismissInput();
+ }
+ }
+
+ @CalledByNative
+ private void setImeVisibility(boolean visible) {
+ // The IME is visible only if |mInputType| isn't 0, so we don't need
+ // change the visibility if |mInputType| is 0.
+ if (mInputType != 0) {
+ if (visible) {
+ showKeyboard();
+ } else {
+ dismissInput();
+ }
+ }
+ }
+
+ private void showKeyboard() {
+ mInputMethodManager.showSoftInput(mWindow, 0);
+ }
+
+ private void dismissInput() {
+ mInputMethodManager.hideSoftInputFromWindow(mWindow.getWindowToken(), 0);
+ }
+
+ // The generated native method implementation will call
+ // PlatformImeControllerAndroid::Init(JNIEnv* env, jobject self)
+ private native void nativeInit(long nativePlatformImeControllerAndroid);
+}
diff --git a/chromium/ui/platform_window/android/java/src/org/chromium/ui/PlatformWindowAndroid.java b/chromium/ui/platform_window/android/java/src/org/chromium/ui/PlatformWindowAndroid.java
new file mode 100644
index 00000000000..26810fff1d7
--- /dev/null
+++ b/chromium/ui/platform_window/android/java/src/org/chromium/ui/PlatformWindowAndroid.java
@@ -0,0 +1,207 @@
+// Copyright 2013 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+package org.chromium.ui;
+
+import android.app.Activity;
+import android.view.KeyEvent;
+import android.view.MotionEvent;
+import android.view.Surface;
+import android.view.SurfaceHolder;
+import android.view.SurfaceView;
+import android.view.View;
+import android.view.inputmethod.EditorInfo;
+import android.view.inputmethod.InputConnection;
+
+import org.chromium.base.ContextUtils;
+import org.chromium.base.annotations.CalledByNative;
+import org.chromium.base.annotations.JNINamespace;
+
+/**
+ * Exposes SurfaceView to native code.
+ */
+@JNINamespace("ui")
+public class PlatformWindowAndroid extends SurfaceView {
+
+ private long mNativeMojoViewport;
+ private final SurfaceHolder.Callback mSurfaceCallback;
+ private final PlatformImeControllerAndroid mImeController;
+
+ @CalledByNative
+ public static PlatformWindowAndroid createForActivity(
+ long nativeViewport, long nativeImeController) {
+ PlatformWindowAndroid rv = new PlatformWindowAndroid(nativeViewport, nativeImeController);
+ ((Activity) ContextUtils.getApplicationContext()).setContentView(rv);
+ return rv;
+ }
+
+ private PlatformWindowAndroid(long nativeViewport, long nativeImeController) {
+ super(ContextUtils.getApplicationContext());
+
+ setFocusable(true);
+ setFocusableInTouchMode(true);
+
+ mNativeMojoViewport = nativeViewport;
+ assert mNativeMojoViewport != 0;
+
+ final float density =
+ ContextUtils.getApplicationContext().getResources().getDisplayMetrics().density;
+
+ mSurfaceCallback = new SurfaceHolder.Callback() {
+ @Override
+ public void surfaceChanged(SurfaceHolder holder, int format, int width, int height) {
+ assert mNativeMojoViewport != 0;
+ nativeSurfaceSetSize(mNativeMojoViewport, width, height, density);
+ }
+
+ @Override
+ public void surfaceCreated(SurfaceHolder holder) {
+ assert mNativeMojoViewport != 0;
+ nativeSurfaceCreated(mNativeMojoViewport, holder.getSurface(), density);
+ }
+
+ @Override
+ public void surfaceDestroyed(SurfaceHolder holder) {
+ assert mNativeMojoViewport != 0;
+ nativeSurfaceDestroyed(mNativeMojoViewport);
+ }
+ };
+ getHolder().addCallback(mSurfaceCallback);
+
+ mImeController = new PlatformImeControllerAndroid(this, nativeImeController);
+ }
+
+ @CalledByNative
+ public void detach() {
+ getHolder().removeCallback(mSurfaceCallback);
+ mNativeMojoViewport = 0;
+ }
+
+ @Override
+ protected void onWindowVisibilityChanged(int visibility) {
+ super.onWindowVisibilityChanged(visibility);
+ if (visibility == View.VISIBLE) {
+ requestFocusFromTouch();
+ requestFocus();
+ }
+ }
+
+ @Override
+ public boolean onTouchEvent(MotionEvent event) {
+ final int actionMasked = event.getActionMasked();
+ if (actionMasked == MotionEvent.ACTION_POINTER_DOWN
+ || actionMasked == MotionEvent.ACTION_POINTER_UP) {
+ // Up/down events identify a single point.
+ return notifyTouchEventAtIndex(event, event.getActionIndex());
+ }
+ assert event.getPointerCount() != 0;
+ // All other types can have more than one point.
+ boolean result = false;
+ for (int i = 0, count = event.getPointerCount(); i < count; i++) {
+ final boolean sub_result = notifyTouchEventAtIndex(event, i);
+ result |= sub_result;
+ }
+ return result;
+ }
+
+ @Override
+ public boolean onCheckIsTextEditor() {
+ return mImeController.isTextEditorType();
+ }
+
+ @Override
+ public InputConnection onCreateInputConnection(EditorInfo outAttrs) {
+ return mImeController.onCreateInputConnection(outAttrs);
+ }
+
+ @Override
+ public boolean dispatchKeyEvent(KeyEvent event) {
+ if (privateDispatchKeyEvent(event)) {
+ return true;
+ }
+ return super.dispatchKeyEvent(event);
+ }
+
+ @Override
+ public boolean dispatchKeyEventPreIme(KeyEvent event) {
+ if (privateDispatchKeyEvent(event)) {
+ return true;
+ }
+ return super.dispatchKeyEventPreIme(event);
+ }
+
+ @Override
+ public boolean dispatchKeyShortcutEvent(KeyEvent event) {
+ if (privateDispatchKeyEvent(event)) {
+ return true;
+ }
+ return super.dispatchKeyShortcutEvent(event);
+ }
+
+ private boolean notifyTouchEventAtIndex(MotionEvent event, int index) {
+ float touchMajor = event.getTouchMajor(index);
+ float touchMinor = event.getTouchMinor(index);
+ if (touchMajor < touchMinor) {
+ float tmp = touchMajor;
+ touchMajor = touchMinor;
+ touchMinor = tmp;
+ }
+
+ return nativeTouchEvent(mNativeMojoViewport, event.getEventTime(), event.getActionMasked(),
+ event.getPointerId(index), event.getX(index), event.getY(index),
+ event.getPressure(index), touchMajor, touchMinor,
+ event.getOrientation(index), event.getAxisValue(MotionEvent.AXIS_HSCROLL, index),
+ event.getAxisValue(MotionEvent.AXIS_VSCROLL, index));
+ }
+
+ private boolean privateDispatchKeyEvent(KeyEvent event) {
+ if (event.getAction() == KeyEvent.ACTION_MULTIPLE) {
+ boolean result = false;
+ if (event.getKeyCode() == KeyEvent.KEYCODE_UNKNOWN && event.getCharacters() != null) {
+ String characters = event.getCharacters();
+ for (int i = 0; i < characters.length(); ++i) {
+ char c = characters.charAt(i);
+ int codepoint = c;
+ if (codepoint >= Character.MIN_SURROGATE
+ && codepoint < (Character.MAX_SURROGATE + 1)) {
+ i++;
+ char c2 = characters.charAt(i);
+ codepoint = Character.toCodePoint(c, c2);
+ }
+ result |= nativeKeyEvent(mNativeMojoViewport, true, 0, codepoint);
+ result |= nativeKeyEvent(mNativeMojoViewport, false, 0, codepoint);
+ }
+ } else {
+ for (int i = 0; i < event.getRepeatCount(); ++i) {
+ result |= nativeKeyEvent(
+ mNativeMojoViewport, true, event.getKeyCode(), event.getUnicodeChar());
+ result |= nativeKeyEvent(
+ mNativeMojoViewport, false, event.getKeyCode(), event.getUnicodeChar());
+ }
+ }
+ return result;
+ } else {
+ return nativeKeyEvent(mNativeMojoViewport, event.getAction() == KeyEvent.ACTION_DOWN,
+ event.getKeyCode(), event.getUnicodeChar());
+ }
+ }
+
+ private static native void nativeDestroy(long nativePlatformWindowAndroid);
+
+ private static native void nativeSurfaceCreated(
+ long nativePlatformWindowAndroid, Surface surface, float devicePixelRatio);
+
+ private static native void nativeSurfaceDestroyed(
+ long nativePlatformWindowAndroid);
+
+ private static native void nativeSurfaceSetSize(
+ long nativePlatformWindowAndroid, int width, int height, float density);
+
+ private static native boolean nativeTouchEvent(long nativePlatformWindowAndroid, long timeMs,
+ int maskedAction, int pointerId, float x, float y, float pressure, float touchMajor,
+ float touchMinor, float orientation, float hWheel, float vWheel);
+
+ private static native boolean nativeKeyEvent(
+ long nativePlatformWindowAndroid, boolean pressed, int keyCode, int unicodeCharacter);
+}
diff --git a/chromium/ui/platform_window/android/platform_window_android.cc b/chromium/ui/platform_window/android/platform_window_android.cc
index 7267e3cbe4c..25f80458eee 100644
--- a/chromium/ui/platform_window/android/platform_window_android.cc
+++ b/chromium/ui/platform_window/android/platform_window_android.cc
@@ -120,8 +120,8 @@ bool PlatformWindowAndroid::TouchEvent(JNIEnv* env,
event_type, gfx::Point(),
base::TimeTicks() + base::TimeDelta::FromMilliseconds(time_ms),
ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, pointer_id,
- touch_major, touch_minor, pressure),
- ui::EF_NONE, orientation);
+ touch_major, touch_minor, pressure, orientation),
+ ui::EF_NONE);
touch.set_location_f(gfx::PointF(x, y));
touch.set_root_location_f(gfx::PointF(x, y));
delegate()->DispatchEvent(&touch);
diff --git a/chromium/ui/platform_window/platform_window.h b/chromium/ui/platform_window/platform_window.h
index 181ad85fd70..c7611eee8af 100644
--- a/chromium/ui/platform_window/platform_window.h
+++ b/chromium/ui/platform_window/platform_window.h
@@ -8,6 +8,7 @@
#include <memory>
#include "base/strings/string16.h"
+#include "ui/base/class_property.h"
#include "ui/base/cursor/cursor.h"
#include "ui/platform_window/platform_window_delegate.h"
@@ -24,7 +25,7 @@ class PlatformImeController;
//
// Each instance of PlatformWindow represents a single window in the
// underlying platform windowing system (i.e. X11/Win/OSX).
-class PlatformWindow {
+class PlatformWindow : public PropertyHandler {
public:
virtual ~PlatformWindow() {}
diff --git a/chromium/ui/platform_window/platform_window_handler/BUILD.gn b/chromium/ui/platform_window/platform_window_handler/BUILD.gn
new file mode 100644
index 00000000000..be75a75c702
--- /dev/null
+++ b/chromium/ui/platform_window/platform_window_handler/BUILD.gn
@@ -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.
+
+import("//build/config/jumbo.gni")
+
+jumbo_component("platform_window_handler") {
+ output_name = "platform_window_handler_libs"
+
+ sources = [
+ "wm_move_resize_handler.cc",
+ "wm_move_resize_handler.h",
+ "wm_platform_export.h",
+ ]
+
+ defines = [ "PLATFORM_WINDOW_HANDLER_IMPLEMENTATION" ]
+
+ deps = [
+ "//ui/base",
+ "//ui/platform_window",
+ ]
+}
diff --git a/chromium/ui/platform_window/platform_window_handler/DEPS b/chromium/ui/platform_window/platform_window_handler/DEPS
new file mode 100644
index 00000000000..381a2e478f2
--- /dev/null
+++ b/chromium/ui/platform_window/platform_window_handler/DEPS
@@ -0,0 +1,4 @@
+include_rules = [
+ "+ui/base/class_property.h",
+ "+ui/platform_window/platform_window.h",
+]
diff --git a/chromium/ui/platform_window/platform_window_handler/wm_move_resize_handler.cc b/chromium/ui/platform_window/platform_window_handler/wm_move_resize_handler.cc
new file mode 100644
index 00000000000..5a295a06e1b
--- /dev/null
+++ b/chromium/ui/platform_window/platform_window_handler/wm_move_resize_handler.cc
@@ -0,0 +1,28 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h"
+
+#include "ui/base/class_property.h"
+#include "ui/platform_window/platform_window.h"
+
+DEFINE_UI_CLASS_PROPERTY_TYPE(WmMoveResizeHandler*);
+
+namespace ui {
+
+DEFINE_UI_CLASS_PROPERTY_KEY(WmMoveResizeHandler*,
+ kWmMoveResizeHandlerKey,
+ nullptr);
+
+void SetWmMoveResizeHandler(PlatformWindow* platform_window,
+ WmMoveResizeHandler* move_resize_handler) {
+ platform_window->SetProperty(kWmMoveResizeHandlerKey, move_resize_handler);
+}
+
+WmMoveResizeHandler* GetWmMoveResizeHandler(
+ const PlatformWindow& platform_window) {
+ return platform_window.GetProperty(kWmMoveResizeHandlerKey);
+}
+
+} // namespace ui
diff --git a/chromium/ui/platform_window/platform_window_handler/wm_move_resize_handler.h b/chromium/ui/platform_window/platform_window_handler/wm_move_resize_handler.h
new file mode 100644
index 00000000000..cd5a696a06b
--- /dev/null
+++ b/chromium/ui/platform_window/platform_window_handler/wm_move_resize_handler.h
@@ -0,0 +1,62 @@
+// 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_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_MOVE_RESIZE_HANDLER_H_
+#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_MOVE_RESIZE_HANDLER_H_
+
+#include "ui/platform_window/platform_window_handler/wm_platform_export.h"
+
+namespace gfx {
+class Point;
+} // namespace gfx
+
+namespace ui {
+
+class PlatformWindow;
+
+class WmMoveResizeHandler {
+ public:
+ // A system window manager starts interactive drag or resize of a window based
+ // on the |hittest| value. The |hittest| value identifies in which direction
+ // the window should be resized or whether it should be moved. See
+ // ui/base/hit_test.h for a concrete example with chromium symbolic names
+ // defined. The |pointer_location| indicates the position of the button press
+ // with respect to the platform window, which is needed when sending a
+ // move/resize request in such backends as X11. See _NET_WM_MOVERESIZE section
+ // in https://specifications.freedesktop.org/wm-spec/1.4/ar01s04.html.
+ //
+ // There is no need to implement this by all the platforms except Ozone/X11
+ // and Ozone/Wayland, compositors of which support interactive move/resize.
+ //
+ // This API must be used on mouse or touch events, which are targeted for
+ // non-client components (check ui/base/hit_test.h again) except the ones
+ // targeted for components like HTMAXBUTTON. In that case, the mouse events
+ // are used to identify clicks on maximize/minimize/restore buttons located in
+ // the top non-client area of the chromium window. See
+ // WindowEventFilter::OnMouseEvent for a concrete example of how mouse events
+ // are identified as client or non-client.
+ //
+ // When the API is called, there is no way to know that the call was
+ // successful or not. The browser continues performing as usual except that a
+ // system compositor does not send any mouse/keyboard/etc events until user
+ // releases a mouse button. Instead, the compositor sends new bounds, which a
+ // client uses to recreate gpu buffers and redraw visual represantation of the
+ // browser.
+ virtual void DispatchHostWindowDragMovement(
+ int hittest,
+ const gfx::Point& pointer_location) = 0;
+
+ protected:
+ virtual ~WmMoveResizeHandler() {}
+};
+
+WM_PLATFORM_EXPORT void SetWmMoveResizeHandler(
+ PlatformWindow* platform_window,
+ WmMoveResizeHandler* move_resize_handler);
+WM_PLATFORM_EXPORT WmMoveResizeHandler* GetWmMoveResizeHandler(
+ const PlatformWindow& platform_window);
+
+} // namespace ui
+
+#endif // UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_MOVE_RESIZE_HANDLER_H_
diff --git a/chromium/ui/platform_window/platform_window_handler/wm_platform_export.h b/chromium/ui/platform_window/platform_window_handler/wm_platform_export.h
new file mode 100644
index 00000000000..37165fb71ef
--- /dev/null
+++ b/chromium/ui/platform_window/platform_window_handler/wm_platform_export.h
@@ -0,0 +1,32 @@
+// 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_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_PLATFORM_EXPORT_H_
+#define UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_PLATFORM_EXPORT_H_
+
+// Defines WM_PLATFORM_EXPORT so that functionality implemented by the
+// wm_platform module can be exported to consumers.
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(PLATFORM_WINDOW_HANDLER_IMPLEMENTATION)
+#define WM_PLATFORM_EXPORT __declspec(dllexport)
+#else
+#define WM_PLATFORM_EXPORT __declspec(dllimport)
+#endif // defined(WM_PLATFORM_IMPLEMENTATION)
+
+#else // defined(WIN32)
+#if defined(PLATFORM_WINDOW_HANDLER_IMPLEMENTATION)
+#define WM_PLATFORM_EXPORT __attribute__((visibility("default")))
+#else
+#define WM_PLATFORM_EXPORT
+#endif
+#endif
+
+#else // defined(COMPONENT_BUILD)
+#define WM_PLATFORM_EXPORT
+#endif
+
+#endif // UI_PLATFORM_WINDOW_PLATFORM_WINDOW_HANDLER_WM_PLATFORM_EXPORT_H_
diff --git a/chromium/ui/shell_dialogs/base_shell_dialog_win.cc b/chromium/ui/shell_dialogs/base_shell_dialog_win.cc
index ab67062109f..a61a9e7f953 100644
--- a/chromium/ui/shell_dialogs/base_shell_dialog_win.cc
+++ b/chromium/ui/shell_dialogs/base_shell_dialog_win.cc
@@ -6,11 +6,32 @@
#include <algorithm>
-#include "base/threading/thread.h"
+#include "base/task/post_task.h"
#include "base/win/scoped_com_initializer.h"
namespace ui {
+namespace {
+
+// Creates a SingleThreadTaskRunner to run a shell dialog on. Each dialog
+// requires its own dedicated single-threaded sequence otherwise in some
+// situations where a singleton owns a single instance of this object we can
+// have a situation where a modal dialog in one window blocks the appearance
+// of a modal dialog in another.
+scoped_refptr<base::SingleThreadTaskRunner> CreateDialogTaskRunner() {
+ return CreateCOMSTATaskRunnerWithTraits(
+ {base::TaskPriority::USER_BLOCKING,
+ base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN, base::MayBlock()},
+ base::SingleThreadTaskRunnerThreadMode::DEDICATED);
+}
+
+} // namespace
+
+BaseShellDialogImpl::RunState::RunState() = default;
+BaseShellDialogImpl::RunState::~RunState() = default;
+
+BaseShellDialogImpl::RunState::RunState(const RunState& run_state) = default;
+
// static
BaseShellDialogImpl::Owners BaseShellDialogImpl::owners_;
int BaseShellDialogImpl::instance_count_ = 0;
@@ -32,7 +53,7 @@ BaseShellDialogImpl::RunState BaseShellDialogImpl::BeginRun(HWND owner) {
// entries in our map for the same top level window.
DCHECK(!owner || owner == GetAncestor(owner, GA_ROOT));
RunState run_state;
- run_state.dialog_thread = CreateDialogThread();
+ run_state.dialog_task_runner = CreateDialogTaskRunner();
run_state.owner = owner;
if (owner) {
owners_.insert(owner);
@@ -48,8 +69,6 @@ void BaseShellDialogImpl::EndRun(RunState run_state) {
DCHECK(owners_.find(run_state.owner) != owners_.end());
owners_.erase(run_state.owner);
}
- DCHECK(run_state.dialog_thread);
- delete run_state.dialog_thread;
}
bool BaseShellDialogImpl::IsRunningDialogForOwner(HWND owner) const {
@@ -61,16 +80,6 @@ void BaseShellDialogImpl::DisableOwner(HWND owner) {
EnableWindow(owner, FALSE);
}
-// static
-base::Thread* BaseShellDialogImpl::CreateDialogThread() {
- base::Thread* thread = new base::Thread("Chrome_ShellDialogThread");
- // Many shell dialogs require a COM Single-Threaded Apartment (STA) to run.
- thread->init_com_with_mta(false);
- bool started = thread->Start();
- DCHECK(started);
- return thread;
-}
-
void BaseShellDialogImpl::EnableOwner(HWND owner) {
if (IsWindow(owner))
EnableWindow(owner, TRUE);
diff --git a/chromium/ui/shell_dialogs/base_shell_dialog_win.h b/chromium/ui/shell_dialogs/base_shell_dialog_win.h
index ca5ce0bd567..37959ba6c8a 100644
--- a/chromium/ui/shell_dialogs/base_shell_dialog_win.h
+++ b/chromium/ui/shell_dialogs/base_shell_dialog_win.h
@@ -9,11 +9,12 @@
#include <set>
#include "base/macros.h"
+#include "base/memory/scoped_refptr.h"
#include "ui/shell_dialogs/base_shell_dialog.h"
#include "ui/shell_dialogs/shell_dialogs_export.h"
namespace base {
-class Thread;
+class SingleThreadTaskRunner;
}
namespace ui {
@@ -28,17 +29,22 @@ class SHELL_DIALOGS_EXPORT BaseShellDialogImpl {
protected:
// Represents a run of a dialog.
- struct RunState {
+ struct SHELL_DIALOGS_EXPORT RunState {
+ RunState();
+ ~RunState();
+
+ RunState(const RunState& run_state);
+
// Owning HWND, may be null.
HWND owner;
- // Thread dialog is run on.
- base::Thread* dialog_thread;
+ // Dedicated sequence on which the dialog runs.
+ scoped_refptr<base::SingleThreadTaskRunner> dialog_task_runner;
};
// Called at the beginning of a modal dialog run. Disables the owner window
- // and tracks it. Returns the message loop of the thread that the dialog will
- // be run on.
+ // and tracks it. Returns the dedicated single-threaded sequence that the
+ // dialog will be run on.
RunState BeginRun(HWND owner);
// Cleans up after a dialog run. If the run_state has a valid HWND this makes
@@ -54,24 +60,17 @@ class SHELL_DIALOGS_EXPORT BaseShellDialogImpl {
bool IsRunningDialogForOwner(HWND owner) const;
// Disables the window |owner|. Can be run from either the ui or the dialog
- // thread. Can be called on either the UI or the dialog thread. This function
- // is called on the dialog thread after the modal Windows Common dialog
- // functions return because Windows automatically re-enables the owning
- // window when those functions return, but we don't actually want them to be
- // re-enabled until the response of the dialog propagates back to the UI
- // thread, so we disable the owner manually after the Common dialog function
- // returns.
+ // thread. This function is called on the dialog thread after the modal
+ // Windows Common dialog functions return because Windows automatically
+ // re-enables the owning window when those functions return, but we don't
+ // actually want them to be re-enabled until the response of the dialog
+ // propagates back to the UI thread, so we disable the owner manually after
+ // the Common dialog function returns.
void DisableOwner(HWND owner);
private:
typedef std::set<HWND> Owners;
- // Creates a thread to run a shell dialog on. Each dialog requires its own
- // thread otherwise in some situations where a singleton owns a single
- // instance of this object we can have a situation where a modal dialog in
- // one window blocks the appearance of a modal dialog in another.
- static base::Thread* CreateDialogThread();
-
// Enables the window |owner_|. Can only be run from the ui thread.
void EnableOwner(HWND owner);
diff --git a/chromium/ui/shell_dialogs/select_file_dialog_android.cc b/chromium/ui/shell_dialogs/select_file_dialog_android.cc
index 5a4fa530ce4..9b4346ca909 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog_android.cc
+++ b/chromium/ui/shell_dialogs/select_file_dialog_android.cc
@@ -92,6 +92,15 @@ void SelectFileDialogImpl::OnFileNotSelected(
listener_->FileSelectionCanceled(NULL);
}
+void SelectFileDialogImpl::OnContactsSelected(
+ JNIEnv* env,
+ const JavaParamRef<jobject>& java_object,
+ const JavaParamRef<jstring>& java_contacts) {
+ std::string data = ConvertJavaStringToUTF8(env, java_contacts.obj());
+ listener_->FileSelectedWithExtraInfo(ui::SelectedFileInfo(), 0,
+ (void*)data.c_str());
+}
+
bool SelectFileDialogImpl::IsRunning(gfx::NativeWindow) const {
return listener_;
}
diff --git a/chromium/ui/shell_dialogs/select_file_dialog_android.h b/chromium/ui/shell_dialogs/select_file_dialog_android.h
index 5ac283abf45..719ea966689 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog_android.h
+++ b/chromium/ui/shell_dialogs/select_file_dialog_android.h
@@ -34,6 +34,11 @@ class SelectFileDialogImpl : public SelectFileDialog {
JNIEnv* env,
const base::android::JavaParamRef<jobject>& java_object);
+ void OnContactsSelected(
+ JNIEnv* env,
+ const base::android::JavaParamRef<jobject>& java_object,
+ const base::android::JavaParamRef<jstring>& contacts);
+
// From SelectFileDialog
bool IsRunning(gfx::NativeWindow) const override;
void ListenerDestroyed() override;
diff --git a/chromium/ui/shell_dialogs/select_file_dialog_win.cc b/chromium/ui/shell_dialogs/select_file_dialog_win.cc
index c2208efd854..5f30fefc62f 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog_win.cc
+++ b/chromium/ui/shell_dialogs/select_file_dialog_win.cc
@@ -23,7 +23,6 @@
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
-#include "base/threading/thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/win/registry.h"
#include "base/win/shortcut.h"
@@ -274,7 +273,7 @@ class SelectFileDialogImpl : public ui::SelectFileDialog,
// Runs a Folder selection dialog box, passes back the selected folder in
// |path| and returns true if the user clicks OK. If the user cancels the
// dialog box the value in |path| is not modified and returns false. Run
- // on the dialog thread.
+ // on the dedicated dialog sequence.
bool RunSelectFolderDialog(const ExecuteSelectParams& params,
base::FilePath* path);
@@ -344,7 +343,7 @@ void SelectFileDialogImpl::SelectFileImpl(
default_path, file_types, file_type_index,
default_extension, BeginRun(owner),
owner, params);
- execute_params.run_state.dialog_thread->task_runner()->PostTask(
+ execute_params.run_state.dialog_task_runner->PostTask(
FROM_HERE, base::BindOnce(&SelectFileDialogImpl::ExecuteSelectFile, this,
execute_params));
}
diff --git a/chromium/ui/snapshot/snapshot_aura_unittest.cc b/chromium/ui/snapshot/snapshot_aura_unittest.cc
index 232b732e9f8..84854e5ec6f 100644
--- a/chromium/ui/snapshot/snapshot_aura_unittest.cc
+++ b/chromium/ui/snapshot/snapshot_aura_unittest.cc
@@ -10,6 +10,7 @@
#include "base/bind.h"
#include "base/macros.h"
#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
#include "base/test/test_simple_task_runner.h"
#include "base/win/windows_version.h"
#include "build/build_config.h"
@@ -98,6 +99,10 @@ class SnapshotAuraTest : public testing::Test {
void SetUp() override {
testing::Test::SetUp();
+ scoped_task_environment_ =
+ std::make_unique<base::test::ScopedTaskEnvironment>(
+ base::test::ScopedTaskEnvironment::MainThreadType::UI);
+
// The ContextFactory must exist before any Compositors are created.
// Snapshot test tests real drawing and readback, so needs pixel output.
bool enable_pixel_output = true;
@@ -118,6 +123,7 @@ class SnapshotAuraTest : public testing::Test {
helper_->RunAllPendingInMessageLoop();
helper_->TearDown();
ui::TerminateContextFactoryForTests();
+ scoped_task_environment_.reset();
testing::Test::TearDown();
}
@@ -178,6 +184,7 @@ class SnapshotAuraTest : public testing::Test {
bool completed_;
};
+ std::unique_ptr<base::test::ScopedTaskEnvironment> scoped_task_environment_;
std::unique_ptr<aura::test::AuraTestHelper> helper_;
std::unique_ptr<aura::Window> test_window_;
std::unique_ptr<TestPaintingWindowDelegate> delegate_;
diff --git a/chromium/ui/strings/translations/ui_strings_am.xtb b/chromium/ui/strings/translations/ui_strings_am.xtb
index 654af29168e..83623cebe78 100644
--- a/chromium/ui/strings/translations/ui_strings_am.xtb
+++ b/chromium/ui/strings/translations/ui_strings_am.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{ከ1 ደቂቃ በፊት}one{ከ# ደቂቃዎች በፊት}other{ከ# ደቂቃዎች በፊት}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1ደ}one{#ደ}other{#ደ}}</translation>
<translation id="1243314992276662751">ስቀል</translation>
+<translation id="1269641567813814718">ማሸነፍ</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">የሚመከሩ መተግበሪያዎች</translation>
<translation id="1368832886055348810">ከግራ ወደ ቀኝ</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">አስገባ</translation>
<translation id="8210608804940886430">ወደታች አንቀሳቅስ</translation>
<translation id="8245914219290430011">ትር</translation>
+<translation id="8259556432390118667">የአስራስድስትዮሽ ቀለም እሴት</translation>
<translation id="8328145009876646418">የግራ ጠርዝ</translation>
<translation id="8331626408530291785">ወደ ላይ ሸብልል</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 አመት}one{# ዓመቶች}other{# ዓመቶች}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">እንደወረደ</translation>
<translation id="8806053966018712535">አቃፊ <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">ምስልን አብራራ</translation>
+<translation id="8841375032071747811">የተመለስ አዝራር</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> ኪባ</translation>
<translation id="9002566407876343676">ክፈት</translation>
<translation id="9038489124413477075">ያልተሰየመ አቃፊ</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_ar.xtb b/chromium/ui/strings/translations/ui_strings_ar.xtb
index b212cd8a850..5e810ada0ea 100644
--- a/chromium/ui/strings/translations/ui_strings_ar.xtb
+++ b/chromium/ui/strings/translations/ui_strings_ar.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{قبل دقيقة واحدة}zero{قبل # دقيقة}two{قبل دقيقتين (#)}few{قبل # دقائق}many{قبل # دقيقة}other{قبل # دقيقة}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{دقيقة واحدة}zero{# دقيقة}two{دقيقتان (#)}few{# دقائق}many{# دقيقة}other{# دقيقة}}</translation>
<translation id="1243314992276662751">تحميل</translation>
+<translation id="1269641567813814718">الفوز</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">تطبيقات مقترحة</translation>
<translation id="1368832886055348810">من اليسار لليمين</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">صفحة إلى أسفل</translation>
<translation id="8245914219290430011">علامة تبويب</translation>
+<translation id="8259556432390118667">القيمة السداسية للّون</translation>
<translation id="8328145009876646418">الحافة اليمنى</translation>
<translation id="8331626408530291785">التمرير إلى أعلى</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{سنة واحدة}zero{# سنة}two{سنتان (#)}few{# سنوات}many{# سنةً}other{# سنة}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">التلقائي</translation>
<translation id="8806053966018712535">مجلد <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">إضافة تعليق توضيحي على الصورة</translation>
+<translation id="8841375032071747811">زر الرجوع</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> كيلوبايت</translation>
<translation id="9002566407876343676">الفتح</translation>
<translation id="9038489124413477075">مجلد بدون اسم</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_bg.xtb b/chromium/ui/strings/translations/ui_strings_bg.xtb
index da271229490..e1a2be58747 100644
--- a/chromium/ui/strings/translations/ui_strings_bg.xtb
+++ b/chromium/ui/strings/translations/ui_strings_bg.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{Преди 1 минута}other{Преди # минути}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 мин}other{# мин}}</translation>
<translation id="1243314992276662751">Качване</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">ПРЕПОРЪЧАНИ ПРИЛОЖЕНИЯ</translation>
<translation id="1368832886055348810">Отляво надясно</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Страница надолу</translation>
<translation id="8245914219290430011">Табулатор</translation>
+<translation id="8259556432390118667">Шестнадесетична стойност за цвета</translation>
<translation id="8328145009876646418">Ляв край</translation>
<translation id="8331626408530291785">Превъртане нагоре</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 година}other{# години}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">По подразбиране</translation>
<translation id="8806053966018712535">Папка „<ph name="FOLDER_NAME" />“</translation>
<translation id="883911313571074303">Добавяне на пояснение към изображението</translation>
+<translation id="8841375032071747811">Бутон за връщане назад</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KБ</translation>
<translation id="9002566407876343676">отварям</translation>
<translation id="9038489124413477075">Папка без име</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_bn.xtb b/chromium/ui/strings/translations/ui_strings_bn.xtb
index 97d034f74d3..3ed795a58e5 100644
--- a/chromium/ui/strings/translations/ui_strings_bn.xtb
+++ b/chromium/ui/strings/translations/ui_strings_bn.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{১ মিনিট আগে}one{# মিনিট আগে}other{# মিনিট আগে}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{১ মিনিট}one{# মিনিট}other{# মিনিট}}</translation>
<translation id="1243314992276662751">আপলোড</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">প্রস্তাবিত অ্যাপ</translation>
<translation id="1368832886055348810">বাঁ থেকে ডান</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">পৃষ্ঠা উপরে</translation>
<translation id="8245914219290430011">ট্যাব</translation>
+<translation id="8259556432390118667">হেক্স রঙের মান</translation>
<translation id="8328145009876646418">বাঁ প্রান্ত</translation>
<translation id="8331626408530291785">উপরে স্ক্রোল করুন</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 বছর}one{# বছর}other{# বছর}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">ডিফল্ট</translation>
<translation id="8806053966018712535"><ph name="FOLDER_NAME" /> ফোল্ডার</translation>
<translation id="883911313571074303">চিত্রের জন্য টিকা লিখুন</translation>
+<translation id="8841375032071747811">ফিরে যাওয়ার বোতাম</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">খুলুন</translation>
<translation id="9038489124413477075">নামবিহীন ফোল্ডার</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_ca.xtb b/chromium/ui/strings/translations/ui_strings_ca.xtb
index dec5fd41189..9020f20262a 100644
--- a/chromium/ui/strings/translations/ui_strings_ca.xtb
+++ b/chromium/ui/strings/translations/ui_strings_ca.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{Fa 1 minut}other{Fa # minuts}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 m}other{# m}}</translation>
<translation id="1243314992276662751">Penja</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">APLICACIONS RECOMANADES</translation>
<translation id="1368832886055348810">D'esquerra a dreta</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Retorn</translation>
<translation id="8210608804940886430">Av Pàg</translation>
<translation id="8245914219290430011">Tabulador</translation>
+<translation id="8259556432390118667">Valor del color hexadecimal</translation>
<translation id="8328145009876646418">Extrem esquerre</translation>
<translation id="8331626408530291785">Desplaçament amunt</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 any}other{# anys}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Predeterminat</translation>
<translation id="8806053966018712535">Carpeta <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Afegeix una anotació a la imatge</translation>
+<translation id="8841375032071747811">Botó Enrere</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">obrir</translation>
<translation id="9038489124413477075">Carpeta sense nom</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_cs.xtb b/chromium/ui/strings/translations/ui_strings_cs.xtb
index 39a8bc4c5b6..fe6c504aa2d 100644
--- a/chromium/ui/strings/translations/ui_strings_cs.xtb
+++ b/chromium/ui/strings/translations/ui_strings_cs.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{před minutou}few{před # minutami}many{před # minuty}other{před # minutami}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 min}few{# min}many{# min}other{# min}}</translation>
<translation id="1243314992276662751">Nahrát</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Klávesa Esc</translation>
<translation id="1306549533752902673">DOPORUČENÉ APLIKACE</translation>
<translation id="1368832886055348810">Zleva doprava</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Klávesa PageDown</translation>
<translation id="8245914219290430011">Tab</translation>
+<translation id="8259556432390118667">Hexadecimální kód barvy</translation>
<translation id="8328145009876646418">Levý okraj</translation>
<translation id="8331626408530291785">Posuv nahoru</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 rok}few{# roky}many{# roku}other{# let}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Výchozí</translation>
<translation id="8806053966018712535">Složka <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Přidat k obrázku poznámku</translation>
+<translation id="8841375032071747811">Tlačítko Zpět</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> kB</translation>
<translation id="9002566407876343676">otevřít</translation>
<translation id="9038489124413477075">Nepojmenovaná složka</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_da.xtb b/chromium/ui/strings/translations/ui_strings_da.xtb
index b8a2327aa1c..847fd83e9f7 100644
--- a/chromium/ui/strings/translations/ui_strings_da.xtb
+++ b/chromium/ui/strings/translations/ui_strings_da.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{For 1 minut siden}one{For # minut siden}other{For # minutter siden}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 min.}one{# min.}other{# min.}}</translation>
<translation id="1243314992276662751">Upload</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">ANBEFALEDE APPS</translation>
<translation id="1368832886055348810">Venstre til højre</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Side ned</translation>
<translation id="8245914219290430011">Tabulatortast</translation>
+<translation id="8259556432390118667">Hex-farveværdi</translation>
<translation id="8328145009876646418">Venstre kant</translation>
<translation id="8331626408530291785">Scroll Up</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 år}one{# år}other{# år}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Standard</translation>
<translation id="8806053966018712535">Mappen <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Annoter billede</translation>
+<translation id="8841375032071747811">Knappen Tilbage</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> kB</translation>
<translation id="9002566407876343676">åbn</translation>
<translation id="9038489124413477075">Unavngiven mappe</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_de.xtb b/chromium/ui/strings/translations/ui_strings_de.xtb
index 08739f8213b..47df84f9805 100644
--- a/chromium/ui/strings/translations/ui_strings_de.xtb
+++ b/chromium/ui/strings/translations/ui_strings_de.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{Vor 1 Minute}other{Vor # Minuten}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 min}other{# min}}</translation>
<translation id="1243314992276662751">Hochladen</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">EMPFOHLENE APPS</translation>
<translation id="1368832886055348810">Rechtsläufig</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Nach unten</translation>
<translation id="8245914219290430011">Tabulatortaste</translation>
+<translation id="8259556432390118667">Hex-Farbwert</translation>
<translation id="8328145009876646418">Linker Rand</translation>
<translation id="8331626408530291785">Nach oben blättern</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 Jahr}other{# Jahre}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Standardeinstellung</translation>
<translation id="8806053966018712535">Ordner <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Bild mit Anmerkung versehen</translation>
+<translation id="8841375032071747811">Schaltfläche "Zurück"</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">Öffnen</translation>
<translation id="9038489124413477075">Unbenannter Ordner</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_el.xtb b/chromium/ui/strings/translations/ui_strings_el.xtb
index dfba157889d..f1cca4202c7 100644
--- a/chromium/ui/strings/translations/ui_strings_el.xtb
+++ b/chromium/ui/strings/translations/ui_strings_el.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{Πριν από 1 λεπτό}other{Πριν από # λεπτά}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1λ.}other{#λ.}}</translation>
<translation id="1243314992276662751">Μεταφόρτωση</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">ΠΡΟΤΕΙΝΟΜΕΝΕΣ ΕΦΑΡΜΟΓΕΣ</translation>
<translation id="1368832886055348810">Από αριστερά προς τα δεξιά</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Επόμενη σελίδα</translation>
<translation id="8245914219290430011">Πλήκτρο tab</translation>
+<translation id="8259556432390118667">Δεκαεξαδική τιμή χρώματος</translation>
<translation id="8328145009876646418">Αριστερή άκρη</translation>
<translation id="8331626408530291785">Κύλιση επάνω</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 χρόνος}other{# χρόνια}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Προεπιλογή</translation>
<translation id="8806053966018712535">Φάκελος <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Σχολιασμός εικόνας</translation>
+<translation id="8841375032071747811">Κουμπί "Πίσω"</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">ανοίγω</translation>
<translation id="9038489124413477075">Φάκελος χωρίς όνομα</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_en-GB.xtb b/chromium/ui/strings/translations/ui_strings_en-GB.xtb
index 01dfc8c5cf9..cda9340e79c 100644
--- a/chromium/ui/strings/translations/ui_strings_en-GB.xtb
+++ b/chromium/ui/strings/translations/ui_strings_en-GB.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1 minute ago}other{# minutes ago}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 m}other{# m}}</translation>
<translation id="1243314992276662751">Upload</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">RECOMMENDED APPS</translation>
<translation id="1368832886055348810">Left to Right</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Page Down</translation>
<translation id="8245914219290430011">Tab</translation>
+<translation id="8259556432390118667">Hex colour value</translation>
<translation id="8328145009876646418">Left Edge</translation>
<translation id="8331626408530291785">Scroll Up</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 year}other{# years}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Default</translation>
<translation id="8806053966018712535">Folder <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Annotate image</translation>
+<translation id="8841375032071747811">Back button</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">open</translation>
<translation id="9038489124413477075">Unnamed Folder</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_es-419.xtb b/chromium/ui/strings/translations/ui_strings_es-419.xtb
index fef2f136abf..2ceb6b6d7b3 100644
--- a/chromium/ui/strings/translations/ui_strings_es-419.xtb
+++ b/chromium/ui/strings/translations/ui_strings_es-419.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{Hace 1 minuto}other{Hace # minutos}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 min}other{# min}}</translation>
<translation id="1243314992276662751">Cargar</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">APPS RECOMENDADAS</translation>
<translation id="1368832886055348810">De izquierda a derecha</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Intro</translation>
<translation id="8210608804940886430">Avanzar página</translation>
<translation id="8245914219290430011">Tabulador</translation>
+<translation id="8259556432390118667">Valor de color hexadecimal</translation>
<translation id="8328145009876646418">Borde izquierdo</translation>
<translation id="8331626408530291785">Desplazar hacia arriba</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 año}other{# años}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Predeterminado</translation>
<translation id="8806053966018712535">Carpeta <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Escribir en la imagen</translation>
+<translation id="8841375032071747811">Botón Atrás</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">abrir</translation>
<translation id="9038489124413477075">Carpeta sin nombre</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_es.xtb b/chromium/ui/strings/translations/ui_strings_es.xtb
index 6eb857a643d..ad68eca086e 100644
--- a/chromium/ui/strings/translations/ui_strings_es.xtb
+++ b/chromium/ui/strings/translations/ui_strings_es.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{Hace 1 minuto}other{Hace # minutos}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 min}other{# min}}</translation>
<translation id="1243314992276662751">Subir</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">APLICACIONES RECOMENDADAS</translation>
<translation id="1368832886055348810">De izquierda a derecha</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Intro</translation>
<translation id="8210608804940886430">Avanzar página</translation>
<translation id="8245914219290430011">Tabulador</translation>
+<translation id="8259556432390118667">Valor de color hexadecimal</translation>
<translation id="8328145009876646418">Borde izquierdo</translation>
<translation id="8331626408530291785">Desplazar hacia arriba</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 año}other{# años}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Predeterminado</translation>
<translation id="8806053966018712535">Carpeta <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Anotar imagen</translation>
+<translation id="8841375032071747811">Botón Atrás</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">abrir</translation>
<translation id="9038489124413477075">Carpeta sin nombre</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_et.xtb b/chromium/ui/strings/translations/ui_strings_et.xtb
index 7eac371d49a..154405d6628 100644
--- a/chromium/ui/strings/translations/ui_strings_et.xtb
+++ b/chromium/ui/strings/translations/ui_strings_et.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1 minut tagasi}other{# minutit tagasi}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1m}other{#m}}</translation>
<translation id="1243314992276662751">Laadi üles</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">SOOVITATUD RAKENDUSED</translation>
<translation id="1368832886055348810">Left to Right (Vasakult paremale)</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Sisestusklahv</translation>
<translation id="8210608804940886430">Lehekülje lõppu</translation>
<translation id="8245914219290430011">Vahekaart</translation>
+<translation id="8259556432390118667">Värvi kuueteistkümnendväärtus</translation>
<translation id="8328145009876646418">Vasak serv</translation>
<translation id="8331626408530291785">Keri üles</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 aasta}other{# aastat}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Vaikimisi</translation>
<translation id="8806053966018712535">Kaust <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Lisa kujutisele märkused</translation>
+<translation id="8841375032071747811">Nupp Tagasi</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> kB</translation>
<translation id="9002566407876343676">avage</translation>
<translation id="9038489124413477075">Nimeta kaust</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_fa.xtb b/chromium/ui/strings/translations/ui_strings_fa.xtb
index 513e1464e6d..38102551c88 100644
--- a/chromium/ui/strings/translations/ui_strings_fa.xtb
+++ b/chromium/ui/strings/translations/ui_strings_fa.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{۱ دقیقه قبل}one{# دقیقه قبل}other{# دقیقه قبل}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{۱ دقیقه}one{# دقیقه}other{# دقیقه}}</translation>
<translation id="1243314992276662751">بارگذاری</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">برنامه‌های توصیه‌شده</translation>
<translation id="1368832886055348810">چپ به راست</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">ورود</translation>
<translation id="8210608804940886430">صفحه پایین</translation>
<translation id="8245914219290430011">Tab</translation>
+<translation id="8259556432390118667">مقدار رنگ در مبنای شانزده</translation>
<translation id="8328145009876646418">حاشیه چپ</translation>
<translation id="8331626408530291785">پیمایش به بالا</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{۱ سال}one{# سال}other{# سال}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">پیش‌فرض</translation>
<translation id="8806053966018712535">پوشه <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">حاشیه‌نویسی تصویر</translation>
+<translation id="8841375032071747811">دکمه برگشت</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> کیلوبایت</translation>
<translation id="9002566407876343676">باز کنید</translation>
<translation id="9038489124413477075">پوشه بدون نام</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_fi.xtb b/chromium/ui/strings/translations/ui_strings_fi.xtb
index 42f06a67df3..3deafdc6e5b 100644
--- a/chromium/ui/strings/translations/ui_strings_fi.xtb
+++ b/chromium/ui/strings/translations/ui_strings_fi.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1 minuutti sitten}other{# minuuttia sitten}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 min}other{# min}}</translation>
<translation id="1243314992276662751">Lähetä</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">SOVELLUSSUOSITUKSET</translation>
<translation id="1368832886055348810">Vasemmalta oikealle</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Sivu alas</translation>
<translation id="8245914219290430011">Sarkain</translation>
+<translation id="8259556432390118667">Värin heksadesimaaliarvo</translation>
<translation id="8328145009876646418">Vasen reuna</translation>
<translation id="8331626408530291785">Vieritä ylös</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 vuosi}other{# vuotta}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Oletus</translation>
<translation id="8806053966018712535">Kansio <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Lisää kuvaan muistiinpano</translation>
+<translation id="8841375032071747811">Takaisin-painike</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> kt</translation>
<translation id="9002566407876343676">avata</translation>
<translation id="9038489124413477075">Nimetön kansio</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_fil.xtb b/chromium/ui/strings/translations/ui_strings_fil.xtb
index 33f399ad03b..14edf08b529 100644
--- a/chromium/ui/strings/translations/ui_strings_fil.xtb
+++ b/chromium/ui/strings/translations/ui_strings_fil.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1 minuto ang nakalipas}one{# minuto ang nakalipas}other{# na minuto ang nakalipas}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 minuto}one{# minuto}other{# na minuto}}</translation>
<translation id="1243314992276662751">I-upload</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">MGA INIREREKOMENDANG APP</translation>
<translation id="1368832886055348810">Kaliwa papuntang Kanan</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Page Down</translation>
<translation id="8245914219290430011">Tab</translation>
+<translation id="8259556432390118667">Value ng kulay ng hex</translation>
<translation id="8328145009876646418">Kalwang Edge</translation>
<translation id="8331626408530291785">Mag-scroll Pataas</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 taon}one{# taon}other{# na taon}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Default</translation>
<translation id="8806053966018712535">Folder <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">I-annotate ang larawan</translation>
+<translation id="8841375032071747811">Button na Bumalik</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">buksan</translation>
<translation id="9038489124413477075">Walang Pangalan na Folder</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_fr.xtb b/chromium/ui/strings/translations/ui_strings_fr.xtb
index 3721d9b2ce5..b5dfcea2e3e 100644
--- a/chromium/ui/strings/translations/ui_strings_fr.xtb
+++ b/chromium/ui/strings/translations/ui_strings_fr.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{Il y a une minute}one{Il y a # minute}other{Il y a # minutes}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 m}one{# m}other{# m}}</translation>
<translation id="1243314992276662751">Importer</translation>
+<translation id="1269641567813814718">Windows</translation>
<translation id="1293699935367580298">Échap</translation>
<translation id="1306549533752902673">APPLICATIONS RECOMMANDÉES</translation>
<translation id="1368832886055348810">De gauche à droite</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Entrée</translation>
<translation id="8210608804940886430">Page suivante</translation>
<translation id="8245914219290430011">Tabulation</translation>
+<translation id="8259556432390118667">Valeur de couleur hexadécimale</translation>
<translation id="8328145009876646418">Côté gauche</translation>
<translation id="8331626408530291785">Défilement vers le haut</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 an}one{# an}other{# ans}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Par défaut</translation>
<translation id="8806053966018712535">Dossier <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Annoter l'image</translation>
+<translation id="8841375032071747811">Bouton Retour</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> Ko</translation>
<translation id="9002566407876343676">ouvrir</translation>
<translation id="9038489124413477075">Dossier sans nom</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_gu.xtb b/chromium/ui/strings/translations/ui_strings_gu.xtb
index 61f663f5f16..d1acf345a72 100644
--- a/chromium/ui/strings/translations/ui_strings_gu.xtb
+++ b/chromium/ui/strings/translations/ui_strings_gu.xtb
@@ -6,12 +6,13 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1 મિનિટ પહેલાં}one{# મિનિટ પહેલાં}other{# મિનિટ પહેલાં}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 મિ}one{# મિ}other{# મિ}}</translation>
<translation id="1243314992276662751">અપલોડ કરો</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">ભલામણ કરેલ ઍપ</translation>
<translation id="1368832886055348810">ડાબેથી જમણે</translation>
<translation id="1383876407941801731">શોધો</translation>
<translation id="1398853756734560583">મોટું કરો</translation>
-<translation id="1413622004203049571"><ph name="NOTIFIER_NAME" /> તરફથી સૂચનાઓ અક્ષમ કરો</translation>
+<translation id="1413622004203049571"><ph name="NOTIFIER_NAME" /> તરફથી સૂચનાઓ બંધ કરો</translation>
<translation id="1591184457164800433">{MINUTES,plural, =1{1 મિનિટ અને }one{# મિનિટ અને }other{# મિનિટ અને }}</translation>
<translation id="1643823602425662293">સૂચના</translation>
<translation id="169515659049020177">Shift</translation>
@@ -43,7 +44,7 @@
<translation id="2497284189126895209">બધી ફાઇલો</translation>
<translation id="2515586267016047495">Alt</translation>
<translation id="2522350507219695259">કૅલિબ્રેશન પૂર્ણ થયું</translation>
-<translation id="252373100621549798">અજ્ઞાત પ્રદર્શન</translation>
+<translation id="252373100621549798">અજાણ્યું ડિસ્પ્લે</translation>
<translation id="2583543531130364912">તમારી ટચસ્ક્રીનને કેલિબ્રેટ કરો</translation>
<translation id="2666092431469916601">ઉપર</translation>
<translation id="2743387203779672305">ક્લિપબોર્ડ પર કૉપિ કરો</translation>
@@ -68,7 +69,7 @@
<translation id="3842239759367498783">તમારા મોબાઇલ ઉપકરણ <ph name="TITLE" />માંથી વાંચવાનું ચાલુ રાખો</translation>
<translation id="385051799172605136">પાછળ</translation>
<translation id="3889424535448813030">જમણો એરો</translation>
-<translation id="3892641579809465218">આંતરિક પ્રદર્શન</translation>
+<translation id="3892641579809465218">આંતરિક ડિસ્પ્લે</translation>
<translation id="3897092660631435901">મેનૂ</translation>
<translation id="3909791450649380159">કા&amp;પો</translation>
<translation id="3990502903496589789">જમણી કિનારી</translation>
@@ -83,7 +84,7 @@
<translation id="4788285488841504513">{MONTHS,plural, =1{1 મહિનો બાકી}one{# મહિનો બાકી}other{# મહિના બાકી}}</translation>
<translation id="4841881773802181781">ઉમેરો</translation>
<translation id="4968171027979920686">{SECONDS,plural, =1{1 સેકન્ડ}one{# સેકન્ડ}other{# સેકન્ડ}}</translation>
-<translation id="4971687151119236543">મીડિયા પહેલાંનું ટ્રૅક</translation>
+<translation id="4971687151119236543">મીડિયા પાછલું ગીત</translation>
<translation id="5046499563572181734">અહીં ટૅપ કરો</translation>
<translation id="5076340679995252485">પેસ્ટ કરો</translation>
<translation id="5137751499640340777">Google આસિસ્ટંટ શરૂ કરો</translation>
@@ -128,7 +129,7 @@
<translation id="6845383723252244143">ફોલ્ડર પસંદ કરો</translation>
<translation id="6845533974506654842">દબાવો</translation>
<translation id="6863590663815976734">{HOURS,plural, =1{1 કલાક બાકી}one{# કલાક બાકી}other{# કલાક બાકી}}</translation>
-<translation id="688711909580084195">શીર્ષક વિનાનું વેબપૃષ્ઠ </translation>
+<translation id="688711909580084195">શીર્ષક વિનાનું વેબપેજ</translation>
<translation id="6907759265145635167"><ph name="QUANTITY" /> PB/s</translation>
<translation id="6917971086528278418">{YEARS,plural, =1{1 વર્ષ બાકી}one{# વર્ષ બાકી}other{# વર્ષ બાકી}}</translation>
<translation id="6945221475159498467">પસંદ કરો</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">પૃષ્ઠ નીચે</translation>
<translation id="8245914219290430011">ટૅબ</translation>
+<translation id="8259556432390118667">રંગનું હેક્સ મૂલ્ય</translation>
<translation id="8328145009876646418">ડાબી કિનારી</translation>
<translation id="8331626408530291785">ઉપર સ્ક્રોલ કરો</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 વર્ષ}one{# વર્ષ}other{# વર્ષ}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">ડિફૉલ્ટ</translation>
<translation id="8806053966018712535"><ph name="FOLDER_NAME" /> ફોલ્ડર</translation>
<translation id="883911313571074303">છબીમાં ટીકા કરો</translation>
+<translation id="8841375032071747811">પાછળ બટન</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">ખોલો</translation>
<translation id="9038489124413477075">અનામાંકિત ફોલ્ડર</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_hi.xtb b/chromium/ui/strings/translations/ui_strings_hi.xtb
index 79f3983c19c..a8d86000ed5 100644
--- a/chromium/ui/strings/translations/ui_strings_hi.xtb
+++ b/chromium/ui/strings/translations/ui_strings_hi.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1 मिनट पहले}one{# मिनट पहले}other{# मिनट पहले}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 मिनट}one{# मिनट}other{# मिनट}}</translation>
<translation id="1243314992276662751">अपलोड करें</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">सुझाए गए ऐप्लिकेशन</translation>
<translation id="1368832886055348810">बाएं से दाएं</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Page Down</translation>
<translation id="8245914219290430011">टैब</translation>
+<translation id="8259556432390118667">हेक्स रंग मान</translation>
<translation id="8328145009876646418">बायां सिरा</translation>
<translation id="8331626408530291785">ऊपर स्क्रोल करें</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 वर्ष}one{# वर्ष}other{# वर्ष}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">सामान्य</translation>
<translation id="8806053966018712535"><ph name="FOLDER_NAME" /> फ़ोल्डर</translation>
<translation id="883911313571074303">व्याख्या चित्र</translation>
+<translation id="8841375032071747811">वापस जाएं बटन</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> केबी</translation>
<translation id="9002566407876343676">खोलें</translation>
<translation id="9038489124413477075">अनाम फ़ोल्डर</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_hr.xtb b/chromium/ui/strings/translations/ui_strings_hr.xtb
index 53be996b138..5447710ad23 100644
--- a/chromium/ui/strings/translations/ui_strings_hr.xtb
+++ b/chromium/ui/strings/translations/ui_strings_hr.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{Prije 1 minute}one{prije # minute}few{prije # minute}other{prije # minuta}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 min}one{# min}few{# min}other{# min}}</translation>
<translation id="1243314992276662751">Prenesi</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">PREPORUČENE APLIKACIJE</translation>
<translation id="1368832886055348810">Slijeva udesno</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Stranica prema dolje</translation>
<translation id="8245914219290430011">Kartica</translation>
+<translation id="8259556432390118667">Heksadecimalna vrijednost boje</translation>
<translation id="8328145009876646418">Lijevi rub</translation>
<translation id="8331626408530291785">Pomakni se gore</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 godina}one{# godina}few{# godine}other{# godina}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Zadano</translation>
<translation id="8806053966018712535">Mapa <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Dodaj napomenu slici</translation>
+<translation id="8841375032071747811">Gumb Natrag</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">otvaranje</translation>
<translation id="9038489124413477075">Neimenovana mapa</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_hu.xtb b/chromium/ui/strings/translations/ui_strings_hu.xtb
index 37d3461083a..7e0643cf914 100644
--- a/chromium/ui/strings/translations/ui_strings_hu.xtb
+++ b/chromium/ui/strings/translations/ui_strings_hu.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1 perce}other{# perce}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 p}other{# p}}</translation>
<translation id="1243314992276662751">Feltöltés</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">AJÁNLOTT ALKALMAZÁSOK</translation>
<translation id="1368832886055348810">Balról jobbra</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Page Down</translation>
<translation id="8245914219290430011">Lap</translation>
+<translation id="8259556432390118667">Hexadecimális színérték</translation>
<translation id="8328145009876646418">Bal sarok</translation>
<translation id="8331626408530291785">Görgetés felfelé</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 év}other{# év}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Alapértelmezett</translation>
<translation id="8806053966018712535"><ph name="FOLDER_NAME" /> mappa</translation>
<translation id="883911313571074303">Megjegyzés fűzése a képhez</translation>
+<translation id="8841375032071747811">Vissza gomb</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> kB</translation>
<translation id="9002566407876343676">megnyitás</translation>
<translation id="9038489124413477075">Név nélküli mappa</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_id.xtb b/chromium/ui/strings/translations/ui_strings_id.xtb
index 5adc85f6491..c5349e33811 100644
--- a/chromium/ui/strings/translations/ui_strings_id.xtb
+++ b/chromium/ui/strings/translations/ui_strings_id.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1 menit yang lalu}other{# menit yang lalu}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 m}other{# m}}</translation>
<translation id="1243314992276662751">Upload</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">APLIKASI YANG DIREKOMENDASIKAN</translation>
<translation id="1368832886055348810">Kiri ke Kanan</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Page Down</translation>
<translation id="8245914219290430011">Tab</translation>
+<translation id="8259556432390118667">Nilai warna hex</translation>
<translation id="8328145009876646418">Tepi Kiri</translation>
<translation id="8331626408530291785">Gulir ke Atas</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 tahun}other{# tahun}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Default</translation>
<translation id="8806053966018712535">Folder <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Gambar anotasi</translation>
+<translation id="8841375032071747811">Tombol kembali</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">buka</translation>
<translation id="9038489124413477075">Folder Tanpa Nama</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_it.xtb b/chromium/ui/strings/translations/ui_strings_it.xtb
index dfdeddd620e..e6b55ba6964 100644
--- a/chromium/ui/strings/translations/ui_strings_it.xtb
+++ b/chromium/ui/strings/translations/ui_strings_it.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1 minuto fa}other{# minuti fa}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 m}other{# m}}</translation>
<translation id="1243314992276662751">Carica</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">APP CONSIGLIATE</translation>
<translation id="1368832886055348810">Da sinistra a destra</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Invio</translation>
<translation id="8210608804940886430">Pagina giù</translation>
<translation id="8245914219290430011">Tabulazione</translation>
+<translation id="8259556432390118667">Valore del colore esadecimale</translation>
<translation id="8328145009876646418">Margine sinistro</translation>
<translation id="8331626408530291785">Scorri verso l'alto</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 anno}other{# anni}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Predefinito</translation>
<translation id="8806053966018712535">Cartella <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Annota immagine</translation>
+<translation id="8841375032071747811">Pulsante Indietro</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> kB</translation>
<translation id="9002566407876343676">apri</translation>
<translation id="9038489124413477075">Cartella senza nome</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_iw.xtb b/chromium/ui/strings/translations/ui_strings_iw.xtb
index 844ab24bd34..8178dc769ea 100644
--- a/chromium/ui/strings/translations/ui_strings_iw.xtb
+++ b/chromium/ui/strings/translations/ui_strings_iw.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{לפני דקה אחת}two{לפני # דקות}many{לפני # דקות}other{לפני # דקות}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{דקה}two{# דק}many{# דק}other{# דק}}</translation>
<translation id="1243314992276662751">העלה</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">אפליקציות מומלצות</translation>
<translation id="1368832886055348810">משמאל לימין</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">דף למטה</translation>
<translation id="8245914219290430011">כרטיסייה</translation>
+<translation id="8259556432390118667">ערך צבע הקסדצימלי</translation>
<translation id="8328145009876646418">קצה שמאלי</translation>
<translation id="8331626408530291785">גלול למעלה</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{שנה אחת}two{שנתיים}many{# שנים}other{# שנים}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">ברירת מחדל</translation>
<translation id="8806053966018712535">תיקייה <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">רשום הערה לתמונה</translation>
+<translation id="8841375032071747811">לחצן 'הקודם'</translation>
<translation id="8901569739625249689">‏<ph name="QUANTITY" /> KB‏</translation>
<translation id="9002566407876343676">פתח</translation>
<translation id="9038489124413477075">תיקייה ללא שם</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_ja.xtb b/chromium/ui/strings/translations/ui_strings_ja.xtb
index c459dac1d8a..55d4dee55a6 100644
--- a/chromium/ui/strings/translations/ui_strings_ja.xtb
+++ b/chromium/ui/strings/translations/ui_strings_ja.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1 分前}other{# 分前}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1分}other{#分}}</translation>
<translation id="1243314992276662751">アップロード</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">おすすめのアプリ</translation>
<translation id="1368832886055348810">左から右</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">次のページへ</translation>
<translation id="8245914219290430011">タブ</translation>
+<translation id="8259556432390118667">16 進数色コード</translation>
<translation id="8328145009876646418">左端</translation>
<translation id="8331626408530291785">上にスクロール</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 年}other{# 年}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">既定</translation>
<translation id="8806053966018712535">フォルダ <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">画像に注釈を付ける</translation>
+<translation id="8841375032071747811">戻るボタン</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">開く</translation>
<translation id="9038489124413477075">名前のないフォルダ</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_kn.xtb b/chromium/ui/strings/translations/ui_strings_kn.xtb
index d43c9918a6f..3875572b073 100644
--- a/chromium/ui/strings/translations/ui_strings_kn.xtb
+++ b/chromium/ui/strings/translations/ui_strings_kn.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1 ನಿಮಿಷದ ಹಿಂದೆ}one{# ನಿಮಿಷಗಳ ಹಿಂದೆ}other{# ನಿಮಿಷಗಳ ಹಿಂದೆ}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1ಮೀ}one{#ಮೀ}other{#ಮೀ}}</translation>
<translation id="1243314992276662751">ಅಪ್‌ಲೋಡ್</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">ಶಿಫಾರಸು ಮಾಡಲಾದ ಅಪ್ಲಿಕೇಶನ್‌ಗಳು</translation>
<translation id="1368832886055348810">ಎಡದಿಂದ ಬಲಕ್ಕೆ</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">ಪುಟ ಕೆಳಗೆ</translation>
<translation id="8245914219290430011">ಟ್ಯಾಬ್</translation>
+<translation id="8259556432390118667">ಹೆಕ್ಸ್ ಬಣ್ಣ ಮೌಲ್ಯ</translation>
<translation id="8328145009876646418">ಎಡ ಬದಿ</translation>
<translation id="8331626408530291785">ಮೇಲೆ ಸ್ಕ್ರೋಲ್ ಮಾಡು</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 ವರ್ಷ}one{# ವರ್ಷಗಳು}other{# ವರ್ಷಗಳು}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">ಡಿಫಾಲ್ಟ್</translation>
<translation id="8806053966018712535">ಫೋಲ್ಡರ್ <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">ಚಿತ್ರವನ್ನು ಟಿಪ್ಪಣಿ ಮಾಡಿ</translation>
+<translation id="8841375032071747811">ಹಿಂದೆ ಬಟನ್</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">ತೆರೆ</translation>
<translation id="9038489124413477075">ಹೆಸರಿಸದ ಫೋಲ್ಡರ್</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_ko.xtb b/chromium/ui/strings/translations/ui_strings_ko.xtb
index ea76ee5da19..7d7fa80827e 100644
--- a/chromium/ui/strings/translations/ui_strings_ko.xtb
+++ b/chromium/ui/strings/translations/ui_strings_ko.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1분 전}other{#분 전}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1분}other{#분}}</translation>
<translation id="1243314992276662751">업로드</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">추천 앱</translation>
<translation id="1368832886055348810">왼쪽에서 오른쪽으로</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">페이지 아래로</translation>
<translation id="8245914219290430011">탭</translation>
+<translation id="8259556432390118667">16진수 색상 값</translation>
<translation id="8328145009876646418">왼쪽 모서리</translation>
<translation id="8331626408530291785">위로 스크롤</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1년}other{#년}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">기본값</translation>
<translation id="8806053966018712535"><ph name="FOLDER_NAME" /> 폴더</translation>
<translation id="883911313571074303">이미지에 주석 달기</translation>
+<translation id="8841375032071747811">뒤로 버튼</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" />KB</translation>
<translation id="9002566407876343676">열기</translation>
<translation id="9038489124413477075">이름이 없는 폴더</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_lt.xtb b/chromium/ui/strings/translations/ui_strings_lt.xtb
index 5d1dc6431bb..ec6bc01b05a 100644
--- a/chromium/ui/strings/translations/ui_strings_lt.xtb
+++ b/chromium/ui/strings/translations/ui_strings_lt.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{Prieš 1 minutę}one{Prieš # minutę}few{Prieš # minutes}many{Prieš # minutės}other{Prieš # minučių}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 min.}one{# min.}few{# min.}many{# min.}other{# min.}}</translation>
<translation id="1243314992276662751">Įkelti</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">REKOMENDUOJAMOS PROGRAMOS</translation>
<translation id="1368832886055348810">Iš kairės į dešinę</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Įvesti</translation>
<translation id="8210608804940886430">Puslapį žemyn</translation>
<translation id="8245914219290430011">Skirtukas</translation>
+<translation id="8259556432390118667">Šešioliktainės spalvos vertė</translation>
<translation id="8328145009876646418">Kairysis kraštas</translation>
<translation id="8331626408530291785">Slinkti į viršų</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 metai}one{# metai}few{# metai}many{# metų}other{# metų}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Numatytasis</translation>
<translation id="8806053966018712535">Aplankas „<ph name="FOLDER_NAME" />“</translation>
<translation id="883911313571074303">Komentuoti vaizdą</translation>
+<translation id="8841375032071747811">Mygtukas „Atgal“</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">atidaryti</translation>
<translation id="9038489124413477075">Aplankas be pavadinimo</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_lv.xtb b/chromium/ui/strings/translations/ui_strings_lv.xtb
index ef7ea461f7f..621829fab9a 100644
--- a/chromium/ui/strings/translations/ui_strings_lv.xtb
+++ b/chromium/ui/strings/translations/ui_strings_lv.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{Pirms 1 minūtes}zero{Pirms # minūtēm}one{Pirms # minūtes}other{Pirms # minūtēm}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 min}zero{# min}one{# min}other{# min}}</translation>
<translation id="1243314992276662751">Augšupielādēt</translation>
+<translation id="1269641567813814718">Windows</translation>
<translation id="1293699935367580298">Atsolis</translation>
<translation id="1306549533752902673">IETEIKTĀS LIETOTNES</translation>
<translation id="1368832886055348810">No kreisās uz labo pusi</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Ievadīt</translation>
<translation id="8210608804940886430">Lejup</translation>
<translation id="8245914219290430011">Tabulēšanas taustiņš</translation>
+<translation id="8259556432390118667">Heksadecimāla krāsas vērtība</translation>
<translation id="8328145009876646418">Kreisā mala</translation>
<translation id="8331626408530291785">Ritināt augšup</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 gads}zero{# gadu}one{# gads}other{# gadi}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Noklusējums</translation>
<translation id="8806053966018712535">Mape <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Anotēt attēlu</translation>
+<translation id="8841375032071747811">Poga Atpakaļ</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">atvērt</translation>
<translation id="9038489124413477075">Mape bez nosaukuma</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_ml.xtb b/chromium/ui/strings/translations/ui_strings_ml.xtb
index d44fc29a0e9..30a79e79ec1 100644
--- a/chromium/ui/strings/translations/ui_strings_ml.xtb
+++ b/chromium/ui/strings/translations/ui_strings_ml.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{ഒരു മിനിറ്റിന് മുമ്പ്}other{# മിനിറ്റ് മുമ്പ്}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{ 1 മീറ്റര്‍}other{# മീറ്റർ}}</translation>
<translation id="1243314992276662751">അപ്‌ലോഡുചെയ്യുക</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">ശുപാർശിത ആപ്പുകൾ</translation>
<translation id="1368832886055348810">ഇടതുനിന്ന് വലത്തേക്ക്</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">താഴെയുള്ള പേജുകള്‍</translation>
<translation id="8245914219290430011">ടാബ്</translation>
+<translation id="8259556432390118667">ഹെക്‌സ് വർണ മൂല്യം</translation>
<translation id="8328145009876646418">ഇടത് അഗ്രം</translation>
<translation id="8331626408530291785">മുകളിലേക്ക് സ്ക്രോള്‍ ചെയ്യൂ</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{ഒരു വര്‍ഷം}other{# വർഷം}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">സ്ഥിരസ്ഥിതി</translation>
<translation id="8806053966018712535">ഫോൾഡർ <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">ചിത്രം വ്യാഖ്യാനിക്കുക</translation>
+<translation id="8841375032071747811">ബാക്ക് ബട്ടൺ</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">തുറക്കുക</translation>
<translation id="9038489124413477075">പേരിടാത്ത ഫോൾഡർ</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_mr.xtb b/chromium/ui/strings/translations/ui_strings_mr.xtb
index dfd03abac5e..3c0483238e5 100644
--- a/chromium/ui/strings/translations/ui_strings_mr.xtb
+++ b/chromium/ui/strings/translations/ui_strings_mr.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1 मिनिटापूर्वी}one{# मिनिटापूर्वी}other{# मिनिटांपूर्वी}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1मि}one{#मि}other{#मि}}</translation>
<translation id="1243314992276662751">अपलोड करा</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">शिफारस केलेले अ‍ॅप्स</translation>
<translation id="1368832886055348810">डावीकडून उजवीकडे</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">पृष्ठ खाली</translation>
<translation id="8245914219290430011">टॅब</translation>
+<translation id="8259556432390118667">हेक्स रंग मूल्य</translation>
<translation id="8328145009876646418">डावे काठ</translation>
<translation id="8331626408530291785">वर स्क्रोल करा</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 वर्ष}one{# वर्ष}other{# वर्षे}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">डीफॉल्ट</translation>
<translation id="8806053966018712535"><ph name="FOLDER_NAME" /> फोल्डर</translation>
<translation id="883911313571074303">इमेजवर भाष्य करा</translation>
+<translation id="8841375032071747811">मागे जा बटण</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">उघडा</translation>
<translation id="9038489124413477075">अनामित फोल्डर</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_ms.xtb b/chromium/ui/strings/translations/ui_strings_ms.xtb
index ddf56c5d6ec..51591dd3ffb 100644
--- a/chromium/ui/strings/translations/ui_strings_ms.xtb
+++ b/chromium/ui/strings/translations/ui_strings_ms.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{Seminit yang lalu}other{# minit yang lalu}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1m}other{#m}}</translation>
<translation id="1243314992276662751">Muat naik</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">APL YANG DISYORKAN</translation>
<translation id="1368832886055348810">Kiri ke Kanan</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Ke Bawah Halaman</translation>
<translation id="8245914219290430011">Tab</translation>
+<translation id="8259556432390118667">Nilai warna perenambelasan</translation>
<translation id="8328145009876646418">Tepi Kiri</translation>
<translation id="8331626408530291785">Tatal Ke Atas</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 tahun}other{# tahun}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Lalai</translation>
<translation id="8806053966018712535">Folder <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Anotasikan imej</translation>
+<translation id="8841375032071747811">Butang kembali</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">buka</translation>
<translation id="9038489124413477075">Folder Tanpa Nama</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_nl.xtb b/chromium/ui/strings/translations/ui_strings_nl.xtb
index 65ebdb0427b..c8c3bb38225 100644
--- a/chromium/ui/strings/translations/ui_strings_nl.xtb
+++ b/chromium/ui/strings/translations/ui_strings_nl.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1 minuut geleden}other{# minuten geleden}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 m}other{# m}}</translation>
<translation id="1243314992276662751">Uploaden</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">AANBEVOLEN APPS</translation>
<translation id="1368832886055348810">Links naar rechts</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Pagina omlaag</translation>
<translation id="8245914219290430011">Tab</translation>
+<translation id="8259556432390118667">Hex-kleurwaarde</translation>
<translation id="8328145009876646418">Linkerzijde</translation>
<translation id="8331626408530291785">Omhoog bladeren</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 jaar}other{# jaar}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Standaard</translation>
<translation id="8806053966018712535">Map <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Afbeelding annoteren</translation>
+<translation id="8841375032071747811">Knop Terug</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">openen</translation>
<translation id="9038489124413477075">Naamloze map</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_no.xtb b/chromium/ui/strings/translations/ui_strings_no.xtb
index bec5f749721..551c58bafa1 100644
--- a/chromium/ui/strings/translations/ui_strings_no.xtb
+++ b/chromium/ui/strings/translations/ui_strings_no.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{for 1 minutt siden}other{for # minutter siden}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 m}other{# m}}</translation>
<translation id="1243314992276662751">Last opp</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">ANBEFALTE APPER</translation>
<translation id="1368832886055348810">Venstre til høyre</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Ned 1 s.</translation>
<translation id="8245914219290430011">Fane</translation>
+<translation id="8259556432390118667">Heksadesimal fargekode</translation>
<translation id="8328145009876646418">Venstre kant</translation>
<translation id="8331626408530291785">Rull opp</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 år}other{# år}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Standard</translation>
<translation id="8806053966018712535">Mappen <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Kommenter bildet</translation>
+<translation id="8841375032071747811">Tilbakeknapp</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> kB</translation>
<translation id="9002566407876343676">åpne</translation>
<translation id="9038489124413477075">Mappe uten navn</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_pl.xtb b/chromium/ui/strings/translations/ui_strings_pl.xtb
index d4f9cb40769..39c52df45dc 100644
--- a/chromium/ui/strings/translations/ui_strings_pl.xtb
+++ b/chromium/ui/strings/translations/ui_strings_pl.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{minutę temu}few{# minuty temu}many{# minut temu}other{# minuty temu}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 min}few{# min}many{# min}other{# min}}</translation>
<translation id="1243314992276662751">Prześlij</translation>
+<translation id="1269641567813814718">Windows</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">POLECANE APLIKACJE</translation>
<translation id="1368832886055348810">Od lewej do prawej</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Strona w dół</translation>
<translation id="8245914219290430011">Tab</translation>
+<translation id="8259556432390118667">Wartość szesnastkowego kodu koloru</translation>
<translation id="8328145009876646418">Krawędź po lewej</translation>
<translation id="8331626408530291785">Przewiń w górę</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 rok}few{# lata}many{# lat}other{# roku}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Domyślny</translation>
<translation id="8806053966018712535">Folder <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Dodaj notatkę na grafice</translation>
+<translation id="8841375032071747811">Przycisk Wstecz</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> kB</translation>
<translation id="9002566407876343676">otwórz</translation>
<translation id="9038489124413477075">Folder bez nazwy</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_pt-BR.xtb b/chromium/ui/strings/translations/ui_strings_pt-BR.xtb
index d1fd8f0e48b..84cc1d9f60a 100644
--- a/chromium/ui/strings/translations/ui_strings_pt-BR.xtb
+++ b/chromium/ui/strings/translations/ui_strings_pt-BR.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1 minuto atrás}one{# minuto atrás}other{# minutos atrás}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 min}one{# min}other{# min}}</translation>
<translation id="1243314992276662751">Fazer upload</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">APPS RECOMENDADOS</translation>
<translation id="1368832886055348810">Da esquerda para a direita</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Entrar</translation>
<translation id="8210608804940886430">Página para baixo</translation>
<translation id="8245914219290430011">Guia</translation>
+<translation id="8259556432390118667">Valor de cor hexadecimal</translation>
<translation id="8328145009876646418">Borda esquerda</translation>
<translation id="8331626408530291785">Percorrer para cima</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{ ano}one{# ano}other{# anos}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Padrão</translation>
<translation id="8806053966018712535">Pasta <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Fazer anotações na imagem</translation>
+<translation id="8841375032071747811">Botão "Voltar"</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">abrir</translation>
<translation id="9038489124413477075">Pasta sem nome</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_pt-PT.xtb b/chromium/ui/strings/translations/ui_strings_pt-PT.xtb
index 620b5191fcf..f6590736244 100644
--- a/chromium/ui/strings/translations/ui_strings_pt-PT.xtb
+++ b/chromium/ui/strings/translations/ui_strings_pt-PT.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{Há 1 minuto}other{Há # minutos}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 min}other{# min}}</translation>
<translation id="1243314992276662751">Carregar</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">APLICAÇÕES RECOMENDADAS</translation>
<translation id="1368832886055348810">Da esquerda para a direita</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Página para baixo</translation>
<translation id="8245914219290430011">Tabulação</translation>
+<translation id="8259556432390118667">Valor de cor hexadecimal</translation>
<translation id="8328145009876646418">Margem esquerda</translation>
<translation id="8331626408530291785">Deslocar-se para cima</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 ano}other{# anos}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Predefinição</translation>
<translation id="8806053966018712535">Pasta <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Anotar imagem</translation>
+<translation id="8841375032071747811">Botão Anterior</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">abrir</translation>
<translation id="9038489124413477075">Pasta sem nome</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_ro.xtb b/chromium/ui/strings/translations/ui_strings_ro.xtb
index 9ce3d6fee25..b3a5f77cbcc 100644
--- a/chromium/ui/strings/translations/ui_strings_ro.xtb
+++ b/chromium/ui/strings/translations/ui_strings_ro.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{Acum 1 minut}few{Acum # minute}other{Acum # de minute}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 min.}few{# min.}other{# min.}}</translation>
<translation id="1243314992276662751">Încărcați</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">APLICAȚII RECOMANDATE</translation>
<translation id="1368832886055348810">De la stânga la dreapta</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">O pagină mai jos</translation>
<translation id="8245914219290430011">Tab</translation>
+<translation id="8259556432390118667">Valoarea culorii hexazecimale</translation>
<translation id="8328145009876646418">Marginea stângă</translation>
<translation id="8331626408530291785">Derulează în sus</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 an}few{# ani}other{# de ani}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Prestabilit</translation>
<translation id="8806053966018712535">Dosarul <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Adnotează imaginea</translation>
+<translation id="8841375032071747811">Butonul Înapoi</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KO</translation>
<translation id="9002566407876343676">deschide</translation>
<translation id="9038489124413477075">Dosar fără nume</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_ru.xtb b/chromium/ui/strings/translations/ui_strings_ru.xtb
index 638879b683a..b4752a9a49c 100644
--- a/chromium/ui/strings/translations/ui_strings_ru.xtb
+++ b/chromium/ui/strings/translations/ui_strings_ru.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{минуту назад}one{# минуту назад}few{# минуты назад}many{# минут назад}other{# минуты назад}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 мин.}one{# мин.}few{# мин.}many{# мин.}other{# мин.}}</translation>
<translation id="1243314992276662751">Загрузить</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">РЕКОМЕНДУЕМЫЕ ПРИЛОЖЕНИЯ</translation>
<translation id="1368832886055348810">Слева направо</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">ВВОД</translation>
<translation id="8210608804940886430">Прокрутка вниз</translation>
<translation id="8245914219290430011">Tab</translation>
+<translation id="8259556432390118667">Шестнадцатеричный код цвета</translation>
<translation id="8328145009876646418">Левый край</translation>
<translation id="8331626408530291785">Прокрутка вверх</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 год}one{# год}few{# года}many{# лет}other{# года}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">По умолчанию</translation>
<translation id="8806053966018712535">Папка <ph name="FOLDER_NAME" />.</translation>
<translation id="883911313571074303">Добавить примечание к изображению</translation>
+<translation id="8841375032071747811">Назад</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> КБ</translation>
<translation id="9002566407876343676">открыть</translation>
<translation id="9038489124413477075">Без названия</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_sk.xtb b/chromium/ui/strings/translations/ui_strings_sk.xtb
index 3688bce2913..6b8c84d28c2 100644
--- a/chromium/ui/strings/translations/ui_strings_sk.xtb
+++ b/chromium/ui/strings/translations/ui_strings_sk.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{pred minútou}few{pred # minútami}many{pred # minútami}other{pred # minútami}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 min}few{# min}many{# min}other{# min}}</translation>
<translation id="1243314992276662751">Nahrať</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">ODPORÚČANÉ APLIKÁCIE</translation>
<translation id="1368832886055348810">Zľava doprava</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Stránkovať nadol</translation>
<translation id="8245914219290430011">Tab</translation>
+<translation id="8259556432390118667">Hodnota farby v šestnástkovej sústave</translation>
<translation id="8328145009876646418">Ľavý okraj</translation>
<translation id="8331626408530291785">Rolovať nahor</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 rok}few{# roky}many{# roka}other{# rokov}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Predvolené</translation>
<translation id="8806053966018712535">Priečinok <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Pridať k obrázku poznámku</translation>
+<translation id="8841375032071747811">Tlačidlo Späť</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> kB</translation>
<translation id="9002566407876343676">otvorenie</translation>
<translation id="9038489124413477075">Priečinok bez názvu</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_sl.xtb b/chromium/ui/strings/translations/ui_strings_sl.xtb
index a56bf499085..d43f759535c 100644
--- a/chromium/ui/strings/translations/ui_strings_sl.xtb
+++ b/chromium/ui/strings/translations/ui_strings_sl.xtb
@@ -5,6 +5,7 @@
<translation id="1127811143501539442">{DAYS,plural, =1{Pred 1 dnevom}one{Pred # dnevom}two{Pred # dnevoma}few{Pred # dnevi}other{Pred # dnevi}}</translation>
<translation id="1156623771253174079">{SECONDS,plural, =1{Pred 1 minuto}one{Pred # minuto}two{Pred # minutama}few{Pred # minutami}other{Pred # minutami}}</translation>
<translation id="1243314992276662751">Prenesi</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">PRIPOROČENE APLIKACIJE</translation>
<translation id="1368832886055348810">Od leve proti desni</translation>
@@ -150,6 +151,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Stran dol</translation>
<translation id="8245914219290430011">Zavihek</translation>
+<translation id="8259556432390118667">Vrednost barve v šestnajstiškem zapisu</translation>
<translation id="8328145009876646418">Levi rob</translation>
<translation id="8331626408530291785">Pomik gor</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 leto}one{# leto}two{# leti}few{# leta}other{# let}}</translation>
@@ -162,6 +164,7 @@
<translation id="8798099450830957504">Privzeto</translation>
<translation id="8806053966018712535">Mapa <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Dodaj pripis sliki</translation>
+<translation id="8841375032071747811">Gumb za nazaj</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">odpreti</translation>
<translation id="9038489124413477075">Neimenovana mapa</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_sr.xtb b/chromium/ui/strings/translations/ui_strings_sr.xtb
index 77293bd1e87..72192440d37 100644
--- a/chromium/ui/strings/translations/ui_strings_sr.xtb
+++ b/chromium/ui/strings/translations/ui_strings_sr.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{Пре 1 минут}one{Пре # минут}few{Пре # минута}other{Пре # минута}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 м}one{# м}few{# м}other{# м}}</translation>
<translation id="1243314992276662751">Отпреми</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">ПРЕПОРУЧЕНЕ АПЛИКАЦИЈЕ</translation>
<translation id="1368832886055348810">Слева надесно</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Страница надоле</translation>
<translation id="8245914219290430011">Табулатор</translation>
+<translation id="8259556432390118667">Хексадецимална вредност боје</translation>
<translation id="8328145009876646418">Лева ивица</translation>
<translation id="8331626408530291785">Помери нагоре</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 година}one{# година}few{# године}other{# година}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Подразумевано</translation>
<translation id="8806053966018712535">Директоријум <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Додај напомену у слику</translation>
+<translation id="8841375032071747811">Дугме Назад</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">отварање</translation>
<translation id="9038489124413477075">Неименовани директоријум</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_sv.xtb b/chromium/ui/strings/translations/ui_strings_sv.xtb
index ddad007d50c..54a2a2e2dd2 100644
--- a/chromium/ui/strings/translations/ui_strings_sv.xtb
+++ b/chromium/ui/strings/translations/ui_strings_sv.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1 minut sedan}other{# minuter sedan}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 min}other{# min}}</translation>
<translation id="1243314992276662751">Ladda upp</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">REKOMMENDERADE APPAR</translation>
<translation id="1368832886055348810">Vänster till höger</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Page Down</translation>
<translation id="8245914219290430011">Flik</translation>
+<translation id="8259556432390118667">Hexadecimalt färgvärde</translation>
<translation id="8328145009876646418">Vänsterkant</translation>
<translation id="8331626408530291785">Rulla uppåt</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 år}other{# år}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Standard</translation>
<translation id="8806053966018712535">Mappen <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Kommentera bild</translation>
+<translation id="8841375032071747811">Bakåtknapp</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> kB</translation>
<translation id="9002566407876343676">öppna</translation>
<translation id="9038489124413477075">Namnlös mapp</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_sw.xtb b/chromium/ui/strings/translations/ui_strings_sw.xtb
index d840c0ccf19..7826e6cc78b 100644
--- a/chromium/ui/strings/translations/ui_strings_sw.xtb
+++ b/chromium/ui/strings/translations/ui_strings_sw.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{Dakika 1 iliyopita}other{Dakika # zilizopita}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{Dak 1}other{Dak #}}</translation>
<translation id="1243314992276662751">Pakia</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">PROGRAMU ZINAZOPENDEKEZWA</translation>
<translation id="1368832886055348810">Kushoto hadi Kulia</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Ukurasa mmoja chini</translation>
<translation id="8245914219290430011">Kichupo</translation>
+<translation id="8259556432390118667">Thamani ya rangi ya hex</translation>
<translation id="8328145009876646418">Ncha ya Kushoto</translation>
<translation id="8331626408530291785">Sogeza Juu</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{Mwaka 1}other{Miaka #}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Chaguomsingi</translation>
<translation id="8806053966018712535">Folda ya <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Eleza kuhusu picha</translation>
+<translation id="8841375032071747811">Kitufe cha Nyuma</translation>
<translation id="8901569739625249689">KB <ph name="QUANTITY" /></translation>
<translation id="9002566407876343676">fungua</translation>
<translation id="9038489124413477075">Folda isiyo na jina</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_ta.xtb b/chromium/ui/strings/translations/ui_strings_ta.xtb
index 7431697282f..012be74b666 100644
--- a/chromium/ui/strings/translations/ui_strings_ta.xtb
+++ b/chromium/ui/strings/translations/ui_strings_ta.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1 நிமிடத்திற்கு முன்பு}other{# நிமிடங்களுக்கு முன்பு}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1நி}other{#நி}}</translation>
<translation id="1243314992276662751">பதிவேற்று</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">பரிந்துரைக்கப்படும் பயன்பாடுகள்</translation>
<translation id="1368832886055348810">இடமிருந்து வலம்</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">பக்கத்தின் கீழே</translation>
<translation id="8245914219290430011">தாவல்</translation>
+<translation id="8259556432390118667">ஹெக்ஸ் வண்ண மதிப்பு</translation>
<translation id="8328145009876646418">இடதுபுற முனை</translation>
<translation id="8331626408530291785">மேலே உருட்டு</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 ஆண்டு}other{# ஆண்டுகள்}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">இயல்புநிலை</translation>
<translation id="8806053966018712535"><ph name="FOLDER_NAME" /> கோப்புறை</translation>
<translation id="883911313571074303">படத்தைக் குறிப்பிடு</translation>
+<translation id="8841375032071747811">முந்தையது பொத்தான்</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> கி.பை.</translation>
<translation id="9002566407876343676">திற</translation>
<translation id="9038489124413477075">பெயரிடப்படாதக் கோப்புறை</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_te.xtb b/chromium/ui/strings/translations/ui_strings_te.xtb
index d435e2ad85a..b94fc4fc376 100644
--- a/chromium/ui/strings/translations/ui_strings_te.xtb
+++ b/chromium/ui/strings/translations/ui_strings_te.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1 నిమిషం క్రితం}other{# నిమిషాల క్రితం}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1ని}other{#ని}}</translation>
<translation id="1243314992276662751">అప్‌లోడ్ చేయి</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">సిఫార్సు చేసిన యాప్‌లు</translation>
<translation id="1368832886055348810">ఎడమ నుండి కుడికి</translation>
@@ -38,7 +39,7 @@
<translation id="2289052229480071835">మీ స్క్రీన్‌పై ఉన్న స్పర్శ లక్ష్యాలను నొక్కండి.</translation>
<translation id="2295140143284145483">సర్వే</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
-<translation id="24452542372838207">నోటిఫికేషన్‌ని విస్తరించు</translation>
+<translation id="24452542372838207">నోటిఫికేషన్‌ను విస్తరించు</translation>
<translation id="2482878487686419369">ప్రకటనలు</translation>
<translation id="2497284189126895209">మొత్తం ఫైళ్లు</translation>
<translation id="2515586267016047495">Alt</translation>
@@ -92,7 +93,7 @@
<translation id="528468243742722775">ముగింపు</translation>
<translation id="5329858601952122676">&amp;తొలగించు</translation>
<translation id="5463830097259460683">ఎమోజి &amp;&amp; చిహ్నాలు</translation>
-<translation id="5476505524087279545">ఎంపిక చెయ్యబడలేదు</translation>
+<translation id="5476505524087279545">ఎంపిక చేయబడలేదు</translation>
<translation id="5574202486608032840"><ph name="IDS_SHORT_PRODUCT_OS_NAME" /> సిస్టమ్</translation>
<translation id="5583640892426849032">Backspace</translation>
<translation id="5613020302032141669">ఎడమ బాణం</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">పేజీ క్రిందికి</translation>
<translation id="8245914219290430011">ట్యాబ్</translation>
+<translation id="8259556432390118667">హెక్స్ రంగు విలువ</translation>
<translation id="8328145009876646418">ఎడమ హద్దు</translation>
<translation id="8331626408530291785">పైకి స్క్రోల్ చెయ్యి</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 సంవత్సరం}other{# సంవత్సరాలు}}</translation>
@@ -172,11 +174,12 @@
<translation id="8798099450830957504">డిఫాల్ట్</translation>
<translation id="8806053966018712535">ఫోల్డర్ <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">చిత్రాన్ని అనులేఖించు</translation>
+<translation id="8841375032071747811">వెనుకకు బటన్</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">తెరువు</translation>
<translation id="9038489124413477075">పేరులేని ఫోల్డర్</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 సెక.}other{# సెక.}}</translation>
-<translation id="9059834730836941392">నోటిఫికేషన్‌ని కుదించు</translation>
+<translation id="9059834730836941392">నోటిఫికేషన్‌ను కుదించు</translation>
<translation id="9150735707954472829">ట్యాబ్</translation>
<translation id="9161053988251441839">సూచించబడిన అనువర్తనాలు</translation>
<translation id="9170848237812810038">&amp;అన్డు</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_th.xtb b/chromium/ui/strings/translations/ui_strings_th.xtb
index a1e943da437..632f518ccd6 100644
--- a/chromium/ui/strings/translations/ui_strings_th.xtb
+++ b/chromium/ui/strings/translations/ui_strings_th.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1 นาทีที่ผ่านมา}other{# นาทีที่ผ่านมา}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 นาที}other{# นาที}}</translation>
<translation id="1243314992276662751">อัปโหลด</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">แอปแนะนำ</translation>
<translation id="1368832886055348810">ซ้ายไปขวา</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">เลื่อนหน้าลง</translation>
<translation id="8245914219290430011">แท็บ</translation>
+<translation id="8259556432390118667">ค่าสีแบบเลขฐาน 16</translation>
<translation id="8328145009876646418">ขอบซ้าย</translation>
<translation id="8331626408530291785">เลื่อนขึ้น</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 ปี}other{# ปี}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">ค่าเริ่มต้น</translation>
<translation id="8806053966018712535">โฟลเดอร์ <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">ใส่หมายเหตุในรูปภาพ</translation>
+<translation id="8841375032071747811">ปุ่มกลับ</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">เปิด</translation>
<translation id="9038489124413477075">โฟลเดอร์ที่ไม่มีชื่อ</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_tr.xtb b/chromium/ui/strings/translations/ui_strings_tr.xtb
index abfe2111d7f..0d1d871005b 100644
--- a/chromium/ui/strings/translations/ui_strings_tr.xtb
+++ b/chromium/ui/strings/translations/ui_strings_tr.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1 dakika önce}other{# dakika önce}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 dk.}other{# dk.}}</translation>
<translation id="1243314992276662751">Yükle</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">ÖNERİLEN UYGULAMALAR</translation>
<translation id="1368832886055348810">Soldan Sağa</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Page Down</translation>
<translation id="8245914219290430011">Sekme</translation>
+<translation id="8259556432390118667">Onaltılık renk değeri</translation>
<translation id="8328145009876646418">Sol Kenar</translation>
<translation id="8331626408530291785">Yukarı Kaydır</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 yıl}other{# yıl}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Varsayılan</translation>
<translation id="8806053966018712535"><ph name="FOLDER_NAME" /> klasörü</translation>
<translation id="883911313571074303">Resme açıklama ekle</translation>
+<translation id="8841375032071747811">Geri düğmesi</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">açma</translation>
<translation id="9038489124413477075">Adsız Klasör</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_uk.xtb b/chromium/ui/strings/translations/ui_strings_uk.xtb
index 11c9c184233..bc3ffde91dc 100644
--- a/chromium/ui/strings/translations/ui_strings_uk.xtb
+++ b/chromium/ui/strings/translations/ui_strings_uk.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1 хвилину тому}one{# хвилину тому}few{# хвилини тому}many{# хвилин тому}other{# хвилини тому}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 хв}one{# хв}few{# хв}many{# хв}other{# хв}}</translation>
<translation id="1243314992276662751">Завантажити</translation>
+<translation id="1269641567813814718">Win</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">РЕКОМЕНДОВАНІ ПРОГРАМИ</translation>
<translation id="1368832886055348810">Зліва направо</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Сторінка вниз</translation>
<translation id="8245914219290430011">Tab</translation>
+<translation id="8259556432390118667">Шістнадцятковий код кольору</translation>
<translation id="8328145009876646418">Лівий край</translation>
<translation id="8331626408530291785">Прокрутка вгору</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 рік}one{# рік}few{# роки}many{# років}other{# року}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">За умовчанням</translation>
<translation id="8806053966018712535">Папка <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Додати нотатку до зображення</translation>
+<translation id="8841375032071747811">Кнопка "Назад"</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> КБ</translation>
<translation id="9002566407876343676">відкрити</translation>
<translation id="9038489124413477075">Папка без назви</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_vi.xtb b/chromium/ui/strings/translations/ui_strings_vi.xtb
index 4ab508cc38e..ea8e3c7e21b 100644
--- a/chromium/ui/strings/translations/ui_strings_vi.xtb
+++ b/chromium/ui/strings/translations/ui_strings_vi.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1 phút trước}other{# phút trước}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 phút}other{# phút}}</translation>
<translation id="1243314992276662751">Tải lên</translation>
+<translation id="1269641567813814718">Phím Win</translation>
<translation id="1293699935367580298">Thoát</translation>
<translation id="1306549533752902673">ỨNG DỤNG ĐỀ XUẤT</translation>
<translation id="1368832886055348810">Trái sang Phải</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">Trang Dưới</translation>
<translation id="8245914219290430011">Tab</translation>
+<translation id="8259556432390118667">Giá trị màu hex</translation>
<translation id="8328145009876646418">Cạnh Bên trái</translation>
<translation id="8331626408530291785">Cuộn Lên</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 năm}other{# năm}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">Mặc định</translation>
<translation id="8806053966018712535">Thư mục <ph name="FOLDER_NAME" /></translation>
<translation id="883911313571074303">Chú thích hình ảnh</translation>
+<translation id="8841375032071747811">Nút quay lại</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">mở</translation>
<translation id="9038489124413477075">Thư mục không có tên</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_zh-CN.xtb b/chromium/ui/strings/translations/ui_strings_zh-CN.xtb
index 6bf7da30423..2d61a32c8e8 100644
--- a/chromium/ui/strings/translations/ui_strings_zh-CN.xtb
+++ b/chromium/ui/strings/translations/ui_strings_zh-CN.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1 分钟前}other{# 分钟前}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 分钟}other{# 分钟}}</translation>
<translation id="1243314992276662751">上传</translation>
+<translation id="1269641567813814718">Win 键</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">推荐的应用</translation>
<translation id="1368832886055348810">从左向右</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">向下翻页</translation>
<translation id="8245914219290430011">Tab</translation>
+<translation id="8259556432390118667">十六进制颜色值</translation>
<translation id="8328145009876646418">左边缘</translation>
<translation id="8331626408530291785">向上滚动</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 年}other{# 年}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">默认</translation>
<translation id="8806053966018712535">文件夹“<ph name="FOLDER_NAME" />”</translation>
<translation id="883911313571074303">为图片添加注释</translation>
+<translation id="8841375032071747811">“返回”按钮</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">打开</translation>
<translation id="9038489124413477075">未命名的文件夹</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_zh-TW.xtb b/chromium/ui/strings/translations/ui_strings_zh-TW.xtb
index efc43f929f4..4ef0487a835 100644
--- a/chromium/ui/strings/translations/ui_strings_zh-TW.xtb
+++ b/chromium/ui/strings/translations/ui_strings_zh-TW.xtb
@@ -6,6 +6,7 @@
<translation id="1156623771253174079">{SECONDS,plural, =1{1 分鐘前}other{# 分鐘前}}</translation>
<translation id="1169783199079129864">{MINUTES,plural, =1{1 分鐘}other{# 分鐘}}</translation>
<translation id="1243314992276662751">上傳</translation>
+<translation id="1269641567813814718">Windows 鍵</translation>
<translation id="1293699935367580298">Esc</translation>
<translation id="1306549533752902673">推薦應用程式</translation>
<translation id="1368832886055348810">由左至右</translation>
@@ -157,6 +158,7 @@
<translation id="8179976553408161302">Enter</translation>
<translation id="8210608804940886430">向下翻頁</translation>
<translation id="8245914219290430011">Tab 鍵</translation>
+<translation id="8259556432390118667">16 進位色彩值</translation>
<translation id="8328145009876646418">左邊緣</translation>
<translation id="8331626408530291785">向上捲動</translation>
<translation id="8352146631962686268">{YEARS,plural, =1{1 年}other{# 年}}</translation>
@@ -172,6 +174,7 @@
<translation id="8798099450830957504">預設</translation>
<translation id="8806053966018712535"><ph name="FOLDER_NAME" />資料夾</translation>
<translation id="883911313571074303">為圖片加註</translation>
+<translation id="8841375032071747811">返回按鈕</translation>
<translation id="8901569739625249689"><ph name="QUANTITY" /> KB</translation>
<translation id="9002566407876343676">開啟</translation>
<translation id="9038489124413477075">未命名的資料夾</translation>
diff --git a/chromium/ui/strings/ui_strings.grd b/chromium/ui/strings/ui_strings.grd
index fcf59a3d0c9..d82bf2ff6ce 100644
--- a/chromium/ui/strings/ui_strings.grd
+++ b/chromium/ui/strings/ui_strings.grd
@@ -429,6 +429,9 @@ need to be translated for each locale.-->
Disclosure triangle
</message>
</if>
+ <message name="IDS_APP_ACCNAME_BACK" desc="The accessible name for the back button on the window frame.">
+ Back button
+ </message>
<message name="IDS_APP_ACCNAME_CLOSE" desc="The accessible name for the Close button.">
Close
</message>
@@ -444,6 +447,9 @@ need to be translated for each locale.-->
<message name="IDS_APP_ACCNAME_MENU" desc="The accessible name for the Menu button.">
Menu
</message>
+ <message name="IDS_APP_ACCNAME_COLOR_CHOOSER_HEX_INPUT" desc="The accessible name for the color chooser hexadecimal input field">
+ Hex color value
+ </message>
<!-- Scroll Bar Context Menu Labels -->
<message name="IDS_APP_SCROLLBAR_CXMENU_SCROLLHERE" desc="The label for the 'Scroll Here' item">
@@ -613,6 +619,12 @@ need to be translated for each locale.-->
<message name="IDS_APP_SHIFT_KEY" desc="Shift key">
Shift
</message>
+ <if expr="is_win">
+ <message name="IDS_APP_WINDOWS_KEY" desc="This refers to the 'Windows' key on certain
+ keyboards (often between Ctrl and Alt). This may not need to be translated.">
+ Win
+ </message>
+ </if>
<!-- Accelerator format -->
<message name="IDS_APP_ACCELERATOR_WITH_MODIFIER" desc="Accelerator with a modifier key">
diff --git a/chromium/ui/strings/ui_strings_grd/IDS_APP_ACCNAME_COLOR_CHOOSER_HEX_INPUT.png.sha1 b/chromium/ui/strings/ui_strings_grd/IDS_APP_ACCNAME_COLOR_CHOOSER_HEX_INPUT.png.sha1
new file mode 100644
index 00000000000..6b9993fc250
--- /dev/null
+++ b/chromium/ui/strings/ui_strings_grd/IDS_APP_ACCNAME_COLOR_CHOOSER_HEX_INPUT.png.sha1
@@ -0,0 +1 @@
+6f818215e03008c17e7fe7f3ac6b88d0ca52e958 \ No newline at end of file
diff --git a/chromium/ui/strings/ui_strings_grd/OWNERS b/chromium/ui/strings/ui_strings_grd/OWNERS
new file mode 100644
index 00000000000..72e8ffc0db8
--- /dev/null
+++ b/chromium/ui/strings/ui_strings_grd/OWNERS
@@ -0,0 +1 @@
+*
diff --git a/chromium/ui/views/BUILD.gn b/chromium/ui/views/BUILD.gn
index 3265121c103..b7fa6d3073c 100644
--- a/chromium/ui/views/BUILD.gn
+++ b/chromium/ui/views/BUILD.gn
@@ -54,7 +54,13 @@ jumbo_component("views") {
all_dependent_configs = [ ":flags" ]
public = [
+ # TODO(ccameron): Move these sources to the views_bridge_mac component
+ "../views_bridge_mac/bridge_factory_impl.h",
+ "../views_bridge_mac/bridged_native_widget_impl.h",
+ "../views_bridge_mac/native_widget_mac_nswindow.h",
+ "../views_bridge_mac/window_touch_bar_delegate.h",
"accessibility/view_accessibility.h",
+ "accessibility/view_accessibility_utils.h",
"accessible_pane_view.h",
"animation/bounds_animator.h",
"animation/bounds_animator_observer.h",
@@ -84,13 +90,12 @@ jumbo_component("views") {
"bubble/info_bubble.h",
"bubble/tooltip_icon.h",
"button_drag_utils.h",
- "cocoa/bridged_native_widget.h",
- "cocoa/native_widget_mac_nswindow.h",
- "cocoa/window_touch_bar_delegate.h",
+ "cocoa/bridge_factory_host.h",
"color_chooser/color_chooser_listener.h",
"color_chooser/color_chooser_view.h",
"context_menu_controller.h",
"controls/animated_icon_view.h",
+ "controls/animated_image_view.h",
"controls/button/blue_button.h",
"controls/button/button.h",
"controls/button/checkbox.h",
@@ -108,6 +113,7 @@ jumbo_component("views") {
"controls/focus_ring.h",
"controls/focusable_border.h",
"controls/image_view.h",
+ "controls/image_view_base.h",
"controls/label.h",
"controls/link.h",
"controls/link_listener.h",
@@ -176,6 +182,7 @@ jumbo_component("views") {
"drag_utils.h",
"event_monitor.h",
"event_monitor_mac.h",
+ "event_utils.h",
"focus/external_focus_tracker.h",
"focus/focus_manager.h",
"focus/focus_manager_delegate.h",
@@ -256,7 +263,11 @@ jumbo_component("views") {
]
sources = [
+ # TODO(ccameron): Move these sources to the views_bridge_mac component
+ "../views_bridge_mac/bridged_native_widget_impl.mm",
+ "../views_bridge_mac/native_widget_mac_nswindow.mm",
"accessibility/view_accessibility.cc",
+ "accessibility/view_accessibility_utils.cc",
"accessible_pane_view.cc",
"animation/bounds_animator.cc",
"animation/flood_fill_ink_drop_ripple.cc",
@@ -281,10 +292,9 @@ jumbo_component("views") {
"bubble/info_bubble.cc",
"bubble/tooltip_icon.cc",
"button_drag_utils.cc",
- "cocoa/bridged_native_widget.mm",
- "cocoa/native_widget_mac_nswindow.mm",
"color_chooser/color_chooser_view.cc",
"controls/animated_icon_view.cc",
+ "controls/animated_image_view.cc",
"controls/button/blue_button.cc",
"controls/button/button.cc",
"controls/button/checkbox.cc",
@@ -300,6 +310,7 @@ jumbo_component("views") {
"controls/focus_ring.cc",
"controls/focusable_border.cc",
"controls/image_view.cc",
+ "controls/image_view_base.cc",
"controls/label.cc",
"controls/link.cc",
"controls/menu/display_change_listener_mac.cc",
@@ -362,6 +373,7 @@ jumbo_component("views") {
"drag_utils.cc",
"drag_utils_mac.mm",
"event_monitor_mac.mm",
+ "event_utils.cc",
"focus/external_focus_tracker.cc",
"focus/focus_manager.cc",
"focus/focus_manager_factory.cc",
@@ -434,28 +446,24 @@ jumbo_component("views") {
# Internal sources. TODO(https://crbug.com/871123): Move more headers from
# public into this list, along with the implementation file.
sources += [
- "cocoa/bridged_content_view.h",
- "cocoa/bridged_content_view.mm",
- "cocoa/bridged_content_view_touch_bar.mm",
- "cocoa/bridged_native_widget_host.h",
+ # TODO(ccameron): Move these sources to the views_bridge_mac component
+ "../views_bridge_mac/bridge_factory_impl.mm",
+ "../views_bridge_mac/bridged_content_view.h",
+ "../views_bridge_mac/bridged_content_view.mm",
+ "../views_bridge_mac/bridged_content_view_touch_bar.mm",
+ "../views_bridge_mac/cocoa_window_move_loop.h",
+ "../views_bridge_mac/cocoa_window_move_loop.mm",
+ "../views_bridge_mac/views_nswindow_delegate.h",
+ "../views_bridge_mac/views_nswindow_delegate.mm",
+ "../views_bridge_mac/views_scrollbar_bridge.h",
+ "../views_bridge_mac/views_scrollbar_bridge.mm",
+ "cocoa/bridge_factory_host.cc",
"cocoa/bridged_native_widget_host_impl.h",
"cocoa/bridged_native_widget_host_impl.mm",
- "cocoa/bridged_native_widget_owner.h",
- "cocoa/cocoa_mouse_capture.h",
- "cocoa/cocoa_mouse_capture.mm",
- "cocoa/cocoa_mouse_capture_delegate.h",
- "cocoa/cocoa_window_move_loop.h",
- "cocoa/cocoa_window_move_loop.mm",
"cocoa/drag_drop_client_mac.h",
"cocoa/drag_drop_client_mac.mm",
"cocoa/tooltip_manager_mac.h",
"cocoa/tooltip_manager_mac.mm",
- "cocoa/views_nswindow_delegate.h",
- "cocoa/views_nswindow_delegate.mm",
- "cocoa/views_scrollbar_bridge.h",
- "cocoa/views_scrollbar_bridge.mm",
- "cocoa/widget_owner_nswindow_adapter.h",
- "cocoa/widget_owner_nswindow_adapter.mm",
"controls/button/label_button_label.cc",
"controls/button/label_button_label.h",
"controls/menu/menu_pre_target_handler.h",
@@ -477,6 +485,7 @@ jumbo_component("views") {
"//base:i18n",
"//base/third_party/dynamic_annotations",
"//cc/paint",
+ "//mojo/public/cpp/bindings",
"//services/ws/public/mojom",
"//skia",
"//third_party/icu",
@@ -506,7 +515,6 @@ jumbo_component("views") {
"//ui/gfx/animation",
"//ui/gfx/geometry",
"//ui/views/resources",
- "//ui/views_bridge_mac:mojo",
]
if (use_x11) {
@@ -588,11 +596,11 @@ jumbo_component("views") {
public += [
"accessibility/ax_aura_obj_cache.h",
"accessibility/ax_aura_obj_wrapper.h",
+ "accessibility/ax_root_obj_wrapper.h",
"accessibility/ax_tree_source_views.h",
"accessibility/ax_view_obj_wrapper.h",
"accessibility/ax_widget_obj_wrapper.h",
"accessibility/ax_window_obj_wrapper.h",
- "bubble/tray_bubble_view.h",
"controls/native/native_view_host_aura.h",
"corewm/cursor_height_provider_win.h",
"corewm/tooltip.h",
@@ -620,11 +628,11 @@ jumbo_component("views") {
sources += [
"accessibility/ax_aura_obj_cache.cc",
"accessibility/ax_aura_obj_wrapper.cc",
+ "accessibility/ax_root_obj_wrapper.cc",
"accessibility/ax_tree_source_views.cc",
"accessibility/ax_view_obj_wrapper.cc",
"accessibility/ax_widget_obj_wrapper.cc",
"accessibility/ax_window_obj_wrapper.cc",
- "bubble/tray_bubble_view.cc",
"controls/menu/display_change_listener_aura.cc",
"controls/menu/menu_pre_target_handler_aura.cc",
"controls/menu/menu_pre_target_handler_aura.h",
@@ -658,6 +666,7 @@ jumbo_component("views") {
"//services/ws/public/mojom",
"//ui/aura",
"//ui/platform_window",
+ "//ui/platform_window/platform_window_handler",
"//ui/touch_selection",
"//ui/wm",
"//ui/wm/public",
@@ -734,7 +743,9 @@ jumbo_component("views") {
"//components/crash/core/common",
"//ui/accelerated_widget_mac",
"//ui/events:dom_keycode_converter",
+ "//ui/views_bridge_mac",
]
+ public_deps += [ "//ui/views_bridge_mac:mojo" ]
libs = [
"AppKit.framework",
"CoreGraphics.framework",
@@ -1111,7 +1122,10 @@ source_set("views_unittests_sources") {
if (is_mac) {
# views_unittests not yet compiling on Mac. http://crbug.com/378134
sources -= [ "controls/native/native_view_host_unittest.cc" ]
- public_deps += [ "//ui/accelerated_widget_mac" ]
+ public_deps += [
+ "//ui/accelerated_widget_mac",
+ "//ui/views_bridge_mac:views_bridge_mac",
+ ]
}
}
@@ -1211,12 +1225,23 @@ source_set("views_interactive_ui_tests") {
"corewm/desktop_capture_controller_unittest.cc",
"widget/native_widget_aura_interactive_uitest.cc",
]
+
deps += [
"//ui/aura",
"//ui/aura:test_support",
"//ui/wm",
"//ui/wm/public",
]
+
+ if (!is_chromeos && ((is_linux && !use_x11) || is_fuchsia)) {
+ sources += [ "widget/desktop_aura/desktop_window_tree_host_platform_interactive_uitest.cc" ]
+ }
+
+ deps += [
+ "//ui/events/platform",
+ "//ui/platform_window",
+ "//ui/platform_window/platform_window_handler",
+ ]
}
if (use_x11) {
diff --git a/chromium/ui/views/DEPS b/chromium/ui/views/DEPS
index f591ea6f71c..a2d0ab1f98c 100644
--- a/chromium/ui/views/DEPS
+++ b/chromium/ui/views/DEPS
@@ -2,6 +2,7 @@ include_rules = [
"+cc/paint",
"+components/crash/core/common/crash_key.h",
"+components/vector_icons",
+ "+mojo/public/cpp/bindings",
"+services/ws/public/mojom",
"+skia/ext",
"+third_party/iaccessible2",
@@ -20,6 +21,7 @@ include_rules = [
"+ui/resources/grit/ui_resources.h",
"+ui/strings/grit/ui_strings.h",
"+ui/touch_selection",
+ "+ui/views_bridge_mac",
"+ui/wm/core",
"+ui/wm/public",
diff --git a/chromium/ui/views/OWNERS b/chromium/ui/views/OWNERS
index 4aca57c69ca..57c9ed66f82 100644
--- a/chromium/ui/views/OWNERS
+++ b/chromium/ui/views/OWNERS
@@ -10,4 +10,7 @@ per-file *_mac.*=ellyjones@chromium.org
per-file *_cocoa.*=ellyjones@chromium.org
per-file *.mm=ellyjones@chromium.org
+# If you're doing structural changes get a review from one of the OWNERS.
+per-file BUILD.gn=*
+
# COMPONENT: Internals>Views
diff --git a/chromium/ui/views/accessibility/ax_aura_obj_cache.cc b/chromium/ui/views/accessibility/ax_aura_obj_cache.cc
index 519d09c2959..5811bf26790 100644
--- a/chromium/ui/views/accessibility/ax_aura_obj_cache.cc
+++ b/chromium/ui/views/accessibility/ax_aura_obj_cache.cc
@@ -31,6 +31,9 @@ AXAuraObjCache* AXAuraObjCache::GetInstance() {
}
AXAuraObjWrapper* AXAuraObjCache::GetOrCreate(View* view) {
+ // Avoid problems with transient focus events. https://crbug.com/729449
+ if (!view->GetWidget())
+ return nullptr;
return CreateInternal<AXViewObjWrapper>(view, view_to_id_map_);
}
@@ -122,24 +125,28 @@ AXAuraObjCache::~AXAuraObjCache() {
}
View* AXAuraObjCache::GetFocusedView() {
- if (root_windows_.empty())
- return nullptr;
- aura::client::FocusClient* focus_client =
- GetFocusClient(*root_windows_.begin());
- if (!focus_client)
- return nullptr;
-
- aura::Window* focused_window = focus_client->GetFocusedWindow();
- if (!focused_window)
- return nullptr;
-
- Widget* focused_widget = Widget::GetWidgetForNativeView(focused_window);
- while (!focused_widget) {
- focused_window = focused_window->parent();
+ 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;
+
+ focused_window = focus_client->GetFocusedWindow();
if (!focused_window)
- break;
+ return nullptr;
focused_widget = Widget::GetWidgetForNativeView(focused_window);
+ while (!focused_widget) {
+ focused_window = focused_window->parent();
+ if (!focused_window)
+ break;
+
+ focused_widget = Widget::GetWidgetForNativeView(focused_window);
+ }
}
if (!focused_widget)
@@ -153,7 +160,8 @@ View* AXAuraObjCache::GetFocusedView() {
if (focused_view)
return focused_view;
- if (focused_window->GetProperty(
+ if (focused_window &&
+ focused_window->GetProperty(
aura::client::kAccessibilityFocusFallsbackToWidgetKey)) {
// If focused widget has non client view, falls back to first child view of
// its client view. We don't expect that non client view gets keyboard
diff --git a/chromium/ui/views/accessibility/ax_aura_obj_cache.h b/chromium/ui/views/accessibility/ax_aura_obj_cache.h
index f798bdb059e..3a4a448e0ed 100644
--- a/chromium/ui/views/accessibility/ax_aura_obj_cache.h
+++ b/chromium/ui/views/accessibility/ax_aura_obj_cache.h
@@ -45,8 +45,11 @@ class VIEWS_EXPORT AXAuraObjCache : public aura::client::FocusChangeObserver {
ax::mojom::Event event_type) = 0;
};
- // Get or create an entry in the cache based on an Aura view.
+ // Get or create an entry in the cache. May return null if the View is not
+ // associated with a Widget.
AXAuraObjWrapper* GetOrCreate(View* view);
+
+ // Get or create an entry in the cache.
AXAuraObjWrapper* GetOrCreate(Widget* widget);
AXAuraObjWrapper* GetOrCreate(aura::Window* window);
@@ -92,6 +95,13 @@ class VIEWS_EXPORT AXAuraObjCache : public aura::client::FocusChangeObserver {
void SetDelegate(Delegate* delegate) { delegate_ = delegate; }
+ // Changes the behavior of GetFocusedView() so that it only considers
+ // views within the given Widget, this enables making tests
+ // involving focus reliable.
+ void set_focused_widget_for_testing(views::Widget* widget) {
+ focused_widget_for_testing_ = widget;
+ }
+
private:
friend struct base::DefaultSingletonTraits<AXAuraObjCache>;
@@ -131,6 +141,8 @@ class VIEWS_EXPORT AXAuraObjCache : public aura::client::FocusChangeObserver {
std::set<aura::Window*> root_windows_;
+ views::Widget* focused_widget_for_testing_ = nullptr;
+
DISALLOW_COPY_AND_ASSIGN(AXAuraObjCache);
};
diff --git a/chromium/ui/views/accessibility/ax_root_obj_wrapper.cc b/chromium/ui/views/accessibility/ax_root_obj_wrapper.cc
new file mode 100644
index 00000000000..8f16302c7cb
--- /dev/null
+++ b/chromium/ui/views/accessibility/ax_root_obj_wrapper.cc
@@ -0,0 +1,115 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/accessibility/ax_root_obj_wrapper.h"
+
+#include <utility>
+
+#include "base/stl_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "ui/accessibility/ax_enums.mojom.h"
+#include "ui/accessibility/ax_node_data.h"
+#include "ui/aura/env.h"
+#include "ui/aura/window.h"
+#include "ui/display/display.h"
+#include "ui/display/screen.h"
+#include "ui/views/accessibility/ax_aura_obj_cache.h"
+#include "ui/views/accessibility/ax_window_obj_wrapper.h"
+
+AXRootObjWrapper::AXRootObjWrapper(views::AXAuraObjCache::Delegate* delegate)
+ : alert_window_(std::make_unique<aura::Window>(nullptr)),
+ delegate_(delegate) {
+ alert_window_->Init(ui::LAYER_NOT_DRAWN);
+#if !defined(IS_CHROMECAST)
+ aura::Env::GetInstance()->AddObserver(this);
+
+ if (display::Screen::GetScreen())
+ display::Screen::GetScreen()->AddObserver(this);
+#endif
+}
+
+AXRootObjWrapper::~AXRootObjWrapper() {
+#if !defined(IS_CHROMECAST)
+ if (display::Screen::GetScreen())
+ display::Screen::GetScreen()->RemoveObserver(this);
+
+ // If alert_window_ is nullptr already, that means OnWillDestroyEnv
+ // was already called, so we shouldn't call RemoveObserver(this) again.
+ if (!alert_window_)
+ return;
+
+ aura::Env::GetInstance()->RemoveObserver(this);
+#endif
+ alert_window_.reset();
+}
+
+views::AXAuraObjWrapper* AXRootObjWrapper::GetAlertForText(
+ const std::string& text) {
+ alert_window_->SetTitle(base::UTF8ToUTF16((text)));
+ views::AXWindowObjWrapper* window_obj =
+ static_cast<views::AXWindowObjWrapper*>(
+ views::AXAuraObjCache::GetInstance()->GetOrCreate(
+ alert_window_.get()));
+ window_obj->set_is_alert(true);
+ return window_obj;
+}
+
+bool AXRootObjWrapper::HasChild(views::AXAuraObjWrapper* child) {
+ std::vector<views::AXAuraObjWrapper*> children;
+ GetChildren(&children);
+ return base::ContainsValue(children, child);
+}
+
+bool AXRootObjWrapper::IsIgnored() {
+ return false;
+}
+
+views::AXAuraObjWrapper* AXRootObjWrapper::GetParent() {
+ return NULL;
+}
+
+void AXRootObjWrapper::GetChildren(
+ std::vector<views::AXAuraObjWrapper*>* out_children) {
+ views::AXAuraObjCache::GetInstance()->GetTopLevelWindows(out_children);
+ out_children->push_back(
+ views::AXAuraObjCache::GetInstance()->GetOrCreate(alert_window_.get()));
+}
+
+void AXRootObjWrapper::Serialize(ui::AXNodeData* out_node_data) {
+ out_node_data->id = unique_id_.Get();
+ out_node_data->role = ax::mojom::Role::kDesktop;
+
+#if !defined(IS_CHROMECAST)
+ display::Screen* screen = display::Screen::GetScreen();
+ if (!screen)
+ return;
+
+ const display::Display& display = screen->GetPrimaryDisplay();
+
+ // Utilize the display bounds to figure out if this screen is in landscape or
+ // portrait. We use this rather than |rotation| because some devices default
+ // to landscape, some in portrait. Encode landscape as horizontal state,
+ // portrait as vertical state.
+ if (display.bounds().width() > display.bounds().height())
+ out_node_data->AddState(ax::mojom::State::kHorizontal);
+ else
+ out_node_data->AddState(ax::mojom::State::kVertical);
+#endif
+}
+
+const ui::AXUniqueId& AXRootObjWrapper::GetUniqueId() const {
+ return unique_id_;
+}
+
+void AXRootObjWrapper::OnDisplayMetricsChanged(const display::Display& display,
+ uint32_t changed_metrics) {
+ delegate_->OnEvent(this, ax::mojom::Event::kLocationChanged);
+}
+
+void AXRootObjWrapper::OnWindowInitialized(aura::Window* window) {}
+
+void AXRootObjWrapper::OnWillDestroyEnv() {
+ alert_window_.reset();
+ aura::Env::GetInstance()->RemoveObserver(this);
+}
diff --git a/chromium/ui/views/accessibility/ax_root_obj_wrapper.h b/chromium/ui/views/accessibility/ax_root_obj_wrapper.h
new file mode 100644
index 00000000000..f90f9853dab
--- /dev/null
+++ b/chromium/ui/views/accessibility/ax_root_obj_wrapper.h
@@ -0,0 +1,60 @@
+// 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_VIEWS_ACCESSIBILITY_AX_ROOT_OBJ_WRAPPER_H_
+#define UI_VIEWS_ACCESSIBILITY_AX_ROOT_OBJ_WRAPPER_H_
+
+#include <stdint.h>
+
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "base/macros.h"
+#include "ui/accessibility/platform/ax_unique_id.h"
+#include "ui/aura/env_observer.h"
+#include "ui/display/display_observer.h"
+#include "ui/views/accessibility/ax_aura_obj_cache.h"
+#include "ui/views/accessibility/ax_aura_obj_wrapper.h"
+
+class VIEWS_EXPORT AXRootObjWrapper : public views::AXAuraObjWrapper,
+ display::DisplayObserver,
+ aura::EnvObserver {
+ public:
+ explicit AXRootObjWrapper(views::AXAuraObjCache::Delegate* delegate);
+ ~AXRootObjWrapper() override;
+
+ // Returns an AXAuraObjWrapper for an alert window with title set to |text|.
+ views::AXAuraObjWrapper* GetAlertForText(const std::string& text);
+
+ // Convenience method to check for existence of a child.
+ bool HasChild(views::AXAuraObjWrapper* child);
+
+ // views::AXAuraObjWrapper overrides.
+ bool IsIgnored() override;
+ views::AXAuraObjWrapper* GetParent() override;
+ void GetChildren(
+ std::vector<views::AXAuraObjWrapper*>* out_children) override;
+ void Serialize(ui::AXNodeData* out_node_data) override;
+ const ui::AXUniqueId& GetUniqueId() const override;
+
+ private:
+ // display::DisplayObserver:
+ void OnDisplayMetricsChanged(const display::Display& display,
+ uint32_t changed_metrics) override;
+
+ // aura::EnvObserver:
+ void OnWindowInitialized(aura::Window* window) override;
+ void OnWillDestroyEnv() override;
+
+ ui::AXUniqueId unique_id_;
+
+ std::unique_ptr<aura::Window> alert_window_;
+
+ views::AXAuraObjCache::Delegate* delegate_;
+
+ DISALLOW_COPY_AND_ASSIGN(AXRootObjWrapper);
+};
+
+#endif // UI_VIEWS_ACCESSIBILITY_AX_ROOT_OBJ_WRAPPER_H_
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 84b893fca7f..aa9e497e6b1 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
@@ -21,6 +21,7 @@
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gl/test/gl_surface_test_support.h"
+#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/controls/textfield/textfield_test_api.h"
#include "ui/views/test/widget_test.h"
@@ -74,6 +75,132 @@ class AXSystemCaretWinTest : public test::WidgetTest {
DISALLOW_COPY_AND_ASSIGN(AXSystemCaretWinTest);
};
+class WinAccessibilityCaretEventMonitor {
+ public:
+ WinAccessibilityCaretEventMonitor(UINT event_min, UINT event_max);
+ ~WinAccessibilityCaretEventMonitor();
+
+ // Blocks until the next event is received. When it's received, it
+ // queries accessibility information about the object that fired the
+ // event and populates the event, hwnd, role, state, and name in the
+ // passed arguments.
+ void WaitForNextEvent(DWORD* out_event, UINT* out_role, UINT* out_state);
+
+ private:
+ void OnWinEventHook(HWINEVENTHOOK handle,
+ DWORD event,
+ HWND hwnd,
+ LONG obj_id,
+ LONG child_id,
+ DWORD event_thread,
+ DWORD event_time);
+
+ static void CALLBACK WinEventHookThunk(HWINEVENTHOOK handle,
+ DWORD event,
+ HWND hwnd,
+ LONG obj_id,
+ LONG child_id,
+ DWORD event_thread,
+ DWORD event_time);
+
+ struct EventInfo {
+ DWORD event;
+ HWND hwnd;
+ LONG obj_id;
+ LONG child_id;
+ };
+
+ base::circular_deque<EventInfo> event_queue_;
+ base::RunLoop loop_runner_;
+ HWINEVENTHOOK win_event_hook_handle_;
+ static WinAccessibilityCaretEventMonitor* instance_;
+
+ DISALLOW_COPY_AND_ASSIGN(WinAccessibilityCaretEventMonitor);
+};
+
+// static
+WinAccessibilityCaretEventMonitor*
+ WinAccessibilityCaretEventMonitor::instance_ = NULL;
+
+WinAccessibilityCaretEventMonitor::WinAccessibilityCaretEventMonitor(
+ UINT event_min,
+ UINT event_max) {
+ CHECK(!instance_) << "There can be only one instance of"
+ << " WinAccessibilityCaretEventMonitor at a time.";
+ instance_ = this;
+ win_event_hook_handle_ =
+ SetWinEventHook(event_min, event_max, NULL,
+ &WinAccessibilityCaretEventMonitor::WinEventHookThunk,
+ GetCurrentProcessId(),
+ 0, // Hook all threads
+ WINEVENT_OUTOFCONTEXT);
+}
+
+WinAccessibilityCaretEventMonitor::~WinAccessibilityCaretEventMonitor() {
+ UnhookWinEvent(win_event_hook_handle_);
+ instance_ = NULL;
+}
+
+void WinAccessibilityCaretEventMonitor::WaitForNextEvent(DWORD* out_event,
+ UINT* out_role,
+ UINT* out_state) {
+ if (event_queue_.empty())
+ loop_runner_.Run();
+
+ EventInfo event_info = event_queue_.front();
+ event_queue_.pop_front();
+
+ *out_event = event_info.event;
+
+ Microsoft::WRL::ComPtr<IAccessible> acc_obj;
+ base::win::ScopedVariant child_variant;
+ CHECK(S_OK == AccessibleObjectFromEvent(
+ event_info.hwnd, event_info.obj_id, event_info.child_id,
+ acc_obj.GetAddressOf(), child_variant.Receive()));
+
+ base::win::ScopedVariant role_variant;
+ if (S_OK == acc_obj->get_accRole(child_variant, role_variant.Receive()))
+ *out_role = V_I4(role_variant.ptr());
+ else
+ *out_role = 0;
+
+ base::win::ScopedVariant state_variant;
+ if (S_OK == acc_obj->get_accState(child_variant, state_variant.Receive()))
+ *out_state = V_I4(state_variant.ptr());
+ else
+ *out_state = 0;
+}
+
+void WinAccessibilityCaretEventMonitor::OnWinEventHook(HWINEVENTHOOK handle,
+ DWORD event,
+ HWND hwnd,
+ LONG obj_id,
+ LONG child_id,
+ DWORD event_thread,
+ DWORD event_time) {
+ EventInfo event_info;
+ event_info.event = event;
+ event_info.hwnd = hwnd;
+ event_info.obj_id = obj_id;
+ event_info.child_id = child_id;
+ event_queue_.push_back(event_info);
+ loop_runner_.Quit();
+}
+
+// static
+void CALLBACK
+WinAccessibilityCaretEventMonitor::WinEventHookThunk(HWINEVENTHOOK handle,
+ DWORD event,
+ HWND hwnd,
+ LONG obj_id,
+ LONG child_id,
+ DWORD event_thread,
+ DWORD event_time) {
+ if (instance_ && obj_id == OBJID_CARET) {
+ instance_->OnWinEventHook(handle, event, hwnd, obj_id, child_id,
+ event_thread, event_time);
+ }
+}
} // namespace
TEST_F(AXSystemCaretWinTest, DISABLED_TestOnCaretBoundsChangeInTextField) {
@@ -183,4 +310,81 @@ TEST_F(AXSystemCaretWinTest, DISABLED_TestMovingWindow) {
EXPECT_EQ(height, height3);
}
+TEST_F(AXSystemCaretWinTest, DISABLED_TestCaretMSAAEvents) {
+ TextfieldTestApi textfield_test_api(textfield_);
+ Microsoft::WRL::ComPtr<IAccessible> caret_accessible;
+ gfx::NativeWindow native_window = widget_->GetNativeWindow();
+ ASSERT_NE(nullptr, native_window);
+ HWND hwnd = native_window->GetHost()->GetAcceleratedWidget();
+ EXPECT_HRESULT_SUCCEEDED(AccessibleObjectFromWindow(
+ hwnd, static_cast<DWORD>(OBJID_CARET), IID_IAccessible,
+ reinterpret_cast<void**>(caret_accessible.GetAddressOf())));
+
+ DWORD event;
+ UINT role;
+ UINT state;
+
+ {
+ // Set caret to start of textfield.
+ WinAccessibilityCaretEventMonitor monitor(EVENT_OBJECT_SHOW,
+ EVENT_OBJECT_LOCATIONCHANGE);
+ textfield_test_api.ExecuteTextEditCommand(
+ ui::TextEditCommand::MOVE_TO_BEGINNING_OF_DOCUMENT);
+ monitor.WaitForNextEvent(&event, &role, &state);
+ ASSERT_EQ(event, static_cast<DWORD>(EVENT_OBJECT_LOCATIONCHANGE))
+ << "Event should be EVENT_OBJECT_LOCATIONCHANGE";
+ ASSERT_EQ(role, static_cast<UINT>(ROLE_SYSTEM_CARET))
+ << "Role should be ROLE_SYSTEM_CARET";
+ ASSERT_EQ(state, static_cast<UINT>(0)) << "State should be 0";
+ }
+
+ {
+ // Set caret to end of textfield.
+ WinAccessibilityCaretEventMonitor monitor(EVENT_OBJECT_SHOW,
+ EVENT_OBJECT_LOCATIONCHANGE);
+ textfield_test_api.ExecuteTextEditCommand(
+ ui::TextEditCommand::MOVE_TO_END_OF_DOCUMENT);
+ monitor.WaitForNextEvent(&event, &role, &state);
+ ASSERT_EQ(event, static_cast<DWORD>(EVENT_OBJECT_LOCATIONCHANGE))
+ << "Event should be EVENT_OBJECT_LOCATIONCHANGE";
+ ASSERT_EQ(role, static_cast<UINT>(ROLE_SYSTEM_CARET))
+ << "Role should be ROLE_SYSTEM_CARET";
+ ASSERT_EQ(state, static_cast<UINT>(0)) << "State should be 0";
+ }
+
+ {
+ // Move focus to a button.
+ LabelButton button(nullptr, base::string16());
+ button.SetBounds(500, 0, 200, 20);
+ widget_->GetRootView()->AddChildView(&button);
+ test::WidgetActivationWaiter waiter(widget_, true);
+ WinAccessibilityCaretEventMonitor monitor(EVENT_OBJECT_SHOW,
+ EVENT_OBJECT_LOCATIONCHANGE);
+ widget_->Show();
+ waiter.Wait();
+ button.SetFocusBehavior(View::FocusBehavior::ALWAYS);
+ button.RequestFocus();
+ monitor.WaitForNextEvent(&event, &role, &state);
+ ASSERT_EQ(event, static_cast<DWORD>(EVENT_OBJECT_HIDE))
+ << "Event should be EVENT_OBJECT_HIDE";
+ ASSERT_EQ(role, static_cast<UINT>(ROLE_SYSTEM_CARET))
+ << "Role should be ROLE_SYSTEM_CARET";
+ ASSERT_EQ(state, static_cast<UINT>(STATE_SYSTEM_INVISIBLE))
+ << "State should be STATE_SYSTEM_INVISIBLE";
+ }
+
+ {
+ // Move focus back to the text field.
+ WinAccessibilityCaretEventMonitor monitor(EVENT_OBJECT_SHOW,
+ EVENT_OBJECT_LOCATIONCHANGE);
+ textfield_->RequestFocus();
+ monitor.WaitForNextEvent(&event, &role, &state);
+ ASSERT_EQ(event, static_cast<DWORD>(EVENT_OBJECT_SHOW))
+ << "Event should be EVENT_OBJECT_SHOW";
+ ASSERT_EQ(role, static_cast<UINT>(ROLE_SYSTEM_CARET))
+ << "Role should be ROLE_SYSTEM_CARET";
+ ASSERT_EQ(state, static_cast<UINT>(0)) << "State should be 0";
+ }
+}
+
} // namespace views
diff --git a/chromium/ui/views/accessibility/ax_window_obj_wrapper.cc b/chromium/ui/views/accessibility/ax_window_obj_wrapper.cc
index b8ea4c3c754..cd77dabfd1b 100644
--- a/chromium/ui/views/accessibility/ax_window_obj_wrapper.cc
+++ b/chromium/ui/views/accessibility/ax_window_obj_wrapper.cc
@@ -9,6 +9,7 @@
#include "base/strings/utf_string_conversions.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
+#include "ui/accessibility/ax_tree_id.h"
#include "ui/accessibility/platform/aura_window_properties.h"
#include "ui/accessibility/platform/ax_unique_id.h"
#include "ui/aura/client/focus_client.h"
@@ -96,9 +97,9 @@ void AXWindowObjWrapper::Serialize(ui::AXNodeData* out_node_data) {
if (!window_->IsVisible())
out_node_data->AddState(ax::mojom::State::kInvisible);
out_node_data->location = gfx::RectF(window_->GetBoundsInScreen());
- ui::AXTreeIDRegistry::AXTreeID child_ax_tree_id =
- window_->GetProperty(ui::kChildAXTreeID);
- if (child_ax_tree_id != ui::AXTreeIDRegistry::kNoAXTreeID) {
+ 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.
@@ -110,8 +111,8 @@ void AXWindowObjWrapper::Serialize(ui::AXNodeData* out_node_data) {
return;
}
- out_node_data->AddIntAttribute(ax::mojom::IntAttribute::kChildTreeId,
- child_ax_tree_id);
+ out_node_data->AddStringAttribute(ax::mojom::StringAttribute::kChildTreeId,
+ *child_ax_tree_id_ptr);
}
}
diff --git a/chromium/ui/views/accessibility/view_accessibility_utils.cc b/chromium/ui/views/accessibility/view_accessibility_utils.cc
new file mode 100644
index 00000000000..9663921aec7
--- /dev/null
+++ b/chromium/ui/views/accessibility/view_accessibility_utils.cc
@@ -0,0 +1,44 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/accessibility/view_accessibility_utils.h"
+
+#include "ui/views/view.h"
+#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_delegate.h"
+
+namespace views {
+
+// static
+Widget* ViewAccessibilityUtils::GetFocusedChildWidgetForAccessibility(
+ const View* view) {
+ const FocusManager* focus_manager = view->GetFocusManager();
+ if (!focus_manager)
+ return nullptr;
+ const View* focused_view = view->GetFocusManager()->GetFocusedView();
+ if (!focused_view)
+ return nullptr;
+
+ std::set<Widget*> child_widgets;
+ Widget::GetAllOwnedWidgets(view->GetWidget()->GetNativeView(),
+ &child_widgets);
+ for (auto iter = child_widgets.begin(); iter != child_widgets.end(); ++iter) {
+ Widget* child_widget = *iter;
+ DCHECK_NE(view->GetWidget(), child_widget);
+
+ if (IsFocusedChildWidget(child_widget, focused_view))
+ return child_widget;
+ }
+
+ return nullptr;
+}
+
+// static
+bool ViewAccessibilityUtils::IsFocusedChildWidget(Widget* widget,
+ const View* focused_view) {
+ return widget->IsVisible() &&
+ widget->GetContentsView()->Contains(focused_view);
+};
+
+} // namespace views
diff --git a/chromium/ui/views/accessibility/view_accessibility_utils.h b/chromium/ui/views/accessibility/view_accessibility_utils.h
new file mode 100644
index 00000000000..24c1a324b14
--- /dev/null
+++ b/chromium/ui/views/accessibility/view_accessibility_utils.h
@@ -0,0 +1,29 @@
+// 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_VIEWS_ACCESSIBILITY_VIEW_ACCESSIBILITY_UTILS_H_
+#define UI_VIEWS_ACCESSIBILITY_VIEW_ACCESSIBILITY_UTILS_H_
+
+#include "ui/views/view.h"
+#include "ui/views/widget/widget.h"
+
+namespace views {
+
+class VIEWS_EXPORT ViewAccessibilityUtils {
+ public:
+ // Returns a focused child widget if the view has a child that should be
+ // treated as a special case. For example, if a tab modal dialog is visible
+ // and focused, this will return the dialog when called on the BrowserView.
+ // This helper function is used to treat such widgets as separate windows for
+ // accessibility. Returns nullptr if no such widget is present.
+ static Widget* GetFocusedChildWidgetForAccessibility(const View* view);
+
+ // Used by GetFocusedChildWidgetForAccessibility to determine if a Widget
+ // should be handled separately.
+ static bool IsFocusedChildWidget(Widget* widget, const View* focused_view);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_ACCESSIBILITY_VIEW_ACCESSIBILITY_UTILS_H_
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 10cc9408045..adc4575fd6e 100644
--- a/chromium/ui/views/accessibility/view_ax_platform_node_delegate.cc
+++ b/chromium/ui/views/accessibility/view_ax_platform_node_delegate.cc
@@ -9,12 +9,15 @@
#include "base/lazy_instance.h"
#include "base/threading/thread_task_runner_handle.h"
+#include "ui/accessibility/ax_role_properties.h"
#include "ui/accessibility/platform/ax_platform_node.h"
#include "ui/events/event_utils.h"
#include "ui/gfx/native_widget_types.h"
+#include "ui/views/accessibility/view_accessibility_utils.h"
#include "ui/views/controls/native/native_view_host.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_delegate.h"
namespace views {
@@ -146,7 +149,7 @@ void ViewAXPlatformNodeDelegate::NotifyAccessibilityEvent(
OnMenuEnd();
break;
case ax::mojom::Event::kSelection:
- if (menu_depth_ && GetData().role == ax::mojom::Role::kMenuItem)
+ if (menu_depth_ && ui::IsMenuItem(GetData().role))
OnMenuItemActive();
break;
case ax::mojom::Event::kFocusContext: {
@@ -227,7 +230,12 @@ int ViewAXPlatformNodeDelegate::GetChildCount() {
int child_count = view()->child_count();
std::vector<Widget*> child_widgets;
- PopulateChildWidgetVector(&child_widgets);
+ bool is_tab_modal_showing;
+ PopulateChildWidgetVector(&child_widgets, &is_tab_modal_showing);
+ if (is_tab_modal_showing) {
+ DCHECK_EQ(child_widgets.size(), 1ULL);
+ return 1;
+ }
child_count += child_widgets.size();
return child_count;
@@ -239,7 +247,16 @@ gfx::NativeViewAccessible ViewAXPlatformNodeDelegate::ChildAtIndex(int index) {
// If this is a root view, our widget might have child widgets. Include
std::vector<Widget*> child_widgets;
- PopulateChildWidgetVector(&child_widgets);
+ bool is_tab_modal_showing;
+ PopulateChildWidgetVector(&child_widgets, &is_tab_modal_showing);
+
+ // If a visible tab modal dialog is present, ignore |index| and return the
+ // dialog.
+ if (is_tab_modal_showing) {
+ DCHECK_EQ(child_widgets.size(), 1ULL);
+ return child_widgets[0]->GetRootView()->GetNativeViewAccessible();
+ }
+
int child_widget_count = static_cast<int>(child_widgets.size());
if (index < view()->child_count()) {
@@ -290,7 +307,8 @@ gfx::NativeViewAccessible ViewAXPlatformNodeDelegate::HitTestSync(int x,
// Search child widgets first, since they're on top in the z-order.
std::vector<Widget*> child_widgets;
- PopulateChildWidgetVector(&child_widgets);
+ bool is_tab_modal_showing;
+ PopulateChildWidgetVector(&child_widgets, &is_tab_modal_showing);
for (Widget* child_widget : child_widgets) {
View* child_root_view = child_widget->GetRootView();
gfx::Point point(x, y);
@@ -358,13 +376,20 @@ const ui::AXUniqueId& ViewAXPlatformNodeDelegate::GetUniqueId() const {
}
void ViewAXPlatformNodeDelegate::PopulateChildWidgetVector(
- std::vector<Widget*>* result_child_widgets) {
+ std::vector<Widget*>* result_child_widgets,
+ bool* is_tab_modal_showing) {
// Only attach child widgets to the root view.
Widget* widget = view()->GetWidget();
// Note that during window close, a Widget may exist in a state where it has
// no NativeView, but hasn't yet torn down its view hierarchy.
- if (!widget || !widget->GetNativeView() || widget->GetRootView() != view())
+ if (!widget || !widget->GetNativeView() || widget->GetRootView() != view()) {
+ *is_tab_modal_showing = false;
return;
+ }
+
+ const views::FocusManager* focus_manager = view()->GetFocusManager();
+ const views::View* focused_view =
+ focus_manager ? focus_manager->GetFocusedView() : nullptr;
std::set<Widget*> child_widgets;
Widget::GetAllOwnedWidgets(widget->GetNativeView(), &child_widgets);
@@ -378,8 +403,19 @@ void ViewAXPlatformNodeDelegate::PopulateChildWidgetVector(
if (widget->GetNativeWindowProperty(kWidgetNativeViewHostKey))
continue;
+ // Focused child widgets should take the place of the web page they cover in
+ // the accessibility tree.
+ if (ViewAccessibilityUtils::IsFocusedChildWidget(child_widget,
+ focused_view)) {
+ result_child_widgets->clear();
+ result_child_widgets->push_back(child_widget);
+ *is_tab_modal_showing = true;
+ return;
+ }
+
result_child_widgets->push_back(child_widget);
}
+ *is_tab_modal_showing = false;
}
} // namespace views
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 f3829054acc..8dea736b61f 100644
--- a/chromium/ui/views/accessibility/view_ax_platform_node_delegate.h
+++ b/chromium/ui/views/accessibility/view_ax_platform_node_delegate.h
@@ -63,7 +63,11 @@ class VIEWS_EXPORT ViewAXPlatformNodeDelegate
explicit ViewAXPlatformNodeDelegate(View* view);
private:
- void PopulateChildWidgetVector(std::vector<Widget*>* result_child_widgets);
+ // |is_tab_modal_showing| is set to true if, instead of populating
+ // |result_child_widgets| normally, a single child widget was returned (e.g. a
+ // dialog that should be read instead of the rest of the page contents).
+ void PopulateChildWidgetVector(std::vector<Widget*>* result_child_widgets,
+ bool* is_tab_modal_showing);
void OnMenuItemActive();
void OnMenuStart();
diff --git a/chromium/ui/views/accessible_pane_view.cc b/chromium/ui/views/accessible_pane_view.cc
index cfd86c97ac1..a0b033b19fd 100644
--- a/chromium/ui/views/accessible_pane_view.cc
+++ b/chromium/ui/views/accessible_pane_view.cc
@@ -174,6 +174,9 @@ bool AccessiblePaneView::AcceleratorPressed(
case ui::VKEY_ESCAPE: {
RemovePaneFocus();
View* last_focused_view = last_focused_view_tracker_->view();
+ // Ignore |last_focused_view| if it's no longer in the same widget.
+ if (last_focused_view && GetWidget() != last_focused_view->GetWidget())
+ last_focused_view = nullptr;
if (last_focused_view) {
focus_manager_->SetFocusedViewWithReason(
last_focused_view, FocusManager::kReasonFocusRestore);
diff --git a/chromium/ui/views/accessible_pane_view_unittest.cc b/chromium/ui/views/accessible_pane_view_unittest.cc
index 7aef74a3bbe..f8e88ebfb46 100644
--- a/chromium/ui/views/accessible_pane_view_unittest.cc
+++ b/chromium/ui/views/accessible_pane_view_unittest.cc
@@ -206,7 +206,7 @@ TEST_F(AccessiblePaneViewTest, PaneFocusTraversal) {
EXPECT_TRUE(original_test_view->SetPaneFocus(
original_test_view->third_child_button()));
- // Test travesal in second view.
+ // Test traversal in second view.
// Set pane focus on second child.
EXPECT_TRUE(test_view->SetPaneFocus(test_view->second_child_button()));
// home
@@ -234,4 +234,35 @@ TEST_F(AccessiblePaneViewTest, PaneFocusTraversal) {
widget->CloseNow();
widget.reset();
}
+
+TEST_F(AccessiblePaneViewTest, DoesntCrashOnEscapeWithRemovedView) {
+ TestBarView* test_view1 = new TestBarView();
+ TestBarView* test_view2 = new TestBarView();
+ Widget widget;
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.bounds = gfx::Rect(50, 50, 650, 650);
+ widget.Init(params);
+ View* root = widget.GetRootView();
+ root->AddChildView(test_view1);
+ root->AddChildView(test_view2);
+ widget.Show();
+ widget.Activate();
+
+ View* v1 = test_view1->child_button();
+ View* v2 = test_view2->child_button();
+ // Do the following:
+ // 1. focus |v1|.
+ // 2. focus |v2|. This makes |test_view2| remember |v1| as having focus.
+ // 3. Removes |v1| from it's parent.
+ // 4. Presses escape on |test_view2|. Escape attempts to revert focus to |v1|
+ // (because of step 2). Because |v1| is not in a widget this should not
+ // attempt to focus anything.
+ EXPECT_TRUE(test_view1->SetPaneFocus(v1));
+ EXPECT_TRUE(test_view2->SetPaneFocus(v2));
+ v1->parent()->RemoveChildView(v1);
+ // This shouldn't hit a CHECK in the FocusManager.
+ EXPECT_TRUE(test_view2->AcceleratorPressed(test_view2->escape_key()));
+}
+
} // namespace views
diff --git a/chromium/ui/views/animation/ink_drop_host_view.cc b/chromium/ui/views/animation/ink_drop_host_view.cc
index f21c750bd1f..b98691b786e 100644
--- a/chromium/ui/views/animation/ink_drop_host_view.cc
+++ b/chromium/ui/views/animation/ink_drop_host_view.cc
@@ -16,6 +16,7 @@
#include "ui/views/animation/ink_drop_stub.h"
#include "ui/views/animation/square_ink_drop_ripple.h"
#include "ui/views/style/platform_style.h"
+#include "ui/views/view_properties.h"
namespace views {
namespace {
@@ -170,6 +171,9 @@ std::unique_ptr<InkDropHighlight> InkDropHostView::CreateInkDropHighlight()
}
std::unique_ptr<views::InkDropMask> InkDropHostView::CreateInkDropMask() const {
+ if (gfx::Path* highlight_path = GetProperty(kHighlightPathKey))
+ return std::make_unique<views::PathInkDropMask>(size(), *highlight_path);
+
return nullptr;
}
diff --git a/chromium/ui/views/animation/ink_drop_mask.cc b/chromium/ui/views/animation/ink_drop_mask.cc
index a2d2adb366e..63c93c61b4a 100644
--- a/chromium/ui/views/animation/ink_drop_mask.cc
+++ b/chromium/ui/views/animation/ink_drop_mask.cc
@@ -75,4 +75,20 @@ void CircleInkDropMask::OnPaintLayer(const ui::PaintContext& context) {
recorder.canvas()->DrawCircle(mask_center_, mask_radius_, flags);
}
+// PathInkDropMask
+
+PathInkDropMask::PathInkDropMask(const gfx::Size& layer_size,
+ const gfx::Path& path)
+ : InkDropMask(layer_size), path_(path) {}
+
+void PathInkDropMask::OnPaintLayer(const ui::PaintContext& context) {
+ cc::PaintFlags flags;
+ flags.setAlpha(255);
+ flags.setStyle(cc::PaintFlags::kFill_Style);
+ flags.setAntiAlias(true);
+
+ ui::PaintRecorder recorder(context, layer()->size());
+ recorder.canvas()->DrawPath(path_, flags);
+}
+
} // namespace views
diff --git a/chromium/ui/views/animation/ink_drop_mask.h b/chromium/ui/views/animation/ink_drop_mask.h
index debfb1604e2..1a3fa87e066 100644
--- a/chromium/ui/views/animation/ink_drop_mask.h
+++ b/chromium/ui/views/animation/ink_drop_mask.h
@@ -11,6 +11,7 @@
#include "ui/gfx/geometry/insets_f.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/path.h"
#include "ui/views/views_export.h"
namespace views {
@@ -33,7 +34,7 @@ class VIEWS_EXPORT InkDropMask : public ui::LayerDelegate {
explicit InkDropMask(const gfx::Size& layer_size);
private:
- // Overriden from ui::LayerDelegate:
+ // ui::LayerDelegate:
void OnDeviceScaleFactorChanged(float old_device_scale_factor,
float new_device_scale_factor) override;
@@ -50,7 +51,7 @@ class VIEWS_EXPORT RoundRectInkDropMask : public InkDropMask {
float corner_radius);
private:
- // Overriden from InkDropMask:
+ // InkDropMask:
void OnPaintLayer(const ui::PaintContext& context) override;
gfx::InsetsF mask_insets_;
@@ -67,7 +68,7 @@ class VIEWS_EXPORT CircleInkDropMask : public InkDropMask {
int mask_radius);
private:
- // Overriden from InkDropMask:
+ // InkDropMask:
void OnPaintLayer(const ui::PaintContext& context) override;
gfx::Point mask_center_;
@@ -76,6 +77,20 @@ class VIEWS_EXPORT CircleInkDropMask : public InkDropMask {
DISALLOW_COPY_AND_ASSIGN(CircleInkDropMask);
};
+// An ink-drop mask that paints a specified path.
+class VIEWS_EXPORT PathInkDropMask : public InkDropMask {
+ public:
+ PathInkDropMask(const gfx::Size& layer_size, const gfx::Path& path);
+
+ private:
+ // InkDropMask:
+ void OnPaintLayer(const ui::PaintContext& context) override;
+
+ gfx::Path path_;
+
+ DISALLOW_COPY_AND_ASSIGN(PathInkDropMask);
+};
+
} // namespace views
#endif // UI_VIEWS_ANIMATION_INK_DROP_MASK_H_
diff --git a/chromium/ui/views/bubble/OWNERS b/chromium/ui/views/bubble/OWNERS
index f04407c0829..d17d1b2257c 100644
--- a/chromium/ui/views/bubble/OWNERS
+++ b/chromium/ui/views/bubble/OWNERS
@@ -1,4 +1,3 @@
msw@chromium.org
-per-file tray_bubble_view.*=stevenjb@chromium.org
# COMPONENT: UI>Browser>Bubbles
diff --git a/chromium/ui/views/bubble/bubble_border.cc b/chromium/ui/views/bubble/bubble_border.cc
index 9fc042cd02f..88e4653b928 100644
--- a/chromium/ui/views/bubble/bubble_border.cc
+++ b/chromium/ui/views/bubble/bubble_border.cc
@@ -14,6 +14,7 @@
#include "third_party/skia/include/core/SkPath.h"
#include "ui/base/material_design/material_design_controller.h"
#include "ui/base/resource/resource_bundle.h"
+#include "ui/gfx/color_palette.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/path.h"
#include "ui/gfx/scoped_canvas.h"
@@ -127,7 +128,8 @@ gfx::Rect BubbleBorder::GetBounds(const gfx::Rect& anchor_rect,
}
// With NO_ASSETS, there should be further insets, but the same logic is
// used to position the bubble origin according to |anchor_rect|.
- DCHECK(shadow_ != NO_ASSETS || shadow_insets.IsEmpty());
+ DCHECK((shadow_ != NO_ASSETS && shadow_ != NO_SHADOW) ||
+ shadow_insets.IsEmpty());
contents_bounds.Inset(-shadow_insets);
// |arrow_offset_| is used to adjust bubbles that would normally be
// partially offscreen.
@@ -177,6 +179,9 @@ void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) {
if (shadow_ == NO_ASSETS)
return PaintNoAssets(view, canvas);
+ if (shadow_ == NO_SHADOW)
+ return PaintNoShadow(view, canvas);
+
gfx::ScopedCanvas scoped(canvas);
SkRRect r_rect = GetClientRect(view);
@@ -188,9 +193,11 @@ void BubbleBorder::Paint(const views::View& view, gfx::Canvas* canvas) {
}
gfx::Insets BubbleBorder::GetInsets() const {
- return (shadow_ == NO_ASSETS)
- ? gfx::Insets()
- : GetBorderAndShadowInsets(md_shadow_elevation_);
+ if (shadow_ == NO_ASSETS)
+ return gfx::Insets();
+ if (shadow_ == NO_SHADOW)
+ return gfx::Insets(kBorderThicknessDip);
+ return GetBorderAndShadowInsets(md_shadow_elevation_);
}
gfx::Size BubbleBorder::GetMinimumSize() const {
@@ -247,8 +254,8 @@ const cc::PaintFlags& BubbleBorder::GetBorderAndShadowFlags(
return flag_map->find(key)->second;
cc::PaintFlags flags;
- constexpr SkColor kBorderColor = SkColorSetA(SK_ColorBLACK, 0x26);
- flags.setColor(kBorderColor);
+ constexpr SkColor kBlurredBorderColor = SkColorSetA(SK_ColorBLACK, 0x26);
+ flags.setColor(kBlurredBorderColor);
flags.setAntiAlias(true);
flags.setLooper(
gfx::CreateShadowDrawLooper(GetShadowValues(elevation, color)));
@@ -280,6 +287,18 @@ void BubbleBorder::PaintNoAssets(const View& view, gfx::Canvas* canvas) {
canvas->sk_canvas()->drawColor(SK_ColorTRANSPARENT, SkBlendMode::kSrc);
}
+void BubbleBorder::PaintNoShadow(const View& view, gfx::Canvas* canvas) {
+ gfx::RectF bounds(view.GetLocalBounds());
+ bounds.Inset(gfx::InsetsF(kBorderThicknessDip / 2.0f));
+ cc::PaintFlags flags;
+ flags.setAntiAlias(true);
+ flags.setStyle(cc::PaintFlags::kStroke_Style);
+ flags.setStrokeWidth(kBorderThicknessDip);
+ constexpr SkColor kBorderColor = gfx::kGoogleGrey600;
+ flags.setColor(kBorderColor);
+ canvas->DrawRoundRect(bounds, GetBorderCornerRadius(), flags);
+}
+
void BubbleBackground::Paint(gfx::Canvas* canvas, views::View* view) const {
if (border_->shadow() == BubbleBorder::NO_SHADOW_OPAQUE_BORDER)
canvas->DrawColor(border_->background_color());
diff --git a/chromium/ui/views/bubble/bubble_border.h b/chromium/ui/views/bubble/bubble_border.h
index d4a6e2a28a7..79c182cffd1 100644
--- a/chromium/ui/views/bubble/bubble_border.h
+++ b/chromium/ui/views/bubble/bubble_border.h
@@ -229,6 +229,9 @@ class VIEWS_EXPORT BubbleBorder : public Border {
// to make the window shape based on insets and GetBorderCornerRadius().
void PaintNoAssets(const View& view, gfx::Canvas* canvas);
+ // Paint for the NO_SHADOW shadow type. This paints a simple line border.
+ void PaintNoShadow(const View& view, gfx::Canvas* canvas);
+
Arrow arrow_;
int arrow_offset_;
// Corner radius for the bubble border. If supplied the border will use
diff --git a/chromium/ui/views/bubble/bubble_border_unittest.cc b/chromium/ui/views/bubble/bubble_border_unittest.cc
index e1420089ab5..54476123fc1 100644
--- a/chromium/ui/views/bubble/bubble_border_unittest.cc
+++ b/chromium/ui/views/bubble/bubble_border_unittest.cc
@@ -314,6 +314,9 @@ TEST_F(BubbleBorderTest, GetBoundsOriginTest) {
const int kStrokeWidth =
shadow == BubbleBorder::NO_ASSETS ? 0 : BubbleBorder::kStroke;
+ const int kBorderedContentHeight =
+ kContentSize.height() + (2 * kStrokeWidth);
+
const int kTopHorizArrowY = kAnchor.bottom() + kStrokeWidth - kInsets.top();
const int kBottomHorizArrowY = kAnchor.y() - kTotalSize.height();
const int kLeftVertArrowX = kAnchor.x() + kAnchor.width();
@@ -338,9 +341,9 @@ TEST_F(BubbleBorderTest, GetBoundsOriginTest) {
// Vertical arrow tests.
{BubbleBorder::LEFT_TOP, kLeftVertArrowX, kAnchor.y() + kStrokeWidth},
{BubbleBorder::LEFT_CENTER,
- kLeftVertArrowX - (kInsets.right() - kStrokeWidth),
- kAnchor.CenterPoint().y() - (kTotalSize.height() / 2) +
- (2 * kStrokeWidth)},
+ kLeftVertArrowX - (kInsets.left() - kStrokeWidth),
+ kAnchor.CenterPoint().y() - (kBorderedContentHeight / 2) -
+ (kInsets.top() - kStrokeWidth)},
{BubbleBorder::RIGHT_BOTTOM, kRightVertArrowX,
kAnchor.y() + kAnchor.height() - kTotalSize.height() - kStrokeWidth},
diff --git a/chromium/ui/views/bubble/bubble_dialog_delegate_view.cc b/chromium/ui/views/bubble/bubble_dialog_delegate_view.cc
index 84d9ade9513..434ae1ea7db 100644
--- a/chromium/ui/views/bubble/bubble_dialog_delegate_view.cc
+++ b/chromium/ui/views/bubble/bubble_dialog_delegate_view.cc
@@ -17,7 +17,6 @@
#include "ui/views/layout/layout_manager.h"
#include "ui/views/layout/layout_provider.h"
#include "ui/views/view_properties.h"
-#include "ui/views/view_tracker.h"
#include "ui/views/views_delegate.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
@@ -51,17 +50,30 @@ class BubbleDialogFrameView : public BubbleFrameView {
DISALLOW_COPY_AND_ASSIGN(BubbleDialogFrameView);
};
+bool CustomShadowsSupported() {
+#if defined(OS_WIN)
+ return ui::win::IsAeroGlassEnabled();
+#else
+ return true;
+#endif
+}
+
// Create a widget to host the bubble.
Widget* CreateBubbleWidget(BubbleDialogDelegateView* bubble) {
Widget* bubble_widget = new Widget();
Widget::InitParams bubble_params(Widget::InitParams::TYPE_BUBBLE);
bubble_params.delegate = bubble;
- bubble_params.opacity = Widget::InitParams::TRANSLUCENT_WINDOW;
+ bubble_params.opacity = CustomShadowsSupported()
+ ? Widget::InitParams::TRANSLUCENT_WINDOW
+ : Widget::InitParams::OPAQUE_WINDOW;
bubble_params.accept_events = bubble->accept_events();
// Use a window default shadow if the bubble doesn't provides its own.
- bubble_params.shadow_type = bubble->shadow() == BubbleBorder::NO_ASSETS
- ? Widget::InitParams::SHADOW_TYPE_DEFAULT
- : Widget::InitParams::SHADOW_TYPE_NONE;
+ if (bubble->GetShadow() == BubbleBorder::NO_ASSETS)
+ bubble_params.shadow_type = Widget::InitParams::SHADOW_TYPE_DEFAULT;
+ else if (CustomShadowsSupported())
+ bubble_params.shadow_type = Widget::InitParams::SHADOW_TYPE_NONE;
+ else
+ bubble_params.shadow_type = Widget::InitParams::SHADOW_TYPE_DROP;
if (bubble->parent_window())
bubble_params.parent = bubble->parent_window();
else if (bubble->anchor_widget())
@@ -102,12 +114,7 @@ Widget* BubbleDialogDelegateView::CreateBubble(
bubble_delegate->SetAnchorView(bubble_delegate->GetAnchorView());
Widget* bubble_widget = CreateBubbleWidget(bubble_delegate);
-#if defined(OS_WIN)
- // If glass is enabled, the bubble is allowed to extend outside the bounds of
- // the parent frame and let DWM handle compositing. If not, then we don't
- // want to allow the bubble to extend the frame because it will be clipped.
- bubble_delegate->set_adjust_if_offscreen(ui::win::IsAeroGlassEnabled());
-#elif (defined(OS_LINUX) && !defined(OS_CHROMEOS)) || defined(OS_MACOSX)
+#if (defined(OS_LINUX) && !defined(OS_CHROMEOS)) || defined(OS_MACOSX)
// Linux clips bubble windows that extend outside their parent window bounds.
// Mac never adjusts.
bubble_delegate->set_adjust_if_offscreen(false);
@@ -145,7 +152,11 @@ NonClientFrameView* BubbleDialogDelegateView::CreateNonClientFrameView(
if (base::i18n::IsRTL() && mirror_arrow_in_rtl_)
adjusted_arrow = BubbleBorder::horizontal_mirror(adjusted_arrow);
std::unique_ptr<BubbleBorder> border =
- std::make_unique<BubbleBorder>(adjusted_arrow, shadow(), color());
+ std::make_unique<BubbleBorder>(adjusted_arrow, GetShadow(), color());
+ // If custom shadows aren't supported we fall back to an OS provided square
+ // shadow.
+ if (!CustomShadowsSupported())
+ border->SetCornerRadius(0);
frame->SetBubbleBorder(std::move(border));
return frame;
}
@@ -198,16 +209,34 @@ void BubbleDialogDelegateView::OnWidgetBoundsChanged(
SizeToContents();
}
+BubbleBorder::Shadow BubbleDialogDelegateView::GetShadow() const {
+ if (CustomShadowsSupported() || shadow_ == BubbleBorder::NO_ASSETS)
+ return shadow_;
+ return BubbleBorder::NO_SHADOW;
+}
+
View* BubbleDialogDelegateView::GetAnchorView() const {
return anchor_view_tracker_->view();
}
-void BubbleDialogDelegateView::set_arrow(BubbleBorder::Arrow arrow) {
+void BubbleDialogDelegateView::SetHighlightedButton(
+ Button* highlighted_button) {
+ bool visible = GetWidget() && GetWidget()->IsVisible();
+ // If the Widget is visible, ensure the old highlight (if any) is removed
+ // when the highlighted view changes.
+ if (visible)
+ UpdateHighlightedButton(false);
+ highlighted_button_tracker_.SetView(highlighted_button);
+ if (visible)
+ UpdateHighlightedButton(true);
+}
+
+void BubbleDialogDelegateView::SetArrow(BubbleBorder::Arrow arrow) {
if (arrow_ == arrow)
return;
arrow_ = arrow;
- // If set_arrow() is called before CreateWidget(), there's no need to update
+ // If SetArrow() is called before CreateWidget(), there's no need to update
// the BubbleFrameView.
if (GetBubbleFrameView()) {
GetBubbleFrameView()->bubble_border()->set_arrow(arrow);
@@ -321,8 +350,10 @@ void BubbleDialogDelegateView::SetAnchorView(View* anchor_view) {
// change as well.
if (!anchor_view || anchor_widget() != anchor_view->GetWidget()) {
if (anchor_widget()) {
- if (GetWidget() && GetWidget()->IsVisible())
+ if (GetWidget() && GetWidget()->IsVisible()) {
UpdateAnchorWidgetRenderState(false);
+ UpdateHighlightedButton(false);
+ }
anchor_widget_->RemoveObserver(this);
anchor_widget_ = NULL;
}
@@ -330,7 +361,9 @@ void BubbleDialogDelegateView::SetAnchorView(View* anchor_view) {
anchor_widget_ = anchor_view->GetWidget();
if (anchor_widget_) {
anchor_widget_->AddObserver(this);
- UpdateAnchorWidgetRenderState(GetWidget() && GetWidget()->IsVisible());
+ const bool visible = GetWidget() && GetWidget()->IsVisible();
+ UpdateAnchorWidgetRenderState(visible);
+ UpdateHighlightedButton(visible);
}
}
}
@@ -391,8 +424,10 @@ void BubbleDialogDelegateView::UpdateColorsFromTheme(
void BubbleDialogDelegateView::HandleVisibilityChanged(Widget* widget,
bool visible) {
- if (widget == GetWidget())
+ if (widget == GetWidget()) {
UpdateAnchorWidgetRenderState(visible);
+ UpdateHighlightedButton(visible);
+ }
// Fire ax::mojom::Event::kAlert for bubbles marked as
// ax::mojom::Role::kAlertDialog; this instructs accessibility tools to read
@@ -419,4 +454,11 @@ void BubbleDialogDelegateView::UpdateAnchorWidgetRenderState(bool visible) {
anchor_widget()->GetTopLevelWidget()->SetAlwaysRenderAsActive(visible);
}
+void BubbleDialogDelegateView::UpdateHighlightedButton(bool highlighted) {
+ Button* button = Button::AsButton(highlighted_button_tracker_.view());
+ button = button ? button : Button::AsButton(anchor_view_tracker_->view());
+ if (button)
+ button->SetHighlighted(highlighted);
+}
+
} // namespace views
diff --git a/chromium/ui/views/bubble/bubble_dialog_delegate_view.h b/chromium/ui/views/bubble/bubble_dialog_delegate_view.h
index 51a95a0ab17..8d6561420c6 100644
--- a/chromium/ui/views/bubble/bubble_dialog_delegate_view.h
+++ b/chromium/ui/views/bubble/bubble_dialog_delegate_view.h
@@ -12,6 +12,7 @@
#include "build/build_config.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/views/bubble/bubble_border.h"
+#include "ui/views/view_tracker.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
#include "ui/views/window/dialog_delegate.h"
@@ -27,7 +28,7 @@ class Rect;
namespace views {
class BubbleFrameView;
-class ViewTracker;
+class Button;
// BubbleDialogDelegateView is a special DialogDelegateView for bubbles.
class VIEWS_EXPORT BubbleDialogDelegateView : public DialogDelegateView,
@@ -68,15 +69,17 @@ class VIEWS_EXPORT BubbleDialogDelegateView : public DialogDelegateView,
View* GetAnchorView() const;
Widget* anchor_widget() const { return anchor_widget_; }
+ void SetHighlightedButton(Button* highlighted_button);
+
// The anchor rect is used in the absence of an assigned anchor view.
const gfx::Rect& anchor_rect() const { return anchor_rect_; }
BubbleBorder::Arrow arrow() const { return arrow_; }
- void set_arrow(BubbleBorder::Arrow arrow);
+ void SetArrow(BubbleBorder::Arrow arrow);
void set_mirror_arrow_in_rtl(bool mirror) { mirror_arrow_in_rtl_ = mirror; }
- BubbleBorder::Shadow shadow() const { return shadow_; }
+ BubbleBorder::Shadow GetShadow() const;
void set_shadow(BubbleBorder::Shadow shadow) { shadow_ = shadow; }
SkColor color() const { return color_; }
@@ -182,6 +185,11 @@ class VIEWS_EXPORT BubbleDialogDelegateView : public DialogDelegateView,
// When a bubble is visible, the anchor widget should always render as active.
void UpdateAnchorWidgetRenderState(bool visible);
+ // Update the button highlight, which may be the anchor view or an explicit
+ // view set in |highlighted_button_tracker_|. This can be overridden to
+ // provide different highlight effects.
+ virtual void UpdateHighlightedButton(bool highlighted);
+
// A flag controlling bubble closure on deactivation.
bool close_on_deactivate_;
@@ -191,6 +199,11 @@ class VIEWS_EXPORT BubbleDialogDelegateView : public DialogDelegateView,
std::unique_ptr<ViewTracker> anchor_view_tracker_;
Widget* anchor_widget_;
+ // If provided, this button should be highlighted while the bubble is visible.
+ // If not provided, the anchor_view will attempt to be highlighted. A
+ // ViewTracker is used because the view can be deleted.
+ ViewTracker highlighted_button_tracker_;
+
// The anchor rect used in the absence of an anchor view.
mutable gfx::Rect anchor_rect_;
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 5de626a2bd4..cf205c20d3f 100644
--- a/chromium/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc
+++ b/chromium/ui/views/bubble/bubble_dialog_delegate_view_unittest.cc
@@ -11,7 +11,10 @@
#include "base/strings/utf_string_conversions.h"
#include "ui/base/hit_test.h"
#include "ui/events/event_utils.h"
+#include "ui/views/animation/test/ink_drop_host_view_test_api.h"
+#include "ui/views/animation/test/test_ink_drop.h"
#include "ui/views/bubble/bubble_frame_view.h"
+#include "ui/views/controls/button/button.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/styled_label.h"
#include "ui/views/test/test_views.h"
@@ -22,6 +25,8 @@
namespace views {
+using test::TestInkDrop;
+
namespace {
constexpr int kContentHeight = 200;
@@ -362,6 +367,7 @@ TEST_F(BubbleDialogDelegateViewTest, CloseMethods) {
BubbleDialogDelegateView::CreateBubble(bubble_delegate);
bubble_widget->Show();
BubbleFrameView* frame_view = bubble_delegate->GetBubbleFrameView();
+ frame_view->ResetViewShownTimeStampForTesting();
Button* close_button = frame_view->close_;
ASSERT_TRUE(close_button);
frame_view->ButtonPressed(
@@ -477,6 +483,62 @@ TEST_F(BubbleDialogDelegateViewTest, StyledLabelTitle) {
bubble_widget->GetWindowBoundsInScreen().height());
}
+// Ensure associated buttons are highlighted or unhighlighted when the bubble
+// widget is shown or hidden respectively.
+TEST_F(BubbleDialogDelegateViewTest, AttachedWidgetShowsInkDropWhenVisible) {
+ std::unique_ptr<Widget> anchor_widget(CreateTestWidget());
+ LabelButton* button = new LabelButton(nullptr, base::string16());
+ anchor_widget->GetContentsView()->AddChildView(button);
+ TestInkDrop* ink_drop = new TestInkDrop();
+ test::InkDropHostViewTestApi(button).SetInkDrop(base::WrapUnique(ink_drop));
+ TestBubbleDialogDelegateView* bubble_delegate =
+ new TestBubbleDialogDelegateView(nullptr);
+ bubble_delegate->set_parent_window(anchor_widget->GetNativeView());
+
+ Widget* bubble_widget =
+ BubbleDialogDelegateView::CreateBubble(bubble_delegate);
+ bubble_delegate->SetHighlightedButton(button);
+ bubble_widget->Show();
+ // Explicitly calling OnWidgetVisibilityChanging to test functionality for
+ // OS_WIN. Outside of the test environment this happens automatically by way
+ // of HWNDMessageHandler.
+ bubble_delegate->OnWidgetVisibilityChanging(bubble_widget, true);
+ EXPECT_EQ(InkDropState::ACTIVATED, ink_drop->GetTargetInkDropState());
+
+ bubble_widget->Close();
+ bubble_delegate->OnWidgetVisibilityChanging(bubble_widget, false);
+ EXPECT_EQ(InkDropState::DEACTIVATED, ink_drop->GetTargetInkDropState());
+}
+
+// Ensure associated buttons are highlighted or unhighlighted when the bubble
+// widget is shown or hidden respectively when highlighted button is set after
+// widget is shown.
+TEST_F(BubbleDialogDelegateViewTest, VisibleWidgetShowsInkDropOnAttaching) {
+ std::unique_ptr<Widget> anchor_widget(CreateTestWidget());
+ LabelButton* button = new LabelButton(nullptr, base::string16());
+ anchor_widget->GetContentsView()->AddChildView(button);
+ TestInkDrop* ink_drop = new TestInkDrop();
+ test::InkDropHostViewTestApi(button).SetInkDrop(base::WrapUnique(ink_drop));
+ TestBubbleDialogDelegateView* bubble_delegate =
+ new TestBubbleDialogDelegateView(nullptr);
+ bubble_delegate->set_parent_window(anchor_widget->GetNativeView());
+
+ Widget* bubble_widget =
+ BubbleDialogDelegateView::CreateBubble(bubble_delegate);
+ bubble_widget->Show();
+ // Explicitly calling OnWidgetVisibilityChanging to test functionality for
+ // OS_WIN. Outside of the test environment this happens automatically by way
+ // of HWNDMessageHandler.
+ bubble_delegate->OnWidgetVisibilityChanging(bubble_widget, true);
+ EXPECT_EQ(InkDropState::HIDDEN, ink_drop->GetTargetInkDropState());
+ bubble_delegate->SetHighlightedButton(button);
+ EXPECT_EQ(InkDropState::ACTIVATED, ink_drop->GetTargetInkDropState());
+
+ bubble_widget->Close();
+ bubble_delegate->OnWidgetVisibilityChanging(bubble_widget, false);
+ EXPECT_EQ(InkDropState::DEACTIVATED, ink_drop->GetTargetInkDropState());
+}
+
TEST_F(BubbleDialogDelegateViewTest, VisibleAnchorChanges) {
std::unique_ptr<Widget> anchor_widget(CreateTestWidget());
TestBubbleDialogDelegateView* bubble_delegate =
diff --git a/chromium/ui/views/bubble/bubble_frame_view.cc b/chromium/ui/views/bubble/bubble_frame_view.cc
index f43e505afb4..02aa4a05ff8 100644
--- a/chromium/ui/views/bubble/bubble_frame_view.cc
+++ b/chromium/ui/views/bubble/bubble_frame_view.cc
@@ -28,10 +28,12 @@
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/button/image_button_factory.h"
#include "ui/views/controls/image_view.h"
+#include "ui/views/event_utils.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/layout_provider.h"
#include "ui/views/paint_info.h"
#include "ui/views/resources/grit/views_resources.h"
+#include "ui/views/view_properties.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/window/client_view.h"
@@ -131,6 +133,11 @@ Button* BubbleFrameView::CreateCloseButton(ButtonListener* listener) {
close_button->SetTooltipText(l10n_util::GetStringUTF16(IDS_APP_CLOSE));
close_button->SizeToPreferredSize();
+ // Let the close button use a circular inkdrop shape.
+ auto highlight_path = std::make_unique<gfx::Path>();
+ highlight_path->addOval(gfx::RectToSkRect(gfx::Rect(close_button->size())));
+ close_button->SetProperty(kHighlightPathKey, highlight_path.release());
+
// Remove the close button from tab traversal on all platforms. Note this does
// not affect screen readers' ability to focus the close button. Keyboard
// access to the close button when not using a screen reader is done via the
@@ -407,6 +414,13 @@ void BubbleFrameView::ViewHierarchyChanged(
}
}
+void BubbleFrameView::VisibilityChanged(View* starting_from, bool is_visible) {
+ NonClientFrameView::VisibilityChanged(starting_from, is_visible);
+
+ if (is_visible)
+ view_shown_time_stamp_ = base::TimeTicks::Now();
+}
+
void BubbleFrameView::OnPaint(gfx::Canvas* canvas) {
OnPaintBackground(canvas);
// Border comes after children.
@@ -424,6 +438,9 @@ void BubbleFrameView::PaintChildren(const PaintInfo& paint_info) {
}
void BubbleFrameView::ButtonPressed(Button* sender, const ui::Event& event) {
+ if (IsPossiblyUnintendedInteraction(view_shown_time_stamp_, event))
+ return;
+
if (sender == close_) {
close_button_clicked_ = true;
GetWidget()->Close();
@@ -477,6 +494,10 @@ gfx::Rect BubbleFrameView::GetUpdatedWindowBounds(const gfx::Rect& anchor_rect,
return bubble_border_->GetBounds(anchor_rect, size);
}
+void BubbleFrameView::ResetViewShownTimeStampForTesting() {
+ view_shown_time_stamp_ = base::TimeTicks();
+}
+
gfx::Rect BubbleFrameView::GetAvailableScreenBounds(
const gfx::Rect& rect) const {
// The bubble attempts to fit within the current screen bounds.
diff --git a/chromium/ui/views/bubble/bubble_frame_view.h b/chromium/ui/views/bubble/bubble_frame_view.h
index eef3fda7a3e..bfb407a231f 100644
--- a/chromium/ui/views/bubble/bubble_frame_view.h
+++ b/chromium/ui/views/bubble/bubble_frame_view.h
@@ -8,6 +8,7 @@
#include "base/compiler_specific.h"
#include "base/gtest_prod_util.h"
#include "base/macros.h"
+#include "base/time/time.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/controls/button/button.h"
@@ -65,6 +66,7 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView,
void OnNativeThemeChanged(const ui::NativeTheme* theme) override;
void ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) override;
+ void VisibilityChanged(View* starting_from, bool is_visible) override;
// ButtonListener:
void ButtonPressed(Button* sender, const ui::Event& event) override;
@@ -99,6 +101,11 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView,
Button* GetCloseButtonForTest() { return close_; }
+ // Resets the time when view has been shown. Tests may need to call this
+ // method if they use events that could be otherwise treated as unintended.
+ // See IsPossiblyUnintendedInteraction().
+ void ResetViewShownTimeStampForTesting();
+
protected:
// Returns the available screen bounds if the frame were to show in |rect|.
virtual gfx::Rect GetAvailableScreenBounds(const gfx::Rect& rect) const;
@@ -115,6 +122,7 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView,
FRIEND_TEST_ALL_PREFIXES(BubbleFrameViewTest, GetBoundsForClientView);
FRIEND_TEST_ALL_PREFIXES(BubbleFrameViewTest, RemoveFootnoteView);
FRIEND_TEST_ALL_PREFIXES(BubbleFrameViewTest, LayoutWithIcon);
+ FRIEND_TEST_ALL_PREFIXES(BubbleFrameViewTest, IgnorePossiblyUnintendedClicks);
FRIEND_TEST_ALL_PREFIXES(BubbleDelegateTest, CloseReasons);
FRIEND_TEST_ALL_PREFIXES(BubbleDialogDelegateViewTest, CloseMethods);
@@ -180,6 +188,9 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView,
// Whether the close button was clicked.
bool close_button_clicked_;
+ // Time when view has been shown.
+ base::TimeTicks view_shown_time_stamp_;
+
DISALLOW_COPY_AND_ASSIGN(BubbleFrameView);
};
diff --git a/chromium/ui/views/bubble/bubble_frame_view_unittest.cc b/chromium/ui/views/bubble/bubble_frame_view_unittest.cc
index 0a060d2fbf5..38930c39de0 100644
--- a/chromium/ui/views/bubble/bubble_frame_view_unittest.cc
+++ b/chromium/ui/views/bubble/bubble_frame_view_unittest.cc
@@ -8,14 +8,19 @@
#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
#include "build/build_config.h"
+#include "ui/events/base_event_utils.h"
+#include "ui/events/event.h"
#include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/gfx/text_utils.h"
#include "ui/views/bubble/bubble_border.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
#include "ui/views/controls/button/label_button.h"
+#include "ui/views/metrics.h"
#include "ui/views/test/test_layout_provider.h"
#include "ui/views/test/test_views.h"
#include "ui/views/test/views_test_base.h"
@@ -84,7 +89,7 @@ class TestBubbleFrameView : public BubbleFrameView {
: BubbleFrameView(gfx::Insets(), gfx::Insets(kMargin)),
available_bounds_(gfx::Rect(0, 0, 1000, 1000)) {
SetBubbleBorder(std::make_unique<BubbleBorder>(
- kArrow, BubbleBorder::NO_SHADOW, kColor));
+ kArrow, BubbleBorder::BIG_SHADOW, kColor));
widget_ = std::make_unique<Widget>();
widget_delegate_ =
std::make_unique<TestBubbleFrameViewWidgetDelegate>(widget_.get());
@@ -751,4 +756,28 @@ TEST_F(BubbleFrameViewTest, NoElideTitle) {
EXPECT_EQ(title, title_label->GetDisplayTextForTesting());
}
+// Ensures that clicks are ignored for short time after view has been shown.
+TEST_F(BubbleFrameViewTest, IgnorePossiblyUnintendedClicks) {
+ TestBubbleDialogDelegateView delegate;
+ TestAnchor anchor(CreateParams(Widget::InitParams::TYPE_WINDOW));
+ delegate.SetAnchorView(anchor.widget().GetContentsView());
+ Widget* bubble = BubbleDialogDelegateView::CreateBubble(&delegate);
+ bubble->Show();
+
+ BubbleFrameView* frame = delegate.GetBubbleFrameView();
+ frame->ButtonPressed(
+ frame->close_,
+ ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+ ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE));
+ EXPECT_FALSE(bubble->IsClosed());
+
+ frame->ButtonPressed(
+ frame->close_,
+ ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+ ui::EventTimeForNow() + base::TimeDelta::FromMilliseconds(
+ GetDoubleClickInterval()),
+ ui::EF_NONE, ui::EF_NONE));
+ EXPECT_TRUE(bubble->IsClosed());
+}
+
} // namespace views
diff --git a/chromium/ui/views/bubble/info_bubble.cc b/chromium/ui/views/bubble/info_bubble.cc
index 65fc0411ece..442287d5d22 100644
--- a/chromium/ui/views/bubble/info_bubble.cc
+++ b/chromium/ui/views/bubble/info_bubble.cc
@@ -79,7 +79,7 @@ NonClientFrameView* InfoBubble::CreateNonClientFrameView(Widget* widget) {
frame_ = new InfoBubbleFrame(margins());
frame_->set_available_bounds(anchor_widget()->GetWindowBoundsInScreen());
frame_->SetBubbleBorder(std::unique_ptr<BubbleBorder>(
- new BubbleBorder(arrow(), shadow(), color())));
+ new BubbleBorder(arrow(), GetShadow(), color())));
return frame_;
}
diff --git a/chromium/ui/views/bubble/tooltip_icon.cc b/chromium/ui/views/bubble/tooltip_icon.cc
index 8e1969cd449..09be527d930 100644
--- a/chromium/ui/views/bubble/tooltip_icon.cc
+++ b/chromium/ui/views/bubble/tooltip_icon.cc
@@ -84,7 +84,7 @@ void TooltipIcon::ShowBubble() {
bubble_ = new InfoBubble(this, tooltip_);
bubble_->set_preferred_width(preferred_width_);
- bubble_->set_arrow(anchor_point_arrow_);
+ bubble_->SetArrow(anchor_point_arrow_);
// When shown due to a gesture event, close on deactivate (i.e. don't use
// "focusless").
bubble_->set_can_activate(!mouse_inside_);
diff --git a/chromium/ui/views/bubble/tray_bubble_view.cc b/chromium/ui/views/bubble/tray_bubble_view.cc
deleted file mode 100644
index 9e2994cfefd..00000000000
--- a/chromium/ui/views/bubble/tray_bubble_view.cc
+++ /dev/null
@@ -1,496 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/bubble/tray_bubble_view.h"
-
-#include <algorithm>
-
-#include "base/macros.h"
-#include "cc/paint/paint_flags.h"
-#include "third_party/skia/include/core/SkCanvas.h"
-#include "third_party/skia/include/core/SkColor.h"
-#include "third_party/skia/include/core/SkPath.h"
-#include "third_party/skia/include/effects/SkBlurImageFilter.h"
-#include "ui/accessibility/ax_node_data.h"
-#include "ui/aura/env.h"
-#include "ui/aura/window.h"
-#include "ui/compositor/layer.h"
-#include "ui/compositor/layer_owner.h"
-#include "ui/events/event.h"
-#include "ui/gfx/canvas.h"
-#include "ui/gfx/color_palette.h"
-#include "ui/gfx/geometry/insets.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/path.h"
-#include "ui/gfx/skia_util.h"
-#include "ui/views/bubble/bubble_frame_view.h"
-#include "ui/views/layout/box_layout.h"
-#include "ui/views/painter.h"
-#include "ui/views/views_delegate.h"
-#include "ui/views/widget/widget.h"
-#include "ui/wm/core/shadow_types.h"
-#include "ui/wm/core/window_util.h"
-
-namespace views {
-
-namespace {
-
-// The sampling time for mouse position changes in ms - which is roughly a frame
-// time.
-const int kFrameTimeInMS = 30;
-
-BubbleBorder::Arrow GetArrowAlignment(
- TrayBubbleView::AnchorAlignment alignment) {
- if (alignment == TrayBubbleView::ANCHOR_ALIGNMENT_BOTTOM) {
- return base::i18n::IsRTL() ? BubbleBorder::BOTTOM_LEFT
- : BubbleBorder::BOTTOM_RIGHT;
- }
- if (alignment == TrayBubbleView::ANCHOR_ALIGNMENT_LEFT)
- return BubbleBorder::LEFT_BOTTOM;
- return BubbleBorder::RIGHT_BOTTOM;
-}
-
-// Only one TrayBubbleView is visible at a time, but there are cases where the
-// lifetimes of two different bubbles can overlap briefly.
-int g_current_tray_bubble_showing_count_ = 0;
-
-} // namespace
-
-namespace internal {
-
-// Detects any mouse movement. This is needed to detect mouse movements by the
-// user over the bubble if the bubble got created underneath the cursor.
-class MouseMoveDetectorHost : public MouseWatcherHost {
- public:
- MouseMoveDetectorHost();
- ~MouseMoveDetectorHost() override;
-
- bool Contains(const gfx::Point& screen_point, MouseEventType type) override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(MouseMoveDetectorHost);
-};
-
-MouseMoveDetectorHost::MouseMoveDetectorHost() {
-}
-
-MouseMoveDetectorHost::~MouseMoveDetectorHost() {
-}
-
-bool MouseMoveDetectorHost::Contains(const gfx::Point& screen_point,
- MouseEventType type) {
- return false;
-}
-
-// Custom layout for the bubble-view. Does the default box-layout if there is
-// enough height. Otherwise, makes sure the bottom rows are visible.
-class BottomAlignedBoxLayout : public BoxLayout {
- public:
- explicit BottomAlignedBoxLayout(TrayBubbleView* bubble_view)
- : BoxLayout(BoxLayout::kVertical), bubble_view_(bubble_view) {}
-
- ~BottomAlignedBoxLayout() override {}
-
- private:
- void Layout(View* host) override {
- if (host->height() >= host->GetPreferredSize().height() ||
- !bubble_view_->is_gesture_dragging()) {
- BoxLayout::Layout(host);
- return;
- }
-
- int consumed_height = 0;
- for (int i = host->child_count() - 1;
- i >= 0 && consumed_height < host->height(); --i) {
- View* child = host->child_at(i);
- if (!child->visible())
- continue;
- gfx::Size size = child->GetPreferredSize();
- child->SetBounds(0, host->height() - consumed_height - size.height(),
- host->width(), size.height());
- consumed_height += size.height();
- }
- }
-
- TrayBubbleView* bubble_view_;
-
- DISALLOW_COPY_AND_ASSIGN(BottomAlignedBoxLayout);
-};
-
-} // namespace internal
-
-using internal::BottomAlignedBoxLayout;
-
-TrayBubbleView::Delegate::~Delegate() {}
-
-void TrayBubbleView::Delegate::BubbleViewDestroyed() {}
-
-void TrayBubbleView::Delegate::OnMouseEnteredView() {}
-
-void TrayBubbleView::Delegate::OnMouseExitedView() {}
-
-base::string16 TrayBubbleView::Delegate::GetAccessibleNameForBubble() {
- return base::string16();
-}
-
-bool TrayBubbleView::Delegate::ShouldEnableExtraKeyboardAccessibility() {
- return false;
-}
-
-void TrayBubbleView::Delegate::HideBubble(const TrayBubbleView* bubble_view) {}
-
-void TrayBubbleView::Delegate::ProcessGestureEventForBubble(
- ui::GestureEvent* event) {}
-
-TrayBubbleView::InitParams::InitParams() = default;
-
-TrayBubbleView::InitParams::InitParams(const InitParams& other) = default;
-
-TrayBubbleView::RerouteEventHandler::RerouteEventHandler(
- TrayBubbleView* tray_bubble_view)
- : tray_bubble_view_(tray_bubble_view) {
- aura::Env::GetInstance()->AddPreTargetHandler(
- this, ui::EventTarget::Priority::kSystem);
-}
-
-TrayBubbleView::RerouteEventHandler::~RerouteEventHandler() {
- aura::Env::GetInstance()->RemovePreTargetHandler(this);
-}
-
-void TrayBubbleView::RerouteEventHandler::OnKeyEvent(ui::KeyEvent* event) {
- // Do not handle a key event if it is targeted to the tray or its descendants,
- // or if the target has the tray as a transient ancestor. RerouteEventHandler
- // is for rerouting events which are not targetted to the tray. Those events
- // should be handled by the target.
- aura::Window* target = static_cast<aura::Window*>(event->target());
- aura::Window* tray_window = tray_bubble_view_->GetWidget()->GetNativeView();
- if (target && (tray_window->Contains(target) ||
- wm::HasTransientAncestor(target, tray_window))) {
- return;
- }
-
- // Only passes Tab, Shift+Tab, Esc to the widget as it can consume more key
- // events. e.g. Alt+Tab can be consumed as focus traversal by FocusManager.
- ui::KeyboardCode key_code = event->key_code();
- int flags = event->flags();
- if ((key_code == ui::VKEY_TAB && flags == ui::EF_NONE) ||
- (key_code == ui::VKEY_TAB && flags == ui::EF_SHIFT_DOWN) ||
- (key_code == ui::VKEY_ESCAPE && flags == ui::EF_NONE)) {
- // Make TrayBubbleView activatable as the following Widget::OnKeyEvent might
- // try to activate it.
- tray_bubble_view_->set_can_activate(true);
-
- tray_bubble_view_->GetWidget()->OnKeyEvent(event);
-
- if (event->handled())
- return;
- }
-
- // Always consumes key event not to pass it to other widgets. Calling
- // StopPropagation here to make this consistent with
- // MenuController::OnWillDispatchKeyEvent.
- event->StopPropagation();
-
- // To provide consistent behavior with a menu, process accelerator as a menu
- // is open if the event is not handled by the widget.
- ui::Accelerator accelerator(*event);
- ViewsDelegate::ProcessMenuAcceleratorResult result =
- ViewsDelegate::GetInstance()->ProcessAcceleratorWhileMenuShowing(
- accelerator);
- if (result == ViewsDelegate::ProcessMenuAcceleratorResult::CLOSE_MENU)
- tray_bubble_view_->CloseBubbleView();
-}
-
-TrayBubbleView::TrayBubbleView(const InitParams& init_params)
- : BubbleDialogDelegateView(init_params.anchor_view,
- GetArrowAlignment(init_params.anchor_alignment)),
- params_(init_params),
- layout_(nullptr),
- delegate_(init_params.delegate),
- preferred_width_(init_params.min_width),
- bubble_border_(new BubbleBorder(
- arrow(),
- init_params.has_shadow ? BubbleBorder::NO_ASSETS
- : BubbleBorder::NO_SHADOW,
- init_params.bg_color.value_or(gfx::kPlaceholderColor))),
- owned_bubble_border_(bubble_border_),
- is_gesture_dragging_(false),
- mouse_actively_entered_(false) {
- DCHECK(delegate_);
- DCHECK(params_.parent_window);
- DCHECK(anchor_widget()); // Computed by BubbleDialogDelegateView().
- bubble_border_->set_use_theme_background_color(!init_params.bg_color);
- if (init_params.corner_radius)
- bubble_border_->SetCornerRadius(init_params.corner_radius.value());
- set_parent_window(params_.parent_window);
- set_can_activate(false);
- set_notify_enter_exit_on_child(true);
- set_close_on_deactivate(init_params.close_on_deactivate);
- set_margins(gfx::Insets());
- SetPaintToLayer();
-
- bubble_content_mask_ = views::Painter::CreatePaintedLayer(
- views::Painter::CreateSolidRoundRectPainter(
- SK_ColorBLACK, bubble_border_->GetBorderCornerRadius()));
-
- auto layout = std::make_unique<BottomAlignedBoxLayout>(this);
- layout->SetDefaultFlex(1);
- layout_ = SetLayoutManager(std::move(layout));
-}
-
-TrayBubbleView::~TrayBubbleView() {
- mouse_watcher_.reset();
-
- if (delegate_) {
- // Inform host items (models) that their views are being destroyed.
- delegate_->BubbleViewDestroyed();
- }
-}
-
-// static
-bool TrayBubbleView::IsATrayBubbleOpen() {
- return g_current_tray_bubble_showing_count_ > 0;
-}
-
-void TrayBubbleView::InitializeAndShowBubble() {
- layer()->parent()->SetMaskLayer(bubble_content_mask_->layer());
-
- GetWidget()->Show();
- UpdateBubble();
-
- ++g_current_tray_bubble_showing_count_;
-
- // If TrayBubbleView cannot be activated and is shown by clicking on the
- // corresponding tray view, register pre target event handler to reroute key
- // events to the widget for activating the view or closing it.
- if (!CanActivate() && params_.show_by_click) {
- reroute_event_handler_ = std::make_unique<RerouteEventHandler>(this);
- }
-}
-
-void TrayBubbleView::UpdateBubble() {
- if (GetWidget()) {
- SizeToContents();
- GetWidget()->GetRootView()->SchedulePaint();
-
- // When extra keyboard accessibility is enabled, focus the default item if
- // no item is focused.
- if (delegate_ && delegate_->ShouldEnableExtraKeyboardAccessibility())
- FocusDefaultIfNeeded();
- }
-}
-
-void TrayBubbleView::SetMaxHeight(int height) {
- params_.max_height = height;
- if (GetWidget())
- SizeToContents();
-}
-
-void TrayBubbleView::SetBottomPadding(int padding) {
- layout_->set_inside_border_insets(gfx::Insets(0, 0, padding, 0));
-}
-
-void TrayBubbleView::SetWidth(int width) {
- width = std::max(std::min(width, params_.max_width), params_.min_width);
- if (preferred_width_ == width)
- return;
- preferred_width_ = width;
- if (GetWidget())
- SizeToContents();
-}
-
-gfx::Insets TrayBubbleView::GetBorderInsets() const {
- return bubble_border_->GetInsets();
-}
-
-void TrayBubbleView::ResetDelegate() {
- reroute_event_handler_.reset();
-
- delegate_ = nullptr;
-}
-
-void TrayBubbleView::ChangeAnchorView(views::View* anchor_view) {
- BubbleDialogDelegateView::SetAnchorView(anchor_view);
-}
-
-int TrayBubbleView::GetDialogButtons() const {
- return ui::DIALOG_BUTTON_NONE;
-}
-
-ax::mojom::Role TrayBubbleView::GetAccessibleWindowRole() const {
- // We override the role because the base class sets it to alert dialog.
- // This would make screen readers announce the whole of the system tray
- // which is undesirable.
- return ax::mojom::Role::kDialog;
-}
-
-void TrayBubbleView::SizeToContents() {
- BubbleDialogDelegateView::SizeToContents();
- bubble_content_mask_->layer()->SetBounds(layer()->parent()->bounds());
-}
-
-void TrayBubbleView::OnBeforeBubbleWidgetInit(Widget::InitParams* params,
- Widget* bubble_widget) const {
- if (bubble_border_->shadow() == BubbleBorder::NO_ASSETS) {
- // Apply a WM-provided shadow (see ui/wm/core/).
- params->shadow_type = Widget::InitParams::SHADOW_TYPE_DROP;
- params->shadow_elevation = wm::kShadowElevationActiveWindow;
- }
-}
-
-void TrayBubbleView::OnWidgetClosing(Widget* widget) {
- // We no longer need to watch key events for activation if the widget is
- // closing.
- reroute_event_handler_.reset();
-
- BubbleDialogDelegateView::OnWidgetClosing(widget);
- --g_current_tray_bubble_showing_count_;
- DCHECK_GE(g_current_tray_bubble_showing_count_, 0)
- << "Closing " << widget->GetName();
-}
-
-void TrayBubbleView::OnWidgetActivationChanged(Widget* widget, bool active) {
- // We no longer need to watch key events for activation if the widget is
- // activated.
- reroute_event_handler_.reset();
-
- BubbleDialogDelegateView::OnWidgetActivationChanged(widget, active);
-}
-
-NonClientFrameView* TrayBubbleView::CreateNonClientFrameView(Widget* widget) {
- BubbleFrameView* frame = static_cast<BubbleFrameView*>(
- BubbleDialogDelegateView::CreateNonClientFrameView(widget));
- frame->SetBubbleBorder(std::move(owned_bubble_border_));
- return frame;
-}
-
-bool TrayBubbleView::WidgetHasHitTestMask() const {
- return true;
-}
-
-void TrayBubbleView::GetWidgetHitTestMask(gfx::Path* mask) const {
- DCHECK(mask);
- mask->addRect(gfx::RectToSkRect(GetBubbleFrameView()->GetContentsBounds()));
-}
-
-base::string16 TrayBubbleView::GetAccessibleWindowTitle() const {
- if (delegate_)
- return delegate_->GetAccessibleNameForBubble();
- else
- return base::string16();
-}
-
-gfx::Size TrayBubbleView::CalculatePreferredSize() const {
- DCHECK_LE(preferred_width_, params_.max_width);
- return gfx::Size(preferred_width_, GetHeightForWidth(preferred_width_));
-}
-
-int TrayBubbleView::GetHeightForWidth(int width) const {
- int height = GetInsets().height();
- width = std::max(width - GetInsets().width(), 0);
- for (int i = 0; i < child_count(); ++i) {
- const View* child = child_at(i);
- if (child->visible())
- height += child->GetHeightForWidth(width);
- }
-
- return (params_.max_height != 0) ?
- std::min(height, params_.max_height) : height;
-}
-
-void TrayBubbleView::OnMouseEntered(const ui::MouseEvent& event) {
- mouse_watcher_.reset();
- if (delegate_ && !(event.flags() & ui::EF_IS_SYNTHESIZED)) {
- // Coming here the user was actively moving the mouse over the bubble and
- // we inform the delegate that we entered. This will prevent the bubble
- // to auto close.
- delegate_->OnMouseEnteredView();
- mouse_actively_entered_ = true;
- } else {
- // Coming here the bubble got shown and the mouse was 'accidentally' over it
- // which is not a reason to prevent the bubble to auto close. As such we
- // do not call the delegate, but wait for the first mouse move within the
- // bubble. The used MouseWatcher will notify use of a movement and call
- // |MouseMovedOutOfHost|.
- mouse_watcher_ = std::make_unique<MouseWatcher>(
- std::make_unique<views::internal::MouseMoveDetectorHost>(), this);
- // Set the mouse sampling frequency to roughly a frame time so that the user
- // cannot see a lag.
- mouse_watcher_->set_notify_on_exit_time(
- base::TimeDelta::FromMilliseconds(kFrameTimeInMS));
- mouse_watcher_->Start(GetWidget()->GetNativeWindow());
- }
-}
-
-void TrayBubbleView::OnMouseExited(const ui::MouseEvent& event) {
- // If there was a mouse watcher waiting for mouse movements we disable it
- // immediately since we now leave the bubble.
- mouse_watcher_.reset();
- // Do not notify the delegate of an exit if we never told it that we entered.
- if (delegate_ && mouse_actively_entered_)
- delegate_->OnMouseExitedView();
-}
-
-void TrayBubbleView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
- if (delegate_ && CanActivate()) {
- node_data->role = ax::mojom::Role::kWindow;
- node_data->SetName(delegate_->GetAccessibleNameForBubble());
- }
-}
-
-void TrayBubbleView::OnGestureEvent(ui::GestureEvent* event) {
- if (delegate_)
- delegate_->ProcessGestureEventForBubble(event);
-
- if (!event->handled())
- BubbleDialogDelegateView::OnGestureEvent(event);
-}
-
-void TrayBubbleView::MouseMovedOutOfHost() {
- // The mouse was accidentally over the bubble when it opened and the AutoClose
- // logic was not activated. Now that the user did move the mouse we tell the
- // delegate to disable AutoClose.
- if (delegate_)
- delegate_->OnMouseEnteredView();
- mouse_actively_entered_ = true;
- mouse_watcher_->Stop();
-}
-
-void TrayBubbleView::ChildPreferredSizeChanged(View* child) {
- SizeToContents();
-}
-
-void TrayBubbleView::ViewHierarchyChanged(
- const ViewHierarchyChangedDetails& details) {
- if (details.is_add && details.child == this) {
- details.parent->SetPaintToLayer();
- details.parent->layer()->SetMasksToBounds(true);
- }
-}
-
-void TrayBubbleView::CloseBubbleView() {
- if (!delegate_)
- return;
-
- delegate_->HideBubble(this);
-}
-
-void TrayBubbleView::FocusDefaultIfNeeded() {
- views::FocusManager* manager = GetFocusManager();
- if (!manager || manager->GetFocusedView())
- return;
-
- views::View* view =
- manager->GetNextFocusableView(nullptr, nullptr, false, false);
- if (!view)
- return;
-
- // No need to explicitly activate the widget. View::RequestFocus will activate
- // it if necessary.
- set_can_activate(true);
-
- view->RequestFocus();
-}
-
-} // namespace views
diff --git a/chromium/ui/views/bubble/tray_bubble_view.h b/chromium/ui/views/bubble/tray_bubble_view.h
deleted file mode 100644
index 5ef449781bc..00000000000
--- a/chromium/ui/views/bubble/tray_bubble_view.h
+++ /dev/null
@@ -1,230 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_BUBBLE_TRAY_BUBBLE_VIEW_H_
-#define UI_VIEWS_BUBBLE_TRAY_BUBBLE_VIEW_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "base/optional.h"
-#include "ui/accessibility/ax_enums.mojom.h"
-#include "ui/events/event.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/views/bubble/bubble_dialog_delegate_view.h"
-#include "ui/views/mouse_watcher.h"
-#include "ui/views/views_export.h"
-
-namespace ui {
-class LayerOwner;
-}
-
-namespace views {
-class BoxLayout;
-class View;
-class Widget;
-}
-
-namespace views {
-
-// Specialized bubble view for bubbles associated with a tray icon (e.g. the
-// Ash status area). Mostly this handles custom anchor location and arrow and
-// border rendering. This also has its own delegate for handling mouse events
-// and other implementation specific details.
-class VIEWS_EXPORT TrayBubbleView : public BubbleDialogDelegateView,
- public MouseWatcherListener {
- public:
- // AnchorAlignment determines to which side of the anchor the bubble will
- // align itself.
- enum AnchorAlignment {
- ANCHOR_ALIGNMENT_BOTTOM,
- ANCHOR_ALIGNMENT_LEFT,
- ANCHOR_ALIGNMENT_RIGHT,
- };
-
- class VIEWS_EXPORT Delegate {
- public:
- typedef TrayBubbleView::AnchorAlignment AnchorAlignment;
-
- Delegate() {}
- virtual ~Delegate();
-
- // Called when the view is destroyed. Any pointers to the view should be
- // cleared when this gets called.
- virtual void BubbleViewDestroyed();
-
- // Called when the mouse enters/exits the view.
- // Note: This event will only be called if the mouse gets actively moved by
- // the user to enter the view.
- virtual void OnMouseEnteredView();
- virtual void OnMouseExitedView();
-
- // Called from GetAccessibleNodeData(); should return the appropriate
- // accessible name for the bubble.
- virtual base::string16 GetAccessibleNameForBubble();
-
- // Should return true if extra keyboard accessibility is enabled.
- // TrayBubbleView will put focus on the default item if extra keyboard
- // accessibility is enabled.
- virtual bool ShouldEnableExtraKeyboardAccessibility();
-
- // Called when a bubble wants to hide/destroy itself (e.g. last visible
- // child view was closed).
- virtual void HideBubble(const TrayBubbleView* bubble_view);
-
- // Called to process the gesture events that happened on the TrayBubbleView.
- // Swiping down on the opened TrayBubbleView to close the bubble.
- virtual void ProcessGestureEventForBubble(ui::GestureEvent* event);
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Delegate);
- };
-
- struct VIEWS_EXPORT InitParams {
- InitParams();
- InitParams(const InitParams& other);
- Delegate* delegate = nullptr;
- gfx::NativeWindow parent_window = nullptr;
- View* anchor_view = nullptr;
- AnchorAlignment anchor_alignment = ANCHOR_ALIGNMENT_BOTTOM;
- int min_width = 0;
- int max_width = 0;
- int max_height = 0;
- bool close_on_deactivate = true;
- // Indicates whether tray bubble view is shown by click on the tray view.
- bool show_by_click = false;
- // If not provided, the bg color will be derived from the NativeTheme.
- base::Optional<SkColor> bg_color;
- base::Optional<int> corner_radius;
- bool has_shadow = true;
- };
-
- explicit TrayBubbleView(const InitParams& init_params);
- ~TrayBubbleView() override;
-
- // Returns whether a tray bubble is active.
- static bool IsATrayBubbleOpen();
-
- // Sets up animations, and show the bubble. Must occur after CreateBubble()
- // is called.
- void InitializeAndShowBubble();
-
- // Called whenever the bubble size or location may have changed.
- void UpdateBubble();
-
- // Sets the maximum bubble height and resizes the bubble.
- void SetMaxHeight(int height);
-
- // Sets the bottom padding that child views will be laid out within.
- void SetBottomPadding(int padding);
-
- // Sets the bubble width.
- void SetWidth(int width);
-
- // Returns the border insets. Called by TrayEventFilter.
- gfx::Insets GetBorderInsets() const;
-
- // Called when the delegate is destroyed. This must be called before the
- // delegate is actually destroyed. TrayBubbleView will do clean up in
- // ResetDelegate.
- void ResetDelegate();
-
- // Anchors the bubble to |anchor_view|.
- void ChangeAnchorView(views::View* anchor_view);
-
- Delegate* delegate() { return delegate_; }
-
- void set_gesture_dragging(bool dragging) { is_gesture_dragging_ = dragging; }
- bool is_gesture_dragging() const { return is_gesture_dragging_; }
-
- // Overridden from views::WidgetDelegate.
- views::NonClientFrameView* CreateNonClientFrameView(
- views::Widget* widget) override;
- bool WidgetHasHitTestMask() const override;
- void GetWidgetHitTestMask(gfx::Path* mask) const override;
- base::string16 GetAccessibleWindowTitle() const override;
-
- // Overridden from views::BubbleDialogDelegateView.
- void OnBeforeBubbleWidgetInit(Widget::InitParams* params,
- Widget* bubble_widget) const override;
- void OnWidgetClosing(Widget* widget) override;
- void OnWidgetActivationChanged(Widget* widget, bool active) override;
-
- // Overridden from views::View.
- gfx::Size CalculatePreferredSize() const override;
- int GetHeightForWidth(int width) const override;
- void OnMouseEntered(const ui::MouseEvent& event) override;
- void OnMouseExited(const ui::MouseEvent& event) override;
- void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
- void OnGestureEvent(ui::GestureEvent* event) override;
-
- // Overridden from MouseWatcherListener
- void MouseMovedOutOfHost() override;
-
- protected:
- // Overridden from views::BubbleDialogDelegateView.
- int GetDialogButtons() const override;
- ax::mojom::Role GetAccessibleWindowRole() const override;
- void SizeToContents() override;
-
- // Overridden from views::View.
- void ChildPreferredSizeChanged(View* child) override;
- void ViewHierarchyChanged(
- const ViewHierarchyChangedDetails& details) override;
-
- private:
- // This reroutes receiving key events to the TrayBubbleView passed in the
- // constructor. TrayBubbleView is not activated by default. But we want to
- // activate it if user tries to interact it with keyboard. To capture those
- // key events in early stage, RerouteEventHandler installs this handler to
- // aura::Env. RerouteEventHandler also sends key events to ViewsDelegate to
- // process accelerator as menu is currently open.
- class RerouteEventHandler : public ui::EventHandler {
- public:
- explicit RerouteEventHandler(TrayBubbleView* tray_bubble_view);
- ~RerouteEventHandler() override;
-
- // Overridden from ui::EventHandler
- void OnKeyEvent(ui::KeyEvent* event) override;
-
- private:
- // TrayBubbleView to which key events are going to be rerouted. Not owned.
- TrayBubbleView* tray_bubble_view_;
-
- DISALLOW_COPY_AND_ASSIGN(RerouteEventHandler);
- };
-
- void CloseBubbleView();
-
- // Focus the default item if no item is focused.
- void FocusDefaultIfNeeded();
-
- InitParams params_;
- BoxLayout* layout_;
- Delegate* delegate_;
- int preferred_width_;
- // |bubble_border_| and |owned_bubble_border_| point to the same thing, but
- // the latter ensures we don't leak it before passing off ownership.
- BubbleBorder* bubble_border_;
- std::unique_ptr<views::BubbleBorder> owned_bubble_border_;
- std::unique_ptr<ui::LayerOwner> bubble_content_mask_;
- bool is_gesture_dragging_;
-
- // True once the mouse cursor was actively moved by the user over the bubble.
- // Only then the OnMouseExitedView() event will get passed on to listeners.
- bool mouse_actively_entered_;
-
- // Used to find any mouse movements.
- std::unique_ptr<MouseWatcher> mouse_watcher_;
-
- // Used to activate tray bubble view if user tries to interact the tray with
- // keyboard.
- std::unique_ptr<EventHandler> reroute_event_handler_;
-
- DISALLOW_COPY_AND_ASSIGN(TrayBubbleView);
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_BUBBLE_TRAY_BUBBLE_VIEW_H_
diff --git a/chromium/ui/views/cocoa/DEPS b/chromium/ui/views/cocoa/DEPS
index fcaeee7d596..440d45f5357 100644
--- a/chromium/ui/views/cocoa/DEPS
+++ b/chromium/ui/views/cocoa/DEPS
@@ -1,5 +1,4 @@
include_rules = [
- "+components/viz/common",
"+ui/accelerated_widget_mac",
"+ui/views_bridge_mac",
]
diff --git a/chromium/ui/views/cocoa/bridge_factory_host.cc b/chromium/ui/views/cocoa/bridge_factory_host.cc
new file mode 100644
index 00000000000..4350aae5c1a
--- /dev/null
+++ b/chromium/ui/views/cocoa/bridge_factory_host.cc
@@ -0,0 +1,35 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/cocoa/bridge_factory_host.h"
+
+#include "mojo/public/cpp/bindings/interface_request.h"
+
+namespace views {
+
+BridgeFactoryHost::BridgeFactoryHost(
+ uint64_t host_id,
+ views_bridge_mac::mojom::BridgeFactoryAssociatedRequest* request)
+ : host_id_(host_id) {
+ *request = mojo::MakeRequest(&bridge_factory_ptr_);
+}
+
+BridgeFactoryHost::~BridgeFactoryHost() {
+ for (Observer& obs : observers_)
+ obs.OnBridgeFactoryHostDestroying(this);
+}
+
+views_bridge_mac::mojom::BridgeFactory* BridgeFactoryHost::GetFactory() {
+ return bridge_factory_ptr_.get();
+}
+
+void BridgeFactoryHost::AddObserver(Observer* observer) {
+ observers_.AddObserver(observer);
+}
+
+void BridgeFactoryHost::RemoveObserver(const Observer* observer) {
+ observers_.RemoveObserver(observer);
+}
+
+} // namespace views
diff --git a/chromium/ui/views/cocoa/bridge_factory_host.h b/chromium/ui/views/cocoa/bridge_factory_host.h
new file mode 100644
index 00000000000..14a197dce5e
--- /dev/null
+++ b/chromium/ui/views/cocoa/bridge_factory_host.h
@@ -0,0 +1,47 @@
+// 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_VIEWS_COCOA_BRIDGE_FACTORY_HOST_H_
+#define UI_VIEWS_COCOA_BRIDGE_FACTORY_HOST_H_
+
+#include "base/observer_list.h"
+#include "base/observer_list_types.h"
+#include "ui/views/views_export.h"
+#include "ui/views_bridge_mac/mojo/bridge_factory.mojom.h"
+
+namespace views {
+
+class VIEWS_EXPORT BridgeFactoryHost {
+ public:
+ class Observer : public base::CheckedObserver {
+ public:
+ virtual void OnBridgeFactoryHostDestroying(BridgeFactoryHost* host) = 0;
+
+ protected:
+ ~Observer() override {}
+ };
+
+ BridgeFactoryHost(
+ uint64_t host_id,
+ views_bridge_mac::mojom::BridgeFactoryAssociatedRequest* request);
+ ~BridgeFactoryHost();
+
+ // Return an id for the host process. This can be used to look up other
+ // factories to create NSViews (e.g in content).
+ uint64_t GetHostId() const { return host_id_; }
+
+ views_bridge_mac::mojom::BridgeFactory* GetFactory();
+
+ void AddObserver(Observer* observer);
+ void RemoveObserver(const Observer* observer);
+
+ private:
+ const uint64_t host_id_;
+ views_bridge_mac::mojom::BridgeFactoryAssociatedPtr bridge_factory_ptr_;
+ base::ObserverList<Observer> observers_;
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_COCOA_BRIDGE_FACTORY_HOST_H_
diff --git a/chromium/ui/views/cocoa/bridged_native_widget_host.h b/chromium/ui/views/cocoa/bridged_native_widget_host.h
deleted file mode 100644
index 9fa2c68091c..00000000000
--- a/chromium/ui/views/cocoa/bridged_native_widget_host.h
+++ /dev/null
@@ -1,152 +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_VIEWS_COCOA_BRIDGED_NATIVE_WIDGET_HOST_H_
-#define UI_VIEWS_COCOA_BRIDGED_NATIVE_WIDGET_HOST_H_
-
-#include "ui/base/ui_base_types.h"
-#include "ui/events/event_utils.h"
-#include "ui/gfx/decorated_text.h"
-#include "ui/gfx/geometry/point.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/views/views_export.h"
-
-@class NSView;
-
-namespace views {
-
-// The interface through which the app shim (BridgedNativeWidgetImpl)
-// communicates with the browser process (BridgedNativeWidgetHostImpl).
-class VIEWS_EXPORT BridgedNativeWidgetHost {
- public:
- virtual ~BridgedNativeWidgetHost() = default;
-
- // Retrieve the NSView for accessibility for this widget.
- // TODO(ccameron): This interface cannot be implemented over IPC. A scheme
- // for implementing accessibility across processes needs to be designed and
- // implemented.
- virtual NSView* GetNativeViewAccessible() = 0;
-
- // Update the views::Widget, ui::Compositor and ui::Layer's visibility.
- virtual void OnVisibilityChanged(bool visible) = 0;
-
- // Resize the underlying views::View to |new_size|. Note that this will not
- // necessarily match the content bounds from OnWindowGeometryChanged.
- virtual void SetViewSize(const gfx::Size& new_size) = 0;
-
- // Indicate if full keyboard accessibility is needed and updates focus if
- // needed.
- virtual void SetKeyboardAccessible(bool enabled) = 0;
-
- // Indicate if the NSView is the first responder.
- virtual void SetIsFirstResponder(bool is_first_responder) = 0;
-
- // Indicate if mouse capture is active.
- virtual void OnMouseCaptureActiveChanged(bool capture_is_active) = 0;
-
- // Handle events. Note that whether or not the event is actually handled is
- // not returned.
- virtual void OnScrollEvent(const ui::ScrollEvent& const_event) = 0;
- virtual void OnMouseEvent(const ui::MouseEvent& const_event) = 0;
- virtual void OnGestureEvent(const ui::GestureEvent& const_event) = 0;
-
- // Synchronously dispatch a key event and return in |event_handled| whether
- // or not the event was handled.
- virtual void DispatchKeyEvent(const ui::KeyEvent& const_event,
- bool* event_handled) = 0;
-
- // Synchronously dispatch a key event to the current menu controller (if any)
- // exists. Return in |event_swallowed| whether or not the event was swallowed
- // (that is, if the menu's dispatch returned POST_DISPATCH_NONE). Return in
- // in |event_handled| whether or not the event was handled (that is, if the
- // event in the caller's frame should be marked as handled).
- virtual void DispatchKeyEventToMenuController(const ui::KeyEvent& const_event,
- bool* event_swallowed,
- bool* event_handled) = 0;
-
- // Synchronously return in |has_menu_controller| whether or not a menu
- // controller exists for this widget.
- virtual void GetHasMenuController(bool* has_menu_controller) = 0;
-
- // Synchronously query if |location_in_content| is a draggable background.
- virtual void GetIsDraggableBackgroundAt(const gfx::Point& location_in_content,
- bool* is_draggable_background) = 0;
-
- // Synchronously query the tooltip text for |location_in_content|.
- virtual void GetTooltipTextAt(const gfx::Point& location_in_content,
- base::string16* new_tooltip_text) = 0;
-
- // Synchronously query the quicklook text at |location_in_content|. Return in
- // |found_word| whether or not a word was found.
- virtual void GetWordAt(const gfx::Point& location_in_content,
- bool* found_word,
- gfx::DecoratedText* decorated_word,
- gfx::Point* baseline_point) = 0;
-
- // Synchronously query the value of IsModal for this widget and store it in
- // |*widget_is_modal|.
- virtual void GetWidgetIsModal(bool* widget_is_modal) = 0;
-
- // Synchronously return in |is_textual| whether or not the focused view
- // contains text that can be selected and copied.
- virtual void GetIsFocusedViewTextual(bool* is_textual) = 0;
-
- // Called whenever the NSWindow's size or position changes.
- virtual void OnWindowGeometryChanged(
- const gfx::Rect& window_bounds_in_screen_dips,
- const gfx::Rect& content_bounds_in_screen_dips) = 0;
-
- // Called when the window begins transitioning to or from being fullscreen.
- virtual void OnWindowFullscreenTransitionStart(
- bool target_fullscreen_state) = 0;
-
- // Called when the window has completed its transition to or from being
- // fullscreen. Note that if there are multiple consecutive transitions
- // (because a new transition was initiated before the previous one completed)
- // then this will only be called when all transitions have competed.
- virtual void OnWindowFullscreenTransitionComplete(bool is_fullscreen) = 0;
-
- // Called when the window is miniaturized or deminiaturized.
- virtual void OnWindowMiniaturizedChanged(bool miniaturized) = 0;
-
- // Called when the current display or the properties of the current display
- // change.
- virtual void OnWindowDisplayChanged(const display::Display& display) = 0;
-
- // Called before the NSWindow is closed and destroyed.
- virtual void OnWindowWillClose() = 0;
-
- // Called after the NSWindow has been closed and destroyed.
- virtual void OnWindowHasClosed() = 0;
-
- // Called when the NSWindow becomes key or resigns from being key. Additional
- // state required for the transition include whether or not the content NSView
- // is the first responder for the NSWindow in |is_content_first_responder| and
- // whether or not the NSApp's full keyboard access is enabled in
- // |full_keyboard_access_enabled|.
- virtual void OnWindowKeyStatusChanged(bool is_key,
- bool is_content_first_responder,
- bool full_keyboard_access_enabled) = 0;
-
- // Accept or cancel the current dialog window (depending on the value of
- // |button|), if a current dialog exists.
- virtual void DoDialogButtonAction(ui::DialogButton button) = 0;
-
- // Synchronously determine if the specified button exists in the current
- // dialog (if any), along with its label, whether or not it is enabled, and
- // whether or not it is the default button..
- virtual void GetDialogButtonInfo(ui::DialogButton button,
- bool* button_exists,
- base::string16* title,
- bool* is_button_enabled,
- bool* is_button_default) = 0;
-
- // Synchronously return in |buttons_exist| whether or not any buttons exist
- // for the current dialog.
- virtual void GetDoDialogButtonsExist(bool* buttons_exist) = 0;
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_COCOA_BRIDGED_NATIVE_WIDGET_HOST_H_
diff --git a/chromium/ui/views/cocoa/bridged_native_widget_host_impl.h b/chromium/ui/views/cocoa/bridged_native_widget_host_impl.h
index 561f3553ca6..5451da8d177 100644
--- a/chromium/ui/views/cocoa/bridged_native_widget_host_impl.h
+++ b/chromium/ui/views/cocoa/bridged_native_widget_host_impl.h
@@ -6,23 +6,27 @@
#define UI_VIEWS_COCOA_BRIDGED_NATIVE_WIDGET_HOST_IMPL_H_
#include <memory>
+#include <vector>
+#include "base/mac/scoped_nsobject.h"
#include "base/macros.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
#include "ui/accelerated_widget_mac/display_link_mac.h"
#include "ui/base/ime/input_method_delegate.h"
#include "ui/compositor/layer_owner.h"
-#include "ui/views/cocoa/bridged_native_widget_host.h"
+#include "ui/views/cocoa/bridge_factory_host.h"
+#include "ui/views/cocoa/drag_drop_client_mac.h"
#include "ui/views/focus/focus_manager.h"
#include "ui/views/views_export.h"
#include "ui/views/widget/widget.h"
#include "ui/views/window/dialog_observer.h"
+#include "ui/views_bridge_mac/bridged_native_widget_host_helper.h"
+#include "ui/views_bridge_mac/mojo/bridged_native_widget.mojom.h"
+#include "ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom.h"
-namespace views_bridge_mac {
-namespace mojom {
-class BridgedNativeWidget;
-} // namespace mojom
-} // namespace views_bridge_mac
+@class NativeWidgetMacNSWindow;
+@class NSView;
namespace ui {
class RecyclableCompositorMac;
@@ -30,14 +34,16 @@ class RecyclableCompositorMac;
namespace views {
-class BridgedNativeWidget;
+class BridgedNativeWidgetImpl;
class NativeWidgetMac;
// The portion of NativeWidgetMac that lives in the browser process. This
-// communicates to the BridgedNativeWidget, which interacts with the Cocoa
+// communicates to the BridgedNativeWidgetImpl, which interacts with the Cocoa
// APIs, and which may live in an app shim process.
class VIEWS_EXPORT BridgedNativeWidgetHostImpl
- : public BridgedNativeWidgetHost,
+ : public views_bridge_mac::BridgedNativeWidgetHostHelper,
+ public BridgeFactoryHost::Observer,
+ public views_bridge_mac::mojom::BridgedNativeWidgetHost,
public DialogObserver,
public FocusChangeListener,
public ui::internal::InputMethodDelegate,
@@ -45,15 +51,64 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
public ui::LayerOwner,
public ui::AcceleratedWidgetMacNSView {
public:
- // Creates one side of the bridge. |parent| must not be NULL.
- explicit BridgedNativeWidgetHostImpl(NativeWidgetMac* parent);
+ // Retrieves the bridge host associated with the given NSWindow. Returns null
+ // if the supplied handle has no associated Widget.
+ static BridgedNativeWidgetHostImpl* GetFromNativeWindow(
+ gfx::NativeWindow window);
+
+ // Unique integer id handles are used to bridge between the
+ // BridgedNativeWidgetHostImpl in one process and the BridgedNativeWidgetHost
+ // potentially in another.
+ static BridgedNativeWidgetHostImpl* GetFromId(
+ uint64_t bridged_native_widget_id);
+ uint64_t bridged_native_widget_id() const { return widget_id_; }
+
+ // Creates one side of the bridge. |owner| must not be NULL.
+ explicit BridgedNativeWidgetHostImpl(NativeWidgetMac* owner);
~BridgedNativeWidgetHostImpl() override;
- // Provide direct access to the BridgedNativeWidget that this is hosting.
+ // The NativeWidgetMac that owns |this|.
+ views::NativeWidgetMac* native_widget_mac() const {
+ return native_widget_mac_;
+ }
+ BridgedNativeWidgetHostImpl* parent() const { return parent_; }
+ std::vector<BridgedNativeWidgetHostImpl*> children() const {
+ return children_;
+ }
+
+ // The bridge factory that was used to create the true NSWindow for this
+ // widget. This is nullptr for in-process windows.
+ BridgeFactoryHost* bridge_factory_host() const {
+ return bridge_factory_host_;
+ }
+
+ // A NSWindow that is guaranteed to exist in this process. If the bridge
+ // object for this host is in this process, then this points to the bridge's
+ // NSWindow. Otherwise, it mirrors the id and bounds of the child window.
+ NativeWidgetMacNSWindow* GetLocalNSWindow() const;
+
+ // The mojo interface through which to communicate with the underlying
+ // NSWindow and NSView.
+ views_bridge_mac::mojom::BridgedNativeWidget* bridge() const;
+
+ // Direct access to the BridgedNativeWidgetImpl that this is hosting.
// TODO(ccameron): Remove all accesses to this member, and replace them
// with methods that may be sent across processes.
- BridgedNativeWidget* bridge_impl() const { return bridge_impl_.get(); }
- views_bridge_mac::mojom::BridgedNativeWidget* bridge() const;
+ BridgedNativeWidgetImpl* bridge_impl() const { return bridge_impl_.get(); }
+
+ TooltipManager* tooltip_manager() { return tooltip_manager_.get(); }
+
+ DragDropClientMac* drag_drop_client() const {
+ return drag_drop_client_.get();
+ }
+
+ // Create and set the bridge object to be in this process.
+ void CreateLocalBridge(base::scoped_nsobject<NativeWidgetMacNSWindow> window);
+
+ // Create and set the bridge object to be potentially in another process.
+ void CreateRemoteBridge(
+ BridgeFactoryHost* bridge_factory_host,
+ views_bridge_mac::mojom::CreateWindowParamsPtr window_create_params);
void InitWindow(const Widget::InitParams& params);
@@ -75,6 +130,9 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
// Set the root view (set during initialization and un-set during teardown).
void SetRootView(views::View* root_view);
+ // Return the id through which the NSView for |root_view_| may be looked up.
+ uint64_t GetRootViewNSViewId() const { return root_view_id_; }
+
// Initialize the ui::Compositor and ui::Layer.
void CreateCompositor(const Widget::InitParams& params);
@@ -93,14 +151,12 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
// Geometry of the window, in DIPs.
const gfx::Rect& GetWindowBoundsInScreen() const {
- DCHECK(has_received_window_geometry_);
return window_bounds_in_screen_;
}
// Geometry of the content area of the window, in DIPs. Note that this is not
// necessarily the same as the views::View's size.
const gfx::Rect& GetContentBoundsInScreen() const {
- DCHECK(has_received_window_geometry_);
return content_bounds_in_screen_;
}
@@ -111,42 +167,70 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
// fullscreen or transitioning between fullscreen states.
gfx::Rect GetRestoredBounds() const;
+ // Set |parent_| and update the old and new parents' |children_|. It is valid
+ // to set |new_parent| to nullptr. Propagate this to the BridgedNativeWidget.
+ void SetParent(BridgedNativeWidgetHostImpl* new_parent);
+
+ // Properties set and queried by views. Not actually native.
+ void SetNativeWindowProperty(const char* name, void* value);
+ void* GetNativeWindowProperty(const char* name) const;
+
+ // Updates |associated_views_| on NativeViewHost::Attach()/Detach().
+ void SetAssociationForView(const views::View* view, NSView* native_view);
+ void ClearAssociationForView(const views::View* view);
+
+ // Sorts child NSViews according to NativeViewHosts order in views hierarchy.
+ void ReorderChildViews();
+
bool IsVisible() const { return is_visible_; }
bool IsMiniaturized() const { return is_miniaturized_; }
bool IsWindowKey() const { return is_window_key_; }
bool IsMouseCaptureActive() const { return is_mouse_capture_active_; }
+ // Used by NativeWidgetPrivate::GetGlobalCapture.
+ static NSView* GetGlobalCaptureView();
+
private:
- gfx::Vector2d GetBoundsOffsetForParent() const;
void UpdateCompositorProperties();
void DestroyCompositor();
+ void RankNSViewsRecursive(View* view, std::map<NSView*, int>* rank) const;
- // views::BridgedNativeWidgetHost:
+ // BridgedNativeWidgetHostHelper:
NSView* GetNativeViewAccessible() override;
+ void DispatchKeyEvent(ui::KeyEvent* event) override;
+ bool DispatchKeyEventToMenuController(ui::KeyEvent* event) override;
+ void GetWordAt(const gfx::Point& location_in_content,
+ bool* found_word,
+ gfx::DecoratedText* decorated_word,
+ gfx::Point* baseline_point) override;
+ double SheetPositionY() override;
+ views_bridge_mac::DragDropClient* GetDragDropClient() override;
+
+ // BridgeFactoryHost::Observer:
+ void OnBridgeFactoryHostDestroying(BridgeFactoryHost* host) override;
+
+ // views_bridge_mac::mojom::BridgedNativeWidgetHost:
void OnVisibilityChanged(bool visible) override;
+ void OnWindowNativeThemeChanged() override;
void SetViewSize(const gfx::Size& new_size) override;
void SetKeyboardAccessible(bool enabled) override;
void SetIsFirstResponder(bool is_first_responder) override;
void OnMouseCaptureActiveChanged(bool capture_is_active) override;
- void OnScrollEvent(const ui::ScrollEvent& const_event) override;
- void OnMouseEvent(const ui::MouseEvent& const_event) override;
- void OnGestureEvent(const ui::GestureEvent& const_event) override;
- void DispatchKeyEvent(const ui::KeyEvent& const_event,
- bool* event_handled) override;
- void DispatchKeyEventToMenuController(const ui::KeyEvent& const_event,
- bool* event_swallowed,
- bool* event_handled) override;
- void GetHasMenuController(bool* has_menu_controller) override;
- void GetIsDraggableBackgroundAt(const gfx::Point& location_in_content,
+ void OnScrollEvent(std::unique_ptr<ui::Event> event) override;
+ void OnMouseEvent(std::unique_ptr<ui::Event> event) override;
+ void OnGestureEvent(std::unique_ptr<ui::Event> event) override;
+ bool DispatchKeyEventRemote(std::unique_ptr<ui::Event> event,
+ bool* event_handled) override;
+ bool DispatchKeyEventToMenuControllerRemote(std::unique_ptr<ui::Event> event,
+ bool* event_swallowed,
+ bool* event_handled) override;
+ bool GetHasMenuController(bool* has_menu_controller) override;
+ bool GetIsDraggableBackgroundAt(const gfx::Point& location_in_content,
bool* is_draggable_background) override;
- void GetTooltipTextAt(const gfx::Point& location_in_content,
+ bool GetTooltipTextAt(const gfx::Point& location_in_content,
base::string16* new_tooltip_text) override;
- void GetWordAt(const gfx::Point& location_in_content,
- bool* found_word,
- gfx::DecoratedText* decorated_word,
- gfx::Point* baseline_point) override;
- void GetWidgetIsModal(bool* widget_is_modal) override;
- void GetIsFocusedViewTextual(bool* is_textual) override;
+ bool GetWidgetIsModal(bool* widget_is_modal) override;
+ bool GetIsFocusedViewTextual(bool* is_textual) override;
void OnWindowGeometryChanged(
const gfx::Rect& window_bounds_in_screen_dips,
const gfx::Rect& content_bounds_in_screen_dips) override;
@@ -161,12 +245,42 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
bool is_content_first_responder,
bool full_keyboard_access_enabled) override;
void DoDialogButtonAction(ui::DialogButton button) override;
- void GetDialogButtonInfo(ui::DialogButton type,
+ bool GetDialogButtonInfo(ui::DialogButton type,
bool* button_exists,
base::string16* button_label,
bool* is_button_enabled,
bool* is_button_default) override;
- void GetDoDialogButtonsExist(bool* buttons_exist) override;
+ bool GetDoDialogButtonsExist(bool* buttons_exist) override;
+ bool GetShouldShowWindowTitle(bool* should_show_window_title) override;
+ bool GetCanWindowBecomeKey(bool* can_window_become_key) override;
+ bool GetAlwaysRenderWindowAsKey(bool* always_render_as_key) override;
+ bool GetCanWindowClose(bool* can_window_close) override;
+
+ // views_bridge_mac::mojom::BridgedNativeWidgetHost, synchronous callbacks:
+ void DispatchKeyEventRemote(std::unique_ptr<ui::Event> event,
+ DispatchKeyEventRemoteCallback callback) override;
+ void DispatchKeyEventToMenuControllerRemote(
+ std::unique_ptr<ui::Event> event,
+ DispatchKeyEventToMenuControllerRemoteCallback callback) override;
+ void GetHasMenuController(GetHasMenuControllerCallback callback) override;
+ void GetIsDraggableBackgroundAt(
+ const gfx::Point& location_in_content,
+ GetIsDraggableBackgroundAtCallback callback) override;
+ void GetTooltipTextAt(const gfx::Point& location_in_content,
+ GetTooltipTextAtCallback callback) override;
+ void GetWidgetIsModal(GetWidgetIsModalCallback callback) override;
+ void GetIsFocusedViewTextual(
+ GetIsFocusedViewTextualCallback callback) override;
+ void GetDialogButtonInfo(ui::DialogButton button,
+ GetDialogButtonInfoCallback callback) override;
+ void GetDoDialogButtonsExist(
+ GetDoDialogButtonsExistCallback callback) override;
+ void GetShouldShowWindowTitle(
+ GetShouldShowWindowTitleCallback callback) override;
+ void GetCanWindowBecomeKey(GetCanWindowBecomeKeyCallback callback) override;
+ void GetAlwaysRenderWindowAsKey(
+ GetAlwaysRenderWindowAsKeyCallback callback) override;
+ void GetCanWindowClose(GetCanWindowCloseCallback callback) override;
// DialogObserver:
void OnDialogModelChanged() override;
@@ -176,7 +290,9 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
void OnDidChangeFocus(View* focused_before, View* focused_now) override;
// ui::internal::InputMethodDelegate:
- ui::EventDispatchDetails DispatchKeyEventPostIME(ui::KeyEvent* key) override;
+ ui::EventDispatchDetails DispatchKeyEventPostIME(
+ ui::KeyEvent* key,
+ base::OnceCallback<void(bool)> ack_callback) override;
// ui::LayerDelegate:
void OnPaintLayer(const ui::PaintContext& context) override;
@@ -186,17 +302,38 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
// ui::AcceleratedWidgetMacNSView:
void AcceleratedWidgetCALayerParamsUpdated() override;
+ // The id that this bridge may be looked up from.
+ const uint64_t widget_id_;
views::NativeWidgetMac* const native_widget_mac_; // Weak. Owns |this_|.
+ // Parent and child widgets.
+ BridgedNativeWidgetHostImpl* parent_ = nullptr;
+ std::vector<BridgedNativeWidgetHostImpl*> children_;
+
+ // The factory that was used to create |bridge_ptr_|. This must be the same
+ // as |parent_->bridge_factory_host_|.
+ BridgeFactoryHost* bridge_factory_host_ = nullptr;
+
Widget::InitParams::Type widget_type_ = Widget::InitParams::TYPE_WINDOW;
+ // The id that may be used to look up the NSView for |root_view_|.
+ const uint64_t root_view_id_;
views::View* root_view_ = nullptr; // Weak. Owned by |native_widget_mac_|.
+ std::unique_ptr<DragDropClientMac> drag_drop_client_;
- // TODO(ccameron): Rather than instantiate a BridgedNativeWidget here,
- // we will instantiate a mojo BridgedNativeWidget interface to a Cocoa
+ // The mojo pointer to a BridgedNativeWidget, which may exist in another
+ // process.
+ views_bridge_mac::mojom::BridgedNativeWidgetAssociatedPtr bridge_ptr_;
+
+ // TODO(ccameron): Rather than instantiate a BridgedNativeWidgetImpl here,
+ // we will instantiate a mojo BridgedNativeWidgetImpl interface to a Cocoa
// instance that may be in another process.
- std::unique_ptr<BridgedNativeWidget> bridge_impl_;
+ std::unique_ptr<BridgedNativeWidgetImpl> bridge_impl_;
+
+ // Window that is guaranteed to exist in this process (see GetLocalNSWindow).
+ base::scoped_nsobject<NativeWidgetMacNSWindow> local_window_;
+ std::unique_ptr<TooltipManager> tooltip_manager_;
std::unique_ptr<ui::InputMethod> input_method_;
FocusManager* focus_manager_ = nullptr; // Weak. Owned by our Widget.
@@ -209,7 +346,6 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
scoped_refptr<ui::DisplayLinkMac> display_link_;
// The geometry of the window and its contents view, in screen coordinates.
- bool has_received_window_geometry_ = false;
gfx::Rect window_bounds_in_screen_;
gfx::Rect content_bounds_in_screen_;
bool is_visible_ = false;
@@ -222,6 +358,14 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
std::unique_ptr<ui::RecyclableCompositorMac> compositor_;
+ // Properties used by Set/GetNativeWindowProperty.
+ std::map<std::string, void*> native_window_properties_;
+
+ // Contains NativeViewHost->gfx::NativeView associations.
+ std::map<const views::View*, NSView*> associated_views_;
+
+ mojo::AssociatedBinding<views_bridge_mac::mojom::BridgedNativeWidgetHost>
+ host_mojo_binding_;
DISALLOW_COPY_AND_ASSIGN(BridgedNativeWidgetHostImpl);
};
diff --git a/chromium/ui/views/cocoa/bridged_native_widget_host_impl.mm b/chromium/ui/views/cocoa/bridged_native_widget_host_impl.mm
index 53e6a582b6c..63f9be6db98 100644
--- a/chromium/ui/views/cocoa/bridged_native_widget_host_impl.mm
+++ b/chromium/ui/views/cocoa/bridged_native_widget_host_impl.mm
@@ -4,6 +4,8 @@
#include "ui/views/cocoa/bridged_native_widget_host_impl.h"
+#include "base/mac/foundation_util.h"
+#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
#include "ui/base/hit_test.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/input_method_factory.h"
@@ -11,7 +13,9 @@
#include "ui/compositor/recyclable_compositor_mac.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/dip_util.h"
-#include "ui/views/cocoa/bridged_native_widget.h"
+#include "ui/gfx/mac/coordinate_conversion.h"
+#include "ui/native_theme/native_theme_mac.h"
+#include "ui/views/cocoa/tooltip_manager_mac.h"
#include "ui/views/controls/menu/menu_config.h"
#include "ui/views/controls/menu/menu_controller.h"
#include "ui/views/views_delegate.h"
@@ -21,6 +25,9 @@
#include "ui/views/window/dialog_client_view.h"
#include "ui/views/window/dialog_delegate.h"
#include "ui/views/word_lookup_client.h"
+#include "ui/views_bridge_mac/bridged_native_widget_impl.h"
+#include "ui/views_bridge_mac/cocoa_mouse_capture.h"
+#include "ui/views_bridge_mac/native_widget_mac_nswindow.h"
using views_bridge_mac::mojom::BridgedNativeWidgetInitParams;
using views_bridge_mac::mojom::WindowVisibilityState;
@@ -40,14 +47,61 @@ bool PositionWindowInScreenCoordinates(Widget* widget,
return widget && widget->is_top_level();
}
+std::map<uint64_t, BridgedNativeWidgetHostImpl*>& GetIdToWidgetHostImplMap() {
+ static base::NoDestructor<std::map<uint64_t, BridgedNativeWidgetHostImpl*>>
+ id_map;
+ return *id_map;
+}
+
+uint64_t g_last_bridged_native_widget_id = 0;
+
} // namespace
-BridgedNativeWidgetHostImpl::BridgedNativeWidgetHostImpl(
- NativeWidgetMac* parent)
- : native_widget_mac_(parent),
- bridge_impl_(new BridgedNativeWidget(this, parent)) {}
+// static
+BridgedNativeWidgetHostImpl* BridgedNativeWidgetHostImpl::GetFromNativeWindow(
+ gfx::NativeWindow window) {
+ if (NativeWidgetMacNSWindow* widget_window =
+ base::mac::ObjCCast<NativeWidgetMacNSWindow>(window)) {
+ return GetFromId([widget_window bridgedNativeWidgetId]);
+ }
+ return nullptr; // Not created by NativeWidgetMac.
+}
+
+// static
+BridgedNativeWidgetHostImpl* BridgedNativeWidgetHostImpl::GetFromId(
+ uint64_t bridged_native_widget_id) {
+ auto found = GetIdToWidgetHostImplMap().find(bridged_native_widget_id);
+ if (found == GetIdToWidgetHostImplMap().end())
+ return nullptr;
+ return found->second;
+}
+
+BridgedNativeWidgetHostImpl::BridgedNativeWidgetHostImpl(NativeWidgetMac* owner)
+ : widget_id_(++g_last_bridged_native_widget_id),
+ native_widget_mac_(owner),
+ root_view_id_(ui::NSViewIds::GetNewId()),
+ host_mojo_binding_(this) {
+ DCHECK(GetIdToWidgetHostImplMap().find(widget_id_) ==
+ GetIdToWidgetHostImplMap().end());
+ GetIdToWidgetHostImplMap().insert(std::make_pair(widget_id_, this));
+ DCHECK(owner);
+}
BridgedNativeWidgetHostImpl::~BridgedNativeWidgetHostImpl() {
+ DCHECK(children_.empty());
+ if (bridge_factory_host_) {
+ bridge_ptr_.reset();
+ host_mojo_binding_.Unbind();
+ bridge_factory_host_->RemoveObserver(this);
+ bridge_factory_host_ = nullptr;
+ }
+
+ // Ensure that |this| cannot be reached by its id while it is being destroyed.
+ auto found = GetIdToWidgetHostImplMap().find(widget_id_);
+ DCHECK(found != GetIdToWidgetHostImplMap().end());
+ DCHECK_EQ(found->second, this);
+ GetIdToWidgetHostImplMap().erase(found);
+
// Destroy the bridge first to prevent any calls back into this during
// destruction.
// TODO(ccameron): When all communication from |bridge_| to this goes through
@@ -57,26 +111,67 @@ BridgedNativeWidgetHostImpl::~BridgedNativeWidgetHostImpl() {
DestroyCompositor();
}
+NativeWidgetMacNSWindow* BridgedNativeWidgetHostImpl::GetLocalNSWindow() const {
+ return local_window_.get();
+}
+
views_bridge_mac::mojom::BridgedNativeWidget*
BridgedNativeWidgetHostImpl::bridge() const {
- return bridge_impl_.get();
+ if (bridge_ptr_)
+ return bridge_ptr_.get();
+ if (bridge_impl_)
+ return bridge_impl_.get();
+ return nullptr;
+}
+
+void BridgedNativeWidgetHostImpl::CreateLocalBridge(
+ base::scoped_nsobject<NativeWidgetMacNSWindow> window) {
+ local_window_ = window;
+ bridge_impl_ =
+ std::make_unique<BridgedNativeWidgetImpl>(widget_id_, this, this);
+ bridge_impl_->SetWindow(window);
+}
+
+void BridgedNativeWidgetHostImpl::CreateRemoteBridge(
+ BridgeFactoryHost* bridge_factory_host,
+ views_bridge_mac::mojom::CreateWindowParamsPtr window_create_params) {
+ bridge_factory_host_ = bridge_factory_host;
+ bridge_factory_host_->AddObserver(this);
+
+ // Create the local window with the same parameters as will be used in the
+ // other process.
+ local_window_ =
+ BridgedNativeWidgetImpl::CreateNSWindow(window_create_params.get());
+ [local_window_ setBridgedNativeWidgetId:widget_id_];
+
+ // Initialize |bridge_ptr_| to point to a bridge created by |factory|.
+ views_bridge_mac::mojom::BridgedNativeWidgetHostAssociatedPtr host_ptr;
+ host_mojo_binding_.Bind(mojo::MakeRequest(&host_ptr),
+ ui::WindowResizeHelperMac::Get()->task_runner());
+ bridge_factory_host_->GetFactory()->CreateBridgedNativeWidget(
+ widget_id_, mojo::MakeRequest(&bridge_ptr_), host_ptr.PassInterface());
+
+ // Create the window in its process, and attach it to its parent window.
+ bridge()->CreateWindow(std::move(window_create_params));
}
void BridgedNativeWidgetHostImpl::InitWindow(const Widget::InitParams& params) {
+ Widget* widget = native_widget_mac_->GetWidget();
// Tooltip Widgets shouldn't have their own tooltip manager, but tooltips are
// native on Mac, so nothing should ever want one in Widget form.
DCHECK_NE(params.type, Widget::InitParams::TYPE_TOOLTIP);
widget_type_ = params.type;
-
- bridge_impl_->SetParent(params.parent);
+ tooltip_manager_.reset(new TooltipManagerMac(bridge()));
// Initialize the window.
{
auto bridge_params = BridgedNativeWidgetInitParams::New();
- bridge_params->modal_type =
- native_widget_mac_->GetWidget()->widget_delegate()->GetModalType();
+ bridge_params->modal_type = widget->widget_delegate()->GetModalType();
bridge_params->is_translucent =
params.opacity == Widget::InitParams::TRANSLUCENT_WINDOW;
+ bridge_params->widget_is_top_level = widget->is_top_level();
+ bridge_params->position_window_in_screen_coords =
+ PositionWindowInScreenCoordinates(widget, widget_type_);
// OSX likes to put shadows on most things. However, frameless windows (with
// styleMask = NSBorderlessWindowMask) default to no shadow. So change that.
@@ -111,9 +206,11 @@ void BridgedNativeWidgetHostImpl::InitWindow(const Widget::InitParams& params) {
// set at all, the creator of the Widget is expected to call SetBounds()
// before calling Widget::Show() to avoid a kWindowSizeDeterminedLater-sized
// (i.e. 1x1) window appearing.
- bridge()->SetInitialBounds(params.bounds,
- native_widget_mac_->GetWidget()->GetMinimumSize(),
- GetBoundsOffsetForParent());
+ bridge()->SetInitialBounds(params.bounds, widget->GetMinimumSize());
+
+ // TODO(ccameron): Correctly set these based |local_window_|.
+ window_bounds_in_screen_ = params.bounds;
+ content_bounds_in_screen_ = params.bounds;
// Widgets for UI controls (usually layered above web contents) start visible.
if (widget_type_ == Widget::InitParams::TYPE_CONTROL)
@@ -121,21 +218,10 @@ void BridgedNativeWidgetHostImpl::InitWindow(const Widget::InitParams& params) {
}
void BridgedNativeWidgetHostImpl::SetBounds(const gfx::Rect& bounds) {
- gfx::Rect adjusted_bounds = bounds;
- adjusted_bounds.Offset(GetBoundsOffsetForParent());
- bridge()->SetBounds(adjusted_bounds,
+ bridge()->SetBounds(bounds,
native_widget_mac_->GetWidget()->GetMinimumSize());
}
-gfx::Vector2d BridgedNativeWidgetHostImpl::GetBoundsOffsetForParent() const {
- gfx::Vector2d offset;
- Widget* widget = native_widget_mac_->GetWidget();
- BridgedNativeWidgetOwner* parent = bridge_impl_->parent();
- if (parent && !PositionWindowInScreenCoordinates(widget, widget_type_))
- offset = parent->GetChildWindowOffset();
- return offset;
-}
-
void BridgedNativeWidgetHostImpl::SetFullscreen(bool fullscreen) {
// Note that when the NSWindow begins a fullscreen transition, the value of
// |target_fullscreen_state_| updates via OnWindowFullscreenTransitionStart.
@@ -148,6 +234,15 @@ void BridgedNativeWidgetHostImpl::SetFullscreen(bool fullscreen) {
void BridgedNativeWidgetHostImpl::SetRootView(views::View* root_view) {
root_view_ = root_view;
+ if (root_view_) {
+ // TODO(ccameron): Drag-drop functionality does not yet run over mojo.
+ if (bridge_impl_) {
+ drag_drop_client_.reset(
+ new DragDropClientMac(bridge_impl_.get(), root_view_));
+ }
+ } else {
+ drag_drop_client_.reset();
+ }
}
void BridgedNativeWidgetHostImpl::CreateCompositor(
@@ -202,7 +297,7 @@ void BridgedNativeWidgetHostImpl::DestroyCompositor() {
if (layer()) {
// LayerOwner supports a change in ownership, e.g., to animate a closing
// window, but that won't work as expected for the root layer in
- // BridgedNativeWidget.
+ // BridgedNativeWidgetImpl.
DCHECK_EQ(this, layer()->owner());
layer()->CompleteAllAnimations();
layer()->SuppressPaint();
@@ -267,13 +362,129 @@ gfx::Rect BridgedNativeWidgetHostImpl::GetRestoredBounds() const {
return window_bounds_in_screen_;
}
+void BridgedNativeWidgetHostImpl::SetNativeWindowProperty(const char* name,
+ void* value) {
+ if (value)
+ native_window_properties_[name] = value;
+ else
+ native_window_properties_.erase(name);
+}
+
+void* BridgedNativeWidgetHostImpl::GetNativeWindowProperty(
+ const char* name) const {
+ auto found = native_window_properties_.find(name);
+ if (found == native_window_properties_.end())
+ return nullptr;
+ return found->second;
+}
+
+void BridgedNativeWidgetHostImpl::SetParent(
+ BridgedNativeWidgetHostImpl* new_parent) {
+ if (new_parent == parent_)
+ return;
+
+ if (parent_) {
+ auto found =
+ std::find(parent_->children_.begin(), parent_->children_.end(), this);
+ DCHECK(found != parent_->children_.end());
+ parent_->children_.erase(found);
+ }
+
+ parent_ = new_parent;
+ if (parent_) {
+ // We can only re-parent to another Widget if that Widget is hosted in the
+ // same process that we were already hosted by.
+ CHECK_EQ(bridge_factory_host_, parent_->bridge_factory_host());
+ parent_->children_.push_back(this);
+ bridge()->SetParent(parent_->bridged_native_widget_id());
+ } else {
+ bridge()->SetParent(0);
+ }
+}
+
+void BridgedNativeWidgetHostImpl::SetAssociationForView(const View* view,
+ NSView* native_view) {
+ DCHECK_EQ(0u, associated_views_.count(view));
+ associated_views_[view] = native_view;
+ native_widget_mac_->GetWidget()->ReorderNativeViews();
+}
+
+void BridgedNativeWidgetHostImpl::ClearAssociationForView(const View* view) {
+ auto it = associated_views_.find(view);
+ DCHECK(it != associated_views_.end());
+ associated_views_.erase(it);
+}
+
+void BridgedNativeWidgetHostImpl::ReorderChildViews() {
+ std::map<NSView*, int> rank;
+ Widget* widget = native_widget_mac_->GetWidget();
+ RankNSViewsRecursive(widget->GetRootView(), &rank);
+ if (bridge_impl_)
+ bridge_impl_->SortSubviews(std::move(rank));
+}
+
+void BridgedNativeWidgetHostImpl::RankNSViewsRecursive(
+ View* view,
+ std::map<NSView*, int>* rank) const {
+ auto it = associated_views_.find(view);
+ if (it != associated_views_.end())
+ rank->emplace(it->second, rank->size());
+ for (int i = 0; i < view->child_count(); ++i)
+ RankNSViewsRecursive(view->child_at(i), rank);
+}
+
+// static
+NSView* BridgedNativeWidgetHostImpl::GetGlobalCaptureView() {
+ // TODO(ccameron): This will not work across process boundaries.
+ return [CocoaMouseCapture::GetGlobalCaptureWindow() contentView];
+}
+
////////////////////////////////////////////////////////////////////////////////
-// BridgedNativeWidgetHostImpl, views::BridgedNativeWidgetHost:
+// BridgedNativeWidgetHostImpl, views_bridge_mac::BridgedNativeWidgetHostHelper:
NSView* BridgedNativeWidgetHostImpl::GetNativeViewAccessible() {
return root_view_ ? root_view_->GetNativeViewAccessible() : nil;
}
+void BridgedNativeWidgetHostImpl::DispatchKeyEvent(ui::KeyEvent* event) {
+ ignore_result(
+ root_view_->GetWidget()->GetInputMethod()->DispatchKeyEvent(event));
+}
+
+bool BridgedNativeWidgetHostImpl::DispatchKeyEventToMenuController(
+ ui::KeyEvent* event) {
+ MenuController* menu_controller = MenuController::GetActiveInstance();
+ if (menu_controller && root_view_ &&
+ menu_controller->owner() == root_view_->GetWidget()) {
+ return menu_controller->OnWillDispatchKeyEvent(event) ==
+ ui::POST_DISPATCH_NONE;
+ }
+ return false;
+}
+
+double BridgedNativeWidgetHostImpl::SheetPositionY() {
+ return native_widget_mac_->SheetPositionY();
+}
+
+views_bridge_mac::DragDropClient*
+BridgedNativeWidgetHostImpl::GetDragDropClient() {
+ return drag_drop_client_.get();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// BridgedNativeWidgetHostImpl, BridgeFactoryHost::Observer:
+void BridgedNativeWidgetHostImpl::OnBridgeFactoryHostDestroying(
+ BridgeFactoryHost* host) {
+ DCHECK_EQ(host, bridge_factory_host_);
+ bridge_factory_host_->RemoveObserver(this);
+ bridge_factory_host_ = nullptr;
+ // TODO(ccameron): This should be treated as the window closing.
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// BridgedNativeWidgetHostImpl,
+// views_bridge_mac::mojom::BridgedNativeWidgetHost:
+
void BridgedNativeWidgetHostImpl::OnVisibilityChanged(bool window_visible) {
is_visible_ = window_visible;
if (compositor_) {
@@ -289,54 +500,48 @@ void BridgedNativeWidgetHostImpl::OnVisibilityChanged(bool window_visible) {
window_visible);
}
+void BridgedNativeWidgetHostImpl::OnWindowNativeThemeChanged() {
+ ui::NativeTheme::GetInstanceForNativeUi()->NotifyObservers();
+}
+
void BridgedNativeWidgetHostImpl::OnScrollEvent(
- const ui::ScrollEvent& const_event) {
- ui::ScrollEvent event = const_event;
- root_view_->GetWidget()->OnScrollEvent(&event);
+ std::unique_ptr<ui::Event> event) {
+ root_view_->GetWidget()->OnScrollEvent(event->AsScrollEvent());
}
void BridgedNativeWidgetHostImpl::OnMouseEvent(
- const ui::MouseEvent& const_event) {
- ui::MouseEvent event = const_event;
- root_view_->GetWidget()->OnMouseEvent(&event);
+ std::unique_ptr<ui::Event> event) {
+ root_view_->GetWidget()->OnMouseEvent(event->AsMouseEvent());
}
void BridgedNativeWidgetHostImpl::OnGestureEvent(
- const ui::GestureEvent& const_event) {
- ui::GestureEvent event = const_event;
- root_view_->GetWidget()->OnGestureEvent(&event);
+ std::unique_ptr<ui::Event> event) {
+ root_view_->GetWidget()->OnGestureEvent(event->AsGestureEvent());
}
-void BridgedNativeWidgetHostImpl::DispatchKeyEvent(
- const ui::KeyEvent& const_event,
+bool BridgedNativeWidgetHostImpl::DispatchKeyEventRemote(
+ std::unique_ptr<ui::Event> event,
bool* event_handled) {
- ui::KeyEvent event = const_event;
- ignore_result(
- root_view_->GetWidget()->GetInputMethod()->DispatchKeyEvent(&event));
- *event_handled = event.handled();
+ DispatchKeyEvent(event->AsKeyEvent());
+ *event_handled = event->handled();
+ return true;
}
-void BridgedNativeWidgetHostImpl::DispatchKeyEventToMenuController(
- const ui::KeyEvent& const_event,
+bool BridgedNativeWidgetHostImpl::DispatchKeyEventToMenuControllerRemote(
+ std::unique_ptr<ui::Event> event,
bool* event_swallowed,
bool* event_handled) {
- ui::KeyEvent event = const_event;
- MenuController* menu_controller = MenuController::GetActiveInstance();
- if (menu_controller && root_view_ &&
- menu_controller->owner() == root_view_->GetWidget()) {
- *event_swallowed = menu_controller->OnWillDispatchKeyEvent(&event) ==
- ui::POST_DISPATCH_NONE;
- } else {
- *event_swallowed = false;
- }
- *event_handled = event.handled();
+ *event_swallowed = DispatchKeyEventToMenuController(event->AsKeyEvent());
+ *event_handled = event->handled();
+ return true;
}
-void BridgedNativeWidgetHostImpl::GetHasMenuController(
+bool BridgedNativeWidgetHostImpl::GetHasMenuController(
bool* has_menu_controller) {
MenuController* menu_controller = MenuController::GetActiveInstance();
*has_menu_controller = menu_controller && root_view_ &&
menu_controller->owner() == root_view_->GetWidget();
+ return true;
}
void BridgedNativeWidgetHostImpl::SetViewSize(const gfx::Size& new_size) {
@@ -364,15 +569,16 @@ void BridgedNativeWidgetHostImpl::OnMouseCaptureActiveChanged(bool is_active) {
native_widget_mac_->GetWidget()->OnMouseCaptureLost();
}
-void BridgedNativeWidgetHostImpl::GetIsDraggableBackgroundAt(
+bool BridgedNativeWidgetHostImpl::GetIsDraggableBackgroundAt(
const gfx::Point& location_in_content,
bool* is_draggable_background) {
int component =
root_view_->GetWidget()->GetNonClientComponent(location_in_content);
*is_draggable_background = component == HTCAPTION;
+ return true;
}
-void BridgedNativeWidgetHostImpl::GetTooltipTextAt(
+bool BridgedNativeWidgetHostImpl::GetTooltipTextAt(
const gfx::Point& location_in_content,
base::string16* new_tooltip_text) {
views::View* view =
@@ -384,6 +590,7 @@ void BridgedNativeWidgetHostImpl::GetTooltipTextAt(
if (!view->GetTooltipText(view_point, new_tooltip_text))
DCHECK(new_tooltip_text->empty());
}
+ return true;
}
void BridgedNativeWidgetHostImpl::GetWordAt(
@@ -414,22 +621,32 @@ void BridgedNativeWidgetHostImpl::GetWordAt(
*found_word = true;
}
-void BridgedNativeWidgetHostImpl::GetWidgetIsModal(bool* widget_is_modal) {
+bool BridgedNativeWidgetHostImpl::GetWidgetIsModal(bool* widget_is_modal) {
*widget_is_modal = native_widget_mac_->GetWidget()->IsModal();
+ return true;
}
-void BridgedNativeWidgetHostImpl::GetIsFocusedViewTextual(bool* is_textual) {
+bool BridgedNativeWidgetHostImpl::GetIsFocusedViewTextual(bool* is_textual) {
views::FocusManager* focus_manager =
root_view_ ? root_view_->GetWidget()->GetFocusManager() : nullptr;
*is_textual = focus_manager && focus_manager->GetFocusedView() &&
focus_manager->GetFocusedView()->GetClassName() ==
views::Label::kViewClassName;
+ return true;
}
void BridgedNativeWidgetHostImpl::OnWindowGeometryChanged(
const gfx::Rect& new_window_bounds_in_screen,
const gfx::Rect& new_content_bounds_in_screen) {
- has_received_window_geometry_ = true;
+ // If we are accessing the BridgedNativeWidget through mojo, then
+ // |local_window_| is not the true window that was just resized. Update
+ // the frame of |local_window_| to keep it in sync for any native calls
+ // that may use it (e.g, for context menu positioning).
+ if (bridge_ptr_) {
+ [local_window_ setFrame:gfx::ScreenRectToNSRect(new_window_bounds_in_screen)
+ display:NO
+ animate:NO];
+ }
bool window_has_moved =
new_window_bounds_in_screen.origin() != window_bounds_in_screen_.origin();
@@ -478,6 +695,8 @@ void BridgedNativeWidgetHostImpl::OnWindowFullscreenTransitionComplete(
void BridgedNativeWidgetHostImpl::OnWindowMiniaturizedChanged(
bool miniaturized) {
is_miniaturized_ = miniaturized;
+ if (native_widget_mac_)
+ native_widget_mac_->GetWidget()->OnNativeWidgetWindowShowStateChanged();
}
void BridgedNativeWidgetHostImpl::OnWindowDisplayChanged(
@@ -486,7 +705,7 @@ void BridgedNativeWidgetHostImpl::OnWindowDisplayChanged(
display_.device_scale_factor() != new_display.device_scale_factor();
bool display_id_changed = display_.id() != new_display.id();
display_ = new_display;
- if (scale_factor_changed && compositor_ && has_received_window_geometry_) {
+ if (scale_factor_changed && compositor_) {
compositor_->UpdateSurface(
ConvertSizeToPixel(display_.device_scale_factor(),
content_bounds_in_screen_.size()),
@@ -507,9 +726,14 @@ void BridgedNativeWidgetHostImpl::OnWindowWillClose() {
if (DialogDelegate* dialog = widget->widget_delegate()->AsDialogDelegate())
dialog->RemoveObserver(this);
native_widget_mac_->WindowDestroying();
+ // Remove |this| from the parent's list of children.
+ SetParent(nullptr);
}
void BridgedNativeWidgetHostImpl::OnWindowHasClosed() {
+ // OnWindowHasClosed will be called only after all child windows have had
+ // OnWindowWillClose called on them.
+ DCHECK(children_.empty());
native_widget_mac_->WindowDestroyed();
}
@@ -551,7 +775,7 @@ void BridgedNativeWidgetHostImpl::DoDialogButtonAction(
}
}
-void BridgedNativeWidgetHostImpl::GetDialogButtonInfo(
+bool BridgedNativeWidgetHostImpl::GetDialogButtonInfo(
ui::DialogButton button,
bool* button_exists,
base::string16* button_label,
@@ -561,17 +785,154 @@ void BridgedNativeWidgetHostImpl::GetDialogButtonInfo(
ui::DialogModel* model =
root_view_->GetWidget()->widget_delegate()->AsDialogDelegate();
if (!model || !(model->GetDialogButtons() & button))
- return;
+ return true;
*button_exists = true;
*button_label = model->GetDialogButtonLabel(button);
*is_button_enabled = model->IsDialogButtonEnabled(button);
*is_button_default = button == model->GetDefaultDialogButton();
+ return true;
}
-void BridgedNativeWidgetHostImpl::GetDoDialogButtonsExist(bool* buttons_exist) {
+bool BridgedNativeWidgetHostImpl::GetDoDialogButtonsExist(bool* buttons_exist) {
ui::DialogModel* model =
root_view_->GetWidget()->widget_delegate()->AsDialogDelegate();
*buttons_exist = model && model->GetDialogButtons();
+ return true;
+}
+
+bool BridgedNativeWidgetHostImpl::GetShouldShowWindowTitle(
+ bool* should_show_window_title) {
+ *should_show_window_title =
+ root_view_
+ ? root_view_->GetWidget()->widget_delegate()->ShouldShowWindowTitle()
+ : true;
+ return true;
+}
+
+bool BridgedNativeWidgetHostImpl::GetCanWindowBecomeKey(
+ bool* can_window_become_key) {
+ *can_window_become_key =
+ root_view_ ? root_view_->GetWidget()->CanActivate() : false;
+ return true;
+}
+
+bool BridgedNativeWidgetHostImpl::GetAlwaysRenderWindowAsKey(
+ bool* always_render_as_key) {
+ *always_render_as_key =
+ root_view_ ? root_view_->GetWidget()->IsAlwaysRenderAsActive() : false;
+ return true;
+}
+
+bool BridgedNativeWidgetHostImpl::GetCanWindowClose(bool* can_window_close) {
+ *can_window_close = true;
+ views::NonClientView* non_client_view =
+ root_view_ ? root_view_->GetWidget()->non_client_view() : nullptr;
+ if (non_client_view)
+ *can_window_close = non_client_view->CanClose();
+ return true;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// BridgedNativeWidgetHostImpl,
+// views_bridge_mac::mojom::BridgedNativeWidgetHost synchronous callbacks:
+
+void BridgedNativeWidgetHostImpl::DispatchKeyEventRemote(
+ std::unique_ptr<ui::Event> event,
+ DispatchKeyEventRemoteCallback callback) {
+ bool event_handled = false;
+ DispatchKeyEventRemote(std::move(event), &event_handled);
+ std::move(callback).Run(event_handled);
+}
+
+void BridgedNativeWidgetHostImpl::DispatchKeyEventToMenuControllerRemote(
+ std::unique_ptr<ui::Event> event,
+ DispatchKeyEventToMenuControllerRemoteCallback callback) {
+ ui::KeyEvent* key_event = event->AsKeyEvent();
+ bool event_swallowed = DispatchKeyEventToMenuController(key_event);
+ std::move(callback).Run(event_swallowed, key_event->handled());
+}
+
+void BridgedNativeWidgetHostImpl::GetHasMenuController(
+ GetHasMenuControllerCallback callback) {
+ bool has_menu_controller = false;
+ GetHasMenuController(&has_menu_controller);
+ std::move(callback).Run(has_menu_controller);
+}
+
+void BridgedNativeWidgetHostImpl::GetIsDraggableBackgroundAt(
+ const gfx::Point& location_in_content,
+ GetIsDraggableBackgroundAtCallback callback) {
+ bool is_draggable_background = false;
+ GetIsDraggableBackgroundAt(location_in_content, &is_draggable_background);
+ std::move(callback).Run(is_draggable_background);
+}
+
+void BridgedNativeWidgetHostImpl::GetTooltipTextAt(
+ const gfx::Point& location_in_content,
+ GetTooltipTextAtCallback callback) {
+ base::string16 new_tooltip_text;
+ GetTooltipTextAt(location_in_content, &new_tooltip_text);
+ std::move(callback).Run(new_tooltip_text);
+}
+
+void BridgedNativeWidgetHostImpl::GetIsFocusedViewTextual(
+ GetIsFocusedViewTextualCallback callback) {
+ bool is_textual = false;
+ GetIsFocusedViewTextual(&is_textual);
+ std::move(callback).Run(is_textual);
+}
+
+void BridgedNativeWidgetHostImpl::GetWidgetIsModal(
+ GetWidgetIsModalCallback callback) {
+ bool widget_is_modal = false;
+ GetWidgetIsModal(&widget_is_modal);
+ std::move(callback).Run(widget_is_modal);
+}
+
+void BridgedNativeWidgetHostImpl::GetDialogButtonInfo(
+ ui::DialogButton button,
+ GetDialogButtonInfoCallback callback) {
+ bool exists = false;
+ base::string16 label;
+ bool is_enabled = false;
+ bool is_default = false;
+ GetDialogButtonInfo(button, &exists, &label, &is_enabled, &is_default);
+ std::move(callback).Run(exists, label, is_enabled, is_default);
+}
+
+void BridgedNativeWidgetHostImpl::GetDoDialogButtonsExist(
+ GetDoDialogButtonsExistCallback callback) {
+ bool buttons_exist = false;
+ GetDoDialogButtonsExist(&buttons_exist);
+ std::move(callback).Run(buttons_exist);
+}
+
+void BridgedNativeWidgetHostImpl::GetShouldShowWindowTitle(
+ GetShouldShowWindowTitleCallback callback) {
+ bool should_show_window_title = false;
+ GetShouldShowWindowTitle(&should_show_window_title);
+ std::move(callback).Run(should_show_window_title);
+}
+
+void BridgedNativeWidgetHostImpl::GetCanWindowBecomeKey(
+ GetCanWindowBecomeKeyCallback callback) {
+ bool can_window_become_key = false;
+ GetCanWindowBecomeKey(&can_window_become_key);
+ std::move(callback).Run(can_window_become_key);
+}
+
+void BridgedNativeWidgetHostImpl::GetAlwaysRenderWindowAsKey(
+ GetAlwaysRenderWindowAsKeyCallback callback) {
+ bool always_render_as_key = false;
+ GetAlwaysRenderWindowAsKey(&always_render_as_key);
+ std::move(callback).Run(always_render_as_key);
+}
+
+void BridgedNativeWidgetHostImpl::GetCanWindowClose(
+ GetCanWindowCloseCallback callback) {
+ bool can_window_close = false;
+ GetCanWindowClose(&can_window_close);
+ std::move(callback).Run(can_window_close);
}
////////////////////////////////////////////////////////////////////////////////
@@ -598,20 +959,25 @@ void BridgedNativeWidgetHostImpl::OnDidChangeFocus(View* focused_before,
// Sanity check: When focus moves away from the widget (i.e. |focused_now|
// is nil), then the textInputClient will be cleared.
DCHECK(!!focused_now || !input_client);
- bridge_impl_->SetTextInputClient(input_client);
+ // TODO(ccameron): TextInputClient is not handled across process borders
+ // yet.
+ if (bridge_impl_)
+ bridge_impl_->SetTextInputClient(input_client);
}
}
////////////////////////////////////////////////////////////////////////////////
-// BridgedNativeWidget, internal::InputMethodDelegate:
+// BridgedNativeWidgetImpl, internal::InputMethodDelegate:
ui::EventDispatchDetails BridgedNativeWidgetHostImpl::DispatchKeyEventPostIME(
- ui::KeyEvent* key) {
+ ui::KeyEvent* key,
+ base::OnceCallback<void(bool)> ack_callback) {
DCHECK(focus_manager_);
if (!focus_manager_->OnKeyEvent(*key))
key->StopPropagation();
else
native_widget_mac_->GetWidget()->OnKeyEvent(key);
+ CallDispatchKeyEventPostIMEAck(key, std::move(ack_callback));
return ui::EventDispatchDetails();
}
diff --git a/chromium/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm b/chromium/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm
index 53c32814537..38f71672f2e 100644
--- a/chromium/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm
+++ b/chromium/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#import "ui/views/cocoa/bridged_native_widget.h"
+#import "ui/views_bridge_mac/bridged_native_widget_impl.h"
#import <Cocoa/Cocoa.h>
@@ -251,7 +251,7 @@ void WaitForEvent(NSUInteger mask) {
} // namespace
// This is used to inject test versions of NativeFrameView and
-// BridgedNativeWidget.
+// BridgedNativeWidgetImpl.
class HitTestNativeWidgetMac : public NativeWidgetMac {
public:
HitTestNativeWidgetMac(internal::NativeWidgetDelegate* delegate,
diff --git a/chromium/ui/views/cocoa/bridged_native_widget_owner.h b/chromium/ui/views/cocoa/bridged_native_widget_owner.h
deleted file mode 100644
index 9869ed5a938..00000000000
--- a/chromium/ui/views/cocoa/bridged_native_widget_owner.h
+++ /dev/null
@@ -1,44 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_COCOA_BRIDGED_NATIVE_WIDGET_OWNER_H_
-#define UI_VIEWS_COCOA_BRIDGED_NATIVE_WIDGET_OWNER_H_
-
-namespace gfx {
-class Vector2d;
-}
-
-@class NSWindow;
-
-namespace views {
-
-class BridgedNativeWidget;
-
-// An abstract interface wrapping an NSWindow that ties the lifetime of one or
-// more child BridgedNativeWidgets to the lifetime of that NSWindow. This is not
-// simply an NSWindow, because the child window API provided by NSWindow
-// requires child windows to always be visible.
-class BridgedNativeWidgetOwner {
- public:
- // The NSWindow parent.
- virtual NSWindow* GetNSWindow() = 0;
-
- // The offset in screen pixels for positioning child windows owned by |this|.
- virtual gfx::Vector2d GetChildWindowOffset() const = 0;
-
- // Return false if |this| is hidden, or has a hidden ancestor.
- virtual bool IsVisibleParent() const = 0;
-
- // Removes a child window. Note |this| may be deleted after calling, so the
- // caller should immediately null out the pointer used to make the call.
- virtual void RemoveChildWindow(BridgedNativeWidget* child) = 0;
-
- protected:
- // Instances of this class may be self-deleting.
- virtual ~BridgedNativeWidgetOwner() {}
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_COCOA_BRIDGED_NATIVE_WIDGET_OWNER_H_
diff --git a/chromium/ui/views/cocoa/bridged_native_widget_unittest.mm b/chromium/ui/views/cocoa/bridged_native_widget_unittest.mm
index 8f3abc65650..3a2248849fd 100644
--- a/chromium/ui/views/cocoa/bridged_native_widget_unittest.mm
+++ b/chromium/ui/views/cocoa/bridged_native_widget_unittest.mm
@@ -2,9 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#import "ui/views/cocoa/bridged_native_widget.h"
+#import "ui/views_bridge_mac/bridged_native_widget_impl.h"
#import <Cocoa/Cocoa.h>
+#include <objc/runtime.h>
#include <memory>
@@ -25,10 +26,7 @@
#include "ui/base/test/material_design_controller_test_api.h"
#include "ui/events/test/cocoa_test_event_utils.h"
#import "ui/gfx/mac/coordinate_conversion.h"
-#import "ui/views/cocoa/bridged_content_view.h"
#import "ui/views/cocoa/bridged_native_widget_host_impl.h"
-#import "ui/views/cocoa/native_widget_mac_nswindow.h"
-#import "ui/views/cocoa/views_nswindow_delegate.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/controls/textfield/textfield_controller.h"
#include "ui/views/controls/textfield/textfield_model.h"
@@ -38,6 +36,9 @@
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
+#import "ui/views_bridge_mac/bridged_content_view.h"
+#import "ui/views_bridge_mac/native_widget_mac_nswindow.h"
+#import "ui/views_bridge_mac/views_nswindow_delegate.h"
using base::ASCIIToUTF16;
using base::SysNSStringToUTF8;
@@ -121,8 +122,8 @@ NSArray* const kDeleteActions = @[
@"deleteToBeginningOfParagraph:", @"deleteToEndOfParagraph:"
];
-NSArray* const kMiscActions =
- @[ @"insertText:", @"cancelOperation:", @"transpose:", @"yank:" ];
+// This omits @"insertText:":. See BridgedNativeWidgetTest.NilTextInputClient.
+NSArray* const kMiscActions = @[ @"cancelOperation:", @"transpose:", @"yank:" ];
// Empty range shortcut for readibility.
NSRange EmptyRange() {
@@ -293,12 +294,12 @@ NSTextInputContext* g_fake_current_input_context = nullptr;
namespace views {
namespace test {
-// Provides the |parent| argument to construct a BridgedNativeWidget.
+// Provides the |parent| argument to construct a BridgedNativeWidgetImpl.
class MockNativeWidgetMac : public NativeWidgetMac {
public:
explicit MockNativeWidgetMac(internal::NativeWidgetDelegate* delegate)
: NativeWidgetMac(delegate) {}
- using NativeWidgetMac::bridge;
+ using NativeWidgetMac::bridge_impl;
using NativeWidgetMac::bridge_host_for_testing;
// internal::NativeWidgetPrivate:
@@ -311,7 +312,12 @@ class MockNativeWidgetMac : public NativeWidgetMac {
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO]);
- bridge()->SetWindow(window);
+ bridge_host_for_testing()->CreateLocalBridge(window);
+ if (BridgedNativeWidgetHostImpl* parent =
+ BridgedNativeWidgetHostImpl::GetFromNativeWindow(
+ [params.parent window])) {
+ bridge_host_for_testing()->SetParent(parent);
+ }
bridge_host_for_testing()->InitWindow(params);
// Usually the bridge gets initialized here. It is skipped to run extra
@@ -330,7 +336,7 @@ class MockNativeWidgetMac : public NativeWidgetMac {
DISALLOW_COPY_AND_ASSIGN(MockNativeWidgetMac);
};
-// Helper test base to construct a BridgedNativeWidget with a valid parent.
+// Helper test base to construct a BridgedNativeWidgetImpl with a valid parent.
class BridgedNativeWidgetTestBase : public ui::CocoaTest {
public:
struct SkipInitialization {};
@@ -342,11 +348,27 @@ class BridgedNativeWidgetTestBase : public ui::CocoaTest {
explicit BridgedNativeWidgetTestBase(SkipInitialization tag)
: native_widget_mac_(nullptr) {}
- BridgedNativeWidget* bridge() { return native_widget_mac_->bridge(); }
+ BridgedNativeWidgetImpl* bridge() {
+ return native_widget_mac_->bridge_impl();
+ }
BridgedNativeWidgetHostImpl* bridge_host() {
return native_widget_mac_->bridge_host_for_testing();
}
+ // Generate an autoreleased KeyDown NSEvent* in |widget_| for pressing the
+ // corresponding |key_code|.
+ NSEvent* VkeyKeyDown(ui::KeyboardCode key_code) {
+ return cocoa_test_event_utils::SynthesizeKeyEvent(
+ widget_->GetNativeWindow(), true /* keyDown */, key_code, 0);
+ }
+
+ // Generate an autoreleased KeyDown NSEvent* using the given keycode, and
+ // representing the first unicode character of |chars|.
+ NSEvent* UnicodeKeyDown(int key_code, NSString* chars) {
+ return cocoa_test_event_utils::KeyEventWithKeyCode(
+ key_code, [chars characterAtIndex:0], NSKeyDown, 0);
+ }
+
// Overridden from testing::Test:
void SetUp() override {
ui::CocoaTest::SetUp();
@@ -385,7 +407,9 @@ class BridgedNativeWidgetTestBase : public ui::CocoaTest {
}
NSWindow* bridge_window() const {
- return native_widget_mac_->bridge()->ns_window();
+ if (native_widget_mac_->bridge_impl())
+ return native_widget_mac_->bridge_impl()->ns_window();
+ return nil;
}
protected:
@@ -614,7 +638,8 @@ void BridgedNativeWidgetTest::SetUp() {
// The delegate should exist before setting the root view.
EXPECT_TRUE([window delegate]);
bridge_host()->SetRootView(view_.get());
- bridge()->CreateContentView(view_->bounds());
+ bridge()->CreateContentView(bridge_host()->GetRootViewNSViewId(),
+ view_->bounds());
ns_view_ = bridge()->ns_view();
// Pretend it has been shown via NativeWidgetMac::Show().
@@ -853,7 +878,7 @@ class BridgedNativeWidgetInitTest : public BridgedNativeWidgetTestBase {
DISALLOW_COPY_AND_ASSIGN(BridgedNativeWidgetInitTest);
};
-// Test that BridgedNativeWidget remains sane if Init() is never called.
+// Test that BridgedNativeWidgetImpl remains sane if Init() is never called.
TEST_F(BridgedNativeWidgetInitTest, InitNotCalled) {
// Don't use a Widget* as the delegate. ~Widget() checks for Widget::
// |native_widget_destroyed_| being set to true. That can only happen with a
@@ -862,8 +887,8 @@ TEST_F(BridgedNativeWidgetInitTest, InitNotCalled) {
std::unique_ptr<MockNativeWidgetMac> native_widget(
new MockNativeWidgetMac(nullptr));
native_widget_mac_ = native_widget.get();
- EXPECT_FALSE(bridge()->ns_view());
- EXPECT_FALSE(bridge()->ns_window());
+ EXPECT_FALSE(bridge());
+ EXPECT_FALSE(bridge_host()->GetLocalNSWindow());
}
// Tests the shadow type given in InitParams.
@@ -1323,10 +1348,16 @@ TEST_F(BridgedNativeWidgetTest, NilTextInputClient) {
[selectors addObjectsFromArray:kMoveActions];
[selectors addObjectsFromArray:kSelectActions];
[selectors addObjectsFromArray:kDeleteActions];
+
+ // -insertText: is omitted from this list to avoid a DCHECK in
+ // doCommandBySelector:. AppKit never passes -insertText: to
+ // doCommandBySelector: (it calls -insertText: directly instead).
[selectors addObjectsFromArray:kMiscActions];
for (NSString* selector in selectors)
[ns_view_ doCommandBySelector:NSSelectorFromString(selector)];
+
+ [ns_view_ insertText:@""];
}
// Test transpose command against expectations set by |dummy_text_view_|.
@@ -1434,27 +1465,22 @@ TEST_F(BridgedNativeWidgetTest, TextInput_SimulatePhoneticIme) {
// Sequence of calls (and corresponding keyDown events) obtained via tracing
// with 2-Set Korean IME and pressing q, o, then Enter on the keyboard.
- NSEvent* q_in_ime = cocoa_test_event_utils::KeyEventWithKeyCode(
- 12, [@"ㅂ" characterAtIndex:0], NSKeyDown, 0);
+ NSEvent* q_in_ime = UnicodeKeyDown(12, @"ㅂ");
InterpretKeyEventsCallback handle_q_in_ime = base::BindRepeating([](id view) {
[view insertText:@"ㅂ" replacementRange:NSMakeRange(NSNotFound, 0)];
});
- NSEvent* o_in_ime = cocoa_test_event_utils::KeyEventWithKeyCode(
- 31, [@"ㅐ" characterAtIndex:0], NSKeyDown, 0);
+ NSEvent* o_in_ime = UnicodeKeyDown(31, @"ㅐ");
InterpretKeyEventsCallback handle_o_in_ime = base::BindRepeating([](id view) {
[view insertText:@"배" replacementRange:NSMakeRange(0, 1)];
});
- NSEvent* return_in_ime = cocoa_test_event_utils::SynthesizeKeyEvent(
- widget_->GetNativeWindow(), true, ui::VKEY_RETURN, 0);
InterpretKeyEventsCallback handle_return_in_ime =
base::BindRepeating([](id view) {
// When confirming the composition, AppKit repeats itself.
[view insertText:@"배" replacementRange:NSMakeRange(0, 1)];
[view insertText:@"배" replacementRange:NSMakeRange(0, 1)];
- // Note: there is no insertText:@"\r", which we would normally see when
- // not in an IME context for VKEY_RETURN.
+ [view doCommandBySelector:@selector(insertNewLine:)];
});
// Add a hook for the KeyEvent being received by the TextfieldController. E.g.
@@ -1486,7 +1512,7 @@ TEST_F(BridgedNativeWidgetTest, TextInput_SimulatePhoneticIme) {
// Note the "Enter" should not replace the replacement range, even though a
// replacement range was set.
g_fake_interpret_key_events = &handle_return_in_ime;
- [ns_view_ keyDown:return_in_ime];
+ [ns_view_ keyDown:VkeyKeyDown(ui::VKEY_RETURN)];
EXPECT_EQ(base::SysNSStringToUTF16(@"배"), textfield->text());
// VKEY_RETURN should be seen by via the unhandled key event handler (but not
@@ -1496,6 +1522,76 @@ TEST_F(BridgedNativeWidgetTest, TextInput_SimulatePhoneticIme) {
g_fake_interpret_key_events = nullptr;
}
+// Test simulated codepaths for typing 'm', 'o', 'o', Enter in the Telex IME.
+// This IME does not mark text, but, unlike 2-set Korean, it re-inserts the
+// entire word on each keypress, even though only the last character in the word
+// can be modified. This prevents the keypress being treated as a "character"
+// event (which is unavoidably unfortunate for the Undo buffer), but also led to
+// a codepath that suppressed a VKEY_RETURN when it should not, since there is
+// no candidate IME window to dismiss for this IME.
+TEST_F(BridgedNativeWidgetTest, TextInput_SimulateTelexMoo) {
+ Textfield* textfield = InstallTextField("");
+ EXPECT_TRUE([ns_view_ textInputClient]);
+
+ EnterAcceleratorView* enter_view = new EnterAcceleratorView();
+ textfield->parent()->AddChildView(enter_view);
+
+ // Sequence of calls (and corresponding keyDown events) obtained via tracing
+ // with Telex IME and pressing 'm', 'o', 'o', then Enter on the keyboard.
+ // Note that without the leading 'm', only one character changes, which could
+ // allow the keypress to be treated as a character event, which would not
+ // produce the bug.
+ NSEvent* m_in_ime = UnicodeKeyDown(46, @"m");
+ InterpretKeyEventsCallback handle_m_in_ime = base::BindRepeating([](id view) {
+ [view insertText:@"m" replacementRange:NSMakeRange(NSNotFound, 0)];
+ });
+
+ // Note that (unlike Korean IME), Telex generates a latin "o" for both events:
+ // it doesn't associate a unicode character on the second NSEvent.
+ NSEvent* o_in_ime = UnicodeKeyDown(31, @"o");
+ InterpretKeyEventsCallback handle_first_o_in_ime =
+ base::BindRepeating([](id view) {
+ // Note the whole word is replaced, not just the last character.
+ [view insertText:@"mo" replacementRange:NSMakeRange(0, 1)];
+ });
+ InterpretKeyEventsCallback handle_second_o_in_ime =
+ base::BindRepeating([](id view) {
+ [view insertText:@"mô" replacementRange:NSMakeRange(0, 2)];
+ });
+
+ InterpretKeyEventsCallback handle_return_in_ime =
+ base::BindRepeating([](id view) {
+ // Note the previous -insertText: repeats, even though it is unchanged.
+ // But the IME also follows with an -insertNewLine:.
+ [view insertText:@"mô" replacementRange:NSMakeRange(0, 2)];
+ [view doCommandBySelector:@selector(insertNewLine:)];
+ });
+
+ EXPECT_EQ(base::UTF8ToUTF16(""), textfield->text());
+ EXPECT_EQ(0, enter_view->count());
+
+ object_setClass(ns_view_, [InterpretKeyEventMockedBridgedContentView class]);
+ g_fake_interpret_key_events = &handle_m_in_ime;
+ [ns_view_ keyDown:m_in_ime];
+ EXPECT_EQ(base::SysNSStringToUTF16(@"m"), textfield->text());
+ EXPECT_EQ(0, enter_view->count());
+
+ g_fake_interpret_key_events = &handle_first_o_in_ime;
+ [ns_view_ keyDown:o_in_ime];
+ EXPECT_EQ(base::SysNSStringToUTF16(@"mo"), textfield->text());
+ EXPECT_EQ(0, enter_view->count());
+
+ g_fake_interpret_key_events = &handle_second_o_in_ime;
+ [ns_view_ keyDown:o_in_ime];
+ EXPECT_EQ(base::SysNSStringToUTF16(@"mô"), textfield->text());
+ EXPECT_EQ(0, enter_view->count());
+
+ g_fake_interpret_key_events = &handle_return_in_ime;
+ [ns_view_ keyDown:VkeyKeyDown(ui::VKEY_RETURN)];
+ EXPECT_EQ(base::SysNSStringToUTF16(@"mô"), textfield->text()); // No change.
+ EXPECT_EQ(1, enter_view->count()); // Now we see the accelerator.
+}
+
// Simulate 'a', Enter in Hiragana. This should just insert "あ", suppressing
// accelerators.
TEST_F(BridgedNativeWidgetTest, TextInput_NoAcceleratorEnterComposition) {
@@ -1507,8 +1603,8 @@ TEST_F(BridgedNativeWidgetTest, TextInput_NoAcceleratorEnterComposition) {
// Sequence of calls (and corresponding keyDown events) obtained via tracing
// with Hiragana IME and pressing 'a', then Enter on the keyboard.
- NSEvent* a_in_ime = cocoa_test_event_utils::KeyEventWithKeyCode(
- 0, [@"a" characterAtIndex:0], NSKeyDown, 0);
+ // Note 0 is the actual keyCode for 'a', not a placeholder.
+ NSEvent* a_in_ime = UnicodeKeyDown(0, @"a");
InterpretKeyEventsCallback handle_a_in_ime = base::BindRepeating([](id view) {
// TODO(crbug/612675): |text| should be an NSAttributedString.
[view setMarkedText:@"あ"
@@ -1516,12 +1612,13 @@ TEST_F(BridgedNativeWidgetTest, TextInput_NoAcceleratorEnterComposition) {
replacementRange:NSMakeRange(NSNotFound, 0)];
});
- NSEvent* return_event = cocoa_test_event_utils::SynthesizeKeyEvent(
- widget_->GetNativeWindow(), true, ui::VKEY_RETURN, 0);
- InterpretKeyEventsCallback handle_return_in_ime =
+ InterpretKeyEventsCallback handle_first_return_in_ime =
base::BindRepeating([](id view) {
[view insertText:@"あ" replacementRange:NSMakeRange(NSNotFound, 0)];
+ // Note there is no call to -insertNewLine: here.
});
+ InterpretKeyEventsCallback handle_second_return_in_ime = base::BindRepeating(
+ [](id view) { [view doCommandBySelector:@selector(insertNewLine:)]; });
EXPECT_EQ(base::UTF8ToUTF16(""), textfield->text());
EXPECT_EQ(0, enter_view->count());
@@ -1532,16 +1629,14 @@ TEST_F(BridgedNativeWidgetTest, TextInput_NoAcceleratorEnterComposition) {
EXPECT_EQ(base::SysNSStringToUTF16(@"あ"), textfield->text());
EXPECT_EQ(0, enter_view->count());
- g_fake_interpret_key_events = &handle_return_in_ime;
- [ns_view_ keyDown:return_event];
+ g_fake_interpret_key_events = &handle_first_return_in_ime;
+ [ns_view_ keyDown:VkeyKeyDown(ui::VKEY_RETURN)];
EXPECT_EQ(base::SysNSStringToUTF16(@"あ"), textfield->text());
EXPECT_EQ(0, enter_view->count()); // Not seen as an accelerator.
- // IME Window is dismissed here and there is no marked text, so remove the
- // swizzler.
- object_setClass(ns_view_, [BridgedContentView class]);
-
- [ns_view_ keyDown:return_event]; // Sanity check: send Enter again.
+ g_fake_interpret_key_events = &handle_second_return_in_ime;
+ [ns_view_
+ keyDown:VkeyKeyDown(ui::VKEY_RETURN)]; // Sanity check: send Enter again.
EXPECT_EQ(base::SysNSStringToUTF16(@"あ"), textfield->text()); // No change.
EXPECT_EQ(1, enter_view->count()); // Now we see the accelerator.
}
@@ -1557,8 +1652,7 @@ TEST_F(BridgedNativeWidgetTest, TextInput_NoAcceleratorTabEnterComposition) {
// Sequence of calls (and corresponding keyDown events) obtained via tracing
// with Hiragana IME and pressing 'a', Tab, then Enter on the keyboard.
- NSEvent* a_in_ime = cocoa_test_event_utils::KeyEventWithKeyCode(
- 0, [@"a" characterAtIndex:0], NSKeyDown, 0);
+ NSEvent* a_in_ime = UnicodeKeyDown(0, @"a");
InterpretKeyEventsCallback handle_a_in_ime = base::BindRepeating([](id view) {
// TODO(crbug/612675): |text| should have an underline.
[view setMarkedText:@"あ"
@@ -1566,8 +1660,6 @@ TEST_F(BridgedNativeWidgetTest, TextInput_NoAcceleratorTabEnterComposition) {
replacementRange:NSMakeRange(NSNotFound, 0)];
});
- NSEvent* tab_in_ime = cocoa_test_event_utils::SynthesizeKeyEvent(
- widget_->GetNativeWindow(), true, ui::VKEY_TAB, 0);
InterpretKeyEventsCallback handle_tab_in_ime =
base::BindRepeating([](id view) {
// TODO(crbug/612675): |text| should be an NSAttributedString (now with
@@ -1575,10 +1667,9 @@ TEST_F(BridgedNativeWidgetTest, TextInput_NoAcceleratorTabEnterComposition) {
[view setMarkedText:@"a"
selectedRange:NSMakeRange(0, 1)
replacementRange:NSMakeRange(NSNotFound, 0)];
+ // Note there is no -insertTab: generated.
});
- NSEvent* return_event = cocoa_test_event_utils::SynthesizeKeyEvent(
- widget_->GetNativeWindow(), true, ui::VKEY_RETURN, 0);
InterpretKeyEventsCallback handle_first_return_in_ime =
base::BindRepeating([](id view) {
// Do *nothing*. Enter does not confirm nor change the composition, it
@@ -1589,6 +1680,11 @@ TEST_F(BridgedNativeWidgetTest, TextInput_NoAcceleratorTabEnterComposition) {
// The second return will confirm the composition.
[view insertText:@"a" replacementRange:NSMakeRange(NSNotFound, 0)];
});
+ InterpretKeyEventsCallback handle_third_return_in_ime =
+ base::BindRepeating([](id view) {
+ // Only the third return will generate -insertNewLine:.
+ [view doCommandBySelector:@selector(insertNewLine:)];
+ });
EXPECT_EQ(base::UTF8ToUTF16(""), textfield->text());
EXPECT_EQ(0, enter_view->count());
@@ -1600,28 +1696,26 @@ TEST_F(BridgedNativeWidgetTest, TextInput_NoAcceleratorTabEnterComposition) {
EXPECT_EQ(0, enter_view->count());
g_fake_interpret_key_events = &handle_tab_in_ime;
- [ns_view_ keyDown:tab_in_ime];
+ [ns_view_ keyDown:VkeyKeyDown(ui::VKEY_TAB)];
// Tab will switch to a Romanji (Latin) character.
EXPECT_EQ(base::SysNSStringToUTF16(@"a"), textfield->text());
EXPECT_EQ(0, enter_view->count());
g_fake_interpret_key_events = &handle_first_return_in_ime;
- [ns_view_ keyDown:return_event];
+ [ns_view_ keyDown:VkeyKeyDown(ui::VKEY_RETURN)];
// Enter just dismisses the IME window. The composition is still active.
EXPECT_EQ(base::SysNSStringToUTF16(@"a"), textfield->text());
EXPECT_EQ(0, enter_view->count()); // Not seen as an accelerator.
g_fake_interpret_key_events = &handle_second_return_in_ime;
- [ns_view_ keyDown:return_event];
+ [ns_view_ keyDown:VkeyKeyDown(ui::VKEY_RETURN)];
// Enter now confirms the composition (unmarks text). Note there is still no
// IME window visible but, since there is marked text, IME is still active.
EXPECT_EQ(base::SysNSStringToUTF16(@"a"), textfield->text());
EXPECT_EQ(0, enter_view->count()); // Not seen as an accelerator.
- // No marked text, no IME window. We could remove the swizzler here, but
- // that is equivalent to the "do nothing" case, so set than handler again.
- g_fake_interpret_key_events = &handle_first_return_in_ime;
- [ns_view_ keyDown:return_event]; // Send Enter a _third_ time.
+ g_fake_interpret_key_events = &handle_third_return_in_ime;
+ [ns_view_ keyDown:VkeyKeyDown(ui::VKEY_RETURN)]; // Send Enter a third time.
EXPECT_EQ(base::SysNSStringToUTF16(@"a"), textfield->text()); // No change.
EXPECT_EQ(1, enter_view->count()); // Now we see the accelerator.
}
@@ -1754,8 +1848,8 @@ TEST_F(BridgedNativeWidgetSimulateFullscreenTest, FailToEnterAndExit) {
object:window];
// On a failure, Cocoa starts by sending an unexpected *exit* fullscreen, and
- // BridgedNativeWidget will think it's just a delayed transition and try to go
- // back into fullscreen but get ignored by Cocoa.
+ // BridgedNativeWidgetImpl will think it's just a delayed transition and try
+ // to go back into fullscreen but get ignored by Cocoa.
EXPECT_EQ(0, [window ignoredToggleFullScreenCount]);
EXPECT_TRUE(bridge()->target_fullscreen_state());
[center postNotificationName:NSWindowDidExitFullScreenNotification
diff --git a/chromium/ui/views/cocoa/cocoa_mouse_capture_unittest.mm b/chromium/ui/views/cocoa/cocoa_mouse_capture_unittest.mm
index 47235a7fcff..295e0617cd8 100644
--- a/chromium/ui/views/cocoa/cocoa_mouse_capture_unittest.mm
+++ b/chromium/ui/views/cocoa/cocoa_mouse_capture_unittest.mm
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#import "ui/views/cocoa/cocoa_mouse_capture.h"
+#import "ui/views_bridge_mac/cocoa_mouse_capture.h"
#import <Cocoa/Cocoa.h>
@@ -10,7 +10,7 @@
#include "base/macros.h"
#import "ui/base/test/cocoa_helper.h"
#import "ui/events/test/cocoa_test_event_utils.h"
-#import "ui/views/cocoa/cocoa_mouse_capture_delegate.h"
+#import "ui/views_bridge_mac/cocoa_mouse_capture_delegate.h"
// Simple test view that counts calls to -[NSView mouseDown:].
@interface CocoaMouseCaptureTestView : NSView {
@@ -30,7 +30,7 @@
@end
-namespace views {
+namespace views_bridge_mac {
namespace {
// Simple capture delegate that just counts events forwarded.
@@ -128,4 +128,4 @@ TEST_F(CocoaMouseCaptureTest, CaptureEvents) {
EXPECT_EQ(2, [view mouseDownCount]);
}
-} // namespace views
+} // namespace views_bridge_mac
diff --git a/chromium/ui/views/cocoa/drag_drop_client_mac.h b/chromium/ui/views/cocoa/drag_drop_client_mac.h
index 2e1129957b4..e93d8a09441 100644
--- a/chromium/ui/views/cocoa/drag_drop_client_mac.h
+++ b/chromium/ui/views/cocoa/drag_drop_client_mac.h
@@ -14,6 +14,7 @@
#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/views/views_export.h"
#include "ui/views/widget/drop_helper.h"
+#include "ui/views_bridge_mac/drag_drop_client.h"
// This class acts as a bridge between NSPasteboardItem and OSExchangeData by
// implementing NSPasteboardItemDataProvider and writing data from
@@ -32,16 +33,16 @@ namespace test {
class DragDropClientMacTest;
}
-class BridgedNativeWidget;
+class BridgedNativeWidgetImpl;
class View;
// Implements drag and drop on MacViews. This class acts as a bridge between
// the Views and native system's drag and drop. This class mimics
// DesktopDragDropClientAuraX11.
-class VIEWS_EXPORT DragDropClientMac {
+class VIEWS_EXPORT DragDropClientMac : public views_bridge_mac::DragDropClient {
public:
- explicit DragDropClientMac(BridgedNativeWidget* bridge, View* root_view);
- ~DragDropClientMac();
+ DragDropClientMac(BridgedNativeWidgetImpl* bridge, View* root_view);
+ ~DragDropClientMac() override;
// Initiates a drag and drop session. Returns the drag operation that was
// applied at the end of the drag drop session.
@@ -50,20 +51,14 @@ class VIEWS_EXPORT DragDropClientMac {
int operation,
ui::DragDropTypes::DragEventSource source);
- // Called when mouse is dragged during a drag and drop.
- NSDragOperation DragUpdate(id<NSDraggingInfo>);
-
- // Called when mouse is released during a drag and drop.
- NSDragOperation Drop(id<NSDraggingInfo> sender);
-
- // Called when the drag and drop session has ended.
- void EndDrag();
-
- // Called when mouse leaves the drop area.
- void DragExit();
-
DropHelper* drop_helper() { return &drop_helper_; }
+ // views_bridge_mac::DragDropClient:
+ NSDragOperation DragUpdate(id<NSDraggingInfo>) override;
+ NSDragOperation Drop(id<NSDraggingInfo> sender) override;
+ void EndDrag() override;
+ void DragExit() override;
+
private:
friend class test::DragDropClientMacTest;
@@ -80,7 +75,7 @@ class VIEWS_EXPORT DragDropClientMac {
int operation_;
// The bridge between the content view and the drag drop client.
- BridgedNativeWidget* bridge_; // Weak. Owns |this|.
+ BridgedNativeWidgetImpl* bridge_; // Weak. Owns |this|.
// The closure for the drag and drop's run loop.
base::Closure quit_closure_;
diff --git a/chromium/ui/views/cocoa/drag_drop_client_mac.mm b/chromium/ui/views/cocoa/drag_drop_client_mac.mm
index 78e7b0b3226..2df33355f9e 100644
--- a/chromium/ui/views/cocoa/drag_drop_client_mac.mm
+++ b/chromium/ui/views/cocoa/drag_drop_client_mac.mm
@@ -10,9 +10,9 @@
#import "ui/base/dragdrop/os_exchange_data_provider_mac.h"
#include "ui/gfx/image/image_skia_util_mac.h"
#include "ui/views/drag_utils.h"
-#import "ui/views/cocoa/bridged_content_view.h"
-#import "ui/views/cocoa/bridged_native_widget.h"
#include "ui/views/widget/native_widget_mac.h"
+#import "ui/views_bridge_mac/bridged_content_view.h"
+#import "ui/views_bridge_mac/bridged_native_widget_impl.h"
@interface CocoaDragDropDataProvider ()
- (id)initWithData:(const ui::OSExchangeData&)data;
@@ -57,7 +57,7 @@
namespace views {
-DragDropClientMac::DragDropClientMac(BridgedNativeWidget* bridge,
+DragDropClientMac::DragDropClientMac(BridgedNativeWidgetImpl* bridge,
View* root_view)
: drop_helper_(root_view),
operation_(0),
diff --git a/chromium/ui/views/cocoa/drag_drop_client_mac_unittest.mm b/chromium/ui/views/cocoa/drag_drop_client_mac_unittest.mm
index 9f3559de2ef..4202d53a348 100644
--- a/chromium/ui/views/cocoa/drag_drop_client_mac_unittest.mm
+++ b/chromium/ui/views/cocoa/drag_drop_client_mac_unittest.mm
@@ -13,12 +13,12 @@
#include "base/threading/thread_task_runner_handle.h"
#import "ui/base/clipboard/clipboard_util_mac.h"
#include "ui/gfx/image/image_unittest_util.h"
-#import "ui/views/cocoa/bridged_native_widget.h"
#import "ui/views/cocoa/bridged_native_widget_host_impl.h"
#include "ui/views/test/widget_test.h"
#include "ui/views/view.h"
#include "ui/views/widget/native_widget_mac.h"
#include "ui/views/widget/widget.h"
+#import "ui/views_bridge_mac/bridged_native_widget_impl.h"
using base::ASCIIToUTF16;
@@ -156,7 +156,9 @@ class DragDropClientMacTest : public WidgetTest {
public:
DragDropClientMacTest() : widget_(new Widget) {}
- DragDropClientMac* drag_drop_client() { return bridge_->drag_drop_client(); }
+ DragDropClientMac* drag_drop_client() {
+ return bridge_host_->drag_drop_client();
+ }
NSDragOperation DragUpdate(NSPasteboard* pasteboard) {
DragDropClientMac* client = drag_drop_client();
@@ -186,9 +188,9 @@ class DragDropClientMacTest : public WidgetTest {
gfx::Rect bounds(0, 0, 100, 100);
widget_->SetBounds(bounds);
- bridge_ =
- NativeWidgetMac::GetBridgeForNativeWindow(widget_->GetNativeWindow());
- bridge_host_ = NativeWidgetMac::GetBridgeHostImplForNativeWindow(
+ bridge_ = BridgedNativeWidgetImpl::GetFromNativeWindow(
+ widget_->GetNativeWindow());
+ bridge_host_ = BridgedNativeWidgetHostImpl::GetFromNativeWindow(
widget_->GetNativeWindow());
widget_->Show();
@@ -207,7 +209,7 @@ class DragDropClientMacTest : public WidgetTest {
protected:
Widget* widget_ = nullptr;
- BridgedNativeWidget* bridge_ = nullptr;
+ BridgedNativeWidgetImpl* bridge_ = nullptr;
BridgedNativeWidgetHostImpl* bridge_host_ = nullptr;
DragDropView* target_ = nullptr;
base::scoped_nsobject<MockDraggingInfo> dragging_info_;
diff --git a/chromium/ui/views/cocoa/tooltip_manager_mac.h b/chromium/ui/views/cocoa/tooltip_manager_mac.h
index 208fb4e948a..7fa612ca843 100644
--- a/chromium/ui/views/cocoa/tooltip_manager_mac.h
+++ b/chromium/ui/views/cocoa/tooltip_manager_mac.h
@@ -8,13 +8,19 @@
#include "base/macros.h"
#include "ui/views/widget/tooltip_manager.h"
-namespace views {
+namespace views_bridge_mac {
+namespace mojom {
class BridgedNativeWidget;
+} // namespace mojom
+} // namespace views_bridge_mac
+
+namespace views {
-// Manages native Cocoa tooltips for the given BridgedNativeWidget.
+// Manages native Cocoa tooltips for the given BridgedNativeWidgetHostImpl.
class TooltipManagerMac : public TooltipManager {
public:
- explicit TooltipManagerMac(BridgedNativeWidget* widget);
+ explicit TooltipManagerMac(
+ views_bridge_mac::mojom::BridgedNativeWidget* bridge);
~TooltipManagerMac() override;
// TooltipManager:
@@ -24,7 +30,8 @@ class TooltipManagerMac : public TooltipManager {
void TooltipTextChanged(View* view) override;
private:
- BridgedNativeWidget* widget_; // Weak. Owns this.
+ views_bridge_mac::mojom::BridgedNativeWidget*
+ bridge_; // Weak. Owned by the owner of this.
DISALLOW_COPY_AND_ASSIGN(TooltipManagerMac);
};
diff --git a/chromium/ui/views/cocoa/tooltip_manager_mac.mm b/chromium/ui/views/cocoa/tooltip_manager_mac.mm
index 99a1fb5d906..cbf12b14fda 100644
--- a/chromium/ui/views/cocoa/tooltip_manager_mac.mm
+++ b/chromium/ui/views/cocoa/tooltip_manager_mac.mm
@@ -4,11 +4,12 @@
#include "ui/views/cocoa/tooltip_manager_mac.h"
+#include "base/no_destructor.h"
#include "ui/base/cocoa/cocoa_base_utils.h"
#include "ui/gfx/font_list.h"
#import "ui/gfx/mac/coordinate_conversion.h"
-#import "ui/views/cocoa/bridged_content_view.h"
-#import "ui/views/cocoa/bridged_native_widget.h"
+#import "ui/views_bridge_mac/bridged_content_view.h"
+#import "ui/views_bridge_mac/bridged_native_widget_impl.h"
namespace {
@@ -19,9 +20,9 @@ const int kTooltipMaxWidthPixels = 250;
namespace views {
-TooltipManagerMac::TooltipManagerMac(BridgedNativeWidget* widget)
- : widget_(widget) {
-}
+TooltipManagerMac::TooltipManagerMac(
+ views_bridge_mac::mojom::BridgedNativeWidget* bridge)
+ : bridge_(bridge) {}
TooltipManagerMac::~TooltipManagerMac() {
}
@@ -31,20 +32,13 @@ int TooltipManagerMac::GetMaxWidth(const gfx::Point& location) const {
}
const gfx::FontList& TooltipManagerMac::GetFontList() const {
- CR_DEFINE_STATIC_LOCAL(gfx::FontList, font_list,
- (gfx::Font([NSFont toolTipsFontOfSize:0])));
- return font_list;
+ static base::NoDestructor<gfx::FontList> font_list(
+ []() { return gfx::Font([NSFont toolTipsFontOfSize:0]); }());
+ return *font_list;
}
void TooltipManagerMac::UpdateTooltip() {
- NSWindow* window = widget_->ns_window();
- BridgedContentView* view = widget_->ns_view();
-
- NSPoint nspoint =
- ui::ConvertPointFromScreenToWindow(window, [NSEvent mouseLocation]);
- // Note: flip in the view's frame, which matches the window's contentRect.
- gfx::Point point(nspoint.x, NSHeight([view frame]) - nspoint.y);
- [view updateTooltipIfRequiredAt:point];
+ bridge_->UpdateTooltip();
}
void TooltipManagerMac::TooltipTextChanged(View* view) {
diff --git a/chromium/ui/views/cocoa/widget_owner_nswindow_adapter.h b/chromium/ui/views/cocoa/widget_owner_nswindow_adapter.h
deleted file mode 100644
index 8240bead793..00000000000
--- a/chromium/ui/views/cocoa/widget_owner_nswindow_adapter.h
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_COCOA_WIDGET_OWNER_NSWINDOW_ADAPTER_H_
-#define UI_VIEWS_COCOA_WIDGET_OWNER_NSWINDOW_ADAPTER_H_
-
-#import "base/mac/scoped_nsobject.h"
-#include "base/macros.h"
-#import "ui/views/cocoa/bridged_native_widget_owner.h"
-
-@class NSView;
-@class NSWindow;
-@class WidgetOwnerNSWindowAdapterBridge;
-
-namespace views {
-
-// An adapter that allows a views::Widget to be owned by an NSWindow that is not
-// backed by another BridgedNativeWidget.
-class WidgetOwnerNSWindowAdapter : public BridgedNativeWidgetOwner {
- public:
- // Create an adapter that will own |child|, tying its lifetime with the
- // NSWindow containing |anchor_view|. The object is self-deleting, via a call
- // to RemoveChildWindow() made in child->OnWindowWillClose().
- WidgetOwnerNSWindowAdapter(BridgedNativeWidget* child, NSView* anchor_view);
-
- // Called when the owning window is closing.
- void OnWindowWillClose();
-
- // Called when the owning window is hidden or shown.
- void OnWindowDidChangeOcclusionState();
-
- // Overridden from BridgedNativeWidgetOwner:
- NSWindow* GetNSWindow() override;
- gfx::Vector2d GetChildWindowOffset() const override;
- bool IsVisibleParent() const override;
- void RemoveChildWindow(BridgedNativeWidget* child) override;
-
- private:
- // Self-deleting.
- ~WidgetOwnerNSWindowAdapter() override;
-
- BridgedNativeWidget* child_; // Weak. Owned by its NativeWidgetMac.
- base::scoped_nsobject<NSView> anchor_view_;
- base::scoped_nsobject<NSWindow> anchor_window_;
- base::scoped_nsobject<WidgetOwnerNSWindowAdapterBridge> observer_bridge_;
-
- DISALLOW_COPY_AND_ASSIGN(WidgetOwnerNSWindowAdapter);
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_COCOA_WIDGET_OWNER_NSWINDOW_ADAPTER_H_
diff --git a/chromium/ui/views/cocoa/widget_owner_nswindow_adapter.mm b/chromium/ui/views/cocoa/widget_owner_nswindow_adapter.mm
deleted file mode 100644
index 3585b78344e..00000000000
--- a/chromium/ui/views/cocoa/widget_owner_nswindow_adapter.mm
+++ /dev/null
@@ -1,166 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#import "ui/views/cocoa/widget_owner_nswindow_adapter.h"
-
-#import <Cocoa/Cocoa.h>
-
-#include "base/logging.h"
-#include "base/mac/sdk_forward_declarations.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/geometry/vector2d.h"
-#import "ui/gfx/mac/coordinate_conversion.h"
-#import "ui/views/cocoa/bridged_native_widget.h"
-
-// Bridges an AppKit observer to observe when the (non-views) NSWindow owning a
-// views::Widget will close or change occlusion state.
-@interface WidgetOwnerNSWindowAdapterBridge : NSObject {
- @private
- views::WidgetOwnerNSWindowAdapter* adapter_; // Weak. Owns us.
-}
-- (instancetype)initWithAdapter:(views::WidgetOwnerNSWindowAdapter*)adapter;
-- (void)windowWillClose:(NSNotification*)notification;
-- (void)windowDidChangeOcclusionState:(NSNotification*)notification;
-@end
-
-@implementation WidgetOwnerNSWindowAdapterBridge
-
-- (instancetype)initWithAdapter:(views::WidgetOwnerNSWindowAdapter*)adapter {
- if ((self = [super init]))
- adapter_ = adapter;
- return self;
-}
-
-- (void)windowWillClose:(NSNotification*)notification {
- adapter_->OnWindowWillClose();
-}
-
-- (void)windowDidChangeOcclusionState:(NSNotification*)notification {
- adapter_->OnWindowDidChangeOcclusionState();
-}
-
-@end
-
-namespace views {
-
-WidgetOwnerNSWindowAdapter::WidgetOwnerNSWindowAdapter(
- BridgedNativeWidget* child,
- NSView* anchor_view)
- : child_(child),
- anchor_view_([anchor_view retain]),
- observer_bridge_(
- [[WidgetOwnerNSWindowAdapterBridge alloc] initWithAdapter:this]) {
-
- // Although the |anchor_view| must be in an NSWindow when the child dialog is
- // created, it's permitted for the |anchor_view| to be removed from its view
- // hierarchy before the child dialog window is fully removed from screen. When
- // this happens, [anchor_view_ window] will become nil, so retain both.
- anchor_window_.reset([[anchor_view_ window] retain]);
- DCHECK(anchor_window_);
-
- [[NSNotificationCenter defaultCenter]
- addObserver:observer_bridge_
- selector:@selector(windowWillClose:)
- name:NSWindowWillCloseNotification
- object:anchor_window_];
-
- // BridgedNativeWidget removes NSWindow parent/child relationships for hidden
- // windows. Observe when the parent's visibility changes so they can be
- // reconnected.
- [[NSNotificationCenter defaultCenter]
- addObserver:observer_bridge_
- selector:@selector(windowDidChangeOcclusionState:)
- name:NSWindowDidChangeOcclusionStateNotification
- object:anchor_window_];
-
- // On a deminiaturize, the occlusion state change may occur before -[NSWindow
- // isVisible] returns YES. So observe NSWindowDidDeminiaturizeNotification.
- // This allows the adapter to check again at the end of the deminiaturize.
- [[NSNotificationCenter defaultCenter]
- addObserver:observer_bridge_
- selector:@selector(windowDidChangeOcclusionState:)
- name:NSWindowDidDeminiaturizeNotification
- object:anchor_window_];
-}
-
-void WidgetOwnerNSWindowAdapter::OnWindowWillClose() {
- // Retain the child window before closing it. If the last reference to the
- // NSWindow goes away inside -[NSWindow close], then bad stuff can happen.
- // See e.g. http://crbug.com/616701.
- base::scoped_nsobject<NSWindow> child_window(child_->ns_window(),
- base::scoped_policy::RETAIN);
-
- // AppKit child window relationships break when the windows are not visible,
- // so if the child is not visible, it won't currently be a child.
- if (![child_window isVisible])
- DCHECK(![child_window parentWindow] && ![child_window sheetParent]);
- DCHECK([child_window delegate]);
-
- [child_window close];
- // Note: |this| will be deleted here.
-
- DCHECK(![child_window parentWindow]);
- DCHECK(![child_window delegate]);
-}
-
-void WidgetOwnerNSWindowAdapter::OnWindowDidChangeOcclusionState() {
- // The adapter only needs to handle a parent "show", since the only way it
- // should be hidden is via -[NSApp hide], and all BridgedNativeWidgets
- // subscribe to NSApplicationDidHideNotification already.
- if (![anchor_window_ isVisible])
- return;
-
- if (child_->window_visible()) {
- // A sheet should never have a parentWindow, otherwise dismissing the sheet
- // causes graphical glitches (http://crbug.com/605098). Non-sheets should
- // always have a parentWindow.
- DCHECK([child_->ns_window() isSheet] !=
- !![child_->ns_window() parentWindow]);
- DCHECK(child_->wants_to_be_visible());
- return;
- }
-
- // The parent relationship should have been removed when the child was hidden.
- DCHECK(![child_->ns_window() parentWindow]);
- if (!child_->wants_to_be_visible())
- return;
-
- [child_->ns_window() orderWindow:NSWindowAbove
- relativeTo:[anchor_window_ windowNumber]];
-
- // Ordering the window should add back the relationship (unless it's a sheet).
- DCHECK([child_->ns_window() isSheet] != !![child_->ns_window() parentWindow]);
- DCHECK(child_->window_visible());
-}
-
-NSWindow* WidgetOwnerNSWindowAdapter::GetNSWindow() {
- return anchor_window_;
-}
-
-gfx::Vector2d WidgetOwnerNSWindowAdapter::GetChildWindowOffset() const {
- NSRect rect_in_window =
- [anchor_view_ convertRect:[anchor_view_ bounds] toView:nil];
- NSRect rect_in_screen = [anchor_window_ convertRectToScreen:rect_in_window];
- // Ensure we anchor off the top-left of |anchor_view_| (rect_in_screen.origin
- // is the bottom-left of the view).
- NSPoint anchor_in_screen =
- NSMakePoint(NSMinX(rect_in_screen), NSMaxY(rect_in_screen));
- return gfx::ScreenPointFromNSPoint(anchor_in_screen).OffsetFromOrigin();
-}
-
-bool WidgetOwnerNSWindowAdapter::IsVisibleParent() const {
- return [anchor_window_ isVisible];
-}
-
-void WidgetOwnerNSWindowAdapter::RemoveChildWindow(BridgedNativeWidget* child) {
- DCHECK_EQ(child, child_);
- [GetNSWindow() removeChildWindow:child->ns_window()];
- delete this;
-}
-
-WidgetOwnerNSWindowAdapter::~WidgetOwnerNSWindowAdapter() {
- [[NSNotificationCenter defaultCenter] removeObserver:observer_bridge_];
-}
-
-} // namespace views
diff --git a/chromium/ui/views/color_chooser/color_chooser_view.cc b/chromium/ui/views/color_chooser/color_chooser_view.cc
index d844b6a58f2..19eab2ec3d5 100644
--- a/chromium/ui/views/color_chooser/color_chooser_view.cc
+++ b/chromium/ui/views/color_chooser/color_chooser_view.cc
@@ -15,10 +15,12 @@
#include "cc/paint/paint_shader.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
+#include "ui/base/l10n/l10n_util.h"
#include "ui/events/event.h"
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/insets.h"
+#include "ui/strings/grit/ui_strings.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/color_chooser/color_chooser_listener.h"
@@ -389,6 +391,8 @@ ColorChooserView::ColorChooserView(ColorChooserListener* listener,
textfield_ = new Textfield();
textfield_->set_controller(this);
textfield_->SetDefaultWidthInChars(kTextfieldLengthInChars);
+ textfield_->SetAccessibleName(
+ l10n_util::GetStringUTF16(IDS_APP_ACCNAME_COLOR_CHOOSER_HEX_INPUT));
layout->AddView(textfield_);
selected_color_patch_ = new SelectedColorPatchView();
layout->AddView(selected_color_patch_);
diff --git a/chromium/ui/views/controls/animated_image_view.cc b/chromium/ui/views/controls/animated_image_view.cc
new file mode 100644
index 00000000000..2d56a88b440
--- /dev/null
+++ b/chromium/ui/views/controls/animated_image_view.cc
@@ -0,0 +1,139 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/controls/animated_image_view.h"
+
+#include <utility>
+
+#include "base/logging.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/skottie_wrapper.h"
+#include "ui/views/widget/widget.h"
+
+namespace views {
+namespace {
+
+bool AreAnimatedImagesEqual(const gfx::SkiaVectorAnimation& animation_1,
+ const gfx::SkiaVectorAnimation& animation_2) {
+ // In rare cases this may return false, even if the animated images are backed
+ // by the same resource file.
+ return animation_1.skottie() == animation_2.skottie();
+}
+
+} // namespace
+
+AnimatedImageView::AnimatedImageView() = default;
+
+AnimatedImageView::~AnimatedImageView() = default;
+
+void AnimatedImageView::SetAnimatedImage(
+ std::unique_ptr<gfx::SkiaVectorAnimation> animated_image) {
+ if (animated_image_ &&
+ AreAnimatedImagesEqual(*animated_image, *animated_image_)) {
+ Stop();
+ return;
+ }
+
+ gfx::Size preferred_size(GetPreferredSize());
+ animated_image_ = std::move(animated_image);
+
+ // Stop the animation to reset it.
+ Stop();
+
+ if (preferred_size != GetPreferredSize())
+ PreferredSizeChanged();
+ SchedulePaint();
+}
+
+void AnimatedImageView::Play() {
+ DCHECK(animated_image_);
+ DCHECK_EQ(state_, State::kStopped);
+
+ state_ = State::kPlaying;
+
+ // We cannot play the animation unless we have a valid compositor.
+ if (!compositor_)
+ return;
+
+ // Ensure the class is added as an observer to receive clock ticks.
+ if (!compositor_->HasAnimationObserver(this))
+ compositor_->AddAnimationObserver(this);
+
+ animated_image_->Start();
+}
+
+void AnimatedImageView::Stop() {
+ DCHECK(animated_image_);
+ if (compositor_)
+ compositor_->RemoveAnimationObserver(this);
+
+ animated_image_->Stop();
+ state_ = State::kStopped;
+}
+
+gfx::Size AnimatedImageView::GetImageSize() const {
+ return image_size_.value_or(
+ animated_image_ ? animated_image_->GetOriginalSize() : gfx::Size());
+}
+
+void AnimatedImageView::OnPaint(gfx::Canvas* canvas) {
+ View::OnPaint(canvas);
+ if (!animated_image_)
+ return;
+ canvas->Save();
+ canvas->Translate(GetImageBounds().origin().OffsetFromOrigin());
+
+ // OnPaint may be called before clock tick was received; in that case just
+ // paint the first frame.
+ if (!previous_timestamp_.is_null() && state_ != State::kStopped)
+ animated_image_->Paint(canvas, previous_timestamp_, GetImageSize());
+ else
+ animated_image_->PaintFrame(canvas, 0, GetImageSize());
+
+ canvas->Restore();
+}
+
+const char* AnimatedImageView::GetClassName() const {
+ return "AnimatedImageView";
+}
+
+void AnimatedImageView::NativeViewHierarchyChanged() {
+ // When switching a window from one display to another, the compositor
+ // associated with the widget changes.
+ AddedToWidget();
+}
+
+void AnimatedImageView::AddedToWidget() {
+ ui::Compositor* compositor = GetWidget()->GetCompositor();
+ DCHECK(compositor);
+ if (compositor_ != compositor) {
+ if (compositor_ && compositor_->HasAnimationObserver(this))
+ compositor_->RemoveAnimationObserver(this);
+ compositor_ = compositor;
+ }
+}
+
+void AnimatedImageView::RemovedFromWidget() {
+ if (compositor_) {
+ Stop();
+ if (compositor_->HasAnimationObserver(this))
+ compositor_->RemoveAnimationObserver(this);
+ compositor_ = nullptr;
+ }
+}
+
+void AnimatedImageView::OnAnimationStep(base::TimeTicks timestamp) {
+ previous_timestamp_ = timestamp;
+ SchedulePaint();
+}
+
+void AnimatedImageView::OnCompositingShuttingDown(ui::Compositor* compositor) {
+ if (compositor_ == compositor) {
+ Stop();
+ compositor_->RemoveAnimationObserver(this);
+ compositor_ = nullptr;
+ }
+}
+
+} // namespace views
diff --git a/chromium/ui/views/controls/animated_image_view.h b/chromium/ui/views/controls/animated_image_view.h
new file mode 100644
index 00000000000..c62fe5c3723
--- /dev/null
+++ b/chromium/ui/views/controls/animated_image_view.h
@@ -0,0 +1,91 @@
+// 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_VIEWS_CONTROLS_ANIMATED_IMAGE_VIEW_H_
+#define UI_VIEWS_CONTROLS_ANIMATED_IMAGE_VIEW_H_
+
+#include <memory>
+
+#include "base/macros.h"
+#include "ui/gfx/skia_vector_animation.h"
+#include "ui/views/controls/image_view_base.h"
+
+namespace gfx {
+class SkiaVectorAnimation;
+class Canvas;
+} // namespace gfx
+
+namespace ui {
+class Compositor;
+}
+
+namespace views {
+
+/////////////////////////////////////////////////////////////////////////////
+//
+// AnimatedImageView class.
+//
+// An AnimatedImageView can display a skia vector animation. The animation paint
+// size can be set via SetImageSize. The animation is stopped by default.
+// Use this over AnimatedIconView if you want to play a skottie animation file.
+//
+/////////////////////////////////////////////////////////////////////////////
+class VIEWS_EXPORT AnimatedImageView : public ImageViewBase,
+ public ui::CompositorAnimationObserver {
+ public:
+ enum class State {
+ kPlaying, // The animation is currently playing.
+ kStopped // The animation is stopped and paint will raster the first
+ // frame.
+ };
+
+ AnimatedImageView();
+ ~AnimatedImageView() override;
+
+ // Set the animated image that should be displayed. Setting an animated image
+ // will result in stopping the current animation.
+ void SetAnimatedImage(
+ std::unique_ptr<gfx::SkiaVectorAnimation> animated_image);
+
+ // Plays the animation in loop.
+ void Play();
+
+ // Stops any animation and resets it to the start frame.
+ void Stop();
+
+ private:
+ friend class AnimatedImageViewTest;
+
+ // Overridden from View:
+ void OnPaint(gfx::Canvas* canvas) override;
+ const char* GetClassName() const override;
+ void NativeViewHierarchyChanged() override;
+ void AddedToWidget() override;
+ void RemovedFromWidget() override;
+
+ // Overridden from ui::CompositorAnimationObserver:
+ void OnAnimationStep(base::TimeTicks timestamp) override;
+ void OnCompositingShuttingDown(ui::Compositor* compositor) override;
+
+ // Overridden from ImageViewBase:
+ gfx::Size GetImageSize() const override;
+
+ // The current state of the animation.
+ State state_ = State::kStopped;
+
+ // The compositor associated with the widget of this view.
+ ui::Compositor* compositor_ = nullptr;
+
+ // The most recent timestamp at which a paint was scheduled for this view.
+ base::TimeTicks previous_timestamp_;
+
+ // The underlying skia vector animation.
+ std::unique_ptr<gfx::SkiaVectorAnimation> animated_image_;
+
+ DISALLOW_COPY_AND_ASSIGN(AnimatedImageView);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_CONTROLS_ANIMATED_IMAGE_VIEW_H_
diff --git a/chromium/ui/views/controls/button/button.cc b/chromium/ui/views/controls/button/button.cc
index 9656e5dc4a3..ebf086404e3 100644
--- a/chromium/ui/views/controls/button/button.cc
+++ b/chromium/ui/views/controls/button/button.cc
@@ -170,6 +170,12 @@ void Button::SetFocusPainter(std::unique_ptr<Painter> focus_painter) {
focus_painter_ = std::move(focus_painter);
}
+void Button::SetHighlighted(bool bubble_visible) {
+ AnimateInkDrop(bubble_visible ? views::InkDropState::ACTIVATED
+ : views::InkDropState::DEACTIVATED,
+ nullptr);
+}
+
////////////////////////////////////////////////////////////////////////////////
// Button, View overrides:
diff --git a/chromium/ui/views/controls/button/button.h b/chromium/ui/views/controls/button/button.h
index b5347ff0e00..050512ffa34 100644
--- a/chromium/ui/views/controls/button/button.h
+++ b/chromium/ui/views/controls/button/button.h
@@ -151,6 +151,9 @@ class VIEWS_EXPORT Button : public InkDropHostView,
void SetFocusPainter(std::unique_ptr<Painter> focus_painter);
+ // Highlights the ink drop for the button.
+ void SetHighlighted(bool bubble_visible);
+
// Overridden from View:
void OnEnabledChanged() override;
const char* GetClassName() const override;
diff --git a/chromium/ui/views/controls/button/checkbox.cc b/chromium/ui/views/controls/button/checkbox.cc
index 91e398ebfe3..1a84d97ab26 100644
--- a/chromium/ui/views/controls/button/checkbox.cc
+++ b/chromium/ui/views/controls/button/checkbox.cc
@@ -55,7 +55,10 @@ Checkbox::~Checkbox() {
}
void Checkbox::SetChecked(bool checked) {
- checked_ = checked;
+ if (checked_ != checked) {
+ checked_ = checked;
+ NotifyAccessibilityEvent(ax::mojom::Event::kCheckedStateChanged, true);
+ }
UpdateImage();
}
diff --git a/chromium/ui/views/controls/button/image_button_factory.cc b/chromium/ui/views/controls/button/image_button_factory.cc
index 649002d85ad..baf33d4ef8d 100644
--- a/chromium/ui/views/controls/button/image_button_factory.cc
+++ b/chromium/ui/views/controls/button/image_button_factory.cc
@@ -31,7 +31,8 @@ void SetImageFromVectorIcon(ImageButton* button,
SkColor related_text_color) {
const SkColor icon_color =
color_utils::DeriveDefaultIconColor(related_text_color);
- const SkColor disabled_color = SkColorSetA(icon_color, 0xff / 2);
+ const SkColor disabled_color =
+ SkColorSetA(icon_color, gfx::kDisabledControlAlpha);
button->SetImage(Button::STATE_NORMAL,
gfx::CreateVectorIcon(icon, icon_color));
button->SetImage(Button::STATE_DISABLED,
diff --git a/chromium/ui/views/controls/button/label_button_unittest.cc b/chromium/ui/views/controls/button/label_button_unittest.cc
index 4a1ac7683d6..966ab6fec75 100644
--- a/chromium/ui/views/controls/button/label_button_unittest.cc
+++ b/chromium/ui/views/controls/button/label_button_unittest.cc
@@ -543,8 +543,6 @@ class InkDropLabelButtonTest : public ViewsTestBase {
// ViewsTestBase:
void SetUp() override {
- base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
- switches::kTopChromeMD, switches::kTopChromeMDMaterial);
ViewsTestBase::SetUp();
// Create a widget so that the Button can query the hover state
@@ -568,7 +566,6 @@ class InkDropLabelButtonTest : public ViewsTestBase {
void TearDown() override {
widget_.reset();
ViewsTestBase::TearDown();
- ui::test::MaterialDesignControllerTestAPI::Uninitialize();
}
protected:
diff --git a/chromium/ui/views/controls/button/md_text_button.cc b/chromium/ui/views/controls/button/md_text_button.cc
index 4e6011dc24e..0d9f69cab39 100644
--- a/chromium/ui/views/controls/button/md_text_button.cc
+++ b/chromium/ui/views/controls/button/md_text_button.cc
@@ -7,7 +7,6 @@
#include "base/i18n/case_conversion.h"
#include "base/memory/ptr_util.h"
#include "build/build_config.h"
-#include "ui/base/material_design/material_design_controller.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/color_utils.h"
@@ -197,12 +196,9 @@ void MdTextButton::UpdatePadding() {
style::GetFont(style::CONTEXT_BUTTON_MD, style::STYLE_PRIMARY)
.GetFontSize();
// TODO(tapted): This should get |target_height| using LayoutProvider::
- // GetControlHeightForFont(). It can't because that only returns a correct
- // result with --secondary-ui-md, and MdTextButtons appear in top chrome
- // without that.
- const int base_height =
- ui::MaterialDesignController::IsNewerMaterialUi() ? 32 : 28;
- int target_height = std::max(base_height + size_delta * 2,
+ // GetControlHeightForFont().
+ constexpr int kBaseHeight = 32;
+ int target_height = std::max(kBaseHeight + size_delta * 2,
label()->font_list().GetFontSize() * 2);
int label_height = label()->GetPreferredSize().height();
diff --git a/chromium/ui/views/controls/button/radio_button.cc b/chromium/ui/views/controls/button/radio_button.cc
index 9adf4949221..6113742ab7f 100644
--- a/chromium/ui/views/controls/button/radio_button.cc
+++ b/chromium/ui/views/controls/button/radio_button.cc
@@ -99,7 +99,7 @@ void RadioButton::SetChecked(bool checked) {
if (container) {
Views other;
container->GetViewsInGroup(GetGroup(), &other);
- for (Views::iterator i(other.begin()); i != other.end(); ++i) {
+ for (auto i(other.begin()); i != other.end(); ++i) {
if (*i != this) {
if (strcmp((*i)->GetClassName(), kViewClassName)) {
NOTREACHED() << "radio-button-nt has same group as other non "
diff --git a/chromium/ui/views/controls/focus_ring.cc b/chromium/ui/views/controls/focus_ring.cc
index 148c22ae909..bc9597596ce 100644
--- a/chromium/ui/views/controls/focus_ring.cc
+++ b/chromium/ui/views/controls/focus_ring.cc
@@ -7,6 +7,7 @@
#include "ui/gfx/canvas.h"
#include "ui/views/controls/focusable_border.h"
#include "ui/views/style/platform_style.h"
+#include "ui/views/view_properties.h"
namespace {
@@ -79,6 +80,11 @@ void FocusRing::OnPaint(gfx::Canvas* canvas) {
paint.setStrokeWidth(PlatformStyle::kFocusHaloThickness);
SkPath path = path_;
+ if (path.isEmpty()) {
+ gfx::Path* highlight_path = parent()->GetProperty(kHighlightPathKey);
+ if (highlight_path)
+ path = *highlight_path;
+ }
if (path.isEmpty())
path.addRect(RectToSkRect(parent()->GetLocalBounds()));
diff --git a/chromium/ui/views/controls/focus_ring.h b/chromium/ui/views/controls/focus_ring.h
index a608042b24f..1627eda9347 100644
--- a/chromium/ui/views/controls/focus_ring.h
+++ b/chromium/ui/views/controls/focus_ring.h
@@ -58,6 +58,9 @@ class VIEWS_EXPORT FocusRing : public View, public ViewObserver {
// view's coordinate system, *not* in the FocusRing's coordinate system. Note
// that this path will not be mirrored in RTL, so your View's computation of
// it should take RTL into account.
+ // Note: This method should only be used if the focus ring needs to differ
+ // from the highlight shape used for inkdrops. Otherwise set kHighlightPathKey
+ // on the parent and FocusRing will use it as well.
void SetPath(const SkPath& path);
// Sets whether the FocusRing should show an invalid state for the View it
diff --git a/chromium/ui/views/controls/image_view.cc b/chromium/ui/views/controls/image_view.cc
index b1abacf1e0d..2e9c4062526 100644
--- a/chromium/ui/views/controls/image_view.cc
+++ b/chromium/ui/views/controls/image_view.cc
@@ -7,12 +7,9 @@
#include <utility>
#include "base/logging.h"
-#include "base/strings/utf_string_conversions.h"
#include "cc/paint/paint_flags.h"
#include "skia/ext/image_operations.h"
-#include "ui/accessibility/ax_node_data.h"
#include "ui/gfx/canvas.h"
-#include "ui/gfx/geometry/insets.h"
namespace views {
@@ -21,7 +18,7 @@ namespace {
// Returns the pixels for the bitmap in |image| at scale |image_scale|.
void* GetBitmapPixels(const gfx::ImageSkia& img, float image_scale) {
DCHECK_NE(0.0f, image_scale);
- return img.GetRepresentation(image_scale).sk_bitmap().getPixels();
+ return img.GetRepresentation(image_scale).GetBitmap().getPixels();
}
} // namespace
@@ -29,13 +26,9 @@ void* GetBitmapPixels(const gfx::ImageSkia& img, float image_scale) {
// static
const char ImageView::kViewClassName[] = "ImageView";
-ImageView::ImageView()
- : horizontal_alignment_(CENTER),
- vertical_alignment_(CENTER),
- last_paint_scale_(0.f),
- last_painted_bitmap_pixels_(nullptr) {}
+ImageView::ImageView() = default;
-ImageView::~ImageView() {}
+ImageView::~ImageView() = default;
void ImageView::SetImage(const gfx::ImageSkia& img) {
if (IsImageEqual(img))
@@ -63,20 +56,6 @@ const gfx::ImageSkia& ImageView::GetImage() const {
return image_;
}
-void ImageView::SetImageSize(const gfx::Size& image_size) {
- image_size_ = image_size;
- PreferredSizeChanged();
-}
-
-gfx::Rect ImageView::GetImageBounds() const {
- gfx::Size image_size = GetImageSize();
- return gfx::Rect(ComputeImageOrigin(image_size), image_size);
-}
-
-void ImageView::ResetImageSize() {
- image_size_.reset();
-}
-
bool ImageView::IsImageEqual(const gfx::ImageSkia& img) const {
// Even though we copy ImageSkia in SetImage() the backing store
// (ImageSkiaStorage) is not copied and may have changed since the last call
@@ -92,119 +71,15 @@ gfx::Size ImageView::GetImageSize() const {
return image_size_.value_or(image_.size());
}
-gfx::Point ImageView::ComputeImageOrigin(const gfx::Size& image_size) const {
- gfx::Insets insets = GetInsets();
-
- int x = 0;
- // In order to properly handle alignment of images in RTL locales, we need
- // to flip the meaning of trailing and leading. For example, if the
- // horizontal alignment is set to trailing, then we'll use left alignment for
- // the image instead of right alignment if the UI layout is RTL.
- Alignment actual_horizontal_alignment = horizontal_alignment_;
- if (base::i18n::IsRTL() && (horizontal_alignment_ != CENTER)) {
- actual_horizontal_alignment =
- (horizontal_alignment_ == LEADING) ? TRAILING : LEADING;
- }
- switch (actual_horizontal_alignment) {
- case LEADING:
- x = insets.left();
- break;
- case TRAILING:
- x = width() - insets.right() - image_size.width();
- break;
- case CENTER:
- x = (width() - insets.width() - image_size.width()) / 2 + insets.left();
- break;
- }
-
- int y = 0;
- switch (vertical_alignment_) {
- case LEADING:
- y = insets.top();
- break;
- case TRAILING:
- y = height() - insets.bottom() - image_size.height();
- break;
- case CENTER:
- y = (height() - insets.height() - image_size.height()) / 2 + insets.top();
- break;
- }
-
- return gfx::Point(x, y);
-}
-
void ImageView::OnPaint(gfx::Canvas* canvas) {
View::OnPaint(canvas);
OnPaintImage(canvas);
}
-void ImageView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
- node_data->role = ax::mojom::Role::kImage;
- node_data->SetName(tooltip_text_);
-}
-
const char* ImageView::GetClassName() const {
return kViewClassName;
}
-void ImageView::SetHorizontalAlignment(Alignment alignment) {
- if (alignment != horizontal_alignment_) {
- horizontal_alignment_ = alignment;
- SchedulePaint();
- }
-}
-
-ImageView::Alignment ImageView::GetHorizontalAlignment() const {
- return horizontal_alignment_;
-}
-
-void ImageView::SetVerticalAlignment(Alignment alignment) {
- if (alignment != vertical_alignment_) {
- vertical_alignment_ = alignment;
- SchedulePaint();
- }
-}
-
-ImageView::Alignment ImageView::GetVerticalAlignment() const {
- return vertical_alignment_;
-}
-
-void ImageView::SetTooltipText(const base::string16& tooltip) {
- tooltip_text_ = tooltip;
-}
-
-base::string16 ImageView::GetTooltipText() const {
- return tooltip_text_;
-}
-
-bool ImageView::GetTooltipText(const gfx::Point& p,
- base::string16* tooltip) const {
- if (tooltip_text_.empty())
- return false;
-
- *tooltip = GetTooltipText();
- return true;
-}
-
-gfx::Size ImageView::CalculatePreferredSize() const {
- gfx::Size size = GetImageSize();
- size.Enlarge(GetInsets().width(), GetInsets().height());
- return size;
-}
-
-views::PaintInfo::ScaleType ImageView::GetPaintScaleType() const {
- // ImageView contains an image which is rastered at the device scale factor.
- // By default, the paint commands are recorded at a scale factor slightly
- // different from the device scale factor. Re-rastering the image at this
- // paint recording scale will result in a distorted image. Paint recording
- // scale might also not be uniform along the x & y axis, thus resulting in
- // further distortion in the aspect ratio of the final image.
- // |kUniformScaling| ensures that the paint recording scale is uniform along
- // the x & y axis and keeps the scale equal to the device scale factor.
- // See http://crbug.com/754010 for more details.
- return views::PaintInfo::ScaleType::kUniformScaling;
-}
-
void ImageView::OnPaintImage(gfx::Canvas* canvas) {
last_paint_scale_ = canvas->image_scale();
last_painted_bitmap_pixels_ = nullptr;
@@ -248,7 +123,7 @@ gfx::ImageSkia ImageView::GetPaintImage(float scale) {
gfx::Size scaled_size =
gfx::ScaleToCeiledSize(rep.pixel_size(), scale / rep.scale());
scaled_image_.AddRepresentation(gfx::ImageSkiaRep(
- skia::ImageOperations::Resize(rep.sk_bitmap(),
+ skia::ImageOperations::Resize(rep.GetBitmap(),
skia::ImageOperations::RESIZE_BEST,
scaled_size.width(), scaled_size.height()),
scale));
diff --git a/chromium/ui/views/controls/image_view.h b/chromium/ui/views/controls/image_view.h
index c3adf654e36..e80a97a34a1 100644
--- a/chromium/ui/views/controls/image_view.h
+++ b/chromium/ui/views/controls/image_view.h
@@ -6,9 +6,8 @@
#define UI_VIEWS_CONTROLS_IMAGE_VIEW_H_
#include "base/macros.h"
-#include "base/optional.h"
#include "ui/gfx/image/image_skia.h"
-#include "ui/views/view.h"
+#include "ui/views/controls/image_view_base.h"
namespace gfx {
class Canvas;
@@ -26,17 +25,11 @@ namespace views {
// provided image size.
//
/////////////////////////////////////////////////////////////////////////////
-class VIEWS_EXPORT ImageView : public View {
+class VIEWS_EXPORT ImageView : public ImageViewBase {
public:
// Internal class name.
static const char kViewClassName[];
- enum Alignment {
- LEADING = 0,
- CENTER,
- TRAILING
- };
-
ImageView();
~ImageView() override;
@@ -52,35 +45,13 @@ class VIEWS_EXPORT ImageView : public View {
// The returned image is still owned by the ImageView.
const gfx::ImageSkia& GetImage() const;
- // Set the desired image size for the receiving ImageView.
- void SetImageSize(const gfx::Size& image_size);
-
- // Returns the actual bounds of the visible image inside the view.
- gfx::Rect GetImageBounds() const;
-
- // Reset the image size to the current image dimensions.
- void ResetImageSize();
-
- // Set / Get the horizontal alignment.
- void SetHorizontalAlignment(Alignment ha);
- Alignment GetHorizontalAlignment() const;
-
- // Set / Get the vertical alignment.
- void SetVerticalAlignment(Alignment va);
- Alignment GetVerticalAlignment() const;
-
- // Set / Get the tooltip text.
- void SetTooltipText(const base::string16& tooltip);
- base::string16 GetTooltipText() const;
-
- // Overriden from View:
+ // Overridden from View:
void OnPaint(gfx::Canvas* canvas) override;
- void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
const char* GetClassName() const override;
- bool GetTooltipText(const gfx::Point& p,
- base::string16* tooltip) const override;
- gfx::Size CalculatePreferredSize() const override;
- views::PaintInfo::ScaleType GetPaintScaleType() const override;
+
+ protected:
+ // Overridden from ImageViewBase:
+ gfx::Size GetImageSize() const override;
private:
friend class ImageViewTest;
@@ -95,37 +66,18 @@ class VIEWS_EXPORT ImageView : public View {
// for this to return false even though the images are in fact equal.
bool IsImageEqual(const gfx::ImageSkia& img) const;
- // Returns the size the image will be painted.
- gfx::Size GetImageSize() const;
-
- // Compute the image origin given the desired size and the receiver alignment
- // properties.
- gfx::Point ComputeImageOrigin(const gfx::Size& image_size) const;
-
- // The actual image size.
- base::Optional<gfx::Size> image_size_;
-
// The underlying image.
gfx::ImageSkia image_;
// Caches the scaled image reps.
gfx::ImageSkia scaled_image_;
- // Horizontal alignment.
- Alignment horizontal_alignment_;
-
- // Vertical alignment.
- Alignment vertical_alignment_;
-
- // The current tooltip text.
- base::string16 tooltip_text_;
-
// Scale last painted at.
- float last_paint_scale_;
+ float last_paint_scale_ = 0.f;
// Address of bytes we last painted. This is used only for comparison, so its
// safe to cache.
- void* last_painted_bitmap_pixels_;
+ void* last_painted_bitmap_pixels_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(ImageView);
};
diff --git a/chromium/ui/views/controls/image_view_base.cc b/chromium/ui/views/controls/image_view_base.cc
new file mode 100644
index 00000000000..d898798239f
--- /dev/null
+++ b/chromium/ui/views/controls/image_view_base.cc
@@ -0,0 +1,160 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/controls/image_view_base.h"
+
+#include <utility>
+
+#include "base/logging.h"
+#include "ui/accessibility/ax_node_data.h"
+#include "ui/gfx/geometry/insets.h"
+
+namespace views {
+
+ImageViewBase::ImageViewBase() = default;
+
+ImageViewBase::~ImageViewBase() = default;
+
+void ImageViewBase::SetImageSize(const gfx::Size& image_size) {
+ image_size_ = image_size;
+ PreferredSizeChanged();
+}
+
+gfx::Rect ImageViewBase::GetImageBounds() const {
+ return gfx::Rect(image_origin_, GetImageSize());
+}
+
+void ImageViewBase::ResetImageSize() {
+ image_size_.reset();
+ PreferredSizeChanged();
+}
+
+void ImageViewBase::GetAccessibleNodeData(ui::AXNodeData* node_data) {
+ node_data->role = ax::mojom::Role::kImage;
+ node_data->SetName(accessible_name_);
+}
+
+void ImageViewBase::SetHorizontalAlignment(Alignment alignment) {
+ if (alignment != horizontal_alignment_) {
+ horizontal_alignment_ = alignment;
+ UpdateImageOrigin();
+ SchedulePaint();
+ }
+}
+
+ImageViewBase::Alignment ImageViewBase::GetHorizontalAlignment() const {
+ return horizontal_alignment_;
+}
+
+void ImageViewBase::SetVerticalAlignment(Alignment alignment) {
+ if (alignment != vertical_alignment_) {
+ vertical_alignment_ = alignment;
+ UpdateImageOrigin();
+ SchedulePaint();
+ }
+}
+
+ImageViewBase::Alignment ImageViewBase::GetVerticalAlignment() const {
+ return vertical_alignment_;
+}
+
+void ImageViewBase::SetAccessibleName(const base::string16& accessible_name) {
+ accessible_name_ = accessible_name;
+}
+
+base::string16 ImageViewBase::GetAccessibleName() const {
+ return accessible_name_;
+}
+
+// TODO(crbug.com/890465): Update the duplicate code here and in views::Button.
+void ImageViewBase::SetTooltipText(const base::string16& tooltip) {
+ tooltip_text_ = tooltip;
+ if (accessible_name_.empty())
+ accessible_name_ = tooltip_text_;
+}
+
+base::string16 ImageViewBase::GetTooltipText() const {
+ return tooltip_text_;
+}
+
+bool ImageViewBase::GetTooltipText(const gfx::Point& p,
+ base::string16* tooltip) const {
+ if (tooltip_text_.empty())
+ return false;
+
+ *tooltip = GetTooltipText();
+ return true;
+}
+
+gfx::Size ImageViewBase::CalculatePreferredSize() const {
+ gfx::Size size = GetImageSize();
+ size.Enlarge(GetInsets().width(), GetInsets().height());
+ return size;
+}
+
+views::PaintInfo::ScaleType ImageViewBase::GetPaintScaleType() const {
+ // ImageViewBase contains an image which is rastered at the device scale
+ // factor. By default, the paint commands are recorded at a scale factor
+ // slightly different from the device scale factor. Re-rastering the image at
+ // this paint recording scale will result in a distorted image. Paint
+ // recording scale might also not be uniform along the x & y axis, thus
+ // resulting in further distortion in the aspect ratio of the final image.
+ // |kUniformScaling| ensures that the paint recording scale is uniform along
+ // the x & y axis and keeps the scale equal to the device scale factor.
+ // See http://crbug.com/754010 for more details.
+ return views::PaintInfo::ScaleType::kUniformScaling;
+}
+
+void ImageViewBase::OnBoundsChanged(const gfx::Rect& previous_bounds) {
+ UpdateImageOrigin();
+}
+
+void ImageViewBase::UpdateImageOrigin() {
+ gfx::Size image_size = GetImageSize();
+ gfx::Insets insets = GetInsets();
+
+ int x = 0;
+ // In order to properly handle alignment of images in RTL locales, we need
+ // to flip the meaning of trailing and leading. For example, if the
+ // horizontal alignment is set to trailing, then we'll use left alignment for
+ // the image instead of right alignment if the UI layout is RTL.
+ Alignment actual_horizontal_alignment = horizontal_alignment_;
+ if (base::i18n::IsRTL() && (horizontal_alignment_ != CENTER)) {
+ actual_horizontal_alignment =
+ (horizontal_alignment_ == LEADING) ? TRAILING : LEADING;
+ }
+ switch (actual_horizontal_alignment) {
+ case LEADING:
+ x = insets.left();
+ break;
+ case TRAILING:
+ x = width() - insets.right() - image_size.width();
+ break;
+ case CENTER:
+ x = (width() - insets.width() - image_size.width()) / 2 + insets.left();
+ break;
+ }
+
+ int y = 0;
+ switch (vertical_alignment_) {
+ case LEADING:
+ y = insets.top();
+ break;
+ case TRAILING:
+ y = height() - insets.bottom() - image_size.height();
+ break;
+ case CENTER:
+ y = (height() - insets.height() - image_size.height()) / 2 + insets.top();
+ break;
+ }
+
+ image_origin_ = gfx::Point(x, y);
+}
+
+void ImageViewBase::PreferredSizeChanged() {
+ View::PreferredSizeChanged();
+ UpdateImageOrigin();
+}
+
+} // namespace views
diff --git a/chromium/ui/views/controls/image_view_base.h b/chromium/ui/views/controls/image_view_base.h
new file mode 100644
index 00000000000..4764f2f4c47
--- /dev/null
+++ b/chromium/ui/views/controls/image_view_base.h
@@ -0,0 +1,94 @@
+// 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_VIEWS_CONTROLS_IMAGE_VIEW_BASE_H_
+#define UI_VIEWS_CONTROLS_IMAGE_VIEW_BASE_H_
+
+#include "base/macros.h"
+#include "base/optional.h"
+#include "ui/views/view.h"
+
+namespace gfx {
+class Canvas;
+}
+
+namespace views {
+
+class VIEWS_EXPORT ImageViewBase : public View {
+ public:
+ enum Alignment { LEADING, CENTER, TRAILING };
+
+ ImageViewBase();
+ ~ImageViewBase() override;
+
+ // Set the desired image size for the receiving ImageView.
+ void SetImageSize(const gfx::Size& image_size);
+
+ // Returns the actual bounds of the visible image inside the view.
+ gfx::Rect GetImageBounds() const;
+
+ // Reset the image size to the current image dimensions.
+ void ResetImageSize();
+
+ // Set / Get the horizontal alignment.
+ void SetHorizontalAlignment(Alignment ha);
+ Alignment GetHorizontalAlignment() const;
+
+ // Set / Get the vertical alignment.
+ void SetVerticalAlignment(Alignment va);
+ Alignment GetVerticalAlignment() const;
+
+ // Set / Get the tooltip text.
+ void SetTooltipText(const base::string16& tooltip);
+ base::string16 GetTooltipText() const;
+
+ // Set / Get the accessible name text.
+ void SetAccessibleName(const base::string16& name);
+ base::string16 GetAccessibleName() const;
+
+ // Overridden from View:
+ void OnPaint(gfx::Canvas* canvas) override = 0;
+ void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
+ const char* GetClassName() const override = 0;
+ bool GetTooltipText(const gfx::Point& p,
+ base::string16* tooltip) const override;
+ gfx::Size CalculatePreferredSize() const override;
+ views::PaintInfo::ScaleType GetPaintScaleType() const override;
+ void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
+ void PreferredSizeChanged() override;
+
+ protected:
+ // Returns the size the image will be painted.
+ virtual gfx::Size GetImageSize() const = 0;
+
+ // The requested image size.
+ base::Optional<gfx::Size> image_size_;
+
+ private:
+ friend class ImageViewTest;
+
+ // Recomputes and updates the |image_origin_|.
+ void UpdateImageOrigin();
+
+ // The origin of the image.
+ gfx::Point image_origin_;
+
+ // Horizontal alignment.
+ Alignment horizontal_alignment_ = Alignment::CENTER;
+
+ // Vertical alignment.
+ Alignment vertical_alignment_ = Alignment::CENTER;
+
+ // The current tooltip text.
+ base::string16 tooltip_text_;
+
+ // The current accessible name text.
+ base::string16 accessible_name_;
+
+ DISALLOW_COPY_AND_ASSIGN(ImageViewBase);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_CONTROLS_IMAGE_VIEW_BASE_H_
diff --git a/chromium/ui/views/controls/image_view_unittest.cc b/chromium/ui/views/controls/image_view_unittest.cc
index 28cbb21460a..5e4d4a5576a 100644
--- a/chromium/ui/views/controls/image_view_unittest.cc
+++ b/chromium/ui/views/controls/image_view_unittest.cc
@@ -69,8 +69,8 @@ class ImageViewTest : public ViewsTestBase,
}
int CurrentImageOriginForParam() {
- gfx::Point origin =
- image_view()->ComputeImageOrigin(image_view()->GetImageSize());
+ image_view()->UpdateImageOrigin();
+ gfx::Point origin = image_view()->GetImageBounds().origin();
return GetParam() == Axis::kHorizontal ? origin.x() : origin.y();
}
@@ -126,6 +126,21 @@ TEST_P(ImageViewTest, CenterAlignment) {
EXPECT_EQ(kLeadingInset, CurrentImageOriginForParam());
}
+TEST_P(ImageViewTest, ImageOriginForCustomViewBounds) {
+ gfx::Rect image_view_bounds(10, 10, 80, 80);
+ image_view()->SetHorizontalAlignment(ImageView::CENTER);
+ image_view()->SetBoundsRect(image_view_bounds);
+
+ SkBitmap bitmap;
+ constexpr int kImageSkiaSize = 20;
+ bitmap.allocN32Pixels(kImageSkiaSize, kImageSkiaSize);
+ gfx::ImageSkia image_skia = gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
+ image_view()->SetImage(image_skia);
+
+ EXPECT_EQ(gfx::Point(30, 30), image_view()->GetImageBounds().origin());
+ EXPECT_EQ(image_view_bounds, image_view()->bounds());
+}
+
INSTANTIATE_TEST_CASE_P(,
ImageViewTest,
::testing::Values(Axis::kHorizontal, Axis::kVertical));
diff --git a/chromium/ui/views/controls/label_unittest.cc b/chromium/ui/views/controls/label_unittest.cc
index d87acf7c42d..1ee2b444c42 100644
--- a/chromium/ui/views/controls/label_unittest.cc
+++ b/chromium/ui/views/controls/label_unittest.cc
@@ -20,7 +20,6 @@
#include "ui/events/test/event_generator.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/render_text.h"
-#include "ui/gfx/switches.h"
#include "ui/gfx/text_elider.h"
#include "ui/strings/grit/ui_strings.h"
#include "ui/views/border.h"
@@ -163,14 +162,6 @@ class LabelSelectionTest : public LabelTest {
// LabelTest overrides:
void SetUp() override {
-#if defined(OS_MACOSX)
- // On Mac, by default RenderTextMac is used for labels which does not
- // support text selection. Instead use RenderTextHarfBuzz for selection
- // related tests. TODO(crbug.com/661394): Remove this once Mac also uses
- // RenderTextHarfBuzz for Labels.
- base::CommandLine::ForCurrentProcess()->AppendSwitch(
- switches::kEnableHarfBuzzRenderText);
-#endif
LabelTest::SetUp();
event_generator_ =
std::make_unique<ui::test::EventGenerator>(widget()->GetNativeWindow());
diff --git a/chromium/ui/views/controls/menu/menu_closure_animation_mac.h b/chromium/ui/views/controls/menu/menu_closure_animation_mac.h
index 5c3b6d69aff..e966edd9888 100644
--- a/chromium/ui/views/controls/menu/menu_closure_animation_mac.h
+++ b/chromium/ui/views/controls/menu/menu_closure_animation_mac.h
@@ -14,6 +14,7 @@
namespace views {
class MenuItemView;
+class SubmenuView;
// This class implements the Mac menu closure animation:
// 1) For 100ms, the selected item is drawn as unselected
@@ -24,11 +25,19 @@ class MenuItemView;
// will stop the timer or animation (if they are running), so the callback will
// *not* be run - which is good, since the MenuController that would have
// received it is being deleted.
+//
+// This class also supports animating a menu away without animating the
+// selection effect, which is achieved by passing nullptr for the item to
+// animate. In this case, the animation skips straight to step 3 above.
class VIEWS_EXPORT MenuClosureAnimationMac : public gfx::AnimationDelegate {
public:
- // After this closure animation is done, |callback| is run to finally accept
- // |item|.
- MenuClosureAnimationMac(MenuItemView* item, base::OnceClosure callback);
+ // After this closure animation is done, |callback| is run to finish
+ // dismissing the menu. If |item| is given, this will animate the item being
+ // accepted before animating the menu closing; if |item| is nullptr, only the
+ // menu closure will be animated.
+ MenuClosureAnimationMac(MenuItemView* item,
+ SubmenuView* menu,
+ base::OnceClosure callback);
~MenuClosureAnimationMac() override;
// Start the animation.
@@ -37,6 +46,9 @@ class VIEWS_EXPORT MenuClosureAnimationMac : public gfx::AnimationDelegate {
// Returns the MenuItemView this animation targets.
MenuItemView* item() { return item_; }
+ // Returns the SubmenuView this animation targets.
+ SubmenuView* menu() { return menu_; }
+
// Causes animations to take no time for testing purposes. Note that this
// still causes the completion callback to be run asynchronously, so test
// situations have the same control flow as non-test situations.
@@ -51,7 +63,7 @@ class VIEWS_EXPORT MenuClosureAnimationMac : public gfx::AnimationDelegate {
kFinish,
};
- static constexpr AnimationStep NextStepFor(AnimationStep step);
+ AnimationStep NextStepFor(AnimationStep step) const;
void AdvanceAnimation();
@@ -64,6 +76,7 @@ class VIEWS_EXPORT MenuClosureAnimationMac : public gfx::AnimationDelegate {
base::OneShotTimer timer_;
std::unique_ptr<gfx::Animation> fade_animation_;
MenuItemView* item_;
+ SubmenuView* menu_;
AnimationStep step_;
DISALLOW_COPY_AND_ASSIGN(MenuClosureAnimationMac);
diff --git a/chromium/ui/views/controls/menu/menu_closure_animation_mac.mm b/chromium/ui/views/controls/menu/menu_closure_animation_mac.mm
index 2bec6d31087..32127db42d9 100644
--- a/chromium/ui/views/controls/menu/menu_closure_animation_mac.mm
+++ b/chromium/ui/views/controls/menu/menu_closure_animation_mac.mm
@@ -10,6 +10,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "ui/gfx/animation/linear_animation.h"
#include "ui/views/controls/menu/menu_item_view.h"
+#include "ui/views/controls/menu/submenu_view.h"
#include "ui/views/widget/widget.h"
namespace {
@@ -19,9 +20,11 @@ static bool g_disable_animations_for_testing = false;
namespace views {
MenuClosureAnimationMac::MenuClosureAnimationMac(MenuItemView* item,
+ SubmenuView* menu,
base::OnceClosure callback)
: callback_(std::move(callback)),
item_(item),
+ menu_(menu),
step_(AnimationStep::kStart) {}
MenuClosureAnimationMac::~MenuClosureAnimationMac() {}
@@ -42,12 +45,11 @@ void MenuClosureAnimationMac::Start() {
}
// static
-constexpr MenuClosureAnimationMac::AnimationStep
-MenuClosureAnimationMac::NextStepFor(
- MenuClosureAnimationMac::AnimationStep step) {
+MenuClosureAnimationMac::AnimationStep MenuClosureAnimationMac::NextStepFor(
+ MenuClosureAnimationMac::AnimationStep step) const {
switch (step) {
case AnimationStep::kStart:
- return AnimationStep::kUnselected;
+ return item_ ? AnimationStep::kUnselected : AnimationStep::kFading;
case AnimationStep::kUnselected:
return AnimationStep::kSelected;
case AnimationStep::kSelected:
@@ -84,7 +86,7 @@ void MenuClosureAnimationMac::DisableAnimationsForTesting() {
void MenuClosureAnimationMac::AnimationProgressed(
const gfx::Animation* animation) {
- NSWindow* window = item_->GetWidget()->GetNativeWindow();
+ NSWindow* window = menu_->GetWidget()->GetNativeWindow();
[window setAlphaValue:animation->CurrentValueBetween(1.0, 0.0)];
}
diff --git a/chromium/ui/views/controls/menu/menu_config.cc b/chromium/ui/views/controls/menu/menu_config.cc
index 7ea5c0104bc..3dc6eef0d4f 100644
--- a/chromium/ui/views/controls/menu/menu_config.cc
+++ b/chromium/ui/views/controls/menu/menu_config.cc
@@ -5,6 +5,7 @@
#include "ui/views/controls/menu/menu_config.h"
#include "base/macros.h"
+#include "base/no_destructor.h"
#include "ui/views/controls/menu/menu_controller.h"
#include "ui/views/controls/menu/menu_image_util.h"
#include "ui/views/controls/menu/menu_item_view.h"
@@ -100,8 +101,8 @@ bool MenuConfig::ShouldShowAcceleratorText(const MenuItemView* item,
// static
const MenuConfig& MenuConfig::instance() {
- CR_DEFINE_STATIC_LOCAL(MenuConfig, instance, ());
- return instance;
+ static base::NoDestructor<MenuConfig> instance;
+ return *instance;
}
} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu_config_win.cc b/chromium/ui/views/controls/menu/menu_config_win.cc
index 6048ee062fd..72665510ca0 100644
--- a/chromium/ui/views/controls/menu/menu_config_win.cc
+++ b/chromium/ui/views/controls/menu/menu_config_win.cc
@@ -10,9 +10,8 @@
#include "base/logging.h"
#include "base/win/scoped_gdi_object.h"
-#include "base/win/win_client_metrics.h"
-#include "ui/base/l10n/l10n_util_win.h"
#include "ui/gfx/color_utils.h"
+#include "ui/gfx/platform_font_win.h"
#include "ui/native_theme/native_theme_win.h"
using ui::NativeTheme;
@@ -21,15 +20,9 @@ namespace views {
void MenuConfig::Init() {
arrow_color = color_utils::GetSysSkColor(COLOR_MENUTEXT);
+ font_list = gfx::FontList(gfx::PlatformFontWin::GetSystemFont(
+ gfx::PlatformFontWin::SystemFont::kMenu));
- NONCLIENTMETRICS_XP metrics;
- base::win::GetNonClientMetrics(&metrics);
- l10n_util::AdjustUIFont(&(metrics.lfMenuFont));
- {
- base::win::ScopedHFONT new_font(CreateFontIndirect(&metrics.lfMenuFont));
- DLOG_ASSERT(new_font.is_valid());
- font_list = gfx::FontList(gfx::Font(new_font.get()));
- }
NativeTheme::ExtraParams extra;
gfx::Size arrow_size = NativeTheme::GetInstanceForNativeUi()->GetPartSize(
NativeTheme::kMenuPopupArrow, NativeTheme::kNormal, extra);
diff --git a/chromium/ui/views/controls/menu/menu_controller.cc b/chromium/ui/views/controls/menu/menu_controller.cc
index d6806061652..9e56ca54813 100644
--- a/chromium/ui/views/controls/menu/menu_controller.cc
+++ b/chromium/ui/views/controls/menu/menu_controller.cc
@@ -499,6 +499,10 @@ void MenuController::Run(Widget* parent,
}
void MenuController::Cancel(ExitType type) {
+#if defined(OS_MACOSX)
+ menu_closure_animation_.reset();
+#endif
+
// If the menu has already been destroyed, no further cancellation is
// needed. We especially don't want to set the |exit_type_| to a lesser
// value.
@@ -1529,7 +1533,7 @@ void MenuController::UpdateInitialLocation(const gfx::Rect& bounds,
void MenuController::Accept(MenuItemView* item, int event_flags) {
#if defined(OS_MACOSX)
menu_closure_animation_ = std::make_unique<MenuClosureAnimationMac>(
- item,
+ item, item->GetParentMenuItem()->GetSubmenu(),
base::BindOnce(&MenuController::ReallyAccept, base::Unretained(this),
base::Unretained(item), event_flags));
menu_closure_animation_->Start();
@@ -1845,8 +1849,7 @@ void MenuController::CommitPendingSelection() {
// Open all the submenus preceeding the last menu item (last menu item is
// handled next).
if (new_path.size() > 1) {
- for (std::vector<MenuItemView*>::iterator i = new_path.begin();
- i != new_path.end() - 1; ++i) {
+ for (auto i = new_path.begin(); i != new_path.end() - 1; ++i) {
OpenMenu(*i);
}
}
@@ -2070,10 +2073,9 @@ gfx::Rect MenuController::CalculateMenuBounds(MenuItemView* item,
const int right_of_parent =
item_loc.x() + item->width() - submenu_horizontal_inset;
- int border_size = menu_config.CornerRadiusForMenu(this);
- if (!border_size)
- border_size = menu_config.menu_vertical_border_size;
- menu_bounds.set_y(item_loc.y() - border_size);
+ MenuScrollViewContainer* container =
+ item->GetParentMenuItem()->GetSubmenu()->GetScrollViewContainer();
+ menu_bounds.set_y(item_loc.y() - container->border()->GetInsets().top());
// Assume the menu can be placed in the preferred location.
menu_bounds.set_x(create_on_right ? right_of_parent : left_of_parent);
@@ -2609,7 +2611,18 @@ void MenuController::RepostEventAndCancel(SubmenuView* source,
if (last_part.type != MenuPart::NONE)
exit_type = EXIT_OUTERMOST;
}
+#if defined(OS_MACOSX)
+ SubmenuView* target = exit_type == EXIT_ALL
+ ? source
+ : state_.item->GetRootMenuItem()->GetSubmenu();
+ menu_closure_animation_ = std::make_unique<MenuClosureAnimationMac>(
+ nullptr, target,
+ base::BindOnce(&MenuController::Cancel, base::Unretained(this),
+ exit_type));
+ menu_closure_animation_->Start();
+#else
Cancel(exit_type);
+#endif
}
void MenuController::SetDropMenuItem(MenuItemView* new_target,
diff --git a/chromium/ui/views/controls/menu/menu_controller_unittest.cc b/chromium/ui/views/controls/menu/menu_controller_unittest.cc
index 57c22228ae9..ad8f6732a80 100644
--- a/chromium/ui/views/controls/menu/menu_controller_unittest.cc
+++ b/chromium/ui/views/controls/menu/menu_controller_unittest.cc
@@ -1232,6 +1232,7 @@ TEST_F(MenuControllerTest, PreserveGestureForOwner) {
// Tests that touch outside menu does not closes the menu when forwarding
// gesture events to owner.
TEST_F(MenuControllerTest, NoTouchCloseWhenSendingGesturesToOwner) {
+ views::test::DisableMenuClosureAnimations();
MenuController* controller = menu_controller();
// Owner wants the gesture events.
@@ -1259,6 +1260,7 @@ TEST_F(MenuControllerTest, NoTouchCloseWhenSendingGesturesToOwner) {
// Touch outside again and menu should be closed.
controller->OnTouchEvent(sub_menu, &touch_event);
+ views::test::WaitForMenuClosureAnimation();
EXPECT_FALSE(IsShowing());
EXPECT_EQ(MenuController::EXIT_ALL, controller->exit_type());
}
@@ -1267,6 +1269,7 @@ TEST_F(MenuControllerTest, NoTouchCloseWhenSendingGesturesToOwner) {
// occur outside of the bounds of the menu. Instead a proper shutdown should
// occur.
TEST_F(MenuControllerTest, AsynchronousRepostEvent) {
+ views::test::DisableMenuClosureAnimations();
MenuController* controller = menu_controller();
TestMenuControllerDelegate* delegate = menu_controller_delegate();
std::unique_ptr<TestMenuControllerDelegate> nested_delegate(
@@ -1291,6 +1294,7 @@ TEST_F(MenuControllerTest, AsynchronousRepostEvent) {
// When attempting to select outside of all menus this should lead to a
// shutdown. This should not crash while attempting to repost the event.
SetSelectionOnPointerDown(sub_menu, &event);
+ views::test::WaitForMenuClosureAnimation();
EXPECT_EQ(delegate, GetCurrentDelegate());
EXPECT_EQ(1, delegate->on_menu_closed_called());
@@ -1305,6 +1309,7 @@ TEST_F(MenuControllerTest, AsynchronousRepostEvent) {
// Tests that an asynchronous menu reposts touch events that occur outside of
// the bounds of the menu, and that the menu closes.
TEST_F(MenuControllerTest, AsynchronousTouchEventRepostEvent) {
+ views::test::DisableMenuClosureAnimations();
MenuController* controller = menu_controller();
TestMenuControllerDelegate* delegate = menu_controller_delegate();
@@ -1319,6 +1324,7 @@ TEST_F(MenuControllerTest, AsynchronousTouchEventRepostEvent) {
ui::ET_TOUCH_PRESSED, location, ui::EventTimeForNow(),
ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
controller->OnTouchEvent(sub_menu, &event);
+ views::test::WaitForMenuClosureAnimation();
EXPECT_FALSE(IsShowing());
EXPECT_EQ(1, delegate->on_menu_closed_called());
@@ -1332,6 +1338,7 @@ TEST_F(MenuControllerTest, AsynchronousTouchEventRepostEvent) {
// Tests that having the MenuController deleted during RepostEvent does not
// cause a crash. ASAN bots should not detect use-after-free in MenuController.
TEST_F(MenuControllerTest, AsynchronousRepostEventDeletesController) {
+ views::test::DisableMenuClosureAnimations();
MenuController* controller = menu_controller();
std::unique_ptr<TestMenuControllerDelegate> nested_delegate(
new TestMenuControllerDelegate());
@@ -1358,6 +1365,7 @@ TEST_F(MenuControllerTest, AsynchronousRepostEventDeletesController) {
// When attempting to select outside of all menus this should lead to a
// shutdown. This should not crash while attempting to repost the event.
SetSelectionOnPointerDown(sub_menu, &event);
+ views::test::WaitForMenuClosureAnimation();
// Close to remove observers before test TearDown
sub_menu->Close();
diff --git a/chromium/ui/views/controls/menu/menu_host.cc b/chromium/ui/views/controls/menu/menu_host.cc
index 104ae4c6da5..780a0f9c27b 100644
--- a/chromium/ui/views/controls/menu/menu_host.cc
+++ b/chromium/ui/views/controls/menu/menu_host.cc
@@ -86,7 +86,7 @@ void TransferGesture(Widget* source, Widget* target) {
#else // !defined(OS_MACOSX)
source->GetGestureRecognizer()->TransferEventsTo(
source->GetNativeView(), target->GetNativeView(),
- ui::GestureRecognizer::ShouldCancelTouches::DontCancel);
+ ui::TransferTouchesBehavior::kDontCancel);
#endif // defined(OS_MACOSX)
}
diff --git a/chromium/ui/views/controls/menu/menu_item_view.cc b/chromium/ui/views/controls/menu/menu_item_view.cc
index 6c007a1030c..7b17d2662ec 100644
--- a/chromium/ui/views/controls/menu/menu_item_view.cc
+++ b/chromium/ui/views/controls/menu/menu_item_view.cc
@@ -155,7 +155,18 @@ bool MenuItemView::GetTooltipText(const gfx::Point& p,
}
void MenuItemView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
- node_data->role = ax::mojom::Role::kMenuItem;
+ // Set the role based on the type of menu item.
+ switch (GetType()) {
+ case CHECKBOX:
+ node_data->role = ax::mojom::Role::kMenuItemCheckBox;
+ break;
+ case RADIO:
+ node_data->role = ax::mojom::Role::kMenuItemRadio;
+ break;
+ default:
+ node_data->role = ax::mojom::Role::kMenuItem;
+ break;
+ }
base::string16 item_text;
if (IsContainer()) {
@@ -867,7 +878,7 @@ void MenuItemView::GetLabelStyle(MenuDelegate::LabelStyle* style) const {
void MenuItemView::AddEmptyMenus() {
DCHECK(HasSubmenu());
- if (!submenu_->HasVisibleChildren()) {
+ if (!submenu_->HasVisibleChildren() && !submenu_->HasEmptyMenuItemView()) {
submenu_->AddChildViewAt(new EmptyMenuMenuItem(this), 0);
} else {
for (int i = 0, item_count = submenu_->GetMenuItemCount(); i < item_count;
diff --git a/chromium/ui/views/controls/menu/menu_item_view_unittest.cc b/chromium/ui/views/controls/menu/menu_item_view_unittest.cc
index 07273f5de1a..e4f42f008b4 100644
--- a/chromium/ui/views/controls/menu/menu_item_view_unittest.cc
+++ b/chromium/ui/views/controls/menu/menu_item_view_unittest.cc
@@ -136,13 +136,18 @@ TEST(MenuItemViewUnitTest, TestEmptySubmenuWhenAllChildItemsAreHidden) {
EXPECT_EQ(2, submenu->child_count());
// Adds any empty menu items to the menu, if needed.
+ EXPECT_FALSE(submenu->HasEmptyMenuItemView());
root_menu.AddEmptyMenus();
-
+ EXPECT_TRUE(submenu->HasEmptyMenuItemView());
// Because all of the submenu's children are hidden, an empty menu item should
// have been added.
ASSERT_EQ(3, submenu->child_count());
MenuItemView* empty_item = static_cast<MenuItemView*>(submenu->child_at(0));
ASSERT_TRUE(empty_item);
+ // Not allowed to add an duplicated empty menu item
+ // if it already has an empty menu item.
+ root_menu.AddEmptyMenus();
+ ASSERT_EQ(3, submenu->child_count());
ASSERT_EQ(MenuItemView::kEmptyMenuItemViewID, empty_item->id());
EXPECT_EQ(l10n_util::GetStringUTF16(IDS_APP_MENU_EMPTY_SUBMENU),
empty_item->title());
diff --git a/chromium/ui/views/controls/menu/menu_pre_target_handler_aura.cc b/chromium/ui/views/controls/menu/menu_pre_target_handler_aura.cc
index 45b071661bb..b38b0d49d53 100644
--- a/chromium/ui/views/controls/menu/menu_pre_target_handler_aura.cc
+++ b/chromium/ui/views/controls/menu/menu_pre_target_handler_aura.cc
@@ -6,6 +6,7 @@
#include "ui/aura/env.h"
#include "ui/aura/window.h"
+#include "ui/base/ui_base_features.h"
#include "ui/views/controls/menu/menu_controller.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/public/activation_client.h"
@@ -23,16 +24,27 @@ aura::Window* GetOwnerRootWindow(views::Widget* owner) {
MenuPreTargetHandlerAura::MenuPreTargetHandlerAura(MenuController* controller,
Widget* owner)
: controller_(controller), root_(GetOwnerRootWindow(owner)) {
- aura::Env::GetInstance()->AddPreTargetHandler(
- this, ui::EventTarget::Priority::kSystem);
if (root_) {
+ root_->env()->AddPreTargetHandler(this, ui::EventTarget::Priority::kSystem);
wm::GetActivationClient(root_)->AddObserver(this);
root_->AddObserver(this);
+ } else {
+ // TODO(mukai): check if this code path can run in ChromeOS and find the
+ // solution for SingleProcessMash.
+ if (features::IsUsingWindowService()) {
+ LOG(WARNING) << "MenuPreTargetHandlerAura is created without owner "
+ << "widget. This may not work well in SingleProcessMash.";
+ }
+ aura::Env::GetInstance()->AddPreTargetHandler(
+ this, ui::EventTarget::Priority::kSystem);
}
}
MenuPreTargetHandlerAura::~MenuPreTargetHandlerAura() {
- aura::Env::GetInstance()->RemovePreTargetHandler(this);
+ if (root_)
+ root_->env()->RemovePreTargetHandler(this);
+ else
+ aura::Env::GetInstance()->RemovePreTargetHandler(this);
Cleanup();
}
diff --git a/chromium/ui/views/controls/menu/menu_runner_cocoa_unittest.mm b/chromium/ui/views/controls/menu/menu_runner_cocoa_unittest.mm
index 2cc6a8c1a7c..7acfc99f907 100644
--- a/chromium/ui/views/controls/menu/menu_runner_cocoa_unittest.mm
+++ b/chromium/ui/views/controls/menu/menu_runner_cocoa_unittest.mm
@@ -106,6 +106,8 @@ class MenuRunnerCocoaTest : public ViewsTestBase,
gfx::Rect(kWindowOffset, kWindowOffset, kWindowWidth, kWindowHeight));
parent_->Show();
+ native_view_subview_count_ = [[parent_->GetNativeView() subviews] count];
+
base::Closure on_close = base::Bind(&MenuRunnerCocoaTest::MenuCloseCallback,
base::Unretained(this));
if (GetParam() == MenuType::NATIVE)
@@ -116,6 +118,9 @@ class MenuRunnerCocoaTest : public ViewsTestBase,
}
void TearDown() override {
+ EXPECT_EQ(native_view_subview_count_,
+ [[parent_->GetNativeView() subviews] count]);
+
if (runner_) {
runner_->Release();
runner_ = NULL;
@@ -151,10 +156,6 @@ class MenuRunnerCocoaTest : public ViewsTestBase,
void RunMenuAt(const gfx::Rect& anchor) {
last_anchor_frame_ = NSZeroRect;
- // Should be one child (the compositor layer) before showing, and it should
- // go up by one (the anchor view) while the menu is shown.
- EXPECT_EQ(1u, [[parent_->GetNativeView() subviews] count]);
-
base::OnceClosure callback =
base::BindOnce(&MenuRunnerCocoaTest::ComboboxRunMenuAtCallback,
base::Unretained(this));
@@ -168,9 +169,6 @@ class MenuRunnerCocoaTest : public ViewsTestBase,
runner_->RunMenuAt(parent_, nullptr, anchor, MENU_ANCHOR_TOPLEFT,
MenuRunner::COMBOBOX);
MaybeRunAsync();
-
- // Ensure the anchor view is removed.
- EXPECT_EQ(1u, [[parent_->GetNativeView() subviews] count]);
}
void MenuCancelCallback() {
@@ -244,6 +242,7 @@ class MenuRunnerCocoaTest : public ViewsTestBase,
internal::MenuRunnerImplInterface* runner_ = nullptr;
views::Widget* parent_ = nullptr;
NSRect last_anchor_frame_ = NSZeroRect;
+ NSUInteger native_view_subview_count_ = 0;
int menu_close_count_ = 0;
private:
@@ -256,10 +255,11 @@ class MenuRunnerCocoaTest : public ViewsTestBase,
NSArray* subviews = [parent_->GetNativeView() subviews];
// An anchor view should only be added for Native menus.
if (GetParam() == MenuType::NATIVE) {
- ASSERT_EQ(2u, [subviews count]);
- last_anchor_frame_ = [[subviews objectAtIndex:1] frame];
+ ASSERT_EQ(native_view_subview_count_ + 1, [subviews count]);
+ last_anchor_frame_ =
+ [[subviews objectAtIndex:native_view_subview_count_] frame];
} else {
- EXPECT_EQ(1u, [subviews count]);
+ EXPECT_EQ(native_view_subview_count_, [subviews count]);
}
runner_->Cancel();
}
diff --git a/chromium/ui/views/controls/menu/menu_runner_impl.cc b/chromium/ui/views/controls/menu/menu_runner_impl.cc
index 1c7b5c4c72a..3f1fb8af38b 100644
--- a/chromium/ui/views/controls/menu/menu_runner_impl.cc
+++ b/chromium/ui/views/controls/menu/menu_runner_impl.cc
@@ -192,8 +192,7 @@ void MenuRunnerImpl::SiblingMenuCreated(MenuItemView* menu) {
MenuRunnerImpl::~MenuRunnerImpl() {
delete menu_;
- for (std::set<MenuItemView*>::iterator i = sibling_menus_.begin();
- i != sibling_menus_.end(); ++i)
+ for (auto i = sibling_menus_.begin(); i != sibling_menus_.end(); ++i)
delete *i;
}
diff --git a/chromium/ui/views/controls/menu/submenu_view.cc b/chromium/ui/views/controls/menu/submenu_view.cc
index c9ad4e4f5b9..36865a59316 100644
--- a/chromium/ui/views/controls/menu/submenu_view.cc
+++ b/chromium/ui/views/controls/menu/submenu_view.cc
@@ -61,6 +61,14 @@ SubmenuView::~SubmenuView() {
delete scroll_view_container_;
}
+bool SubmenuView::HasEmptyMenuItemView() {
+ for (int i = 0; i < child_count(); i++) {
+ if (child_at(i)->id() == MenuItemView::kEmptyMenuItemViewID)
+ return true;
+ }
+ return false;
+}
+
bool SubmenuView::HasVisibleChildren() {
for (int i = 0, item_count = GetMenuItemCount(); i < item_count; i++) {
if (GetMenuItemAt(i)->visible())
diff --git a/chromium/ui/views/controls/menu/submenu_view.h b/chromium/ui/views/controls/menu/submenu_view.h
index 9ba69331264..4374790035e 100644
--- a/chromium/ui/views/controls/menu/submenu_view.h
+++ b/chromium/ui/views/controls/menu/submenu_view.h
@@ -51,6 +51,9 @@ class VIEWS_EXPORT SubmenuView : public View,
explicit SubmenuView(MenuItemView* parent);
~SubmenuView() override;
+ // Returns true if the submenu has at least one empty menu item.
+ bool HasEmptyMenuItemView();
+
// Returns true if the submenu has at least one visible child item.
bool HasVisibleChildren();
diff --git a/chromium/ui/views/controls/native/native_view_host.cc b/chromium/ui/views/controls/native/native_view_host.cc
index 32019ba3fdb..5240d2bf72d 100644
--- a/chromium/ui/views/controls/native/native_view_host.cc
+++ b/chromium/ui/views/controls/native/native_view_host.cc
@@ -67,6 +67,10 @@ void NativeViewHost::SetNativeViewSize(const gfx::Size& size) {
InvalidateLayout();
}
+gfx::NativeView NativeViewHost::GetNativeViewContainer() const {
+ return native_view_ ? native_wrapper_->GetNativeViewContainer() : nullptr;
+}
+
void NativeViewHost::NativeViewDestroyed() {
// Detach so we can clear our state and notify the native_wrapper_ to release
// ref on the native view.
@@ -225,7 +229,7 @@ void NativeViewHost::ClearFocus() {
Widget::Widgets widgets;
Widget::GetAllChildWidgets(native_view(), &widgets);
- for (Widget::Widgets::iterator i = widgets.begin(); i != widgets.end(); ++i) {
+ for (auto i = widgets.begin(); i != widgets.end(); ++i) {
focus_manager->ViewRemoved((*i)->GetRootView());
if (!focus_manager->GetFocusedView())
return;
diff --git a/chromium/ui/views/controls/native/native_view_host.h b/chromium/ui/views/controls/native/native_view_host.h
index 5bd897cf3ed..ec0b8e9f18a 100644
--- a/chromium/ui/views/controls/native/native_view_host.h
+++ b/chromium/ui/views/controls/native/native_view_host.h
@@ -63,6 +63,10 @@ class VIEWS_EXPORT NativeViewHost : public View {
// NatieView's size always equals this View's size.
void SetNativeViewSize(const gfx::Size& size);
+ // Returns the container that contains this host's native view. Returns null
+ // if there's no attached native view or it has no container.
+ gfx::NativeView GetNativeViewContainer() const;
+
// Fast resizing will move the native view and clip its visible region, this
// will result in white areas and will not resize the content (so scrollbars
// will be all wrong and content will flow offscreen). Only use this
diff --git a/chromium/ui/views/controls/native/native_view_host_aura.cc b/chromium/ui/views/controls/native/native_view_host_aura.cc
index 4bd67c7a87d..3be7f536eb1 100644
--- a/chromium/ui/views/controls/native/native_view_host_aura.cc
+++ b/chromium/ui/views/controls/native/native_view_host_aura.cc
@@ -5,6 +5,7 @@
#include "ui/views/controls/native/native_view_host_aura.h"
#include "base/logging.h"
+#include "base/optional.h"
#include "build/build_config.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/focus_client.h"
@@ -98,10 +99,12 @@ void NativeViewHostAura::AttachNativeView() {
}
void NativeViewHostAura::NativeViewDetaching(bool destroyed) {
- // This method causes a succession of window tree changes.
- // ScopedPauseOcclusionTracking ensures that occlusion is recomputed at the
- // end of the method instead of after each change.
- aura::WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion;
+ // This method causes a succession of window tree changes. ScopedPause ensures
+ // that occlusion is recomputed at the end of the method instead of after each
+ // change.
+ base::Optional<aura::WindowOcclusionTracker::ScopedPause> pause_occlusion;
+ if (clipping_window_)
+ pause_occlusion.emplace(clipping_window_->env());
clipping_window_delegate_->set_native_view(NULL);
RemoveClippingWindow();
@@ -212,6 +215,10 @@ void NativeViewHostAura::SetFocus() {
client->FocusWindow(window);
}
+gfx::NativeView NativeViewHostAura::GetNativeViewContainer() const {
+ return clipping_window_.get();
+}
+
gfx::NativeViewAccessible NativeViewHostAura::GetNativeViewAccessible() {
return NULL;
}
diff --git a/chromium/ui/views/controls/native/native_view_host_aura.h b/chromium/ui/views/controls/native/native_view_host_aura.h
index a6072997977..0adf8fb3aec 100644
--- a/chromium/ui/views/controls/native/native_view_host_aura.h
+++ b/chromium/ui/views/controls/native/native_view_host_aura.h
@@ -41,6 +41,7 @@ class NativeViewHostAura : public NativeViewHostWrapper,
override;
void HideWidget() override;
void SetFocus() override;
+ gfx::NativeView GetNativeViewContainer() const override;
gfx::NativeViewAccessible GetNativeViewAccessible() override;
gfx::NativeCursor GetCursor(int x, int y) override;
diff --git a/chromium/ui/views/controls/native/native_view_host_mac.h b/chromium/ui/views/controls/native/native_view_host_mac.h
index 69659c9aafd..f46e575e442 100644
--- a/chromium/ui/views/controls/native/native_view_host_mac.h
+++ b/chromium/ui/views/controls/native/native_view_host_mac.h
@@ -7,24 +7,35 @@
#include "base/mac/scoped_nsobject.h"
#include "base/macros.h"
+#include "ui/base/cocoa/views_hostable.h"
#include "ui/views/controls/native/native_view_host_wrapper.h"
#include "ui/views/views_export.h"
namespace ui {
class LayerOwner;
-}
+class ViewsHostableView;
+} // namespace ui
namespace views {
+class BridgedNativeWidgetHostImpl;
class NativeViewHost;
// Mac implementation of NativeViewHostWrapper.
-class NativeViewHostMac : public NativeViewHostWrapper {
+class NativeViewHostMac : public NativeViewHostWrapper,
+ public ui::ViewsHostableView::Host {
public:
explicit NativeViewHostMac(NativeViewHost* host);
~NativeViewHostMac() override;
- // Overridden from NativeViewHostWrapper:
+ // ViewsHostableView::Host:
+ ui::Layer* GetUiLayer() const override;
+ uint64_t GetViewsFactoryHostId() const override;
+ uint64_t GetNSViewId() const override;
+ id GetAccessibilityElement() const override;
+ void OnHostableViewDestroying() override;
+
+ // NativeViewHostWrapper:
void AttachNativeView() override;
void NativeViewDetaching(bool destroyed) override;
void AddedToWidget() override;
@@ -37,16 +48,25 @@ class NativeViewHostMac : public NativeViewHostWrapper {
override;
void HideWidget() override;
void SetFocus() override;
+ gfx::NativeView GetNativeViewContainer() const override;
gfx::NativeViewAccessible GetNativeViewAccessible() override;
gfx::NativeCursor GetCursor(int x, int y) override;
private:
+ // Return the BridgedNativeWidgetHostImpl for this hosted view.
+ BridgedNativeWidgetHostImpl* GetBridgedNativeWidgetHost() const;
+
// Our associated NativeViewHost. Owns this.
NativeViewHost* host_;
// Retain the native view as it may be destroyed at an unpredictable time.
base::scoped_nsobject<NSView> native_view_;
+ // If |native_view| supports the ViewsHostable protocol, then this is the
+ // the corresponding ViewsHostableView interface (which is implemeted only
+ // by WebContents and tests).
+ ui::ViewsHostableView* native_view_hostable_ = nullptr;
+
DISALLOW_COPY_AND_ASSIGN(NativeViewHostMac);
};
diff --git a/chromium/ui/views/controls/native/native_view_host_mac.mm b/chromium/ui/views/controls/native/native_view_host_mac.mm
index debbe51f102..d98e6e1456c 100644
--- a/chromium/ui/views/controls/native/native_view_host_mac.mm
+++ b/chromium/ui/views/controls/native/native_view_host_mac.mm
@@ -8,19 +8,11 @@
#include "base/mac/foundation_util.h"
#import "ui/accessibility/platform/ax_platform_node_mac.h"
-#import "ui/base/cocoa/accessibility_hostable.h"
-#import "ui/views/cocoa/bridged_native_widget.h"
+#import "ui/views/cocoa/bridged_native_widget_host_impl.h"
#include "ui/views/controls/native/native_view_host.h"
#include "ui/views/widget/native_widget_mac.h"
#include "ui/views/widget/widget.h"
-// NSViews that can be drawn as a ui::Layer directly will implement this
-// interface. Calling cr_setParentLayer will embed the ui::Layer of the NSView
-// under |parentUiLayer|.
-@interface NSView (UICompositor)
-- (void)cr_setParentUiLayer:(ui::Layer*)parentUiLayer;
-@end
-
namespace views {
namespace {
@@ -59,6 +51,60 @@ NativeViewHostMac::NativeViewHostMac(NativeViewHost* host) : host_(host) {
NativeViewHostMac::~NativeViewHostMac() {
}
+BridgedNativeWidgetHostImpl* NativeViewHostMac::GetBridgedNativeWidgetHost()
+ const {
+ return BridgedNativeWidgetHostImpl::GetFromNativeWindow(
+ host_->GetWidget()->GetNativeWindow());
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// NativeViewHostMac, ViewsHostableView::Host implementation:
+
+ui::Layer* NativeViewHostMac::GetUiLayer() const {
+ return host_->layer();
+}
+
+uint64_t NativeViewHostMac::GetViewsFactoryHostId() const {
+ auto* bridge_host = GetBridgedNativeWidgetHost();
+ if (bridge_host && bridge_host->bridge_factory_host())
+ return bridge_host->bridge_factory_host()->GetHostId();
+ return 0;
+}
+
+uint64_t NativeViewHostMac::GetNSViewId() const {
+ auto* bridge_host = GetBridgedNativeWidgetHost();
+ if (bridge_host)
+ return bridge_host->GetRootViewNSViewId();
+ return 0;
+}
+
+id NativeViewHostMac::GetAccessibilityElement() const {
+ // Find the closest ancestor view that participates in the views toolkit
+ // accessibility hierarchy and set its element as the native view's parent.
+ // This is necessary because a closer ancestor might already be attaching
+ // to the NSView/content hierarchy.
+ // For example, web content is currently embedded into the views hierarchy
+ // roughly like this:
+ // BrowserView (views)
+ // |_ WebView (views)
+ // |_ NativeViewHost (views)
+ // |_ WebContentView (Cocoa, is |native_view_| in this scenario,
+ // | accessibility ignored).
+ // |_ RenderWidgetHostView (Cocoa)
+ // WebView specifies either the RenderWidgetHostView or the native view as
+ // its accessibility element. That means that if we were to set it as
+ // |native_view_|'s parent, the RenderWidgetHostView would be its own
+ // accessibility parent! Instead, we want to find the browser view and
+ // attach to its node.
+ return ClosestPlatformAncestorNode(host_->parent());
+}
+
+void NativeViewHostMac::OnHostableViewDestroying() {
+ DCHECK(native_view_hostable_);
+ host_->NativeViewDestroyed();
+ DCHECK(!native_view_hostable_);
+}
+
////////////////////////////////////////////////////////////////////////////////
// NativeViewHostMac, NativeViewHostWrapper implementation:
@@ -66,46 +112,25 @@ void NativeViewHostMac::AttachNativeView() {
DCHECK(host_->native_view());
DCHECK(!native_view_);
native_view_.reset([host_->native_view() retain]);
+ EnsureNativeViewHasNoChildWidgets(native_view_);
- if ([native_view_ respondsToSelector:@selector(cr_setParentUiLayer:)])
- [native_view_ cr_setParentUiLayer:host_->layer()];
- if ([native_view_ conformsToProtocol:@protocol(AccessibilityHostable)]) {
- // Find the closest ancestor view that participates in the views toolkit
- // accessibility hierarchy and set its element as the native view's parent.
- // This is necessary because a closer ancestor might already be attaching
- // to the NSView/content hierarchy.
- // For example, web content is currently embedded into the views hierarchy
- // roughly like this:
- // BrowserView (views)
- // |_ WebView (views)
- // |_ NativeViewHost (views)
- // |_ WebContentView (Cocoa, is |native_view_| in this scenario,
- // | accessibility ignored).
- // |_ RenderWidgetHostView (Cocoa)
- // WebView specifies either the RenderWidgetHostView or the native view as
- // its accessibility element. That means that if we were to set it as
- // |native_view_|'s parent, the RenderWidgetHostView would be its own
- // accessibility parent! Instead, we want to find the browser view and
- // attach to its node.
+ auto* bridge_host = GetBridgedNativeWidgetHost();
+ DCHECK(bridge_host);
+ [bridge_host->native_widget_mac()->GetNativeView() addSubview:native_view_];
+ bridge_host->SetAssociationForView(host_, native_view_);
+
+ if ([native_view_ conformsToProtocol:@protocol(ViewsHostable)]) {
id hostable = native_view_;
- [hostable setAccessibilityParentElement:ClosestPlatformAncestorNode(
- host_->parent())];
+ native_view_hostable_ = [hostable viewsHostableView];
+ if (native_view_hostable_)
+ native_view_hostable_->OnViewsHostableAttached(this);
}
-
- EnsureNativeViewHasNoChildWidgets(native_view_);
- BridgedNativeWidget* bridge = NativeWidgetMac::GetBridgeForNativeWindow(
- host_->GetWidget()->GetNativeWindow());
- DCHECK(bridge);
- [bridge->ns_view() addSubview:native_view_];
- bridge->SetAssociationForView(host_, native_view_);
}
void NativeViewHostMac::NativeViewDetaching(bool destroyed) {
- // |destroyed| is only true if this class calls host_->NativeViewDestroyed().
- // Aura does this after observing an aura OnWindowDestroying, but NSViews
- // are reference counted so there isn't a reliable signal. Instead, a
- // reference is retained until the NativeViewHost is detached.
- DCHECK(!destroyed);
+ // |destroyed| is only true if this class calls host_->NativeViewDestroyed(),
+ // which is called if a hosted WebContentsView about to be destroyed (note
+ // that its corresponding NSView may still exist).
// |native_view_| can be nil here if RemovedFromWidget() is called before
// NativeViewHost::Detach().
@@ -118,19 +143,16 @@ void NativeViewHostMac::NativeViewDetaching(bool destroyed) {
[host_->native_view() setHidden:YES];
[host_->native_view() removeFromSuperview];
- if ([native_view_ respondsToSelector:@selector(cr_setParentUiLayer:)])
- [native_view_ cr_setParentUiLayer:nullptr];
- if ([native_view_ conformsToProtocol:@protocol(AccessibilityHostable)]) {
- id hostable = native_view_;
- [hostable setAccessibilityParentElement:nil];
+ if (native_view_hostable_) {
+ native_view_hostable_->OnViewsHostableDetached();
+ native_view_hostable_ = nullptr;
}
EnsureNativeViewHasNoChildWidgets(host_->native_view());
- BridgedNativeWidget* bridge = NativeWidgetMac::GetBridgeForNativeWindow(
- host_->GetWidget()->GetNativeWindow());
- // BridgedNativeWidget can be null when Widget is closing.
- if (bridge)
- bridge->ClearAssociationForView(host_);
+ auto* bridge_host = GetBridgedNativeWidgetHost();
+ // BridgedNativeWidgetImpl can be null when Widget is closing.
+ if (bridge_host)
+ bridge_host->ClearAssociationForView(host_);
native_view_.reset();
}
@@ -191,15 +213,29 @@ void NativeViewHostMac::ShowWidget(int x,
[[host_->native_view() superview] convertRect:window_rect fromView:nil];
[host_->native_view() setFrame:container_rect];
[host_->native_view() setHidden:NO];
+
+ if (native_view_hostable_)
+ native_view_hostable_->OnViewsHostableShow(gfx::Rect(x, y, w, h));
}
void NativeViewHostMac::HideWidget() {
[host_->native_view() setHidden:YES];
+
+ if (native_view_hostable_)
+ native_view_hostable_->OnViewsHostableHide();
}
void NativeViewHostMac::SetFocus() {
if ([host_->native_view() acceptsFirstResponder])
[[host_->native_view() window] makeFirstResponder:host_->native_view()];
+
+ if (native_view_hostable_)
+ native_view_hostable_->OnViewsHostableMakeFirstResponder();
+}
+
+gfx::NativeView NativeViewHostMac::GetNativeViewContainer() const {
+ NOTIMPLEMENTED();
+ return nullptr;
}
gfx::NativeViewAccessible NativeViewHostMac::GetNativeViewAccessible() {
diff --git a/chromium/ui/views/controls/native/native_view_host_mac_unittest.mm b/chromium/ui/views/controls/native/native_view_host_mac_unittest.mm
index 4a4fdcad1b1..85373e5b977 100644
--- a/chromium/ui/views/controls/native/native_view_host_mac_unittest.mm
+++ b/chromium/ui/views/controls/native/native_view_host_mac_unittest.mm
@@ -12,17 +12,38 @@
#import "base/mac/scoped_nsobject.h"
#include "base/macros.h"
#import "testing/gtest_mac.h"
-#import "ui/base/cocoa/accessibility_hostable.h"
+#import "ui/base/cocoa/views_hostable.h"
#include "ui/views/controls/native/native_view_host.h"
#include "ui/views/controls/native/native_view_host_test_base.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
-@interface TestAccessibilityHostableView : NSView<AccessibilityHostable>
-@property(nonatomic, assign) id accessibilityParentElement;
+class TestViewsHostable : public ui::ViewsHostableView {
+ public:
+ id parent_accessibility_element() const {
+ return parent_accessibility_element_;
+ }
+
+ private:
+ // ui::ViewsHostableView:
+ void OnViewsHostableAttached(ui::ViewsHostableView::Host* host) override {
+ parent_accessibility_element_ = host->GetAccessibilityElement();
+ }
+ void OnViewsHostableDetached() override {
+ parent_accessibility_element_ = nil;
+ }
+ void OnViewsHostableShow(const gfx::Rect& bounds_in_window) override {}
+ void OnViewsHostableHide() override {}
+ void OnViewsHostableMakeFirstResponder() override {}
+
+ id parent_accessibility_element_ = nil;
+};
+
+@interface TestViewsHostableView : NSView<ViewsHostable>
+@property(nonatomic, assign) ui::ViewsHostableView* viewsHostableView;
@end
-@implementation TestAccessibilityHostableView
-@synthesize accessibilityParentElement = accessibilityParentElement_;
+@implementation TestViewsHostableView
+@synthesize viewsHostableView = viewsHostableView_;
@end
namespace views {
@@ -115,15 +136,18 @@ TEST_F(NativeViewHostMacTest, AccessibilityParent) {
CreateHost();
host()->Detach();
- base::scoped_nsobject<TestAccessibilityHostableView> view(
- [[TestAccessibilityHostableView alloc] init]);
+ base::scoped_nsobject<TestViewsHostableView> view(
+ [[TestViewsHostableView alloc] init]);
+ TestViewsHostable views_hostable;
+ [view setViewsHostableView:&views_hostable];
+
host()->Attach(view);
- EXPECT_NSEQ([view accessibilityParentElement],
+ EXPECT_NSEQ(views_hostable.parent_accessibility_element(),
toplevel()->GetRootView()->GetNativeViewAccessible());
host()->Detach();
DestroyHost();
- EXPECT_FALSE([view accessibilityParentElement]);
+ EXPECT_FALSE(views_hostable.parent_accessibility_element());
}
// Test that the content windows' bounds are set to the correct values while the
diff --git a/chromium/ui/views/controls/native/native_view_host_wrapper.h b/chromium/ui/views/controls/native/native_view_host_wrapper.h
index 513c35f1a71..07cf9f1fea0 100644
--- a/chromium/ui/views/controls/native/native_view_host_wrapper.h
+++ b/chromium/ui/views/controls/native/native_view_host_wrapper.h
@@ -78,6 +78,10 @@ class NativeViewHostWrapper {
// Sets focus to the gfx::NativeView.
virtual void SetFocus() = 0;
+ // Returns the container that contains the NativeViewHost's native view if
+ // any.
+ virtual gfx::NativeView GetNativeViewContainer() const = 0;
+
// Return the native view accessible corresponding to the wrapped native
// view.
virtual gfx::NativeViewAccessible GetNativeViewAccessible() = 0;
diff --git a/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.h b/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.h
index a0c88726dab..c69087a9382 100644
--- a/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.h
+++ b/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.h
@@ -5,13 +5,13 @@
#ifndef UI_VIEWS_CONTROLS_SCROLLBAR_COCOA_SCROLL_BAR_H_
#define UI_VIEWS_CONTROLS_SCROLLBAR_COCOA_SCROLL_BAR_H_
-#include "base/macros.h"
#import "base/mac/scoped_nsobject.h"
+#include "base/macros.h"
#include "ui/compositor/layer_animation_observer.h"
#include "ui/gfx/animation/slide_animation.h"
-#import "ui/views/cocoa/views_scrollbar_bridge.h"
#include "ui/views/controls/scrollbar/base_scroll_bar.h"
#include "ui/views/views_export.h"
+#import "ui/views_bridge_mac/views_scrollbar_bridge.h"
namespace views {
diff --git a/chromium/ui/views/controls/styled_label.cc b/chromium/ui/views/controls/styled_label.cc
index 2c12e6e77ef..9e4477f7636 100644
--- a/chromium/ui/views/controls/styled_label.cc
+++ b/chromium/ui/views/controls/styled_label.cc
@@ -28,13 +28,6 @@ namespace views {
namespace {
-gfx::Insets FocusBorderInsets(const Label& label) {
- // StyledLabel never adds a border, so the only Insets added are for the
- // possible focus ring.
- DCHECK(label.View::GetInsets().IsEmpty());
- return label.GetInsets();
-}
-
std::unique_ptr<Label> CreateLabelRange(
const base::string16& text,
int text_context,
@@ -216,24 +209,6 @@ const char* StyledLabel::GetClassName() const {
return kViewClassName;
}
-gfx::Insets StyledLabel::GetInsets() const {
- gfx::Insets insets = View::GetInsets();
- if (Link::GetDefaultFocusStyle() != Link::FocusStyle::RING)
- return insets;
-
- // We need a focus border iff we contain a link that will have a focus border.
- // That in turn will be true only if the link is non-empty.
- for (StyleRanges::const_iterator i(style_ranges_.begin());
- i != style_ranges_.end(); ++i) {
- if (i->style_info.IsLink() && !i->range.is_empty()) {
- insets += gfx::Insets(Link::kFocusBorderPadding);
- break;
- }
- }
-
- return insets;
-}
-
void StyledLabel::GetAccessibleNodeData(ui::AXNodeData* node_data) {
if (text_context_ == style::CONTEXT_DIALOG_TITLE)
node_data->role = ax::mojom::Role::kTitleBar;
@@ -488,26 +463,18 @@ gfx::Size StyledLabel::CalculateAndDoLayout(int width, bool dry_run) {
gfx::Size view_size = child_view->GetPreferredSize();
// |offset.y()| already contains |insets.top()|.
gfx::Point view_origin(insets.left() + offset.x(), offset.y());
- gfx::Insets focus_border_insets;
- if (Link::GetDefaultFocusStyle() == Link::FocusStyle::RING && label) {
- // Calculate the size of the optional focus border, and overlap by that
- // amount. Otherwise, "<a>link</a>," will render as "link ,".
- focus_border_insets = FocusBorderInsets(*label);
- }
- view_origin.Offset(-focus_border_insets.left(), -focus_border_insets.top());
// The custom view could be wider than the available width; clamp as needed.
- if (custom_view) {
- view_size.set_width(std::min(
- view_size.width(), width - offset.x() + focus_border_insets.width()));
- }
+ if (custom_view)
+ view_size.set_width(std::min(view_size.width(), width - offset.x()));
+
child_view->SetBoundsRect(gfx::Rect(view_origin, view_size));
- offset.set_x(offset.x() + view_size.width() - focus_border_insets.width());
+ offset.set_x(offset.x() + view_size.width());
total_height =
- std::max(total_height, child_view->bounds().bottom() + insets.bottom() -
- focus_border_insets.bottom());
+ std::max(total_height, std::max(child_view->bounds().bottom(),
+ offset.y() + default_line_height) +
+ insets.bottom());
used_width = std::max(used_width, offset.x());
- max_line_height = std::max(
- max_line_height, view_size.height() - focus_border_insets.height());
+ max_line_height = std::max(max_line_height, view_size.height());
if (!dry_run) {
views_in_a_line.push_back(child_view);
diff --git a/chromium/ui/views/controls/styled_label.h b/chromium/ui/views/controls/styled_label.h
index 43544ef691b..110007b1838 100644
--- a/chromium/ui/views/controls/styled_label.h
+++ b/chromium/ui/views/controls/styled_label.h
@@ -140,7 +140,6 @@ class VIEWS_EXPORT StyledLabel : public View, public LinkListener {
// View:
const char* GetClassName() const override;
- gfx::Insets GetInsets() const override;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
gfx::Size CalculatePreferredSize() const override;
int GetHeightForWidth(int w) const override;
diff --git a/chromium/ui/views/controls/styled_label_unittest.cc b/chromium/ui/views/controls/styled_label_unittest.cc
index e79fadddb32..1d218215e66 100644
--- a/chromium/ui/views/controls/styled_label_unittest.cc
+++ b/chromium/ui/views/controls/styled_label_unittest.cc
@@ -513,13 +513,32 @@ TEST_F(StyledLabelTest, SetTextContextAndDefaultStyle) {
}
TEST_F(StyledLabelTest, LineHeight) {
- const std::string text("one");
+ const std::string text("one\ntwo\nthree");
+ InitStyledLabel(text);
+ styled()->SetLineHeight(18);
+ EXPECT_EQ(18 * 3, styled()->GetHeightForWidth(100));
+}
+
+TEST_F(StyledLabelTest, LineHeightWithBorder) {
+ const std::string text("one\ntwo\nthree");
+ InitStyledLabel(text);
+ styled()->SetLineHeight(18);
+ styled()->SetBorder(views::CreateSolidBorder(1, SK_ColorGRAY));
+ EXPECT_EQ(18 * 3 + 2, styled()->GetHeightForWidth(100));
+}
+
+TEST_F(StyledLabelTest, LineHeightWithLink) {
+ const std::string text("one\ntwo\nthree");
InitStyledLabel(text);
- int default_height = styled()->GetHeightForWidth(100);
- const std::string newline_text("one\ntwo\nthree");
- InitStyledLabel(newline_text);
styled()->SetLineHeight(18);
- EXPECT_EQ(18 * 2 + default_height, styled()->GetHeightForWidth(100));
+
+ styled()->AddStyleRange(gfx::Range(0, 3),
+ StyledLabel::RangeStyleInfo::CreateForLink());
+ styled()->AddStyleRange(gfx::Range(4, 7),
+ StyledLabel::RangeStyleInfo::CreateForLink());
+ styled()->AddStyleRange(gfx::Range(8, 13),
+ StyledLabel::RangeStyleInfo::CreateForLink());
+ EXPECT_EQ(18 * 3, styled()->GetHeightForWidth(100));
}
TEST_F(StyledLabelTest, HandleEmptyLayout) {
diff --git a/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc b/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc
index 04e572c25d0..96309bc1709 100644
--- a/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc
+++ b/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc
@@ -407,7 +407,7 @@ TabStrip::TabStrip(TabbedPane::Orientation orientation,
layout->set_cross_axis_alignment(BoxLayout::CROSS_AXIS_ALIGNMENT_END);
} else {
const int kTabStripEdgePadding = 8;
- const int kTabSpacing = 16;
+ const int kTabSpacing = 8;
layout = std::make_unique<BoxLayout>(
BoxLayout::kVertical, gfx::Insets(kTabStripEdgePadding, 0, 0, 0),
kTabSpacing);
diff --git a/chromium/ui/views/controls/textfield/textfield.cc b/chromium/ui/views/controls/textfield/textfield.cc
index 752c642e2da..2ff60335add 100644
--- a/chromium/ui/views/controls/textfield/textfield.cc
+++ b/chromium/ui/views/controls/textfield/textfield.cc
@@ -19,6 +19,7 @@
#include "ui/base/cursor/cursor.h"
#include "ui/base/default_style.h"
#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/base/ime/constants.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/text_edit_commands.h"
#include "ui/base/resource/resource_bundle.h"
@@ -73,6 +74,7 @@
#endif
#if defined(OS_MACOSX)
+#include "ui/base/cocoa/defaults_utils.h"
#include "ui/base/cocoa/secure_password_input.h"
#endif
@@ -149,6 +151,14 @@ ui::TextEditCommand GetCommandForKeyEvent(const ui::KeyEvent& event) {
return shift
? ui::TextEditCommand::MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION
: ui::TextEditCommand::MOVE_TO_END_OF_LINE;
+ case ui::VKEY_UP:
+ return shift ? ui::TextEditCommand::
+ MOVE_TO_BEGINNING_OF_LINE_AND_MODIFY_SELECTION
+ : ui::TextEditCommand::INVALID_COMMAND;
+ case ui::VKEY_DOWN:
+ return shift
+ ? ui::TextEditCommand::MOVE_TO_END_OF_LINE_AND_MODIFY_SELECTION
+ : ui::TextEditCommand::INVALID_COMMAND;
case ui::VKEY_BACK:
if (!control)
return ui::TextEditCommand::DELETE_BACKWARD;
@@ -203,11 +213,14 @@ ui::TextEditCommand GetTextEditCommandFromMenuCommand(int command_id,
return ui::TextEditCommand::INVALID_COMMAND;
}
-base::TimeDelta GetPasswordRevealDuration() {
- return ViewsDelegate::GetInstance()
- ? ViewsDelegate::GetInstance()
- ->GetTextfieldPasswordRevealDuration()
- : base::TimeDelta();
+base::TimeDelta GetPasswordRevealDuration(const ui::KeyEvent& event) {
+ // The key event may carries the property that indicates it was from the
+ // virtual keyboard.
+ // In that case, reveals the password characters for 1 second.
+ auto* properties = event.properties();
+ bool from_vk =
+ properties && properties->find(ui::kPropertyFromVK) != properties->end();
+ return from_vk ? base::TimeDelta::FromSeconds(1) : base::TimeDelta();
}
bool IsControlKeyModifier(int flags) {
@@ -229,8 +242,6 @@ const char Textfield::kViewClassName[] = "Textfield";
// static
base::TimeDelta Textfield::GetCaretBlinkInterval() {
- static constexpr base::TimeDelta default_value =
- base::TimeDelta::FromMilliseconds(500);
#if defined(OS_WIN)
static const size_t system_value = ::GetCaretBlinkTime();
if (system_value != 0) {
@@ -238,8 +249,12 @@ base::TimeDelta Textfield::GetCaretBlinkInterval() {
? base::TimeDelta()
: base::TimeDelta::FromMilliseconds(system_value);
}
+#elif defined(OS_MACOSX)
+ base::TimeDelta system_value;
+ if (ui::TextInsertionCaretBlinkPeriod(&system_value))
+ return system_value;
#endif
- return default_value;
+ return base::TimeDelta::FromMilliseconds(500);
}
// static
@@ -1398,17 +1413,9 @@ bool Textfield::GetAcceleratorForCommandId(int command_id,
*accelerator = ui::Accelerator(ui::VKEY_A, ui::EF_PLATFORM_ACCELERATOR);
return true;
- case IDS_CONTENT_CONTEXT_EMOJI:
-#if defined(OS_MACOSX)
- *accelerator = ui::Accelerator(ui::VKEY_SPACE,
- ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN);
- return true;
-#else
- return false;
-#endif
-
default:
- return false;
+ return text_services_context_menu_->GetAcceleratorForCommandId(
+ command_id, accelerator);
}
}
@@ -1495,11 +1502,14 @@ void Textfield::InsertChar(const ui::KeyEvent& event) {
DoInsertChar(ch);
- if (text_input_type_ == ui::TEXT_INPUT_TYPE_PASSWORD &&
- !GetPasswordRevealDuration().is_zero()) {
- const size_t change_offset = model_->GetCursorPosition();
- DCHECK_GT(change_offset, 0u);
- RevealPasswordChar(change_offset - 1);
+ if (text_input_type_ == ui::TEXT_INPUT_TYPE_PASSWORD) {
+ password_char_reveal_index_ = -1;
+ base::TimeDelta duration = GetPasswordRevealDuration(event);
+ if (!duration.is_zero()) {
+ const size_t change_offset = model_->GetCursorPosition();
+ DCHECK_GT(change_offset, 0u);
+ RevealPasswordChar(change_offset - 1, duration);
+ }
}
}
@@ -2287,15 +2297,16 @@ bool Textfield::ImeEditingAllowed() const {
return (t != ui::TEXT_INPUT_TYPE_NONE && t != ui::TEXT_INPUT_TYPE_PASSWORD);
}
-void Textfield::RevealPasswordChar(int index) {
+void Textfield::RevealPasswordChar(int index, base::TimeDelta duration) {
GetRenderText()->SetObscuredRevealIndex(index);
SchedulePaint();
+ password_char_reveal_index_ = index;
if (index != -1) {
password_reveal_timer_.Start(
- FROM_HERE, GetPasswordRevealDuration(),
+ FROM_HERE, duration,
base::Bind(&Textfield::RevealPasswordChar,
- weak_ptr_factory_.GetWeakPtr(), -1));
+ weak_ptr_factory_.GetWeakPtr(), -1, duration));
}
}
diff --git a/chromium/ui/views/controls/textfield/textfield.h b/chromium/ui/views/controls/textfield/textfield.h
index 314bde9feff..4d20d983432 100644
--- a/chromium/ui/views/controls/textfield/textfield.h
+++ b/chromium/ui/views/controls/textfield/textfield.h
@@ -244,6 +244,8 @@ class VIEWS_EXPORT Textfield : public View,
// Set extra spacing placed between glyphs; used for obscured text styling.
void SetGlyphSpacing(int spacing);
+ int GetPasswordCharRevealIndex() const { return password_char_reveal_index_; }
+
// View overrides:
int GetBaseline() const override;
gfx::Size CalculatePreferredSize() const override;
@@ -470,7 +472,8 @@ class VIEWS_EXPORT Textfield : public View,
// Reveals the password character at |index| for a set duration.
// If |index| is -1, the existing revealed character will be reset.
- void RevealPasswordChar(int index);
+ // |duration| is the time to remain the password char to be visible.
+ void RevealPasswordChar(int index, base::TimeDelta duration);
void CreateTouchSelectionControllerAndNotifyIt();
@@ -628,6 +631,9 @@ class VIEWS_EXPORT Textfield : public View,
// The focus ring for this TextField.
std::unique_ptr<FocusRing> focus_ring_;
+ // The password char reveal index, for testing only.
+ int password_char_reveal_index_ = -1;
+
// Used to bind callback functions to this object.
base::WeakPtrFactory<Textfield> weak_ptr_factory_;
diff --git a/chromium/ui/views/controls/textfield/textfield_model.cc b/chromium/ui/views/controls/textfield/textfield_model.cc
index 4d77de34ffc..1bfea07108c 100644
--- a/chromium/ui/views/controls/textfield/textfield_model.cc
+++ b/chromium/ui/views/controls/textfield/textfield_model.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/message_loop/message_loop.h"
+#include "base/no_destructor.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/base/clipboard/clipboard.h"
@@ -268,9 +269,9 @@ gfx::Range GetFirstEmphasizedRange(const ui::CompositionText& composition) {
// NSTextKillRingSize, a text system default. However to keep things simple,
// the default kill ring size of 1 (i.e. a single buffer) is assumed.
base::string16* GetKillBuffer() {
- CR_DEFINE_STATIC_LOCAL(base::string16, kill_buffer, ());
+ static base::NoDestructor<base::string16> kill_buffer;
DCHECK(base::MessageLoopForUI::IsCurrent());
- return &kill_buffer;
+ return kill_buffer.get();
}
// Helper method to set the kill buffer.
@@ -486,7 +487,7 @@ bool TextfieldModel::CanRedo() {
if (edit_history_.empty())
return false;
// There is no redo iff the current edit is the last element in the history.
- EditHistory::iterator iter = current_edit_;
+ auto iter = current_edit_;
return iter == edit_history_.end() || // at the top.
++iter != edit_history_.end();
}
@@ -760,7 +761,7 @@ void TextfieldModel::ClearRedoHistory() {
ClearEditHistory();
return;
}
- EditHistory::iterator delete_start = current_edit_;
+ auto delete_start = current_edit_;
++delete_start;
edit_history_.erase(delete_start, edit_history_.end());
}
diff --git a/chromium/ui/views/controls/textfield/textfield_unittest.cc b/chromium/ui/views/controls/textfield/textfield_unittest.cc
index f8a8292c501..be57d658a24 100644
--- a/chromium/ui/views/controls/textfield/textfield_unittest.cc
+++ b/chromium/ui/views/controls/textfield/textfield_unittest.cc
@@ -11,6 +11,7 @@
#include <string>
#include <vector>
+#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/format_macros.h"
#include "base/i18n/rtl.h"
@@ -27,6 +28,7 @@
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/dragdrop/drag_drop_types.h"
#include "ui/base/emoji/emoji_panel_helper.h"
+#include "ui/base/ime/constants.h"
#include "ui/base/ime/input_method_base.h"
#include "ui/base/ime/input_method_delegate.h"
#include "ui/base/ime/input_method_factory.h"
@@ -157,7 +159,7 @@ ui::EventDispatchDetails MockInputMethod::DispatchKeyEvent(ui::KeyEvent* key) {
// which trigger the appropriate NSResponder action messages for composition.
#if defined(OS_MACOSX)
if (key->is_char())
- return DispatchKeyEventPostIME(key);
+ return DispatchKeyEventPostIME(key, base::NullCallback());
#endif
// Checks whether the key event is from EventGenerator on Windows which will
@@ -177,9 +179,9 @@ ui::EventDispatchDetails MockInputMethod::DispatchKeyEvent(ui::KeyEvent* key) {
ui::KeyEvent mock_key(ui::ET_KEY_PRESSED,
ui::VKEY_PROCESSKEY,
key->flags());
- dispatch_details = DispatchKeyEventPostIME(&mock_key);
+ dispatch_details = DispatchKeyEventPostIME(&mock_key, base::NullCallback());
} else {
- dispatch_details = DispatchKeyEventPostIME(key);
+ dispatch_details = DispatchKeyEventPostIME(key, base::NullCallback());
}
if (key->handled() || dispatch_details.dispatcher_destroyed)
@@ -553,9 +555,13 @@ class TextfieldTest : public ViewsTestBase, public TextfieldController {
SendKeyEvent(key_code, false, false);
}
- void SendKeyEvent(base::char16 ch) { SendKeyEvent(ch, ui::EF_NONE); }
+ void SendKeyEvent(base::char16 ch) { SendKeyEvent(ch, ui::EF_NONE, false); }
void SendKeyEvent(base::char16 ch, int flags) {
+ SendKeyEvent(ch, flags, false);
+ }
+
+ void SendKeyEvent(base::char16 ch, int flags, bool from_vk) {
if (ch < 0x80) {
ui::KeyboardCode code =
ch == ' ' ? ui::VKEY_SPACE :
@@ -567,6 +573,11 @@ class TextfieldTest : public ViewsTestBase, public TextfieldController {
// Mac, key events don't pass through InputMethod. Hence they are
// dispatched regularly.
ui::KeyEvent event(ch, ui::VKEY_UNKNOWN, ui::DomCode::NONE, flags);
+ if (from_vk) {
+ ui::Event::Properties properties;
+ properties[ui::kPropertyFromVK] = std::vector<uint8_t>();
+ event.SetProperties(properties);
+ }
#if defined(OS_MACOSX)
event_generator_->Dispatch(&event);
#else
@@ -1056,27 +1067,18 @@ TEST_F(TextfieldTest, MoveUpDownAndModifySelection) {
textfield_->SetSelectionRange(gfx::Range(6));
- // Shift+[Up/Down] on Mac should execute the command
- // MOVE_[UP/DOWN]_AND_MODIFY_SELECTION. On other platforms, textfield won't
- // handle these events.
+ // Shift+[Up/Down] should select the text to the beginning and end of the
+ // line, respectively.
SendKeyEvent(ui::VKEY_UP, true /* shift */, false /* command */);
EXPECT_TRUE(textfield_->key_received());
-#if defined(OS_MACOSX)
EXPECT_TRUE(textfield_->key_handled());
EXPECT_EQ(gfx::Range(6, 0), textfield_->GetSelectedRange());
-#else
- EXPECT_FALSE(textfield_->key_handled());
-#endif
textfield_->clear();
SendKeyEvent(ui::VKEY_DOWN, true /* shift */, false /* command */);
EXPECT_TRUE(textfield_->key_received());
-#if defined(OS_MACOSX)
EXPECT_TRUE(textfield_->key_handled());
EXPECT_EQ(gfx::Range(6, 11), textfield_->GetSelectedRange());
-#else
- EXPECT_FALSE(textfield_->key_handled());
-#endif
textfield_->clear();
}
@@ -1292,8 +1294,15 @@ TEST_F(TextfieldTest, TextInputType_InsertionTest) {
EXPECT_EQ(ui::TEXT_INPUT_TYPE_PASSWORD, textfield_->GetTextInputType());
SendKeyEvent(ui::VKEY_A);
- SendKeyEvent(kHebrewLetterSamekh);
+ EXPECT_EQ(-1, textfield_->GetPasswordCharRevealIndex());
+ SendKeyEvent(kHebrewLetterSamekh, ui::EF_NONE, true /* from_vk */);
+#if !defined(OS_MACOSX)
+ // Don't verifies the password character reveal on MacOS, because on MacOS,
+ // the text insertion is not done through TextInputClient::InsertChar().
+ EXPECT_EQ(1, textfield_->GetPasswordCharRevealIndex());
+#endif
SendKeyEvent(ui::VKEY_B);
+ EXPECT_EQ(-1, textfield_->GetPasswordCharRevealIndex());
EXPECT_EQ(WideToUTF16(L"a\x05E1"
L"b"),
diff --git a/chromium/ui/views/controls/views_text_services_context_menu.h b/chromium/ui/views/controls/views_text_services_context_menu.h
index bf411354261..726f6e37146 100644
--- a/chromium/ui/views/controls/views_text_services_context_menu.h
+++ b/chromium/ui/views/controls/views_text_services_context_menu.h
@@ -8,6 +8,7 @@
#include <memory>
#include "base/i18n/rtl.h"
+#include "ui/base/accelerators/accelerator.h"
#include "ui/views/views_export.h"
namespace ui {
@@ -20,10 +21,8 @@ class Textfield;
// This class is used to add and handle text service items in the text context
// menu.
-class ViewsTextServicesContextMenu {
+class ViewsTextServicesContextMenu : public ui::AcceleratorProvider {
public:
- virtual ~ViewsTextServicesContextMenu() {}
-
// Creates a platform-specific ViewsTextServicesContextMenu object.
static std::unique_ptr<ViewsTextServicesContextMenu> Create(
ui::SimpleMenuModel* menu,
diff --git a/chromium/ui/views/controls/views_text_services_context_menu_base.cc b/chromium/ui/views/controls/views_text_services_context_menu_base.cc
index eae69906422..89858fbb099 100644
--- a/chromium/ui/views/controls/views_text_services_context_menu_base.cc
+++ b/chromium/ui/views/controls/views_text_services_context_menu_base.cc
@@ -5,17 +5,28 @@
#include "ui/views/controls/views_text_services_context_menu_base.h"
#include "base/metrics/histogram_macros.h"
+#include "build/build_config.h"
+#include "ui/base/accelerators/accelerator.h"
#include "ui/base/emoji/emoji_panel_helper.h"
#include "ui/base/models/simple_menu_model.h"
+#include "ui/events/event.h"
+#include "ui/events/event_constants.h"
#include "ui/resources/grit/ui_resources.h"
#include "ui/strings/grit/ui_strings.h"
#include "ui/views/controls/textfield/textfield.h"
namespace views {
+namespace {
+
const char kViewsTextServicesContextMenuHistogram[] =
"ViewsTextServicesContextMenu.Used";
+// Do not change the values in this enum as they are used by UMA.
+enum class Command { kEmoji = 0, kMaxValue = kEmoji };
+
+} // namespace
+
ViewsTextServicesContextMenuBase::ViewsTextServicesContextMenuBase(
ui::SimpleMenuModel* menu,
Textfield* client)
@@ -25,7 +36,7 @@ ViewsTextServicesContextMenuBase::ViewsTextServicesContextMenuBase(
// Not inserted on read-only fields or if the OS/version doesn't support it.
if (!client_->read_only() && ui::IsEmojiPanelSupported()) {
menu->InsertSeparatorAt(0, ui::NORMAL_SEPARATOR);
- menu->InsertItemWithStringIdAt(0, static_cast<int>(Command::kEmoji),
+ menu->InsertItemWithStringIdAt(0, IDS_CONTENT_CONTEXT_EMOJI,
IDS_CONTENT_CONTEXT_EMOJI);
}
}
@@ -33,7 +44,27 @@ ViewsTextServicesContextMenuBase::ViewsTextServicesContextMenuBase(
ViewsTextServicesContextMenuBase::~ViewsTextServicesContextMenuBase() {}
bool ViewsTextServicesContextMenuBase::SupportsCommand(int command_id) const {
- return command_id == static_cast<int>(Command::kEmoji);
+ return command_id == IDS_CONTENT_CONTEXT_EMOJI;
+}
+
+bool ViewsTextServicesContextMenuBase::GetAcceleratorForCommandId(
+ int command_id,
+ ui::Accelerator* accelerator) const {
+ if (command_id == IDS_CONTENT_CONTEXT_EMOJI) {
+#if defined(OS_WIN)
+ *accelerator = ui::Accelerator(ui::VKEY_OEM_PERIOD, ui::EF_COMMAND_DOWN);
+ return true;
+#elif defined(OS_MACOSX)
+ *accelerator = ui::Accelerator(ui::VKEY_SPACE,
+ ui::EF_COMMAND_DOWN | ui::EF_CONTROL_DOWN);
+ return true;
+#else
+ // TODO(crbug.com/887660): Add accelerator key for Chrome OS.
+ return false;
+#endif
+ }
+
+ return false;
}
bool ViewsTextServicesContextMenuBase::IsCommandIdChecked(
@@ -43,14 +74,14 @@ bool ViewsTextServicesContextMenuBase::IsCommandIdChecked(
bool ViewsTextServicesContextMenuBase::IsCommandIdEnabled(
int command_id) const {
- if (command_id == static_cast<int>(Command::kEmoji))
+ if (command_id == IDS_CONTENT_CONTEXT_EMOJI)
return true;
return false;
}
void ViewsTextServicesContextMenuBase::ExecuteCommand(int command_id) {
- if (command_id == static_cast<int>(Command::kEmoji)) {
+ if (command_id == IDS_CONTENT_CONTEXT_EMOJI) {
ui::ShowEmojiPanel();
UMA_HISTOGRAM_ENUMERATION(kViewsTextServicesContextMenuHistogram,
Command::kEmoji);
diff --git a/chromium/ui/views/controls/views_text_services_context_menu_base.h b/chromium/ui/views/controls/views_text_services_context_menu_base.h
index 08e5a7ad0c0..bbc3e19d206 100644
--- a/chromium/ui/views/controls/views_text_services_context_menu_base.h
+++ b/chromium/ui/views/controls/views_text_services_context_menu_base.h
@@ -21,6 +21,10 @@ class ViewsTextServicesContextMenuBase : public ViewsTextServicesContextMenu {
// Returns true if the given |command_id| is handled by the menu.
bool SupportsCommand(int command_id) const override;
+ // ui::AcceleratorProvider:
+ bool GetAcceleratorForCommandId(int command_id,
+ ui::Accelerator* accelerator) const override;
+
// Methods associated with SimpleMenuModel::Delegate.
bool IsCommandIdChecked(int command_id) const override;
bool IsCommandIdEnabled(int command_id) const override;
@@ -30,9 +34,6 @@ class ViewsTextServicesContextMenuBase : public ViewsTextServicesContextMenu {
Textfield* client() const { return client_; }
private:
- // Do not change the values in this enum as they are used by UMA.
- enum class Command { kEmoji = 0, kMaxValue = kEmoji };
-
// The view associated with the menu. Weak. Owns |this|.
Textfield* client_ = nullptr;
diff --git a/chromium/ui/views/controls/webview/unhandled_keyboard_event_handler_mac.mm b/chromium/ui/views/controls/webview/unhandled_keyboard_event_handler_mac.mm
index ece41dd5f53..e87f913ff61 100644
--- a/chromium/ui/views/controls/webview/unhandled_keyboard_event_handler_mac.mm
+++ b/chromium/ui/views/controls/webview/unhandled_keyboard_event_handler_mac.mm
@@ -5,7 +5,7 @@
#include "ui/views/controls/webview/unhandled_keyboard_event_handler.h"
#import "base/mac/foundation_util.h"
-#import "ui/views/cocoa/native_widget_mac_nswindow.h"
+#import "ui/views_bridge_mac/native_widget_mac_nswindow.h"
namespace views {
diff --git a/chromium/ui/views/controls/webview/web_dialog_view.cc b/chromium/ui/views/controls/webview/web_dialog_view.cc
index 90a9612cf61..56fc98b2840 100644
--- a/chromium/ui/views/controls/webview/web_dialog_view.cc
+++ b/chromium/ui/views/controls/webview/web_dialog_view.cc
@@ -116,7 +116,7 @@ bool WebDialogView::CanClose() {
if (!is_attempting_close_dialog_) {
// Fire beforeunload event when user attempts to close the dialog.
is_attempting_close_dialog_ = true;
- web_view_->web_contents()->DispatchBeforeUnload();
+ web_view_->web_contents()->DispatchBeforeUnload(false /* auto_cancel */);
}
return false;
}
@@ -140,6 +140,12 @@ base::string16 WebDialogView::GetWindowTitle() const {
return base::string16();
}
+base::string16 WebDialogView::GetAccessibleWindowTitle() const {
+ if (delegate_)
+ return delegate_->GetAccessibleDialogTitle();
+ return GetWindowTitle();
+}
+
std::string WebDialogView::GetWindowName() const {
if (delegate_)
return delegate_->GetDialogName();
diff --git a/chromium/ui/views/controls/webview/web_dialog_view.h b/chromium/ui/views/controls/webview/web_dialog_view.h
index 0fd7bc03288..29d18cb2e1f 100644
--- a/chromium/ui/views/controls/webview/web_dialog_view.h
+++ b/chromium/ui/views/controls/webview/web_dialog_view.h
@@ -66,6 +66,7 @@ class WEBVIEW_EXPORT WebDialogView : public views::ClientView,
bool CanResize() const override;
ui::ModalType GetModalType() const override;
base::string16 GetWindowTitle() const override;
+ base::string16 GetAccessibleWindowTitle() const override;
std::string GetWindowName() const override;
void WindowClosing() override;
views::View* GetContentsView() override;
diff --git a/chromium/ui/views/controls/webview/webview.cc b/chromium/ui/views/controls/webview/webview.cc
index 74ddbc9b3a4..2a4cc7e8938 100644
--- a/chromium/ui/views/controls/webview/webview.cc
+++ b/chromium/ui/views/controls/webview/webview.cc
@@ -149,18 +149,6 @@ const char* WebView::GetClassName() const {
return kViewClassName;
}
-std::unique_ptr<content::WebContents> WebView::SwapWebContents(
- std::unique_ptr<content::WebContents> new_web_contents) {
- if (wc_owner_)
- wc_owner_->SetDelegate(NULL);
- std::unique_ptr<content::WebContents> old_web_contents(std::move(wc_owner_));
- wc_owner_ = std::move(new_web_contents);
- if (wc_owner_)
- wc_owner_->SetDelegate(this);
- SetWebContents(wc_owner_.get());
- return old_web_contents;
-}
-
void WebView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
if (crashed_overlay_view_)
crashed_overlay_view_->SetBoundsRect(gfx::Rect(size()));
@@ -258,6 +246,10 @@ void WebView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
// provided via other means. Providing it here would be redundant.
// Mark the name as explicitly empty so that accessibility_checks pass.
node_data->SetNameExplicitlyEmpty();
+ if (child_ax_tree_id_ != ui::AXTreeIDUnknown()) {
+ node_data->AddStringAttribute(ax::mojom::StringAttribute::kChildTreeId,
+ child_ax_tree_id_);
+ }
}
gfx::NativeViewAccessible WebView::GetNativeViewAccessible() {
@@ -415,8 +407,13 @@ void WebView::UpdateCrashedOverlayView() {
}
void WebView::NotifyAccessibilityWebContentsChanged() {
- if (web_contents())
- NotifyAccessibilityEvent(ax::mojom::Event::kChildrenChanged, false);
+ content::RenderFrameHost* rfh =
+ web_contents() ? web_contents()->GetMainFrame() : nullptr;
+ if (rfh)
+ child_ax_tree_id_ = rfh->GetAXTreeID();
+ else
+ child_ax_tree_id_ = ui::AXTreeIDUnknown();
+ NotifyAccessibilityEvent(ax::mojom::Event::kChildrenChanged, false);
}
std::unique_ptr<content::WebContents> WebView::CreateWebContents(
diff --git a/chromium/ui/views/controls/webview/webview.h b/chromium/ui/views/controls/webview/webview.h
index 994520b83b1..2a4b4937c16 100644
--- a/chromium/ui/views/controls/webview/webview.h
+++ b/chromium/ui/views/controls/webview/webview.h
@@ -120,11 +120,6 @@ class WEBVIEW_EXPORT WebView : public View,
};
protected:
- // Swaps the owned WebContents |wc_owner_| with |new_web_contents|. Returns
- // the previously owned WebContents.
- std::unique_ptr<content::WebContents> SwapWebContents(
- std::unique_ptr<content::WebContents> new_web_contents);
-
// Called when the web contents is successfully attached.
virtual void OnWebContentsAttached() {}
// Called when letterboxing (scaling the native view to preserve aspect
@@ -211,6 +206,10 @@ class WEBVIEW_EXPORT WebView : public View,
gfx::Size min_size_;
gfx::Size max_size_;
+ // Tracks the child accessibility tree id which is associated with the
+ // WebContents's main RenderFrameHost.
+ ui::AXTreeID child_ax_tree_id_;
+
DISALLOW_COPY_AND_ASSIGN(WebView);
};
diff --git a/chromium/ui/views/corewm/tooltip_controller.cc b/chromium/ui/views/corewm/tooltip_controller.cc
index 02cd71ac0ad..77d84caccc6 100644
--- a/chromium/ui/views/corewm/tooltip_controller.cc
+++ b/chromium/ui/views/corewm/tooltip_controller.cc
@@ -95,16 +95,14 @@ aura::Window* GetTooltipTarget(const ui::MouseEvent& event,
// If |target| has capture all events go to it, even if the mouse is
// really over another window. Find the real window the mouse is over.
- gfx::Point screen_loc(event.location());
- aura::client::GetScreenPositionClient(event_target->GetRootWindow())->
- ConvertPointToScreen(event_target, &screen_loc);
+ const gfx::Point screen_loc = event.target()->GetScreenLocation(event);
display::Screen* screen = display::Screen::GetScreen();
aura::Window* target = screen->GetWindowAtScreenPoint(screen_loc);
if (!target)
return NULL;
gfx::Point target_loc(screen_loc);
- aura::client::GetScreenPositionClient(target->GetRootWindow())->
- ConvertPointFromScreen(target, &target_loc);
+ aura::client::GetScreenPositionClient(target->GetRootWindow())
+ ->ConvertPointFromScreen(target, &target_loc);
aura::Window* screen_target = target->GetEventHandlerForPoint(target_loc);
if (!IsValidTarget(event_target, screen_target))
return NULL;
diff --git a/chromium/ui/views/corewm/tooltip_controller_unittest.cc b/chromium/ui/views/corewm/tooltip_controller_unittest.cc
index 1212a6f38b1..83519930cee 100644
--- a/chromium/ui/views/corewm/tooltip_controller_unittest.cc
+++ b/chromium/ui/views/corewm/tooltip_controller_unittest.cc
@@ -463,10 +463,8 @@ namespace {
// Returns the index of |window| in its parent's children.
int IndexInParent(const aura::Window* window) {
- aura::Window::Windows::const_iterator i =
- std::find(window->parent()->children().begin(),
- window->parent()->children().end(),
- window);
+ auto i = std::find(window->parent()->children().begin(),
+ window->parent()->children().end(), window);
return i == window->parent()->children().end() ? -1 :
static_cast<int>(i - window->parent()->children().begin());
}
diff --git a/chromium/ui/views/corewm/tooltip_win.cc b/chromium/ui/views/corewm/tooltip_win.cc
index 462365750fb..153d4c47484 100644
--- a/chromium/ui/views/corewm/tooltip_win.cc
+++ b/chromium/ui/views/corewm/tooltip_win.cc
@@ -4,8 +4,6 @@
#include "ui/views/corewm/tooltip_win.h"
-#include <winuser.h>
-
#include "base/debug/stack_trace.h"
#include "base/i18n/rtl.h"
#include "base/logging.h"
@@ -14,11 +12,28 @@
#include "ui/display/screen.h"
#include "ui/display/win/screen_win.h"
#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/platform_font_win.h"
#include "ui/views/corewm/cursor_height_provider_win.h"
namespace views {
namespace corewm {
+namespace {
+
+// Substitute GetWindowFont() from windowsx.h.
+// Do not include windowsx.h as its macros break the views jumbo build.
+HFONT GetWindowFont(HWND hwnd) {
+ return reinterpret_cast<HFONT>(::SendMessage(hwnd, WM_GETFONT, 0, 0));
+}
+
+// Substitute SetWindowFont() from windowsx.h.
+// Do not include windowsx.h as its macros break the views jumbo build.
+void SetWindowFont(HWND hwnd, HFONT hfont, BOOL fRedraw) {
+ ::SendMessage(hwnd, WM_SETFONT, reinterpret_cast<WPARAM>(hfont), fRedraw);
+}
+
+} // namespace
+
TooltipWin::TooltipWin(HWND parent)
: parent_hwnd_(parent),
tooltip_hwnd_(NULL),
@@ -70,7 +85,7 @@ bool TooltipWin::EnsureTooltipWindow() {
return false;
}
- l10n_util::AdjustUIFontForWindow(tooltip_hwnd_);
+ MaybeOverrideFont();
SendMessage(tooltip_hwnd_, TTM_ADDTOOL, 0,
reinterpret_cast<LPARAM>(&toolinfo_));
@@ -96,6 +111,33 @@ void TooltipWin::PositionTooltip() {
display.work_area()));
SetWindowPos(tooltip_hwnd_, NULL, tooltip_bounds.x(), tooltip_bounds.y(), 0,
0, SWP_NOSIZE | SWP_NOZORDER | SWP_NOACTIVATE);
+
+ MaybeOverrideFont();
+}
+
+void TooltipWin::MaybeOverrideFont() {
+ gfx::PlatformFontWin::FontAdjustment font_adjustment;
+ const HFONT old_font = GetWindowFont(tooltip_hwnd_);
+
+ // Determine if we need to override the font.
+ if ((!override_font_ || override_font_->GetNativeFont() != old_font) &&
+ l10n_util::NeedOverrideDefaultUIFont(
+ &font_adjustment.font_family_override, &font_adjustment.font_scale)) {
+ // Determine if we need to regenerate the font.
+ // There are a number of situations under which Windows can replace the
+ // font in a tooltip, but we don't actually need to regenerate our override
+ // font unless the underlying text/DPI scale of the window has changed.
+ const float current_scale =
+ display::win::ScreenWin::GetScaleFactorForHWND(tooltip_hwnd_);
+ if (!override_font_ || current_scale != override_scale_) {
+ override_font_ =
+ gfx::PlatformFontWin::AdjustExistingFont(old_font, font_adjustment);
+ override_scale_ = current_scale;
+ }
+
+ // Override the font in the tooltip.
+ SetWindowFont(tooltip_hwnd_, override_font_->GetNativeFont(), FALSE);
+ }
}
int TooltipWin::GetMaxWidth(const gfx::Point& location) const {
@@ -116,12 +158,6 @@ void TooltipWin::SetText(aura::Window* window,
// See comment in header for details on why |location_| is needed.
location_ = location;
- // Without this we get a flicker of the tooltip appearing at 0x0. Not sure
- // why.
- SetWindowPos(tooltip_hwnd_, NULL, 0, 0, 0, 0,
- SWP_HIDEWINDOW | SWP_NOACTIVATE | SWP_NOMOVE |
- SWP_NOREPOSITION | SWP_NOSIZE | SWP_NOZORDER);
-
base::string16 adjusted_text(tooltip_text);
base::i18n::AdjustStringForLocaleDirection(&adjusted_text);
toolinfo_.lpszText = const_cast<WCHAR*>(adjusted_text.c_str());
@@ -138,8 +174,6 @@ void TooltipWin::Show() {
SendMessage(tooltip_hwnd_, TTM_TRACKACTIVATE,
TRUE, reinterpret_cast<LPARAM>(&toolinfo_));
- SetWindowPos(tooltip_hwnd_, HWND_TOPMOST, 0, 0, 0, 0,
- SWP_NOACTIVATE | SWP_NOMOVE | SWP_NOOWNERZORDER | SWP_NOSIZE);
}
void TooltipWin::Hide() {
diff --git a/chromium/ui/views/corewm/tooltip_win.h b/chromium/ui/views/corewm/tooltip_win.h
index eb9e5209de3..e656c87d3ce 100644
--- a/chromium/ui/views/corewm/tooltip_win.h
+++ b/chromium/ui/views/corewm/tooltip_win.h
@@ -5,15 +5,17 @@
#ifndef UI_VIEWS_COREWM_TOOLTIP_WIN_H_
#define UI_VIEWS_COREWM_TOOLTIP_WIN_H_
+#include <windows.h>
+#include <commctrl.h>
+
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "base/optional.h"
#include "base/strings/string16.h"
+#include "ui/gfx/font.h"
#include "ui/gfx/geometry/point.h"
#include "ui/views/corewm/tooltip.h"
-#include <windows.h>
-#include <commctrl.h>
-
namespace views {
namespace corewm {
@@ -36,6 +38,9 @@ class VIEWS_EXPORT TooltipWin : public Tooltip {
// Sets the position of the tooltip.
void PositionTooltip();
+ // Might override the font size for localization (e.g. Hindi).
+ void MaybeOverrideFont();
+
// Tooltip:
int GetMaxWidth(const gfx::Point& location) const override;
void SetText(aura::Window* window,
@@ -45,6 +50,11 @@ class VIEWS_EXPORT TooltipWin : public Tooltip {
void Hide() override;
bool IsVisible() override;
+ // Font we're currently overriding our UI font with.
+ // (Lets us keep a handle around so we don't leak.)
+ // Should outlast |tooltip_hwnd_|.
+ base::Optional<gfx::Font> override_font_;
+
// The window |tooltip_hwnd_| is parented to.
HWND parent_hwnd_;
@@ -62,6 +72,10 @@ class VIEWS_EXPORT TooltipWin : public Tooltip {
// cache it.
gfx::Point location_;
+ // What the scale was the last time we overrode the font, to see if we can
+ // re-use our previous override.
+ float override_scale_ = 0.0f;
+
DISALLOW_COPY_AND_ASSIGN(TooltipWin);
};
diff --git a/chromium/ui/views/event_utils.cc b/chromium/ui/views/event_utils.cc
new file mode 100644
index 00000000000..ecec6e0220c
--- /dev/null
+++ b/chromium/ui/views/event_utils.cc
@@ -0,0 +1,22 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/event_utils.h"
+
+#include "base/time/time.h"
+#include "ui/events/event.h"
+#include "ui/views/metrics.h"
+
+namespace views {
+
+bool IsPossiblyUnintendedInteraction(const base::TimeTicks& initial_timestamp,
+ const ui::Event& event) {
+ return (event.IsMouseEvent() || event.IsPointerEvent() ||
+ event.IsTouchEvent()) &&
+ event.time_stamp() <
+ initial_timestamp +
+ base::TimeDelta::FromMilliseconds(GetDoubleClickInterval());
+}
+
+} // namespace views
diff --git a/chromium/ui/views/event_utils.h b/chromium/ui/views/event_utils.h
new file mode 100644
index 00000000000..cfc553ff659
--- /dev/null
+++ b/chromium/ui/views/event_utils.h
@@ -0,0 +1,28 @@
+// Copyright (c) 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_VIEWS_EVENT_UTILS_H_
+#define UI_VIEWS_EVENT_UTILS_H_
+
+#include "ui/views/views_export.h"
+
+namespace base {
+class TimeTicks;
+}
+
+namespace ui {
+class Event;
+}
+
+namespace views {
+
+// Returns true if the event is a mouse, touch, or pointer event that took place
+// within the double-click time interval after the |initial_timestamp|.
+VIEWS_EXPORT bool IsPossiblyUnintendedInteraction(
+ const base::TimeTicks& initial_timestamp,
+ const ui::Event& event);
+
+} // namespace views
+
+#endif // UI_VIEWS_EVENT_UTILS_H_
diff --git a/chromium/ui/views/examples/BUILD.gn b/chromium/ui/views/examples/BUILD.gn
index c757e20b7ff..0069d8c9c8d 100644
--- a/chromium/ui/views/examples/BUILD.gn
+++ b/chromium/ui/views/examples/BUILD.gn
@@ -9,6 +9,8 @@ jumbo_component("views_examples_lib") {
testonly = true
sources = [
+ "animated_image_view_example.cc",
+ "animated_image_view_example.h",
"box_layout_example.cc",
"box_layout_example.h",
"bubble_example.cc",
diff --git a/chromium/ui/views/examples/animated_image_view_example.cc b/chromium/ui/views/examples/animated_image_view_example.cc
new file mode 100644
index 00000000000..4e52a95aeab
--- /dev/null
+++ b/chromium/ui/views/examples/animated_image_view_example.cc
@@ -0,0 +1,143 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/examples/animated_image_view_example.h"
+
+#include <memory>
+
+#include "base/files/file_path.h"
+#include "base/files/file_util.h"
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "base/strings/string_number_conversions.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/threading/thread_restrictions.h"
+#include "build/build_config.h"
+#include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/skottie_wrapper.h"
+#include "ui/views/border.h"
+#include "ui/views/controls/animated_image_view.h"
+#include "ui/views/controls/button/button.h"
+#include "ui/views/controls/button/md_text_button.h"
+#include "ui/views/controls/textfield/textfield.h"
+#include "ui/views/controls/textfield/textfield_controller.h"
+#include "ui/views/layout/box_layout.h"
+#include "ui/views/layout/fill_layout.h"
+#include "ui/views/view.h"
+
+namespace views {
+namespace examples {
+
+namespace {
+
+// This class can load a skottie(and lottie) animation file from disk and play
+// it in a view as AnimatedImageView.
+// See https://skia.org/user/modules/skottie for more info on skottie.
+class AnimationGallery : public View,
+ public TextfieldController,
+ public ButtonListener {
+ public:
+ AnimationGallery()
+ : animated_image_view_(new AnimatedImageView()),
+ image_view_container_(new views::View()),
+ size_input_(new Textfield()),
+ file_chooser_(new Textfield()),
+ file_go_button_(
+ MdTextButton::Create(this, base::ASCIIToUTF16("Render"))) {
+ AddChildView(size_input_);
+
+ image_view_container_->AddChildView(animated_image_view_);
+ image_view_container_->SetLayoutManager(std::make_unique<FillLayout>());
+ animated_image_view_->SetBorder(
+ CreateSolidSidedBorder(1, 1, 1, 1, SK_ColorBLACK));
+ AddChildView(image_view_container_);
+
+ BoxLayout* box = SetLayoutManager(
+ std::make_unique<BoxLayout>(BoxLayout::kVertical, gfx::Insets(10), 10));
+ box->SetFlexForView(image_view_container_, 1);
+
+ file_chooser_->set_placeholder_text(
+ base::ASCIIToUTF16("Enter path to lottie JSON file"));
+ View* file_container = new View();
+ BoxLayout* file_box =
+ file_container->SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::kHorizontal, gfx::Insets(10), 10));
+ file_container->AddChildView(file_chooser_);
+ file_container->AddChildView(file_go_button_);
+ file_box->SetFlexForView(file_chooser_, 1);
+ AddChildView(file_container);
+
+ size_input_->set_placeholder_text(
+ base::ASCIIToUTF16("Size in dip (Empty for default)"));
+ size_input_->set_controller(this);
+ }
+
+ ~AnimationGallery() override = default;
+
+ // TextfieldController:
+ void ContentsChanged(Textfield* sender,
+ const base::string16& new_contents) override {
+ if (sender == size_input_) {
+ if (!base::StringToInt(new_contents, &size_) && (size_ > 0)) {
+ size_ = 0;
+ size_input_->SetText(base::string16());
+ }
+ Update();
+ }
+ }
+
+ // ButtonListener:
+ void ButtonPressed(Button* sender, const ui::Event& event) override {
+ DCHECK_EQ(file_go_button_, sender);
+ std::string json;
+ base::ScopedAllowBlockingForTesting allow_blocking;
+#if defined(OS_POSIX)
+ base::FilePath path(base::UTF16ToUTF8(file_chooser_->text()));
+#else
+ base::FilePath path(file_chooser_->text());
+#endif // defined(OS_POSIX)
+ base::ReadFileToString(path, &json);
+
+ auto skottie = base::MakeRefCounted<gfx::SkottieWrapper>(
+ base::RefCountedString::TakeString(&json));
+ animated_image_view_->SetAnimatedImage(
+ std::make_unique<gfx::SkiaVectorAnimation>(skottie));
+ animated_image_view_->Play();
+ Update();
+ }
+
+ private:
+ void Update() {
+ if (size_ > 24)
+ animated_image_view_->SetImageSize(gfx::Size(size_, size_));
+ else
+ animated_image_view_->ResetImageSize();
+ Layout();
+ }
+
+ AnimatedImageView* animated_image_view_;
+ View* image_view_container_;
+ Textfield* size_input_;
+ Textfield* file_chooser_;
+ Button* file_go_button_;
+
+ int size_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(AnimationGallery);
+};
+
+} // namespace
+
+AnimatedImageViewExample::AnimatedImageViewExample()
+ : ExampleBase("Animated Image View") {}
+
+AnimatedImageViewExample::~AnimatedImageViewExample() {}
+
+void AnimatedImageViewExample::CreateExampleView(View* container) {
+ container->SetLayoutManager(std::make_unique<FillLayout>());
+ container->AddChildView(new AnimationGallery());
+}
+
+} // namespace examples
+} // namespace views
diff --git a/chromium/ui/views/examples/animated_image_view_example.h b/chromium/ui/views/examples/animated_image_view_example.h
new file mode 100644
index 00000000000..8bf30b56a87
--- /dev/null
+++ b/chromium/ui/views/examples/animated_image_view_example.h
@@ -0,0 +1,29 @@
+// 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_VIEWS_EXAMPLES_ANIMATED_IMAGE_VIEW_EXAMPLE_H_
+#define UI_VIEWS_EXAMPLES_ANIMATED_IMAGE_VIEW_EXAMPLE_H_
+
+#include "base/macros.h"
+#include "ui/views/examples/example_base.h"
+
+namespace views {
+namespace examples {
+
+class VIEWS_EXAMPLES_EXPORT AnimatedImageViewExample : public ExampleBase {
+ public:
+ AnimatedImageViewExample();
+ ~AnimatedImageViewExample() override;
+
+ // ExampleBase:
+ void CreateExampleView(View* container) override;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(AnimatedImageViewExample);
+};
+
+} // namespace examples
+} // namespace views
+
+#endif // UI_VIEWS_EXAMPLES_ANIMATED_IMAGE_VIEW_EXAMPLE_H_
diff --git a/chromium/ui/views/examples/examples_main.cc b/chromium/ui/views/examples/examples_main.cc
index 4dd22a71197..f2f3a2a205b 100644
--- a/chromium/ui/views/examples/examples_main.cc
+++ b/chromium/ui/views/examples/examples_main.cc
@@ -118,9 +118,10 @@ int main(int argc, char** argv) {
display::Screen::SetScreenInstance(desktop_screen.get());
#endif
- views::examples::ShowExamplesWindow(views::examples::QUIT_ON_CLOSE);
+ base::RunLoop run_loop;
+ views::examples::ShowExamplesWindow(run_loop.QuitClosure());
- base::RunLoop().Run();
+ run_loop.Run();
ui::ResourceBundle::CleanupSharedInstance();
}
diff --git a/chromium/ui/views/examples/examples_window.cc b/chromium/ui/views/examples/examples_window.cc
index b903e478740..683d5d59711 100644
--- a/chromium/ui/views/examples/examples_window.cc
+++ b/chromium/ui/views/examples/examples_window.cc
@@ -18,6 +18,7 @@
#include "ui/views/background.h"
#include "ui/views/controls/combobox/combobox.h"
#include "ui/views/controls/label.h"
+#include "ui/views/examples/animated_image_view_example.h"
#include "ui/views/examples/box_layout_example.h"
#include "ui/views/examples/bubble_example.h"
#include "ui/views/examples/button_example.h"
@@ -58,6 +59,7 @@ namespace {
// Creates the default set of examples.
ExampleVector CreateExamples() {
ExampleVector examples;
+ examples.push_back(std::make_unique<AnimatedImageViewExample>());
examples.push_back(std::make_unique<BoxLayoutExample>());
examples.push_back(std::make_unique<BubbleExample>());
examples.push_back(std::make_unique<ButtonExample>());
@@ -131,11 +133,11 @@ class ComboboxModelExampleList : public ui::ComboboxModel {
class ExamplesWindowContents : public WidgetDelegateView,
public ComboboxListener {
public:
- ExamplesWindowContents(Operation operation, ExampleVector examples)
+ ExamplesWindowContents(base::OnceClosure on_close, ExampleVector examples)
: combobox_(new Combobox(&combobox_model_)),
example_shown_(new View),
status_label_(new Label),
- operation_(operation) {
+ on_close_(std::move(on_close)) {
instance_ = this;
combobox_->set_listener(this);
combobox_model_.SetExamples(std::move(examples));
@@ -188,8 +190,8 @@ class ExamplesWindowContents : public WidgetDelegateView,
}
void WindowClosing() override {
instance_ = NULL;
- if (operation_ == QUIT_ON_CLOSE)
- base::RunLoop::QuitCurrentWhenIdleDeprecated();
+ if (on_close_)
+ std::move(on_close_).Run();
}
gfx::Size CalculatePreferredSize() const override {
return gfx::Size(800, 300);
@@ -212,7 +214,7 @@ class ExamplesWindowContents : public WidgetDelegateView,
Combobox* combobox_;
View* example_shown_;
Label* status_label_;
- const Operation operation_;
+ base::OnceClosure on_close_;
DISALLOW_COPY_AND_ASSIGN(ExamplesWindowContents);
};
@@ -220,7 +222,7 @@ class ExamplesWindowContents : public WidgetDelegateView,
// static
ExamplesWindowContents* ExamplesWindowContents::instance_ = NULL;
-void ShowExamplesWindow(Operation operation,
+void ShowExamplesWindow(base::OnceClosure on_close,
gfx::NativeWindow window_context,
ExampleVector extra_examples) {
if (ExamplesWindowContents::instance()) {
@@ -230,7 +232,7 @@ void ShowExamplesWindow(Operation operation,
Widget* widget = new Widget;
Widget::InitParams params;
params.delegate =
- new ExamplesWindowContents(operation, std::move(examples));
+ new ExamplesWindowContents(std::move(on_close), std::move(examples));
params.context = window_context;
widget->Init(params);
widget->Show();
diff --git a/chromium/ui/views/examples/examples_window.h b/chromium/ui/views/examples/examples_window.h
index 804252fcc9b..d543c01c3f6 100644
--- a/chromium/ui/views/examples/examples_window.h
+++ b/chromium/ui/views/examples/examples_window.h
@@ -15,16 +15,11 @@
namespace views {
namespace examples {
-enum Operation {
- DO_NOTHING_ON_CLOSE = 0,
- QUIT_ON_CLOSE,
-};
-
// Shows a window with the views examples in it. |extra_examples| contains any
// additional examples to add. |window_context| is used to determine where the
// window should be created (see |Widget::InitParams::context| for details).
VIEWS_EXAMPLES_EXPORT void ShowExamplesWindow(
- Operation operation,
+ base::OnceClosure on_close,
gfx::NativeWindow window_context = nullptr,
std::vector<std::unique_ptr<ExampleBase>> extra_examples =
std::vector<std::unique_ptr<ExampleBase>>());
diff --git a/chromium/ui/views/examples/examples_window_with_content.cc b/chromium/ui/views/examples/examples_window_with_content.cc
index 1133e88fa9a..c9391fa8bd8 100644
--- a/chromium/ui/views/examples/examples_window_with_content.cc
+++ b/chromium/ui/views/examples/examples_window_with_content.cc
@@ -14,12 +14,13 @@
namespace views {
namespace examples {
-void ShowExamplesWindowWithContent(Operation operation,
+void ShowExamplesWindowWithContent(base::OnceClosure on_close,
content::BrowserContext* browser_context,
gfx::NativeWindow window_context) {
std::vector<std::unique_ptr<ExampleBase>> extra_examples;
extra_examples.push_back(std::make_unique<WebViewExample>(browser_context));
- ShowExamplesWindow(operation, window_context, std::move(extra_examples));
+ ShowExamplesWindow(std::move(on_close), window_context,
+ std::move(extra_examples));
}
} // namespace examples
diff --git a/chromium/ui/views/examples/examples_window_with_content.h b/chromium/ui/views/examples/examples_window_with_content.h
index 945201bdf7c..dbcb1fbd806 100644
--- a/chromium/ui/views/examples/examples_window_with_content.h
+++ b/chromium/ui/views/examples/examples_window_with_content.h
@@ -18,7 +18,7 @@ namespace examples {
// Shows a window with the views examples in it.
VIEWS_EXAMPLES_WITH_CONTENT_EXPORT void ShowExamplesWindowWithContent(
- Operation operation,
+ base::OnceClosure on_close,
content::BrowserContext* browser_context,
gfx::NativeWindow window_context);
diff --git a/chromium/ui/views/examples/examples_with_content_main_exe.cc b/chromium/ui/views/examples/examples_with_content_main_exe.cc
index ffbad7ff3e7..3506d740035 100644
--- a/chromium/ui/views/examples/examples_with_content_main_exe.cc
+++ b/chromium/ui/views/examples/examples_with_content_main_exe.cc
@@ -15,11 +15,12 @@
namespace {
-void ShowContentExampleWindow(content::BrowserContext* browser_context,
+void ShowContentExampleWindow(ui::ViewsContentClient* views_content_client,
+ content::BrowserContext* browser_context,
gfx::NativeWindow window_context) {
- views::examples::ShowExamplesWindowWithContent(views::examples::QUIT_ON_CLOSE,
- browser_context,
- window_context);
+ views::examples::ShowExamplesWindowWithContent(
+ std::move(views_content_client->quit_closure()), browser_context,
+ window_context);
// These lines serve no purpose other than to introduce an explicit content
// dependency. If the main executable doesn't have this dependency, the linker
@@ -45,6 +46,7 @@ int main(int argc, const char** argv) {
ui::ViewsContentClient views_content_client(argc, argv);
#endif
- views_content_client.set_task(base::Bind(&ShowContentExampleWindow));
+ views_content_client.set_task(base::Bind(
+ &ShowContentExampleWindow, base::Unretained(&views_content_client)));
return views_content_client.RunMain();
}
diff --git a/chromium/ui/views/examples/menu_example.cc b/chromium/ui/views/examples/menu_example.cc
index 2e9081c9893..3c2713a432c 100644
--- a/chromium/ui/views/examples/menu_example.cc
+++ b/chromium/ui/views/examples/menu_example.cc
@@ -155,7 +155,7 @@ void ExampleMenuModel::ExecuteCommand(int command_id, int event_flags) {
checked_fruit = "Kiwi";
// Update the check status.
- std::set<int>::iterator iter = checked_fruits_.find(command_id);
+ auto iter = checked_fruits_.find(command_id);
if (iter == checked_fruits_.end()) {
DVLOG(1) << "Checked " << checked_fruit;
checked_fruits_.insert(command_id);
diff --git a/chromium/ui/views/focus/focus_manager_unittest.cc b/chromium/ui/views/focus/focus_manager_unittest.cc
index ed29e91704b..10da1cd7fb3 100644
--- a/chromium/ui/views/focus/focus_manager_unittest.cc
+++ b/chromium/ui/views/focus/focus_manager_unittest.cc
@@ -130,12 +130,6 @@ TEST_F(FocusManagerTest, FocusChangeListener) {
}
TEST_F(FocusManagerTest, WidgetFocusChangeListener) {
- // TODO: this test ends up calling focus on the aura::Window associated with
- // the Widget and expecting that to change activation. This should work for
- // aura-mus-client as well. http://crbug.com/664261.
- if (IsMus())
- return;
-
// First, ensure the simulator is aware of the Widget created in SetUp() being
// currently active.
test::WidgetTest::SimulateNativeActivate(GetWidget());
diff --git a/chromium/ui/views/focus/widget_focus_manager.cc b/chromium/ui/views/focus/widget_focus_manager.cc
index 099b286e94c..79517fbd4bd 100644
--- a/chromium/ui/views/focus/widget_focus_manager.cc
+++ b/chromium/ui/views/focus/widget_focus_manager.cc
@@ -4,17 +4,63 @@
#include "ui/views/focus/widget_focus_manager.h"
-#include "base/memory/singleton.h"
+#include "base/supports_user_data.h"
+
+#if defined(USE_AURA)
+#include "ui/aura/env.h"
+#include "ui/aura/window.h"
+#endif
namespace views {
+#if defined(USE_AURA)
+namespace {
+
+const char kWidgetFocusManagerKey[] = "WidgetFocusManager";
+
+} // namespace
+
+class WidgetFocusManager::Owner : public base::SupportsUserData::Data {
+ public:
+ explicit Owner(std::unique_ptr<WidgetFocusManager> focus_manager)
+ : focus_manager_(std::move(focus_manager)) {}
+ ~Owner() override = default;
+
+ WidgetFocusManager* focus_manager() { return focus_manager_.get(); }
+
+ private:
+ std::unique_ptr<WidgetFocusManager> focus_manager_;
+
+ DISALLOW_COPY_AND_ASSIGN(Owner);
+};
+
+#endif
+
// WidgetFocusManager ----------------------------------------------------------
// static
-WidgetFocusManager* WidgetFocusManager::GetInstance() {
- return base::Singleton<WidgetFocusManager>::get();
+WidgetFocusManager* WidgetFocusManager::GetInstance(gfx::NativeWindow context) {
+#if defined(USE_AURA)
+ // With aura there may be multiple Envs, in such a situation the
+ // WidgetFocusManager needs to be per Env.
+ aura::Env* env = context ? context->env() : aura::Env::GetInstance();
+ DCHECK(env);
+ Owner* owner = static_cast<Owner*>(env->GetUserData(kWidgetFocusManagerKey));
+ if (!owner) {
+ std::unique_ptr<Owner> owner_ptr =
+ std::make_unique<Owner>(base::WrapUnique(new WidgetFocusManager()));
+ owner = owner_ptr.get();
+ env->SetUserData(kWidgetFocusManagerKey, std::move(owner_ptr));
+ }
+ return owner->focus_manager();
+#else
+ static base::NoDestructor<WidgetFocusManager> instance;
+ return instance.get();
+#endif
}
+WidgetFocusManager::~WidgetFocusManager() = default;
+
void WidgetFocusManager::AddFocusChangeListener(
WidgetFocusChangeListener* listener) {
focus_change_listeners_.AddObserver(listener);
@@ -34,8 +80,6 @@ void WidgetFocusManager::OnNativeFocusChanged(gfx::NativeView focused_now) {
WidgetFocusManager::WidgetFocusManager() : enabled_(true) {}
-WidgetFocusManager::~WidgetFocusManager() {}
-
// AutoNativeNotificationDisabler ----------------------------------------------
AutoNativeNotificationDisabler::AutoNativeNotificationDisabler() {
diff --git a/chromium/ui/views/focus/widget_focus_manager.h b/chromium/ui/views/focus/widget_focus_manager.h
index 068a4825b46..eb29250c7e6 100644
--- a/chromium/ui/views/focus/widget_focus_manager.h
+++ b/chromium/ui/views/focus/widget_focus_manager.h
@@ -6,14 +6,11 @@
#define UI_VIEWS_FOCUS_WIDGET_FOCUS_MANAGER_H_
#include "base/macros.h"
+#include "base/no_destructor.h"
#include "base/observer_list.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/views/views_export.h"
-namespace base {
-template <typename T> struct DefaultSingletonTraits;
-}
-
namespace views {
// This interface should be implemented by classes that want to be notified when
@@ -32,7 +29,9 @@ class WidgetFocusChangeListener {
class VIEWS_EXPORT WidgetFocusManager {
public:
// Returns the singleton instance.
- static WidgetFocusManager* GetInstance();
+ static WidgetFocusManager* GetInstance(gfx::NativeWindow context = nullptr);
+
+ ~WidgetFocusManager();
// Adds/removes a WidgetFocusChangeListener |listener| to the set of
// active listeners.
@@ -50,10 +49,10 @@ class VIEWS_EXPORT WidgetFocusManager {
void DisableNotifications() { enabled_ = false; }
private:
- friend struct base::DefaultSingletonTraits<WidgetFocusManager>;
+ class Owner;
+ friend class base::NoDestructor<WidgetFocusManager>;
WidgetFocusManager();
- ~WidgetFocusManager();
base::ObserverList<WidgetFocusChangeListener>::Unchecked
focus_change_listeners_;
diff --git a/chromium/ui/views/layout/box_layout.cc b/chromium/ui/views/layout/box_layout.cc
index f9c1b6dc485..cdc9750f08b 100644
--- a/chromium/ui/views/layout/box_layout.cc
+++ b/chromium/ui/views/layout/box_layout.cc
@@ -363,7 +363,7 @@ void BoxLayout::ViewRemoved(View* host, View* view) {
}
int BoxLayout::GetFlexForView(const View* view) const {
- FlexMap::const_iterator it = flex_map_.find(view);
+ auto it = flex_map_.find(view);
if (it == flex_map_.end())
return default_flex_;
@@ -371,7 +371,7 @@ int BoxLayout::GetFlexForView(const View* view) const {
}
int BoxLayout::GetMinimumSizeForView(const View* view) const {
- FlexMap::const_iterator it = flex_map_.find(view);
+ auto it = flex_map_.find(view);
if (it == flex_map_.end() || !it->second.use_min_size)
return 0;
diff --git a/chromium/ui/views/linux_ui/linux_ui.h b/chromium/ui/views/linux_ui/linux_ui.h
index 86a3c0a78cb..759d4ab03f0 100644
--- a/chromium/ui/views/linux_ui/linux_ui.h
+++ b/chromium/ui/views/linux_ui/linux_ui.h
@@ -101,12 +101,10 @@ class VIEWS_EXPORT LinuxUI : public ui::LinuxInputMethodContextFactory,
virtual bool GetColor(int id,
SkColor* color,
PrefService* pref_service) const = 0;
+ virtual bool GetDisplayProperty(int id, int* result) const = 0;
// Returns the preferences that we pass to WebKit.
virtual SkColor GetFocusRingColor() const = 0;
- virtual SkColor GetThumbActiveColor() const = 0;
- virtual SkColor GetThumbInactiveColor() const = 0;
- virtual SkColor GetTrackColor() const = 0;
virtual SkColor GetActiveSelectionBgColor() const = 0;
virtual SkColor GetActiveSelectionFgColor() const = 0;
virtual SkColor GetInactiveSelectionBgColor() const = 0;
diff --git a/chromium/ui/views/mus/ax_remote_host.cc b/chromium/ui/views/mus/ax_remote_host.cc
index 0affab635ac..01511da2296 100644
--- a/chromium/ui/views/mus/ax_remote_host.cc
+++ b/chromium/ui/views/mus/ax_remote_host.cc
@@ -6,10 +6,12 @@
#include <stddef.h>
+#include "base/no_destructor.h"
#include "services/service_manager/public/cpp/connector.h"
#include "ui/accessibility/ax_action_data.h"
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_event.h"
+#include "ui/accessibility/platform/aura_window_properties.h"
#include "ui/accessibility/platform/ax_unique_id.h"
#include "ui/aura/mus/window_tree_client.h"
#include "ui/aura/window.h"
@@ -27,9 +29,6 @@ using display::Screen;
namespace views {
-// For external linkage.
-constexpr int AXRemoteHost::kRemoteAXTreeID;
-
AXRemoteHost::AXRemoteHost() {
AXAuraObjCache::GetInstance()->SetDelegate(this);
}
@@ -42,12 +41,12 @@ AXRemoteHost::~AXRemoteHost() {
void AXRemoteHost::Init(service_manager::Connector* connector) {
connector->BindInterface(ax::mojom::kAXHostServiceName, &ax_host_ptr_);
- BindAndSetRemote();
+ BindAndRegisterRemote();
}
void AXRemoteHost::InitForTesting(ax::mojom::AXHostPtr host_ptr) {
ax_host_ptr_ = std::move(host_ptr);
- BindAndSetRemote();
+ BindAndRegisterRemote();
}
void AXRemoteHost::StartMonitoringWidget(Widget* widget) {
@@ -62,6 +61,10 @@ void AXRemoteHost::StartMonitoringWidget(Widget* widget) {
widget_ = widget;
widget_->AddObserver(this);
+ DCHECK_NE(tree_id_, ui::AXTreeIDUnknown());
+ widget_->GetNativeWindow()->SetProperty(ui::kChildAXTreeID,
+ new std::string(tree_id_.ToString()));
+
// The cache needs to track the root window to follow focus changes.
AXAuraObjCache* cache = AXAuraObjCache::GetInstance();
cache->OnRootWindowObjCreated(widget_->GetNativeWindow());
@@ -71,7 +74,7 @@ void AXRemoteHost::StartMonitoringWidget(Widget* widget) {
View* contents_view = widget_->widget_delegate()->GetContentsView();
AXAuraObjWrapper* contents_wrapper = cache->GetOrCreate(contents_view);
- tree_source_ = std::make_unique<AXTreeSourceMus>(contents_wrapper);
+ tree_source_ = std::make_unique<AXTreeSourceMus>(contents_wrapper, tree_id_);
tree_serializer_ = std::make_unique<AuraAXTreeSerializer>(tree_source_.get());
// Inform the serializer of the display device scale factor.
@@ -99,9 +102,15 @@ void AXRemoteHost::HandleEvent(View* view, ax::mojom::Event event_type) {
if (!enabled_)
return;
- AXAuraObjWrapper* aura_obj =
- view ? AXAuraObjCache::GetInstance()->GetOrCreate(view)
- : tree_source_->GetRoot();
+ if (!view) {
+ SendEvent(tree_source_->GetRoot(), event_type);
+ return;
+ }
+
+ // Can return null for views without a widget.
+ AXAuraObjWrapper* aura_obj = AXAuraObjCache::GetInstance()->GetOrCreate(view);
+ if (!aura_obj)
+ return;
SendEvent(aura_obj, event_type);
}
@@ -168,15 +177,26 @@ void AXRemoteHost::FlushForTesting() {
ax_host_ptr_.FlushForTesting();
}
-void AXRemoteHost::BindAndSetRemote() {
+void AXRemoteHost::BindAndRegisterRemote() {
ax::mojom::AXRemoteHostPtr remote;
binding_.Bind(mojo::MakeRequest(&remote));
- ax_host_ptr_->SetRemoteHost(std::move(remote));
+ ax_host_ptr_->RegisterRemoteHost(
+ std::move(remote),
+ base::BindOnce(&AXRemoteHost::RegisterRemoteHostCallback,
+ base::Unretained(this)));
+}
+
+void AXRemoteHost::RegisterRemoteHostCallback(const ui::AXTreeID& tree_id,
+ bool enabled) {
+ tree_id_ = tree_id;
+
+ // Set the initial enabled state and send the AX tree if necessary.
+ OnAutomationEnabled(enabled);
}
void AXRemoteHost::Enable() {
// Don't early-exit if already enabled. AXRemoteHost can start up in the
- // "enabled" state even if ChromeVox is on at the moment the app launches.
+ // "enabled" state even if ChromeVox is off at the moment the app launches.
// Turning on ChromeVox later will generate another OnAutomationEnabled()
// call and we need to serialize the node tree again. This is similar to
// AutomationManagerAura's behavior. https://crbug.com/876407
@@ -234,7 +254,7 @@ void AXRemoteHost::SendEvent(AXAuraObjWrapper* aura_obj,
event.event_type = event_type;
// Other fields are not used.
- ax_host_ptr_->HandleAccessibilityEvent(kRemoteAXTreeID, updates, event);
+ ax_host_ptr_->HandleAccessibilityEvent(tree_id_, updates, event);
}
void AXRemoteHost::PerformHitTest(const ui::AXActionData& action) {
diff --git a/chromium/ui/views/mus/ax_remote_host.h b/chromium/ui/views/mus/ax_remote_host.h
index 7e506159487..bb432ba5073 100644
--- a/chromium/ui/views/mus/ax_remote_host.h
+++ b/chromium/ui/views/mus/ax_remote_host.h
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "mojo/public/cpp/bindings/binding.h"
+#include "ui/accessibility/ax_tree_id.h"
#include "ui/accessibility/ax_tree_serializer.h"
#include "ui/accessibility/mojom/ax_host.mojom.h"
#include "ui/display/display_observer.h"
@@ -41,10 +42,6 @@ class VIEWS_MUS_EXPORT AXRemoteHost : public ax::mojom::AXRemoteHost,
public display::DisplayObserver,
public AXAuraObjCache::Delegate {
public:
- // Well-known tree ID for the remote client.
- // TODO(jamescook): Support different IDs for different clients.
- static constexpr int kRemoteAXTreeID = -2;
-
AXRemoteHost();
~AXRemoteHost() override;
@@ -84,7 +81,10 @@ class VIEWS_MUS_EXPORT AXRemoteHost : public ax::mojom::AXRemoteHost,
private:
// Registers this object as a remote host for the parent AXHost.
- void BindAndSetRemote();
+ void BindAndRegisterRemote();
+
+ // Callback for initial state from AXHost.
+ void RegisterRemoteHostCallback(const ui::AXTreeID& tree_id, bool enabled);
void Enable();
void Disable();
@@ -102,6 +102,9 @@ class VIEWS_MUS_EXPORT AXRemoteHost : public ax::mojom::AXRemoteHost,
mojo::Binding<ax::mojom::AXRemoteHost> binding_{this};
+ // ID to use for the AX tree.
+ ui::AXTreeID tree_id_;
+
// Whether accessibility automation support is enabled.
bool enabled_ = false;
diff --git a/chromium/ui/views/mus/ax_remote_host_unittest.cc b/chromium/ui/views/mus/ax_remote_host_unittest.cc
index fd187350140..d6620cf9b2a 100644
--- a/chromium/ui/views/mus/ax_remote_host_unittest.cc
+++ b/chromium/ui/views/mus/ax_remote_host_unittest.cc
@@ -5,9 +5,11 @@
#include "ui/views/mus/ax_remote_host.h"
#include "base/macros.h"
+#include "base/no_destructor.h"
#include "base/run_loop.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/accessibility/mojom/ax_host.mojom.h"
+#include "ui/accessibility/platform/aura_window_properties.h"
#include "ui/display/display.h"
#include "ui/gfx/geometry/vector2d_f.h"
#include "ui/gfx/transform.h"
@@ -21,6 +23,13 @@
namespace views {
namespace {
+// Returns a well-known tree ID for the test widget.
+const ui::AXTreeID& TestAXTreeID() {
+ static const base::NoDestructor<ui::AXTreeID> test_ax_tree_id(
+ ui::AXTreeID::FromString("123"));
+ return *test_ax_tree_id;
+}
+
// Simulates the AXHostService in the browser.
class TestAXHostService : public ax::mojom::AXHost {
public:
@@ -35,33 +44,34 @@ class TestAXHostService : public ax::mojom::AXHost {
}
void ResetCounts() {
- add_client_count_ = 0;
+ remote_host_count_ = 0;
event_count_ = 0;
- last_tree_id_ = 0;
+ last_tree_id_ = ui::AXTreeIDUnknown();
last_updates_.clear();
last_event_ = ui::AXEvent();
}
// ax::mojom::AXHost:
- void SetRemoteHost(ax::mojom::AXRemoteHostPtr client) override {
- ++add_client_count_;
- client->OnAutomationEnabled(automation_enabled_);
+ void RegisterRemoteHost(ax::mojom::AXRemoteHostPtr client,
+ RegisterRemoteHostCallback cb) override {
+ ++remote_host_count_;
+ std::move(cb).Run(TestAXTreeID(), automation_enabled_);
client.FlushForTesting();
}
- void HandleAccessibilityEvent(int32_t tree_id,
+ void HandleAccessibilityEvent(const ui::AXTreeID& tree_id,
const std::vector<ui::AXTreeUpdate>& updates,
const ui::AXEvent& event) override {
++event_count_;
- last_tree_id_ = tree_id;
+ last_tree_id_ = ui::AXTreeID::FromString(tree_id);
last_updates_ = updates;
last_event_ = event;
}
mojo::Binding<ax::mojom::AXHost> binding_{this};
bool automation_enabled_ = false;
- int add_client_count_ = 0;
+ int remote_host_count_ = 0;
int event_count_ = 0;
- int last_tree_id_ = 0;
+ ui::AXTreeID last_tree_id_ = ui::AXTreeIDUnknown();
std::vector<ui::AXTreeUpdate> last_updates_;
ui::AXEvent last_event_;
@@ -127,7 +137,7 @@ TEST_F(AXRemoteHostTest, CreateRemote) {
CreateRemote(&service);
// Client registered itself with service.
- EXPECT_EQ(1, service.add_client_count_);
+ EXPECT_EQ(1, service.remote_host_count_);
}
TEST_F(AXRemoteHostTest, AutomationEnabled) {
@@ -136,7 +146,15 @@ TEST_F(AXRemoteHostTest, AutomationEnabled) {
std::unique_ptr<Widget> widget = CreateTestWidget();
remote->FlushForTesting();
+ // Tree ID is assigned.
+ std::string* tree_id_ptr =
+ widget->GetNativeWindow()->GetProperty(ui::kChildAXTreeID);
+ ASSERT_TRUE(tree_id_ptr);
+ ui::AXTreeID tree_id = ui::AXTreeID::FromString(*tree_id_ptr);
+ EXPECT_EQ(TestAXTreeID(), tree_id);
+
// Event was sent with initial hierarchy.
+ EXPECT_EQ(TestAXTreeID(), service.last_tree_id_);
EXPECT_EQ(ax::mojom::Event::kLoadComplete, service.last_event_.event_type);
EXPECT_EQ(AXAuraObjCache::GetInstance()->GetID(
widget->widget_delegate()->GetContentsView()),
@@ -165,13 +183,15 @@ TEST_F(AXRemoteHostTest, AutomationEnabledTwice) {
EXPECT_EQ(ax::mojom::Event::kLoadComplete, service.last_event_.event_type);
}
-// Views can trigger accessibility events during Widget construction before the
-// AXRemoteHost starts monitoring the widget. This happens with the material
-// design focus ring on text fields. Verify we don't crash in this case.
-// https://crbug.com/862759
-TEST_F(AXRemoteHostTest, SendEventBeforeWidgetCreated) {
+// Verifies that a remote app doesn't crash if a View triggers an accessibility
+// event before it is attached to a Widget. https://crbug.com/889121
+TEST_F(AXRemoteHostTest, SendEventOnViewWithNoWidget) {
TestAXHostService service(true /*automation_enabled*/);
AXRemoteHost* remote = CreateRemote(&service);
+ std::unique_ptr<Widget> widget = CreateTestWidget();
+ remote->FlushForTesting();
+
+ // Create a view that is not yet associated with the widget.
views::View view;
remote->HandleEvent(&view, ax::mojom::Event::kLocationChanged);
// No crash.
@@ -230,6 +250,9 @@ TEST_F(AXRemoteHostTest, PerformAction) {
// Create a view to sense the action.
TestView view;
+ view.SetBounds(0, 0, 100, 100);
+ std::unique_ptr<Widget> widget = CreateTestWidget();
+ widget->GetRootView()->AddChildView(&view);
AXAuraObjCache::GetInstance()->GetOrCreate(&view);
// Request an action on the view.
diff --git a/chromium/ui/views/mus/ax_tree_source_mus.cc b/chromium/ui/views/mus/ax_tree_source_mus.cc
index 7f767c443f6..6199fb3cabf 100644
--- a/chromium/ui/views/mus/ax_tree_source_mus.cc
+++ b/chromium/ui/views/mus/ax_tree_source_mus.cc
@@ -11,14 +11,17 @@
namespace views {
-AXTreeSourceMus::AXTreeSourceMus(AXAuraObjWrapper* root) : root_(root) {
+AXTreeSourceMus::AXTreeSourceMus(AXAuraObjWrapper* root,
+ const ui::AXTreeID& tree_id)
+ : root_(root), tree_id_(tree_id) {
DCHECK(root_);
+ DCHECK_NE(tree_id_, ui::AXTreeIDUnknown());
}
AXTreeSourceMus::~AXTreeSourceMus() = default;
bool AXTreeSourceMus::GetTreeData(ui::AXTreeData* tree_data) const {
- tree_data->tree_id = AXRemoteHost::kRemoteAXTreeID;
+ tree_data->tree_id = tree_id_;
return AXTreeSourceViews::GetTreeData(tree_data);
}
diff --git a/chromium/ui/views/mus/ax_tree_source_mus.h b/chromium/ui/views/mus/ax_tree_source_mus.h
index 6e3681e0773..6c9170747ed 100644
--- a/chromium/ui/views/mus/ax_tree_source_mus.h
+++ b/chromium/ui/views/mus/ax_tree_source_mus.h
@@ -6,6 +6,7 @@
#define UI_VIEWS_MUS_AX_TREE_SOURCE_MUS_H_
#include "base/macros.h"
+#include "ui/accessibility/ax_tree_id.h"
#include "ui/views/accessibility/ax_tree_source_views.h"
#include "ui/views/mus/mus_export.h"
@@ -20,7 +21,7 @@ class AXAuraObjWrapper;
class VIEWS_MUS_EXPORT AXTreeSourceMus : public AXTreeSourceViews {
public:
// |root| must outlive this object.
- explicit AXTreeSourceMus(AXAuraObjWrapper* root);
+ AXTreeSourceMus(AXAuraObjWrapper* root, const ui::AXTreeID& tree_id);
~AXTreeSourceMus() override;
void set_device_scale_factor(float scale) { device_scale_factor_ = scale; }
@@ -35,6 +36,9 @@ class VIEWS_MUS_EXPORT AXTreeSourceMus : public AXTreeSourceViews {
// The top-level object to use for the AX tree.
AXAuraObjWrapper* root_;
+ // ID to use for the AX tree.
+ const ui::AXTreeID tree_id_;
+
// The display device scale factor to use while serializing this update.
float device_scale_factor_ = 1.f;
diff --git a/chromium/ui/views/mus/ax_tree_source_mus_unittest.cc b/chromium/ui/views/mus/ax_tree_source_mus_unittest.cc
index 2f7bc9a6299..b4fbdd54ac4 100644
--- a/chromium/ui/views/mus/ax_tree_source_mus_unittest.cc
+++ b/chromium/ui/views/mus/ax_tree_source_mus_unittest.cc
@@ -51,6 +51,7 @@ class AXTreeSourceMusTest : public ViewsTestBase {
std::unique_ptr<Widget> widget_;
Label* label_ = nullptr; // Owned by views hierarchy.
+ const ui::AXTreeID ax_tree_id_ = ui::AXTreeID::FromString("123");
private:
DISALLOW_COPY_AND_ASSIGN(AXTreeSourceMusTest);
@@ -59,17 +60,17 @@ class AXTreeSourceMusTest : public ViewsTestBase {
TEST_F(AXTreeSourceMusTest, GetTreeData) {
AXAuraObjWrapper* root =
AXAuraObjCache::GetInstance()->GetOrCreate(widget_->GetContentsView());
- AXTreeSourceMus tree(root);
+ AXTreeSourceMus tree(root, ax_tree_id_);
ui::AXTreeData tree_data;
tree.GetTreeData(&tree_data);
- EXPECT_EQ(AXRemoteHost::kRemoteAXTreeID, tree_data.tree_id);
+ EXPECT_EQ(ax_tree_id_, tree_data.tree_id);
}
TEST_F(AXTreeSourceMusTest, Serialize) {
AXAuraObjCache* cache = AXAuraObjCache::GetInstance();
AXAuraObjWrapper* root = cache->GetOrCreate(widget_->GetContentsView());
- AXTreeSourceMus tree(root);
+ AXTreeSourceMus tree(root, ax_tree_id_);
EXPECT_EQ(root, tree.GetRoot());
// Serialize the root.
@@ -93,7 +94,7 @@ TEST_F(AXTreeSourceMusTest, ScaleFactor) {
AXAuraObjWrapper* root = cache->GetOrCreate(widget_->GetContentsView());
// Simulate serializing a widget on a high-dpi display.
- AXTreeSourceMus tree(root);
+ AXTreeSourceMus tree(root, ax_tree_id_);
tree.set_device_scale_factor(2.f);
// Serialize the root.
diff --git a/chromium/ui/views/mus/desktop_window_tree_host_mus.cc b/chromium/ui/views/mus/desktop_window_tree_host_mus.cc
index 93d30122d2a..61fd282fbb4 100644
--- a/chromium/ui/views/mus/desktop_window_tree_host_mus.cc
+++ b/chromium/ui/views/mus/desktop_window_tree_host_mus.cc
@@ -43,7 +43,7 @@ namespace views {
namespace {
// As the window manager renderers the non-client decorations this class does
-// very little but honor the client area insets from the window manager.
+// very little but honor kTopViewInset.
class ClientSideNonClientFrameView : public NonClientFrameView,
public aura::WindowObserver {
public:
@@ -53,16 +53,22 @@ class ClientSideNonClientFrameView : public NonClientFrameView,
// provided by the window manager.
GetViewAccessibility().set_is_ignored(true);
- observed_.Add(widget_->GetNativeWindow()->GetRootWindow());
+ // Initialize kTopViewInset to a default value. Further updates will come
+ // from Ash. This is necessary so that during app window creation,
+ // GetWindowBoundsForClientBounds() can calculate correctly.
+ const auto& values = views::WindowManagerFrameValues::instance();
+ widget->GetNativeWindow()->SetProperty(aura::client::kTopViewInset,
+ widget->IsMaximized()
+ ? values.maximized_insets.top()
+ : values.normal_insets.top());
+ observed_.Add(window());
}
~ClientSideNonClientFrameView() override {}
private:
- // Returns the default values of client area insets from the window manager.
- static gfx::Insets GetDefaultWindowManagerInsets(bool is_maximized) {
- const WindowManagerFrameValues& values =
- WindowManagerFrameValues::instance();
- return is_maximized ? values.maximized_insets : values.normal_insets;
+ gfx::Insets GetClientInsets() const {
+ const int top_inset = window()->GetProperty(aura::client::kTopViewInset);
+ return gfx::Insets(top_inset, 0, 0, 0);
}
// View:
@@ -75,7 +81,7 @@ class ClientSideNonClientFrameView : public NonClientFrameView,
gfx::Rect result(GetLocalBounds());
if (widget_->IsFullscreen())
return result;
- result.Inset(GetDefaultWindowManagerInsets(widget_->IsMaximized()));
+ result.Inset(GetClientInsets());
return result;
}
gfx::Rect GetWindowBoundsForClientBounds(
@@ -83,12 +89,9 @@ class ClientSideNonClientFrameView : public NonClientFrameView,
if (widget_->IsFullscreen())
return client_bounds;
- const gfx::Insets insets(
- GetDefaultWindowManagerInsets(widget_->IsMaximized()));
- return gfx::Rect(client_bounds.x() - insets.left(),
- client_bounds.y() - insets.top(),
- client_bounds.width() + insets.width(),
- client_bounds.height() + insets.height());
+ gfx::Rect outset_bounds = client_bounds;
+ outset_bounds.Inset(-GetClientInsets());
+ return outset_bounds;
}
int NonClientHitTest(const gfx::Point& point) override { return HTNOWHERE; }
void GetWindowMask(const gfx::Size& size, gfx::Path* window_mask) override {
@@ -136,20 +139,16 @@ class ClientSideNonClientFrameView : public NonClientFrameView,
void OnWindowPropertyChanged(aura::Window* window,
const void* key,
intptr_t old) override {
- // Do a re-layout on state changes which affect GetBoundsForClientView().
- // The associated bounds change would also cause a re-layout, but there may
- // not be a bounds change or it may come from the server before the state is
- // updated.
- if (key == aura::client::kShowStateKey) {
- if (GetBoundsForClientView() != widget_->client_view()->bounds() &&
- window->GetProperty(aura::client::kShowStateKey) !=
- ui::SHOW_STATE_MINIMIZED) {
- InvalidateLayout();
- widget_->GetRootView()->Layout();
- }
+ if (key == aura::client::kTopViewInset) {
+ InvalidateLayout();
+ widget_->GetRootView()->Layout();
}
}
+ aura::Window* window() const {
+ return widget_->GetNativeWindow()->GetRootWindow();
+ }
+
views::Widget* widget_;
ScopedObserver<aura::Window, aura::WindowObserver> observed_{this};
@@ -286,20 +285,6 @@ void DesktopWindowTreeHostMus::SendClientAreaToServer() {
std::vector<gfx::Rect>());
}
-void DesktopWindowTreeHostMus::SendHitTestMaskToServer() {
- if (!native_widget_delegate_->HasHitTestMask()) {
- aura::WindowPortMus::Get(window())->SetHitTestMask(base::nullopt);
- return;
- }
-
- gfx::Path mask_path;
- native_widget_delegate_->GetHitTestMask(&mask_path);
- // TODO(jamescook): Use the full path for the mask.
- gfx::Rect mask_rect =
- gfx::ToEnclosingRect(gfx::SkRectToRectF(mask_path.getBounds()));
- aura::WindowPortMus::Get(window())->SetHitTestMask(mask_rect);
-}
-
bool DesktopWindowTreeHostMus::IsFocusClientInstalledOnFocusSynchronizer()
const {
return MusClient::Get()
@@ -340,8 +325,11 @@ void DesktopWindowTreeHostMus::Init(const Widget::InitParams& params) {
window()->SetProperty(aura::client::kShowStateKey, params.show_state);
- if (!params.bounds.IsEmpty())
+ if (!params.bounds.IsEmpty()) {
+ // Init the scale now (before InitHost below), it is used by SetBoundsInDIP.
+ IntializeDeviceScaleFactor(GetDisplay().device_scale_factor());
SetBoundsInDIP(params.bounds);
+ }
cursor_manager_ = std::make_unique<wm::CursorManager>(
std::make_unique<NativeCursorManagerMus>(window()));
@@ -428,7 +416,6 @@ void DesktopWindowTreeHostMus::OnWidgetInitDone() {
// the NonClientView was created, which means we may not have sent the
// client-area and hit-test-mask.
SendClientAreaToServer();
- SendHitTestMaskToServer();
MusClient::Get()->OnCaptureClientSet(
aura::client::GetCaptureClient(window()));
@@ -871,7 +858,6 @@ void DesktopWindowTreeHostMus::OnWindowManagerFrameValuesChanged() {
}
SendClientAreaToServer();
- SendHitTestMaskToServer();
}
void DesktopWindowTreeHostMus::OnActiveFocusClientChanged(
@@ -946,7 +932,6 @@ void DesktopWindowTreeHostMus::OnViewBoundsChanged(views::View* observed_view) {
native_widget_delegate_->AsWidget()->non_client_view()->frame_view());
SendClientAreaToServer();
- SendHitTestMaskToServer();
}
void DesktopWindowTreeHostMus::OnViewIsDeleting(View* observed_view) {
diff --git a/chromium/ui/views/mus/desktop_window_tree_host_mus.h b/chromium/ui/views/mus/desktop_window_tree_host_mus.h
index a93e0c297ed..17c0655e987 100644
--- a/chromium/ui/views/mus/desktop_window_tree_host_mus.h
+++ b/chromium/ui/views/mus/desktop_window_tree_host_mus.h
@@ -49,7 +49,6 @@ class VIEWS_MUS_EXPORT DesktopWindowTreeHostMus
private:
void SendClientAreaToServer();
- void SendHitTestMaskToServer();
// Returns true if the FocusClient associated with our window is installed on
// the FocusSynchronizer.
diff --git a/chromium/ui/views/mus/desktop_window_tree_host_mus_unittest.cc b/chromium/ui/views/mus/desktop_window_tree_host_mus_unittest.cc
index 85bfbad2488..159770b5a1c 100644
--- a/chromium/ui/views/mus/desktop_window_tree_host_mus_unittest.cc
+++ b/chromium/ui/views/mus/desktop_window_tree_host_mus_unittest.cc
@@ -24,7 +24,6 @@
#include "ui/views/mus/mus_client.h"
#include "ui/views/mus/mus_client_test_api.h"
#include "ui/views/mus/screen_mus.h"
-#include "ui/views/mus/window_manager_frame_values.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
@@ -240,42 +239,24 @@ TEST_F(DesktopWindowTreeHostMusTest, ActivateBeforeShow) {
->active_focus_client());
}
-// Tests that changes to a widget's show state will cause the client area to be
-// updated.
-TEST_F(DesktopWindowTreeHostMusTest, ServerShowStateChangeUpdatesClientArea) {
- WindowManagerFrameValues test_frame_values;
- test_frame_values.normal_insets = {3, 0, 0, 0};
- test_frame_values.maximized_insets = {7, 0, 0, 0};
- WindowManagerFrameValues::SetInstance(test_frame_values);
-
+// Tests that changes to kTopViewInset will cause the client area to be updated.
+TEST_F(DesktopWindowTreeHostMusTest, ServerTopInsetChangeUpdatesClientArea) {
std::unique_ptr<Widget> widget(CreateWidget());
widget->Show();
- // Simulate state changes from the server.
- auto set_widget_state =
- [&widget](ui::WindowShowState state) {
- widget->GetNativeWindow()->GetRootWindow()->SetProperty(
- aura::client::kShowStateKey, state);
- };
-
- // A restored window respects normal_insets (the client area is inset from the
- // root view).
- gfx::Rect expected_restored_bounds = widget->GetRootView()->bounds();
- expected_restored_bounds.Inset(test_frame_values.normal_insets);
- EXPECT_EQ(expected_restored_bounds, widget->client_view()->bounds());
-
- // A fullscreen window has no insets.
- EXPECT_FALSE(widget->IsFullscreen());
- set_widget_state(ui::SHOW_STATE_FULLSCREEN);
- EXPECT_TRUE(widget->IsFullscreen());
+ auto set_top_inset = [&widget](int value) {
+ widget->GetNativeWindow()->GetRootWindow()->SetProperty(
+ aura::client::kTopViewInset, value);
+ };
+
EXPECT_EQ(widget->GetRootView()->bounds(), widget->client_view()->bounds());
- // A maximized window respects maximized_insets.
- gfx::Rect expected_maximized_bounds = widget->GetRootView()->bounds();
- expected_maximized_bounds.Inset(test_frame_values.maximized_insets);
- set_widget_state(ui::SHOW_STATE_MAXIMIZED);
- EXPECT_FALSE(widget->IsFullscreen());
- EXPECT_EQ(expected_maximized_bounds, widget->client_view()->bounds());
+ set_top_inset(3);
+ gfx::Rect root_bounds = widget->GetRootView()->bounds();
+ root_bounds.Inset(gfx::Insets(3, 0, 0, 0));
+
+ set_top_inset(0);
+ EXPECT_EQ(widget->GetRootView()->bounds(), widget->client_view()->bounds());
}
TEST_F(DesktopWindowTreeHostMusTest, CursorClientDuringTearDown) {
diff --git a/chromium/ui/views/mus/drag_interactive_uitest.cc b/chromium/ui/views/mus/drag_interactive_uitest.cc
index 999ec9e269a..92dc07d7a7d 100644
--- a/chromium/ui/views/mus/drag_interactive_uitest.cc
+++ b/chromium/ui/views/mus/drag_interactive_uitest.cc
@@ -86,24 +86,24 @@ class TargetView : public views::View {
DISALLOW_COPY_AND_ASSIGN(TargetView);
};
-std::unique_ptr<ui::PointerEvent> CreateMouseMoveEvent(int x, int y) {
- return std::make_unique<ui::PointerEvent>(ui::MouseEvent(
+std::unique_ptr<ui::MouseEvent> CreateMouseMoveEvent(int x, int y) {
+ return std::make_unique<ui::MouseEvent>(
ui::ET_MOUSE_MOVED, gfx::Point(x, y), gfx::Point(x, y),
- ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_NONE));
+ ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON, ui::EF_NONE);
}
-std::unique_ptr<ui::PointerEvent> CreateMouseDownEvent(int x, int y) {
- return std::make_unique<ui::PointerEvent>(
- ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(x, y), gfx::Point(x, y),
- ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
- ui::EF_LEFT_MOUSE_BUTTON));
+std::unique_ptr<ui::MouseEvent> CreateMouseDownEvent(int x, int y) {
+ return std::make_unique<ui::MouseEvent>(
+ ui::ET_MOUSE_PRESSED, gfx::Point(x, y), gfx::Point(x, y),
+ ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
+ ui::EF_LEFT_MOUSE_BUTTON);
}
-std::unique_ptr<ui::PointerEvent> CreateMouseUpEvent(int x, int y) {
- return std::make_unique<ui::PointerEvent>(
- ui::MouseEvent(ui::ET_MOUSE_RELEASED, gfx::Point(x, y), gfx::Point(x, y),
- ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
- ui::EF_LEFT_MOUSE_BUTTON));
+std::unique_ptr<ui::MouseEvent> CreateMouseUpEvent(int x, int y) {
+ return std::make_unique<ui::MouseEvent>(
+ ui::ET_MOUSE_RELEASED, gfx::Point(x, y), gfx::Point(x, y),
+ ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
+ ui::EF_LEFT_MOUSE_BUTTON);
}
} // namespace
diff --git a/chromium/ui/views/mus/mus_client.cc b/chromium/ui/views/mus/mus_client.cc
index 4678479162a..4bed24086c3 100644
--- a/chromium/ui/views/mus/mus_client.cc
+++ b/chromium/ui/views/mus/mus_client.cc
@@ -270,7 +270,7 @@ MusClient::ConfigurePropertiesFromParams(
// TODO(crbug.com/667566): Support additional scales or gfx::Image[Skia].
gfx::ImageSkia app_icon = init_params.delegate->GetWindowAppIcon();
- SkBitmap app_bitmap = app_icon.GetRepresentation(1.f).sk_bitmap();
+ SkBitmap app_bitmap = app_icon.GetRepresentation(1.f).GetBitmap();
if (!app_bitmap.isNull()) {
properties[WindowManager::kAppIcon_Property] =
mojo::ConvertTo<TransportType>(app_bitmap);
@@ -278,7 +278,7 @@ MusClient::ConfigurePropertiesFromParams(
// TODO(crbug.com/667566): Support additional scales or gfx::Image[Skia].
gfx::ImageSkia window_icon = init_params.delegate->GetWindowIcon();
- SkBitmap window_bitmap = window_icon.GetRepresentation(1.f).sk_bitmap();
+ SkBitmap window_bitmap = window_icon.GetRepresentation(1.f).GetBitmap();
if (!window_bitmap.isNull()) {
properties[WindowManager::kWindowIcon_Property] =
mojo::ConvertTo<TransportType>(window_bitmap);
diff --git a/chromium/ui/views/mus/mus_views_delegate.cc b/chromium/ui/views/mus/mus_views_delegate.cc
index e383ac00d69..6456b0d31d7 100644
--- a/chromium/ui/views/mus/mus_views_delegate.cc
+++ b/chromium/ui/views/mus/mus_views_delegate.cc
@@ -6,6 +6,7 @@
#include "ui/views/mus/ax_remote_host.h"
#include "ui/views/mus/mus_client.h"
+#include "ui/views/mus/pointer_watcher_event_router.h"
namespace views {
@@ -19,4 +20,19 @@ void MusViewsDelegate::NotifyAccessibilityEvent(View* view,
MusClient::Get()->ax_remote_host()->HandleEvent(view, event_type);
}
+void MusViewsDelegate::AddPointerWatcher(PointerWatcher* pointer_watcher,
+ bool wants_moves) {
+ MusClient::Get()->pointer_watcher_event_router()->AddPointerWatcher(
+ pointer_watcher, wants_moves);
+}
+
+void MusViewsDelegate::RemovePointerWatcher(PointerWatcher* pointer_watcher) {
+ MusClient::Get()->pointer_watcher_event_router()->RemovePointerWatcher(
+ pointer_watcher);
+}
+
+bool MusViewsDelegate::IsPointerWatcherSupported() const {
+ return true;
+}
+
} // namespace views
diff --git a/chromium/ui/views/mus/mus_views_delegate.h b/chromium/ui/views/mus/mus_views_delegate.h
index b7d55503ac1..6346df2979b 100644
--- a/chromium/ui/views/mus/mus_views_delegate.h
+++ b/chromium/ui/views/mus/mus_views_delegate.h
@@ -20,6 +20,10 @@ class VIEWS_MUS_EXPORT MusViewsDelegate : public ViewsDelegate {
// ViewsDelegate:
void NotifyAccessibilityEvent(View* view,
ax::mojom::Event event_type) override;
+ void AddPointerWatcher(PointerWatcher* pointer_watcher,
+ bool wants_moves) override;
+ void RemovePointerWatcher(PointerWatcher* pointer_watcher) override;
+ bool IsPointerWatcherSupported() const override;
private:
LayoutProvider layout_provider_;
diff --git a/chromium/ui/views/mus/remote_view/remote_view_host.cc b/chromium/ui/views/mus/remote_view/remote_view_host.cc
index a203d2b14fd..a0fc60681e3 100644
--- a/chromium/ui/views/mus/remote_view/remote_view_host.cc
+++ b/chromium/ui/views/mus/remote_view/remote_view_host.cc
@@ -15,7 +15,14 @@
namespace views {
-RemoteViewHost::RemoteViewHost() = default;
+RemoteViewHost::RemoteViewHost()
+ : embedding_root_(std::make_unique<aura::Window>(nullptr)) {
+ embedding_root_->set_owned_by_parent(false);
+ embedding_root_->SetName("RemoteViewHostWindow");
+ embedding_root_->SetType(aura::client::WINDOW_TYPE_CONTROL);
+ embedding_root_->Init(ui::LAYER_NOT_DRAWN);
+}
+
RemoteViewHost::~RemoteViewHost() = default;
void RemoteViewHost::EmbedUsingToken(const base::UnguessableToken& embed_token,
@@ -29,29 +36,11 @@ void RemoteViewHost::EmbedUsingToken(const base::UnguessableToken& embed_token,
embed_callback_ = std::move(callback);
if (GetWidget())
- CreateEmbeddingRoot();
+ EmbedImpl();
}
-void RemoteViewHost::CreateEmbeddingRoot() {
- // Should not be attached to anything.
- DCHECK(!native_view());
-
- // There is a pending embed request.
- DCHECK(!embed_token_.is_empty());
-
- embedding_root_ = std::make_unique<aura::Window>(nullptr);
- embedding_root_->set_owned_by_parent(false);
-
- embedding_root_->SetName("RemoteViewHostWindow");
- embedding_root_->SetProperty(aura::client::kEmbedType,
- aura::client::WindowEmbedType::EMBED_IN_OWNER);
- embedding_root_->SetType(aura::client::WINDOW_TYPE_CONTROL);
- embedding_root_->Init(ui::LAYER_NOT_DRAWN);
-
- // Must happen before EmbedUsingToken call for window server to figure out
- // the relevant display.
- Attach(embedding_root_.get());
-
+void RemoteViewHost::EmbedImpl() {
+ DCHECK(IsEmbedPending());
aura::WindowPortMus::Get(embedding_root_.get())
->EmbedUsingToken(embed_token_, embed_flags_,
base::BindOnce(&RemoteViewHost::OnEmbedResult,
@@ -60,17 +49,17 @@ void RemoteViewHost::CreateEmbeddingRoot() {
void RemoteViewHost::OnEmbedResult(bool success) {
LOG_IF(ERROR, !success) << "Failed to embed, token=" << embed_token_;
-
- if (!success && embedding_root_)
- embedding_root_.reset();
-
+ embed_token_ = {};
if (embed_callback_)
std::move(embed_callback_).Run(success);
}
void RemoteViewHost::AddedToWidget() {
- if (!native_view() && !embed_token_.is_empty())
- CreateEmbeddingRoot();
+ if (native_view())
+ return;
+ Attach(embedding_root_.get());
+ if (IsEmbedPending())
+ EmbedImpl();
}
} // namespace views
diff --git a/chromium/ui/views/mus/remote_view/remote_view_host.h b/chromium/ui/views/mus/remote_view/remote_view_host.h
index 44b1552f325..2a3e4530124 100644
--- a/chromium/ui/views/mus/remote_view/remote_view_host.h
+++ b/chromium/ui/views/mus/remote_view/remote_view_host.h
@@ -36,8 +36,10 @@ class RemoteViewHost : public views::NativeViewHost {
EmbedCallback callback);
private:
+ bool IsEmbedPending() const { return !embed_token_.is_empty(); }
+
// Creates the embedding aura::Window and attach to it.
- void CreateEmbeddingRoot();
+ void EmbedImpl();
// Invoked after the embed operation.
void OnEmbedResult(bool success);
@@ -49,7 +51,7 @@ class RemoteViewHost : public views::NativeViewHost {
int embed_flags_ = 0;
EmbedCallback embed_callback_;
- std::unique_ptr<aura::Window> embedding_root_;
+ const std::unique_ptr<aura::Window> embedding_root_;
base::WeakPtrFactory<RemoteViewHost> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(RemoteViewHost);
diff --git a/chromium/ui/views/mus/remote_view/remote_view_host_unittest.cc b/chromium/ui/views/mus/remote_view/remote_view_host_unittest.cc
index 611c00151cd..30db5c39f9a 100644
--- a/chromium/ui/views/mus/remote_view/remote_view_host_unittest.cc
+++ b/chromium/ui/views/mus/remote_view/remote_view_host_unittest.cc
@@ -80,21 +80,20 @@ class RemoteViewHostTest : public aura::test::AuraTestBase {
DISALLOW_COPY_AND_ASSIGN(RemoteViewHostTest);
};
-// Tests that the embed operation fails with an unknown token and RemoteViewHost
-// will not be attached.
+// Tests that the embed operation fails with an unknown token.
TEST_F(RemoteViewHostTest, BadEmbed) {
const base::UnguessableToken unknown_token = base::UnguessableToken::Create();
// Ownership will be passed to |widget| later.
RemoteViewHost* host = new RemoteViewHost();
std::unique_ptr<views::Widget> widget = CreateTestWidget(host);
- EXPECT_FALSE(host->native_view());
+ EXPECT_TRUE(host->native_view());
// Embed fails with unknown token.
EXPECT_FALSE(Embed(host, unknown_token));
- // |host| is not attached after adding to a widget.
- EXPECT_FALSE(host->native_view());
+ // |host| is still attached despite the Embed failure.
+ EXPECT_TRUE(host->native_view());
}
// Tests when RemoveViewHost is added to a widget before embedding.
@@ -105,15 +104,15 @@ TEST_F(RemoteViewHostTest, AddToWidgetBeforeEmbed) {
// Ownership will be passed to |widget| later.
RemoteViewHost* host = new RemoteViewHost();
- // |host| is not attached because embed operation is not performed.
+ // |host| is not attached until the widget is created.
EXPECT_FALSE(host->native_view());
std::unique_ptr<views::Widget> widget = CreateTestWidget(host);
- EXPECT_FALSE(host->native_view());
+ EXPECT_TRUE(host->native_view());
// Embed succeeds.
EXPECT_TRUE(Embed(host, token));
- // |host| is now attached to the embedding window.
+ // |host| is still attached to the embedding window.
EXPECT_TRUE(host->native_view());
}
diff --git a/chromium/ui/views/mus/views_mus_test_suite.cc b/chromium/ui/views/mus/views_mus_test_suite.cc
index 40dafe4c9db..1beddbf9de8 100644
--- a/chromium/ui/views/mus/views_mus_test_suite.cc
+++ b/chromium/ui/views/mus/views_mus_test_suite.cc
@@ -14,7 +14,6 @@
#include "base/run_loop.h"
#include "base/synchronization/waitable_event.h"
#include "base/threading/simple_thread.h"
-#include "base/threading/thread.h"
#include "mojo/core/embedder/embedder.h"
#include "mojo/core/embedder/scoped_ipc_support.h"
#include "services/catalog/catalog.h"
@@ -68,24 +67,18 @@ class DefaultService : public service_manager::Service {
class ServiceManagerConnection {
public:
ServiceManagerConnection()
- : thread_("Persistent service_manager connections"),
- ipc_thread_("IPC thread") {
+ : thread_("Persistent service_manager connections") {
catalog::Catalog::LoadDefaultCatalogManifest(
base::FilePath(kCatalogFilename));
- mojo::core::Init();
- ipc_thread_.StartWithOptions(
- base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
- ipc_support_ = std::make_unique<mojo::core::ScopedIPCSupport>(
- ipc_thread_.task_runner(),
- mojo::core::ScopedIPCSupport::ShutdownPolicy::CLEAN);
-
base::WaitableEvent wait(base::WaitableEvent::ResetPolicy::AUTOMATIC,
base::WaitableEvent::InitialState::NOT_SIGNALED);
base::Thread::Options options;
thread_.StartWithOptions(options);
thread_.task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&ServiceManagerConnection::SetUpConnections,
- base::Unretained(this), &wait));
+ FROM_HERE,
+ base::BindOnce(
+ &ServiceManagerConnection::SetUpConnectionsOnBackgroundThread,
+ base::Unretained(this), &wait));
wait.Wait();
}
@@ -94,8 +87,9 @@ class ServiceManagerConnection {
base::WaitableEvent::InitialState::NOT_SIGNALED);
thread_.task_runner()->PostTask(
FROM_HERE,
- base::BindOnce(&ServiceManagerConnection::TearDownConnections,
- base::Unretained(this), &wait));
+ base::BindOnce(
+ &ServiceManagerConnection::TearDownConnectionsOnBackgroundThread,
+ base::Unretained(this), &wait));
wait.Wait();
}
@@ -124,7 +118,7 @@ class ServiceManagerConnection {
wait->Signal();
}
- void SetUpConnections(base::WaitableEvent* wait) {
+ void SetUpConnectionsOnBackgroundThread(base::WaitableEvent* wait) {
background_service_manager_ =
std::make_unique<service_manager::BackgroundServiceManager>(nullptr,
nullptr);
@@ -140,8 +134,9 @@ class ServiceManagerConnection {
wait->Signal();
}
- void TearDownConnections(base::WaitableEvent* wait) {
+ void TearDownConnectionsOnBackgroundThread(base::WaitableEvent* wait) {
context_.reset();
+ background_service_manager_.reset();
wait->Signal();
}
@@ -155,8 +150,6 @@ class ServiceManagerConnection {
}
base::Thread thread_;
- base::Thread ipc_thread_;
- std::unique_ptr<mojo::core::ScopedIPCSupport> ipc_support_;
std::unique_ptr<service_manager::BackgroundServiceManager>
background_service_manager_;
std::unique_ptr<service_manager::ServiceContext> context_;
@@ -226,7 +219,7 @@ std::unique_ptr<PlatformTestHelper> CreatePlatformTestHelper() {
} // namespace
ViewsMusTestSuite::ViewsMusTestSuite(int argc, char** argv)
- : ViewsTestSuite(argc, argv) {}
+ : ViewsTestSuite(argc, argv), ipc_thread_("IPC thread") {}
ViewsMusTestSuite::~ViewsMusTestSuite() {}
@@ -248,6 +241,13 @@ void ViewsMusTestSuite::Initialize() {
switches::kEnableFeatures, features::kMash.name);
PlatformTestHelper::set_factory(base::Bind(&CreatePlatformTestHelper));
+
+ mojo::core::Init();
+ ipc_thread_.StartWithOptions(
+ base::Thread::Options(base::MessageLoop::TYPE_IO, 0));
+ ipc_support_ = std::make_unique<mojo::core::ScopedIPCSupport>(
+ ipc_thread_.task_runner(),
+ mojo::core::ScopedIPCSupport::ShutdownPolicy::CLEAN);
}
void ViewsMusTestSuite::InitializeEnv() {
diff --git a/chromium/ui/views/mus/views_mus_test_suite.h b/chromium/ui/views/mus/views_mus_test_suite.h
index 4dc9d09dc07..8490ab91912 100644
--- a/chromium/ui/views/mus/views_mus_test_suite.h
+++ b/chromium/ui/views/mus/views_mus_test_suite.h
@@ -9,8 +9,15 @@
#include "base/macros.h"
#include "base/test/scoped_feature_list.h"
+#include "base/threading/thread.h"
#include "ui/views/views_test_suite.h"
+namespace mojo {
+namespace core {
+class ScopedIPCSupport;
+}
+} // namespace mojo
+
namespace views {
class ViewsMusTestSuite : public ViewsTestSuite {
@@ -24,6 +31,9 @@ class ViewsMusTestSuite : public ViewsTestSuite {
void InitializeEnv() override;
void DestroyEnv() override;
+ base::Thread ipc_thread_;
+ std::unique_ptr<mojo::core::ScopedIPCSupport> ipc_support_;
+
base::test::ScopedFeatureList feature_list_;
std::unique_ptr<aura::Env> env_;
diff --git a/chromium/ui/views/painter.cc b/chromium/ui/views/painter.cc
index 24bb9e2a566..da297c1a02b 100644
--- a/chromium/ui/views/painter.cc
+++ b/chromium/ui/views/painter.cc
@@ -31,7 +31,9 @@ class SolidRoundRectPainter : public Painter {
SolidRoundRectPainter(SkColor bg_color,
SkColor stroke_color,
float radius,
- const gfx::Insets& insets);
+ const gfx::Insets& insets,
+ SkBlendMode blend_mode,
+ bool antialias);
~SolidRoundRectPainter() override;
// Painter:
@@ -43,6 +45,8 @@ class SolidRoundRectPainter : public Painter {
const SkColor stroke_color_;
const float radius_;
const gfx::Insets insets_;
+ const SkBlendMode blend_mode_;
+ const bool antialias_;
DISALLOW_COPY_AND_ASSIGN(SolidRoundRectPainter);
};
@@ -50,11 +54,15 @@ class SolidRoundRectPainter : public Painter {
SolidRoundRectPainter::SolidRoundRectPainter(SkColor bg_color,
SkColor stroke_color,
float radius,
- const gfx::Insets& insets)
+ const gfx::Insets& insets,
+ SkBlendMode blend_mode,
+ bool antialias)
: bg_color_(bg_color),
stroke_color_(stroke_color),
radius_(radius),
- insets_(insets) {}
+ insets_(insets),
+ blend_mode_(blend_mode),
+ antialias_(antialias) {}
SolidRoundRectPainter::~SolidRoundRectPainter() {}
@@ -68,20 +76,27 @@ void SolidRoundRectPainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
gfx::Rect inset_rect(size);
inset_rect.Inset(insets_);
- gfx::RectF border_rect_f(gfx::ScaleToEnclosingRect(inset_rect, scale));
- const SkScalar scaled_corner_radius = SkFloatToScalar(radius_ * scale);
+ gfx::RectF fill_rect(gfx::ScaleToEnclosingRect(inset_rect, scale));
+ gfx::RectF stroke_rect = fill_rect;
+ float scaled_radius = radius_ * scale;
cc::PaintFlags flags;
- flags.setAntiAlias(true);
+ flags.setBlendMode(blend_mode_);
+ if (antialias_)
+ flags.setAntiAlias(true);
flags.setStyle(cc::PaintFlags::kFill_Style);
flags.setColor(bg_color_);
- canvas->DrawRoundRect(border_rect_f, scaled_corner_radius, flags);
-
- border_rect_f.Inset(gfx::InsetsF(0.5f));
- flags.setStyle(cc::PaintFlags::kStroke_Style);
- flags.setStrokeWidth(1);
- flags.setColor(stroke_color_);
- canvas->DrawRoundRect(border_rect_f, scaled_corner_radius, flags);
+ canvas->DrawRoundRect(fill_rect, scaled_radius, flags);
+
+ if (stroke_color_ != SK_ColorTRANSPARENT) {
+ constexpr float kStrokeWidth = 1.0f;
+ stroke_rect.Inset(gfx::InsetsF(kStrokeWidth / 2));
+ scaled_radius -= kStrokeWidth / 2;
+ flags.setStyle(cc::PaintFlags::kStroke_Style);
+ flags.setStrokeWidth(kStrokeWidth);
+ flags.setColor(stroke_color_);
+ canvas->DrawRoundRect(stroke_rect, scaled_radius, flags);
+ }
}
// DashedFocusPainter ----------------------------------------------------------
@@ -266,18 +281,22 @@ void Painter::PaintFocusPainter(View* view,
std::unique_ptr<Painter> Painter::CreateSolidRoundRectPainter(
SkColor color,
float radius,
- const gfx::Insets& insets) {
- return std::make_unique<SolidRoundRectPainter>(color, SK_ColorTRANSPARENT,
- radius, insets);
+ const gfx::Insets& insets,
+ SkBlendMode blend_mode,
+ bool antialias) {
+ return std::make_unique<SolidRoundRectPainter>(
+ color, SK_ColorTRANSPARENT, radius, insets, blend_mode, antialias);
}
// static
std::unique_ptr<Painter> Painter::CreateRoundRectWith1PxBorderPainter(
SkColor bg_color,
SkColor stroke_color,
- float radius) {
- return std::make_unique<SolidRoundRectPainter>(bg_color, stroke_color, radius,
- gfx::Insets());
+ float radius,
+ SkBlendMode blend_mode,
+ bool antialias) {
+ return std::make_unique<SolidRoundRectPainter>(
+ bg_color, stroke_color, radius, gfx::Insets(), blend_mode, antialias);
}
// static
diff --git a/chromium/ui/views/painter.h b/chromium/ui/views/painter.h
index cb3f495dc8d..984348ee13a 100644
--- a/chromium/ui/views/painter.h
+++ b/chromium/ui/views/painter.h
@@ -11,6 +11,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
+#include "third_party/skia/include/core/SkBlendMode.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/base/nine_image_painter_factory.h"
#include "ui/gfx/geometry/insets.h"
@@ -57,14 +58,18 @@ class VIEWS_EXPORT Painter {
static std::unique_ptr<Painter> CreateSolidRoundRectPainter(
SkColor color,
float radius,
- const gfx::Insets& insets = gfx::Insets());
+ const gfx::Insets& insets = gfx::Insets(),
+ SkBlendMode blend_mode = SkBlendMode::kSrcOver,
+ bool antialias = true);
// Creates a painter that draws a RoundRect with a solid color and a given
// corner radius, and also adds a 1px border (inset) in the given color.
static std::unique_ptr<Painter> CreateRoundRectWith1PxBorderPainter(
SkColor bg_color,
SkColor stroke_color,
- float radius);
+ float radius,
+ SkBlendMode blend_mode = SkBlendMode::kSrcOver,
+ bool antialias = true);
// Creates a painter that divides |image| into nine regions. The four corners
// are rendered at the size specified in insets (eg. the upper-left corner is
diff --git a/chromium/ui/views/touchui/touch_selection_controller_impl.cc b/chromium/ui/views/touchui/touch_selection_controller_impl.cc
index ae97f1994e4..5264dfe5712 100644
--- a/chromium/ui/views/touchui/touch_selection_controller_impl.cc
+++ b/chromium/ui/views/touchui/touch_selection_controller_impl.cc
@@ -1,10 +1,9 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// Copyright 2018 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
#include "ui/views/touchui/touch_selection_controller_impl.h"
-#include "base/macros.h"
#include "base/metrics/histogram_macros.h"
#include "base/time/time.h"
#include "ui/aura/client/cursor_client.h"
@@ -19,6 +18,7 @@
#include "ui/gfx/image/image.h"
#include "ui/gfx/path.h"
#include "ui/resources/grit/ui_resources.h"
+#include "ui/views/views_delegate.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/wm/core/coordinate_conversion.h"
@@ -74,14 +74,14 @@ const int kSelectionHandleBarBottomAllowance = 3;
// Creates a widget to host SelectionHandleView.
views::Widget* CreateTouchSelectionPopupWidget(
- gfx::NativeView context,
+ gfx::NativeView parent,
views::WidgetDelegate* widget_delegate) {
views::Widget* widget = new views::Widget;
views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
params.shadow_type = views::Widget::InitParams::SHADOW_TYPE_NONE;
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- params.parent = context;
+ params.parent = parent;
params.delegate = widget_delegate;
widget->Init(params);
return widget;
@@ -202,34 +202,6 @@ gfx::Rect BoundToRect(const gfx::SelectionBound& bound) {
bound.edge_bottom_rounded());
}
-// A WindowTargeter that insets the top of the touch handle's hit-test region.
-// This ensures that the client receives touch events above the painted image.
-// The widget extends its height to handle touch events below the painted image.
-class TouchHandleWindowTargeter : public aura::WindowTargeter {
- public:
- explicit TouchHandleWindowTargeter(aura::Window* window) : window_(window) {}
- ~TouchHandleWindowTargeter() override = default;
-
- void SetTopInset(int inset) { SetInsets(gfx::Insets(inset, 0, 0, 0)); }
-
- // aura::WindowTargeter:
- void OnSetInsets(const gfx::Insets& last_mouse_extend,
- const gfx::Insets& last_touch_extend) override {
- // Send the targeter insets to the window service if this is a mus client.
- // This helps the window service send events directly to the text window.
- // OnSetInsets is generally only called when the insets actually change.
- if (window_->env()->mode() == aura::Env::Mode::MUS) {
- gfx::Rect mask(window_->bounds().size());
- mask.Inset(touch_extend());
- aura::WindowPortMus::Get(window_->GetRootWindow())->SetHitTestMask(mask);
- }
- }
-
- private:
- aura::Window* window_;
- DISALLOW_COPY_AND_ASSIGN(TouchHandleWindowTargeter);
-};
-
} // namespace
namespace views {
@@ -238,20 +210,24 @@ using EditingHandleView = TouchSelectionControllerImpl::EditingHandleView;
// A View that displays the text selection handle.
class TouchSelectionControllerImpl::EditingHandleView
- : public views::WidgetDelegateView {
+ : public WidgetDelegateView {
public:
EditingHandleView(TouchSelectionControllerImpl* controller,
- gfx::NativeView context,
+ gfx::NativeView parent,
bool is_cursor_handle)
: controller_(controller),
image_(GetCenterHandleImage()),
is_cursor_handle_(is_cursor_handle),
draw_invisible_(false),
weak_ptr_factory_(this) {
- widget_.reset(CreateTouchSelectionPopupWidget(context, this));
+ widget_.reset(CreateTouchSelectionPopupWidget(parent, this));
+ targeter_ = new aura::WindowTargeter();
aura::Window* window = widget_->GetNativeWindow();
- targeter_ = new TouchHandleWindowTargeter(window);
+ // For Mus clients, adjust targeting of the handle's client root window,
+ // constructed by the window server for the handle's "content" window.
+ if (window->env()->mode() == aura::Env::Mode::MUS)
+ window = window->GetRootWindow();
window->SetEventTargeter(std::unique_ptr<aura::WindowTargeter>(targeter_));
// We are owned by the TouchSelectionControllerImpl.
@@ -264,12 +240,12 @@ class TouchSelectionControllerImpl::EditingHandleView
return selection_bound_.type();
}
- // Overridden from views::WidgetDelegateView:
+ // WidgetDelegateView:
void DeleteDelegate() override {
// We are owned and deleted by TouchSelectionControllerImpl.
}
- // Overridden from views::View:
+ // View:
void OnPaint(gfx::Canvas* canvas) override {
if (draw_invisible_)
return;
@@ -379,8 +355,10 @@ class TouchSelectionControllerImpl::EditingHandleView
selection_bound_.SetEdge(gfx::PointF(edge_top), gfx::PointF(edge_bottom));
}
- targeter_->SetTopInset(selection_bound_.GetHeight() +
- kSelectionHandleVerticalVisualOffset);
+ const gfx::Insets insets(
+ selection_bound_.GetHeight() + kSelectionHandleVerticalVisualOffset, 0,
+ 0, 0);
+ targeter_->SetInsets(insets, insets);
}
void SetDrawInvisible(bool draw_invisible) {
@@ -394,11 +372,11 @@ class TouchSelectionControllerImpl::EditingHandleView
std::unique_ptr<Widget> widget_;
TouchSelectionControllerImpl* controller_;
- // A custom targeter that shifts the hit-test target below the apparent bounds
+ // A WindowTargeter that shifts the hit-test target below the apparent bounds
// to make dragging easier. The |widget_|'s NativeWindow takes ownership over
// the |targeter_| but since the |widget_|'s lifetime is known to this class,
// it can safely access the |targeter_|.
- TouchHandleWindowTargeter* targeter_;
+ aura::WindowTargeter* targeter_;
// In local coordinates
gfx::SelectionBound selection_bound_;
@@ -427,23 +405,20 @@ class TouchSelectionControllerImpl::EditingHandleView
TouchSelectionControllerImpl::TouchSelectionControllerImpl(
ui::TouchEditable* client_view)
: client_view_(client_view),
- client_widget_(nullptr),
- selection_handle_1_(new EditingHandleView(this,
- client_view->GetNativeView(),
- false)),
- selection_handle_2_(new EditingHandleView(this,
- client_view->GetNativeView(),
- false)),
- cursor_handle_(new EditingHandleView(this,
- client_view->GetNativeView(),
- true)),
- command_executed_(false),
- dragging_handle_(nullptr) {
+ selection_handle_1_(
+ new EditingHandleView(this, client_view->GetNativeView(), false)),
+ selection_handle_2_(
+ new EditingHandleView(this, client_view->GetNativeView(), false)),
+ cursor_handle_(
+ new EditingHandleView(this, client_view->GetNativeView(), true)) {
selection_start_time_ = base::TimeTicks::Now();
aura::Window* client_window = client_view_->GetNativeView();
client_widget_ = Widget::GetTopLevelWidgetForNativeView(client_window);
+ // Observe client widget moves and resizes to update the selection handles.
if (client_widget_)
client_widget_->AddObserver(this);
+ if (ViewsDelegate::GetInstance()->IsPointerWatcherSupported())
+ ViewsDelegate::GetInstance()->AddPointerWatcher(this, true);
aura::Env::GetInstance()->AddPreTargetHandler(this);
}
@@ -452,6 +427,8 @@ TouchSelectionControllerImpl::~TouchSelectionControllerImpl() {
command_executed_);
HideQuickMenu();
aura::Env::GetInstance()->RemovePreTargetHandler(this);
+ if (ViewsDelegate::GetInstance()->IsPointerWatcherSupported())
+ ViewsDelegate::GetInstance()->RemovePointerWatcher(this);
if (client_widget_)
client_widget_->RemoveObserver(this);
}
@@ -649,6 +626,18 @@ void TouchSelectionControllerImpl::OnWidgetBoundsChanged(
SelectionChanged();
}
+void TouchSelectionControllerImpl::OnPointerEventObserved(
+ const ui::PointerEvent& event,
+ const gfx::Point& location_in_screen,
+ gfx::NativeView target) {
+ // Disregard CursorClient::IsMouseEventsEnabled, it is disabled for touch
+ // events in this client, but not re-enabled for mouse events sent elsewhere.
+ if (event.pointer_details().pointer_type ==
+ ui::EventPointerType::POINTER_TYPE_MOUSE) {
+ client_view_->DestroyTouchSelection();
+ }
+}
+
void TouchSelectionControllerImpl::OnKeyEvent(ui::KeyEvent* event) {
client_view_->DestroyTouchSelection();
}
@@ -773,11 +762,11 @@ gfx::Rect TouchSelectionControllerImpl::GetExpectedHandleBounds(
return GetSelectionWidgetBounds(bound);
}
-views::WidgetDelegateView* TouchSelectionControllerImpl::GetHandle1View() {
+WidgetDelegateView* TouchSelectionControllerImpl::GetHandle1View() {
return selection_handle_1_.get();
}
-views::WidgetDelegateView* TouchSelectionControllerImpl::GetHandle2View() {
+WidgetDelegateView* TouchSelectionControllerImpl::GetHandle2View() {
return selection_handle_2_.get();
}
diff --git a/chromium/ui/views/touchui/touch_selection_controller_impl.h b/chromium/ui/views/touchui/touch_selection_controller_impl.h
index cf222421548..7e231e126e1 100644
--- a/chromium/ui/views/touchui/touch_selection_controller_impl.h
+++ b/chromium/ui/views/touchui/touch_selection_controller_impl.h
@@ -1,9 +1,9 @@
-// Copyright (c) 2013 The Chromium Authors. All rights reserved.
+// 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_UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_
-#define UI_UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_
+#ifndef UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_
+#define UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_
#include "base/macros.h"
#include "base/timer/timer.h"
@@ -11,6 +11,7 @@
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/selection_bound.h"
#include "ui/touch_selection/touch_selection_menu_runner.h"
+#include "ui/views/pointer_watcher.h"
#include "ui/views/view.h"
#include "ui/views/views_export.h"
#include "ui/views/widget/widget_observer.h"
@@ -29,17 +30,16 @@ class VIEWS_EXPORT TouchSelectionControllerImpl
: public ui::TouchEditingControllerDeprecated,
public ui::TouchSelectionMenuClient,
public WidgetObserver,
+ public PointerWatcher,
public ui::EventHandler {
public:
class EditingHandleView;
- // Use TextSelectionController::create().
- explicit TouchSelectionControllerImpl(
- ui::TouchEditable* client_view);
-
+ // Use ui::TouchEditingControllerFactory::Create() instead.
+ explicit TouchSelectionControllerImpl(ui::TouchEditable* client_view);
~TouchSelectionControllerImpl() override;
- // TextSelectionController.
+ // ui::TouchEditingControllerDeprecated:
void SelectionChanged() override;
bool IsHandleDragInProgress() override;
void HideHandles(bool quick) override;
@@ -70,19 +70,22 @@ class VIEWS_EXPORT TouchSelectionControllerImpl
// |bound| should be the clipped version of the selection bound.
bool ShouldShowHandleFor(const gfx::SelectionBound& bound) const;
- // Overridden from ui::TouchSelectionMenuClient.
+ // ui::TouchSelectionMenuClient:
bool IsCommandIdEnabled(int command_id) const override;
void ExecuteCommand(int command_id, int event_flags) override;
void RunContextMenu() override;
- // Overridden from WidgetObserver. We will observe the widget backing the
- // |client_view_| so that when its moved/resized, we can update the selection
- // handles appropriately.
+ // WidgetObserver:
void OnWidgetClosing(Widget* widget) override;
void OnWidgetBoundsChanged(Widget* widget,
const gfx::Rect& new_bounds) override;
- // Overriden from ui::EventHandler.
+ // PointerWatcher:
+ void OnPointerEventObserved(const ui::PointerEvent& event,
+ const gfx::Point& location_in_screen,
+ gfx::NativeView target) override;
+
+ // ui::EventHandler:
void OnKeyEvent(ui::KeyEvent* event) override;
void OnMouseEvent(ui::MouseEvent* event) override;
void OnScrollEvent(ui::ScrollEvent* event) override;
@@ -112,15 +115,15 @@ class VIEWS_EXPORT TouchSelectionControllerImpl
bool IsSelectionHandle2Visible();
bool IsCursorHandleVisible();
gfx::Rect GetExpectedHandleBounds(const gfx::SelectionBound& bound);
- views::WidgetDelegateView* GetHandle1View();
- views::WidgetDelegateView* GetHandle2View();
+ WidgetDelegateView* GetHandle1View();
+ WidgetDelegateView* GetHandle2View();
ui::TouchEditable* client_view_;
- Widget* client_widget_;
+ Widget* client_widget_ = nullptr;
std::unique_ptr<EditingHandleView> selection_handle_1_;
std::unique_ptr<EditingHandleView> selection_handle_2_;
std::unique_ptr<EditingHandleView> cursor_handle_;
- bool command_executed_;
+ bool command_executed_ = false;
base::TimeTicks selection_start_time_;
// Timer to trigger quick menu (Quick menu is not shown if the selection
@@ -129,7 +132,7 @@ class VIEWS_EXPORT TouchSelectionControllerImpl
base::OneShotTimer quick_menu_timer_;
// Pointer to the SelectionHandleView being dragged during a drag session.
- EditingHandleView* dragging_handle_;
+ EditingHandleView* dragging_handle_ = nullptr;
// In cursor mode, the two selection bounds are the same and correspond to
// |cursor_handle_|; otherwise, they correspond to |selection_handle_1_| and
@@ -148,4 +151,4 @@ class VIEWS_EXPORT TouchSelectionControllerImpl
} // namespace views
-#endif // UI_UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_
+#endif // UI_VIEWS_TOUCHUI_TOUCH_SELECTION_CONTROLLER_IMPL_H_
diff --git a/chromium/ui/views/view.cc b/chromium/ui/views/view.cc
index d238fad21fd..d0aba92898f 100644
--- a/chromium/ui/views/view.cc
+++ b/chromium/ui/views/view.cc
@@ -311,7 +311,7 @@ bool View::Contains(const View* view) const {
}
int View::GetIndexOf(const View* view) const {
- Views::const_iterator i(std::find(children_.begin(), children_.end(), view));
+ auto i(std::find(children_.begin(), children_.end(), view));
return i != children_.end() ? static_cast<int>(i - children_.begin()) : -1;
}
@@ -1191,6 +1191,13 @@ void View::ConvertEventToTarget(ui::EventTarget* target,
event->ConvertLocationToTarget(this, static_cast<View*>(target));
}
+gfx::PointF View::GetScreenLocationF(const ui::LocatedEvent& event) const {
+ DCHECK_EQ(this, event.target());
+ gfx::Point screen_location(event.location());
+ ConvertPointToScreen(this, &screen_location);
+ return gfx::PointF(screen_location);
+}
+
// Accelerators ----------------------------------------------------------------
void View::AddAccelerator(const ui::Accelerator& accelerator) {
@@ -1209,8 +1216,7 @@ void View::RemoveAccelerator(const ui::Accelerator& accelerator) {
return;
}
- std::vector<ui::Accelerator>::iterator i(
- std::find(accelerators_->begin(), accelerators_->end(), accelerator));
+ auto i(std::find(accelerators_->begin(), accelerators_->end(), accelerator));
if (i == accelerators_->end()) {
NOTREACHED() << "Removing non-existing accelerator";
return;
@@ -2204,7 +2210,7 @@ void View::BoundsChanged(const gfx::Rect& previous_bounds) {
// Notify interested Views that visible bounds within the root view may have
// changed.
if (descendants_to_notify_.get()) {
- for (Views::iterator i(descendants_to_notify_->begin());
+ for (auto i(descendants_to_notify_->begin());
i != descendants_to_notify_->end(); ++i) {
(*i)->OnVisibleBoundsChanged();
}
@@ -2254,8 +2260,8 @@ void View::AddDescendantToNotify(View* view) {
void View::RemoveDescendantToNotify(View* view) {
DCHECK(view && descendants_to_notify_.get());
- Views::iterator i(std::find(
- descendants_to_notify_->begin(), descendants_to_notify_->end(), view));
+ auto i(std::find(descendants_to_notify_->begin(),
+ descendants_to_notify_->end(), view));
DCHECK(i != descendants_to_notify_->end());
descendants_to_notify_->erase(i);
if (descendants_to_notify_->empty())
diff --git a/chromium/ui/views/view.h b/chromium/ui/views/view.h
index 4248609dd3c..161e015c044 100644
--- a/chromium/ui/views/view.h
+++ b/chromium/ui/views/view.h
@@ -888,6 +888,7 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
ui::EventTargeter* GetEventTargeter() override;
void ConvertEventToTarget(ui::EventTarget* target,
ui::LocatedEvent* event) override;
+ gfx::PointF GetScreenLocationF(const ui::LocatedEvent& event) const override;
// Overridden from ui::EventHandler:
void OnKeyEvent(ui::KeyEvent* event) override;
diff --git a/chromium/ui/views/view_properties.cc b/chromium/ui/views/view_properties.cc
index e55acc0ca94..2f4f54e35ff 100644
--- a/chromium/ui/views/view_properties.cc
+++ b/chromium/ui/views/view_properties.cc
@@ -20,6 +20,8 @@ DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT, gfx::Insets*);
DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT,
views::BubbleDialogDelegateView*);
+DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT, gfx::Path*);
+
namespace views {
DEFINE_UI_CLASS_PROPERTY_KEY(int, kHitTestComponentKey, HTNOWHERE);
@@ -27,5 +29,6 @@ DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::Insets, kMarginsKey, nullptr);
DEFINE_UI_CLASS_PROPERTY_KEY(views::BubbleDialogDelegateView*,
kAnchoredDialogKey,
nullptr);
+DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::Path, kHighlightPathKey, nullptr);
} // namespace views
diff --git a/chromium/ui/views/view_properties.h b/chromium/ui/views/view_properties.h
index 2896ee94512..5f63c1b902d 100644
--- a/chromium/ui/views/view_properties.h
+++ b/chromium/ui/views/view_properties.h
@@ -10,6 +10,7 @@
namespace gfx {
class Insets;
+class Path;
} // namespace gfx
namespace views {
@@ -30,6 +31,12 @@ VIEWS_EXPORT extern const ui::ClassProperty<gfx::Insets*>* const kMarginsKey;
VIEWS_EXPORT extern const ui::ClassProperty<BubbleDialogDelegateView*>* const
kAnchoredDialogKey;
+// A property to store a highlight path related to the view. This is nominally
+// used by the default inkdrop and focus ring that are both used to highlight
+// the view in different ways.
+VIEWS_EXPORT extern const ui::ClassProperty<gfx::Path*>* const
+ kHighlightPathKey;
+
} // namespace views
// Declaring the template specialization here to make sure that the
@@ -40,5 +47,5 @@ VIEWS_EXPORT extern const ui::ClassProperty<BubbleDialogDelegateView*>* const
DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT, gfx::Insets*);
DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT,
views::BubbleDialogDelegateView*);
-
+DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT, gfx::Path*);
#endif // UI_VIEWS_VIEW_PROPERTIES_H_
diff --git a/chromium/ui/views/views_delegate.cc b/chromium/ui/views/views_delegate.cc
index 846e579237c..d580fde1f8b 100644
--- a/chromium/ui/views/views_delegate.cc
+++ b/chromium/ui/views/views_delegate.cc
@@ -48,8 +48,7 @@ ViewsDelegate* ViewsDelegate::GetInstance() {
void ViewsDelegate::SaveWindowPlacement(const Widget* widget,
const std::string& window_name,
const gfx::Rect& bounds,
- ui::WindowShowState show_state) {
-}
+ ui::WindowShowState show_state) {}
bool ViewsDelegate::GetSavedWindowPlacement(
const Widget* widget,
@@ -66,8 +65,7 @@ void ViewsDelegate::NotifyMenuItemFocused(const base::string16& menu_name,
const base::string16& menu_item_name,
int item_index,
int item_count,
- bool has_submenu) {
-}
+ bool has_submenu) {}
ViewsDelegate::ProcessMenuAcceleratorResult
ViewsDelegate::ProcessAcceleratorWhileMenuShowing(
@@ -98,20 +96,14 @@ NonClientFrameView* ViewsDelegate::CreateDefaultNonClientFrameView(
return nullptr;
}
-void ViewsDelegate::AddRef() {
-}
+void ViewsDelegate::AddRef() {}
-void ViewsDelegate::ReleaseRef() {
-}
+void ViewsDelegate::ReleaseRef() {}
void ViewsDelegate::OnBeforeWidgetInit(
Widget::InitParams* params,
internal::NativeWidgetDelegate* delegate) {}
-base::TimeDelta ViewsDelegate::GetTextfieldPasswordRevealDuration() {
- return base::TimeDelta();
-}
-
bool ViewsDelegate::WindowManagerProvidesTitleBar(bool maximized) {
return false;
}
@@ -140,4 +132,16 @@ bool ViewsDelegate::ShouldMirrorArrowsInRTL() const {
return true;
}
+void ViewsDelegate::AddPointerWatcher(PointerWatcher*, bool) {
+ NOTREACHED();
+}
+
+void ViewsDelegate::RemovePointerWatcher(PointerWatcher*) {
+ NOTREACHED();
+}
+
+bool ViewsDelegate::IsPointerWatcherSupported() const {
+ return false;
+}
+
} // namespace views
diff --git a/chromium/ui/views/views_delegate.h b/chromium/ui/views/views_delegate.h
index 3f16d177c21..b5237c3f20f 100644
--- a/chromium/ui/views/views_delegate.h
+++ b/chromium/ui/views/views_delegate.h
@@ -23,10 +23,6 @@
#include "ui/views/views_export.h"
#include "ui/views/widget/widget.h"
-namespace base {
-class TimeDelta;
-}
-
namespace gfx {
class ImageSkia;
class Rect;
@@ -34,13 +30,14 @@ class Rect;
namespace ui {
class ContextFactory;
+class TouchEditingControllerFactory;
}
namespace views {
class NativeWidget;
class NonClientFrameView;
-class ViewsTouchEditingControllerFactory;
+class PointerWatcher;
class View;
class Widget;
@@ -173,9 +170,6 @@ class VIEWS_EXPORT ViewsDelegate {
virtual void OnBeforeWidgetInit(Widget::InitParams* params,
internal::NativeWidgetDelegate* delegate);
- // Returns the password reveal duration for Textfield.
- virtual base::TimeDelta GetTextfieldPasswordRevealDuration();
-
// Returns true if the operating system's window manager will always provide a
// title bar with caption buttons (ignoring the setting to
// |remove_standard_frame| in InitParams). If |maximized|, this applies to
@@ -206,11 +200,18 @@ class VIEWS_EXPORT ViewsDelegate {
// opens in the opposite direction.
virtual bool ShouldMirrorArrowsInRTL() const;
+ // Allows lower-level views components to use Mus-only PointerWatcher wiring.
+ // TODO(crbug.com/887725): Support PointerWatcher without mus, refactor.
+ virtual void AddPointerWatcher(PointerWatcher* pointer_watcher,
+ bool wants_moves);
+ virtual void RemovePointerWatcher(PointerWatcher* pointer_watcher);
+ virtual bool IsPointerWatcherSupported() const;
+
protected:
ViewsDelegate();
private:
- std::unique_ptr<ViewsTouchEditingControllerFactory>
+ std::unique_ptr<ui::TouchEditingControllerFactory>
editing_controller_factory_;
#if defined(USE_AURA)
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_capture_client.cc b/chromium/ui/views/widget/desktop_aura/desktop_capture_client.cc
index 86578b995a2..38447dc9ae0 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_capture_client.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_capture_client.cc
@@ -79,8 +79,7 @@ void DesktopCaptureClient::SetCapture(aura::Window* new_capture_window) {
// Notify the other roots that we got capture. This is important so that
// they reset state.
CaptureClients capture_clients(*capture_clients_);
- for (CaptureClients::iterator i = capture_clients.begin();
- i != capture_clients.end(); ++i) {
+ for (auto i = capture_clients.begin(); i != capture_clients.end(); ++i) {
if (*i != this) {
aura::client::CaptureDelegate* delegate =
(*i)->root_->GetHost()->dispatcher();
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc
index 00073d3d3bf..f0da4f88142 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc
@@ -450,8 +450,7 @@ void DesktopDragDropClientAuraX11::X11DragContext::ReadActions() {
int DesktopDragDropClientAuraX11::X11DragContext::GetDragOperation() const {
int drag_operation = ui::DragDropTypes::DRAG_NONE;
- for (std::vector<::Atom>::const_iterator it = actions_.begin();
- it != actions_.end(); ++it) {
+ for (auto it = actions_.begin(); it != actions_.end(); ++it) {
MaskOperation(*it, &drag_operation);
}
@@ -711,7 +710,7 @@ void DesktopDragDropClientAuraX11::OnXdndDrop(
}
if (!IsDragDropInProgress()) {
- UMA_HISTOGRAM_COUNTS("Event.DragDrop.ExternalOriginDrop", 1);
+ UMA_HISTOGRAM_COUNTS_1M("Event.DragDrop.ExternalOriginDrop", 1);
}
drag_operation = delegate->OnPerformDrop(event);
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc
index a6fe148e3d2..f60cc49e7ab 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc
@@ -354,8 +354,7 @@ void TestDragDropClient::SetTopmostXWindowAndMoveMouse(::Window xid) {
}
void TestDragDropClient::SendXClientEvent(::Window xid, XEvent* event) {
- std::map< ::Window, ClientMessageEventCollector*>::iterator it =
- collectors_.find(xid);
+ auto it = collectors_.find(xid);
if (it != collectors_.end())
it->second->RecordEvent(event->xclient);
}
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_drop_target_win.cc b/chromium/ui/views/widget/desktop_aura/desktop_drop_target_win.cc
index 99c525f3219..094a0b00bce 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_drop_target_win.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_drop_target_win.cc
@@ -99,7 +99,7 @@ DWORD DesktopDropTargetWin::OnDrop(IDataObject* data_object,
DragDropClient* client = aura::client::GetDragDropClient(root_window_);
if (client && !client->IsDragDropInProgress() &&
drag_operation != ui::DragDropTypes::DRAG_NONE) {
- UMA_HISTOGRAM_COUNTS("Event.DragDrop.ExternalOriginDrop", 1);
+ UMA_HISTOGRAM_COUNTS_1M("Event.DragDrop.ExternalOriginDrop", 1);
}
}
if (target_window_) {
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc b/chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc
index 5d4ae7a9805..d0731338684 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_native_cursor_manager.cc
@@ -51,7 +51,7 @@ void DesktopNativeCursorManager::SetCursor(
delegate->CommitCursor(new_cursor);
if (delegate->IsCursorVisible()) {
- for (Hosts::const_iterator i = hosts_.begin(); i != hosts_.end(); ++i)
+ for (auto i = hosts_.begin(); i != hosts_.end(); ++i)
(*i)->SetCursor(new_cursor);
}
}
@@ -66,11 +66,11 @@ void DesktopNativeCursorManager::SetVisibility(
} else {
gfx::NativeCursor invisible_cursor(ui::CursorType::kNone);
cursor_loader_->SetPlatformCursor(&invisible_cursor);
- for (Hosts::const_iterator i = hosts_.begin(); i != hosts_.end(); ++i)
+ for (auto i = hosts_.begin(); i != hosts_.end(); ++i)
(*i)->SetCursor(invisible_cursor);
}
- for (Hosts::const_iterator i = hosts_.begin(); i != hosts_.end(); ++i)
+ for (auto i = hosts_.begin(); i != hosts_.end(); ++i)
(*i)->OnCursorVisibilityChanged(visible);
}
@@ -90,7 +90,7 @@ void DesktopNativeCursorManager::SetMouseEventsEnabled(
SetVisibility(delegate->IsCursorVisible(), delegate);
- for (Hosts::const_iterator i = hosts_.begin(); i != hosts_.end(); ++i)
+ for (auto i = hosts_.begin(); i != hosts_.end(); ++i)
(*i)->dispatcher()->OnMouseEventsEnableStateChanged(enabled);
}
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
index 01a429a67e3..264858b3a46 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc
@@ -595,11 +595,15 @@ const ui::Layer* DesktopNativeWidgetAura::GetLayer() const {
}
void DesktopNativeWidgetAura::ReorderNativeViews() {
+ if (!content_window_)
+ return;
+
// Reordering native views causes multiple changes to the window tree.
- // Instantiate a ScopedPauseOcclusionTracking to recompute occlusion once at
- // the end of this scope rather than after each individual change.
+ // Instantiate a ScopedPause to recompute occlusion once at the end of this
+ // scope rather than after each individual change.
// https://crbug.com/829918
- aura::WindowOcclusionTracker::ScopedPauseOcclusionTracking pause_occlusion;
+ aura::WindowOcclusionTracker::ScopedPause pause_occlusion(
+ content_window_->env());
window_reorderer_->ReorderChildWindows();
}
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc
index 9d4d564ee7a..2514071e8bd 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura_unittest.cc
@@ -17,7 +17,6 @@
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/test/window_occlusion_tracker_test_api.h"
#include "ui/aura/window.h"
-#include "ui/aura/window_occlusion_tracker.h"
#include "ui/aura/window_tree_host.h"
#include "ui/display/screen.h"
#include "ui/events/event_processor.h"
@@ -312,7 +311,7 @@ TEST_F(DesktopNativeWidgetAuraTest, ReorderDoesntRecomputeOcclusion) {
parent.Show();
aura::Window* parent_window = parent.GetNativeWindow();
- aura::WindowOcclusionTracker::Track(parent_window);
+ parent_window->TrackOcclusionState();
View* contents_view = parent.GetContentsView();
@@ -335,7 +334,8 @@ TEST_F(DesktopNativeWidgetAuraTest, ReorderDoesntRecomputeOcclusion) {
contents_view->AddChildView(host_view3);
// Reorder child views. Expect occlusion to only be recomputed once.
- aura::test::WindowOcclusionTrackerTestApi window_occlusion_tracker_test_api;
+ aura::test::WindowOcclusionTrackerTestApi window_occlusion_tracker_test_api(
+ parent_window->env());
const int num_times_occlusion_recomputed =
window_occlusion_tracker_test_api.GetNumTimesOcclusionRecomputed();
contents_view->ReorderChildView(host_view3, 0);
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_ozone.cc b/chromium/ui/views/widget/desktop_aura/desktop_screen_ozone.cc
index a5e871e8dae..6dd57cd7454 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_ozone.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_ozone.cc
@@ -4,6 +4,7 @@
#include "ui/views/widget/desktop_aura/desktop_screen_ozone.h"
+#include "ui/aura/screen_ozone.h"
#include "ui/display/display.h"
#include "ui/display/types/display_constants.h"
#include "ui/display/types/display_snapshot.h"
@@ -55,7 +56,16 @@ void DesktopScreenOzone::OnDisplaySnapshotsInvalidated() {}
//////////////////////////////////////////////////////////////////////////////
display::Screen* CreateDesktopScreen() {
- return new DesktopScreenOzone;
+ auto platform_screen = ui::OzonePlatform::GetInstance()->CreateScreen();
+ if (!platform_screen) {
+ // TODO: At the moment, only the Ozone/Headless uses this patch. Fix it:
+ // https://crbug.com/891613
+ LOG(ERROR) << "PlatformScreen is not implemented for this ozone platform. "
+ "Falling back to old DesktopScreenOzone implementation. See "
+ "https://crbug.com/872339 for details";
+ return new DesktopScreenOzone;
+ }
+ return new aura::ScreenOzone(std::move(platform_screen));
}
} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc
index e90710c2c39..0951d2fb5b9 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc
@@ -232,8 +232,7 @@ display::Display DesktopScreenX11::GetDisplayNearestPoint(
const gfx::Point& point) const {
if (displays_.size() <= 1)
return GetPrimaryDisplay();
- for (std::vector<display::Display>::const_iterator it = displays_.begin();
- it != displays_.end(); ++it) {
+ for (auto it = displays_.begin(); it != displays_.end(); ++it) {
if (it->bounds().Contains(point))
return *it;
}
@@ -244,8 +243,7 @@ display::Display DesktopScreenX11::GetDisplayMatching(
const gfx::Rect& match_rect) const {
int max_area = 0;
const display::Display* matching = NULL;
- for (std::vector<display::Display>::const_iterator it = displays_.begin();
- it != displays_.end(); ++it) {
+ for (auto it = displays_.begin(); it != displays_.end(); ++it) {
gfx::Rect intersect = gfx::IntersectRects(it->bounds(), match_rect);
int area = intersect.width() * intersect.height();
if (area > max_area) {
@@ -450,7 +448,7 @@ std::vector<display::Display> DesktopScreenX11::BuildDisplaysFromXRandRInfo() {
if (monitor_iter != output_to_monitor.end() && monitor_iter->second == 0)
monitor_order_primary_display_index = displays.size();
- if (!display::Display::HasForceColorProfile()) {
+ if (!display::Display::HasForceDisplayColorProfile()) {
gfx::ICCProfile icc_profile = GetICCProfileForMonitor(
monitor_iter == output_to_monitor.end() ? 0 : monitor_iter->second);
icc_profile.HistogramDisplay(display.id());
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
index dcf1d7d40c2..fbfa8df1f7d 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
@@ -6,13 +6,16 @@
#include "ui/aura/client/drag_drop_client.h"
#include "ui/aura/client/transient_window_client.h"
+#include "ui/base/hit_test.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/platform_window/platform_window.h"
+#include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h"
#include "ui/platform_window/platform_window_init_properties.h"
#include "ui/views/corewm/tooltip_aura.h"
#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
+#include "ui/views/widget/desktop_aura/window_event_filter.h"
#include "ui/views/widget/widget_aura_utils.h"
#include "ui/views/window/native_frame_view.h"
#include "ui/wm/core/window_util.h"
@@ -91,6 +94,19 @@ void DesktopWindowTreeHostPlatform::Init(const Widget::InitParams& params) {
void DesktopWindowTreeHostPlatform::OnNativeWidgetCreated(
const Widget::InitParams& params) {
native_widget_delegate_->OnNativeWidgetCreated(true);
+
+ // Setup a non_client_window_event_filter, which handles resize/move, double
+ // click and other events.
+ DCHECK(!non_client_window_event_filter_);
+ std::unique_ptr<WindowEventFilter> window_event_filter =
+ std::make_unique<WindowEventFilter>(this);
+ auto* wm_move_resize_handler = GetWmMoveResizeHandler(*platform_window());
+ if (wm_move_resize_handler)
+ window_event_filter->SetWmMoveResizeHandler(
+ GetWmMoveResizeHandler(*(platform_window())));
+
+ non_client_window_event_filter_ = std::move(window_event_filter);
+ window()->AddPreTargetHandler(non_client_window_event_filter_.get());
}
void DesktopWindowTreeHostPlatform::OnWidgetInitDone() {}
@@ -135,6 +151,8 @@ void DesktopWindowTreeHostPlatform::CloseNow() {
if (!weak_ref || got_on_closed_)
return;
+ RemoveNonClientEventFilter();
+
native_widget_delegate_->OnNativeWidgetDestroying();
got_on_closed_ = true;
@@ -449,7 +467,34 @@ bool DesktopWindowTreeHostPlatform::ShouldCreateVisibilityController() const {
return true;
}
+void DesktopWindowTreeHostPlatform::DispatchEvent(ui::Event* event) {
+#if defined(USE_OZONE)
+ // Make sure the |event| is marked as a non-client if it's a non-client
+ // mouse down event. This is needed to make sure the WindowEventDispatcher
+ // does not set a |mouse_pressed_handler_| for such events, because they are
+ // not always followed with non-client mouse up events in case of
+ // Ozone/Wayland or Ozone/X11.
+ //
+ // Also see the comment in WindowEventDispatcher::PreDispatchMouseEvent..
+ aura::Window* content_window = desktop_native_widget_aura_->content_window();
+ if (content_window && content_window->delegate()) {
+ if (event->IsMouseEvent()) {
+ ui::MouseEvent* mouse_event = event->AsMouseEvent();
+ int flags = mouse_event->flags();
+ int hit_test_code = content_window->delegate()->GetNonClientComponent(
+ mouse_event->location());
+ if (hit_test_code != HTCLIENT && hit_test_code != HTNOWHERE)
+ flags |= ui::EF_IS_NON_CLIENT;
+ mouse_event->set_flags(flags);
+ }
+ }
+#endif
+
+ WindowTreeHostPlatform::DispatchEvent(event);
+}
+
void DesktopWindowTreeHostPlatform::OnClosed() {
+ RemoveNonClientEventFilter();
got_on_closed_ = true;
desktop_native_widget_aura_->OnHostClosed();
}
@@ -492,6 +537,14 @@ void DesktopWindowTreeHostPlatform::Relayout() {
widget->GetRootView()->Layout();
}
+void DesktopWindowTreeHostPlatform::RemoveNonClientEventFilter() {
+ if (!non_client_window_event_filter_)
+ return;
+
+ window()->RemovePreTargetHandler(non_client_window_event_filter_.get());
+ non_client_window_event_filter_.reset();
+}
+
Widget* DesktopWindowTreeHostPlatform::GetWidget() {
return native_widget_delegate_->AsWidget();
}
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h
index b6219dd00a7..e0b98abdaf0 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h
@@ -12,6 +12,8 @@
namespace views {
+class WindowEventFilter;
+
class VIEWS_EXPORT DesktopWindowTreeHostPlatform
: public aura::WindowTreeHostPlatform,
public DesktopWindowTreeHost {
@@ -90,14 +92,19 @@ class VIEWS_EXPORT DesktopWindowTreeHostPlatform
bool ShouldCreateVisibilityController() const override;
// WindowTreeHostPlatform:
+ void DispatchEvent(ui::Event* event) override;
void OnClosed() override;
void OnWindowStateChanged(ui::PlatformWindowState new_state) override;
void OnCloseRequest() override;
void OnActivationChanged(bool active) override;
private:
+ FRIEND_TEST_ALL_PREFIXES(DesktopWindowTreeHostPlatformTest, HitTest);
+
void Relayout();
+ void RemoveNonClientEventFilter();
+
Widget* GetWidget();
gfx::Rect ToDIPRect(const gfx::Rect& rect_in_pixels) const;
@@ -113,6 +120,9 @@ class VIEWS_EXPORT DesktopWindowTreeHostPlatform
bool is_active_ = false;
+ // A handler for events intended for non client area.
+ std::unique_ptr<WindowEventFilter> non_client_window_event_filter_;
+
base::WeakPtrFactory<DesktopWindowTreeHostPlatform> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(DesktopWindowTreeHostPlatform);
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform_interactive_uitest.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform_interactive_uitest.cc
new file mode 100644
index 00000000000..f959917fcfe
--- /dev/null
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform_interactive_uitest.cc
@@ -0,0 +1,272 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h"
+
+#include "ui/aura/window_tree_host_platform.h"
+#include "ui/base/hit_test.h"
+#include "ui/platform_window/platform_window.h"
+#include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h"
+#include "ui/views/test/views_interactive_ui_test_base.h"
+#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
+#include "ui/views/widget/desktop_aura/window_event_filter.h"
+#include "ui/views/widget/widget_delegate.h"
+#include "ui/views/window/native_frame_view.h"
+
+namespace views {
+
+namespace {
+
+bool IsNonClientComponent(int hittest) {
+ switch (hittest) {
+ case HTBOTTOM:
+ case HTBOTTOMLEFT:
+ case HTBOTTOMRIGHT:
+ case HTCAPTION:
+ case HTLEFT:
+ case HTRIGHT:
+ case HTTOP:
+ case HTTOPLEFT:
+ case HTTOPRIGHT:
+ return true;
+ default:
+ return false;
+ }
+ return true;
+}
+
+// A fake handler, which just stores the hittest and pointer location values.
+class FakeWmMoveResizeHandler : public ui::WmMoveResizeHandler {
+ public:
+ using SetBoundsCallback = base::RepeatingCallback<void(gfx::Rect)>;
+ explicit FakeWmMoveResizeHandler(ui::PlatformWindow* window)
+ : platform_window_(window), hittest_(-1) {}
+ ~FakeWmMoveResizeHandler() override = default;
+
+ void Reset() {
+ hittest_ = -1;
+ pointer_location_ = gfx::Point();
+ }
+
+ int hittest() const { return hittest_; }
+ gfx::Point pointer_location() const { return pointer_location_; }
+
+ void set_bounds(const gfx::Rect& bounds) { bounds_ = bounds; }
+
+ // ui::WmMoveResizeHandler
+ void DispatchHostWindowDragMovement(
+ int hittest,
+ const gfx::Point& pointer_location) override {
+ hittest_ = hittest;
+ pointer_location_ = pointer_location;
+
+ platform_window_->SetBounds(bounds_);
+ }
+
+ private:
+ ui::PlatformWindow* platform_window_;
+ gfx::Rect bounds_;
+
+ int hittest_ = -1;
+ gfx::Point pointer_location_;
+
+ DISALLOW_COPY_AND_ASSIGN(FakeWmMoveResizeHandler);
+};
+
+void SetExpectationBasedOnHittestValue(int hittest,
+ const FakeWmMoveResizeHandler& handler,
+ const gfx::Point& pointer_location) {
+ if (IsNonClientComponent(hittest)) {
+ // Ensure both the pointer location and the hit test value are passed to the
+ // fake move/resize handler.
+ EXPECT_EQ(handler.pointer_location().ToString(),
+ pointer_location.ToString());
+ EXPECT_EQ(handler.hittest(), hittest);
+ return;
+ }
+
+ // Ensure the handler does not receive the hittest value or the pointer
+ // location.
+ EXPECT_TRUE(handler.pointer_location().IsOrigin());
+ EXPECT_NE(handler.hittest(), hittest);
+}
+
+// This is used to return a customized result to NonClientHitTest.
+class HitTestNonClientFrameView : public NativeFrameView {
+ public:
+ explicit HitTestNonClientFrameView(Widget* widget)
+ : NativeFrameView(widget), hit_test_result_(HTNOWHERE) {}
+ ~HitTestNonClientFrameView() override {}
+
+ void set_hit_test_result(int component) { hit_test_result_ = component; }
+
+ // NonClientFrameView overrides:
+ int NonClientHitTest(const gfx::Point& point) override {
+ return hit_test_result_;
+ }
+
+ private:
+ int hit_test_result_;
+
+ DISALLOW_COPY_AND_ASSIGN(HitTestNonClientFrameView);
+};
+
+// This is used to return HitTestNonClientFrameView on create call.
+class HitTestWidgetDelegate : public views::WidgetDelegate {
+ public:
+ HitTestWidgetDelegate(views::Widget* widget,
+ HitTestNonClientFrameView* frame_view)
+ : widget_(widget), frame_view_(frame_view) {}
+ ~HitTestWidgetDelegate() override {}
+
+ void set_can_resize(bool can_resize) {
+ can_resize_ = can_resize;
+ widget_->OnSizeConstraintsChanged();
+ }
+
+ // views::WidgetDelegate:
+ bool CanResize() const override { return can_resize_; }
+ views::Widget* GetWidget() override { return widget_; }
+ views::Widget* GetWidget() const override { return widget_; }
+ views::NonClientFrameView* CreateNonClientFrameView(Widget* widget) override {
+ return frame_view_;
+ }
+
+ private:
+ views::Widget* widget_;
+ HitTestNonClientFrameView* frame_view_;
+ bool can_resize_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(HitTestWidgetDelegate);
+};
+
+} // namespace
+
+class DesktopWindowTreeHostPlatformTest : public ViewsInteractiveUITestBase {
+ public:
+ DesktopWindowTreeHostPlatformTest() = default;
+ ~DesktopWindowTreeHostPlatformTest() override = default;
+
+ protected:
+ Widget* BuildTopLevelDesktopWidget(const gfx::Rect& bounds) {
+ Widget* toplevel = new Widget;
+ frame_view_ = new HitTestNonClientFrameView(toplevel);
+ delegate_ = new HitTestWidgetDelegate(toplevel, frame_view_);
+ Widget::InitParams toplevel_params =
+ CreateParams(Widget::InitParams::TYPE_WINDOW);
+ toplevel_params.native_widget =
+ new views::DesktopNativeWidgetAura(toplevel);
+ toplevel_params.delegate = delegate_;
+ toplevel_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ toplevel_params.bounds = bounds;
+ toplevel_params.remove_standard_frame = true;
+ toplevel->Init(toplevel_params);
+ return toplevel;
+ }
+
+ std::unique_ptr<ui::MouseEvent> CreateMouseEvent(
+ const gfx::Point& pointer_location,
+ ui::EventType event_type,
+ int flags) {
+ std::unique_ptr<ui::MouseEvent> mouse_event =
+ std::make_unique<ui::MouseEvent>(event_type, pointer_location,
+ pointer_location,
+ base::TimeTicks::Now(), flags, flags);
+ return mouse_event;
+ }
+
+ HitTestNonClientFrameView* frame_view_ = nullptr;
+ HitTestWidgetDelegate* delegate_ = nullptr;
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DesktopWindowTreeHostPlatformTest);
+};
+
+TEST_F(DesktopWindowTreeHostPlatformTest, HitTest) {
+ gfx::Rect bounds(0, 0, 100, 100);
+ std::unique_ptr<Widget> widget(BuildTopLevelDesktopWidget(bounds));
+ widget->Show();
+
+ aura::Window* window = widget->GetNativeWindow();
+ DesktopWindowTreeHostPlatform* host =
+ static_cast<DesktopWindowTreeHostPlatform*>(window->GetHost());
+
+ // Install a fake move/resize handler to intercept the move/resize call.
+ WindowEventFilter* non_client_filter =
+ host->non_client_window_event_filter_.get();
+ std::unique_ptr<FakeWmMoveResizeHandler> handler =
+ std::make_unique<FakeWmMoveResizeHandler>(host->platform_window());
+ non_client_filter->SetWmMoveResizeHandler(handler.get());
+
+ delegate_->set_can_resize(true);
+
+ // It is not important to use pointer locations corresponding to the hittests
+ // values used in the browser itself, because we fake the hit test results,
+ // which non client frame view sends back. Thus, just make sure the content
+ // window is able to receive these events.
+ gfx::Point pointer_location(10, 10);
+
+ constexpr int hittest_values[] = {
+ HTBOTTOM, HTBOTTOMLEFT, HTBOTTOMRIGHT, HTCAPTION, HTLEFT,
+ HTRIGHT, HTTOP, HTTOPLEFT, HTTOPRIGHT, HTNOWHERE,
+ HTBORDER, HTCLIENT, HTCLOSE, HTERROR, HTGROWBOX,
+ HTHELP, HTHSCROLL, HTMENU, HTMAXBUTTON, HTMINBUTTON,
+ HTREDUCE, HTSIZE, HTSYSMENU, HTTRANSPARENT, HTVSCROLL,
+ HTZOOM,
+ };
+
+ for (int hittest : hittest_values) {
+ handler->Reset();
+
+ // Set the desired hit test result value, which will be returned, when
+ // WindowEventFilter starts to perform hit testing.
+ frame_view_->set_hit_test_result(hittest);
+
+ gfx::Rect bounds = window->GetBoundsInScreen();
+
+ // The wm move/resize handler receives pointer location in the global screen
+ // coordinate, whereas event dispatcher receives event locations on a local
+ // system coordinate. Thus, add an offset of a new possible origin value of
+ // a window to the expected pointer location.
+ gfx::Point expected_pointer_location(pointer_location);
+ expected_pointer_location.Offset(bounds.x(), bounds.y());
+
+ if (hittest == HTCAPTION) {
+ // Move the window on HTCAPTION hit test value.
+ bounds =
+ gfx::Rect(gfx::Point(bounds.x() + 2, bounds.y() + 4), bounds.size());
+ handler->set_bounds(bounds);
+ } else if (IsNonClientComponent(hittest)) {
+ // Resize the window on other than HTCAPTION non client hit test values.
+ bounds = gfx::Rect(
+ gfx::Point(bounds.origin()),
+ gfx::Size(bounds.size().width() + 5, bounds.size().height() + 10));
+ handler->set_bounds(bounds);
+ }
+
+ // Send mouse down event and make sure the WindowEventFilter calls the
+ // move/resize handler to start interactive move/resize with the |hittest|
+ // value we specified.
+ auto mouse_down_event = CreateMouseEvent(
+ pointer_location, ui::ET_MOUSE_PRESSED, ui::EF_LEFT_MOUSE_BUTTON);
+ host->DispatchEvent(mouse_down_event.get());
+
+ // The test expectation is based on the hit test component. If it is a
+ // non-client component, which results in a call to move/resize, the handler
+ // must receive the hittest value and the pointer location in global screen
+ // coordinate system. In other cases, it must not.
+ SetExpectationBasedOnHittestValue(hittest, *handler.get(),
+ expected_pointer_location);
+ // Make sure the bounds of the content window are correct.
+ EXPECT_EQ(window->GetBoundsInScreen().ToString(), bounds.ToString());
+
+ // Dispatch mouse up event to release mouse pressed handler and be able to
+ // consume future events.
+ auto mouse_up_event = CreateMouseEvent(
+ pointer_location, ui::ET_MOUSE_RELEASED, ui::EF_LEFT_MOUSE_BUTTON);
+ host->DispatchEvent(mouse_up_event.get());
+ }
+}
+
+} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
index 4e04197810d..0ab1728d69b 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc
@@ -476,8 +476,7 @@ void DesktopWindowTreeHostX11::CloseNow() {
// If we have children, close them. Use a copy for iteration because they'll
// remove themselves.
std::set<DesktopWindowTreeHostX11*> window_children_copy = window_children_;
- for (std::set<DesktopWindowTreeHostX11*>::iterator it =
- window_children_copy.begin(); it != window_children_copy.end();
+ for (auto it = window_children_copy.begin(); it != window_children_copy.end();
++it) {
(*it)->CloseNow();
}
@@ -1006,7 +1005,6 @@ void DesktopWindowTreeHostX11::SetFullscreen(bool fullscreen) {
if (is_fullscreen_ == fullscreen)
return;
is_fullscreen_ = fullscreen;
- OnFullscreenStateChanged();
if (is_fullscreen_)
delayed_resize_task_.Cancel();
@@ -1372,10 +1370,6 @@ void DesktopWindowTreeHostX11::OnDisplayMetricsChanged(
}
}
-void DesktopWindowTreeHostX11::OnMaximizedStateChanged() {}
-
-void DesktopWindowTreeHostX11::OnFullscreenStateChanged() {}
-
////////////////////////////////////////////////////////////////////////////////
// DesktopWindowTreeHostX11, private:
@@ -1677,12 +1671,10 @@ void DesktopWindowTreeHostX11::OnWMStateUpdated() {
void DesktopWindowTreeHostX11::UpdateWindowProperties(
const base::flat_set<XAtom>& new_window_properties) {
bool was_minimized = IsMinimized();
- bool was_maximized = IsMaximized();
window_properties_ = new_window_properties;
bool is_minimized = IsMinimized();
- bool is_maximized = IsMaximized();
// Propagate the window minimization information to the content window, so
// the render side can update its visibility properly. OnWMStateUpdated() is
@@ -1729,9 +1721,6 @@ void DesktopWindowTreeHostX11::UpdateWindowProperties(
is_always_on_top_ = ui::HasWMSpecProperty(
window_properties_, gfx::GetAtom("_NET_WM_STATE_ABOVE"));
- if (was_maximized != is_maximized)
- OnMaximizedStateChanged();
-
// Now that we have different window properties, we may need to relayout the
// window. (The windows code doesn't need this because their window change is
// synchronous.)
@@ -1935,7 +1924,7 @@ void DesktopWindowTreeHostX11::SerializeImageRepresentation(
int height = rep.GetHeight();
data->push_back(height);
- const SkBitmap& bitmap = rep.sk_bitmap();
+ const SkBitmap& bitmap = rep.GetBitmap();
for (int y = 0; y < height; ++y)
for (int x = 0; x < width; ++x)
@@ -2367,7 +2356,7 @@ gfx::Rect DesktopWindowTreeHostX11::ToPixelRect(
return gfx::ToEnclosingRect(rect_in_pixels);
}
-std::unique_ptr<base::OnceClosure>
+std::unique_ptr<base::Closure>
DesktopWindowTreeHostX11::DisableEventListening() {
// Allows to open multiple file-pickers. See https://crbug.com/678982
modal_dialog_counter_++;
@@ -2378,9 +2367,9 @@ DesktopWindowTreeHostX11::DisableEventListening() {
window(), std::make_unique<aura::NullWindowTargeter>());
}
- return std::make_unique<base::OnceClosure>(
- base::BindOnce(&DesktopWindowTreeHostX11::EnableEventListening,
- weak_factory_.GetWeakPtr()));
+ return std::make_unique<base::Closure>(
+ base::Bind(&DesktopWindowTreeHostX11::EnableEventListening,
+ weak_factory_.GetWeakPtr()));
}
void DesktopWindowTreeHostX11::EnableEventListening() {
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
index cc9d5fb4823..2600a0621f3 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h
@@ -86,7 +86,7 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11
static void CleanUpWindowList(void (*func)(aura::Window* window));
// Disables event listening to make |dialog| modal.
- std::unique_ptr<base::OnceClosure> DisableEventListening();
+ std::unique_ptr<base::Closure> DisableEventListening();
// Returns a map of KeyboardEvent code to KeyboardEvent key values.
base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override;
@@ -184,12 +184,6 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11
void OnDisplayMetricsChanged(const display::Display& display,
uint32_t changed_metrics) override;
- // Called after the window is maximized or restored.
- virtual void OnMaximizedStateChanged();
-
- // Called after the window is fullscreened or unfullscreened.
- virtual void OnFullscreenStateChanged();
-
private:
friend class DesktopWindowTreeHostX11HighDPITest;
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc
index 73507805813..2f3f85b16b1 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc
@@ -9,6 +9,7 @@
#include "base/command_line.h"
#include "base/macros.h"
#include "base/run_loop.h"
+#include "base/stl_util.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/base/hit_test.h"
@@ -50,11 +51,8 @@ class WMStateWaiter : public X11PropertyChangeWaiter {
// X11PropertyChangeWaiter:
bool ShouldKeepOnWaiting(const ui::PlatformEvent& event) override {
std::vector<Atom> hints;
- if (ui::GetAtomArrayProperty(xwindow(), "_NET_WM_STATE", &hints)) {
- auto it = std::find(hints.cbegin(), hints.cend(), gfx::GetAtom(hint_));
- bool hint_set = (it != hints.cend());
- return hint_set != wait_till_set_;
- }
+ if (ui::GetAtomArrayProperty(xwindow(), "_NET_WM_STATE", &hints))
+ return base::ContainsValue(hints, gfx::GetAtom(hint_)) != wait_till_set_;
return true;
}
diff --git a/chromium/ui/views/widget/desktop_aura/window_event_filter.cc b/chromium/ui/views/widget/desktop_aura/window_event_filter.cc
index 530b079289b..3b01fb995b4 100644
--- a/chromium/ui/views/widget/desktop_aura/window_event_filter.cc
+++ b/chromium/ui/views/widget/desktop_aura/window_event_filter.cc
@@ -6,6 +6,7 @@
#include "services/ws/public/mojom/window_tree_constants.mojom.h"
#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
#include "ui/aura/window_tree_host.h"
@@ -14,6 +15,7 @@
#include "ui/display/screen.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
+#include "ui/platform_window/platform_window_handler/wm_move_resize_handler.h"
#include "ui/views/linux_ui/linux_ui.h"
#include "ui/views/widget/desktop_aura/desktop_window_tree_host.h"
#include "ui/views/widget/native_widget_aura.h"
@@ -21,6 +23,28 @@
namespace views {
+namespace {
+
+bool CanPerformDragOrResize(int hittest) {
+ switch (hittest) {
+ case HTBOTTOM:
+ case HTBOTTOMLEFT:
+ case HTBOTTOMRIGHT:
+ case HTCAPTION:
+ case HTLEFT:
+ case HTRIGHT:
+ case HTTOP:
+ case HTTOPLEFT:
+ case HTTOPRIGHT:
+ return true;
+ default:
+ return false;
+ }
+ return true;
+}
+
+} // namespace
+
WindowEventFilter::WindowEventFilter(DesktopWindowTreeHost* window_tree_host)
: window_tree_host_(window_tree_host), click_component_(HTNOWHERE) {}
@@ -53,6 +77,12 @@ void WindowEventFilter::OnMouseEvent(ui::MouseEvent* event) {
}
}
+void WindowEventFilter::SetWmMoveResizeHandler(
+ ui::WmMoveResizeHandler* handler) {
+ DCHECK(!handler_);
+ handler_ = handler;
+}
+
void WindowEventFilter::OnClickedCaption(ui::MouseEvent* event,
int previous_click_component) {
aura::Window* target = static_cast<aura::Window*>(event->target());
@@ -149,6 +179,18 @@ void WindowEventFilter::LowerWindow() {}
void WindowEventFilter::MaybeDispatchHostWindowDragMovement(
int hittest,
- ui::MouseEvent* event) {}
+ ui::MouseEvent* event) {
+ if (handler_ && event->IsLeftMouseButton() &&
+ CanPerformDragOrResize(hittest)) {
+ // Some platforms (eg X11) may require last pointer location not in the
+ // local surface coordinates, but rather in the screen coordinates for
+ // interactive move/resize.
+ const gfx::Point last_pointer_location =
+ aura::Env::GetInstance()->last_mouse_location();
+ handler_->DispatchHostWindowDragMovement(hittest, last_pointer_location);
+ event->StopPropagation();
+ return;
+ }
+}
} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/window_event_filter.h b/chromium/ui/views/widget/desktop_aura/window_event_filter.h
index a9bc0387c25..d3d7214f021 100644
--- a/chromium/ui/views/widget/desktop_aura/window_event_filter.h
+++ b/chromium/ui/views/widget/desktop_aura/window_event_filter.h
@@ -10,6 +10,10 @@
#include "ui/events/event_handler.h"
#include "ui/views/views_export.h"
+namespace ui {
+class WmMoveResizeHandler;
+}
+
namespace views {
class DesktopWindowTreeHost;
@@ -24,6 +28,11 @@ class VIEWS_EXPORT WindowEventFilter : public ui::EventHandler {
// Overridden from ui::EventHandler:
void OnMouseEvent(ui::MouseEvent* event) override;
+ // Sets a move resize handler. Currently initialized only by ozone platforms.
+ // See WaylandWindow::WaylandWindow in the wayland_window.cc file for an
+ // example.
+ void SetWmMoveResizeHandler(ui::WmMoveResizeHandler* handler);
+
private:
// Called when the user clicked the caption area.
void OnClickedCaption(ui::MouseEvent* event, int previous_click_component);
@@ -52,6 +61,11 @@ class VIEWS_EXPORT WindowEventFilter : public ui::EventHandler {
// components.
int click_component_;
+ // A handler, which is used for interactive move/resize events if set and
+ // unless MaybeDispatchHostWindowDragMovement is overridden by a derived
+ // class.
+ ui::WmMoveResizeHandler* handler_ = nullptr;
+
DISALLOW_COPY_AND_ASSIGN(WindowEventFilter);
};
diff --git a/chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc b/chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc
index e0a11a00d46..a688da8c12b 100644
--- a/chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc
+++ b/chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc
@@ -11,6 +11,7 @@
#include <vector>
#include "base/macros.h"
+#include "base/stl_util.h"
#include "third_party/skia/include/core/SkRect.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
@@ -42,9 +43,8 @@ class MinimizeWaiter : public X11PropertyChangeWaiter {
bool ShouldKeepOnWaiting(const ui::PlatformEvent& event) override {
std::vector<Atom> wm_states;
if (ui::GetAtomArrayProperty(xwindow(), "_NET_WM_STATE", &wm_states)) {
- auto it = std::find(wm_states.cbegin(), wm_states.cend(),
- gfx::GetAtom("_NET_WM_STATE_HIDDEN"));
- return it == wm_states.cend();
+ return !base::ContainsValue(wm_states,
+ gfx::GetAtom("_NET_WM_STATE_HIDDEN"));
}
return true;
}
@@ -80,8 +80,7 @@ class StackingClientListWaiter : public X11PropertyChangeWaiter {
std::vector<XID> stack;
ui::GetXWindowStack(ui::GetX11RootWindow(), &stack);
for (size_t i = 0; i < expected_windows_.size(); ++i) {
- auto it = std::find(stack.cbegin(), stack.cend(), expected_windows_[i]);
- if (it == stack.cend())
+ if (!base::ContainsValue(stack, expected_windows_[i]))
return true;
}
return false;
diff --git a/chromium/ui/views/widget/native_widget_aura.cc b/chromium/ui/views/widget/native_widget_aura.cc
index e6661017075..28c63b02b81 100644
--- a/chromium/ui/views/widget/native_widget_aura.cc
+++ b/chromium/ui/views/widget/native_widget_aura.cc
@@ -4,6 +4,9 @@
#include "ui/views/widget/native_widget_aura.h"
+#include <memory>
+#include <utility>
+
#include "base/bind.h"
#include "base/location.h"
#include "base/single_thread_task_runner.h"
@@ -57,8 +60,7 @@
#if defined(OS_WIN)
#include "base/win/scoped_gdi_object.h"
-#include "base/win/win_client_metrics.h"
-#include "ui/base/l10n/l10n_util_win.h"
+#include "ui/gfx/platform_font_win.h"
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h"
#endif
@@ -1155,8 +1157,7 @@ void NativeWidgetPrivate::GetAllChildWidgets(gfx::NativeView native_view,
}
const aura::Window::Windows& child_windows = native_view->children();
- for (aura::Window::Windows::const_iterator i = child_windows.begin();
- i != child_windows.end(); ++i) {
+ for (auto i = child_windows.begin(); i != child_windows.end(); ++i) {
GetAllChildWidgets((*i), children);
}
}
@@ -1192,8 +1193,7 @@ void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView native_view,
// First notify all the widgets that they are being disassociated
// from their previous parent.
- for (Widget::Widgets::iterator it = widgets.begin();
- it != widgets.end(); ++it) {
+ for (auto it = widgets.begin(); it != widgets.end(); ++it) {
(*it)->NotifyNativeViewHierarchyWillChange();
}
@@ -1217,8 +1217,7 @@ void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView native_view,
}
// And now, notify them that they have a brand new parent.
- for (Widget::Widgets::iterator it = widgets.begin();
- it != widgets.end(); ++it) {
+ for (auto it = widgets.begin(); it != widgets.end(); ++it) {
(*it)->NotifyNativeViewHierarchyChanged();
}
}
@@ -1226,11 +1225,8 @@ void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView native_view,
// static
gfx::FontList NativeWidgetPrivate::GetWindowTitleFontList() {
#if defined(OS_WIN)
- NONCLIENTMETRICS_XP ncm;
- base::win::GetNonClientMetrics(&ncm);
- l10n_util::AdjustUIFont(&(ncm.lfCaptionFont));
- base::win::ScopedHFONT caption_font(CreateFontIndirect(&(ncm.lfCaptionFont)));
- return gfx::FontList(gfx::Font(caption_font.get()));
+ return gfx::FontList(gfx::PlatformFontWin::GetSystemFont(
+ gfx::PlatformFontWin::SystemFont::kCaption));
#else
return gfx::FontList();
#endif
diff --git a/chromium/ui/views/widget/native_widget_mac.h b/chromium/ui/views/widget/native_widget_mac.h
index 5bb34bd75c3..e8e387ccd3c 100644
--- a/chromium/ui/views/widget/native_widget_mac.h
+++ b/chromium/ui/views/widget/native_widget_mac.h
@@ -15,6 +15,12 @@
class NativeWidgetMacNSWindow;
#endif
+namespace views_bridge_mac {
+namespace mojom {
+class BridgedNativeWidget;
+} // namespace mojom
+} // namespace views_bridge_mac
+
namespace views {
namespace test {
class HitTestNativeWidgetMac;
@@ -22,7 +28,8 @@ class MockNativeWidgetMac;
class WidgetTest;
}
-class BridgedNativeWidget;
+class BridgeFactoryHost;
+class BridgedNativeWidgetImpl;
class BridgedNativeWidgetHostImpl;
class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate {
@@ -30,15 +37,8 @@ class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate {
explicit NativeWidgetMac(internal::NativeWidgetDelegate* delegate);
~NativeWidgetMac() override;
- // Retrieves the bridge associated with the given NSWindow. Returns null if
- // the supplied handle has no associated Widget.
- static BridgedNativeWidgetHostImpl* GetBridgeHostImplForNativeWindow(
- gfx::NativeWindow window);
- static BridgedNativeWidget* GetBridgeForNativeWindow(
- gfx::NativeWindow window);
-
// Informs |delegate_| that the native widget is about to be destroyed.
- // BridgedNativeWidget::OnWindowWillClose() invokes this early when the
+ // BridgedNativeWidgetImpl::OnWindowWillClose() invokes this early when the
// NSWindowDelegate informs the bridge that the window is being closed (later,
// invoking OnWindowDestroyed()).
void WindowDestroying();
@@ -144,7 +144,7 @@ class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate {
std::string GetName() const override;
protected:
- // Creates the NSWindow that will be passed to the BridgedNativeWidget.
+ // Creates the NSWindow that will be passed to the BridgedNativeWidgetImpl.
// Called by InitNativeWidget. The return value will be autoreleased.
// Note that some tests (in particular, views_unittests that interact
// with ScopedFakeNSWindowFullscreen, on 10.10) assume that these windows
@@ -153,11 +153,17 @@ class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate {
virtual NativeWidgetMacNSWindow* CreateNSWindow(
const Widget::InitParams& params);
+ // Return the BridgeFactoryHost that is to be used for creating this window
+ // and all of its child windows. This will return nullptr if the native
+ // windows are to be created in the current process.
+ virtual BridgeFactoryHost* GetBridgeFactoryHost();
+
// Optional hook for subclasses invoked by WindowDestroying().
virtual void OnWindowDestroying(NSWindow* window) {}
internal::NativeWidgetDelegate* delegate() { return delegate_; }
- BridgedNativeWidget* bridge() const;
+ views_bridge_mac::mojom::BridgedNativeWidget* bridge() const;
+ BridgedNativeWidgetImpl* bridge_impl() const;
BridgedNativeWidgetHostImpl* bridge_host_for_testing() const {
return bridge_host_.get();
}
diff --git a/chromium/ui/views/widget/native_widget_mac.mm b/chromium/ui/views/widget/native_widget_mac.mm
index decbcdf69ac..4f75293c284 100644
--- a/chromium/ui/views/widget/native_widget_mac.mm
+++ b/chromium/ui/views/widget/native_widget_mac.mm
@@ -10,7 +10,6 @@
#include "base/bind.h"
#include "base/lazy_instance.h"
-#include "base/mac/foundation_util.h"
#include "base/mac/scoped_nsobject.h"
#include "base/strings/sys_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -25,16 +24,15 @@
#import "ui/gfx/mac/nswindow_frame_controls.h"
#include "ui/native_theme/native_theme.h"
#include "ui/native_theme/native_theme_mac.h"
-#import "ui/views/cocoa/bridged_content_view.h"
-#import "ui/views/cocoa/bridged_native_widget.h"
#import "ui/views/cocoa/bridged_native_widget_host_impl.h"
-#include "ui/views/cocoa/cocoa_mouse_capture.h"
#import "ui/views/cocoa/drag_drop_client_mac.h"
-#import "ui/views/cocoa/native_widget_mac_nswindow.h"
-#import "ui/views/cocoa/views_nswindow_delegate.h"
#include "ui/views/widget/drop_helper.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/window/native_frame_view.h"
+#import "ui/views_bridge_mac/bridged_content_view.h"
+#import "ui/views_bridge_mac/bridged_native_widget_impl.h"
+#import "ui/views_bridge_mac/native_widget_mac_nswindow.h"
+#import "ui/views_bridge_mac/views_nswindow_delegate.h"
using views_bridge_mac::mojom::WindowVisibilityState;
@@ -44,17 +42,6 @@ namespace {
base::LazyInstance<ui::GestureRecognizerImplMac>::Leaky
g_gesture_recognizer_instance = LAZY_INSTANCE_INITIALIZER;
-NativeWidgetMac* GetNativeWidgetMacForNativeWindow(
- gfx::NativeWindow native_window) {
- id<NSWindowDelegate> window_delegate = [native_window delegate];
- if ([window_delegate respondsToSelector:@selector(nativeWidgetMac)]) {
- ViewsNSWindowDelegate* delegate =
- base::mac::ObjCCastStrict<ViewsNSWindowDelegate>(window_delegate);
- return [delegate nativeWidgetMac];
- }
- return nullptr; // Not created by NativeWidgetMac.
-}
-
NSInteger StyleMaskForParams(const Widget::InitParams& params) {
// If the Widget is modal, it will be displayed as a sheet. This works best if
// it has NSTitledWindowMask. For example, with NSBorderlessWindowMask, the
@@ -92,22 +79,6 @@ NativeWidgetMac::~NativeWidgetMac() {
CloseNow();
}
-// static
-BridgedNativeWidget* NativeWidgetMac::GetBridgeForNativeWindow(
- gfx::NativeWindow window) {
- if (NativeWidgetMac* widget = GetNativeWidgetMacForNativeWindow(window))
- return widget->bridge();
- return nullptr; // Not created by NativeWidgetMac.
-}
-
-// static
-BridgedNativeWidgetHostImpl* NativeWidgetMac::GetBridgeHostImplForNativeWindow(
- gfx::NativeWindow window) {
- if (NativeWidgetMac* widget = GetNativeWidgetMacForNativeWindow(window))
- return widget->bridge_host_.get();
- return nullptr; // Not created by NativeWidgetMac.
-}
-
void NativeWidgetMac::WindowDestroying() {
OnWindowDestroying(GetNativeWindow());
delegate_->OnNativeWidgetDestroying();
@@ -137,9 +108,29 @@ int NativeWidgetMac::SheetPositionY() {
void NativeWidgetMac::InitNativeWidget(const Widget::InitParams& params) {
ownership_ = params.ownership;
name_ = params.name;
- base::scoped_nsobject<NativeWidgetMacNSWindow> window(
- [CreateNSWindow(params) retain]);
- bridge()->SetWindow(window);
+ BridgedNativeWidgetHostImpl* parent_host =
+ BridgedNativeWidgetHostImpl::GetFromNativeWindow([params.parent window]);
+
+ // Determine the factory through which to create the bridge
+ BridgeFactoryHost* bridge_factory_host =
+ parent_host ? parent_host->bridge_factory_host() : GetBridgeFactoryHost();
+ if (bridge_factory_host) {
+ // Compute the parameters to describe the NSWindow.
+ // TODO(ccameron): This is not yet adequate to capture all NSWindow
+ // sub-classes that may be used. Make the parameter structure more
+ // expressive.
+ auto create_window_params =
+ views_bridge_mac::mojom::CreateWindowParams::New();
+ create_window_params->style_mask = StyleMaskForParams(params);
+
+ bridge_host_->CreateRemoteBridge(bridge_factory_host,
+ std::move(create_window_params));
+ } else {
+ base::scoped_nsobject<NativeWidgetMacNSWindow> window(
+ [CreateNSWindow(params) retain]);
+ bridge_host_->CreateLocalBridge(std::move(window));
+ }
+ bridge_host_->SetParent(parent_host);
bridge_host_->InitWindow(params);
// Only set always-on-top here if it is true since setting it may affect how
@@ -151,8 +142,8 @@ void NativeWidgetMac::InitNativeWidget(const Widget::InitParams& params) {
DCHECK(GetWidget()->GetRootView());
bridge_host_->SetRootView(GetWidget()->GetRootView());
- bridge()->CreateContentView(GetWidget()->GetRootView()->bounds());
- bridge()->CreateDragDropClient(GetWidget()->GetRootView());
+ bridge()->CreateContentView(bridge_host_->GetRootViewNSViewId(),
+ GetWidget()->GetRootView()->bounds());
if (auto* focus_manager = GetWidget()->GetFocusManager()) {
bridge()->MakeFirstResponder();
bridge_host_->SetFocusManager(focus_manager);
@@ -201,7 +192,7 @@ gfx::NativeView NativeWidgetMac::GetNativeView() const {
}
gfx::NativeWindow NativeWidgetMac::GetNativeWindow() const {
- return bridge() ? bridge()->ns_window() : nil;
+ return bridge_host_ ? bridge_host_->GetLocalNSWindow() : nil;
}
Widget* NativeWidgetMac::GetTopLevelWidget() {
@@ -220,31 +211,32 @@ const ui::Layer* NativeWidgetMac::GetLayer() const {
}
void NativeWidgetMac::ReorderNativeViews() {
- if (bridge())
- bridge()->ReorderChildViews();
+ if (bridge_host_)
+ bridge_host_->ReorderChildViews();
}
void NativeWidgetMac::ViewRemoved(View* view) {
- DragDropClientMac* client = bridge() ? bridge()->drag_drop_client() : nullptr;
+ DragDropClientMac* client =
+ bridge_host_ ? bridge_host_->drag_drop_client() : nullptr;
if (client)
client->drop_helper()->ResetTargetViewIfEquals(view);
}
void NativeWidgetMac::SetNativeWindowProperty(const char* name, void* value) {
- if (bridge())
- bridge()->SetNativeWindowProperty(name, value);
+ if (bridge_host_)
+ bridge_host_->SetNativeWindowProperty(name, value);
}
void* NativeWidgetMac::GetNativeWindowProperty(const char* name) const {
- if (bridge())
- return bridge()->GetNativeWindowProperty(name);
+ if (bridge_host_)
+ return bridge_host_->GetNativeWindowProperty(name);
return nullptr;
}
TooltipManager* NativeWidgetMac::GetTooltipManager() const {
- if (bridge())
- return bridge()->tooltip_manager();
+ if (bridge_host_)
+ return bridge_host_->tooltip_manager();
return nullptr;
}
@@ -268,12 +260,7 @@ ui::InputMethod* NativeWidgetMac::GetInputMethod() {
}
void NativeWidgetMac::CenterWindow(const gfx::Size& size) {
- SetSize(
- BridgedNativeWidget::GetWindowSizeForClientSize(GetNativeWindow(), size));
- // Note that this is not the precise center of screen, but it is the standard
- // location for windows like dialogs to appear on screen for Mac.
- // TODO(tapted): If there is a parent window, center in that instead.
- [GetNativeWindow() center];
+ bridge()->SetSizeAndCenter(size, GetWidget()->GetMinimumSize());
}
void NativeWidgetMac::GetWindowPlacement(
@@ -311,7 +298,7 @@ void NativeWidgetMac::InitModalType(ui::ModalType modal_type) {
// A peculiarity of the constrained window framework is that it permits a
// dialog of MODAL_TYPE_WINDOW to have a null parent window; falling back to
// a non-modal window in this case.
- DCHECK(bridge()->parent() || modal_type == ui::MODAL_TYPE_WINDOW);
+ DCHECK(bridge_host_->parent() || modal_type == ui::MODAL_TYPE_WINDOW);
// Everything happens upon show.
}
@@ -338,19 +325,14 @@ void NativeWidgetMac::SetBounds(const gfx::Rect& bounds) {
}
void NativeWidgetMac::SetBoundsConstrained(const gfx::Rect& bounds) {
- if (!bridge())
+ if (!bridge_host_)
return;
-
gfx::Rect new_bounds(bounds);
- NativeWidgetPrivate* ancestor =
- bridge() && bridge()->parent()
- ? GetNativeWidgetForNativeWindow(bridge()->parent()->GetNSWindow())
- : nullptr;
- if (!ancestor) {
- new_bounds = ConstrainBoundsToDisplayWorkArea(new_bounds);
- } else {
+ if (bridge_host_->parent()) {
new_bounds.AdjustToFit(
- gfx::Rect(ancestor->GetWindowBoundsInScreen().size()));
+ gfx::Rect(bridge_host_->parent()->GetWindowBoundsInScreen().size()));
+ } else {
+ new_bounds = ConstrainBoundsToDisplayWorkArea(new_bounds);
}
SetBounds(new_bounds);
}
@@ -395,8 +377,8 @@ void NativeWidgetMac::Show(ui::WindowShowState show_state,
case ui::SHOW_STATE_DEFAULT:
case ui::SHOW_STATE_NORMAL:
case ui::SHOW_STATE_INACTIVE:
- break;
case ui::SHOW_STATE_MINIMIZED:
+ break;
case ui::SHOW_STATE_MAXIMIZED:
case ui::SHOW_STATE_FULLSCREEN:
NOTIMPLEMENTED();
@@ -405,10 +387,12 @@ void NativeWidgetMac::Show(ui::WindowShowState show_state,
NOTREACHED();
break;
}
- bridge()->SetVisibilityState(
- show_state == ui::SHOW_STATE_INACTIVE
- ? WindowVisibilityState::kShowInactive
- : WindowVisibilityState::kShowAndActivateWindow);
+ auto window_state = WindowVisibilityState::kShowAndActivateWindow;
+ if (show_state == ui::SHOW_STATE_INACTIVE)
+ window_state = WindowVisibilityState::kShowInactive;
+ else if (show_state == ui::SHOW_STATE_MINIMIZED)
+ window_state = WindowVisibilityState::kHideWindow;
+ bridge()->SetVisibilityState(window_state);
// Ignore the SetInitialFocus() result. BridgedContentView should get
// firstResponder status regardless.
@@ -517,7 +501,8 @@ void NativeWidgetMac::RunShellDrag(View* view,
const gfx::Point& location,
int operation,
ui::DragDropTypes::DragEventSource source) {
- bridge()->drag_drop_client()->StartDragAndDrop(view, data, operation, source);
+ bridge_host_->drag_drop_client()->StartDragAndDrop(view, data, operation,
+ source);
}
void NativeWidgetMac::SchedulePaintInRect(const gfx::Rect& rect) {
@@ -535,8 +520,8 @@ void NativeWidgetMac::SchedulePaintInRect(const gfx::Rect& rect) {
}
void NativeWidgetMac::SetCursor(gfx::NativeCursor cursor) {
- if (bridge())
- bridge()->SetCursor(cursor);
+ if (bridge_impl())
+ bridge_impl()->SetCursor(cursor);
}
bool NativeWidgetMac::IsMouseEventsEnabled() const {
@@ -568,20 +553,21 @@ Widget::MoveLoopResult NativeWidgetMac::RunMoveLoop(
const gfx::Vector2d& drag_offset,
Widget::MoveLoopSource source,
Widget::MoveLoopEscapeBehavior escape_behavior) {
- if (!bridge())
+ if (!bridge_impl())
return Widget::MOVE_LOOP_CANCELED;
- return bridge()->RunMoveLoop(drag_offset);
+ return bridge_impl()->RunMoveLoop(drag_offset) ? Widget::MOVE_LOOP_SUCCESSFUL
+ : Widget::MOVE_LOOP_CANCELED;
}
void NativeWidgetMac::EndMoveLoop() {
- if (bridge())
- bridge()->EndMoveLoop();
+ if (bridge_impl())
+ bridge_impl()->EndMoveLoop();
}
void NativeWidgetMac::SetVisibilityChangedAnimationsEnabled(bool value) {
- if (bridge())
- bridge()->SetAnimationEnabled(value);
+ if (bridge_impl())
+ bridge_impl()->SetAnimationEnabled(value);
}
void NativeWidgetMac::SetVisibilityAnimationDuration(
@@ -590,9 +576,25 @@ void NativeWidgetMac::SetVisibilityAnimationDuration(
}
void NativeWidgetMac::SetVisibilityAnimationTransition(
- Widget::VisibilityTransition transition) {
+ Widget::VisibilityTransition widget_transitions) {
+ views_bridge_mac::mojom::VisibilityTransition transitions =
+ views_bridge_mac::mojom::VisibilityTransition::kNone;
+ switch (widget_transitions) {
+ case Widget::ANIMATE_NONE:
+ transitions = views_bridge_mac::mojom::VisibilityTransition::kNone;
+ break;
+ case Widget::ANIMATE_SHOW:
+ transitions = views_bridge_mac::mojom::VisibilityTransition::kShow;
+ break;
+ case Widget::ANIMATE_HIDE:
+ transitions = views_bridge_mac::mojom::VisibilityTransition::kHide;
+ break;
+ case Widget::ANIMATE_BOTH:
+ transitions = views_bridge_mac::mojom::VisibilityTransition::kBoth;
+ break;
+ }
if (bridge())
- bridge()->set_transitions_to_animate(transition);
+ bridge()->SetTransitionsToAnimate(transitions);
}
bool NativeWidgetMac::IsTranslucentWindowOpacitySupported() const {
@@ -631,7 +633,15 @@ NativeWidgetMacNSWindow* NativeWidgetMac::CreateNSWindow(
defer:NO] autorelease];
}
-BridgedNativeWidget* NativeWidgetMac::bridge() const {
+BridgeFactoryHost* NativeWidgetMac::GetBridgeFactoryHost() {
+ return nullptr;
+}
+
+views_bridge_mac::mojom::BridgedNativeWidget* NativeWidgetMac::bridge() const {
+ return bridge_host_ ? bridge_host_->bridge() : nullptr;
+}
+
+BridgedNativeWidgetImpl* NativeWidgetMac::bridge_impl() const {
return bridge_host_ ? bridge_host_->bridge_impl() : nullptr;
}
@@ -690,32 +700,31 @@ NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeView(
// static
NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeWindow(
gfx::NativeWindow window) {
- if (NativeWidgetMac* widget = GetNativeWidgetMacForNativeWindow(window))
- return widget;
+ if (BridgedNativeWidgetHostImpl* bridge_host_impl =
+ BridgedNativeWidgetHostImpl::GetFromNativeWindow(window)) {
+ return bridge_host_impl->native_widget_mac();
+ }
return nullptr; // Not created by NativeWidgetMac.
}
// static
NativeWidgetPrivate* NativeWidgetPrivate::GetTopLevelNativeWidget(
gfx::NativeView native_view) {
- BridgedNativeWidget* bridge =
- NativeWidgetMac::GetBridgeForNativeWindow([native_view window]);
- if (!bridge)
+ BridgedNativeWidgetHostImpl* bridge_host =
+ BridgedNativeWidgetHostImpl::GetFromNativeWindow([native_view window]);
+ if (!bridge_host)
return nullptr;
-
- NativeWidgetPrivate* ancestor =
- bridge->parent() ? GetTopLevelNativeWidget(
- [bridge->parent()->GetNSWindow() contentView])
- : nullptr;
- return ancestor ? ancestor : bridge->native_widget_mac();
+ while (bridge_host->parent())
+ bridge_host = bridge_host->parent();
+ return bridge_host->native_widget_mac();
}
// static
void NativeWidgetPrivate::GetAllChildWidgets(gfx::NativeView native_view,
Widget::Widgets* children) {
- BridgedNativeWidget* bridge =
- NativeWidgetMac::GetBridgeForNativeWindow([native_view window]);
- if (!bridge) {
+ BridgedNativeWidgetHostImpl* bridge_host =
+ BridgedNativeWidgetHostImpl::GetFromNativeWindow([native_view window]);
+ if (!bridge_host) {
// The NSWindow is not itself a views::Widget, but it may have children that
// are. Support returning Widgets that are parented to the NSWindow, except:
// - Ignore requests for children of an NSView that is not a contentView.
@@ -738,67 +747,101 @@ void NativeWidgetPrivate::GetAllChildWidgets(gfx::NativeView native_view,
// If |native_view| is a subview of the contentView, it will share an
// NSWindow, but will itself be a native child of the Widget. That is, adding
- // bridge->..->GetWidget() to |children| would be adding the _parent_ of
+ // bridge_host->..->GetWidget() to |children| would be adding the _parent_ of
// |native_view|, not the Widget for |native_view|. |native_view| doesn't have
// a corresponding Widget of its own in this case (and so can't have Widget
// children of its own on Mac).
- if (bridge->ns_view() != native_view)
+ if (bridge_host->native_widget_mac()->GetNativeView() != native_view)
return;
// Code expects widget for |native_view| to be added to |children|.
- if (bridge->native_widget_mac()->GetWidget())
- children->insert(bridge->native_widget_mac()->GetWidget());
+ if (bridge_host->native_widget_mac()->GetWidget())
+ children->insert(bridge_host->native_widget_mac()->GetWidget());
- // When the NSWindow *is* a Widget, only consider child_windows(). I.e. do not
- // look through -[NSWindow childWindows] as done for the (!bridge) case above.
- // -childWindows does not support hidden windows, and anything in there which
- // is not in child_windows() would have been added by AppKit.
- for (BridgedNativeWidget* child : bridge->child_windows())
- GetAllChildWidgets(child->ns_view(), children);
+ // When the NSWindow *is* a Widget, only consider children(). I.e. do not
+ // look through -[NSWindow childWindows] as done for the (!bridge_host) case
+ // above. -childWindows does not support hidden windows, and anything in there
+ // which is not in children() would have been added by AppKit.
+ for (BridgedNativeWidgetHostImpl* child : bridge_host->children())
+ GetAllChildWidgets(child->native_widget_mac()->GetNativeView(), children);
}
// static
void NativeWidgetPrivate::GetAllOwnedWidgets(gfx::NativeView native_view,
Widget::Widgets* owned) {
- BridgedNativeWidget* bridge =
- NativeWidgetMac::GetBridgeForNativeWindow([native_view window]);
- if (!bridge) {
+ BridgedNativeWidgetHostImpl* bridge_host =
+ BridgedNativeWidgetHostImpl::GetFromNativeWindow([native_view window]);
+ if (!bridge_host) {
GetAllChildWidgets(native_view, owned);
return;
}
- if (bridge->ns_view() != native_view)
+ if (bridge_host->native_widget_mac()->GetNativeView() != native_view)
return;
- for (BridgedNativeWidget* child : bridge->child_windows())
- GetAllChildWidgets(child->ns_view(), owned);
+ for (BridgedNativeWidgetHostImpl* child : bridge_host->children())
+ GetAllChildWidgets(child->native_widget_mac()->GetNativeView(), owned);
}
// static
void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView native_view,
gfx::NativeView new_parent) {
DCHECK_NE(native_view, new_parent);
+ DCHECK([new_parent window]);
if (!new_parent || [native_view superview] == new_parent) {
NOTREACHED();
return;
}
- BridgedNativeWidget* bridge =
- NativeWidgetMac::GetBridgeForNativeWindow([native_view window]);
- BridgedNativeWidget* parent_bridge =
- NativeWidgetMac::GetBridgeForNativeWindow([new_parent window]);
- DCHECK(bridge);
- if (Widget::GetWidgetForNativeView(native_view)->is_top_level() &&
- bridge->parent() == parent_bridge)
+ BridgedNativeWidgetHostImpl* bridge_host =
+ BridgedNativeWidgetHostImpl::GetFromNativeWindow([native_view window]);
+ DCHECK(bridge_host);
+ NSView* bridge_view = bridge_host->native_widget_mac()->GetNativeView();
+ NSWindow* bridge_window = bridge_host->native_widget_mac()->GetNativeWindow();
+ bool bridge_is_top_level =
+ bridge_host->native_widget_mac()->GetWidget()->is_top_level();
+ DCHECK([native_view isDescendantOf:bridge_view]);
+ DCHECK(bridge_window && ![bridge_window isSheet]);
+
+ BridgedNativeWidgetHostImpl* parent_bridge_host =
+ BridgedNativeWidgetHostImpl::GetFromNativeWindow([new_parent window]);
+
+ // Early out for no-op changes.
+ if (native_view == bridge_view && bridge_is_top_level &&
+ bridge_host->parent() == parent_bridge_host) {
return;
+ }
+ // First notify all the widgets that they are being disassociated from their
+ // previous parent.
Widget::Widgets widgets;
GetAllChildWidgets(native_view, &widgets);
-
- // First notify all the widgets that they are being disassociated
- // from their previous parent.
for (auto* child : widgets)
child->NotifyNativeViewHierarchyWillChange();
- bridge->ReparentNativeView(native_view, new_parent);
+ // Update |brige_host|'s parent only if
+ // BridgedNativeWidgetImpl::ReparentNativeView will.
+ if (native_view == bridge_view) {
+ bridge_host->SetParent(parent_bridge_host);
+ if (!bridge_is_top_level) {
+ // Make |bridge_host|'s NSView be a child of |new_parent| by adding it as
+ // a subview. Note that this will have the effect of removing
+ // |bridge_host|'s NSView from its NSWindow. The |NSWindow| must remain
+ // visible because it controls the bounds and visibility of the ui::Layer,
+ // so just hide it by setting alpha value to zero.
+ // TODO(ccameron): This path likely violates assumptions. Verify that this
+ // path is unused and remove it.
+ LOG(ERROR) << "Reparenting a non-top-level BridgedNativeWidget. This is "
+ "likely unsupported.";
+ [new_parent addSubview:native_view];
+ [bridge_window setAlphaValue:0];
+ [bridge_window setIgnoresMouseEvents:YES];
+ }
+ } else {
+ // TODO(ccameron): This path likely violates assumptions. Verify that this
+ // path is unused and remove it.
+ LOG(ERROR) << "Reparenting with a non-root BridgedNativeWidget NSView. "
+ "This is likely unsupported.";
+ [new_parent addSubview:native_view];
+ }
// And now, notify them that they have a brand new parent.
for (auto* child : widgets)
@@ -814,7 +857,7 @@ gfx::FontList NativeWidgetPrivate::GetWindowTitleFontList() {
// static
gfx::NativeView NativeWidgetPrivate::GetGlobalCapture(
gfx::NativeView native_view) {
- return [CocoaMouseCapture::GetGlobalCaptureWindow() contentView];
+ return BridgedNativeWidgetHostImpl::GetGlobalCaptureView();
}
} // namespace internal
diff --git a/chromium/ui/views/widget/native_widget_mac_unittest.mm b/chromium/ui/views/widget/native_widget_mac_unittest.mm
index ebb9ea6cd6d..4efaef021c4 100644
--- a/chromium/ui/views/widget/native_widget_mac_unittest.mm
+++ b/chromium/ui/views/widget/native_widget_mac_unittest.mm
@@ -28,9 +28,6 @@
#include "ui/events/test/event_generator.h"
#import "ui/gfx/mac/coordinate_conversion.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
-#import "ui/views/cocoa/bridged_content_view.h"
-#import "ui/views/cocoa/bridged_native_widget.h"
-#import "ui/views/cocoa/native_widget_mac_nswindow.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/native/native_view_host.h"
@@ -42,6 +39,9 @@
#include "ui/views/widget/native_widget_private.h"
#include "ui/views/window/dialog_client_view.h"
#include "ui/views/window/dialog_delegate.h"
+#import "ui/views_bridge_mac/bridged_content_view.h"
+#import "ui/views_bridge_mac/bridged_native_widget_impl.h"
+#import "ui/views_bridge_mac/native_widget_mac_nswindow.h"
// Donates an implementation of -[NSAnimation stopAnimation] which calls the
// original implementation, then quits a nested run loop.
@@ -86,18 +86,14 @@
@interface FocusableTestNSView : NSView
@end
-@interface TestNativeParentWindow : NSWindow
-@property(assign, nonatomic) bool* deallocFlag;
-@end
-
namespace views {
namespace test {
-// BridgedNativeWidget friend to access private members.
+// BridgedNativeWidgetImpl friend to access private members.
class BridgedNativeWidgetTestApi {
public:
explicit BridgedNativeWidgetTestApi(NSWindow* window) {
- bridge_ = NativeWidgetMac::GetBridgeForNativeWindow(window);
+ bridge_ = BridgedNativeWidgetImpl::GetFromNativeWindow(window);
}
// Simulate a frame swap from the compositor.
@@ -116,7 +112,7 @@ class BridgedNativeWidgetTestApi {
}
private:
- BridgedNativeWidget* bridge_;
+ BridgedNativeWidgetImpl* bridge_;
DISALLOW_COPY_AND_ASSIGN(BridgedNativeWidgetTestApi);
};
@@ -148,30 +144,33 @@ class TestWindowNativeWidgetMac : public NativeWidgetMac {
DISALLOW_COPY_AND_ASSIGN(TestWindowNativeWidgetMac);
};
-// Tests for parts of NativeWidgetMac not covered by BridgedNativeWidget, which
-// need access to Cocoa APIs.
+// Tests for parts of NativeWidgetMac not covered by BridgedNativeWidgetImpl,
+// which need access to Cocoa APIs.
class NativeWidgetMacTest : public WidgetTest {
public:
NativeWidgetMacTest() {}
- // The content size of NSWindows made by MakeNativeParent().
- NSRect ParentRect() const { return NSMakeRect(100, 100, 300, 200); }
-
- // Make a native NSWindow with the given |style_mask| to use as a parent.
- TestNativeParentWindow* MakeNativeParentWithStyle(int style_mask) {
- native_parent_.reset([[TestNativeParentWindow alloc]
- initWithContentRect:ParentRect()
- styleMask:style_mask
- backing:NSBackingStoreBuffered
- defer:NO]);
- [native_parent_ setReleasedWhenClosed:NO]; // Owned by scoped_nsobject.
- [native_parent_ makeKeyAndOrderFront:nil];
- return native_parent_;
+ // Make an NSWindow with a close button and a title bar to use as a parent.
+ // This NSWindow is backed by a widget that is not exposed to the caller.
+ // To destroy the Widget, the native NSWindow must be closed.
+ NativeWidgetMacTestWindow* MakeClosableTitledNativeParent() {
+ NativeWidgetMacTestWindow* native_parent = nil;
+ Widget::InitParams parent_init_params =
+ CreateParams(Widget::InitParams::TYPE_WINDOW);
+ parent_init_params.bounds = gfx::Rect(100, 100, 200, 200);
+ CreateWidgetWithTestWindow(parent_init_params, &native_parent);
+ return native_parent;
}
- // Make a borderless, native NSWindow to use as a parent.
- TestNativeParentWindow* MakeNativeParent() {
- return MakeNativeParentWithStyle(NSBorderlessWindowMask);
+ // Same as the above, but creates a borderless NSWindow.
+ NativeWidgetMacTestWindow* MakeBorderlessNativeParent() {
+ NativeWidgetMacTestWindow* native_parent = nil;
+ Widget::InitParams parent_init_params =
+ CreateParams(Widget::InitParams::TYPE_WINDOW);
+ parent_init_params.remove_standard_frame = true;
+ parent_init_params.bounds = gfx::Rect(100, 100, 200, 200);
+ CreateWidgetWithTestWindow(parent_init_params, &native_parent);
+ return native_parent;
}
// Create a Widget backed by the NativeWidgetMacTestWindow NSWindow subclass.
@@ -187,9 +186,6 @@ class NativeWidgetMacTest : public WidgetTest {
return widget;
}
- protected:
- base::scoped_nsobject<TestNativeParentWindow> native_parent_;
-
private:
DISALLOW_COPY_AND_ASSIGN(NativeWidgetMacTest);
};
@@ -740,26 +736,27 @@ Widget* AttachPopupToNativeParent(NSWindow* native_parent) {
// Tests creating a views::Widget parented off a native NSWindow.
TEST_F(NativeWidgetMacTest, NonWidgetParent) {
- NSWindow* native_parent = MakeNativeParent();
+ NSWindow* native_parent = MakeBorderlessNativeParent();
Widget::Widgets children;
Widget::GetAllChildWidgets([native_parent contentView], &children);
- EXPECT_TRUE(children.empty());
+ EXPECT_EQ(1u, children.size());
Widget* child = AttachPopupToNativeParent(native_parent);
TestWidgetObserver child_observer(child);
- // GetTopLevelNativeWidget() only goes as far as there exists a Widget (i.e.
- // must stop at |child|.
+ // GetTopLevelNativeWidget() will go up through |native_parent|'s Widget.
internal::NativeWidgetPrivate* top_level_widget =
internal::NativeWidgetPrivate::GetTopLevelNativeWidget(
child->GetNativeView());
- EXPECT_EQ(child, top_level_widget->GetWidget());
+ EXPECT_EQ(Widget::GetWidgetForNativeWindow(native_parent),
+ top_level_widget->GetWidget());
+ EXPECT_NE(child, top_level_widget->GetWidget());
// To verify the parent, we need to use NativeWidgetMac APIs.
- BridgedNativeWidget* bridged_native_widget =
- NativeWidgetMac::GetBridgeForNativeWindow(child->GetNativeWindow());
- EXPECT_EQ(native_parent, bridged_native_widget->parent()->GetNSWindow());
+ BridgedNativeWidgetImpl* bridged_native_widget =
+ BridgedNativeWidgetImpl::GetFromNativeWindow(child->GetNativeWindow());
+ EXPECT_EQ(native_parent, bridged_native_widget->parent()->ns_window());
const gfx::Rect child_bounds(50, 50, 200, 100);
child->SetBounds(child_bounds);
@@ -774,8 +771,8 @@ TEST_F(NativeWidgetMacTest, NonWidgetParent) {
EXPECT_EQ(native_parent, [child->GetNativeWindow() parentWindow]);
Widget::GetAllChildWidgets([native_parent contentView], &children);
- ASSERT_EQ(1u, children.size());
- EXPECT_EQ(child, *children.begin());
+ ASSERT_EQ(2u, children.size());
+ EXPECT_EQ(1u, children.count(child));
// Only non-toplevel Widgets are positioned relative to the parent, so the
// bounds set above should be in screen coordinates.
@@ -786,7 +783,7 @@ TEST_F(NativeWidgetMacTest, NonWidgetParent) {
NSView* anchor_view = [[native_parent contentView] subviews][0];
EXPECT_TRUE(anchor_view);
[anchor_view removeFromSuperview];
- EXPECT_EQ(native_parent, bridged_native_widget->parent()->GetNSWindow());
+ EXPECT_EQ(native_parent, bridged_native_widget->parent()->ns_window());
// Closing the parent should close and destroy the child.
EXPECT_FALSE(child_observer.widget_closed());
@@ -794,6 +791,7 @@ TEST_F(NativeWidgetMacTest, NonWidgetParent) {
EXPECT_TRUE(child_observer.widget_closed());
EXPECT_EQ(0u, [[native_parent childWindows] count]);
+ [native_parent close];
}
// Tests that CloseAllSecondaryWidgets behaves in various configurations.
@@ -871,15 +869,16 @@ TEST_F(NativeWidgetMacTest, CloseAllSecondaryWidgetsValidState) {
TEST_F(NativeWidgetMacTest, NonWidgetParentLastReference) {
bool child_dealloced = false;
bool native_parent_dealloced = false;
+ NativeWidgetMacTestWindow* native_parent = nil;
{
base::mac::ScopedNSAutoreleasePool pool;
- TestNativeParentWindow* native_parent = MakeNativeParent();
+ native_parent = MakeBorderlessNativeParent();
[native_parent setDeallocFlag:&native_parent_dealloced];
NativeWidgetMacTestWindow* window;
Widget::InitParams init_params =
CreateParams(Widget::InitParams::TYPE_POPUP);
- init_params.parent = [native_parent_ contentView];
+ init_params.parent = [native_parent contentView];
init_params.bounds = gfx::Rect(0, 0, 100, 200);
CreateWidgetWithTestWindow(init_params, &window);
[window setDeallocFlag:&child_dealloced];
@@ -891,7 +890,7 @@ TEST_F(NativeWidgetMacTest, NonWidgetParentLastReference) {
// to the child window is released inside WidgetOwnerNSWindowAdapter::
// OnWindowWillClose().
base::mac::ScopedNSAutoreleasePool pool;
- [native_parent_.autorelease() close];
+ [native_parent close];
EXPECT_TRUE(child_dealloced);
}
EXPECT_TRUE(native_parent_dealloced);
@@ -900,7 +899,7 @@ TEST_F(NativeWidgetMacTest, NonWidgetParentLastReference) {
// Tests visibility for child of native NSWindow, reshowing after -[NSApp hide].
// Occasionally flaky (maybe due to [NSApp hide]). See https://crbug.com/777247.
TEST_F(NativeWidgetMacTest, DISABLED_VisibleAfterNativeParentShow) {
- NSWindow* native_parent = MakeNativeParent();
+ NSWindow* native_parent = MakeBorderlessNativeParent();
Widget* child = AttachPopupToNativeParent(native_parent);
child->Show();
EXPECT_TRUE(child->IsVisible());
@@ -925,7 +924,7 @@ TEST_F(NativeWidgetMacTest, VisibleAfterNativeParentDeminiaturize) {
if (base::mac::IsOS10_10())
return;
- NSWindow* native_parent = MakeNativeParent();
+ NSWindow* native_parent = MakeBorderlessNativeParent();
[native_parent makeKeyAndOrderFront:nil];
[native_parent miniaturize:nil];
Widget* child = AttachPopupToNativeParent(native_parent);
@@ -1173,9 +1172,9 @@ Widget* ShowWindowModalWidget(NSWindow* native_parent) {
} // namespace
// Tests object lifetime for the show/hide animations used for child-modal
-// windows. Parents the dialog off a native parent window (not a views::Widget).
+// windows.
TEST_F(NativeWidgetMacTest, NativeWindowChildModalShowHide) {
- NSWindow* native_parent = MakeNativeParent();
+ NSWindow* native_parent = MakeBorderlessNativeParent();
{
Widget* modal_dialog_widget = ShowChildModalWidgetAndWait(native_parent);
TestWidgetObserver widget_observer(modal_dialog_widget);
@@ -1228,7 +1227,7 @@ TEST_F(NativeWidgetMacTest, NativeWindowChildModalShowHide) {
// Tests that calls to Hide() a Widget cancel any in-progress show animation,
// and that clients can control the triggering of the animation.
TEST_F(NativeWidgetMacTest, ShowAnimationControl) {
- NSWindow* native_parent = MakeNativeParent();
+ NSWindow* native_parent = MakeBorderlessNativeParent();
Widget* modal_dialog_widget = views::DialogDelegate::CreateDialogWidget(
new ModalDialogDelegate(ui::MODAL_TYPE_CHILD), nullptr,
[native_parent contentView]);
@@ -1247,7 +1246,7 @@ TEST_F(NativeWidgetMacTest, ShowAnimationControl) {
EXPECT_TRUE([retained_animation isAnimating]);
// Hide without waiting for the animation to complete. Animation should cancel
- // and clear references from BridgedNativeWidget.
+ // and clear references from BridgedNativeWidgetImpl.
modal_dialog_widget->Hide();
EXPECT_FALSE([retained_animation isAnimating]);
EXPECT_FALSE(test_api.show_animation());
@@ -1286,8 +1285,7 @@ TEST_F(NativeWidgetMacTest, ShowAnimationControl) {
// Tests behavior of window-modal dialogs, displayed as sheets.
TEST_F(NativeWidgetMacTest, WindowModalSheet) {
- NSWindow* native_parent =
- MakeNativeParentWithStyle(NSClosableWindowMask | NSTitledWindowMask);
+ NSWindow* native_parent = MakeClosableTitledNativeParent();
Widget* sheet_widget = views::DialogDelegate::CreateDialogWidget(
new ModalDialogDelegate(ui::MODAL_TYPE_WINDOW), nullptr,
@@ -1328,7 +1326,7 @@ TEST_F(NativeWidgetMacTest, WindowModalSheet) {
Widget::Widgets children;
Widget::GetAllChildWidgets([native_parent contentView], &children);
- EXPECT_TRUE(children.empty());
+ ASSERT_EQ(2u, children.size());
sheet_widget->Show(); // Should run the above block, then animate the sheet.
EXPECT_TRUE(did_observe);
@@ -1336,8 +1334,8 @@ TEST_F(NativeWidgetMacTest, WindowModalSheet) {
// Ensure sheets are included as a child.
Widget::GetAllChildWidgets([native_parent contentView], &children);
- ASSERT_EQ(1u, children.size());
- EXPECT_EQ(sheet_widget, *children.begin());
+ ASSERT_EQ(2u, children.size());
+ EXPECT_TRUE(children.count(sheet_widget));
// Modal, so the close button in the parent window should get disabled.
EXPECT_FALSE([parent_close_button isEnabled]);
@@ -1348,9 +1346,9 @@ TEST_F(NativeWidgetMacTest, WindowModalSheet) {
// TODO(tapted): Ideally [native_parent orderOut:nil] would also work here.
// But it does not. AppKit's childWindow management breaks down after an
- // -orderOut: (see BridgedNativeWidget::OnVisibilityChanged()). For regular
- // child windows, BridgedNativeWidget fixes the behavior with its own
- // management. However, it can't do that for sheets without encountering
+ // -orderOut: (see BridgedNativeWidgetImpl::OnVisibilityChanged()). For
+ // regular child windows, BridgedNativeWidgetImpl fixes the behavior with its
+ // own management. However, it can't do that for sheets without encountering
// http://crbug.com/605098 and http://crbug.com/667602. -[NSApp hide:] makes
// the NSWindow hidden in a different way, which does not break like
// -orderOut: does. Which is good, because a user can always do -[NSApp
@@ -1368,41 +1366,24 @@ TEST_F(NativeWidgetMacTest, WindowModalSheet) {
sheet_widget->Close();
EXPECT_TRUE(sheet_widget->IsVisible());
- did_observe = false;
-
- // Experimentally (on 10.10), this notification is posted from within the
- // -[NSWindow orderOut:] call that is triggered from -[ViewsNSWindowDelegate
- // sheetDidEnd:]. |sheet_widget| will be destroyed next, so it's still safe to
- // use in the block. However, since the orderOut just happened, it's not very
- // interesting.
- observer = [[NSNotificationCenter defaultCenter]
- addObserverForName:NSWindowDidEndSheetNotification
- object:native_parent
- queue:nil
- usingBlock:^(NSNotification* note) {
- EXPECT_TRUE([sheet_window delegate]);
- *did_observe_ptr = true;
- }];
-
// Pump in order to trigger -[NSWindow endSheet:..], which will block while
// the animation runs, then delete |sheet_widget|.
EXPECT_TRUE([sheet_window delegate]);
base::RunLoop().RunUntilIdle();
EXPECT_FALSE([sheet_window delegate]);
-
- EXPECT_TRUE(did_observe); // Also ensures the Close() actually uses sheets.
[[NSNotificationCenter defaultCenter] removeObserver:observer];
EXPECT_TRUE(widget_observer.widget_closed());
EXPECT_TRUE([parent_close_button isEnabled]);
+
+ [native_parent close];
}
// Tests behavior when closing a window that is a sheet, or that hosts a sheet,
// and reshowing a sheet on a window after the sheet was closed with -[NSWindow
// close].
TEST_F(NativeWidgetMacTest, CloseWithWindowModalSheet) {
- NSWindow* native_parent =
- MakeNativeParentWithStyle(NSClosableWindowMask | NSTitledWindowMask);
+ NSWindow* native_parent = MakeClosableTitledNativeParent();
{
Widget* sheet_widget = ShowWindowModalWidget(native_parent);
@@ -1496,8 +1477,7 @@ TEST_F(NativeWidgetMacTest, CloseWithWindowModalSheet) {
// eventually complete on a destroyed NSWindowDelegate. Regression test for
// https://crbug.com/851376.
TEST_F(NativeWidgetMacTest, CloseWindowModalSheetWithoutSheetParent) {
- NSWindow* native_parent =
- MakeNativeParentWithStyle(NSClosableWindowMask | NSTitledWindowMask);
+ NSWindow* native_parent = MakeClosableTitledNativeParent();
{
base::mac::ScopedNSAutoreleasePool pool;
Widget* sheet_widget = ShowWindowModalWidget(native_parent);
@@ -1541,17 +1521,16 @@ TEST_F(NativeWidgetMacTest, CloseWindowModalSheetWithoutSheetParent) {
}
// Test calls to Widget::ReparentNativeView() that result in a no-op on Mac.
-// Tests with both native and non-native parents.
TEST_F(NativeWidgetMacTest, NoopReparentNativeView) {
- NSWindow* parent = MakeNativeParent();
+ NSWindow* parent = MakeBorderlessNativeParent();
Widget* dialog = views::DialogDelegate::CreateDialogWidget(
new DialogDelegateView, nullptr, [parent contentView]);
- BridgedNativeWidget* bridge =
- NativeWidgetMac::GetBridgeForNativeWindow(dialog->GetNativeWindow());
+ BridgedNativeWidgetImpl* bridge =
+ BridgedNativeWidgetImpl::GetFromNativeWindow(dialog->GetNativeWindow());
- EXPECT_EQ(bridge->parent()->GetNSWindow(), parent);
+ EXPECT_EQ(bridge->parent()->ns_window(), parent);
Widget::ReparentNativeView(dialog->GetNativeView(), [parent contentView]);
- EXPECT_EQ(bridge->parent()->GetNSWindow(), parent);
+ EXPECT_EQ(bridge->parent()->ns_window(), parent);
[parent close];
@@ -1559,11 +1538,12 @@ TEST_F(NativeWidgetMacTest, NoopReparentNativeView) {
parent = parent_widget->GetNativeWindow();
dialog = views::DialogDelegate::CreateDialogWidget(
new DialogDelegateView, nullptr, [parent contentView]);
- bridge = NativeWidgetMac::GetBridgeForNativeWindow(dialog->GetNativeWindow());
+ bridge =
+ BridgedNativeWidgetImpl::GetFromNativeWindow(dialog->GetNativeWindow());
- EXPECT_EQ(bridge->parent()->GetNSWindow(), parent);
+ EXPECT_EQ(bridge->parent()->ns_window(), parent);
Widget::ReparentNativeView(dialog->GetNativeView(), [parent contentView]);
- EXPECT_EQ(bridge->parent()->GetNSWindow(), parent);
+ EXPECT_EQ(bridge->parent()->ns_window(), parent);
parent_widget->CloseNow();
}
@@ -1778,7 +1758,7 @@ TEST_F(NativeWidgetMacTest, DISABLED_DoesHideTitle) {
// The default window with a title should look different from the
// window with an empty title.
- EXPECT_FALSE([empty_title_data isEqualToData:this_title_data]);
+ EXPECT_NSNE(empty_title_data, this_title_data);
delegate.set_should_show_title(false);
delegate.set_title(base::ASCIIToUTF16("This is another title"));
@@ -1788,7 +1768,7 @@ TEST_F(NativeWidgetMacTest, DISABLED_DoesHideTitle) {
// With our magic setting, the window with a title should look the
// same as the window with an empty title.
EXPECT_TRUE([ns_window _isTitleHidden]);
- EXPECT_TRUE([empty_title_data isEqualToData:hidden_title_data]);
+ EXPECT_NSEQ(empty_title_data, hidden_title_data);
widget->CloseNow();
}
@@ -2068,13 +2048,16 @@ TEST_F(NativeWidgetMacTest, ReparentNativeViewTypes) {
CreateParams(Widget::InitParams::TYPE_POPUP);
toplevel_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
toplevel1->Init(toplevel_params);
+ toplevel1->Show();
std::unique_ptr<Widget> toplevel2(new Widget);
toplevel2->Init(toplevel_params);
+ toplevel2->Show();
Widget* child = new Widget;
Widget::InitParams child_params(Widget::InitParams::TYPE_CONTROL);
child->Init(child_params);
+ child->Show();
Widget::ReparentNativeView(child->GetNativeView(),
toplevel1->GetNativeView());
@@ -2106,8 +2089,8 @@ class NativeWidgetMacFullKeyboardAccessTest : public NativeWidgetMacTest {
NativeWidgetMacTest::SetUp();
widget_ = CreateTopLevelPlatformWidget();
- bridge_ =
- NativeWidgetMac::GetBridgeForNativeWindow(widget_->GetNativeWindow());
+ bridge_ = BridgedNativeWidgetImpl::GetFromNativeWindow(
+ widget_->GetNativeWindow());
fake_full_keyboard_access_ =
ui::test::ScopedFakeFullKeyboardAccess::GetInstance();
DCHECK(fake_full_keyboard_access_);
@@ -2120,7 +2103,7 @@ class NativeWidgetMacFullKeyboardAccessTest : public NativeWidgetMacTest {
}
Widget* widget_ = nullptr;
- BridgedNativeWidget* bridge_ = nullptr;
+ BridgedNativeWidgetImpl* bridge_ = nullptr;
ui::test::ScopedFakeFullKeyboardAccess* fake_full_keyboard_access_ = nullptr;
};
@@ -2179,8 +2162,7 @@ class NativeWidgetMacViewsOrderTest : public WidgetTest {
widget_ = CreateTopLevelPlatformWidget();
- ASSERT_EQ(1u, [[widget_->GetNativeView() subviews] count]);
- compositor_view_ = [[widget_->GetNativeView() subviews] firstObject];
+ starting_subviews_.reset([[widget_->GetNativeView() subviews] copy]);
native_host_parent_ = new View();
widget_->GetContentsView()->AddChildView(native_host_parent_);
@@ -2193,9 +2175,10 @@ class NativeWidgetMacViewsOrderTest : public WidgetTest {
hosts_.push_back(std::move(holder));
}
EXPECT_EQ(kNativeViewCount, native_host_parent_->child_count());
- EXPECT_TRUE(([[widget_->GetNativeView() subviews] isEqualToArray:@[
- compositor_view_, hosts_[0]->view(), hosts_[1]->view(), hosts_[2]->view()
- ]]));
+ EXPECT_NSEQ([widget_->GetNativeView() subviews],
+ ([GetStartingSubviews() arrayByAddingObjectsFromArray:@[
+ hosts_[0]->view(), hosts_[1]->view(), hosts_[2]->view()
+ ]]));
}
void TearDown() override {
@@ -2205,10 +2188,12 @@ class NativeWidgetMacViewsOrderTest : public WidgetTest {
NSView* GetContentNativeView() { return widget_->GetNativeView(); }
+ NSArray<NSView*>* GetStartingSubviews() { return starting_subviews_; }
+
Widget* widget_ = nullptr;
View* native_host_parent_ = nullptr;
- NSView* compositor_view_ = nil;
std::vector<std::unique_ptr<NativeHostHolder>> hosts_;
+ base::scoped_nsobject<NSArray<NSView*>> starting_subviews_;
private:
DISALLOW_COPY_AND_ASSIGN(NativeWidgetMacViewsOrderTest);
@@ -2218,61 +2203,65 @@ class NativeWidgetMacViewsOrderTest : public WidgetTest {
// z-order.
TEST_F(NativeWidgetMacViewsOrderTest, NativeViewAttached) {
hosts_[1]->Detach();
- EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[
- compositor_view_, hosts_[0]->view(), hosts_[2]->view()
- ]]));
+ EXPECT_NSEQ([GetContentNativeView() subviews],
+ ([GetStartingSubviews() arrayByAddingObjectsFromArray:@[
+ hosts_[0]->view(), hosts_[2]->view()
+ ]]));
hosts_[1]->AttachNativeView();
- EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[
- compositor_view_, hosts_[0]->view(), hosts_[1]->view(),
- hosts_[2]->view()
- ]]));
+ EXPECT_NSEQ([GetContentNativeView() subviews],
+ ([GetStartingSubviews() arrayByAddingObjectsFromArray:@[
+ hosts_[0]->view(), hosts_[1]->view(), hosts_[2]->view()
+ ]]));
}
// Tests that NativeViews order changes according to views::View hierarchy.
TEST_F(NativeWidgetMacViewsOrderTest, ReorderViews) {
native_host_parent_->ReorderChildView(hosts_[2]->host(), 1);
- EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[
- compositor_view_, hosts_[0]->view(), hosts_[2]->view(),
- hosts_[1]->view()
- ]]));
+ EXPECT_NSEQ([GetContentNativeView() subviews],
+ ([GetStartingSubviews() arrayByAddingObjectsFromArray:@[
+ hosts_[0]->view(), hosts_[2]->view(), hosts_[1]->view()
+ ]]));
native_host_parent_->RemoveChildView(hosts_[2]->host());
- EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[
- compositor_view_, hosts_[0]->view(), hosts_[1]->view()
- ]]));
+ EXPECT_NSEQ([GetContentNativeView() subviews],
+ ([GetStartingSubviews() arrayByAddingObjectsFromArray:@[
+ hosts_[0]->view(), hosts_[1]->view()
+ ]]));
View* new_parent = new View();
native_host_parent_->RemoveChildView(hosts_[1]->host());
native_host_parent_->AddChildView(new_parent);
new_parent->AddChildView(hosts_[1]->host());
new_parent->AddChildView(hosts_[2]->host());
- EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[
- compositor_view_, hosts_[0]->view(), hosts_[1]->view(),
- hosts_[2]->view()
- ]]));
+ EXPECT_NSEQ([GetContentNativeView() subviews],
+ ([GetStartingSubviews() arrayByAddingObjectsFromArray:@[
+ hosts_[0]->view(), hosts_[1]->view(), hosts_[2]->view()
+ ]]));
native_host_parent_->ReorderChildView(new_parent, 0);
- EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[
- compositor_view_, hosts_[1]->view(), hosts_[2]->view(),
- hosts_[0]->view()
- ]]));
+ EXPECT_NSEQ([GetContentNativeView() subviews],
+ ([GetStartingSubviews() arrayByAddingObjectsFromArray:@[
+ hosts_[1]->view(), hosts_[2]->view(), hosts_[0]->view()
+ ]]));
}
// Test that unassociated native views stay on top after reordering.
TEST_F(NativeWidgetMacViewsOrderTest, UnassociatedViewsIsAbove) {
base::scoped_nsobject<NSView> child_view([[NSView alloc] init]);
[GetContentNativeView() addSubview:child_view];
- EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[
- compositor_view_, hosts_[0]->view(), hosts_[1]->view(),
- hosts_[2]->view(), child_view
- ]]));
+ EXPECT_NSEQ(
+ [GetContentNativeView() subviews],
+ ([GetStartingSubviews() arrayByAddingObjectsFromArray:@[
+ hosts_[0]->view(), hosts_[1]->view(), hosts_[2]->view(), child_view
+ ]]));
native_host_parent_->ReorderChildView(hosts_[2]->host(), 1);
- EXPECT_TRUE(([[GetContentNativeView() subviews] isEqualToArray:@[
- compositor_view_, hosts_[0]->view(), hosts_[2]->view(),
- hosts_[1]->view(), child_view
- ]]));
+ EXPECT_NSEQ(
+ [GetContentNativeView() subviews],
+ ([GetStartingSubviews() arrayByAddingObjectsFromArray:@[
+ hosts_[0]->view(), hosts_[2]->view(), hosts_[1]->view(), child_view
+ ]]));
}
// Test -[NSWindowDelegate windowShouldClose:].
@@ -2421,18 +2410,3 @@ TEST_F(NativeWidgetMacTest, TouchBar) {
}
@end
-@implementation TestNativeParentWindow {
- bool* deallocFlag_;
-}
-
-@synthesize deallocFlag = deallocFlag_;
-
-- (void)dealloc {
- if (deallocFlag_) {
- DCHECK(!*deallocFlag_);
- *deallocFlag_ = true;
- }
- [super dealloc];
-}
-
-@end
diff --git a/chromium/ui/views/widget/widget.cc b/chromium/ui/views/widget/widget.cc
index 5ad48b616fa..0353201e793 100644
--- a/chromium/ui/views/widget/widget.cc
+++ b/chromium/ui/views/widget/widget.cc
@@ -1058,11 +1058,13 @@ bool Widget::OnNativeWidgetActivationChanged(bool active) {
}
void Widget::OnNativeFocus() {
- WidgetFocusManager::GetInstance()->OnNativeFocusChanged(GetNativeView());
+ WidgetFocusManager::GetInstance(GetNativeWindow())
+ ->OnNativeFocusChanged(GetNativeView());
}
void Widget::OnNativeBlur() {
- WidgetFocusManager::GetInstance()->OnNativeFocusChanged(nullptr);
+ WidgetFocusManager::GetInstance(GetNativeWindow())
+ ->OnNativeFocusChanged(nullptr);
}
void Widget::OnNativeWidgetVisibilityChanging(bool visible) {
diff --git a/chromium/ui/views/widget/widget_unittest.cc b/chromium/ui/views/widget/widget_unittest.cc
index 24c23336a45..352e4fbfe64 100644
--- a/chromium/ui/views/widget/widget_unittest.cc
+++ b/chromium/ui/views/widget/widget_unittest.cc
@@ -2034,11 +2034,6 @@ TEST_F(WidgetWindowTitleTest, SetWindowTitleChanged_DesktopNativeWidget) {
#endif // !OS_CHROMEOS
TEST_F(WidgetTest, WidgetDeleted_InOnMousePressed) {
- // TODO: test uses GetContext(), which is not applicable to aura-mus.
- // http://crbug.com/663809.
- if (IsMus())
- return;
-
Widget* widget = new Widget;
Widget::InitParams params =
CreateParams(views::Widget::InitParams::TYPE_POPUP);
@@ -2049,10 +2044,14 @@ TEST_F(WidgetTest, WidgetDeleted_InOnMousePressed) {
widget->SetSize(gfx::Size(100, 100));
widget->Show();
- ui::test::EventGenerator generator(GetContext(), widget->GetNativeWindow());
+ ui::test::EventGenerator generator(
+ IsMus() ? widget->GetNativeWindow() : GetContext(),
+ widget->GetNativeWindow());
WidgetDeletionObserver deletion_observer(widget);
- generator.ClickLeftButton();
+ generator.PressLeftButton();
+ if (deletion_observer.IsWidgetAlive())
+ generator.ReleaseLeftButton();
EXPECT_FALSE(deletion_observer.IsWidgetAlive());
// Yay we did not crash!
@@ -4080,7 +4079,7 @@ class CompositingWidgetTest : public views::test::WidgetTest {
const Widget::InitParams::WindowOpacity opacity) {
for (const auto& widget_type : widget_types_) {
#if defined(OS_MACOSX)
- // Tooltips are native on Mac. See BridgedNativeWidget::Init.
+ // Tooltips are native on Mac. See BridgedNativeWidgetImpl::Init.
if (widget_type == Widget::InitParams::TYPE_TOOLTIP)
continue;
#elif defined(OS_WIN)
diff --git a/chromium/ui/views/widget/widget_utils_mac.mm b/chromium/ui/views/widget/widget_utils_mac.mm
index 58d0a437fb0..990e17faf2f 100644
--- a/chromium/ui/views/widget/widget_utils_mac.mm
+++ b/chromium/ui/views/widget/widget_utils_mac.mm
@@ -4,13 +4,13 @@
#include "ui/views/widget/widget_utils_mac.h"
-#import "ui/views/cocoa/bridged_native_widget.h"
+#import "ui/views_bridge_mac/bridged_native_widget_impl.h"
namespace views {
gfx::Size GetWindowSizeForClientSize(Widget* widget, const gfx::Size& size) {
DCHECK(widget);
- return BridgedNativeWidget::GetWindowSizeForClientSize(
+ return BridgedNativeWidgetImpl::GetWindowSizeForClientSize(
widget->GetNativeWindow(), size);
}
diff --git a/chromium/ui/views/widget/window_reorderer.cc b/chromium/ui/views/widget/window_reorderer.cc
index 2f83b18fbd9..2f459a861d6 100644
--- a/chromium/ui/views/widget/window_reorderer.cc
+++ b/chromium/ui/views/widget/window_reorderer.cc
@@ -166,14 +166,13 @@ void WindowReorderer::ReorderChildWindows() {
// |view_with_layer_order| backwards and stack windows at the bottom so that
// windows not associated to a view are stacked above windows with an
// associated view.
- for (std::vector<View*>::reverse_iterator it = view_with_layer_order.rbegin();
+ for (auto it = view_with_layer_order.rbegin();
it != view_with_layer_order.rend(); ++it) {
View* view = *it;
ui::Layer* layer = view->layer();
aura::Window* window = NULL;
- std::map<View*, aura::Window*>::iterator hosted_window_it =
- hosted_windows.find(view);
+ auto hosted_window_it = hosted_windows.find(view);
if (hosted_window_it != hosted_windows.end()) {
window = hosted_window_it->second;
layer = window->layer();
diff --git a/chromium/ui/views/widget/window_reorderer_unittest.cc b/chromium/ui/views/widget/window_reorderer_unittest.cc
index 579e622ee73..faecf6bf9ab 100644
--- a/chromium/ui/views/widget/window_reorderer_unittest.cc
+++ b/chromium/ui/views/widget/window_reorderer_unittest.cc
@@ -39,9 +39,8 @@ void SetWindowAndLayerName(aura::Window* window, const std::string& name) {
// first) of |parent|. The format of the string is "name1 name2 name3 ...".
std::string ChildWindowNamesAsString(const aura::Window& parent) {
std::string names;
- typedef std::vector<aura::Window*> Windows;
- for (Windows::const_iterator it = parent.children().begin();
- it != parent.children().end(); ++it) {
+ for (auto it = parent.children().begin(); it != parent.children().end();
+ ++it) {
if (!names.empty())
names += " ";
names += (*it)->GetName();
diff --git a/chromium/ui/views/win/hwnd_message_handler.cc b/chromium/ui/views/win/hwnd_message_handler.cc
index 54eb0fcd0bf..9afbcf6ca30 100644
--- a/chromium/ui/views/win/hwnd_message_handler.cc
+++ b/chromium/ui/views/win/hwnd_message_handler.cc
@@ -1000,12 +1000,14 @@ void HWNDMessageHandler::OnBlur() {}
void HWNDMessageHandler::OnCaretBoundsChanged(
const ui::TextInputClient* client) {
- if (!client || client->GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
- return;
-
if (!ax_system_caret_)
ax_system_caret_ = std::make_unique<ui::AXSystemCaretWin>(hwnd());
+ if (!client || client->GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE) {
+ ax_system_caret_->Hide();
+ return;
+ }
+
const gfx::Rect dip_caret_bounds(client->GetCaretBounds());
gfx::Rect caret_bounds =
display::win::ScreenWin::DIPToScreenRect(hwnd(), dip_caret_bounds);
@@ -1015,7 +1017,10 @@ void HWNDMessageHandler::OnCaretBoundsChanged(
}
void HWNDMessageHandler::OnTextInputStateChanged(
- const ui::TextInputClient* client) {}
+ const ui::TextInputClient* client) {
+ if (!client || client->GetTextInputType() == ui::TEXT_INPUT_TYPE_NONE)
+ OnCaretBoundsChanged(client);
+}
void HWNDMessageHandler::OnInputMethodDestroyed(
const ui::InputMethod* input_method) {
@@ -1586,8 +1591,7 @@ LRESULT HWNDMessageHandler::OnCreate(CREATESTRUCT* create_struct) {
base::Bind(&HWNDMessageHandler::OnSessionChange,
base::Unretained(this))));
- float scale_factor = display::win::ScreenWin::GetScaleFactorForHWND(hwnd());
- dpi_ = display::win::GetDPIFromScalingFactor(scale_factor);
+ dpi_ = display::win::ScreenWin::GetDPIForHWND(hwnd());
// TODO(beng): move more of NWW::OnCreate here.
return 0;
@@ -1642,7 +1646,7 @@ LRESULT HWNDMessageHandler::OnDpiChanged(UINT msg,
dpi = display::win::GetDPIFromScalingFactor(scaling_factor);
} else {
dpi = LOWORD(w_param);
- scaling_factor = display::win::GetScalingFactorFromDPI(dpi);
+ scaling_factor = display::win::ScreenWin::GetScaleFactorForDPI(dpi);
}
// The first WM_DPICHANGED originates from EnableChildWindowDpiMessage during
@@ -2967,8 +2971,8 @@ LRESULT HWNDMessageHandler::HandlePointerEventTypeTouch(UINT message,
event_type, touch_point, event_time,
ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH,
mapped_pointer_id, radius_x, radius_y, pressure,
- pointer_touch_info.orientation, 0.0f, 0.0f, 0.0f),
- ui::GetModifiersFromKeyState(), rotation_angle);
+ rotation_angle),
+ ui::GetModifiersFromKeyState());
event.latency()->AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, event_time, 1);
diff --git a/chromium/ui/views/win/pen_event_processor.cc b/chromium/ui/views/win/pen_event_processor.cc
index b820c51be5e..e1429935534 100644
--- a/chromium/ui/views/win/pen_event_processor.cc
+++ b/chromium/ui/views/win/pen_event_processor.cc
@@ -56,12 +56,14 @@ std::unique_ptr<ui::Event> PenEventProcessor::GenerateEvent(
// convert pressure into a float [0, 1]. The range of the pressure is
// [0, 1024] as specified on MSDN.
float pressure = static_cast<float>(pointer_pen_info.pressure) / 1024;
- float rotation = pointer_pen_info.rotation;
+ int rotation_angle = static_cast<int>(pointer_pen_info.rotation) % 180;
+ if (rotation_angle < 0)
+ rotation_angle += 180;
int tilt_x = pointer_pen_info.tiltX;
int tilt_y = pointer_pen_info.tiltY;
ui::PointerDetails pointer_details(
input_type, mapped_pointer_id, /* radius_x */ 0.0f, /* radius_y */ 0.0f,
- pressure, rotation, tilt_x, tilt_y, /* tangential_pressure */ 0.0f);
+ pressure, rotation_angle, tilt_x, tilt_y, /* tangential_pressure */ 0.0f);
// If the flag is disabled, we send mouse events for all pen inputs.
if (!direct_manipulation_enabled_) {
@@ -186,12 +188,9 @@ std::unique_ptr<ui::Event> PenEventProcessor::GenerateTouchEvent(
const base::TimeTicks event_time = ui::EventTimeForNow();
- int rotation_angle = static_cast<int>(pointer_details.twist) % 180;
- if (rotation_angle < 0)
- rotation_angle += 180;
std::unique_ptr<ui::TouchEvent> event = std::make_unique<ui::TouchEvent>(
event_type, point, event_time, pointer_details,
- flags | ui::GetModifiersFromKeyState(), rotation_angle);
+ flags | ui::GetModifiersFromKeyState());
event->set_hovering(event_type == ui::ET_TOUCH_RELEASED);
event->latency()->AddLatencyNumberWithTimestamp(
ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, event_time, 1);
diff --git a/chromium/ui/views/window/custom_frame_view.cc b/chromium/ui/views/window/custom_frame_view.cc
index 0ae8ebd9ad3..01a5c58eb39 100644
--- a/chromium/ui/views/window/custom_frame_view.cc
+++ b/chromium/ui/views/window/custom_frame_view.cc
@@ -522,8 +522,7 @@ void CustomFrameView::LayoutWindowControls() {
button_order->trailing_buttons();
ImageButton* button = NULL;
- for (std::vector<views::FrameButton>::const_iterator it =
- leading_buttons.begin(); it != leading_buttons.end(); ++it) {
+ for (auto it = leading_buttons.begin(); it != leading_buttons.end(); ++it) {
button = GetImageButton(*it);
if (!button)
continue;
@@ -538,8 +537,8 @@ void CustomFrameView::LayoutWindowControls() {
// Trailing buttions are laid out in a RTL fashion
next_button_x = width() - FrameBorderThickness();
- for (std::vector<views::FrameButton>::const_reverse_iterator it =
- trailing_buttons.rbegin(); it != trailing_buttons.rend(); ++it) {
+ for (auto it = trailing_buttons.rbegin(); it != trailing_buttons.rend();
+ ++it) {
button = GetImageButton(*it);
if (!button)
continue;
diff --git a/chromium/ui/views/window/dialog_client_view.cc b/chromium/ui/views/window/dialog_client_view.cc
index 40cc9f35cfa..7c5c56f4c27 100644
--- a/chromium/ui/views/window/dialog_client_view.cc
+++ b/chromium/ui/views/window/dialog_client_view.cc
@@ -17,6 +17,7 @@
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/button/md_text_button.h"
+#include "ui/views/event_utils.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/layout/layout_provider.h"
#include "ui/views/style/platform_style.h"
@@ -164,6 +165,13 @@ gfx::Size DialogClientView::GetMaximumSize() const {
return max_size;
}
+void DialogClientView::VisibilityChanged(View* starting_from, bool is_visible) {
+ ClientView::VisibilityChanged(starting_from, is_visible);
+
+ if (is_visible)
+ view_shown_time_stamp_ = base::TimeTicks::Now();
+}
+
void DialogClientView::Layout() {
button_row_container_->SetSize(
gfx::Size(width(), button_row_container_->GetHeightForWidth(width())));
@@ -234,6 +242,9 @@ void DialogClientView::ButtonPressed(Button* sender, const ui::Event& event) {
if (!GetDialogDelegate())
return;
+ if (IsPossiblyUnintendedInteraction(view_shown_time_stamp_, event))
+ return;
+
if (sender == ok_button_)
AcceptWindow();
else if (sender == cancel_button_)
@@ -242,6 +253,10 @@ void DialogClientView::ButtonPressed(Button* sender, const ui::Event& event) {
NOTREACHED();
}
+void DialogClientView::ResetViewShownTimeStampForTesting() {
+ view_shown_time_stamp_ = base::TimeTicks();
+}
+
////////////////////////////////////////////////////////////////////////////////
// DialogClientView, private:
diff --git a/chromium/ui/views/window/dialog_client_view.h b/chromium/ui/views/window/dialog_client_view.h
index 108d9776d0b..3981e4f8b6c 100644
--- a/chromium/ui/views/window/dialog_client_view.h
+++ b/chromium/ui/views/window/dialog_client_view.h
@@ -7,6 +7,7 @@
#include "base/gtest_prod_util.h"
#include "base/macros.h"
+#include "base/time/time.h"
#include "ui/base/ui_base_types.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/window/client_view.h"
@@ -54,6 +55,7 @@ class VIEWS_EXPORT DialogClientView : public ClientView,
gfx::Size CalculatePreferredSize() const override;
gfx::Size GetMinimumSize() const override;
gfx::Size GetMaximumSize() const override;
+ void VisibilityChanged(View* starting_from, bool is_visible) override;
void Layout() override;
bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
@@ -66,6 +68,11 @@ class VIEWS_EXPORT DialogClientView : public ClientView,
void set_minimum_size(const gfx::Size& size) { minimum_size_ = size; }
+ // Resets the time when view has been shown. Tests may need to call this
+ // method if they use events that could be otherwise treated as unintended.
+ // See IsPossiblyUnintendedInteraction().
+ void ResetViewShownTimeStampForTesting();
+
private:
enum {
// The number of buttons that DialogClientView can support.
@@ -134,6 +141,9 @@ class VIEWS_EXPORT DialogClientView : public ClientView,
// SetupLayout(). Everything will be manually updated afterwards.
bool adding_or_removing_views_ = false;
+ // Time when view has been shown.
+ base::TimeTicks view_shown_time_stamp_;
+
DISALLOW_COPY_AND_ASSIGN(DialogClientView);
};
diff --git a/chromium/ui/views/window/dialog_client_view_unittest.cc b/chromium/ui/views/window/dialog_client_view_unittest.cc
index d3f0d56cf04..4c4e67e7dbc 100644
--- a/chromium/ui/views/window/dialog_client_view_unittest.cc
+++ b/chromium/ui/views/window/dialog_client_view_unittest.cc
@@ -8,11 +8,16 @@
#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
+#include "base/time/time.h"
#include "build/build_config.h"
#include "ui/base/ui_base_types.h"
+#include "ui/events/base_event_utils.h"
+#include "ui/events/event.h"
+#include "ui/gfx/geometry/point.h"
#include "ui/views/controls/button/checkbox.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/button/label_button.h"
+#include "ui/views/metrics.h"
#include "ui/views/style/platform_style.h"
#include "ui/views/test/test_layout_provider.h"
#include "ui/views/test/test_views.h"
@@ -505,4 +510,24 @@ TEST_F(DialogClientViewTest, FocusChangingButtons) {
EXPECT_EQ(nullptr, focus_manager->GetFocusedView());
}
+// Ensures that clicks are ignored for short time after view has been shown.
+TEST_F(DialogClientViewTest, IgnorePossiblyUnintendedClicks) {
+ widget()->Show();
+ SetDialogButtons(ui::DIALOG_BUTTON_CANCEL | ui::DIALOG_BUTTON_OK);
+
+ ui::MouseEvent mouse_event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+ ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
+ client_view()->ButtonPressed(client_view()->ok_button(), mouse_event);
+ client_view()->ButtonPressed(client_view()->cancel_button(), mouse_event);
+ EXPECT_FALSE(widget()->IsClosed());
+
+ client_view()->ButtonPressed(
+ client_view()->cancel_button(),
+ ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+ ui::EventTimeForNow() + base::TimeDelta::FromMilliseconds(
+ GetDoubleClickInterval()),
+ ui::EF_NONE, ui::EF_NONE));
+ EXPECT_TRUE(widget()->IsClosed());
+}
+
} // namespace views
diff --git a/chromium/ui/views_bridge_mac/BUILD.gn b/chromium/ui/views_bridge_mac/BUILD.gn
index 81c1add7699..1043a8aa7bb 100644
--- a/chromium/ui/views_bridge_mac/BUILD.gn
+++ b/chromium/ui/views_bridge_mac/BUILD.gn
@@ -4,16 +4,41 @@
import("//mojo/public/tools/bindings/mojom.gni")
+component("views_bridge_mac") {
+ assert(is_mac)
+
+ sources = [
+ "bridged_native_widget_host_helper.h",
+ "cocoa_mouse_capture.h",
+ "cocoa_mouse_capture.mm",
+ "cocoa_mouse_capture_delegate.h",
+ "drag_drop_client.h",
+ "views_bridge_mac_export.h",
+ ]
+ defines = [ "VIEWS_BRIDGE_MAC_IMPLEMENTATION" ]
+ deps = [
+ "//base",
+ "//ui/base",
+ "//ui/events",
+ "//ui/gfx",
+ ]
+ libs = [ "Cocoa.framework" ]
+}
+
mojom("mojo") {
- cpp_only = true
+ assert(is_mac)
sources = [
+ "mojo/bridge_factory.mojom",
"mojo/bridged_native_widget.mojom",
+ "mojo/bridged_native_widget_host.mojom",
]
public_deps = [
"//mojo/public/mojom/base",
"//ui/base/mojo",
+ "//ui/display/mojo:interfaces",
+ "//ui/events/mojo:interfaces",
"//ui/gfx/geometry/mojo",
"//ui/gfx/mojo",
]
diff --git a/chromium/ui/views_bridge_mac/DEPS b/chromium/ui/views_bridge_mac/DEPS
index b51da65b022..612029d43cb 100644
--- a/chromium/ui/views_bridge_mac/DEPS
+++ b/chromium/ui/views_bridge_mac/DEPS
@@ -1,4 +1,17 @@
include_rules = [
+ "+components/crash/core/common/crash_key.h",
+ "+components/viz/common",
+ "+mojo/public/cpp/bindings",
+ "+skia/ext",
+ "+ui/accelerated_widget_mac",
"+ui/base",
+ "+ui/compositor",
+ "+ui/display",
+ "+ui/events",
"+ui/gfx",
+ # TODO(ccameron): This can be removed when sources are moved to the
+ # views_bridge_mac component.
+ "+ui/views/views_export.h",
+ # TODO(ccameron): This file should be moved to forward declarations.
+ "+ui/views/widget/util_mac.h",
]
diff --git a/chromium/ui/views_bridge_mac/bridge_factory_impl.h b/chromium/ui/views_bridge_mac/bridge_factory_impl.h
new file mode 100644
index 00000000000..5075e76bf52
--- /dev/null
+++ b/chromium/ui/views_bridge_mac/bridge_factory_impl.h
@@ -0,0 +1,41 @@
+// 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_VIEWS_BRIDGE_MAC_BRIDGE_FACTORY_IMPL_H_
+#define UI_VIEWS_BRIDGE_MAC_BRIDGE_FACTORY_IMPL_H_
+
+#include "mojo/public/cpp/bindings/associated_binding.h"
+#include "ui/views/views_export.h"
+#include "ui/views_bridge_mac/mojo/bridge_factory.mojom.h"
+#include "ui/views_bridge_mac/mojo/bridged_native_widget.mojom.h"
+#include "ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom.h"
+
+// TODO(ccameron): This file is to be moved to /ui/views_bridge_mac when
+// possible. For now, put it in the namespace of that path.
+namespace views_bridge_mac {
+
+// The factory that creates BridgedNativeWidget instances. This object is to
+// be instantiated in app shim processes.
+class VIEWS_EXPORT BridgeFactoryImpl : public mojom::BridgeFactory {
+ public:
+ static BridgeFactoryImpl* Get();
+ void BindRequest(mojom::BridgeFactoryAssociatedRequest request);
+
+ // mojom::BridgeFactory:
+ void CreateBridgedNativeWidget(
+ uint64_t bridge_id,
+ mojom::BridgedNativeWidgetAssociatedRequest bridge_request,
+ mojom::BridgedNativeWidgetHostAssociatedPtrInfo host) override;
+
+ private:
+ friend class base::NoDestructor<BridgeFactoryImpl>;
+ BridgeFactoryImpl();
+ ~BridgeFactoryImpl() override;
+
+ mojo::AssociatedBinding<mojom::BridgeFactory> binding_;
+};
+
+} // namespace views_bridge_mac
+
+#endif // UI_VIEWS_BRIDGE_MAC_BRIDGE_FACTORY_IMPL_H_
diff --git a/chromium/ui/views_bridge_mac/bridge_factory_impl.mm b/chromium/ui/views_bridge_mac/bridge_factory_impl.mm
new file mode 100644
index 00000000000..323abef93cc
--- /dev/null
+++ b/chromium/ui/views_bridge_mac/bridge_factory_impl.mm
@@ -0,0 +1,86 @@
+// Copyright 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views_bridge_mac/bridge_factory_impl.h"
+
+#include "base/no_destructor.h"
+#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
+#include "ui/views_bridge_mac/bridged_native_widget_host_helper.h"
+#include "ui/views_bridge_mac/bridged_native_widget_impl.h"
+
+namespace views_bridge_mac {
+
+using views::BridgedNativeWidgetImpl;
+using views::BridgedNativeWidgetHostHelper;
+
+namespace {
+
+class Bridge : public BridgedNativeWidgetHostHelper {
+ public:
+ Bridge(uint64_t bridge_id,
+ mojom::BridgedNativeWidgetHostAssociatedPtrInfo host_ptr,
+ mojom::BridgedNativeWidgetAssociatedRequest bridge_request) {
+ host_ptr_.Bind(std::move(host_ptr),
+ ui::WindowResizeHelperMac::Get()->task_runner());
+ bridge_impl_ = std::make_unique<BridgedNativeWidgetImpl>(
+ bridge_id, host_ptr_.get(), this);
+ bridge_impl_->BindRequest(
+ std::move(bridge_request),
+ base::BindOnce(&Bridge::OnConnectionError, base::Unretained(this)));
+ }
+
+ private:
+ ~Bridge() override {}
+
+ void OnConnectionError() { delete this; }
+
+ // BridgedNativeWidgetHostHelper:
+ NSView* GetNativeViewAccessible() override { return nil; }
+ void DispatchKeyEvent(ui::KeyEvent* event) override {}
+ bool DispatchKeyEventToMenuController(ui::KeyEvent* event) override {
+ return false;
+ }
+ void GetWordAt(const gfx::Point& location_in_content,
+ bool* found_word,
+ gfx::DecoratedText* decorated_word,
+ gfx::Point* baseline_point) override {
+ *found_word = false;
+ }
+ double SheetPositionY() override { return 0; }
+ views_bridge_mac::DragDropClient* GetDragDropClient() override {
+ // Drag-drop only doesn't work across mojo yet.
+ return nullptr;
+ }
+
+ mojom::BridgedNativeWidgetHostAssociatedPtr host_ptr_;
+ std::unique_ptr<BridgedNativeWidgetImpl> bridge_impl_;
+};
+
+} // namespace
+
+// static
+BridgeFactoryImpl* BridgeFactoryImpl::Get() {
+ static base::NoDestructor<BridgeFactoryImpl> factory;
+ return factory.get();
+}
+
+void BridgeFactoryImpl::BindRequest(
+ mojom::BridgeFactoryAssociatedRequest request) {
+ binding_.Bind(std::move(request));
+}
+
+void BridgeFactoryImpl::CreateBridgedNativeWidget(
+ uint64_t bridge_id,
+ mojom::BridgedNativeWidgetAssociatedRequest bridge_request,
+ mojom::BridgedNativeWidgetHostAssociatedPtrInfo host) {
+ // The resulting object will be destroyed when its message pipe is closed.
+ ignore_result(
+ new Bridge(bridge_id, std::move(host), std::move(bridge_request)));
+}
+
+BridgeFactoryImpl::BridgeFactoryImpl() : binding_(this) {}
+
+BridgeFactoryImpl::~BridgeFactoryImpl() {}
+
+} // namespace views_bridge_mac
diff --git a/chromium/ui/views/cocoa/bridged_content_view.h b/chromium/ui/views_bridge_mac/bridged_content_view.h
index a6daf562123..eefdeafe1b3 100644
--- a/chromium/ui/views/cocoa/bridged_content_view.h
+++ b/chromium/ui/views_bridge_mac/bridged_content_view.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_VIEWS_COCOA_BRIDGED_CONTENT_VIEW_H_
-#define UI_VIEWS_COCOA_BRIDGED_CONTENT_VIEW_H_
+#ifndef UI_VIEWS_BRIDGE_MAC_BRIDGED_CONTENT_VIEW_H_
+#define UI_VIEWS_BRIDGE_MAC_BRIDGED_CONTENT_VIEW_H_
#import <Cocoa/Cocoa.h>
@@ -17,7 +17,7 @@ class TextInputClient;
}
namespace views {
-class BridgedNativeWidget;
+class BridgedNativeWidgetImpl;
}
// The NSView that sits as the root contentView of the NSWindow, whilst it has
@@ -26,10 +26,11 @@ class BridgedNativeWidget;
VIEWS_EXPORT
@interface BridgedContentView : ToolTipBaseView<NSTextInputClient,
NSUserInterfaceValidations,
- NSDraggingSource> {
+ NSDraggingSource,
+ NSServicesMenuRequestor> {
@private
// Weak, reset by clearView.
- views::BridgedNativeWidget* bridge_;
+ views::BridgedNativeWidgetImpl* bridge_;
// Weak. If non-null the TextInputClient of the currently focused View in the
// hierarchy rooted at |hostedView_|. Owned by the focused View.
@@ -51,16 +52,22 @@ VIEWS_EXPORT
// Whether there's an active key down event which is not handled yet.
BOOL hasUnhandledKeyDownEvent_;
+ // Whether any -insertFoo: selector (e.g. -insertNewLine:) was passed to
+ // -doCommandBySelector: during the processing of this keyDown. These must
+ // always be dispatched as a ui::KeyEvent in -keyDown:.
+ BOOL wantsKeyHandledForInsert_;
+
// The last tooltip text, used to limit updates.
base::string16 lastTooltipText_;
}
-@property(readonly, nonatomic) views::BridgedNativeWidget* bridge;
+@property(readonly, nonatomic) views::BridgedNativeWidgetImpl* bridge;
@property(assign, nonatomic) ui::TextInputClient* textInputClient;
@property(assign, nonatomic) BOOL drawMenuBackgroundForBlur;
// Initialize the NSView -> views::View bridge. |viewToHost| must be non-NULL.
-- (id)initWithBridge:(views::BridgedNativeWidget*)bridge bounds:(gfx::Rect)rect;
+- (id)initWithBridge:(views::BridgedNativeWidgetImpl*)bridge
+ bounds:(gfx::Rect)rect;
// Clear the hosted view. For example, if it is about to be destroyed.
- (void)clearView;
@@ -80,4 +87,4 @@ VIEWS_EXPORT
@end
-#endif // UI_VIEWS_COCOA_BRIDGED_CONTENT_VIEW_H_
+#endif // UI_VIEWS_BRIDGE_MAC_BRIDGED_CONTENT_VIEW_H_
diff --git a/chromium/ui/views/cocoa/bridged_content_view.mm b/chromium/ui/views_bridge_mac/bridged_content_view.mm
index 9ffa0c183b3..ad444b08bd3 100644
--- a/chromium/ui/views/cocoa/bridged_content_view.mm
+++ b/chromium/ui/views_bridge_mac/bridged_content_view.mm
@@ -2,9 +2,10 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#import "ui/views/cocoa/bridged_content_view.h"
+#import "ui/views_bridge_mac/bridged_content_view.h"
#include "base/logging.h"
+#import "base/mac/foundation_util.h"
#import "base/mac/mac_util.h"
#import "base/mac/scoped_nsobject.h"
#import "base/mac/sdk_forward_declarations.h"
@@ -30,13 +31,10 @@
#include "ui/gfx/path.h"
#import "ui/gfx/path_mac.h"
#include "ui/gfx/scoped_ns_graphics_context_save_gstate_mac.h"
-#import "ui/views/cocoa/bridged_native_widget.h"
-#import "ui/views/cocoa/bridged_native_widget_host.h"
-#import "ui/views/cocoa/drag_drop_client_mac.h"
-#include "ui/views/controls/label.h"
-#include "ui/views/view.h"
-#include "ui/views/widget/native_widget_mac.h"
-#include "ui/views/widget/widget.h"
+#include "ui/views_bridge_mac/bridged_native_widget_host_helper.h"
+#import "ui/views_bridge_mac/bridged_native_widget_impl.h"
+#import "ui/views_bridge_mac/drag_drop_client.h"
+#include "ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom.h"
namespace {
@@ -50,9 +48,9 @@ NSString* const kFullKeyboardAccessChangedNotification =
gfx::Point MovePointToWindow(const NSPoint& point,
NSWindow* source_window,
NSWindow* target_window) {
- NSPoint point_in_screen = source_window
- ? ui::ConvertPointFromWindowToScreen(source_window, point)
- : point;
+ NSPoint point_in_screen =
+ source_window ? ui::ConvertPointFromWindowToScreen(source_window, point)
+ : point;
NSPoint point_in_window =
ui::ConvertPointFromScreenToWindow(target_window, point_in_screen);
@@ -197,6 +195,8 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
return ui::TextEditCommand::COPY;
if (action == @selector(paste:))
return ui::TextEditCommand::PASTE;
+ if (action == @selector(pasteAndMatchStyle:))
+ return ui::TextEditCommand::PASTE;
if (action == @selector(selectAll:))
return ui::TextEditCommand::SELECT_ALL;
return ui::TextEditCommand::INVALID_COMMAND;
@@ -254,7 +254,7 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
- (void)insertTextInternal:(id)text;
// Returns the native Widget's drag drop client. Possibly null.
-- (views::DragDropClientMac*)dragDropClient;
+- (views_bridge_mac::DragDropClient*)dragDropClient;
// Menu action handlers.
- (void)undo:(id)sender;
@@ -262,6 +262,7 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
- (void)cut:(id)sender;
- (void)copy:(id)sender;
- (void)paste:(id)sender;
+- (void)pasteAndMatchStyle:(id)sender;
- (void)selectAll:(id)sender;
@end
@@ -272,7 +273,7 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
@synthesize textInputClient = textInputClient_;
@synthesize drawMenuBackgroundForBlur = drawMenuBackgroundForBlur_;
-- (id)initWithBridge:(views::BridgedNativeWidget*)bridge
+- (id)initWithBridge:(views::BridgedNativeWidgetImpl*)bridge
bounds:(gfx::Rect)bounds {
// To keep things simple, assume the origin is (0, 0) until there exists a use
// case for something other than that.
@@ -424,13 +425,13 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
[self updateTooltipIfRequiredAt:event_location];
if (isScrollEvent) {
- ui::ScrollEvent event(theEvent);
- event.set_location(event_location);
- bridge_->host()->OnScrollEvent(event);
+ auto event = std::make_unique<ui::ScrollEvent>(theEvent);
+ event->set_location(event_location);
+ bridge_->host()->OnScrollEvent(std::move(event));
} else {
- ui::MouseEvent event(theEvent);
- event.set_location(event_location);
- bridge_->host()->OnMouseEvent(event);
+ auto event = std::make_unique<ui::MouseEvent>(theEvent);
+ event->set_location(event_location);
+ bridge_->host()->OnMouseEvent(std::move(event));
}
}
@@ -454,11 +455,8 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
// BridgedContentView private implementation.
- (void)dispatchKeyEvent:(ui::KeyEvent*)event {
- bool eventHandled = false;
if (bridge_)
- bridge_->host()->DispatchKeyEvent(*event, &eventHandled);
- if (eventHandled)
- event->SetHandled();
+ bridge_->host_helper()->DispatchKeyEvent(event);
}
- (BOOL)hasActiveMenuController {
@@ -469,15 +467,9 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
}
- (BOOL)dispatchKeyEventToMenuController:(ui::KeyEvent*)event {
- bool eventSwallowed = false;
- bool eventHandled = false;
- if (bridge_) {
- bridge_->host()->DispatchKeyEventToMenuController(*event, &eventSwallowed,
- &eventHandled);
- }
- if (eventHandled)
- event->SetHandled();
- return eventSwallowed;
+ if (bridge_)
+ return bridge_->host_helper()->DispatchKeyEventToMenuController(event);
+ return false;
}
- (void)handleKeyEvent:(ui::KeyEvent*)event {
@@ -617,22 +609,17 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
textInputClient_->InsertChar(
ui::KeyEvent([text characterAtIndex:0], ui::VKEY_UNKNOWN,
ui::DomCode::NONE, ui::EF_NONE));
- // Leave character events that may have triggered IME confirmation for
- // inline IME (e.g. Korean) as "unhandled". There will be no more
- // -insertText: messages, but we are unable to handle these via
- // -handleKeyEvent: earlier in this method since toolkit-views client code
- // assumes it can ignore characters associated with, e.g., VKEY_TAB.
- DCHECK(keyDownEvent_); // Otherwise it is not a character event.
- if ([self hasMarkedText] || !IsImeTriggerEvent(keyDownEvent_))
- hasUnhandledKeyDownEvent_ = NO;
} else {
textInputClient_->InsertText(base::SysNSStringToUTF16(text));
- hasUnhandledKeyDownEvent_ = NO;
}
+ // Suppress accelerators that may be bound to this key, since it inserted
+ // text instead. But note that IME may follow with -insertNewLine:, which
+ // will resurrect the keyEvent for accelerator handling.
+ hasUnhandledKeyDownEvent_ = NO;
}
}
-- (views::DragDropClientMac*)dragDropClient {
+- (views_bridge_mac::DragDropClient*)dragDropClient {
return bridge_ ? bridge_->drag_drop_client() : nullptr;
}
@@ -671,6 +658,13 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
eventFlags:ui::EF_CONTROL_DOWN];
}
+- (void)pasteAndMatchStyle:(id)sender {
+ [self handleAction:ui::TextEditCommand::PASTE
+ keyCode:ui::VKEY_V
+ domCode:ui::DomCode::US_V
+ eventFlags:ui::EF_CONTROL_DOWN | ui::EF_SHIFT_DOWN];
+}
+
- (void)selectAll:(id)sender {
[self handleAction:ui::TextEditCommand::SELECT_ALL
keyCode:ui::VKEY_A
@@ -692,13 +686,13 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
return;
DCHECK([theEvent type] != NSScrollWheel);
- ui::MouseEvent event(theEvent);
- [self adjustUiEventLocation:&event fromNativeEvent:theEvent];
+ auto event = std::make_unique<ui::MouseEvent>(theEvent);
+ [self adjustUiEventLocation:event.get() fromNativeEvent:theEvent];
// Aura updates tooltips with the help of aura::Window::AddPreTargetHandler().
// Mac hooks in here.
- [self updateTooltipIfRequiredAt:event.location()];
- bridge_->host()->OnMouseEvent(event);
+ [self updateTooltipIfRequiredAt:event->location()];
+ bridge_->host()->OnMouseEvent(std::move(event));
}
- (void)forceTouchEvent:(NSEvent*)theEvent {
@@ -780,18 +774,18 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
}
- (NSDragOperation)draggingUpdated:(id<NSDraggingInfo>)sender {
- views::DragDropClientMac* client = [self dragDropClient];
+ views_bridge_mac::DragDropClient* client = [self dragDropClient];
return client ? client->DragUpdate(sender) : ui::DragDropTypes::DRAG_NONE;
}
- (void)draggingExited:(id<NSDraggingInfo>)sender {
- views::DragDropClientMac* client = [self dragDropClient];
+ views_bridge_mac::DragDropClient* client = [self dragDropClient];
if (client)
client->DragExit();
}
- (BOOL)performDragOperation:(id<NSDraggingInfo>)sender {
- views::DragDropClientMac* client = [self dragDropClient];
+ views_bridge_mac::DragDropClient* client = [self dragDropClient];
return client && client->Drop(sender) != NSDragOperationNone;
}
@@ -840,6 +834,7 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
// Convert the event into an action message, according to OSX key mappings.
keyDownEvent_ = theEvent;
hasUnhandledKeyDownEvent_ = YES;
+ wantsKeyHandledForInsert_ = NO;
[self interpretKeyEvents:@[ theEvent ]];
// When there is marked text, -[NSView interpretKeyEvents:] may handle the
@@ -853,8 +848,16 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
if (hadMarkedTextAtKeyDown && IsImeTriggerEvent(theEvent))
hasUnhandledKeyDownEvent_ = NO;
- // If |keyDownEvent_| wasn't cleared during -interpretKeyEvents:, it wasn't
- // handled. Give Widget accelerators a chance to handle it.
+ // Even with marked text, some IMEs may follow with -insertNewLine:;
+ // simultaneously confirming the composition. In this case, always generate
+ // the corresponding ui::KeyEvent. Note this is done even if there was no
+ // marked text, so it is orthogonal to the case above.
+ if (wantsKeyHandledForInsert_)
+ hasUnhandledKeyDownEvent_ = YES;
+
+ // If |hasUnhandledKeyDownEvent_| wasn't set to NO during
+ // -interpretKeyEvents:, it wasn't handled. Give Widget accelerators a chance
+ // to handle it.
[self handleUnhandledKeyDownAsKeyEvent];
DCHECK(!hasUnhandledKeyDownEvent_);
keyDownEvent_ = nil;
@@ -866,6 +869,13 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
}
- (void)flagsChanged:(NSEvent*)theEvent {
+ if (theEvent.keyCode == 0) {
+ // An event like this gets sent when sending some key commands via
+ // AppleScript. Since 0 is VKEY_A, we end up interpreting this as Cmd+A
+ // which is incorrect. The correct event for command up/down (keyCode = 55)
+ // is also sent, so we should drop this one. See https://crbug.com/889618
+ return;
+ }
ui::KeyEvent event(theEvent);
[self handleKeyEvent:&event];
}
@@ -874,13 +884,13 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
if (!bridge_)
return;
- ui::ScrollEvent event(theEvent);
- [self adjustUiEventLocation:&event fromNativeEvent:theEvent];
+ auto event = std::make_unique<ui::ScrollEvent>(theEvent);
+ [self adjustUiEventLocation:event.get() fromNativeEvent:theEvent];
// Aura updates tooltips with the help of aura::Window::AddPreTargetHandler().
// Mac hooks in here.
- [self updateTooltipIfRequiredAt:event.location()];
- bridge_->host()->OnScrollEvent(event);
+ [self updateTooltipIfRequiredAt:event->location()];
+ bridge_->host()->OnScrollEvent(std::move(event));
}
// Called when we get a three-finger swipe, and they're enabled in System
@@ -904,10 +914,10 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
// Note this uses the default unique_touch_event_id of 0 (Swipe events do not
// support -[NSEvent eventNumber]). This doesn't seem like a real omission
// because the three-finger swipes are instant and can't be tracked anyway.
- ui::GestureEvent gestureEvent(location.x(), location.y(),
- ui::EventFlagsFromNative(event),
- ui::EventTimeFromNative(event), swipeDetails);
- bridge_->host()->OnGestureEvent(gestureEvent);
+ auto gestureEvent = std::make_unique<ui::GestureEvent>(
+ location.x(), location.y(), ui::EventFlagsFromNative(event),
+ ui::EventTimeFromNative(event), swipeDetails);
+ bridge_->host()->OnGestureEvent(std::move(gestureEvent));
}
- (void)quickLookWithEvent:(NSEvent*)theEvent {
@@ -920,8 +930,8 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
bool foundWord = false;
gfx::DecoratedText decoratedWord;
gfx::Point baselinePoint;
- bridge_->host()->GetWordAt(locationInContent, &foundWord, &decoratedWord,
- &baselinePoint);
+ bridge_->host_helper()->GetWordAt(locationInContent, &foundWord,
+ &decoratedWord, &baselinePoint);
if (!foundWord)
return;
@@ -1341,21 +1351,27 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
// Currently we only support reading and writing plain strings.
- (id)validRequestorForSendType:(NSString*)sendType
returnType:(NSString*)returnType {
- BOOL canWrite = [sendType isEqualToString:NSStringPboardType] &&
- [self selectedRange].length > 0;
- BOOL canRead = [returnType isEqualToString:NSStringPboardType];
+ NSString* const utf8Type = base::mac::CFToNSCast(kUTTypeUTF8PlainText);
+ BOOL canWrite =
+ [sendType isEqualToString:utf8Type] && [self selectedRange].length > 0;
+ BOOL canRead = [returnType isEqualToString:utf8Type];
// Valid if (sendType, returnType) is either (string, nil), (nil, string),
// or (string, string).
BOOL valid = textInputClient_ && ((canWrite && (canRead || !returnType)) ||
(canRead && (canWrite || !sendType)));
- return valid ? self : [super validRequestorForSendType:sendType
- returnType:returnType];
+ return valid
+ ? self
+ : [super validRequestorForSendType:sendType returnType:returnType];
}
-// NSServicesRequests informal protocol.
+// NSServicesMenuRequestor protocol
- (BOOL)writeSelectionToPasteboard:(NSPasteboard*)pboard types:(NSArray*)types {
- DCHECK([types containsObject:NSStringPboardType]);
+ // NB: The NSServicesMenuRequestor protocol has not (as of 10.14) been
+ // upgraded to request UTIs rather than obsolete PboardType constants. Handle
+ // either for when it is upgraded.
+ DCHECK([types containsObject:NSStringPboardType] ||
+ [types containsObject:base::mac::CFToNSCast(kUTTypeUTF8PlainText)]);
if (!textInputClient_)
return NO;
@@ -1386,9 +1402,9 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
// |self|) that we're trying to invalidate in -setTextInputClient:.
// See https://crbug.com/817097#c12 for further details on this atrocity.
-- (NSAttributedString*)
- attributedSubstringForProposedRange:(NSRange)range
- actualRange:(NSRangePointer)actualRange {
+- (NSAttributedString*)attributedSubstringForProposedRange:(NSRange)range
+ actualRange:
+ (NSRangePointer)actualRange {
// On TouchBar Macs, the IME subsystem sometimes sends an invalid range with a
// non-zero length. This will cause a DCHECK in gfx::Range, so repair it here.
// See https://crbug.com/888782.
@@ -1418,9 +1434,34 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
- (void)doCommandBySelector:(SEL)selector {
// Like the renderer, handle insert action messages as a regular key dispatch.
- // This ensures, e.g., insertTab correctly changes focus between fields.
- if (keyDownEvent_ && [NSStringFromSelector(selector) hasPrefix:@"insert"])
+ // This ensures, e.g., insertTab correctly changes focus between fields. This
+ // handles:
+ // -insertTab:(id)sender
+ // -insertBacktab:
+ // -insertNewline:
+ // -insertParagraphSeparator:
+ // -insertNewlineIgnoringFieldEditor:
+ // -insertTabIgnoringFieldEditor:
+ // -insertLineBreak:
+ // -insertContainerBreak:
+ // -insertSingleQuoteIgnoringSubstitution:
+ // -insertDoubleQuoteIgnoringSubstitution:
+ // It does not handle |-insertText:(id)insertString|, which is not a command.
+ // I.e. AppKit invokes _either_ -insertText: or -doCommandBySelector:. Also
+ // note -insertText: is only invoked if -inputContext: has returned nil.
+ DCHECK_NE(@selector(insertText:), selector);
+ if (keyDownEvent_ && [NSStringFromSelector(selector) hasPrefix:@"insert"]) {
+ // When return is pressed during IME composition, engines typically first
+ // confirm the composition with a series of -insertText:replacementRange:
+ // calls. Then, some also invoke -insertNewLine: (some do not). If an engine
+ // DOES invokes -insertNewLine:, we always want a corresponding VKEY_RETURN
+ // ui::KeyEvent generated. If it does NOT follow with -insertNewLine:, the
+ // VKEY_RETURN must be suppressed in keyDown:, since it typically will have
+ // merely dismissed the IME window: the composition is still ongoing.
+ // Setting this ensures keyDown: always generates a ui::KeyEvent.
+ wantsKeyHandledForInsert_ = YES;
return; // Handle in -keyDown:.
+ }
if ([self respondsToSelector:selector]) {
[self performSelector:selector withObject:nil];
@@ -1547,7 +1588,7 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
- (void)draggingSession:(NSDraggingSession*)session
endedAtPoint:(NSPoint)screenPoint
operation:(NSDragOperation)operation {
- views::DragDropClientMac* client = [self dragDropClient];
+ views_bridge_mac::DragDropClient* client = [self dragDropClient];
if (client)
client->EndDrag();
}
@@ -1556,21 +1597,21 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
- (id)accessibilityAttributeValue:(NSString*)attribute {
if ([attribute isEqualToString:NSAccessibilityChildrenAttribute]) {
- return @[ bridge_->host()->GetNativeViewAccessible() ];
+ return @[ bridge_->host_helper()->GetNativeViewAccessible() ];
}
return [super accessibilityAttributeValue:attribute];
}
- (id)accessibilityHitTest:(NSPoint)point {
- return
- [bridge_->host()->GetNativeViewAccessible() accessibilityHitTest:point];
+ return [bridge_->host_helper()->GetNativeViewAccessible()
+ accessibilityHitTest:point];
}
- (id)accessibilityFocusedUIElement {
if (!bridge_)
return nil;
- return [bridge_->host()->GetNativeViewAccessible()
+ return [bridge_->host_helper()->GetNativeViewAccessible()
accessibilityFocusedUIElement];
}
diff --git a/chromium/ui/views/cocoa/bridged_content_view_touch_bar.mm b/chromium/ui/views_bridge_mac/bridged_content_view_touch_bar.mm
index 6f1d18d11c4..008f7ff7886 100644
--- a/chromium/ui/views/cocoa/bridged_content_view_touch_bar.mm
+++ b/chromium/ui/views_bridge_mac/bridged_content_view_touch_bar.mm
@@ -7,9 +7,9 @@
#import "base/mac/sdk_forward_declarations.h"
#include "base/strings/sys_string_conversions.h"
#import "ui/base/cocoa/touch_bar_forward_declarations.h"
-#import "ui/views/cocoa/bridged_content_view.h"
-#import "ui/views/cocoa/bridged_native_widget.h"
-#import "ui/views/cocoa/bridged_native_widget_host.h"
+#import "ui/views_bridge_mac/bridged_content_view.h"
+#import "ui/views_bridge_mac/bridged_native_widget_impl.h"
+#include "ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom.h"
namespace {
diff --git a/chromium/ui/views_bridge_mac/bridged_native_widget_host_helper.h b/chromium/ui/views_bridge_mac/bridged_native_widget_host_helper.h
new file mode 100644
index 00000000000..4fe8218cc2a
--- /dev/null
+++ b/chromium/ui/views_bridge_mac/bridged_native_widget_host_helper.h
@@ -0,0 +1,67 @@
+// 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_VIEWS_BRIDGE_MAC_BRIDGED_NATIVE_WIDGET_HOST_HELPER_H_
+#define UI_VIEWS_BRIDGE_MAC_BRIDGED_NATIVE_WIDGET_HOST_HELPER_H_
+
+#include "ui/base/ui_base_types.h"
+#include "ui/events/event_utils.h"
+#include "ui/gfx/decorated_text.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/views_bridge_mac/views_bridge_mac_export.h"
+
+@class NSView;
+
+namespace views_bridge_mac {
+
+class DragDropClient;
+
+// This is a helper class for the mojo interface BridgedNativeWidgetHost.
+// This provides an easier-to-use interface than the mojo for selected
+// functions. It also is temporarily exposing functionality that is not yet
+// implemented over mojo.
+class VIEWS_BRIDGE_MAC_EXPORT BridgedNativeWidgetHostHelper {
+ public:
+ virtual ~BridgedNativeWidgetHostHelper() = default;
+
+ // Retrieve the NSView for accessibility for this widget.
+ // TODO(ccameron): This interface cannot be implemented over IPC. A scheme
+ // for implementing accessibility across processes needs to be designed and
+ // implemented.
+ virtual NSView* GetNativeViewAccessible() = 0;
+
+ // Synchronously dispatch a key event. Note that this function will modify
+ // |event| based on whether or not it was handled.
+ virtual void DispatchKeyEvent(ui::KeyEvent* event) = 0;
+
+ // Synchronously dispatch a key event to the current menu controller (if one
+ // exists and it is owned by the widget for this). Return true if the event
+ // was swallowed (that is, if the menu's dispatch returned
+ // POST_DISPATCH_NONE). Note that this function will modify |event| based on
+ // whether or not it was handled.
+ virtual bool DispatchKeyEventToMenuController(ui::KeyEvent* event) = 0;
+
+ // Synchronously query the quicklook text at |location_in_content|. Return in
+ // |found_word| whether or not a word was found.
+ // TODO(ccameron): This needs gfx::DecoratedText to be mojo-ified before it
+ // can be done over mojo.
+ virtual void GetWordAt(const gfx::Point& location_in_content,
+ bool* found_word,
+ gfx::DecoratedText* decorated_word,
+ gfx::Point* baseline_point) = 0;
+
+ // Returns the vertical position that sheets should be anchored, in pixels
+ // from the bottom of the window.
+ // TODO(ccameron): This should be either moved to the mojo interface or
+ // separated out in such a way as to avoid needing to go through mojo.
+ virtual double SheetPositionY() = 0;
+
+ // Return a pointer to host's DragDropClientMac.
+ // TODO(ccameron): Drag-drop behavior needs to be implemented over mojo.
+ virtual DragDropClient* GetDragDropClient() = 0;
+};
+
+} // namespace views_bridge_mac
+
+#endif // UI_VIEWS_BRIDGE_MAC_BRIDGED_NATIVE_WIDGET_HOST_HELPER_H_
diff --git a/chromium/ui/views/cocoa/bridged_native_widget.h b/chromium/ui/views_bridge_mac/bridged_native_widget_impl.h
index 6d2d12e6455..acdb1997003 100644
--- a/chromium/ui/views/cocoa/bridged_native_widget.h
+++ b/chromium/ui/views_bridge_mac/bridged_native_widget_impl.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_VIEWS_COCOA_BRIDGED_NATIVE_WIDGET_H_
-#define UI_VIEWS_COCOA_BRIDGED_NATIVE_WIDGET_H_
+#ifndef UI_VIEWS_BRIDGE_MAC_BRIDGED_NATIVE_WIDGET_IMPL_H_
+#define UI_VIEWS_BRIDGE_MAC_BRIDGED_NATIVE_WIDGET_IMPL_H_
#import <Cocoa/Cocoa.h>
@@ -13,15 +13,14 @@
#import "base/mac/scoped_nsobject.h"
#include "base/macros.h"
#include "components/viz/common/surfaces/parent_local_surface_id_allocator.h"
+#include "mojo/public/cpp/bindings/associated_binding.h"
#include "ui/accelerated_widget_mac/ca_transaction_observer.h"
#include "ui/accelerated_widget_mac/display_ca_layer_tree.h"
+#include "ui/base/cocoa/ns_view_ids.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/display/display_observer.h"
-#import "ui/views/cocoa/bridged_native_widget_owner.h"
-#import "ui/views/cocoa/cocoa_mouse_capture_delegate.h"
-#import "ui/views/focus/focus_manager.h"
#include "ui/views/views_export.h"
-#include "ui/views/widget/widget.h"
+#import "ui/views_bridge_mac/cocoa_mouse_capture_delegate.h"
#include "ui/views_bridge_mac/mojo/bridged_native_widget.mojom.h"
@class BridgedContentView;
@@ -29,75 +28,80 @@
@class NativeWidgetMacNSWindow;
@class ViewsNSWindowDelegate;
+namespace views_bridge_mac {
+
+namespace mojom {
+class BridgedNativeWidgetHost;
+} // namespace mojom
+
+class BridgedNativeWidgetHostHelper;
+class CocoaMouseCapture;
+class DragDropClient;
+
+} // namespace views_bridge_mac
+
namespace views {
namespace test {
class BridgedNativeWidgetTestApi;
}
-class BridgedNativeWidgetHost;
-class CocoaMouseCapture;
class CocoaWindowMoveLoop;
-class DragDropClientMac;
-class NativeWidgetMac;
-class View;
+
+using views_bridge_mac::mojom::BridgedNativeWidgetHost;
+using views_bridge_mac::BridgedNativeWidgetHostHelper;
+using views_bridge_mac::CocoaMouseCapture;
+using views_bridge_mac::CocoaMouseCaptureDelegate;
// A bridge to an NSWindow managed by an instance of NativeWidgetMac or
// DesktopNativeWidgetMac. Serves as a helper class to bridge requests from the
// NativeWidgetMac to the Cocoa window. Behaves a bit like an aura::Window.
-class VIEWS_EXPORT BridgedNativeWidget
+class VIEWS_EXPORT BridgedNativeWidgetImpl
: public views_bridge_mac::mojom::BridgedNativeWidget,
public display::DisplayObserver,
public ui::CATransactionCoordinator::PreCommitObserver,
- public CocoaMouseCaptureDelegate,
- public BridgedNativeWidgetOwner {
+ public CocoaMouseCaptureDelegate {
public:
- // Contains NativeViewHost->gfx::NativeView associations.
- using AssociatedViews = std::map<const views::View*, NSView*>;
-
// Return the size that |window| will take for the given client area |size|,
// based on its current style mask.
static gfx::Size GetWindowSizeForClientSize(NSWindow* window,
const gfx::Size& size);
+ // Retrieves the bridge associated with the given NSWindow. Returns null if
+ // the supplied handle has no associated Widget.
+ static BridgedNativeWidgetImpl* GetFromNativeWindow(NSWindow* window);
+
+ // Retrieve a BridgedNativeWidgetImpl* from its id.
+ static BridgedNativeWidgetImpl* GetFromId(uint64_t bridged_native_widget_id);
+
+ // Create an NSWindow for the specified parameters.
+ static base::scoped_nsobject<NativeWidgetMacNSWindow> CreateNSWindow(
+ views_bridge_mac::mojom::CreateWindowParams* params);
+
// Creates one side of the bridge. |host| and |parent| must not be NULL.
- BridgedNativeWidget(BridgedNativeWidgetHost* host, NativeWidgetMac* parent);
- ~BridgedNativeWidget() override;
+ BridgedNativeWidgetImpl(uint64_t bridged_native_widget_id,
+ BridgedNativeWidgetHost* host,
+ BridgedNativeWidgetHostHelper* host_helper);
+ ~BridgedNativeWidgetImpl() override;
+
+ // Bind |bridge_mojo_binding_| to |request|, and set the connection error
+ // callback for |bridge_mojo_binding_| to |connection_closed_callback| (which
+ // will delete |this| when the connection is closed).
+ void BindRequest(
+ views_bridge_mac::mojom::BridgedNativeWidgetAssociatedRequest request,
+ base::OnceClosure connection_closed_callback);
// Initialize the NSWindow by taking ownership of the specified object.
- // TODO(ccameron): When a BridgedNativeWidget is allocated across a process
- // boundary, it will not be possible to explicitly set an NSWindow in this
- // way.
+ // TODO(ccameron): When a BridgedNativeWidgetImpl is allocated across a
+ // process boundary, it will not be possible to explicitly set an NSWindow in
+ // this way.
void SetWindow(base::scoped_nsobject<NativeWidgetMacNSWindow> window);
- // Create the drag drop client for this widget.
- // TODO(ccameron): This function takes a views::View (and is not rolled into
- // CreateContentView) because drag-drop has not been routed through |host_|
- // yet.
- void CreateDragDropClient(views::View* view);
-
- // Set the parent NSView for the widget.
- // TODO(ccameron): Like SetWindow, this will need to pass a handle instead of
- // an NSView across processes.
- void SetParent(NSView* parent);
-
- // Changes the bounds of the window and the hosted layer if present. The
- // origin is a location in screen coordinates except for "child" windows,
- // which are positioned relative to their parent(). SetBounds() considers a
- // "child" window to be one initialized with InitParams specifying all of:
- // a |parent| NSWindow, the |child| attribute, and a |type| that
- // views::GetAuraWindowTypeForWidgetType does not consider a "popup" type.
- void SetBounds(const gfx::Rect& new_bounds);
-
// Start moving the window, pinned to the mouse cursor, and monitor events.
- // Return MOVE_LOOP_SUCCESSFUL on mouse up or MOVE_LOOP_CANCELED on premature
- // termination via EndMoveLoop() or when window is destroyed during the drag.
- Widget::MoveLoopResult RunMoveLoop(const gfx::Vector2d& drag_offset);
+ // Return true on mouse up or false on premature termination via EndMoveLoop()
+ // or when window is destroyed during the drag.
+ bool RunMoveLoop(const gfx::Vector2d& drag_offset);
void EndMoveLoop();
- // See views::Widget.
- void SetNativeWindowProperty(const char* key, void* value);
- void* GetNativeWindowProperty(const char* key) const;
-
// Sets the cursor associated with the NSWindow. Retains |cursor|.
void SetCursor(NSCursor* cursor);
@@ -141,38 +145,25 @@ class VIEWS_EXPORT BridgedNativeWidget
// Called by the window show animation when it completes and wants to destroy
// itself.
void OnShowAnimationComplete();
+ // Sort child NSViews according to their ranking in |rank|.
+ void SortSubviews(std::map<NSView*, int> rank);
- // Updates |associated_views_| on NativeViewHost::Attach()/Detach().
- void SetAssociationForView(const views::View* view, NSView* native_view);
- void ClearAssociationForView(const views::View* view);
- // Sorts child NSViews according to NativeViewHosts order in views hierarchy.
- void ReorderChildViews();
-
- NativeWidgetMac* native_widget_mac() { return native_widget_mac_; }
BridgedContentView* ns_view() { return bridged_view_; }
BridgedNativeWidgetHost* host() { return host_; }
+ BridgedNativeWidgetHostHelper* host_helper() { return host_helper_; }
NSWindow* ns_window();
- TooltipManager* tooltip_manager() { return tooltip_manager_.get(); }
-
- DragDropClientMac* drag_drop_client() { return drag_drop_client_.get(); }
+ views_bridge_mac::DragDropClient* drag_drop_client();
bool is_translucent_window() const { return is_translucent_window_; }
// The parent widget specified in Widget::InitParams::parent. If non-null, the
// parent will close children before the parent closes, and children will be
// raised above their parent when window z-order changes.
- BridgedNativeWidgetOwner* parent() { return parent_; }
- const std::vector<BridgedNativeWidget*>& child_windows() {
+ BridgedNativeWidgetImpl* parent() { return parent_; }
+ const std::vector<BridgedNativeWidgetImpl*>& child_windows() {
return child_windows_;
}
- // Re-parent a |native_view| in this Widget to be a child of |new_parent|.
- // |native_view| must either be |ns_view()| or a descendant of |ns_view()|.
- // |native_view| is added as a subview of |new_parent| unless it is the
- // contentView of a top-level Widget. If |native_view| is |ns_view()|, |this|
- // also becomes a child window of |new_parent|'s NSWindow.
- void ReparentNativeView(NSView* native_view, NSView* new_parent);
-
bool target_fullscreen_state() const { return target_fullscreen_state_; }
bool window_visible() const { return window_visible_; }
bool wants_to_be_visible() const { return wants_to_be_visible_; }
@@ -181,16 +172,9 @@ class VIEWS_EXPORT BridgedNativeWidget
// Enables or disables all window animations.
void SetAnimationEnabled(bool animate);
- // Sets which transitions will animate. Currently this only affects non-native
- // animations. TODO(tapted): Use scoping to disable native animations at
- // appropriate times as well.
- void set_transitions_to_animate(int transitions) {
- transitions_to_animate_ = transitions;
- }
-
// Whether to run a custom animation for the provided |transition|.
bool ShouldRunCustomAnimationFor(
- Widget::VisibilityTransition transition) const;
+ views_bridge_mac::mojom::VisibilityTransition transition) const;
// display::DisplayObserver:
void OnDisplayMetricsChanged(const display::Display& display,
@@ -201,20 +185,26 @@ class VIEWS_EXPORT BridgedNativeWidget
base::TimeDelta PreCommitTimeout() override;
// views_bridge_mac::mojom::BridgedNativeWidget:
+ void CreateWindow(
+ views_bridge_mac::mojom::CreateWindowParamsPtr params) override;
+ void SetParent(uint64_t parent_id) override;
void InitWindow(views_bridge_mac::mojom::BridgedNativeWidgetInitParamsPtr
params) override;
void InitCompositorView() override;
- void CreateContentView(const gfx::Rect& bounds) override;
+ void CreateContentView(uint64_t ns_view_id, const gfx::Rect& bounds) override;
void DestroyContentView() override;
void CloseWindow() override;
void CloseWindowNow() override;
void SetInitialBounds(const gfx::Rect& new_bounds,
- const gfx::Size& minimum_content_size,
- const gfx::Vector2d& parent_offset) override;
+ const gfx::Size& minimum_content_size) override;
void SetBounds(const gfx::Rect& new_bounds,
const gfx::Size& minimum_content_size) override;
+ void SetSizeAndCenter(const gfx::Size& content_size,
+ const gfx::Size& minimum_content_size) override;
void SetVisibilityState(
views_bridge_mac::mojom::WindowVisibilityState new_state) override;
+ void SetTransitionsToAnimate(
+ views_bridge_mac::mojom::VisibilityTransition transitions) override;
void SetVisibleOnAllSpaces(bool always_visible) override;
void SetFullscreen(bool fullscreen) override;
void SetMiniaturized(bool miniaturized) override;
@@ -228,6 +218,7 @@ class VIEWS_EXPORT BridgedNativeWidget
void SetWindowTitle(const base::string16& title) override;
void MakeFirstResponder() override;
void ClearTouchBar() override;
+ void UpdateTooltip() override;
void AcquireCapture() override;
void ReleaseCapture() override;
@@ -239,18 +230,22 @@ class VIEWS_EXPORT BridgedNativeWidget
// update widget and compositor size.
void UpdateWindowGeometry();
+ // The offset in screen pixels for positioning child windows owned by |this|.
+ gfx::Vector2d GetChildWindowOffset() const;
+
private:
friend class test::BridgedNativeWidgetTestApi;
- // Closes all child windows. BridgedNativeWidget children will be destroyed.
+ // Closes all child windows. BridgedNativeWidgetImpl children will be
+ // destroyed.
void RemoveOrDestroyChildren();
+ // Remove the specified child window without closing it.
+ void RemoveChildWindow(BridgedNativeWidgetImpl* child);
+
// Notify descendants of a visibility change.
void NotifyVisibilityChangeDown();
- // Installs the NSView for hosting the composited layer.
- void AddCompositorSuperview();
-
// Query the display properties of the monitor that |window_| is on, and
// forward them to |host_|.
void UpdateWindowDisplay();
@@ -270,31 +265,23 @@ class VIEWS_EXPORT BridgedNativeWidget
void OnMouseCaptureLost() override;
NSWindow* GetWindow() const override;
- // Returns a properties dictionary associated with the NSWindow.
- // Creates and attaches a new instance if not found.
- NSMutableDictionary* GetWindowProperties() const;
-
- // BridgedNativeWidgetOwner:
- NSWindow* GetNSWindow() override;
- gfx::Vector2d GetChildWindowOffset() const override;
- bool IsVisibleParent() const override;
- void RemoveChildWindow(BridgedNativeWidget* child) override;
-
- BridgedNativeWidgetHost* const host_; // Weak. Owns this.
- NativeWidgetMac* const native_widget_mac_; // Weak. Owns |host_|.
+ const uint64_t id_;
+ BridgedNativeWidgetHost* const host_; // Weak. Owns this.
+ BridgedNativeWidgetHostHelper* const host_helper_; // Weak, owned by |host_|.
base::scoped_nsobject<NativeWidgetMacNSWindow> window_;
base::scoped_nsobject<ViewsNSWindowDelegate> window_delegate_;
base::scoped_nsobject<BridgedContentView> bridged_view_;
+ std::unique_ptr<ui::ScopedNSViewIdMapping> bridged_view_id_mapping_;
base::scoped_nsobject<ModalShowAnimationWithLayer> show_animation_;
std::unique_ptr<CocoaMouseCapture> mouse_capture_;
std::unique_ptr<CocoaWindowMoveLoop> window_move_loop_;
- std::unique_ptr<TooltipManager> tooltip_manager_;
- std::unique_ptr<DragDropClientMac> drag_drop_client_;
ui::ModalType modal_type_ = ui::MODAL_TYPE_NONE;
bool is_translucent_window_ = false;
+ bool widget_is_top_level_ = false;
+ bool position_window_in_screen_coords_ = false;
- BridgedNativeWidgetOwner* parent_ = nullptr; // Weak. If non-null, owns this.
- std::vector<BridgedNativeWidget*> child_windows_;
+ BridgedNativeWidgetImpl* parent_ = nullptr; // Weak. If non-null, owns this.
+ std::vector<BridgedNativeWidgetImpl*> child_windows_;
// The size of the content area of the window most recently sent to |host_|
// (and its compositor).
@@ -305,7 +292,6 @@ class VIEWS_EXPORT BridgedNativeWidget
// |content_dip_size_|, which is the frame size most recently *sent to* the
// compositor.
gfx::Size compositor_frame_dip_size_;
- base::scoped_nsobject<NSView> compositor_superview_;
std::unique_ptr<ui::DisplayCALayerTree> display_ca_layer_tree_;
// Tracks the bounds when the window last started entering fullscreen. Used to
@@ -314,8 +300,9 @@ class VIEWS_EXPORT BridgedNativeWidget
gfx::Rect bounds_before_fullscreen_;
// The transition types to animate when not relying on native NSWindow
- // animation behaviors. Bitmask of Widget::VisibilityTransition.
- int transitions_to_animate_ = Widget::ANIMATE_BOTH;
+ // animation behaviors.
+ views_bridge_mac::mojom::VisibilityTransition transitions_to_animate_ =
+ views_bridge_mac::mojom::VisibilityTransition::kBoth;
// Whether this window wants to be fullscreen. If a fullscreen animation is in
// progress then it might not be actually fullscreen.
@@ -341,11 +328,11 @@ class VIEWS_EXPORT BridgedNativeWidget
// shadow needs to be invalidated when a frame is received for the new shape.
bool invalidate_shadow_on_frame_swap_ = false;
- AssociatedViews associated_views_;
-
- DISALLOW_COPY_AND_ASSIGN(BridgedNativeWidget);
+ mojo::AssociatedBinding<views_bridge_mac::mojom::BridgedNativeWidget>
+ bridge_mojo_binding_;
+ DISALLOW_COPY_AND_ASSIGN(BridgedNativeWidgetImpl);
};
} // namespace views
-#endif // UI_VIEWS_COCOA_BRIDGED_NATIVE_WIDGET_H_
+#endif // UI_VIEWS_BRIDGE_MAC_BRIDGED_NATIVE_WIDGET_IMPL_H_
diff --git a/chromium/ui/views/cocoa/bridged_native_widget.mm b/chromium/ui/views_bridge_mac/bridged_native_widget_impl.mm
index abdbcc45fab..86b67f18fba 100644
--- a/chromium/ui/views/cocoa/bridged_native_widget.mm
+++ b/chromium/ui/views_bridge_mac/bridged_native_widget_impl.mm
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#import "ui/views/cocoa/bridged_native_widget.h"
+#import "ui/views_bridge_mac/bridged_native_widget_impl.h"
#import <objc/runtime.h>
#include <stddef.h>
@@ -13,9 +13,13 @@
#import "base/mac/foundation_util.h"
#include "base/mac/mac_util.h"
#import "base/mac/sdk_forward_declarations.h"
+#include "base/no_destructor.h"
#include "base/single_thread_task_runner.h"
#include "base/strings/sys_string_conversions.h"
+#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
+#include "ui/base/cocoa/cocoa_base_utils.h"
#import "ui/base/cocoa/constrained_window/constrained_window_animation.h"
+#import "ui/base/cocoa/window_size_constants.h"
#include "ui/base/hit_test.h"
#include "ui/base/layout.h"
#include "ui/base/ui_base_switches.h"
@@ -23,25 +27,33 @@
#include "ui/gfx/geometry/dip_util.h"
#import "ui/gfx/mac/coordinate_conversion.h"
#import "ui/gfx/mac/nswindow_frame_controls.h"
-#import "ui/native_theme/native_theme_mac.h"
-#import "ui/views/cocoa/bridged_content_view.h"
-#import "ui/views/cocoa/bridged_native_widget_host.h"
-#import "ui/views/cocoa/cocoa_mouse_capture.h"
-#import "ui/views/cocoa/cocoa_window_move_loop.h"
-#import "ui/views/cocoa/drag_drop_client_mac.h"
-#import "ui/views/cocoa/native_widget_mac_nswindow.h"
-#include "ui/views/cocoa/tooltip_manager_mac.h"
-#import "ui/views/cocoa/views_nswindow_delegate.h"
-#import "ui/views/cocoa/widget_owner_nswindow_adapter.h"
-#include "ui/views/widget/native_widget_mac.h"
-#include "ui/views/widget/widget.h"
-
+#import "ui/views_bridge_mac/bridged_content_view.h"
+#import "ui/views_bridge_mac/bridged_native_widget_host_helper.h"
+#import "ui/views_bridge_mac/cocoa_mouse_capture.h"
+#import "ui/views_bridge_mac/cocoa_window_move_loop.h"
+#include "ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom.h"
+#import "ui/views_bridge_mac/native_widget_mac_nswindow.h"
+#import "ui/views_bridge_mac/views_nswindow_delegate.h"
+
+using views_bridge_mac::mojom::VisibilityTransition;
using views_bridge_mac::mojom::WindowVisibilityState;
namespace {
constexpr auto kUIPaintTimeout = base::TimeDelta::FromSeconds(5);
} // namespace
+// The NSView that hosts the composited CALayer drawing the UI. It fills the
+// window but is not hittable so that accessibility hit tests always go to the
+// BridgedContentView.
+@interface ViewsCompositorSuperview : NSView
+@end
+
+@implementation ViewsCompositorSuperview
+- (NSView*)hitTest:(NSPoint)aPoint {
+ return nil;
+}
+@end
+
// Self-owning animation delegate that starts a hide animation, then calls
// -[NSWindow close] when the animation ends, releasing itself.
@interface ViewsNSWindowCloseAnimator : NSObject<NSAnimationDelegate> {
@@ -77,18 +89,6 @@ constexpr auto kUIPaintTimeout = base::TimeDelta::FromSeconds(5);
}
@end
-// The NSView that hosts the composited CALayer drawing the UI. It fills the
-// window but is not hittable so that accessibility hit tests always go to the
-// BridgedContentView.
-@interface ViewsCompositorSuperview : NSView
-@end
-
-@implementation ViewsCompositorSuperview
-- (NSView*)hitTest:(NSPoint)aPoint {
- return nil;
-}
-@end
-
// This class overrides NSAnimation methods to invalidate the shadow for each
// frame. It is required because the show animation uses CGSSetWindowWarp()
// which is touchy about the consistency of the points it is given. The show
@@ -106,10 +106,10 @@ constexpr auto kUIPaintTimeout = base::TimeDelta::FromSeconds(5);
@implementation ModalShowAnimationWithLayer {
// This is the "real" delegate, but this class acts as the NSAnimationDelegate
// to avoid a separate object.
- views::BridgedNativeWidget* bridgedNativeWidget_;
+ views::BridgedNativeWidgetImpl* bridgedNativeWidget_;
}
- (instancetype)initWithBridgedNativeWidget:
- (views::BridgedNativeWidget*)widget {
+ (views::BridgedNativeWidgetImpl*)widget {
if ((self = [super initWithWindow:widget->ns_window()])) {
bridgedNativeWidget_ = widget;
[self setDelegate:self];
@@ -136,6 +136,8 @@ constexpr auto kUIPaintTimeout = base::TimeDelta::FromSeconds(5);
}
@end
+namespace views {
+
namespace {
using RankMap = std::map<NSView*, int>;
@@ -150,8 +152,6 @@ using NSViewComparatorValue = id;
using NSViewComparatorValue = __kindof NSView*;
#endif
-int kWindowPropertiesKey;
-
// Returns true if the content_view is reparented.
bool PositionWindowInNativeViewParent(NSView* content_view) {
return [[content_view window] contentView] != content_view;
@@ -177,21 +177,14 @@ gfx::Size GetClientSizeForWindowSize(NSWindow* window,
return gfx::Size([window contentRectForFrameRect:frame_rect].size);
}
-void RankNSViews(views::View* view,
- const views::BridgedNativeWidget::AssociatedViews& hosts,
- RankMap* rank) {
- auto it = hosts.find(view);
- if (it != hosts.end())
- rank->emplace(it->second, rank->size());
- for (int i = 0; i < view->child_count(); ++i)
- RankNSViews(view->child_at(i), hosts, rank);
-}
-
NSComparisonResult SubviewSorter(NSViewComparatorValue lhs,
NSViewComparatorValue rhs,
void* rank_as_void) {
DCHECK_NE(lhs, rhs);
+ if ([lhs isKindOfClass:[ViewsCompositorSuperview class]])
+ return NSOrderedAscending;
+
const RankMap* rank = static_cast<const RankMap*>(rank_as_void);
auto left_rank = rank->find(lhs);
auto right_rank = rank->find(rhs);
@@ -211,7 +204,7 @@ NSComparisonResult SubviewSorter(NSViewComparatorValue lhs,
return NSOrderedSame;
}
-// Counts windows managed by a BridgedNativeWidget instance in the
+// Counts windows managed by a BridgedNativeWidgetImpl instance in the
// |child_windows| array ignoring the windows added by AppKit.
NSUInteger CountBridgedWindows(NSArray* child_windows) {
NSUInteger count = 0;
@@ -222,12 +215,16 @@ NSUInteger CountBridgedWindows(NSArray* child_windows) {
return count;
}
-} // namespace
+std::map<uint64_t, BridgedNativeWidgetImpl*>& GetIdToWidgetImplMap() {
+ static base::NoDestructor<std::map<uint64_t, BridgedNativeWidgetImpl*>>
+ id_map;
+ return *id_map;
+}
-namespace views {
+} // namespace
// static
-gfx::Size BridgedNativeWidget::GetWindowSizeForClientSize(
+gfx::Size BridgedNativeWidgetImpl::GetWindowSizeForClientSize(
NSWindow* window,
const gfx::Size& content_size) {
NSRect content_rect =
@@ -236,59 +233,101 @@ gfx::Size BridgedNativeWidget::GetWindowSizeForClientSize(
return gfx::Size(NSWidth(frame_rect), NSHeight(frame_rect));
}
-BridgedNativeWidget::BridgedNativeWidget(BridgedNativeWidgetHost* host,
- NativeWidgetMac* parent)
- : host_(host), native_widget_mac_(parent) {
- DCHECK(parent);
- window_delegate_.reset(
- [[ViewsNSWindowDelegate alloc] initWithBridgedNativeWidget:this]);
- ui::CATransactionCoordinator::Get().AddPreCommitObserver(this);
+// static
+BridgedNativeWidgetImpl* BridgedNativeWidgetImpl::GetFromNativeWindow(
+ gfx::NativeWindow window) {
+ if (NativeWidgetMacNSWindow* widget_window =
+ base::mac::ObjCCast<NativeWidgetMacNSWindow>(window)) {
+ return GetFromId([widget_window bridgedNativeWidgetId]);
+ }
+ return nullptr; // Not created by NativeWidgetMac.
+}
+
+// static
+BridgedNativeWidgetImpl* BridgedNativeWidgetImpl::GetFromId(
+ uint64_t bridged_native_widget_id) {
+ auto found = GetIdToWidgetImplMap().find(bridged_native_widget_id);
+ if (found == GetIdToWidgetImplMap().end())
+ return nullptr;
+ return found->second;
}
-BridgedNativeWidget::~BridgedNativeWidget() {
+// static
+base::scoped_nsobject<NativeWidgetMacNSWindow>
+BridgedNativeWidgetImpl::CreateNSWindow(
+ views_bridge_mac::mojom::CreateWindowParams* params) {
+ base::scoped_nsobject<NativeWidgetMacNSWindow> result(
+ [[NativeWidgetMacNSWindow alloc]
+ initWithContentRect:ui::kWindowSizeDeterminedLater
+ styleMask:params->style_mask
+ backing:NSBackingStoreBuffered
+ defer:NO]);
+ return result;
+}
+
+BridgedNativeWidgetImpl::BridgedNativeWidgetImpl(
+ uint64_t bridged_native_widget_id,
+ BridgedNativeWidgetHost* host,
+ BridgedNativeWidgetHostHelper* host_helper)
+ : id_(bridged_native_widget_id),
+ host_(host),
+ host_helper_(host_helper),
+ bridge_mojo_binding_(this) {
+ DCHECK(GetIdToWidgetImplMap().find(id_) == GetIdToWidgetImplMap().end());
+ GetIdToWidgetImplMap().insert(std::make_pair(id_, this));
+}
+
+BridgedNativeWidgetImpl::~BridgedNativeWidgetImpl() {
// The delegate should be cleared already. Note this enforces the precondition
// that -[NSWindow close] is invoked on the hosted window before the
// destructor is called.
DCHECK(![window_ delegate]);
-
- ui::CATransactionCoordinator::Get().RemovePreCommitObserver(this);
- RemoveOrDestroyChildren();
DCHECK(child_windows_.empty());
DestroyContentView();
}
-void BridgedNativeWidget::SetWindow(
+void BridgedNativeWidgetImpl::BindRequest(
+ views_bridge_mac::mojom::BridgedNativeWidgetAssociatedRequest request,
+ base::OnceClosure connection_closed_callback) {
+ bridge_mojo_binding_.Bind(std::move(request),
+ ui::WindowResizeHelperMac::Get()->task_runner());
+ bridge_mojo_binding_.set_connection_error_handler(
+ std::move(connection_closed_callback));
+}
+
+void BridgedNativeWidgetImpl::SetWindow(
base::scoped_nsobject<NativeWidgetMacNSWindow> window) {
DCHECK(!window_);
+ window_delegate_.reset(
+ [[ViewsNSWindowDelegate alloc] initWithBridgedNativeWidget:this]);
window_ = std::move(window);
+ [window_ setBridgedNativeWidgetId:id_];
[window_ setReleasedWhenClosed:NO]; // Owned by scoped_nsobject.
[window_ setDelegate:window_delegate_];
+ ui::CATransactionCoordinator::Get().AddPreCommitObserver(this);
}
-void BridgedNativeWidget::SetParent(NSView* new_parent) {
- BridgedNativeWidget* bridged_native_widget_parent =
- NativeWidgetMac::GetBridgeForNativeWindow([new_parent window]);
+void BridgedNativeWidgetImpl::SetParent(uint64_t new_parent_id) {
// Remove from the old parent.
if (parent_) {
parent_->RemoveChildWindow(this);
parent_ = nullptr;
}
-
- if (!new_parent)
+ if (!new_parent_id)
return;
- // Disallow creating child windows of views not currently in an NSWindow.
- CHECK([new_parent window]);
+ // It is only valid to have a NativeWidgetMac be the parent of another
+ // NativeWidgetMac.
+ BridgedNativeWidgetImpl* new_parent =
+ BridgedNativeWidgetImpl::GetFromId(new_parent_id);
+ DCHECK(new_parent);
- // If the parent is another BridgedNativeWidget, just add to the collection
- // of child windows it owns and manages. Otherwise, create an adapter to
- // anchor the child widget and observe when the parent NSWindow is closed.
- if (bridged_native_widget_parent) {
- parent_ = bridged_native_widget_parent;
- bridged_native_widget_parent->child_windows_.push_back(this);
- } else {
- parent_ = new WidgetOwnerNSWindowAdapter(this, new_parent);
- }
+ // If the parent is another BridgedNativeWidgetImpl, just add to the
+ // collection of child windows it owns and manages. Otherwise, create an
+ // adapter to anchor the child widget and observe when the parent NSWindow is
+ // closed.
+ parent_ = new_parent;
+ parent_->child_windows_.push_back(this);
// Widget::ShowInactive() could result in a Space switch when the widget has a
// parent, and we're calling -orderWindow:relativeTo:. Use Transient
@@ -296,12 +335,24 @@ void BridgedNativeWidget::SetParent(NSView* new_parent) {
// https://crbug.com/697829
[window_ setCollectionBehavior:[window_ collectionBehavior] |
NSWindowCollectionBehaviorTransient];
+
+ // If |window_| was already visible then add it as a child window immediately.
+ // As in OnVisibilityChanged, do not set a parent for sheets.
+ if (window_visible_ && ![window_ isSheet])
+ [parent_->ns_window() addChildWindow:window_ ordered:NSWindowAbove];
+}
+
+void BridgedNativeWidgetImpl::CreateWindow(
+ views_bridge_mac::mojom::CreateWindowParamsPtr params) {
+ SetWindow(CreateNSWindow(params.get()));
}
-void BridgedNativeWidget::InitWindow(
+void BridgedNativeWidgetImpl::InitWindow(
views_bridge_mac::mojom::BridgedNativeWidgetInitParamsPtr params) {
modal_type_ = params->modal_type;
is_translucent_window_ = params->is_translucent;
+ widget_is_top_level_ = params->widget_is_top_level;
+ position_window_in_screen_coords_ = params->position_window_in_screen_coords;
// Register for application hide notifications so that visibility can be
// properly tracked. This is not done in the delegate so that the lifetime is
@@ -335,13 +386,11 @@ void BridgedNativeWidget::InitWindow(
}
[window_ setHasShadow:params->has_window_server_shadow];
- tooltip_manager_.reset(new TooltipManagerMac(this));
}
-void BridgedNativeWidget::SetInitialBounds(
+void BridgedNativeWidgetImpl::SetInitialBounds(
const gfx::Rect& new_bounds,
- const gfx::Size& minimum_content_size,
- const gfx::Vector2d& bounds_offset_for_parent) {
+ const gfx::Size& minimum_content_size) {
gfx::Rect adjusted_bounds = new_bounds;
if (new_bounds.IsEmpty()) {
// If a position is set, but no size, complain. Otherwise, a 1x1 window
@@ -358,12 +407,11 @@ void BridgedNativeWidget::SetInitialBounds(
adjusted_bounds = gfx::Rect(
gfx::Point(), gfx::Size(NSWidth(frame_rect), NSHeight(frame_rect)));
}
- adjusted_bounds.Offset(bounds_offset_for_parent);
SetBounds(adjusted_bounds, minimum_content_size);
}
-void BridgedNativeWidget::SetBounds(const gfx::Rect& new_bounds,
- const gfx::Size& minimum_content_size) {
+void BridgedNativeWidgetImpl::SetBounds(const gfx::Rect& new_bounds,
+ const gfx::Size& minimum_content_size) {
// -[NSWindow contentMinSize] is only checked by Cocoa for user-initiated
// resizes. This is not what toolkit-views expects, so clamp. Note there is
// no check for maximum size (consistent with aura::Window::SetBounds()).
@@ -387,6 +435,9 @@ void BridgedNativeWidget::SetBounds(const gfx::Rect& new_bounds,
new_bounds.origin(),
GetWindowSizeForClientSize(window_, clamped_content_size));
+ if (parent_ && !position_window_in_screen_coords_)
+ actual_new_bounds.Offset(parent_->GetChildWindowOffset());
+
if (PositionWindowInNativeViewParent(bridged_view_))
actual_new_bounds.Offset(GetNativeViewParentOffset(bridged_view_));
@@ -395,39 +446,60 @@ void BridgedNativeWidget::SetBounds(const gfx::Rect& new_bounds,
animate:NO];
}
-void BridgedNativeWidget::DestroyContentView() {
+void BridgedNativeWidgetImpl::SetSizeAndCenter(
+ const gfx::Size& content_size,
+ const gfx::Size& minimum_content_size) {
+ gfx::Rect new_window_bounds = gfx::ScreenRectFromNSRect([window_ frame]);
+ new_window_bounds.set_size(GetWindowSizeForClientSize(window_, content_size));
+ SetBounds(new_window_bounds, minimum_content_size);
+
+ // Note that this is not the precise center of screen, but it is the standard
+ // location for windows like dialogs to appear on screen for Mac.
+ // TODO(tapted): If there is a parent window, center in that instead.
+ [window_ center];
+}
+
+void BridgedNativeWidgetImpl::DestroyContentView() {
if (!bridged_view_)
return;
- drag_drop_client_.reset();
[bridged_view_ clearView];
+ bridged_view_id_mapping_.reset();
bridged_view_.reset();
[window_ setContentView:nil];
}
-void BridgedNativeWidget::CreateContentView(const gfx::Rect& bounds) {
+void BridgedNativeWidgetImpl::CreateContentView(uint64_t ns_view_id,
+ const gfx::Rect& bounds) {
DCHECK(!bridged_view_);
- // The compositor needs to point at the new content view created here.
- DCHECK(!compositor_superview_);
bridged_view_.reset(
[[BridgedContentView alloc] initWithBridge:this bounds:bounds]);
+ bridged_view_id_mapping_ = std::make_unique<ui::ScopedNSViewIdMapping>(
+ ns_view_id, bridged_view_.get());
// Objective C initializers can return nil. However, if |view| is non-NULL
// this should be treated as an error and caught early.
CHECK(bridged_view_);
- // Layer backing the content view improves resize performance, reduces memory
- // use (no backing store), and clips sublayers to rounded window corners.
- [bridged_view_ setWantsLayer:YES];
+ // Beware: This view was briefly removed (in favor of a bare CALayer) in
+ // crrev/c/1236675. The ordering of unassociated layers relative to NSView
+ // layers is undefined on macOS 10.12 and earlier, so the compositor layer
+ // ended up covering up subviews (see crbug/899499).
+ base::scoped_nsobject<NSView> compositor_view(
+ [[ViewsCompositorSuperview alloc] initWithFrame:[bridged_view_ bounds]]);
+ [compositor_view
+ setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
+ auto* background_layer = [CALayer layer];
+ display_ca_layer_tree_ =
+ std::make_unique<ui::DisplayCALayerTree>(background_layer);
+ [compositor_view setLayer:background_layer];
+ [compositor_view setWantsLayer:YES];
+ [bridged_view_ addSubview:compositor_view];
[window_ setContentView:bridged_view_];
}
-void BridgedNativeWidget::CreateDragDropClient(views::View* view) {
- drag_drop_client_.reset(new DragDropClientMac(this, view));
-}
-
-void BridgedNativeWidget::CloseWindow() {
+void BridgedNativeWidgetImpl::CloseWindow() {
// Keep |window| on the stack so that the ObjectiveC block below can capture
// it and properly increment the reference count bound to the posted task.
NSWindow* window = ns_window();
@@ -447,7 +519,7 @@ void BridgedNativeWidget::CloseWindow() {
}
// For other modal types, animate the close.
- if (ShouldRunCustomAnimationFor(Widget::ANIMATE_HIDE)) {
+ if (ShouldRunCustomAnimationFor(VisibilityTransition::kHide)) {
[ViewsNSWindowCloseAnimator closeWindowWithAnimation:window];
return;
}
@@ -472,7 +544,7 @@ void BridgedNativeWidget::CloseWindow() {
})));
}
-void BridgedNativeWidget::CloseWindowNow() {
+void BridgedNativeWidgetImpl::CloseWindowNow() {
// NSWindows must be retained until -[NSWindow close] returns.
auto window_retain = window_;
@@ -482,7 +554,8 @@ void BridgedNativeWidget::CloseWindowNow() {
// Note: |this| will be deleted here.
}
-void BridgedNativeWidget::SetVisibilityState(WindowVisibilityState new_state) {
+void BridgedNativeWidgetImpl::SetVisibilityState(
+ WindowVisibilityState new_state) {
// Ensure that:
// - A window with an invisible parent is not made visible.
// - A parent changing visibility updates child window visibility.
@@ -519,8 +592,10 @@ void BridgedNativeWidget::SetVisibilityState(WindowVisibilityState new_state) {
// If the parent (or an ancestor) is hidden, return and wait for it to become
// visible.
- if (parent() && !parent()->IsVisibleParent())
- return;
+ for (auto* ancestor = parent_; ancestor; ancestor = ancestor->parent_) {
+ if (!ancestor->window_visible_)
+ return;
+ }
if (IsWindowModalSheet()) {
ShowAsModalSheet();
@@ -549,17 +624,16 @@ void BridgedNativeWidget::SetVisibilityState(WindowVisibilityState new_state) {
if (window_visible_)
return; // Avoid a Spaces transition.
- parent_window_number = [parent_->GetNSWindow() windowNumber];
+ parent_window_number = [parent_->ns_window() windowNumber];
}
- [window_ orderWindow:NSWindowAbove
- relativeTo:parent_window_number];
+ [window_ orderWindow:NSWindowAbove relativeTo:parent_window_number];
}
DCHECK(window_visible_);
// For non-sheet modal types, use the constrained window animations to make
// the window appear.
- if (ShouldRunCustomAnimationFor(Widget::ANIMATE_SHOW)) {
+ if (ShouldRunCustomAnimationFor(VisibilityTransition::kShow)) {
show_animation_.reset(
[[ModalShowAnimationWithLayer alloc] initWithBridgedNativeWidget:this]);
@@ -575,7 +649,14 @@ void BridgedNativeWidget::SetVisibilityState(WindowVisibilityState new_state) {
}
}
-void BridgedNativeWidget::AcquireCapture() {
+void BridgedNativeWidgetImpl::SetTransitionsToAnimate(
+ VisibilityTransition transitions) {
+ // TODO(tapted): Use scoping to disable native animations at appropriate
+ // times as well.
+ transitions_to_animate_ = transitions;
+}
+
+void BridgedNativeWidgetImpl::AcquireCapture() {
if (HasCapture())
return;
if (!window_visible_)
@@ -593,18 +674,18 @@ void BridgedNativeWidget::AcquireCapture() {
[window_ cursorUpdate:[NSApp currentEvent]];
}
-void BridgedNativeWidget::ReleaseCapture() {
+void BridgedNativeWidgetImpl::ReleaseCapture() {
mouse_capture_.reset();
}
-bool BridgedNativeWidget::HasCapture() {
+bool BridgedNativeWidgetImpl::HasCapture() {
return mouse_capture_ && mouse_capture_->IsActive();
}
-Widget::MoveLoopResult BridgedNativeWidget::RunMoveLoop(
- const gfx::Vector2d& drag_offset) {
+bool BridgedNativeWidgetImpl::RunMoveLoop(const gfx::Vector2d& drag_offset) {
DCHECK(!HasCapture());
- DCHECK(!window_move_loop_);
+ // https://crbug.com/876493
+ CHECK(!window_move_loop_);
// RunMoveLoop caller is responsible for updating the window to be under the
// mouse, but it does this using possibly outdated coordinate from the mouse
@@ -628,36 +709,21 @@ Widget::MoveLoopResult BridgedNativeWidget::RunMoveLoop(
// function returns. But don't DCHECK since |this| might not be valid.
}
-void BridgedNativeWidget::EndMoveLoop() {
+void BridgedNativeWidgetImpl::EndMoveLoop() {
DCHECK(window_move_loop_);
window_move_loop_->End();
window_move_loop_.reset();
}
-void BridgedNativeWidget::SetNativeWindowProperty(const char* name,
- void* value) {
- NSString* key = [NSString stringWithUTF8String:name];
- if (value) {
- [GetWindowProperties() setObject:[NSValue valueWithPointer:value]
- forKey:key];
- } else {
- [GetWindowProperties() removeObjectForKey:key];
- }
-}
-
-void* BridgedNativeWidget::GetNativeWindowProperty(const char* name) const {
- NSString* key = [NSString stringWithUTF8String:name];
- return [[GetWindowProperties() objectForKey:key] pointerValue];
-}
-
-void BridgedNativeWidget::SetCursor(NSCursor* cursor) {
+void BridgedNativeWidgetImpl::SetCursor(NSCursor* cursor) {
[window_delegate_ setCursor:cursor];
}
-void BridgedNativeWidget::OnWindowWillClose() {
+void BridgedNativeWidgetImpl::OnWindowWillClose() {
+ ui::CATransactionCoordinator::Get().RemovePreCommitObserver(this);
host_->OnWindowWillClose();
- // Ensure BridgedNativeWidget does not have capture, otherwise
+ // Ensure BridgedNativeWidgetImpl does not have capture, otherwise
// OnMouseCaptureLost() may reference a deleted |host_| when called via
// ~CocoaMouseCapture() upon the destruction of |mouse_capture_|. See
// https://crbug.com/622201. Also we do this before setting the delegate to
@@ -675,11 +741,19 @@ void BridgedNativeWidget::OnWindowWillClose() {
DCHECK(!show_animation_);
[window_ setDelegate:nil];
+
+ // Ensure that |this| cannot be reached by its id while it is being destroyed.
+ size_t erased = GetIdToWidgetImplMap().erase(id_);
+ DCHECK_EQ(1u, erased);
+
+ RemoveOrDestroyChildren();
+ DCHECK(child_windows_.empty());
+
host_->OnWindowHasClosed();
// Note: |this| and its host will be deleted here.
}
-void BridgedNativeWidget::OnFullscreenTransitionStart(
+void BridgedNativeWidgetImpl::OnFullscreenTransitionStart(
bool target_fullscreen_state) {
// Note: This can fail for fullscreen changes started externally, but a user
// shouldn't be able to do that if the window is invisible to begin with.
@@ -692,7 +766,7 @@ void BridgedNativeWidget::OnFullscreenTransitionStart(
host_->OnWindowFullscreenTransitionStart(target_fullscreen_state);
}
-void BridgedNativeWidget::OnFullscreenTransitionComplete(
+void BridgedNativeWidgetImpl::OnFullscreenTransitionComplete(
bool actual_fullscreen_state) {
in_fullscreen_transition_ = false;
@@ -709,7 +783,7 @@ void BridgedNativeWidget::OnFullscreenTransitionComplete(
ToggleDesiredFullscreenState(true /* async */);
}
-void BridgedNativeWidget::ToggleDesiredFullscreenState(bool async) {
+void BridgedNativeWidgetImpl::ToggleDesiredFullscreenState(bool async) {
// If there is currently an animation into or out of fullscreen, then AppKit
// emits the string "not in fullscreen state" to stdio and does nothing. For
// this case, schedule a transition back into the desired state when the
@@ -758,15 +832,15 @@ void BridgedNativeWidget::ToggleDesiredFullscreenState(bool async) {
}
}
-void BridgedNativeWidget::OnSizeChanged() {
+void BridgedNativeWidgetImpl::OnSizeChanged() {
UpdateWindowGeometry();
}
-void BridgedNativeWidget::OnPositionChanged() {
+void BridgedNativeWidgetImpl::OnPositionChanged() {
UpdateWindowGeometry();
}
-void BridgedNativeWidget::OnVisibilityChanged() {
+void BridgedNativeWidgetImpl::OnVisibilityChanged() {
const bool window_visible = [window_ isVisible];
if (window_visible_ == window_visible)
return;
@@ -783,7 +857,7 @@ void BridgedNativeWidget::OnVisibilityChanged() {
// Sheets don't need a parentWindow set, and setting one causes graphical
// glitches (http://crbug.com/605098).
if (parent_ && ![window_ isSheet])
- [parent_->GetNSWindow() addChildWindow:window_ ordered:NSWindowAbove];
+ [parent_->ns_window() addChildWindow:window_ ordered:NSWindowAbove];
} else {
ReleaseCapture(); // Capture on hidden windows is not permitted.
@@ -791,7 +865,7 @@ void BridgedNativeWidget::OnVisibilityChanged() {
// list. Cocoa's childWindow management breaks down when child windows are
// hidden.
if (parent_)
- [parent_->GetNSWindow() removeChildWindow:window_];
+ [parent_->ns_window() removeChildWindow:window_];
}
// Showing a translucent window after hiding it should trigger shadow
@@ -809,24 +883,24 @@ void BridgedNativeWidget::OnVisibilityChanged() {
[window_ setAutodisplay:window_visible_];
}
-void BridgedNativeWidget::OnSystemControlTintChanged() {
- ui::NativeTheme::GetInstanceForNativeUi()->NotifyObservers();
+void BridgedNativeWidgetImpl::OnSystemControlTintChanged() {
+ host_->OnWindowNativeThemeChanged();
}
-void BridgedNativeWidget::OnBackingPropertiesChanged() {
+void BridgedNativeWidgetImpl::OnBackingPropertiesChanged() {
UpdateWindowDisplay();
}
-void BridgedNativeWidget::OnWindowKeyStatusChangedTo(bool is_key) {
+void BridgedNativeWidgetImpl::OnWindowKeyStatusChangedTo(bool is_key) {
host_->OnWindowKeyStatusChanged(
is_key, [window_ contentView] == [window_ firstResponder],
[NSApp isFullKeyboardAccessEnabled]);
}
-void BridgedNativeWidget::SetSizeConstraints(const gfx::Size& min_size,
- const gfx::Size& max_size,
- bool is_resizable,
- bool is_maximizable) {
+void BridgedNativeWidgetImpl::SetSizeConstraints(const gfx::Size& min_size,
+ const gfx::Size& max_size,
+ bool is_resizable,
+ bool is_maximizable) {
// Don't modify the size constraints or fullscreen collection behavior while
// in fullscreen or during a transition. OnFullscreenTransitionComplete will
// reset these after leaving fullscreen.
@@ -842,13 +916,11 @@ void BridgedNativeWidget::SetSizeConstraints(const gfx::Size& min_size,
shows_fullscreen_controls);
}
-void BridgedNativeWidget::OnShowAnimationComplete() {
+void BridgedNativeWidgetImpl::OnShowAnimationComplete() {
show_animation_.reset();
}
-void BridgedNativeWidget::InitCompositorView() {
- AddCompositorSuperview();
-
+void BridgedNativeWidgetImpl::InitCompositorView() {
// Use the regular window background for window modal sheets. The layer will
// still paint over most of it, but the native -[NSApp beginSheet:] animation
// blocks the UI thread, so there's no way to invalidate the shadow to match
@@ -875,84 +947,29 @@ void BridgedNativeWidget::InitCompositorView() {
UpdateWindowGeometry();
}
-void BridgedNativeWidget::SetAssociationForView(const views::View* view,
- NSView* native_view) {
- DCHECK_EQ(0u, associated_views_.count(view));
- associated_views_[view] = native_view;
- native_widget_mac_->GetWidget()->ReorderNativeViews();
-}
-
-void BridgedNativeWidget::ClearAssociationForView(const views::View* view) {
- auto it = associated_views_.find(view);
- DCHECK(it != associated_views_.end());
- associated_views_.erase(it);
-}
-
-void BridgedNativeWidget::ReorderChildViews() {
+void BridgedNativeWidgetImpl::SortSubviews(RankMap rank) {
// Ignore layer manipulation during a Close(). This can be reached during the
// orderOut: in Close(), which notifies visibility changes to Views.
if (!bridged_view_)
return;
-
- RankMap rank;
- Widget* widget = native_widget_mac_->GetWidget();
- RankNSViews(widget->GetRootView(), associated_views_, &rank);
- // Unassociated NSViews should be ordered above associated ones. The exception
- // is the UI compositor's superview, which should always be on the very
- // bottom, so give it an explicit negative rank.
- if (compositor_superview_)
- rank[compositor_superview_] = -1;
[bridged_view_ sortSubviewsUsingFunction:&SubviewSorter context:&rank];
}
-void BridgedNativeWidget::ReparentNativeView(NSView* native_view,
- NSView* new_parent) {
- DCHECK([new_parent window]);
- DCHECK([native_view isDescendantOf:bridged_view_]);
- DCHECK(window_ && ![window_ isSheet]);
-
- BridgedNativeWidget* parent_bridge =
- NativeWidgetMac::GetBridgeForNativeWindow([new_parent window]);
- if (native_view == bridged_view_.get() && parent_bridge != parent_) {
- SetParent(new_parent);
-
- // TODO(ccameron): This is likely not correct, as the window for |this|
- // should only be added as a child window if it is visible.
- if (!window_visible_)
- NOTIMPLEMENTED();
- [[new_parent window] addChildWindow:window_ ordered:NSWindowAbove];
- }
-
- if (!native_widget_mac_->GetWidget()->is_top_level() ||
- native_view != bridged_view_.get()) {
- // Make native_view be a child of new_parent by adding it as a subview.
- // The window_ must remain visible because it controls the bounds and
- // visibility of the ui::Layer. So just hide it by setting alpha value to
- // zero.
- [new_parent addSubview:native_view];
- if (native_view == bridged_view_.get()) {
- [window_ setAlphaValue:0];
- [window_ setIgnoresMouseEvents:YES];
- }
- }
-}
-
-void BridgedNativeWidget::SetAnimationEnabled(bool animate) {
+void BridgedNativeWidgetImpl::SetAnimationEnabled(bool animate) {
[window_
setAnimationBehavior:(animate ? NSWindowAnimationBehaviorDocumentWindow
: NSWindowAnimationBehaviorNone)];
}
-bool BridgedNativeWidget::ShouldRunCustomAnimationFor(
- Widget::VisibilityTransition transition) const {
+bool BridgedNativeWidgetImpl::ShouldRunCustomAnimationFor(
+ VisibilityTransition transition) const {
// The logic around this needs to change if new transition types are set.
// E.g. it would be nice to distinguish "hide" from "close". Mac currently
// treats "hide" only as "close". Hide (e.g. Cmd+h) should not animate on Mac.
- constexpr int kSupported =
- Widget::ANIMATE_SHOW | Widget::ANIMATE_HIDE | Widget::ANIMATE_NONE;
- DCHECK_EQ(0, transitions_to_animate_ & ~kSupported);
- if (!(transitions_to_animate_ & transition))
+ if (transitions_to_animate_ != transition &&
+ transitions_to_animate_ != VisibilityTransition::kBoth) {
return false;
+ }
// Custom animations are only used for tab-modals.
bool widget_is_modal = false;
@@ -974,66 +991,70 @@ bool BridgedNativeWidget::ShouldRunCustomAnimationFor(
return true;
}
-NSWindow* BridgedNativeWidget::ns_window() {
+NSWindow* BridgedNativeWidgetImpl::ns_window() {
return window_.get();
}
+views_bridge_mac::DragDropClient* BridgedNativeWidgetImpl::drag_drop_client() {
+ return host_helper_->GetDragDropClient();
+}
+
////////////////////////////////////////////////////////////////////////////////
-// BridgedNativeWidget, ui::CATransactionObserver
+// BridgedNativeWidgetImpl, ui::CATransactionObserver
-void BridgedNativeWidget::OnDisplayMetricsChanged(
+void BridgedNativeWidgetImpl::OnDisplayMetricsChanged(
const display::Display& display,
uint32_t metrics) {
UpdateWindowDisplay();
}
////////////////////////////////////////////////////////////////////////////////
-// BridgedNativeWidget, ui::CATransactionObserver
+// BridgedNativeWidgetImpl, ui::CATransactionObserver
-bool BridgedNativeWidget::ShouldWaitInPreCommit() {
+bool BridgedNativeWidgetImpl::ShouldWaitInPreCommit() {
if (!window_visible_)
return false;
if (ca_transaction_sync_suppressed_)
return false;
- if (!compositor_superview_)
+ if (!bridged_view_)
return false;
return content_dip_size_ != compositor_frame_dip_size_;
}
-base::TimeDelta BridgedNativeWidget::PreCommitTimeout() {
+base::TimeDelta BridgedNativeWidgetImpl::PreCommitTimeout() {
return kUIPaintTimeout;
}
////////////////////////////////////////////////////////////////////////////////
-// BridgedNativeWidget, CocoaMouseCaptureDelegate:
+// BridgedNativeWidgetImpl, CocoaMouseCaptureDelegate:
-void BridgedNativeWidget::PostCapturedEvent(NSEvent* event) {
+void BridgedNativeWidgetImpl::PostCapturedEvent(NSEvent* event) {
[bridged_view_ processCapturedMouseEvent:event];
}
-void BridgedNativeWidget::OnMouseCaptureLost() {
+void BridgedNativeWidgetImpl::OnMouseCaptureLost() {
host_->OnMouseCaptureActiveChanged(false);
}
-NSWindow* BridgedNativeWidget::GetWindow() const {
+NSWindow* BridgedNativeWidgetImpl::GetWindow() const {
return window_;
}
////////////////////////////////////////////////////////////////////////////////
// TODO(ccameron): Update class names to:
-// BridgedNativeWidgetImpl, BridgedNativeWidget:
+// BridgedNativeWidgetImpl, BridgedNativeWidgetImpl:
-void BridgedNativeWidget::SetVisibleOnAllSpaces(bool always_visible) {
+void BridgedNativeWidgetImpl::SetVisibleOnAllSpaces(bool always_visible) {
gfx::SetNSWindowVisibleOnAllWorkspaces(window_, always_visible);
}
-void BridgedNativeWidget::SetFullscreen(bool fullscreen) {
+void BridgedNativeWidgetImpl::SetFullscreen(bool fullscreen) {
if (fullscreen == target_fullscreen_state_)
return;
ToggleDesiredFullscreenState();
}
-void BridgedNativeWidget::SetMiniaturized(bool miniaturized) {
+void BridgedNativeWidgetImpl::SetMiniaturized(bool miniaturized) {
if (miniaturized) {
// Calling performMiniaturize: will momentarily highlight the button, but
// AppKit will reject it if there is no miniaturize button.
@@ -1046,17 +1067,17 @@ void BridgedNativeWidget::SetMiniaturized(bool miniaturized) {
}
}
-void BridgedNativeWidget::SetOpacity(float opacity) {
+void BridgedNativeWidgetImpl::SetOpacity(float opacity) {
[window_ setAlphaValue:opacity];
}
-void BridgedNativeWidget::SetContentAspectRatio(
+void BridgedNativeWidgetImpl::SetContentAspectRatio(
const gfx::SizeF& aspect_ratio) {
[window_ setContentAspectRatio:NSMakeSize(aspect_ratio.width(),
aspect_ratio.height())];
}
-void BridgedNativeWidget::SetCALayerParams(
+void BridgedNativeWidgetImpl::SetCALayerParams(
const gfx::CALayerParams& ca_layer_params) {
// Ignore frames arriving "late" for an old size. A frame at the new size
// should arrive soon.
@@ -1079,46 +1100,46 @@ void BridgedNativeWidget::SetCALayerParams(
}
}
-void BridgedNativeWidget::MakeFirstResponder() {
+void BridgedNativeWidgetImpl::MakeFirstResponder() {
[window_ makeFirstResponder:bridged_view_];
}
-void BridgedNativeWidget::SetWindowTitle(const base::string16& title) {
+void BridgedNativeWidgetImpl::SetWindowTitle(const base::string16& title) {
NSString* new_title = base::SysUTF16ToNSString(title);
[window_ setTitle:new_title];
}
-void BridgedNativeWidget::ClearTouchBar() {
+void BridgedNativeWidgetImpl::ClearTouchBar() {
if (@available(macOS 10.12.2, *)) {
if ([bridged_view_ respondsToSelector:@selector(setTouchBar:)])
[bridged_view_ setTouchBar:nil];
}
}
-void BridgedNativeWidget::SetTextInputClient(
+void BridgedNativeWidgetImpl::UpdateTooltip() {
+ NSPoint nspoint =
+ ui::ConvertPointFromScreenToWindow(window_, [NSEvent mouseLocation]);
+ // Note: flip in the view's frame, which matches the window's contentRect.
+ gfx::Point point(nspoint.x, NSHeight([bridged_view_ frame]) - nspoint.y);
+ [bridged_view_ updateTooltipIfRequiredAt:point];
+}
+
+void BridgedNativeWidgetImpl::SetTextInputClient(
ui::TextInputClient* text_input_client) {
[bridged_view_ setTextInputClient:text_input_client];
}
////////////////////////////////////////////////////////////////////////////////
-// BridgedNativeWidget, BridgedNativeWidgetOwner:
-
-NSWindow* BridgedNativeWidget::GetNSWindow() {
- return window_;
-}
+// BridgedNativeWidgetImpl, former BridgedNativeWidgetOwner:
-gfx::Vector2d BridgedNativeWidget::GetChildWindowOffset() const {
+gfx::Vector2d BridgedNativeWidgetImpl::GetChildWindowOffset() const {
return gfx::ScreenRectFromNSRect([window_ frame]).OffsetFromOrigin();
}
-bool BridgedNativeWidget::IsVisibleParent() const {
- return parent_ ? window_visible_ && parent_->IsVisibleParent()
- : window_visible_;
-}
-
-void BridgedNativeWidget::RemoveChildWindow(BridgedNativeWidget* child) {
- auto location = std::find(
- child_windows_.begin(), child_windows_.end(), child);
+void BridgedNativeWidgetImpl::RemoveChildWindow(
+ BridgedNativeWidgetImpl* child) {
+ auto location =
+ std::find(child_windows_.begin(), child_windows_.end(), child);
DCHECK(location != child_windows_.end());
child_windows_.erase(location);
@@ -1129,9 +1150,9 @@ void BridgedNativeWidget::RemoveChildWindow(BridgedNativeWidget* child) {
}
////////////////////////////////////////////////////////////////////////////////
-// BridgedNativeWidget, private:
+// BridgedNativeWidgetImpl, private:
-void BridgedNativeWidget::RemoveOrDestroyChildren() {
+void BridgedNativeWidgetImpl::RemoveOrDestroyChildren() {
// TODO(tapted): Implement unowned child windows if required.
while (!child_windows_.empty()) {
// The NSWindow can only be destroyed after -[NSWindow close] is complete.
@@ -1143,13 +1164,13 @@ void BridgedNativeWidget::RemoveOrDestroyChildren() {
}
}
-void BridgedNativeWidget::NotifyVisibilityChangeDown() {
+void BridgedNativeWidgetImpl::NotifyVisibilityChangeDown() {
// Child windows sometimes like to close themselves in response to visibility
// changes. That's supported, but only with the asynchronous Widget::Close().
// Perform a heuristic to detect child removal that would break these loops.
const size_t child_count = child_windows_.size();
if (!window_visible_) {
- for (BridgedNativeWidget* child : child_windows_) {
+ for (BridgedNativeWidgetImpl* child : child_windows_) {
if (child->window_visible_)
[child->ns_window() orderOut:nil];
@@ -1160,7 +1181,7 @@ void BridgedNativeWidget::NotifyVisibilityChangeDown() {
// in each child. There, children will remove themselves from the NSWindow
// childWindow list as well as propagate NotifyVisibilityChangeDown() calls
// to any children of their own. However this is only true for windows
- // managed by the BridgedNativeWidget i.e. windows which have
+ // managed by the BridgedNativeWidgetImpl i.e. windows which have
// ViewsNSWindowDelegate as the delegate.
DCHECK_EQ(0u, CountBridgedWindows([window_ childWindows]));
return;
@@ -1168,7 +1189,7 @@ void BridgedNativeWidget::NotifyVisibilityChangeDown() {
NSUInteger visible_bridged_children = 0; // For a DCHECK below.
NSInteger parent_window_number = [window_ windowNumber];
- for (BridgedNativeWidget* child: child_windows_) {
+ for (BridgedNativeWidgetImpl* child : child_windows_) {
// Note: order the child windows on top, regardless of whether or not they
// are currently visible. They probably aren't, since the parent was hidden
// prior to this, but they could have been made visible in other ways.
@@ -1192,36 +1213,7 @@ void BridgedNativeWidget::NotifyVisibilityChangeDown() {
CountBridgedWindows([window_ childWindows]));
}
-void BridgedNativeWidget::AddCompositorSuperview() {
- DCHECK(!compositor_superview_);
- compositor_superview_.reset(
- [[ViewsCompositorSuperview alloc] initWithFrame:[bridged_view_ bounds]]);
-
- // Size and resize automatically with |bridged_view_|.
- [compositor_superview_
- setAutoresizingMask:NSViewWidthSizable | NSViewHeightSizable];
-
- // Enable HiDPI backing when supported (only on 10.7+).
- if ([compositor_superview_ respondsToSelector:
- @selector(setWantsBestResolutionOpenGLSurface:)]) {
- [compositor_superview_ setWantsBestResolutionOpenGLSurface:YES];
- }
-
- // Set the layer first to create a layer-hosting view (not layer-backed), and
- // set the compositor output to go to that layer.
- base::scoped_nsobject<CALayer> background_layer([[CALayer alloc] init]);
- display_ca_layer_tree_ =
- std::make_unique<ui::DisplayCALayerTree>(background_layer.get());
- [compositor_superview_ setLayer:background_layer];
- [compositor_superview_ setWantsLayer:YES];
-
- // The UI compositor should always be the first subview, to ensure webviews
- // are drawn on top of it.
- DCHECK_EQ(0u, [[bridged_view_ subviews] count]);
- [bridged_view_ addSubview:compositor_superview_];
-}
-
-void BridgedNativeWidget::UpdateWindowGeometry() {
+void BridgedNativeWidgetImpl::UpdateWindowGeometry() {
gfx::Rect window_in_screen = gfx::ScreenRectFromNSRect([window_ frame]);
gfx::Rect content_in_screen = gfx::ScreenRectFromNSRect(
[window_ contentRectForFrameRect:[window_ frame]]);
@@ -1239,23 +1231,23 @@ void BridgedNativeWidget::UpdateWindowGeometry() {
invalidate_shadow_on_frame_swap_ = true;
}
-void BridgedNativeWidget::UpdateWindowDisplay() {
+void BridgedNativeWidgetImpl::UpdateWindowDisplay() {
host_->OnWindowDisplayChanged(
display::Screen::GetScreen()->GetDisplayNearestWindow(window_));
}
-bool BridgedNativeWidget::IsWindowModalSheet() const {
+bool BridgedNativeWidgetImpl::IsWindowModalSheet() const {
return parent_ && modal_type_ == ui::MODAL_TYPE_WINDOW;
}
-void BridgedNativeWidget::ShowAsModalSheet() {
+void BridgedNativeWidgetImpl::ShowAsModalSheet() {
// -[NSApp beginSheet:] will block the UI thread while the animation runs.
// So that it doesn't animate a fully transparent window, first wait for a
// frame. The first step is to pretend that the window is already visible.
window_visible_ = true;
host_->OnVisibilityChanged(window_visible_);
- NSWindow* parent_window = parent_->GetNSWindow();
+ NSWindow* parent_window = parent_->ns_window();
DCHECK(parent_window);
// -beginSheet: does not retain |modalDelegate| (and we would not want it to).
@@ -1269,15 +1261,4 @@ void BridgedNativeWidget::ShowAsModalSheet() {
contextInfo:nullptr];
}
-NSMutableDictionary* BridgedNativeWidget::GetWindowProperties() const {
- NSMutableDictionary* properties = objc_getAssociatedObject(
- window_, &kWindowPropertiesKey);
- if (!properties) {
- properties = [NSMutableDictionary dictionary];
- objc_setAssociatedObject(window_, &kWindowPropertiesKey,
- properties, OBJC_ASSOCIATION_RETAIN);
- }
- return properties;
-}
-
} // namespace views
diff --git a/chromium/ui/views/cocoa/cocoa_mouse_capture.h b/chromium/ui/views_bridge_mac/cocoa_mouse_capture.h
index 9b170e4a7e9..b7dedad9445 100644
--- a/chromium/ui/views/cocoa/cocoa_mouse_capture.h
+++ b/chromium/ui/views_bridge_mac/cocoa_mouse_capture.h
@@ -2,17 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_VIEWS_COCOA_COCOA_MOUSE_CAPTURE_H_
-#define UI_VIEWS_COCOA_COCOA_MOUSE_CAPTURE_H_
+#ifndef UI_VIEWS_BRIDGE_MAC_COCOA_MOUSE_CAPTURE_H_
+#define UI_VIEWS_BRIDGE_MAC_COCOA_MOUSE_CAPTURE_H_
#include <memory>
#include "base/macros.h"
-#include "ui/views/views_export.h"
+#include "ui/views_bridge_mac/views_bridge_mac_export.h"
@class NSWindow;
-namespace views {
+namespace views_bridge_mac {
class CocoaMouseCaptureDelegate;
@@ -21,7 +21,7 @@ class CocoaMouseCaptureDelegate;
// menu should dismiss the menu and "swallow" the mouse event. All events are
// forwarded, but only events to the same application are "swallowed", which is
// consistent with how native NSMenus behave.
-class VIEWS_EXPORT CocoaMouseCapture {
+class VIEWS_BRIDGE_MAC_EXPORT CocoaMouseCapture {
public:
explicit CocoaMouseCapture(CocoaMouseCaptureDelegate* delegate);
~CocoaMouseCapture();
@@ -48,6 +48,6 @@ class VIEWS_EXPORT CocoaMouseCapture {
DISALLOW_COPY_AND_ASSIGN(CocoaMouseCapture);
};
-} // namespace views
+} // namespace views_bridge_mac
-#endif // UI_VIEWS_COCOA_COCOA_MOUSE_CAPTURE_H_
+#endif // UI_VIEWS_BRIDGE_MAC_COCOA_MOUSE_CAPTURE_H_
diff --git a/chromium/ui/views/cocoa/cocoa_mouse_capture.mm b/chromium/ui/views_bridge_mac/cocoa_mouse_capture.mm
index b1f3cb216de..21f538b122f 100644
--- a/chromium/ui/views/cocoa/cocoa_mouse_capture.mm
+++ b/chromium/ui/views_bridge_mac/cocoa_mouse_capture.mm
@@ -2,16 +2,16 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#import "ui/views/cocoa/cocoa_mouse_capture.h"
+#import "ui/views_bridge_mac/cocoa_mouse_capture.h"
#import <Cocoa/Cocoa.h>
#include "base/logging.h"
#include "base/macros.h"
#include "ui/base/cocoa/weak_ptr_nsobject.h"
-#import "ui/views/cocoa/cocoa_mouse_capture_delegate.h"
+#import "ui/views_bridge_mac/cocoa_mouse_capture_delegate.h"
-namespace views {
+namespace views_bridge_mac {
// The ActiveEventTap is a RAII handle on the resources being used to capture
// events. There is either 0 or 1 active instance of this class. If a second
@@ -125,4 +125,4 @@ void CocoaMouseCapture::OnOtherClientGotCapture() {
active_handle_.reset();
}
-} // namespace views
+} // namespace views_bridge_mac
diff --git a/chromium/ui/views/cocoa/cocoa_mouse_capture_delegate.h b/chromium/ui/views_bridge_mac/cocoa_mouse_capture_delegate.h
index 9e6d2a0e4ea..41093fae784 100644
--- a/chromium/ui/views/cocoa/cocoa_mouse_capture_delegate.h
+++ b/chromium/ui/views_bridge_mac/cocoa_mouse_capture_delegate.h
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_VIEWS_COCOA_COCOA_MOUSE_CAPTURE_DELEGATE_H_
-#define UI_VIEWS_COCOA_COCOA_MOUSE_CAPTURE_DELEGATE_H_
+#ifndef UI_VIEWS_BRIDGE_MAC_COCOA_MOUSE_CAPTURE_DELEGATE_H_
+#define UI_VIEWS_BRIDGE_MAC_COCOA_MOUSE_CAPTURE_DELEGATE_H_
@class NSEvent;
@class NSWindow;
-namespace views {
+namespace views_bridge_mac {
// Delegate for receiving captured events from a CocoaMouseCapture.
class CocoaMouseCaptureDelegate {
@@ -26,6 +26,6 @@ class CocoaMouseCaptureDelegate {
virtual NSWindow* GetWindow() const = 0;
};
-} // namespace views
+} // namespace views_bridge_mac
-#endif // UI_VIEWS_COCOA_COCOA_MOUSE_CAPTURE_DELEGATE_H_
+#endif // UI_VIEWS_BRIDGE_MAC_COCOA_MOUSE_CAPTURE_DELEGATE_H_
diff --git a/chromium/ui/views/cocoa/cocoa_window_move_loop.h b/chromium/ui/views_bridge_mac/cocoa_window_move_loop.h
index e688884facb..ff074d8a8f8 100644
--- a/chromium/ui/views/cocoa/cocoa_window_move_loop.h
+++ b/chromium/ui/views_bridge_mac/cocoa_window_move_loop.h
@@ -2,27 +2,27 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_VIEWS_COCOA_COCOA_WINDOW_MOVE_LOOP_H_
-#define UI_VIEWS_COCOA_COCOA_WINDOW_MOVE_LOOP_H_
+#ifndef UI_VIEWS_BRIDGE_MAC_COCOA_WINDOW_MOVE_LOOP_H_
+#define UI_VIEWS_BRIDGE_MAC_COCOA_WINDOW_MOVE_LOOP_H_
#import <Cocoa/Cocoa.h>
#include "base/callback.h"
#include "base/memory/weak_ptr.h"
-#include "ui/views/widget/widget.h"
namespace views {
-class BridgedNativeWidget;
+class BridgedNativeWidgetImpl;
-// Used by views::BridgedNativeWidget when dragging detached tabs.
+// Used by views::BridgedNativeWidgetImpl when dragging detached tabs.
class CocoaWindowMoveLoop {
public:
- CocoaWindowMoveLoop(BridgedNativeWidget* owner,
+ CocoaWindowMoveLoop(BridgedNativeWidgetImpl* owner,
const NSPoint& initial_mouse_in_screen);
~CocoaWindowMoveLoop();
// Initiates the drag until a mouse up event is observed, or End() is called.
- Widget::MoveLoopResult Run();
+ // Returns true if a mouse up event ended the loop.
+ bool Run();
void End();
private:
@@ -32,7 +32,7 @@ class CocoaWindowMoveLoop {
WINDOW_DESTROYED,
};
- BridgedNativeWidget* owner_; // Weak. Owns this.
+ BridgedNativeWidgetImpl* owner_; // Weak. Owns this.
// Initial mouse location at the time before the CocoaWindowMoveLoop is
// created.
@@ -50,4 +50,4 @@ class CocoaWindowMoveLoop {
} // namespace views
-#endif // UI_VIEWS_COCOA_COCOA_WINDOW_MOVE_LOOP_H_
+#endif // UI_VIEWS_BRIDGE_MAC_COCOA_WINDOW_MOVE_LOOP_H_
diff --git a/chromium/ui/views/cocoa/cocoa_window_move_loop.mm b/chromium/ui/views_bridge_mac/cocoa_window_move_loop.mm
index a306f9cfb5c..4b2c64f0941 100644
--- a/chromium/ui/views/cocoa/cocoa_window_move_loop.mm
+++ b/chromium/ui/views_bridge_mac/cocoa_window_move_loop.mm
@@ -2,12 +2,15 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/views/cocoa/cocoa_window_move_loop.h"
+#include "ui/views_bridge_mac/cocoa_window_move_loop.h"
+#include "base/debug/stack_trace.h"
#include "base/run_loop.h"
+#include "base/strings/stringprintf.h"
+#include "components/crash/core/common/crash_key.h"
#include "ui/display/screen.h"
#import "ui/gfx/mac/coordinate_conversion.h"
-#import "ui/views/cocoa/bridged_native_widget.h"
+#import "ui/views_bridge_mac/bridged_native_widget_impl.h"
// When event monitors process the events the full list of monitors is cached,
// and if we unregister the event monitor that's at the end of the list while
@@ -39,15 +42,20 @@
namespace views {
-CocoaWindowMoveLoop::CocoaWindowMoveLoop(
- BridgedNativeWidget* owner,
- const NSPoint& initial_mouse_in_screen)
+CocoaWindowMoveLoop::CocoaWindowMoveLoop(BridgedNativeWidgetImpl* owner,
+ const NSPoint& initial_mouse_in_screen)
: owner_(owner),
initial_mouse_in_screen_(initial_mouse_in_screen),
- weak_factory_(this) {
-}
+ weak_factory_(this) {}
CocoaWindowMoveLoop::~CocoaWindowMoveLoop() {
+ // Record the address and stack to help catch https://crbug.com/876493.
+ static crash_reporter::CrashKeyString<19> address_key("move_loop_address");
+ address_key.Set(base::StringPrintf("%p", this));
+
+ static crash_reporter::CrashKeyString<1024> stack_key("move_loop_stack");
+ crash_reporter::SetCrashKeyStringToStackTrace(&stack_key,
+ base::debug::StackTrace());
// Handle the pathological case, where |this| is destroyed while running.
if (exit_reason_ref_) {
*exit_reason_ref_ = WINDOW_DESTROYED;
@@ -57,7 +65,7 @@ CocoaWindowMoveLoop::~CocoaWindowMoveLoop() {
owner_ = nullptr;
}
-Widget::MoveLoopResult CocoaWindowMoveLoop::Run() {
+bool CocoaWindowMoveLoop::Run() {
LoopExitReason exit_reason = ENDED_EXTERNALLY;
exit_reason_ref_ = &exit_reason;
NSWindow* window = owner_->ns_window();
@@ -75,6 +83,10 @@ Widget::MoveLoopResult CocoaWindowMoveLoop::Run() {
// TabDragController.
NSEventMask mask = NSLeftMouseUpMask | NSLeftMouseDraggedMask;
auto handler = ^NSEvent*(NSEvent* event) {
+ // The docs say this always runs on the main thread, but if it didn't,
+ // it would explain https://crbug.com/876493, so let's make sure.
+ CHECK_EQ(CFRunLoopGetMain(), CFRunLoopGetCurrent());
+
CocoaWindowMoveLoop* strong = [weak_cocoa_window_move_loop weak].get();
if (!strong || !strong->exit_reason_ref_) {
// By this point CocoaWindowMoveLoop was deleted while processing this
@@ -111,8 +123,7 @@ Widget::MoveLoopResult CocoaWindowMoveLoop::Run() {
owner_->EndMoveLoop(); // Deletes |this|.
}
- return exit_reason != MOUSE_UP ? Widget::MOVE_LOOP_CANCELED
- : Widget::MOVE_LOOP_SUCCESSFUL;
+ return exit_reason == MOUSE_UP;
}
void CocoaWindowMoveLoop::End() {
diff --git a/chromium/ui/views_bridge_mac/drag_drop_client.h b/chromium/ui/views_bridge_mac/drag_drop_client.h
new file mode 100644
index 00000000000..3efa842c4e6
--- /dev/null
+++ b/chromium/ui/views_bridge_mac/drag_drop_client.h
@@ -0,0 +1,37 @@
+// 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_VIEWS_BRIDGE_MAC_DRAG_DROP_CLIENT_H_
+#define UI_VIEWS_BRIDGE_MAC_DRAG_DROP_CLIENT_H_
+
+#import <Cocoa/Cocoa.h>
+
+#include "ui/views_bridge_mac/views_bridge_mac_export.h"
+
+namespace views_bridge_mac {
+
+// Interface between the content view of a BridgedNativeWidgetImpl and a
+// DragDropClientMac in the browser process. This interface should eventually
+// become mojo-ified, but at the moment only passes raw pointers (consequently,
+// drag-drop behavior does not work in RemoteMacViews).
+class VIEWS_BRIDGE_MAC_EXPORT DragDropClient {
+ public:
+ virtual ~DragDropClient() {}
+
+ // Called when mouse is dragged during a drag and drop.
+ virtual NSDragOperation DragUpdate(id<NSDraggingInfo>) = 0;
+
+ // Called when mouse is released during a drag and drop.
+ virtual NSDragOperation Drop(id<NSDraggingInfo> sender) = 0;
+
+ // Called when the drag and drop session has ended.
+ virtual void EndDrag() = 0;
+
+ // Called when mouse leaves the drop area.
+ virtual void DragExit() = 0;
+};
+
+} // namespace views_bridge_mac
+
+#endif // UI_VIEWS_BRIDGE_MAC_DRAG_DROP_CLIENT_H_
diff --git a/chromium/ui/views_bridge_mac/mojo/bridge_factory.mojom b/chromium/ui/views_bridge_mac/mojo/bridge_factory.mojom
new file mode 100644
index 00000000000..246ba5bb289
--- /dev/null
+++ b/chromium/ui/views_bridge_mac/mojo/bridge_factory.mojom
@@ -0,0 +1,20 @@
+// 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.
+
+module views_bridge_mac.mojom;
+
+import "ui/views_bridge_mac/mojo/bridged_native_widget.mojom";
+import "ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom";
+
+// The interface through which a bridge is created and connected to its host.
+interface BridgeFactory {
+ // Create a bridge for a native widget. The resulting object will be owned by
+ // the connection for |host|. Closing that connection will result in deleting
+ // the bridge.
+ CreateBridgedNativeWidget(
+ uint64 bridge_id,
+ associated BridgedNativeWidget& bridge_request,
+ associated BridgedNativeWidgetHost host);
+};
+
diff --git a/chromium/ui/views_bridge_mac/mojo/bridged_native_widget.mojom b/chromium/ui/views_bridge_mac/mojo/bridged_native_widget.mojom
index e120fc8268e..a256b186a6e 100644
--- a/chromium/ui/views_bridge_mac/mojo/bridged_native_widget.mojom
+++ b/chromium/ui/views_bridge_mac/mojo/bridged_native_widget.mojom
@@ -9,6 +9,13 @@ import "ui/base/mojo/ui_base_types.mojom";
import "ui/gfx/geometry/mojo/geometry.mojom";
import "ui/gfx/mojo/ca_layer_params.mojom";
+// Parameters used to described creation of an NSWindow.
+// TODO(ccameron): Add additional members to support all window sub-classes.
+struct CreateWindowParams {
+ // The NSWindowStyleMask for the window.
+ uint64 style_mask;
+};
+
// Ways of changing the visibility of the bridged NSWindow.
enum WindowVisibilityState {
// Hides with -[NSWindow orderOut:].
@@ -20,10 +27,23 @@ enum WindowVisibilityState {
kShowInactive
};
+// Window transitions to animate, mirrors views::Widget::VisibilityTransition.
+enum VisibilityTransition {
+ kShow = 1,
+ kHide = 2,
+ kBoth = 3,
+ kNone = 4,
+};
+
struct BridgedNativeWidgetInitParams {
ui.mojom.ModalType modal_type;
// If true, the underlying window potentially be seen through.
bool is_translucent;
+ // True if the widget is considered top level widget.
+ bool widget_is_top_level;
+ // True if the bounds specified to SetBounds should be treated as though they
+ // are in screen coordinates.
+ bool position_window_in_screen_coords;
// If true, then the NSWindow is set to have a shadow using
// -[NSWindow setHasShadow:YES].
bool has_window_server_shadow;
@@ -36,6 +56,13 @@ struct BridgedNativeWidgetInitParams {
// The interface through which a NativeWidgetMac may interact with an NSWindow
// in another process.
interface BridgedNativeWidget {
+ // Create and set the NSWindow for the bridge.
+ CreateWindow(CreateWindowParams params);
+
+ // Set the BridgedNativeWidget indicated by |parent_id| to be the parent of
+ // this BridgedNativeWidget.
+ SetParent(uint64 parent_id);
+
// Initialize the window's style.
InitWindow(BridgedNativeWidgetInitParams params);
@@ -44,8 +71,9 @@ interface BridgedNativeWidget {
// BridgedNativeWidgetHost.
InitCompositorView();
- // Create the NSView to be the content view for the window.
- CreateContentView(gfx.mojom.Rect bounds);
+ // Create the NSView to be the content view for the window. Use |ns_view_id|
+ // to look up this NSView in other functions (e.g, to specify a parent view).
+ CreateContentView(uint64 ns_view_id, gfx.mojom.Rect bounds);
// Destroy the content NSView for this window. Note that the window will
// become blank once this has been called.
@@ -62,12 +90,9 @@ interface BridgedNativeWidget {
// Specify initial bounds for the window via |new_bounds| in screen
// coordinates. It is invalid for |new_bounds| to have an empty size and
// non-zero position. The size of the window will be expanded so that the
- // content size will be at least |minimum_content_size|. The bounds are offset
- // by |parent_offset| (this isn't incorporated directly into |new_bounds| for
- // the aforementioned checks of |new_bounds|' position).
+ // content size will be at least |minimum_content_size|.
SetInitialBounds(gfx.mojom.Rect new_bounds,
- gfx.mojom.Size minimum_content_size,
- gfx.mojom.Vector2d parent_offset);
+ gfx.mojom.Size minimum_content_size);
// Specify new bounds for the window via |new_bounds| in screen coordinates.
// The size of the window will be expanded so that the content size will be
@@ -75,10 +100,20 @@ interface BridgedNativeWidget {
SetBounds(gfx.mojom.Rect new_bounds,
gfx.mojom.Size minimum_content_size);
+ // Centers the window and sets its content size to |content_size|. The size of
+ // the window will be expanded so that the content size will be at least
+ // |minimum_content_size|.
+ SetSizeAndCenter(gfx.mojom.Size content_size,
+ gfx.mojom.Size minimum_content_size);
+
// Sets the desired visibility of the window and updates the visibility of
// descendant windows where necessary.
SetVisibilityState(WindowVisibilityState new_state);
+ // Sets which transitions will animate. Currently this only affects non-native
+ // animations.
+ SetTransitionsToAnimate(VisibilityTransition transitions);
+
// Sets the collection behavior so that the window will or will not be visible
// on all spaces.
SetVisibleOnAllSpaces(bool always_visible);
@@ -114,6 +149,9 @@ interface BridgedNativeWidget {
// Clear the touchbar.
ClearTouchBar();
+ // Update the tooltip text at the current mouse location.
+ UpdateTooltip();
+
// Acquiring mouse capture first steals capture from any existing
// CocoaMouseCaptureDelegate, then captures all mouse events until released.
AcquireCapture();
diff --git a/chromium/ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom b/chromium/ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom
new file mode 100644
index 00000000000..cba9a6b77eb
--- /dev/null
+++ b/chromium/ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom
@@ -0,0 +1,159 @@
+// 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.
+
+module views_bridge_mac.mojom;
+
+import "mojo/public/mojom/base/string16.mojom";
+import "ui/base/mojo/ui_base_types.mojom";
+import "ui/display/mojo/display.mojom";
+import "ui/events/mojo/event.mojom";
+import "ui/gfx/geometry/mojo/geometry.mojom";
+import "ui/gfx/mojo/ca_layer_params.mojom";
+
+// The interface through which a NativeWidgetMac may interact with an NSWindow
+// in another process.
+interface BridgedNativeWidgetHost {
+ // Update the views::Widget, ui::Compositor and ui::Layer's visibility.
+ OnVisibilityChanged(bool visible);
+
+ // Called when the window's native theme changes.
+ OnWindowNativeThemeChanged();
+
+ // Resize the underlying views::View to |new_size|. Note that this will not
+ // necessarily match the content bounds from OnWindowGeometryChanged.
+ SetViewSize(gfx.mojom.Size new_size);
+
+ // Indicate if full keyboard accessibility is needed and update focus if
+ // needed.
+ SetKeyboardAccessible(bool enabled);
+
+ // Indicate if the NSView for this widget is the first responder for the
+ // NSWindow for this widget.
+ SetIsFirstResponder(bool is_first_responder);
+
+ // Indicate if mouse capture is active.
+ OnMouseCaptureActiveChanged(bool capture_is_active);
+
+ // Handle events. Note that whether or not the event is actually handled is
+ // not returned.
+ OnScrollEvent(ui.mojom.Event event);
+ OnMouseEvent(ui.mojom.Event event);
+ OnGestureEvent(ui.mojom.Event event);
+
+ // Synchronously dispatch a key event and return in |event_handled| whether
+ // or not the event was handled. This method is to be used only via the
+ // BridgedNativeWidgetHostHelper interface.
+ [Sync]
+ DispatchKeyEventRemote(ui.mojom.Event event) => (bool event_handled);
+
+ // Synchronously dispatch a key event to the current menu controller (if one
+ // exists and is owned by the widget for this). Return in |event_swallowed|
+ // whether or not the event was swallowed (that is, if the menu's dispatch
+ // returned POST_DISPATCH_NONE). Return in |event_handled| whether or not the
+ // event was handled (that is, if the event in the caller's scope should be
+ // marked as handled). This method is to be used only via the
+ // BridgedNativeWidgetHostHelper interface.
+ [Sync]
+ DispatchKeyEventToMenuControllerRemote(ui.mojom.Event event) =>
+ (bool event_swallowed, bool event_handled);
+
+ // Synchronously return in |has_menu_controller| whether or not a menu
+ // controller exists for this widget.
+ [Sync]
+ GetHasMenuController() => (bool has_menu_controller);
+
+ // Synchronously query if |location_in_content| is a draggable background.
+ [Sync]
+ GetIsDraggableBackgroundAt(gfx.mojom.Point location_in_content) =>
+ (bool is_draggable_background);
+
+ // Synchronously query the tooltip text for |location_in_content|.
+ [Sync]
+ GetTooltipTextAt(gfx.mojom.Point location_in_content) =>
+ (mojo_base.mojom.String16 new_tooltip_text);
+
+ // Synchronously query the value of IsModal for this widget and store it in
+ // |widget_is_modal|.
+ [Sync]
+ GetWidgetIsModal() => (bool widget_is_modal);
+
+ // Synchronously return in |is_textual| whether or not the focused view
+ // contains text that can be selected and copied.
+ [Sync]
+ GetIsFocusedViewTextual() => (bool is_textual);
+
+ // Called whenever the NSWindow's size or position changes.
+ OnWindowGeometryChanged(
+ gfx.mojom.Rect window_bounds_in_screen_dips,
+ gfx.mojom.Rect content_bounds_in_screen_dips);
+
+ // Called when the window begins transitioning to or from being fullscreen.
+ OnWindowFullscreenTransitionStart(
+ bool target_fullscreen_state);
+
+ // Called when the window has completed its transition to or from being
+ // fullscreen. Note that if there are multiple consecutive transitions
+ // (because a new transition was initiated before the previous one completed)
+ // then this will only be called when all transitions have competed.
+ OnWindowFullscreenTransitionComplete(bool is_fullscreen);
+
+ // Called when the window is miniaturized or deminiaturized.
+ OnWindowMiniaturizedChanged(bool miniaturized);
+
+ // Called when the current display or the properties of the current display
+ // change.
+ OnWindowDisplayChanged(display.mojom.Display display);
+
+ // Called before the NSWindow is closed and destroyed.
+ OnWindowWillClose();
+
+ // Called after the NSWindow has been closed and destroyed.
+ OnWindowHasClosed();
+
+ // Called when the NSWindow becomes key or resigns from being key. Additional
+ // state required for the transition include whether or not the content NSView
+ // is the first responder for the NSWindow in |is_content_first_responder| and
+ // whether or not the NSApp's full keyboard access is enabled in
+ // |full_keyboard_access_enabled|.
+ OnWindowKeyStatusChanged(bool is_key,
+ bool is_content_first_responder,
+ bool full_keyboard_access_enabled);
+
+ // Accept or cancel the current dialog window (depending on the value of
+ // |button|), if a current dialog exists.
+ DoDialogButtonAction(ui.mojom.DialogButton button);
+
+ // Synchronously determine if the specified button exists in the current
+ // dialog (if any), along with its label, whether or not it is enabled, and
+ // whether or not it is the default button..
+ [Sync]
+ GetDialogButtonInfo(ui.mojom.DialogButton button) => (bool button_exists,
+ mojo_base.mojom.String16 title,
+ bool is_button_enabled,
+ bool is_button_default);
+
+ // Synchronously return in |buttons_exist| whether or not any buttons exist
+ // for the current dialog.
+ [Sync]
+ GetDoDialogButtonsExist() => (bool buttons_exist);
+
+ // Synchronously query if the NSWindow should display its title.
+ [Sync]
+ GetShouldShowWindowTitle() => (bool should_show_window_title);
+
+ // Synchronously query if the NSWindow can become key (activate, in views
+ // terminology).
+ [Sync]
+ GetCanWindowBecomeKey() => (bool can_window_become_key);
+
+ // Synchronously query if the NSWindow should always render as if it is
+ // the key window (is active, in views terminology).
+ [Sync]
+ GetAlwaysRenderWindowAsKey() => (bool always_render_as_key);
+
+ // Synchronously query if the NSWindow should always render as if it is
+ // the key window (is active, in views terminology).
+ [Sync]
+ GetCanWindowClose() => (bool can_window_close);
+};
diff --git a/chromium/ui/views/cocoa/native_widget_mac_nswindow.h b/chromium/ui/views_bridge_mac/native_widget_mac_nswindow.h
index 8a0f51b791b..ef8afe11aee 100644
--- a/chromium/ui/views/cocoa/native_widget_mac_nswindow.h
+++ b/chromium/ui/views_bridge_mac/native_widget_mac_nswindow.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_VIEWS_COCOA_NATIVE_WIDGET_MAC_NSWINDOW_H_
-#define UI_VIEWS_COCOA_NATIVE_WIDGET_MAC_NSWINDOW_H_
+#ifndef UI_VIEWS_BRIDGE_MAC_NATIVE_WIDGET_MAC_NSWINDOW_H_
+#define UI_VIEWS_BRIDGE_MAC_NATIVE_WIDGET_MAC_NSWINDOW_H_
#import <Cocoa/Cocoa.h>
@@ -47,6 +47,10 @@ VIEWS_EXPORT
// create one.
- (void)setWindowTouchBarDelegate:(id<WindowTouchBarDelegate>)delegate;
+// Identifier for the NativeWidgetMac from which this window was created. This
+// may be used to look up the BridgedNativeWidgetHostImpl in the browser process
+// or the BridgedNativeWidgetImpl in a display process.
+@property(assign, nonatomic) uint64_t bridgedNativeWidgetId;
@end
-#endif // UI_VIEWS_COCOA_NATIVE_WIDGET_MAC_NSWINDOW_H_
+#endif // UI_VIEWS_BRIDGE_MAC_NATIVE_WIDGET_MAC_NSWINDOW_H_
diff --git a/chromium/ui/views/cocoa/native_widget_mac_nswindow.mm b/chromium/ui/views_bridge_mac/native_widget_mac_nswindow.mm
index 3e5775bc184..f0e7ac703ae 100644
--- a/chromium/ui/views/cocoa/native_widget_mac_nswindow.mm
+++ b/chromium/ui/views_bridge_mac/native_widget_mac_nswindow.mm
@@ -2,18 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#import "ui/views/cocoa/native_widget_mac_nswindow.h"
+#import "ui/views_bridge_mac/native_widget_mac_nswindow.h"
#include "base/mac/foundation_util.h"
#import "base/mac/sdk_forward_declarations.h"
#import "ui/base/cocoa/user_interface_item_command_handler.h"
#import "ui/base/cocoa/window_size_constants.h"
-#import "ui/views/cocoa/bridged_native_widget.h"
-#import "ui/views/cocoa/views_nswindow_delegate.h"
-#import "ui/views/cocoa/window_touch_bar_delegate.h"
-#include "ui/views/controls/menu/menu_controller.h"
-#include "ui/views/widget/native_widget_mac.h"
-#include "ui/views/widget/widget_delegate.h"
+#include "ui/views_bridge_mac/bridged_native_widget_host_helper.h"
+#import "ui/views_bridge_mac/bridged_native_widget_impl.h"
+#include "ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom.h"
+#import "ui/views_bridge_mac/views_nswindow_delegate.h"
+#import "ui/views_bridge_mac/window_touch_bar_delegate.h"
@interface NSWindow (Private)
+ (Class)frameViewClassForStyleMask:(NSWindowStyleMask)windowStyle;
@@ -27,13 +26,15 @@
@interface NativeWidgetMacNSWindow ()
- (ViewsNSWindowDelegate*)viewsNSWindowDelegate;
-- (views::Widget*)viewsWidget;
- (BOOL)hasViewsMenuActive;
- (id)rootAccessibilityObject;
// Private API on NSWindow, determines whether the title is drawn on the title
// bar. The title is still visible in menus, Expose, etc.
- (BOOL)_isTitleHidden;
+
+// Retrieve the corresponding views::BridgedNativeWidgetImpl in this process.
+- (views::BridgedNativeWidgetImpl*)bridgeImpl;
@end
// Use this category to implement mouseDown: on multiple frame view classes
@@ -83,7 +84,9 @@
base::scoped_nsobject<CommandDispatcher> commandDispatcher_;
base::scoped_nsprotocol<id<UserInterfaceItemCommandHandler>> commandHandler_;
id<WindowTouchBarDelegate> touchBarDelegate_; // Weak.
+ uint64_t bridgedNativeWidgetId_;
}
+@synthesize bridgedNativeWidgetId = bridgedNativeWidgetId_;
- (instancetype)initWithContentRect:(NSRect)contentRect
styleMask:(NSUInteger)windowStyle
@@ -114,9 +117,9 @@
- (void)sheetDidEnd:(NSWindow*)sheet
returnCode:(NSInteger)returnCode
contextInfo:(void*)contextInfo {
- // Note BridgedNativeWidget may have cleared [self delegate], in which case
- // this will no-op. This indirection is necessary to handle AppKit invoking
- // this selector via a posted task. See https://crbug.com/851376.
+ // Note BridgedNativeWidgetImpl may have cleared [self delegate], in which
+ // case this will no-op. This indirection is necessary to handle AppKit
+ // invoking this selector via a posted task. See https://crbug.com/851376.
[[self viewsNSWindowDelegate] sheetDidEnd:sheet
returnCode:returnCode
contextInfo:contextInfo];
@@ -132,19 +135,18 @@
return base::mac::ObjCCastStrict<ViewsNSWindowDelegate>([self delegate]);
}
-- (views::Widget*)viewsWidget {
- return [[self viewsNSWindowDelegate] nativeWidgetMac]->GetWidget();
+- (views::BridgedNativeWidgetImpl*)bridgeImpl {
+ return views::BridgedNativeWidgetImpl::GetFromId(bridgedNativeWidgetId_);
}
- (BOOL)hasViewsMenuActive {
- views::MenuController* menuController =
- views::MenuController::GetActiveInstance();
- return menuController && menuController->owner() == [self viewsWidget];
+ bool hasMenuController = false;
+ [self bridgeImpl]->host()->GetHasMenuController(&hasMenuController);
+ return hasMenuController;
}
- (id)rootAccessibilityObject {
- views::Widget* widget = [self viewsWidget];
- return widget ? widget->GetRootView()->GetNativeViewAccessible() : nil;
+ return [self bridgeImpl]->host_helper()->GetNativeViewAccessible();
}
// NSWindow overrides.
@@ -161,10 +163,10 @@
}
- (BOOL)_isTitleHidden {
- if (![self delegate])
- return NO;
-
- return ![self viewsWidget]->widget_delegate()->ShouldShowWindowTitle();
+ bool shouldShowWindowTitle = YES;
+ if ([self bridgeImpl])
+ [self bridgeImpl]->host()->GetShouldShowWindowTitle(&shouldShowWindowTitle);
+ return !shouldShowWindowTitle;
}
// The base implementation returns YES if the window's frame view is a custom
@@ -179,23 +181,36 @@
// Note these can be called via -[NSWindow close] while the widget is being torn
// down, so check for a delegate.
- (BOOL)canBecomeKeyWindow {
- return [self delegate] && [self viewsWidget]->CanActivate();
+ bool canBecomeKey = NO;
+ if ([self bridgeImpl])
+ [self bridgeImpl]->host()->GetCanWindowBecomeKey(&canBecomeKey);
+ return canBecomeKey;
}
- (BOOL)canBecomeMainWindow {
- if (![self delegate])
+ views::BridgedNativeWidgetImpl* bridgeImpl = [self bridgeImpl];
+ if (!bridgeImpl)
return NO;
// Dialogs and bubbles shouldn't take large shadows away from their parent.
- views::Widget* widget = [self viewsWidget];
- return widget->CanActivate() &&
- !views::NativeWidgetMac::GetBridgeForNativeWindow(self)->parent();
+ if (bridgeImpl->parent())
+ return NO;
+
+ bool canBecomeKey = NO;
+ if (bridgeImpl)
+ bridgeImpl->host()->GetCanWindowBecomeKey(&canBecomeKey);
+ return canBecomeKey;
}
// Lets the traffic light buttons on the parent window keep their active state.
- (BOOL)hasKeyAppearance {
- if ([self delegate] && [self viewsWidget]->IsAlwaysRenderAsActive())
- return YES;
+ views::BridgedNativeWidgetImpl* bridgeImpl = [self bridgeImpl];
+ if (bridgeImpl) {
+ bool isAlwaysRenderWindowAsKey = NO;
+ bridgeImpl->host()->GetAlwaysRenderWindowAsKey(&isAlwaysRenderWindowAsKey);
+ if (isAlwaysRenderWindowAsKey)
+ return YES;
+ }
return [super hasKeyAppearance];
}
@@ -312,12 +327,12 @@
// Additionally, if we don't do this, VoiceOver reads out the partial a11y
// properties on the NSWindow and repeats them when focusing an item in the
// RootView's a11y group. See http://crbug.com/748221.
- views::Widget* widget = [self viewsWidget];
id superFocus = [super accessibilityFocusedUIElement];
- if (!widget || superFocus != self)
+ views::BridgedNativeWidgetImpl* bridgeImpl = [self bridgeImpl];
+ if (!bridgeImpl || superFocus != self)
return superFocus;
- return widget->GetRootView()->GetNativeViewAccessible();
+ return bridgeImpl->host_helper()->GetNativeViewAccessible();
}
- (id)accessibilityAttributeValue:(NSString*)attribute {
diff --git a/chromium/ui/views_bridge_mac/views_bridge_mac_export.h b/chromium/ui/views_bridge_mac/views_bridge_mac_export.h
new file mode 100644
index 00000000000..6a44a0d32e0
--- /dev/null
+++ b/chromium/ui/views_bridge_mac/views_bridge_mac_export.h
@@ -0,0 +1,32 @@
+// 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_VIEWS_BRIDGE_MAC_VIEWS_BRIDGE_MAC_EXPORT_H_
+#define UI_VIEWS_BRIDGE_MAC_VIEWS_BRIDGE_MAC_EXPORT_H_
+
+// Defines VIEWS_BRIDGE_MAC_EXPORT so that functionality implemented by the
+// RemoteMacViews module can be exported to consumers.
+
+#if defined(COMPONENT_BUILD)
+#if defined(WIN32)
+
+#if defined(VIEWS_BRIDGE_MAC_IMPLEMENTATION)
+#define VIEWS_BRIDGE_MAC_EXPORT __declspec(dllexport)
+#else
+#define VIEWS_BRIDGE_MAC_EXPORT __declspec(dllimport)
+#endif // defined(VIEWS_BRIDGE_MAC_IMPLEMENTATION)
+
+#else // defined(WIN32)
+#if defined(VIEWS_BRIDGE_MAC_IMPLEMENTATION)
+#define VIEWS_BRIDGE_MAC_EXPORT __attribute__((visibility("default")))
+#else
+#define VIEWS_BRIDGE_MAC_EXPORT
+#endif
+#endif
+
+#else // defined(COMPONENT_BUILD)
+#define VIEWS_BRIDGE_MAC_EXPORT
+#endif
+
+#endif // UI_VIEWS_BRIDGE_MAC_VIEWS_BRIDGE_MAC_EXPORT_H_
diff --git a/chromium/ui/views/cocoa/views_nswindow_delegate.h b/chromium/ui/views_bridge_mac/views_nswindow_delegate.h
index 00c2e13bbab..bc9f33afddf 100644
--- a/chromium/ui/views/cocoa/views_nswindow_delegate.h
+++ b/chromium/ui/views_bridge_mac/views_nswindow_delegate.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_VIEWS_COCOA_VIEWS_NSWINDOW_DELEGATE_H_
-#define UI_VIEWS_COCOA_VIEWS_NSWINDOW_DELEGATE_H_
+#ifndef UI_VIEWS_BRIDGE_MAC_VIEWS_NSWINDOW_DELEGATE_H_
+#define UI_VIEWS_BRIDGE_MAC_VIEWS_NSWINDOW_DELEGATE_H_
#import <Cocoa/Cocoa.h>
@@ -11,29 +11,24 @@
#include "ui/views/views_export.h"
namespace views {
-class NativeWidgetMac;
-class BridgedNativeWidget;
+class BridgedNativeWidgetImpl;
}
-// The delegate set on the NSWindow when a views::BridgedNativeWidget is
+// The delegate set on the NSWindow when a views::BridgedNativeWidgetImpl is
// initialized.
VIEWS_EXPORT
@interface ViewsNSWindowDelegate : NSObject<NSWindowDelegate> {
@private
- views::BridgedNativeWidget* parent_; // Weak. Owns this.
+ views::BridgedNativeWidgetImpl* parent_; // Weak. Owns this.
base::scoped_nsobject<NSCursor> cursor_;
}
-// The NativeWidgetMac that created the window this is attached to. Returns
-// NULL if not created by NativeWidgetMac.
-@property(nonatomic, readonly) views::NativeWidgetMac* nativeWidgetMac;
-
// If set, the cursor set in -[NSResponder updateCursor:] when the window is
// reached along the responder chain.
@property(retain, nonatomic) NSCursor* cursor;
// Initialize with the given |parent|.
-- (id)initWithBridgedNativeWidget:(views::BridgedNativeWidget*)parent;
+- (id)initWithBridgedNativeWidget:(views::BridgedNativeWidgetImpl*)parent;
// Notify that the window has been reordered in (or removed from) the window
// server's screen list. This is a substitute for -[NSWindowDelegate
@@ -52,4 +47,4 @@ VIEWS_EXPORT
@end
-#endif // UI_VIEWS_COCOA_VIEWS_NSWINDOW_DELEGATE_H_
+#endif // UI_VIEWS_BRIDGE_MAC_VIEWS_NSWINDOW_DELEGATE_H_
diff --git a/chromium/ui/views/cocoa/views_nswindow_delegate.mm b/chromium/ui/views_bridge_mac/views_nswindow_delegate.mm
index bce74956126..ca77131d78f 100644
--- a/chromium/ui/views/cocoa/views_nswindow_delegate.mm
+++ b/chromium/ui/views_bridge_mac/views_nswindow_delegate.mm
@@ -2,19 +2,19 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#import "ui/views/cocoa/views_nswindow_delegate.h"
+#import "ui/views_bridge_mac/views_nswindow_delegate.h"
#include "base/bind.h"
#include "base/logging.h"
#include "base/threading/thread_task_runner_handle.h"
-#import "ui/views/cocoa/bridged_content_view.h"
-#import "ui/views/cocoa/bridged_native_widget.h"
-#include "ui/views/cocoa/bridged_native_widget_host.h"
-#include "ui/views/widget/native_widget_mac.h"
+#import "ui/views_bridge_mac/bridged_content_view.h"
+#include "ui/views_bridge_mac/bridged_native_widget_host_helper.h"
+#import "ui/views_bridge_mac/bridged_native_widget_impl.h"
+#include "ui/views_bridge_mac/mojo/bridged_native_widget_host.mojom.h"
@implementation ViewsNSWindowDelegate
-- (id)initWithBridgedNativeWidget:(views::BridgedNativeWidget*)parent {
+- (id)initWithBridgedNativeWidget:(views::BridgedNativeWidgetImpl*)parent {
DCHECK(parent);
if ((self = [super init])) {
parent_ = parent;
@@ -22,10 +22,6 @@
return self;
}
-- (views::NativeWidgetMac*)nativeWidgetMac {
- return parent_->native_widget_mac();
-}
-
- (NSCursor*)cursor {
return cursor_.get();
}
@@ -64,7 +60,7 @@
break;
currentWindow = parentWindow;
if ([currentWindow isKeyWindow]) {
- [(newCursor ? newCursor : [NSCursor arrowCursor]) set];
+ [(newCursor ? newCursor : [NSCursor arrowCursor])set];
break;
}
}
@@ -123,9 +119,9 @@
}
- (BOOL)windowShouldClose:(id)sender {
- views::NonClientView* nonClientView =
- [self nativeWidgetMac]->GetWidget()->non_client_view();
- return !nonClientView || nonClientView->CanClose();
+ bool canWindowClose = true;
+ parent_->host()->GetCanWindowClose(&canWindowClose);
+ return canWindowClose;
}
- (void)windowWillClose:(NSNotification*)notification {
@@ -199,12 +195,15 @@
- (NSRect)window:(NSWindow*)window
willPositionSheet:(NSWindow*)sheet
usingRect:(NSRect)defaultSheetLocation {
+ // TODO(ccameron): This should go through the BridgedNativeWidgetHost
+ // interface.
+ CGFloat sheetPositionY = parent_->host_helper()->SheetPositionY();
+
// As per NSWindowDelegate documentation, the origin indicates the top left
// point of the host frame in window coordinates. The width changes the
// animation from vertical to trapezoid if it is smaller than the width of the
// dialog. The height is ignored but should be set to zero.
- return NSMakeRect(0, [self nativeWidgetMac]->SheetPositionY(),
- NSWidth(defaultSheetLocation), 0);
+ return NSMakeRect(0, sheetPositionY, NSWidth(defaultSheetLocation), 0);
}
@end
diff --git a/chromium/ui/views/cocoa/views_scrollbar_bridge.h b/chromium/ui/views_bridge_mac/views_scrollbar_bridge.h
index eb070a161c5..7b5809eba8f 100644
--- a/chromium/ui/views/cocoa/views_scrollbar_bridge.h
+++ b/chromium/ui/views_bridge_mac/views_scrollbar_bridge.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_VIEWS_COCOA_VIEWS_SCROLLBAR_BRIDGE_DELEGATE_H_
-#define UI_VIEWS_COCOA_VIEWS_SCROLLBAR_BRIDGE_DELEGATE_H_
+#ifndef UI_VIEWS_BRIDGE_MAC_VIEWS_SCROLLBAR_BRIDGE_H_
+#define UI_VIEWS_BRIDGE_MAC_VIEWS_SCROLLBAR_BRIDGE_H_
#import <Cocoa/Cocoa.h>
@@ -30,11 +30,11 @@ class ViewsScrollbarBridgeDelegate {
- (id)initWithDelegate:(ViewsScrollbarBridgeDelegate*)delegate;
// Sets |delegate_| to nullptr.
--(void)clearDelegate;
+- (void)clearDelegate;
// Returns the style of scrollers that OSX is using.
+ (NSScrollerStyle)getPreferredScrollerStyle;
@end
-#endif \ No newline at end of file
+#endif
diff --git a/chromium/ui/views/cocoa/views_scrollbar_bridge.mm b/chromium/ui/views_bridge_mac/views_scrollbar_bridge.mm
index d80dece0e7b..c720483d4fe 100644
--- a/chromium/ui/views/cocoa/views_scrollbar_bridge.mm
+++ b/chromium/ui/views_bridge_mac/views_scrollbar_bridge.mm
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#import "ui/views/cocoa/views_scrollbar_bridge.h"
+#import "ui/views_bridge_mac/views_scrollbar_bridge.h"
#import "base/mac/sdk_forward_declarations.h"
diff --git a/chromium/ui/views/cocoa/window_touch_bar_delegate.h b/chromium/ui/views_bridge_mac/window_touch_bar_delegate.h
index daef5466ed6..9de867197fd 100644
--- a/chromium/ui/views/cocoa/window_touch_bar_delegate.h
+++ b/chromium/ui/views_bridge_mac/window_touch_bar_delegate.h
@@ -2,8 +2,8 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_VIEWS_COCOA_WINDOW_TOUCH_BAR_DELEGATE_H_
-#define UI_VIEWS_COCOA_WINDOW_TOUCH_BAR_DELEGATE_H_
+#ifndef UI_VIEWS_BRIDGE_MAC_WINDOW_TOUCH_BAR_DELEGATE_H_
+#define UI_VIEWS_BRIDGE_MAC_WINDOW_TOUCH_BAR_DELEGATE_H_
#import <Cocoa/Cocoa.h>
@@ -18,4 +18,4 @@
@end
-#endif // UI_VIEWS_COCOA_WINDOW_TOUCH_BAR_DELEGATE_H_ \ No newline at end of file
+#endif // UI_VIEWS_BRIDGE_MAC_WINDOW_TOUCH_BAR_DELEGATE_H_
diff --git a/chromium/ui/views_content_client/views_content_client.h b/chromium/ui/views_content_client/views_content_client.h
index 11f653a2476..d71a12fbe01 100644
--- a/chromium/ui/views_content_client/views_content_client.h
+++ b/chromium/ui/views_content_client/views_content_client.h
@@ -66,6 +66,13 @@ class VIEWS_CONTENT_CLIENT_EXPORT ViewsContentClient {
void set_task(const Task& task) { task_ = task; }
const Task& task() const { return task_; }
+ // Called by ViewsContentClientMainParts to supply the quit-closure to use
+ // to exit RunMain().
+ void set_quit_closure(base::OnceClosure quit_closure) {
+ quit_closure_ = std::move(quit_closure);
+ }
+ base::OnceClosure& quit_closure() { return quit_closure_; }
+
private:
#if defined(OS_WIN)
HINSTANCE instance_;
@@ -75,6 +82,7 @@ class VIEWS_CONTENT_CLIENT_EXPORT ViewsContentClient {
const char** argv_;
#endif
Task task_;
+ base::OnceClosure quit_closure_;
DISALLOW_COPY_AND_ASSIGN(ViewsContentClient);
};
diff --git a/chromium/ui/views_content_client/views_content_client_main_parts.cc b/chromium/ui/views_content_client/views_content_client_main_parts.cc
index 3f789391eaf..5a5abb34842 100644
--- a/chromium/ui/views_content_client/views_content_client_main_parts.cc
+++ b/chromium/ui/views_content_client/views_content_client_main_parts.cc
@@ -12,6 +12,7 @@
#include "ui/base/ime/input_method_initializer.h"
#include "ui/base/material_design/material_design_controller.h"
#include "ui/views/test/desktop_test_views_delegate.h"
+#include "ui/views_content_client/views_content_client.h"
namespace ui {
@@ -44,6 +45,7 @@ void ViewsContentClientMainParts::PostMainMessageLoopRun() {
bool ViewsContentClientMainParts::MainMessageLoopRun(int* result_code) {
base::RunLoop run_loop;
+ views_content_client_->set_quit_closure(run_loop.QuitClosure());
run_loop.Run();
return true;
}
diff --git a/chromium/ui/web_dialogs/BUILD.gn b/chromium/ui/web_dialogs/BUILD.gn
index d5d48e4970d..d09fa063ddd 100644
--- a/chromium/ui/web_dialogs/BUILD.gn
+++ b/chromium/ui/web_dialogs/BUILD.gn
@@ -33,7 +33,7 @@ jumbo_component("web_dialogs") {
}
}
-static_library("test_support") {
+jumbo_static_library("test_support") {
sources = [
"test/test_web_contents_handler.cc",
"test/test_web_contents_handler.h",
diff --git a/chromium/ui/web_dialogs/web_dialog_delegate.cc b/chromium/ui/web_dialogs/web_dialog_delegate.cc
index f5ae08226cf..b2ecbf67a84 100644
--- a/chromium/ui/web_dialogs/web_dialog_delegate.cc
+++ b/chromium/ui/web_dialogs/web_dialog_delegate.cc
@@ -8,6 +8,10 @@
namespace ui {
+base::string16 WebDialogDelegate::GetAccessibleDialogTitle() const {
+ return GetDialogTitle();
+}
+
std::string WebDialogDelegate::GetDialogName() const {
return std::string();
}
diff --git a/chromium/ui/web_dialogs/web_dialog_delegate.h b/chromium/ui/web_dialogs/web_dialog_delegate.h
index b966e1fa8d8..ee639fd025e 100644
--- a/chromium/ui/web_dialogs/web_dialog_delegate.h
+++ b/chromium/ui/web_dialogs/web_dialog_delegate.h
@@ -41,6 +41,9 @@ class WEB_DIALOGS_EXPORT WebDialogDelegate {
// Returns the title of the dialog.
virtual base::string16 GetDialogTitle() const = 0;
+ // Returns the title to be read with screen readers.
+ virtual base::string16 GetAccessibleDialogTitle() const;
+
// Returns the dialog's name identifier. Used to identify this dialog for
// state restoration.
virtual std::string GetDialogName() const;
diff --git a/chromium/ui/webui/PLATFORM_OWNERS b/chromium/ui/webui/PLATFORM_OWNERS
index 29e5a4ae960..a93051bd3f8 100644
--- a/chromium/ui/webui/PLATFORM_OWNERS
+++ b/chromium/ui/webui/PLATFORM_OWNERS
@@ -1,10 +1,8 @@
# Please use more specific OWNERS when possible.
-bauerb@chromium.org
calamity@chromium.org
dpapad@chromium.org
dschuyler@chromium.org
michaelpg@chromium.org
-pam@chromium.org
scottchen@chromium.org
stevenjb@chromium.org
tommycli@chromium.org
diff --git a/chromium/ui/webui/mojo_web_ui_controller.cc b/chromium/ui/webui/mojo_web_ui_controller.cc
index e2de8d20f8a..769e194449c 100644
--- a/chromium/ui/webui/mojo_web_ui_controller.cc
+++ b/chromium/ui/webui/mojo_web_ui_controller.cc
@@ -24,6 +24,12 @@ void MojoWebUIController::OnInterfaceRequestFromFrame(
content::RenderFrameHost* render_frame_host,
const std::string& interface_name,
mojo::ScopedMessagePipeHandle* interface_pipe) {
+ if (!registry_.CanBindInterface(interface_name)) {
+ LOG(WARNING) << "Cannot bind request to " << interface_name << "; ignoring "
+ << "request.";
+ return;
+ }
+
// Right now, this is expected to be called only for main frames.
if (render_frame_host->GetParent()) {
LOG(ERROR) << "Terminating renderer for requesting " << interface_name
diff --git a/chromium/ui/webui/resources/cr_components/BUILD.gn b/chromium/ui/webui/resources/cr_components/BUILD.gn
index f3d71a3a372..b39708e6607 100644
--- a/chromium/ui/webui/resources/cr_components/BUILD.gn
+++ b/chromium/ui/webui/resources/cr_components/BUILD.gn
@@ -7,6 +7,9 @@ import("//third_party/closure_compiler/compile_js.gni")
group("closure_compile") {
deps = [
"certificate_manager:closure_compile",
- "chromeos:closure_compile",
]
+
+ if (is_chromeos) {
+ deps += [ "chromeos:closure_compile" ]
+ }
}
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/BUILD.gn b/chromium/ui/webui/resources/cr_components/chromeos/BUILD.gn
index 0fd1a54821e..3c7e36300ab 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/BUILD.gn
+++ b/chromium/ui/webui/resources/cr_components/chromeos/BUILD.gn
@@ -4,9 +4,12 @@
import("//third_party/closure_compiler/compile_js.gni")
+assert(is_chromeos, "Only ChromeOS components belong here.")
+
group("closure_compile") {
deps = [
":chromeos_resources",
+ "multidevice_setup:closure_compile",
"network:closure_compile",
"quick_unlock:closure_compile",
]
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/.eslintrc.js b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/.eslintrc.js
new file mode 100644
index 00000000000..25e21f992eb
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/.eslintrc.js
@@ -0,0 +1,13 @@
+// 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.
+
+module.exports = {
+ 'env': {
+ 'browser': true,
+ 'es6': true,
+ },
+ 'rules': {
+ 'no-var': 'error',
+ },
+};
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/BUILD.gn b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/BUILD.gn
new file mode 100644
index 00000000000..616ad6e48f5
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/BUILD.gn
@@ -0,0 +1,129 @@
+# 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")
+
+assert(is_chromeos, "MultiDevice UI is Chrome OS only.")
+
+js_type_check("closure_compile") {
+ deps = [
+ ":button_bar",
+ ":fake_mojo_service",
+ ":mojo_api",
+ ":multidevice_setup",
+ ":multidevice_setup_browser_proxy",
+ ":multidevice_setup_delegate",
+ ":setup_failed_page",
+ ":setup_succeeded_page",
+ ":start_setup_page",
+ ":ui_page_container_behavior",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ ]
+}
+
+js_library("button_bar") {
+}
+
+js_library("fake_mojo_service") {
+ deps = [
+ "//ui/webui/resources/js:cr",
+ ]
+
+ extra_deps = [
+ "//chromeos/services/device_sync/public/mojom:mojom_js",
+ "//chromeos/services/multidevice_setup/public/mojom:mojom_js",
+ "//mojo/public/mojom/base:base_js",
+ ]
+
+ externs_list = [
+ "$root_gen_dir/chromeos/services/device_sync/public/mojom/device_sync.mojom.externs.js",
+ "$root_gen_dir/chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.externs.js",
+ "$root_gen_dir/mojo/public/mojom/base/time.mojom.externs.js",
+ "$externs_path/mojo.js",
+ ]
+}
+
+js_library("mojo_api") {
+ deps = [
+ "//ui/webui/resources/js:cr",
+ ]
+}
+
+js_library("multidevice_setup") {
+ deps = [
+ ":button_bar",
+ ":fake_mojo_service",
+ ":mojo_api",
+ ":multidevice_setup_delegate",
+ ":password_page",
+ ":setup_failed_page",
+ ":setup_succeeded_page",
+ ":start_setup_page",
+ "//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ ]
+
+ extra_deps = [
+ "//chromeos/services/device_sync/public/mojom:mojom_js",
+ "//chromeos/services/multidevice_setup/public/mojom:mojom_js",
+ "//mojo/public/mojom/base:base_js",
+ ]
+
+ externs_list = [
+ "$root_gen_dir/chromeos/services/device_sync/public/mojom/device_sync.mojom.externs.js",
+ "$root_gen_dir/chromeos/services/multidevice_setup/public/mojom/multidevice_setup.mojom.externs.js",
+ "$root_gen_dir/mojo/public/mojom/base/time.mojom.externs.js",
+ "$externs_path/mojo.js",
+ ]
+}
+
+js_library("multidevice_setup_browser_proxy") {
+ deps = [
+ "//ui/webui/resources/js:cr",
+ ]
+}
+
+js_library("multidevice_setup_delegate") {
+ deps = [
+ "//ui/webui/resources/js:cr",
+ ]
+}
+
+js_library("password_page") {
+ deps = [
+ ":multidevice_setup_browser_proxy",
+ ":ui_page_container_behavior",
+ "//ui/webui/resources/cr_elements/cr_input:cr_input",
+ "//ui/webui/resources/js:cr",
+ ]
+ externs_list = [ "$externs_path/quick_unlock_private.js" ]
+ extra_sources = [ "$interfaces_path/quick_unlock_private_interface.js" ]
+}
+
+js_library("setup_failed_page") {
+ deps = [
+ ":ui_page_container_behavior",
+ ]
+}
+
+js_library("setup_succeeded_page") {
+ deps = [
+ ":multidevice_setup_browser_proxy",
+ ":ui_page_container_behavior",
+ ]
+}
+
+js_library("start_setup_page") {
+ deps = [
+ ":ui_page_container_behavior",
+ "//ui/webui/resources/js:web_ui_listener_behavior",
+ ]
+}
+
+js_library("ui_page_container_behavior") {
+ deps = [
+ "//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:i18n_behavior",
+ ]
+}
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/OWNERS b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/OWNERS
new file mode 100644
index 00000000000..aef4ecb9195
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/OWNERS
@@ -0,0 +1 @@
+file://chromeos/services/multidevice_setup/OWNERS
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/button_bar.html b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/button_bar.html
new file mode 100644
index 00000000000..7b6c70c4df6
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/button_bar.html
@@ -0,0 +1,31 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup_shared_css.html">
+
+<dom-module id="button-bar">
+ <template>
+ <style include="multidevice-setup-shared">
+ :host {
+ display: flex;
+ }
+ </style>
+ <div id="backward"
+ on-click="onBackwardButtonClicked_"
+ hidden$="[[backwardButtonHidden]]">
+ <slot name="backward-button"></slot>
+ </div>
+ <div class="flex"></div>
+ <div id="cancel"
+ on-click="onCancelButtonClicked_"
+ hidden$="[[cancelButtonHidden]]">
+ <slot name="cancel-button"></slot>
+ </div>
+ <div id="forward"
+ on-click="onForwardButtonClicked_"
+ hidden$="[[forwardButtonHidden]]">
+ <slot name="forward-button"></slot>
+ </div>
+ </template>
+ <script src="chrome://resources/cr_components/chromeos/multidevice_setup/button_bar.js">
+ </script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/button_bar.js b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/button_bar.js
new file mode 100644
index 00000000000..f556598dce9
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/button_bar.js
@@ -0,0 +1,46 @@
+// 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.
+
+/**
+ * DOM Element containing (page-dependent) navigation buttons for the
+ * MultiDevice Setup WebUI.
+ */
+Polymer({
+ is: 'button-bar',
+
+ properties: {
+ /** Whether the forward button should be hidden. */
+ forwardButtonHidden: {
+ type: Boolean,
+ value: true,
+ },
+
+ /** Whether the cancel button should be hidden. */
+ cancelButtonHidden: {
+ type: Boolean,
+ value: true,
+ },
+
+ /** Whether the backward button should be hidden. */
+ backwardButtonHidden: {
+ type: Boolean,
+ value: true,
+ },
+ },
+
+ /** @private */
+ onForwardButtonClicked_: function() {
+ this.fire('forward-navigation-requested');
+ },
+
+ /** @private */
+ onCancelButtonClicked_: function() {
+ this.fire('cancel-requested');
+ },
+
+ /** @private */
+ onBackwardButtonClicked_: function() {
+ this.fire('backward-navigation-requested');
+ },
+});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/fake_mojo_service.html b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/fake_mojo_service.html
new file mode 100644
index 00000000000..12556f5782b
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/fake_mojo_service.html
@@ -0,0 +1,4 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+
+<script src="chrome://resources/cr_components/chromeos/multidevice_setup/fake_mojo_service.js">
+</script>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/fake_mojo_service.js b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/fake_mojo_service.js
new file mode 100644
index 00000000000..48e3eaa4ef0
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/fake_mojo_service.js
@@ -0,0 +1,108 @@
+// 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.
+
+/**
+ * @implements {chromeos.multideviceSetup.mojom.MultiDeviceSetupImpl}
+ */
+class FakeMojoService {
+ constructor() {
+ /**
+ * The number of devices to return in a getEligibleHostDevices() call.
+ * @type {number}
+ */
+ this.deviceCount = 2;
+
+ /**
+ * Whether calls to setHostDevice() should succeed.
+ * @type {boolean}
+ */
+ this.shouldSetHostSucceed = true;
+ }
+
+ /** @override */
+ setAccountStatusChangeDelegate(delegate) {
+ // Unimplemented; never called from setup flow.
+ assertNotReached();
+ }
+
+ /** @override */
+ addHostStatusObserver(observer) {
+ // Unimplemented; never called from setup flow.
+ assertNotReached();
+ }
+
+ /** @override */
+ addFeatureStateObserver(observer) {
+ // Unimplemented; never called from setup flow.
+ assertNotReached();
+ }
+
+ /** @override */
+ getEligibleHostDevices() {
+ const deviceNames = ['Pixel', 'Pixel XL', 'Nexus 5', 'Nexus 6P'];
+ let devices = [];
+ for (let i = 0; i < this.deviceCount; i++) {
+ const deviceName = deviceNames[i % 4];
+ devices.push({deviceName: deviceName, deviceId: deviceName + '--' + i});
+ }
+ return new Promise(function(resolve, reject) {
+ resolve({eligibleHostDevices: devices});
+ });
+ }
+
+ /** @override */
+ setHostDevice(deviceId) {
+ if (this.shouldSetHostSucceed) {
+ console.log(
+ 'setHostDevice(' + deviceId + ') called; simulating ' +
+ 'success.');
+ } else {
+ console.warn('setHostDevice() called; simulating failure.');
+ }
+ return new Promise((resolve, reject) => {
+ resolve({success: this.shouldSetHostSucceed});
+ });
+ }
+
+ /** @override */
+ removeHostDevice() {
+ // Unimplemented; never called from setup flow.
+ assertNotReached();
+ }
+
+ /** @override */
+ getHostStatus() {
+ return new Promise((resolve, reject) => {
+ reject('Unimplemented; never called from setup flow.');
+ });
+ }
+
+ /** @override */
+ setFeatureEnabledState() {
+ return new Promise((resolve, reject) => {
+ reject('Unimplemented; never called from setup flow.');
+ });
+ }
+
+ /** @override */
+ getFeatureStates() {
+ return new Promise((resolve, reject) => {
+ reject('Unimplemented; never called from setup flow.');
+ });
+ }
+
+ /** @override */
+ retrySetHostNow() {
+ return new Promise((resolve, reject) => {
+ reject('Unimplemented; never called from setup flow.');
+ });
+ }
+
+ /** @override */
+ triggerEventForDebugging(type) {
+ return new Promise((resolve, reject) => {
+ reject('Unimplemented; never called from setup flow.');
+ });
+ }
+}
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/icons.html b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/icons.html
new file mode 100644
index 00000000000..0232cf476e4
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/icons.html
@@ -0,0 +1,36 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-iconset-svg/iron-iconset-svg.html">
+
+<iron-iconset-svg name="multidevice-setup-icons-32" size="32">
+ <svg>
+ <defs>
+ <g id="google-g" fill="none" fill-rule="evenodd">
+ <path d="M30.42 16.83a16.66 16.66 0 0 0-.264-2.966H16.5v5.609h7.804c-.336 1.812-1.358 3.348-2.894 4.376v3.638h4.686c2.742-2.524 4.324-6.242 4.324-10.657z" fill="#4285F4"></path>
+ <path d="M16.5 31c3.915 0 7.197-1.298 9.596-3.513l-4.686-3.638c-1.298.87-2.96 1.384-4.91 1.384-3.777 0-6.973-2.55-8.113-5.978H3.542v3.757C5.928 27.75 10.832 31 16.5 31z" fill="#34A853"></path>
+ <path d="M8.387 19.255c-.29-.87-.455-1.8-.455-2.755 0-.956.165-1.885.455-2.755V9.988H3.542A14.494 14.494 0 0 0 2 16.5c0 2.34.56 4.554 1.542 6.512l4.845-3.757z" fill="#FBBC05"></path>
+ <path d="M16.5 7.767c2.129 0 4.04.732 5.543 2.168l4.159-4.158C23.69 3.437 20.408 2 16.5 2 10.832 2 5.928 5.25 3.542 9.988l4.845 3.757c1.14-3.427 4.336-5.978 8.113-5.978z" fill="#EA4335"></path>
+ <path d="M2 2h29v29H2z"></path>
+ </g>
+ <g id="error-icon" fill="none" fill-rule="evenodd" transform="translate(-4 -4)">
+ <path d="M20 4C11.168 4 4 11.168 4 20s7.168 16 16 16 16-7.168 16-16S28.832 4 20 4zm1.6 24h-3.2v-3.2h3.2V28zm0-6.4h-3.2V12h3.2v9.6z" fill="#D93025" fill-rule="nonzero"></path>
+ <path d="M.8.8h38.4v38.4H.8z"></path>
+ </g>
+ </defs>
+ </svg>
+</iron-iconset-svg>
+<iron-iconset-svg name="multidevice-setup-icons-20" size="20">
+ <svg>
+ <defs>
+ <g id="messages" fill="none" fill-rule="evenodd">
+ <path d="M16.3107503,3 L3.66666667,3 C2.75,3 2,3.75 2,4.66666667 L2,18.3161621 L5.33333333,15 L16.3107503,15 C17.227417,15 17.977417,14.2328288 17.977417,13.3161621 L17.977417,4.66666667 C17.977417,3.75 17.227417,3 16.3107503,3 Z M16,13 L4,13 L4,5 L16,5 L16,13 Z M6,8 L8,8 L8,10 L6,10 L6,8 Z M9,8 L11,8 L11,10 L9,10 L9,8 Z M12,8 L14,8 L14,10 L12,10 L12,8 Z" fill="#9AA0A6"></path>
+ </g>
+ <g id="downloads" fill="none" fill-rule="evenodd">
+ <path d="M2,13 L4,13 L4,16 L16,16 L16,13 L18,13 L18,16 C18,17.1 17.1,18 16,18 L4,18 C2.9,18 2,17.1 2,16 L2,13 Z M13.59,7.59 L11,10.17 L11,2 L9,2 L9,10.17 L6.41,7.59 L5,9 L10,14 L15,9 L13.59,7.59 Z" fill="#9AA0A6"></path>
+ </g>
+ <g id="features" fill="none" fill-rule="evenodd">
+ <path d="M5,5 L18,5 L18,3.5 L5.16080729,3.5 C4.24414063,3.5 3.49414062,4.23125 3.49414062,5.125 L3.49414062,14 L1,14 L1,17 L11,17 L11,14 L5,14 L5,5 Z M18.1666667,6.49829102 L13.3713582,6.49829102 C12.9130249,6.49829102 12.5,6.86391602 12.5,7.31079102 L12.5,16.171875 C12.5,16.61875 12.9130249,17 13.3713582,17 L18.1666667,17 C18.625,17 19,16.61875 19,16.171875 L19,7.31079102 C19,6.86391602 18.625,6.49829102 18.1666667,6.49829102 Z M17.5,14 L14,14 L14,8.5 L17.5,8.5 L17.5,14 Z" fill="#9AA0A6"></path>
+ </g>
+ </defs>
+ </svg>
+</iron-iconset-svg>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/mojo_api.html b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/mojo_api.html
new file mode 100644
index 00000000000..2bcb1bbc67d
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/mojo_api.html
@@ -0,0 +1,10 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<script src="chrome://resources/js/mojo_bindings.js"></script>
+<script src="chrome://resources/js/time.mojom.js"></script>
+<script src="chrome://resources/js/chromeos/device_sync.mojom.js"></script>
+<script src="chrome://resources/js/chromeos/multidevice_setup.mojom.js">
+</script>
+<script src="chrome://resources/js/chromeos/multidevice_setup_constants.mojom.js">
+</script>
+<script src="chrome://resources/cr_components/chromeos/multidevice_setup/mojo_api.js">
+</script>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/mojo_api.js b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/mojo_api.js
new file mode 100644
index 00000000000..d2aba99703f
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/mojo_api.js
@@ -0,0 +1,40 @@
+// 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.
+
+cr.define('multidevice_setup', function() {
+ /** @interface */
+ class MojoInterfaceProvider {
+ /**
+ * @return {!chromeos.multideviceSetup.mojom.MultiDeviceSetupImpl}
+ */
+ getInterfacePtr() {}
+ }
+
+ /** @implements {multidevice_setup.MojoInterfaceProvider} */
+ class MojoInterfaceProviderImpl {
+ constructor() {
+ /** @private {?chromeos.multideviceSetup.mojom.MultiDeviceSetupPtr} */
+ this.ptr_ = null;
+ }
+
+ /** @override */
+ getInterfacePtr() {
+ if (!this.ptr_) {
+ this.ptr_ = new chromeos.multideviceSetup.mojom.MultiDeviceSetupPtr();
+ Mojo.bindInterface(
+ chromeos.multideviceSetup.mojom.MultiDeviceSetup.name,
+ mojo.makeRequest(this.ptr_).handle);
+ }
+
+ return this.ptr_;
+ }
+ }
+
+ cr.addSingletonGetter(MojoInterfaceProviderImpl);
+
+ return {
+ MojoInterfaceProvider: MojoInterfaceProvider,
+ MojoInterfaceProviderImpl: MojoInterfaceProviderImpl,
+ };
+});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.html b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.html
new file mode 100644
index 00000000000..a75218ee419
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.html
@@ -0,0 +1,67 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/button_bar.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/fake_mojo_service.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/mojo_api.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup_delegate.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup_shared_css.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/password_page.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/setup_failed_page.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/setup_succeeded_page.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/start_setup_page.html">
+<link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-pages/iron-pages.html">
+
+<dom-module id="multidevice-setup">
+ <template>
+ <style include="multidevice-setup-shared">
+ :host {
+ @apply --layout-vertical;
+ box-sizing: border-box;
+ color: var(--google-grey-700);
+ font-size: 13px;
+ height: 640px;
+ line-height: 16px;
+ margin: auto;
+ padding: 60px 32px 32px 32px;
+ width: 768px;
+ }
+
+ iron-pages {
+ padding: 0 32px;
+ }
+ </style>
+ <iron-pages attr-for-selected="is"
+ selected="[[visiblePageName_]]"
+ selected-item="{{visiblePage_}}">
+ <template is="dom-if" if="[[shouldPasswordPageBeIncluded_(delegate)]]"
+ restamp>
+ <password-page auth-token="{{authToken_}}"
+ forward-button-disabled="{{passwordPageForwardButtonDisabled_}}"
+ password-field-valid="{{passwordFieldValid}}"
+ on-user-submitted-password="onUserSubmittedPassword_">
+ </password-page>
+ </template>
+ <setup-failed-page></setup-failed-page>
+ <template is="dom-if"
+ if="[[shouldSetupSucceededPageBeIncluded_(delegate)]]" restamp>
+ <setup-succeeded-page></setup-succeeded-page>
+ </template>
+ <start-setup-page devices="[[devices_]]"
+ selected-device-id="{{selectedDeviceId_}}"
+ delegate="[[delegate]]">
+ </start-setup-page>
+ </iron-pages>
+ <div class="flex"></div>
+ <button-bar forward-button-hidden="[[!forwardButtonText]]"
+ backward-button-hidden="[[!backwardButtonText]]"
+ cancel-button-hidden="[[!cancelButtonText]]">
+ <slot name="backward-button" slot="backward-button"></slot>
+ <slot name="cancel-button" slot="cancel-button"></slot>
+ <slot name="forward-button" slot="forward-button"></slot>
+ </button-bar>
+ </template>
+ <script src="chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup.js">
+ </script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.js b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.js
new file mode 100644
index 00000000000..3dc0dd457d8
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup.js
@@ -0,0 +1,312 @@
+// 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.
+
+cr.exportPath('multidevice_setup');
+
+/** @enum {string} */
+multidevice_setup.PageName = {
+ FAILURE: 'setup-failed-page',
+ PASSWORD: 'password-page',
+ SUCCESS: 'setup-succeeded-page',
+ START: 'start-setup-page',
+};
+
+cr.define('multidevice_setup', function() {
+ const PageName = multidevice_setup.PageName;
+
+ const MultiDeviceSetup = Polymer({
+ is: 'multidevice-setup',
+
+ behaviors: [WebUIListenerBehavior],
+
+ properties: {
+ /**
+ * Delegate object which performs differently in OOBE vs. non-OOBE mode.
+ * @type {!multidevice_setup.MultiDeviceSetupDelegate}
+ */
+ delegate: Object,
+
+ /**
+ * Text to be shown on the forward navigation button.
+ * @type {string|undefined}
+ */
+ forwardButtonText: {
+ type: String,
+ computed: 'getForwardButtonText_(visiblePage_)',
+ notify: true,
+ },
+
+ /** Whether the forward button should be disabled. */
+ forwardButtonDisabled: {
+ type: Boolean,
+ computed: 'shouldForwardButtonBeDisabled_(' +
+ 'passwordPageForwardButtonDisabled_, visiblePageName_)',
+ notify: true
+ },
+
+ /**
+ * Text to be shown on the cancel button.
+ * @type {string|undefined}
+ */
+ cancelButtonText: {
+ type: String,
+ computed: 'getCancelButtonText_(visiblePage_)',
+ notify: true,
+ },
+
+ /**
+ * Text to be shown on the backward navigation button.
+ * @type {string|undefined}
+ */
+ backwardButtonText: {
+ type: String,
+ computed: 'getBackwardButtonText_(visiblePage_)',
+ notify: true,
+ },
+
+ /**
+ * Element name of the currently visible page.
+ *
+ * @private {!multidevice_setup.PageName}
+ */
+ visiblePageName_: {
+ type: String,
+ value: PageName.START,
+ notify: true, // For testing purposes only.
+ },
+
+ /**
+ * DOM Element corresponding to the visible page.
+ *
+ * @private {!PasswordPageElement|!StartSetupPageElement|
+ * !SetupSucceededPageElement|!SetupFailedPageElement}
+ */
+ visiblePage_: Object,
+
+ /**
+ * Authentication token, which is generated by the password page.
+ * @private {string}
+ */
+ authToken_: {
+ type: String,
+ },
+
+ /**
+ * Array of objects representing all potential MultiDevice hosts.
+ *
+ * @private {!Array<!chromeos.deviceSync.mojom.RemoteDevice>}
+ */
+ devices_: Array,
+
+ /**
+ * Unique identifier for the currently selected host device.
+ *
+ * Undefined if the no list of potential hosts has been received from mojo
+ * service.
+ *
+ * @private {string|undefined}
+ */
+ selectedDeviceId_: String,
+
+ /**
+ * Whether the password page reports that the forward button should be
+ * disabled. This field is only relevant when the password page is
+ * visible.
+ * @private {boolean}
+ */
+ passwordPageForwardButtonDisabled_: Boolean,
+
+ /**
+ * Provider of an interface to the MultiDeviceSetup Mojo service.
+ * @private {!multidevice_setup.MojoInterfaceProvider}
+ */
+ mojoInterfaceProvider_: Object
+ },
+
+ listeners: {
+ 'backward-navigation-requested': 'onBackwardNavigationRequested_',
+ 'cancel-requested': 'onCancelRequested_',
+ 'forward-navigation-requested': 'onForwardNavigationRequested_',
+ },
+
+ /** @override */
+ created: function() {
+ this.mojoInterfaceProvider_ =
+ multidevice_setup.MojoInterfaceProviderImpl.getInstance();
+ },
+
+ /** @override */
+ ready: function() {
+ this.addWebUIListener(
+ 'multidevice_setup.initializeSetupFlow',
+ this.initializeSetupFlow.bind(this));
+ },
+
+ initializeSetupFlow: function() {
+ this.mojoInterfaceProvider_.getInterfacePtr()
+ .getEligibleHostDevices()
+ .then((responseParams) => {
+ if (responseParams.eligibleHostDevices.length == 0) {
+ console.warn('Potential host list is empty.');
+ return;
+ }
+
+ this.devices_ = responseParams.eligibleHostDevices;
+ })
+ .catch((error) => {
+ console.warn('Mojo service failure: ' + error);
+ });
+ },
+
+ /** @private */
+ onCancelRequested_: function() {
+ this.exitSetupFlow_();
+ },
+
+ /** @private */
+ onBackwardNavigationRequested_: function() {
+ // The back button is only visible on the password page.
+ assert(this.visiblePageName_ == PageName.PASSWORD);
+
+ this.$$('password-page').clearPasswordTextInput();
+ this.visiblePageName_ = PageName.START;
+ },
+
+ /** @private */
+ onForwardNavigationRequested_: function() {
+ if (this.forwardButtonDisabled)
+ return;
+
+ this.visiblePage_.getCanNavigateToNextPage().then((canNavigate) => {
+ if (!canNavigate)
+ return;
+ this.navigateForward_();
+ });
+ },
+
+ /** @private */
+ navigateForward_: function() {
+ switch (this.visiblePageName_) {
+ case PageName.FAILURE:
+ this.visiblePageName_ = PageName.START;
+ return;
+ case PageName.PASSWORD:
+ this.$$('password-page').clearPasswordTextInput();
+ this.setHostDevice_();
+ return;
+ case PageName.SUCCESS:
+ this.exitSetupFlow_();
+ return;
+ case PageName.START:
+ if (this.delegate.isPasswordRequiredToSetHost())
+ this.visiblePageName_ = PageName.PASSWORD;
+ else
+ this.setHostDevice_();
+ return;
+ }
+ },
+
+ /** @private */
+ setHostDevice_: function() {
+ // An authentication token must be set if a password is required.
+ assert(this.delegate.isPasswordRequiredToSetHost() == !!this.authToken_);
+
+ let deviceId = /** @type {string} */ (this.selectedDeviceId_);
+ this.delegate.setHostDevice(deviceId, this.authToken_)
+ .then((responseParams) => {
+ if (!responseParams.success) {
+ console.warn('Failure setting host with device ID: ' + deviceId);
+ return;
+ }
+
+ if (this.delegate.shouldExitSetupFlowAfterSettingHost()) {
+ this.exitSetupFlow_();
+ return;
+ }
+
+ this.visiblePageName_ = PageName.SUCCESS;
+ this.fire('forward-button-focus-requested');
+ })
+ .catch((error) => {
+ console.warn('Mojo service failure: ' + error);
+ });
+ },
+
+ /** @private */
+ onUserSubmittedPassword_: function() {
+ this.onForwardNavigationRequested_();
+ },
+
+ /**
+ * @return {string|undefined} The forward button text, which is undefined
+ * if no button should be displayed.
+ * @private
+ */
+ getForwardButtonText_: function() {
+ if (!this.visiblePage_)
+ return undefined;
+ return this.visiblePage_.forwardButtonText;
+ },
+
+ /**
+ * @return {boolean} Whether the forward button should be disabled.
+ * @private
+ */
+ shouldForwardButtonBeDisabled_: function() {
+ return (this.visiblePageName_ == PageName.PASSWORD) &&
+ this.passwordPageForwardButtonDisabled_;
+ },
+
+ /**
+ * @return {string|undefined} The cancel button text, which is undefined
+ * if no button should be displayed.
+ * @private
+ */
+ getCancelButtonText_: function() {
+ if (!this.visiblePage_)
+ return undefined;
+ return this.visiblePage_.cancelButtonText;
+ },
+
+ /**
+ * @return {string|undefined} The backward button text, which is undefined
+ * if no button should be displayed.
+ * @private
+ */
+ getBackwardButtonText_: function() {
+ if (!this.visiblePage_)
+ return undefined;
+ return this.visiblePage_.backwardButtonText;
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ shouldPasswordPageBeIncluded_: function() {
+ return this.delegate.isPasswordRequiredToSetHost();
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ shouldSetupSucceededPageBeIncluded_: function() {
+ return !this.delegate.shouldExitSetupFlowAfterSettingHost();
+ },
+
+ /**
+ * Notifies observers that the setup flow has completed.
+ *
+ * @private
+ */
+ exitSetupFlow_: function() {
+ this.fire('setup-exited');
+ },
+ });
+
+ return {
+ MultiDeviceSetup: MultiDeviceSetup,
+ };
+});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_browser_proxy.html b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_browser_proxy.html
new file mode 100644
index 00000000000..82f8d961c25
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_browser_proxy.html
@@ -0,0 +1,3 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<script src="chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup_browser_proxy.js">
+</script>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_browser_proxy.js b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_browser_proxy.js
new file mode 100644
index 00000000000..be88d746277
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_browser_proxy.js
@@ -0,0 +1,41 @@
+// 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.
+
+cr.define('multidevice_setup', function() {
+ /** @interface */
+ class BrowserProxy {
+ /**
+ * Requests profile information; namely, a dictionary containing the user's
+ * e-mail address and profile photo.
+ * @return {!Promise<{profilePhotoUrl: string, email: string}>}
+ */
+ getProfileInfo() {}
+
+ /**
+ * Opens settings to the MultiDevice individual feature settings subpage.
+ * (a.k.a. Connected Devices).
+ */
+ openMultiDeviceSettings() {}
+ }
+
+ /** @implements {multidevice_setup.BrowserProxy} */
+ class BrowserProxyImpl {
+ /** @override */
+ getProfileInfo() {
+ return cr.sendWithPromise('getProfileInfo');
+ }
+
+ /** @override */
+ openMultiDeviceSettings() {
+ chrome.send('openMultiDeviceSettings');
+ }
+ }
+
+ cr.addSingletonGetter(BrowserProxyImpl);
+
+ return {
+ BrowserProxy: BrowserProxy,
+ BrowserProxyImpl: BrowserProxyImpl,
+ };
+});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_delegate.html b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_delegate.html
new file mode 100644
index 00000000000..46ce0b9a518
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_delegate.html
@@ -0,0 +1,4 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<script src="chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup_delegate.js">
+</script>
+
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_delegate.js b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_delegate.js
new file mode 100644
index 00000000000..8526f38216b
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_delegate.js
@@ -0,0 +1,33 @@
+// 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.
+
+cr.define('multidevice_setup', function() {
+ /**
+ * Interface which provides the ability to set the host device and perform
+ * related logic.
+ * @interface
+ */
+ class MultiDeviceSetupDelegate {
+ /** @return {boolean} */
+ isPasswordRequiredToSetHost() {}
+
+ /**
+ * @param {string} hostDeviceId The ID of the host to set.
+ * @param {string=} opt_authToken An auth token to authenticate the request;
+ * only necessary if isPasswordRequiredToSetHost() returns true.
+ * @return {!Promise<{success: boolean}>}
+ */
+ setHostDevice(hostDeviceId, opt_authToken) {}
+
+ /** @return {boolean} */
+ shouldExitSetupFlowAfterSettingHost() {}
+
+ /** @return {string} */
+ getStartSetupCancelButtonTextId() {}
+ }
+
+ return {
+ MultiDeviceSetupDelegate: MultiDeviceSetupDelegate,
+ };
+});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_shared_css.html b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_shared_css.html
new file mode 100644
index 00000000000..c9403122d45
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/multidevice_setup_shared_css.html
@@ -0,0 +1,19 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
+<link rel="import" href="chrome://resources/html/md_select_css.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout.html">
+
+<dom-module id="multidevice-setup-shared">
+ <template>
+ <style include="iron-flex paper-button-style cr-shared-style md-select">
+ a {
+ color: var(--google-blue-600);
+ text-decoration: none;
+ }
+ </style>
+ </template>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/password_page.html b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/password_page.html
new file mode 100644
index 00000000000..b5c52c0f573
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/password_page.html
@@ -0,0 +1,51 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup_shared_css.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/ui_page.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/ui_page_container_behavior.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_input/cr_input.html">
+<link rel="import" href="chrome://resources/html/cr.html">
+
+<dom-module id="password-page">
+ <template>
+ <style include="multidevice-setup-shared">
+ #user-info-container {
+ @apply --layout-horizontal;
+ align-items: center;
+ color: var(--paper-grey-600);
+ }
+
+ #profile-photo {
+ border-radius: 50%;
+ height: 20px;
+ margin-right: 8px;
+ width: 20px;
+ }
+
+ #passwordInput {
+ height: 32px;
+ margin-top: 64px;
+ width: 560px;
+ }
+ </style>
+ <ui-page header-text="[[headerText]]" icon-name="google-g">
+ <div id="content-container" slot="additional-content">
+ <div id="user-info-container">
+ <img id="profile-photo" src="[[profilePhotoUrl_]]"></img>
+ <span id="email">[[email_]]</span>
+ </div>
+ <cr-input id="passwordInput" type="password"
+ placeholder="[[i18n('enterPassword')]]"
+ invalid="[[passwordInvalid_]]"
+ error-message="[[i18n('wrongPassword')]]"
+ value="{{inputValue_}}"
+ aria-disabled="false"
+ on-keypress="onInputKeypress_"
+ autofocus>
+ </cr-input>
+ </div>
+ </ui-page>
+ </template>
+ <script src="chrome://resources/cr_components/chromeos/multidevice_setup/password_page.js">
+ </script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/password_page.js b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/password_page.js
new file mode 100644
index 00000000000..ba2abe0bf6f
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/password_page.js
@@ -0,0 +1,167 @@
+// 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.
+
+Polymer({
+ is: 'password-page',
+
+ behaviors: [
+ UiPageContainerBehavior,
+ ],
+
+ properties: {
+ /**
+ * Whether forward button should be disabled. In this context, the forward
+ * button should be disabled if the user has not entered a password or if
+ * the user has submitted an incorrect password and has not yet edited it.
+ * @type {boolean}
+ */
+ forwardButtonDisabled: {
+ type: Boolean,
+ computed: 'shouldForwardButtonBeDisabled_(' +
+ 'inputValue_, passwordInvalid_, waitingForPasswordCheck_)',
+ notify: true,
+ },
+
+ /** Overridden from UiPageContainerBehavior. */
+ forwardButtonTextId: {
+ type: String,
+ value: 'done',
+ },
+
+ /** Overridden from UiPageContainerBehavior. */
+ cancelButtonTextId: {
+ type: String,
+ value: 'cancel',
+ },
+
+ /** Overridden from UiPageContainerBehavior. */
+ backwardButtonTextId: {
+ type: String,
+ value: 'back',
+ },
+
+ /** Overridden from UiPageContainerBehavior. */
+ headerId: {
+ type: String,
+ value: 'passwordPageHeader',
+ },
+
+ /**
+ * Authentication token; retrieved using the quickUnlockPrivate API.
+ * @type {string}
+ */
+ authToken: {
+ type: String,
+ value: '',
+ notify: true,
+ },
+
+ /** @private {string} */
+ profilePhotoUrl_: {
+ type: String,
+ value: '',
+ },
+
+ /** @private {string} */
+ email_: {
+ type: String,
+ value: '',
+ },
+
+ /** @private {!QuickUnlockPrivate} */
+ quickUnlockPrivate_: {
+ type: Object,
+ value: chrome.quickUnlockPrivate,
+ },
+
+ /** @private {string} */
+ inputValue_: {
+ type: String,
+ value: '',
+ observer: 'onInputValueChange_',
+ },
+
+ /** @private {boolean} */
+ passwordInvalid_: {
+ type: Boolean,
+ value: false,
+ },
+
+ /** @private {boolean} */
+ waitingForPasswordCheck_: {
+ type: Boolean,
+ value: false,
+ },
+ },
+
+ /** @private {?multidevice_setup.BrowserProxy} */
+ browserProxy_: null,
+
+ clearPasswordTextInput: function() {
+ this.$.passwordInput.value = '';
+ },
+
+ /** @override */
+ created: function() {
+ this.browserProxy_ = multidevice_setup.BrowserProxyImpl.getInstance();
+ },
+
+ /** @override */
+ attached: function() {
+ this.browserProxy_.getProfileInfo().then((profileInfo) => {
+ this.profilePhotoUrl_ = profileInfo.profilePhotoUrl;
+ this.email_ = profileInfo.email;
+ });
+ },
+
+ /** Overridden from UiPageContainerBehavior. */
+ getCanNavigateToNextPage: function() {
+ return new Promise((resolve) => {
+ if (this.waitingForPasswordCheck_) {
+ resolve(false /* canNavigate */);
+ return;
+ }
+ this.waitingForPasswordCheck_ = true;
+ this.quickUnlockPrivate_.getAuthToken(this.inputValue_, (tokenInfo) => {
+ this.waitingForPasswordCheck_ = false;
+ if (chrome.runtime.lastError) {
+ this.passwordInvalid_ = true;
+ // Select the password text if the user entered an incorrect password.
+ this.$.passwordInput.select();
+ resolve(false /* canNavigate */);
+ return;
+ }
+ this.authToken = tokenInfo.token;
+ this.passwordInvalid_ = false;
+ resolve(true /* canNavigate */);
+ });
+ });
+ },
+
+ /** @private */
+ onInputValueChange_: function() {
+ this.passwordInvalid_ = false;
+ },
+
+ /**
+ * @param {!Event} e
+ * @private
+ */
+ onInputKeypress_: function(e) {
+ // We are only listening for the user trying to enter their password.
+ if (e.key != 'Enter')
+ return;
+
+ this.fire('user-submitted-password');
+ },
+
+ /**
+ * @return {boolean} Whether the forward button should be disabled.
+ * @private
+ */
+ shouldForwardButtonBeDisabled_: function() {
+ return this.passwordInvalid_ || !this.inputValue_ ||
+ this.waitingForPasswordCheck_;
+ },
+});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_failed_page.html b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_failed_page.html
new file mode 100644
index 00000000000..181687dffd7
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_failed_page.html
@@ -0,0 +1,18 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/ui_page.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/ui_page_container_behavior.html">
+<link rel="import" href="chrome://resources/html/cr.html">
+
+<dom-module id="setup-failed-page">
+ <template>
+ <ui-page header-text="[[headerText]]" icon-name="error-icon">
+ <span slot="message" inner-h-t-m-l="[[messageHtml]]"></span>
+ <div slot="additional-content">
+ This is empty... (PlAcEhOlDeR tExT!!)
+ </div>
+ </ui-page>
+ </template>
+ <script src="chrome://resources/cr_components/chromeos/multidevice_setup/setup_failed_page.js">
+ </script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_failed_page.js b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_failed_page.js
new file mode 100644
index 00000000000..36f2d4ae117
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_failed_page.js
@@ -0,0 +1,43 @@
+// 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.
+
+Polymer({
+ is: 'setup-failed-page',
+
+ properties: {
+ /** Overridden from UiPageContainerBehavior. */
+ forwardButtonTextId: {
+ type: String,
+ value: 'tryAgain',
+ },
+
+ /** Overridden from UiPageContainerBehavior. */
+ cancelButtonTextId: {
+ type: String,
+ value: 'cancel',
+ },
+
+ /** Overridden from UiPageContainerBehavior. */
+ backwardButtonTextId: {
+ type: String,
+ value: 'back',
+ },
+
+ /** Overridden from UiPageContainerBehavior. */
+ headerId: {
+ type: String,
+ value: 'setupFailedPageHeader',
+ },
+
+ /** Overridden from UiPageContainerBehavior. */
+ messageId: {
+ type: String,
+ value: 'setupFailedPageMessage',
+ },
+ },
+
+ behaviors: [
+ UiPageContainerBehavior,
+ ],
+});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_succeeded_icon_1x.png b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_succeeded_icon_1x.png
new file mode 100644
index 00000000000..03074bd5735
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_succeeded_icon_1x.png
Binary files differ
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_succeeded_icon_2x.png b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_succeeded_icon_2x.png
new file mode 100644
index 00000000000..271b0484e3e
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_succeeded_icon_2x.png
Binary files differ
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_succeeded_page.html b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_succeeded_page.html
new file mode 100644
index 00000000000..a899610a5d0
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_succeeded_page.html
@@ -0,0 +1,35 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup_browser_proxy.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup_shared_css.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/ui_page.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/ui_page_container_behavior.html">
+<link rel="import" href="chrome://resources/html/cr.html">
+
+<dom-module id="setup-succeeded-page">
+ <template>
+ <style include="multidevice-setup-shared">
+ #page-icon-container {
+ @apply --layout-horizontal;
+ @apply --layout-center-justified;
+ }
+
+ #page-icon {
+ background-image: -webkit-image-set(
+ url(setup_succeeded_icon_1x.png) 1x,
+ url(setup_succeeded_icon_2x.png) 2x);
+ height: 156px;
+ margin-top: 64px;
+ width: 416px;
+ }
+ </style>
+ <ui-page header-text="[[headerText]]" icon-name="google-g">
+ <span slot="message" inner-h-t-m-l="[[messageHtml]]"></span>
+ <div id="page-icon-container" slot="additional-content">
+ <div id="page-icon"></div>
+ </div>
+ </ui-page>
+ </template>
+ <script src="chrome://resources/cr_components/chromeos/multidevice_setup/setup_succeeded_page.js">
+ </script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_succeeded_page.js b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_succeeded_page.js
new file mode 100644
index 00000000000..e9c4eac1bc1
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/setup_succeeded_page.js
@@ -0,0 +1,59 @@
+// 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.
+
+cr.exportPath('multidevice_setup');
+
+Polymer({
+ is: 'setup-succeeded-page',
+
+ properties: {
+ /** Overridden from UiPageContainerBehavior. */
+ forwardButtonTextId: {
+ type: String,
+ value: 'done',
+ },
+
+ /** Overridden from UiPageContainerBehavior. */
+ headerId: {
+ type: String,
+ value: 'setupSucceededPageHeader',
+ },
+
+ /** Overridden from UiPageContainerBehavior. */
+ messageId: {
+ type: String,
+ value: 'setupSucceededPageMessage',
+ },
+ },
+
+ behaviors: [
+ UiPageContainerBehavior,
+ ],
+
+ /** @private {?multidevice_setup.BrowserProxy} */
+ browserProxy_: null,
+
+ /** @override */
+ created: function() {
+ this.browserProxy_ = multidevice_setup.BrowserProxyImpl.getInstance();
+ },
+
+ /** @private */
+ openSettings_: function() {
+ this.browserProxy_.openMultiDeviceSettings();
+ },
+
+ /** @private */
+ onSettingsLinkClicked_: function() {
+ this.openSettings_();
+ this.fire('setup-exited');
+ },
+
+ /** @override */
+ ready: function() {
+ let linkElement = this.$$('#settings-link');
+ linkElement.setAttribute('href', '#');
+ linkElement.addEventListener('click', () => this.onSettingsLinkClicked_());
+ },
+});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_icon_1x.png b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_icon_1x.png
new file mode 100644
index 00000000000..b6a3a196cb8
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_icon_1x.png
Binary files differ
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_icon_2x.png b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_icon_2x.png
new file mode 100644
index 00000000000..c7234e8f191
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_icon_2x.png
Binary files differ
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.html b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.html
new file mode 100644
index 00000000000..a410816bbf7
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.html
@@ -0,0 +1,135 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/icons.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup_shared_css.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/ui_page.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/ui_page_container_behavior.html">
+<link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/html/web_ui_listener_behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
+
+<dom-module id="start-setup-page">
+ <template>
+ <style include="multidevice-setup-shared">
+ #selector-and-details-container {
+ @apply --layout-horizontal;
+ margin-top: 48px;
+ min-height: 246px;
+ }
+
+ #singleDeviceName {
+ color: var(--google-grey-900);
+ margin-top: 16px;
+ }
+
+ #deviceDropdown {
+ margin-top: 16px;
+ }
+
+ #page-icon-container {
+ @apply --layout-horizontal;
+ @apply --layout-center-justified;
+ }
+
+ #page-icon {
+ background-image: -webkit-image-set(url(start_setup_icon_1x.png) 1x,
+ url(start_setup_icon_2x.png) 2x);
+ height: 116px;
+ margin-top: 10px;
+ width: 320px;
+ }
+
+ #deviceSelectionContainer {
+ color: var(--paper-grey-600);
+ }
+
+ #feature-details-container {
+ @apply --layout-vertical;
+ @apply --layout-center-justified;
+ border-left: 1px solid rgb(218, 220, 224);
+ padding-left: 24px;
+ }
+
+ #feature-details-container-header {
+ margin-bottom: 18px;
+ }
+
+ .feature-detail {
+ @apply --layout-horizontal;
+ @apply --layout-center;
+ box-sizing: border-box;
+ min-height: 64px;
+ padding: 10px 0;
+ }
+
+ .feature-detail iron-icon {
+ --iron-icon-height: 20px;
+ --iron-icon-width: 20px;
+ min-width: 20px;
+ }
+
+ .feature-detail span {
+ margin-left: 8px;
+ }
+
+ #footnote {
+ color: var(--paper-grey-600);
+ margin-top: 12px;
+ }
+ </style>
+
+ <ui-page header-text="[[headerText]]" icon-name="google-g">
+ <span slot="message" id="multidevice-summary-message" inner-h-t-m-l="[[messageHtml]]"></span>
+ <div slot="additional-content">
+ <div id="selector-and-details-container">
+ <div id="deviceSelectionContainer" class="flex">
+ [[getDeviceSelectionHeader_(devices)]]
+ <div class="flex"></div>
+ <div id="singleDeviceName"
+ hidden$="[[!doesDeviceListHaveOneElement_(devices)]]">
+ [[getFirstDeviceNameInList_(devices)]]
+ </div>
+ <div hidden$="[[!doesDeviceListHaveMultipleElements_(devices)]]">
+ <select id="deviceDropdown"
+ class="md-select"
+ on-change="onDeviceDropdownSelectionChanged_">
+ <template is="dom-repeat" items="[[devices]]">
+ <option value$="[[item.deviceId]]">
+ [[item.deviceName]]
+ </option>
+ </template>
+ </select>
+ </div>
+ <div id="page-icon-container">
+ <div id="page-icon"></div>
+ </div>
+ </div>
+ <div id="feature-details-container" class="flex">
+ <div id="feature-details-container-header">
+ [[i18n('startSetupPageFeatureListHeader')]]
+ </div>
+ <div class="feature-detail">
+ <iron-icon icon="multidevice-setup-icons-20:messages"></iron-icon>
+ <span id="awm-summary-message" inner-h-t-m-l="
+ [[i18nAdvanced('startSetupPageFeatureListAwm')]]">
+ </span>
+ </div>
+ <div class="feature-detail">
+ <iron-icon icon="multidevice-setup-icons-20:downloads">
+ </iron-icon>
+ <span>[[i18n('startSetupPageFeatureListInstallApps')]]</span>
+ </div>
+ <div class="feature-detail">
+ <iron-icon icon="multidevice-setup-icons-20:features"></iron-icon>
+ <span>[[i18n('startSetupPageFeatureListAddFeatures')]]</span>
+ </div>
+ </div>
+ </div>
+ <div id="footnote">[[i18n('startSetupPageFootnote')]]</div>
+ </div>
+ </ui-page>
+ </template>
+ <script src="chrome://resources/cr_components/chromeos/multidevice_setup/start_setup_page.js">
+ </script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.js b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.js
new file mode 100644
index 00000000000..d9f6db488e7
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/start_setup_page.js
@@ -0,0 +1,155 @@
+// 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.
+
+Polymer({
+ is: 'start-setup-page',
+
+ properties: {
+ /** Overridden from UiPageContainerBehavior. */
+ forwardButtonTextId: {
+ type: String,
+ value: 'accept',
+ },
+
+ /** Overridden from UiPageContainerBehavior. */
+ cancelButtonTextId: {
+ type: String,
+ computed: 'getCancelButtonTextId_(delegate)',
+ },
+
+ /** Overridden from UiPageContainerBehavior. */
+ headerId: {
+ type: String,
+ value: 'startSetupPageHeader',
+ },
+
+ /** Overridden from UiPageContainerBehavior. */
+ messageId: {
+ type: String,
+ value: 'startSetupPageMessage',
+ },
+
+ /**
+ * Array of objects representing all potential MultiDevice hosts.
+ *
+ * @type {!Array<!chromeos.deviceSync.mojom.RemoteDevice>}
+ */
+ devices: {
+ type: Array,
+ value: () => [],
+ observer: 'devicesChanged_',
+ },
+
+ /**
+ * Unique identifier for the currently selected host device.
+ *
+ * Undefined if the no list of potential hosts has been received from mojo
+ * service.
+ *
+ * @type {string|undefined}
+ */
+ selectedDeviceId: {
+ type: String,
+ notify: true,
+ },
+
+ /**
+ * Delegate object which performs differently in OOBE vs. non-OOBE mode.
+ * @type {!multidevice_setup.MultiDeviceSetupDelegate}
+ */
+ delegate: Object,
+ },
+
+ behaviors: [
+ UiPageContainerBehavior,
+ I18nBehavior,
+ WebUIListenerBehavior,
+ ],
+
+ /** @override */
+ attached: function() {
+ this.addWebUIListener(
+ 'multidevice_setup.initializeSetupFlow',
+ this.initializeSetupFlow_.bind(this));
+ },
+
+ /** @private */
+ initializeSetupFlow_: function() {
+ // The "Learn More" links are inside a grdp string, so we cannot actually
+ // add an onclick handler directly to the html. Instead, grab the two and
+ // manaully add onclick handlers.
+ let helpArticleLinks = [
+ this.$$('#multidevice-summary-message a'),
+ this.$$('#awm-summary-message a')
+ ];
+ for (let i = 0; i < helpArticleLinks.length; i++) {
+ helpArticleLinks[i].onclick = this.fire.bind(
+ this, 'open-learn-more-webview-requested', helpArticleLinks[i].href);
+ }
+ },
+
+ /**
+ * @param {!multidevice_setup.MultiDeviceSetupDelegate} delegate
+ * @return {string} The cancel button text ID, dependent on OOBE vs. non-OOBE.
+ * @private
+ */
+ getCancelButtonTextId_: function(delegate) {
+ return this.delegate.getStartSetupCancelButtonTextId();
+ },
+
+ /**
+ * @param {!Array<!chromeos.deviceSync.mojom.RemoteDevice>} devices
+ * @return {string} Label for devices selection content.
+ * @private
+ */
+ getDeviceSelectionHeader_(devices) {
+ switch (devices.length) {
+ case 0:
+ return '';
+ case 1:
+ return this.i18n('startSetupPageSingleDeviceHeader');
+ default:
+ return this.i18n('startSetupPageMultipleDeviceHeader');
+ }
+ },
+
+ /**
+ * @param {!Array<!chromeos.deviceSync.mojom.RemoteDevice>} devices
+ * @return {boolean} True if there are more than one potential host devices.
+ * @private
+ */
+ doesDeviceListHaveMultipleElements_: function(devices) {
+ return devices.length > 1;
+ },
+
+ /**
+ * @param {!Array<!chromeos.deviceSync.mojom.RemoteDevice>} devices
+ * @return {boolean} True if there is exactly one potential host device.
+ * @private
+ */
+ doesDeviceListHaveOneElement_: function(devices) {
+ return devices.length == 1;
+ },
+
+ /**
+ * @param {!Array<!chromeos.deviceSync.mojom.RemoteDevice>} devices
+ * @return {string} Name of the first device in device list if there are any.
+ * Returns an empty string otherwise.
+ * @private
+ */
+ getFirstDeviceNameInList_: function(devices) {
+ return devices[0] ? this.devices[0].deviceName : '';
+ },
+
+ /** @private */
+ devicesChanged_: function() {
+ if (this.devices.length > 0)
+ this.selectedDeviceId = this.devices[0].deviceId;
+ },
+
+ /** @private */
+ onDeviceDropdownSelectionChanged_: function() {
+ this.selectedDeviceId = this.$.deviceDropdown.value;
+ },
+});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/ui_page.html b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/ui_page.html
new file mode 100644
index 00000000000..289e08644b8
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/ui_page.html
@@ -0,0 +1,42 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-icon/iron-icon.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/icons.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/multidevice_setup/multidevice_setup_shared_css.html">
+
+<dom-module id="ui-page">
+ <template>
+ <style include="multidevice-setup-shared">
+ iron-icon {
+ --iron-icon-width: 32px;
+ --iron-icon-height: 32px;
+ }
+
+ h1 {
+ color: var(--google-grey-900);
+ font-family: 'Google Sans';
+ font-size: 28px;
+ font-weight: normal;
+ line-height: 28px;
+ margin: 0;
+ padding-top: 36px;
+ }
+
+ #message-container {
+ box-sizing: border-box;
+ min-height: 32px;
+ padding-top: 16px;
+ }
+ </style>
+ <iron-icon icon="[[computeIconIdentifier_(iconName)]]"></iron-icon>
+ <h1>[[headerText]]</h1>
+ <div id="message-container">
+ <slot name="message"></slot>
+ </div>
+ <div id="additional-content-container">
+ <slot name="additional-content"></slot>
+ </div>
+ </template>
+ <script src="chrome://resources/cr_components/chromeos/multidevice_setup/ui_page.js">
+ </script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/ui_page.js b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/ui_page.js
new file mode 100644
index 00000000000..d29f7722d10
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/ui_page.js
@@ -0,0 +1,34 @@
+// 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.
+
+/**
+ * An element that encapsulates the structure common to all pages in the WebUI.
+ */
+Polymer({
+ is: 'ui-page',
+
+ properties: {
+ /**
+ * Main heading for the page.
+ *
+ * @type {string}
+ */
+ headerText: String,
+
+ /**
+ * Name of icon within icon set.
+ *
+ * @type {string}
+ */
+ iconName: String,
+ },
+
+ /**
+ * @return {string}
+ * @private
+ */
+ computeIconIdentifier_: function() {
+ return 'multidevice-setup-icons-32:' + this.iconName;
+ },
+});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/ui_page_container_behavior.html b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/ui_page_container_behavior.html
new file mode 100644
index 00000000000..501cc374471
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/ui_page_container_behavior.html
@@ -0,0 +1,5 @@
+<link rel="import" href="chrome://resources/html/cr.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+
+<script src="chrome://resources/cr_components/chromeos/multidevice_setup/ui_page_container_behavior.js">
+</script>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/ui_page_container_behavior.js b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/ui_page_container_behavior.js
new file mode 100644
index 00000000000..e9f16b9ee89
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/multidevice_setup/ui_page_container_behavior.js
@@ -0,0 +1,141 @@
+// 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.
+
+/** @polymerBehavior */
+const UiPageContainerBehaviorImpl = {
+ properties: {
+ /**
+ * ID for forward button label, which must be translated for display.
+ *
+ * Undefined if the visible page has no forward-navigation button.
+ *
+ * @type {string|undefined}
+ */
+ forwardButtonTextId: String,
+
+ /**
+ * ID for cancel button label, which must be translated for display.
+ *
+ * Undefined if the visible page has no cancel button.
+ *
+ * @type {string|undefined}
+ */
+ cancelButtonTextId: String,
+
+ /**
+ * ID for backward button label, which must be translated for display.
+ *
+ * Undefined if the visible page has no backward-navigation button.
+ *
+ * @type {string|undefined}
+ */
+ backwardButtonTextId: String,
+
+ /**
+ * ID for text of main UI Page heading.
+ *
+ * @type {string}
+ */
+ headerId: String,
+
+ /**
+ * ID for text of main UI Page message body.
+ *
+ * @type {string}
+ */
+ messageId: String,
+
+ /**
+ * Translated text to display on the forward-naviation button.
+ *
+ * Undefined if the visible page has no forward-navigation button.
+ *
+ * @type {string|undefined}
+ */
+ forwardButtonText: {
+ type: String,
+ computed: 'computeLocalizedText_(forwardButtonTextId)',
+ },
+
+ /**
+ * Translated text to display on the cancel button.
+ *
+ * Undefined if the visible page has no cancel button.
+ *
+ * @type {string|undefined}
+ */
+ cancelButtonText: {
+ type: String,
+ computed: 'computeLocalizedText_(cancelButtonTextId)',
+ },
+
+ /**
+ * Translated text to display on the backward-naviation button.
+ *
+ * Undefined if the visible page has no backward-navigation button.
+ *
+ * @type {string|undefined}
+ */
+ backwardButtonText: {
+ type: String,
+ computed: 'computeLocalizedText_(backwardButtonTextId)',
+ },
+
+ /**
+ * Translated text of main UI Page heading.
+ *
+ * @type {string|undefined}
+ */
+ headerText: {
+ type: String,
+ computed: 'computeLocalizedText_(headerId)',
+ },
+
+ /**
+ * Translated text of main UI Page heading. In general this can include
+ * some markup.
+ *
+ * @type {string|undefined}
+ */
+ messageHtml: {
+ type: String,
+ computed: 'computeLocalizedText_(messageId)',
+ },
+ },
+
+ /**
+ * Returns a promise which always resolves and returns a boolean representing
+ * whether it should be possible to navigate forward. This function is called
+ * before forward navigation is requested; if false is returned, the active
+ * page does not change.
+ * @return {!Promise}
+ */
+ getCanNavigateToNextPage: function() {
+ return new Promise((resolve) => {
+ resolve(true /* canNavigate */);
+ });
+ },
+
+ /**
+ * @param {string} textId Key for the localized string to appear on a
+ * button.
+ * @return {string|undefined} The localized string corresponding to the key
+ * textId. Return value is undefined if textId is not a key
+ * for any localized string. Note: this includes the case in which
+ * textId is undefined.
+ * @private
+ */
+ computeLocalizedText_: function(textId) {
+ if (!this.i18nExists(textId))
+ return;
+
+ return loadTimeData.getString(textId);
+ },
+};
+
+/** @polymerBehavior */
+const UiPageContainerBehavior = [
+ I18nBehavior,
+ UiPageContainerBehaviorImpl,
+];
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_config.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_config.html
index 4c506f20691..f6053ce9367 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_config.html
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_config.html
@@ -154,7 +154,7 @@
<cr-toggle id="share" checked="{{shareNetwork_}}"
disabled="[[!shareIsEnabled_(guid, configProperties_.*,
security_, eapProperties_.*, shareAllowEnable)]]"
- aria-label="[[i18n('networkConfigShare')]]">
+ aria-labeledby="shareLabel">
</cr-toggle>
</div>
</template>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy.js
index b5dc5c2bbc2..c827a0ddfe5 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy.js
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy.js
@@ -191,7 +191,8 @@ Polymer({
(CrOnc.proxyMatches(jsonHttp, proxy.Manual.SecureHTTPProxy) &&
CrOnc.proxyMatches(jsonHttp, proxy.Manual.FTPProxy) &&
CrOnc.proxyMatches(jsonHttp, proxy.Manual.SOCKS)) ||
- (!proxy.Manual.SecureHTTPProxy.Host &&
+ (!proxy.Manual.HTTPProxy.Host &&
+ !proxy.Manual.SecureHTTPProxy.Host &&
!proxy.Manual.FTPProxy.Host && !proxy.Manual.SOCKS.Host);
}
if (proxySettings.ExcludeDomains) {
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/BUILD.gn b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/BUILD.gn
index a024915b51f..afe7eb05b32 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/BUILD.gn
+++ b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/BUILD.gn
@@ -7,6 +7,7 @@ import("//third_party/closure_compiler/compile_js.gni")
js_type_check("closure_compile") {
deps = [
":pin_keyboard",
+ ":setup_pin_keyboard",
]
}
@@ -17,3 +18,21 @@ js_library("pin_keyboard") {
"//ui/webui/resources/js:i18n_behavior",
]
}
+
+js_library("lock_screen_constants") {
+ deps = [
+ "//ui/webui/resources/cr_elements/cr_profile_avatar_selector:cr_profile_avatar_selector",
+ "//ui/webui/resources/js:cr",
+ ]
+}
+
+js_library("setup_pin_keyboard") {
+ deps = [
+ ":lock_screen_constants",
+ ":pin_keyboard",
+ "//ui/webui/resources/cr_components/chromeos/quick_unlock:lock_screen_constants",
+ "//ui/webui/resources/js:i18n_behavior",
+ ]
+ externs_list = [ "$externs_path/quick_unlock_private.js" ]
+ extra_sources = [ "$interfaces_path/quick_unlock_private_interface.js" ]
+}
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/lock_screen_constants.html b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/lock_screen_constants.html
new file mode 100644
index 00000000000..29c7f5cb64f
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/lock_screen_constants.html
@@ -0,0 +1 @@
+<script src="chrome://resources/cr_components/chromeos/quick_unlock/lock_screen_constants.js"></script>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/lock_screen_constants.js b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/lock_screen_constants.js
new file mode 100644
index 00000000000..e5ee46e6d1a
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/lock_screen_constants.js
@@ -0,0 +1,47 @@
+// Copyright 2016 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 Constants used for logging the pin unlock setup uma.
+ */
+
+/**
+ * Name of the pin unlock setup uma histogram.
+ * @type {string}
+ */
+const PinUnlockUmaHistogramName = 'Settings.PinUnlockSetup';
+
+/**
+ * Stages the user can enter while setting up pin unlock.
+ * @enum {number}
+ */
+const LockScreenProgress = {
+ START_SCREEN_LOCK: 0,
+ ENTER_PASSWORD_CORRECTLY: 1,
+ CHOOSE_PIN_OR_PASSWORD: 2,
+ ENTER_PIN: 3,
+ CONFIRM_PIN: 4,
+ MAX_BUCKET: 5
+};
+
+cr.define('settings', function() {
+ /**
+ * Helper function to send the progress of the pin setup to be recorded in the
+ * histogram.
+ * @param {LockScreenProgress} currentProgress
+ */
+ const recordLockScreenProgress = function(currentProgress) {
+ if (currentProgress >= LockScreenProgress.MAX_BUCKET) {
+ console.error(
+ 'Expected a enumeration value of ' + LockScreenProgress.MAX_BUCKET +
+ ' or lower: Received ' + currentProgress + '.');
+ return;
+ }
+ chrome.send('metricsHandler:recordInHistogram', [
+ PinUnlockUmaHistogramName, currentProgress, LockScreenProgress.MAX_BUCKET
+ ]);
+ };
+
+ return {recordLockScreenProgress: recordLockScreenProgress};
+});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html
index f28f89b9e06..080f3cc0328 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html
+++ b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.html
@@ -36,16 +36,41 @@
<template>
<style include="cr-shared-style">
:host {
+ --backspace-button-ripple-left: calc((var(--backspace-button-width) -
+ var(--pin-button-ripple-width)) / 2);
+ --backspace-button-width: calc(var(--pin-button-width) +
+ var(--pin-button-horizontal-margin) * 2);
+ --pin-button-height: 40px;
+ --pin-button-horizontal-margin: 20px;
+ --pin-button-ripple-height: 48px;
+ --pin-button-ripple-left: calc((var(--pin-button-width) -
+ var(--pin-button-ripple-width)) / 2);
+ --pin-button-ripple-top: calc((var(--pin-button-height) -
+ var(--pin-button-ripple-height)) / 2);
+ --pin-button-ripple-width: 48px;
+ --pin-button-vertical-margin: 8px;
+ --pin-button-width: 40px;
outline: none;
}
#root {
+ align-items: center;
+ display: flex;
+ flex-direction: column;
+ min-height: 0;
+ }
+
+ #rowsContainer {
direction: ltr;
display: block;
+ width: calc((var(--pin-button-width) +
+ var(--pin-button-horizontal-margin) * 2) * 3);
}
.row {
display: flex;
+ margin-bottom: calc(var(--pin-button-vertical-margin) * 2);
+ min-height: 0;
}
:host([enable-password]) #pinInputDiv {
@@ -57,10 +82,10 @@
}
#backspaceButton {
- color: var(--pin-keyboard-backspace-color, #000);
+ color: var(--pin-keyboard-backspace-color, var(--google-grey-700));
left: 0;
opacity: var(--pin-keyboard-backspace-opacity, --dark-primary-opacity);
- padding: 14px;
+ padding: 12px;
position: absolute;
top: 0;
}
@@ -71,75 +96,93 @@
#backspaceButtonContainer {
position: relative;
+ width: var(--backspace-button-width);
}
#backspaceButtonContainer paper-ripple {
- left: var(--pin-keyboard-backspace-paper-ripple-offset, 0);
- top: var(--pin-keyboard-backspace-paper-ripple-offset, 0);
+ left: var(--pin-keyboard-backspace-paper-ripple-offset,
+ var(--backspace-button-ripple-left));
+ top: var(--pin-keyboard-backspace-paper-ripple-offset,
+ var(--pin-button-ripple-top));
}
.digit-button {
+ --paper-button: {
+ min-width: 0;
+ };
align-items: center;
background: none;
border-radius: 0;
box-sizing: border-box;
- color: #000;
+ color: var(--google-grey-900);
display: flex;
flex-direction: column;
- height: 48px;
+ height: var(--pin-button-height)
justify-content: center;
- margin: 0;
- min-height: 48px;
- min-width: 48px;
+ margin: 0 var(--pin-button-horizontal-margin);
+ min-height: 0;
opacity: 0.87px;
- width: 60px;
+ padding: 0;
+ width: var(--pin-button-width);
@apply --pin-keyboard-digit-button;
}
.digit-button inner-text {
- display: flex;
- flex-direction: column;
font-family: 'Roboto';
}
- .letter {
- color: var(--pin-keyboard-letter-color, --paper-blue-grey-700);
- font-size: 9px;
- margin-top: 4px;
+ inner-text.letter {
+ color: var(--pin-keyboard-letter-color, var(--google-grey-700));
+ font-size: 12px;
+ margin-top: 8px;
+
+ @apply --pin-keyboard-digit-button-letter;
}
.number {
- color: var(--pin-keyboard-number-color, --paper-blue-grey-700);
- font-size: 20px;
- height: 52px;
+ color: var(--pin-keyboard-number-color, var(--paper-blue-grey-700));
+ font-size: 18px;
+ height: 16px;
}
paper-ripple {
color: var(--google-grey-700);
- height: 48px;
- left: 6px;
- width: 48px;
+ height: var(--pin-button-ripple-height);
+ left: var(--pin-button-ripple-left);
+ top: var(--pin-button-ripple-top);
+ width: var(--pin-button-ripple-width);
@apply --pin-keyboard-paper-ripple;
}
#pinInput {
+ --cr-input-error-display: none;
+ --cr-input-input: {
+ font-size: 28px;
+ letter-spacing: 28px;
+ };
+ --cr-input-padding-bottom: 1px;
+ --cr-input-padding-end: 0;
+ --cr-input-padding-start: 0;
+ --cr-input-padding-top: 1px;
background-color: white;
border: 0;
box-sizing: border-box;
font-face: Roboto-Regular;
font-size: 13px;
- height: 43px;
left: 0;
opacity: var(--dark-secondary-opacity);
outline: 0;
position: relative;
text-align: center;
- width: 180px;
+ width: 200px;
+
+ @apply --pin-keyboard-pin-input-style;
}
#pinInput[has-content] {
+ --cr-disabled-opacity: var(--dark-primary-opacity);
opacity: var(--dark-primary-opacity);
}
@@ -155,93 +198,98 @@
</style>
<div id="root" on-contextmenu="onContextMenu_" on-tap="focusInput_">
- <div id="pinInputDiv" class="row">
+ <div id="pinInputDiv">
<cr-input id="pinInput" type="password" value="{{value}}"
is-input-rtl$="[[isInputRtl_(value)]]"
has-content$="[[hasInput_(value)]]" invalid="[[hasError]]"
- placeholder="[[getInputPlaceholder_(enablePassword)]]"
- on-keydown="onInputKeyDown_">
+ placeholder="[[getInputPlaceholder_(enablePassword,
+ enablePlaceholder)]]"
+ on-keydown="onInputKeyDown_" force-underline$="[[forceUnderline_]]"
+ disabled="[[isIncognitoUi]]">
</cr-input>
</div>
<slot select="[problem]"></slot>
- <div class="row">
- <paper-button class="digit-button" on-tap="onNumberTap_" value="1"
- noink>
- <inner-text class="number">[[i18n('pinKeyboard1')]]</inner-text>
- <paper-ripple class="circle" center></paper-ripple>
- </paper-button>
- <paper-button class="digit-button" on-tap="onNumberTap_" value="2"
- noink>
- <inner-text class="number">[[i18n('pinKeyboard2')]]</inner-text>
- <inner-text class="letter">ABC</inner-text>
- <paper-ripple class="circle" center></paper-ripple>
- </paper-button>
- <paper-button class="digit-button" on-tap="onNumberTap_" value="3"
- noink>
- <inner-text class="number">[[i18n('pinKeyboard3')]]</inner-text>
- <inner-text class="letter">DEF</inner-text>
- <paper-ripple class="circle" center></paper-ripple>
- </paper-button>
- </div>
- <div class="row">
- <paper-button class="digit-button" on-tap="onNumberTap_" value="4"
- noink>
- <inner-text class="number">[[i18n('pinKeyboard4')]]</inner-text>
- <inner-text class="letter">GHI</inner-text>
- <paper-ripple class="circle" center></paper-ripple>
- </paper-button>
- <paper-button class="digit-button" on-tap="onNumberTap_" value="5"
- noink>
- <inner-text class="number">[[i18n('pinKeyboard5')]]</inner-text>
- <inner-text class="letter">JKL</inner-text>
- <paper-ripple class="circle" center></paper-ripple>
- </paper-button>
- <paper-button class="digit-button" on-tap="onNumberTap_" value="6"
- noink>
- <inner-text class="number">[[i18n('pinKeyboard6')]]</inner-text>
- <inner-text class="letter">MNO</inner-text>
- <paper-ripple class="circle" center></paper-ripple>
- </paper-button>
- </div>
- <div class="row">
- <paper-button class="digit-button" on-tap="onNumberTap_" value="7"
- noink>
- <inner-text class="number">[[i18n('pinKeyboard7')]]</inner-text>
- <inner-text class="letter">PQRS</inner-text>
- <paper-ripple class="circle" center></paper-ripple>
- </paper-button>
- <paper-button class="digit-button" on-tap="onNumberTap_" value="8"
- noink>
- <inner-text class="number">[[i18n('pinKeyboard8')]]</inner-text>
- <inner-text class="letter">TUV</inner-text>
- <paper-ripple class="circle" center></paper-ripple>
- </paper-button>
- <paper-button class="digit-button" on-tap="onNumberTap_" value="9"
- noink>
- <inner-text class="number">[[i18n('pinKeyboard9')]]</inner-text>
- <inner-text class="letter">WXYZ</inner-text>
- <paper-ripple class="circle" center></paper-ripple>
- </paper-button>
- </div>
- <div class="row bottom-row">
- <div class="digit-button"></div>
- <paper-button class="digit-button" on-tap="onNumberTap_" value="0"
- noink>
- <inner-text class="number">[[i18n('pinKeyboard0')]]</inner-text>
- <inner-text class="letter">+</inner-text>
- <paper-ripple class="circle" center></paper-ripple>
- </paper-button>
- <div id="backspaceButtonContainer">
- <paper-icon-button id="backspaceButton" class="digit-button"
- disabled$="[[!hasInput_(value)]]"
- icon="pin-keyboard:backspace"
- on-pointerdown="onBackspacePointerDown_"
- on-pointerout="clearAndReset_"
- on-pointerup="onBackspacePointerUp_"
- title="[[i18n('pinKeyboardDeleteAccessibleName')]]"
+ <div id="rowsContainer">
+ <div class="row">
+ <paper-button class="digit-button" on-tap="onNumberTap_" value="1"
+ noink>
+ <inner-text class="number">[[i18n('pinKeyboard1')]]</inner-text>
+ <inner-text class="letter">&nbsp;</inner-text>
+ <paper-ripple class="circle" center></paper-ripple>
+ </paper-button>
+ <paper-button class="digit-button" on-tap="onNumberTap_" value="2"
+ noink>
+ <inner-text class="number">[[i18n('pinKeyboard2')]]</inner-text>
+ <inner-text class="letter">ABC</inner-text>
+ <paper-ripple class="circle" center></paper-ripple>
+ </paper-button>
+ <paper-button class="digit-button" on-tap="onNumberTap_" value="3"
+ noink>
+ <inner-text class="number">[[i18n('pinKeyboard3')]]</inner-text>
+ <inner-text class="letter">DEF</inner-text>
+ <paper-ripple class="circle" center></paper-ripple>
+ </paper-button>
+ </div>
+ <div class="row">
+ <paper-button class="digit-button" on-tap="onNumberTap_" value="4"
+ noink>
+ <inner-text class="number">[[i18n('pinKeyboard4')]]</inner-text>
+ <inner-text class="letter">GHI</inner-text>
+ <paper-ripple class="circle" center></paper-ripple>
+ </paper-button>
+ <paper-button class="digit-button" on-tap="onNumberTap_" value="5"
+ noink>
+ <inner-text class="number">[[i18n('pinKeyboard5')]]</inner-text>
+ <inner-text class="letter">JKL</inner-text>
+ <paper-ripple class="circle" center></paper-ripple>
+ </paper-button>
+ <paper-button class="digit-button" on-tap="onNumberTap_" value="6"
+ noink>
+ <inner-text class="number">[[i18n('pinKeyboard6')]]</inner-text>
+ <inner-text class="letter">MNO</inner-text>
+ <paper-ripple class="circle" center></paper-ripple>
+ </paper-button>
+ </div>
+ <div class="row">
+ <paper-button class="digit-button" on-tap="onNumberTap_" value="7"
+ noink>
+ <inner-text class="number">[[i18n('pinKeyboard7')]]</inner-text>
+ <inner-text class="letter">PQRS</inner-text>
+ <paper-ripple class="circle" center></paper-ripple>
+ </paper-button>
+ <paper-button class="digit-button" on-tap="onNumberTap_" value="8"
+ noink>
+ <inner-text class="number">[[i18n('pinKeyboard8')]]</inner-text>
+ <inner-text class="letter">TUV</inner-text>
+ <paper-ripple class="circle" center></paper-ripple>
+ </paper-button>
+ <paper-button class="digit-button" on-tap="onNumberTap_" value="9"
+ noink>
+ <inner-text class="number">[[i18n('pinKeyboard9')]]</inner-text>
+ <inner-text class="letter">WXYZ</inner-text>
+ <paper-ripple class="circle" center></paper-ripple>
+ </paper-button>
+ </div>
+ <div class="row bottom-row">
+ <div class="digit-button"></div>
+ <paper-button class="digit-button" on-tap="onNumberTap_" value="0"
noink>
- </paper-icon-button>
- <paper-ripple class="circle" center></paper-ripple>
+ <inner-text class="number">[[i18n('pinKeyboard0')]]</inner-text>
+ <inner-text class="letter">+</inner-text>
+ <paper-ripple class="circle" center></paper-ripple>
+ </paper-button>
+ <div id="backspaceButtonContainer">
+ <paper-icon-button id="backspaceButton" class="digit-button"
+ disabled$="[[!hasInput_(value)]]"
+ icon="pin-keyboard:backspace"
+ on-pointerdown="onBackspacePointerDown_"
+ on-pointerout="clearAndReset_"
+ on-pointerup="onBackspacePointerUp_"
+ title="[[i18n('pinKeyboardDeleteAccessibleName')]]"
+ noink>
+ </paper-icon-button>
+ <paper-ripple class="circle" center></paper-ripple>
+ </div>
</div>
</div>
</div>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.js b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.js
index 0f7e3da6463..ceaaae8adca 100644
--- a/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.js
+++ b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/pin_keyboard.js
@@ -29,7 +29,7 @@
* @type {number}
* @const
*/
-var REPEAT_BACKSPACE_DELAY_MS = 150;
+const REPEAT_BACKSPACE_DELAY_MS = 150;
/**
* How long the backspace button must be held down before auto backspace
@@ -37,7 +37,7 @@ var REPEAT_BACKSPACE_DELAY_MS = 150;
* @type {number}
* @const
*/
-var INITIAL_BACKSPACE_DELAY_MS = 500;
+const INITIAL_BACKSPACE_DELAY_MS = 500;
/**
* The key codes of the keys allowed to be used on the pin input, in addition to
@@ -45,7 +45,7 @@ var INITIAL_BACKSPACE_DELAY_MS = 500;
* @type {Array<number>}
* @const
*/
-var PIN_INPUT_ALLOWED_NON_NUMBER_KEY_CODES = [8, 9, 37, 39];
+const PIN_INPUT_ALLOWED_NON_NUMBER_KEY_CODES = [8, 9, 37, 39];
Polymer({
is: 'pin-keyboard',
@@ -103,6 +103,36 @@ Polymer({
value: '',
observer: 'onPinValueChange_',
},
+
+ /**
+ * @private
+ */
+ forceUnderline_: {
+ type: Boolean,
+ value: false,
+ },
+
+ /**
+ * Enables pin placeholder.
+ */
+ enablePlaceholder: {
+ type: Boolean,
+ value: false,
+ },
+
+ /**
+ * Turns on "incognito mode". (FIXME after https://crbug.com/900351 is
+ * fixed).
+ */
+ isIncognitoUi: {
+ type: Boolean,
+ value: false,
+ },
+ },
+
+ listeners: {
+ 'blur': 'onBlur_',
+ 'focus': 'onFocus_',
},
/**
@@ -174,17 +204,27 @@ Polymer({
this.focus(this.selectionStart_, this.selectionEnd_);
},
+ /** @private */
+ onFocus_: function() {
+ this.forceUnderline_ = true;
+ },
+
+ /** @private */
+ onBlur_: function() {
+ this.forceUnderline_ = false;
+ },
+
/**
* Called when a keypad number has been tapped.
* @param {Event} event The event object.
* @private
*/
onNumberTap_: function(event) {
- var numberValue = event.target.getAttribute('value');
+ let numberValue = event.target.getAttribute('value');
// Add the number where the caret is, then update the selection range of the
// input element.
- var selectionStart = this.selectionStart_;
+ let selectionStart = this.selectionStart_;
this.value = this.value.substring(0, this.selectionStart_) + numberValue +
this.value.substring(this.selectionEnd_);
@@ -223,8 +263,8 @@ Polymer({
// If the input is shown, clear the text based on the caret location or
// selected region of the input element. If it is just a caret, remove the
// character in front of the caret.
- var selectionStart = this.selectionStart_;
- var selectionEnd = this.selectionEnd_;
+ let selectionStart = this.selectionStart_;
+ let selectionEnd = this.selectionEnd_;
if (selectionStart == selectionEnd && selectionStart)
selectionStart--;
@@ -355,9 +395,13 @@ Polymer({
/**
* Computes the value of the pin input placeholder.
* @param {boolean} enablePassword
+ * @param {boolean} enablePlaceholder
* @private
*/
- getInputPlaceholder_: function(enablePassword) {
+ getInputPlaceholder_: function(enablePassword, enablePlaceholder) {
+ if (!enablePlaceholder)
+ return '';
+
return enablePassword ? this.i18n('pinKeyboardPlaceholderPinPassword') :
this.i18n('pinKeyboardPlaceholderPin');
},
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.html b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.html
new file mode 100644
index 00000000000..71e9a15fd8e
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.html
@@ -0,0 +1,103 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_components/chromeos/quick_unlock/lock_screen_constants.html">
+<link rel="import" href="chrome://resources/cr_components/chromeos/quick_unlock/pin_keyboard.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
+<link rel="import" href="chrome://resources/html/assert.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+
+<!--
+
+This module is a "pin setup" keyboard + pin display element.
+It can be integrated into some UI container to set pin unlock.
+
+Usage:
+ <setup-pin-keyboard
+ enable-submit="{{enableSubmit_}}"
+ is-confirm-step="{{isConfirmStep_}}"
+ on-pin-submit="onPinSubmit_"
+ on-set-pin-done="onSetPinDone_"
+ set-modes="{{setModes}}">
+ </setup-pin-keyboard>
+
+Where:
+ * enable-submit - Notification property for the container to enable/disable
+ submit button in the container (if it exists). True when pin can be
+ submitted.
+ * is-confirm-step - Notification property for the container to update UI
+ when pin confirmation is requested. False when initial PIN entry step
+ is active, true when pin confirmation is active.
+ * on-pin-submit - Event handler for the user requested pin submit by pressing
+ "Enter" key on the keyboard. setup-pin-keyboard will
+ not submit pin automatically, delegating this step to outer container.
+ Container must call setup-pin-keyboard.doSubmit() when
+ pin should be submitted.
+ * on-set-pin-done - Event handler for the "set pin done" event, which should
+ normally close the pin setup UI. This object state is reset before
+ sending this event.
+ * set-modes - Reflects property set in password_prompt_dialog.js.
+
+-->
+
+<dom-module id="setup-pin-keyboard">
+ <template>
+ <style include="settings-shared">
+ .error {
+ color: var(--google-red-600);
+ }
+
+ .error > iron-icon {
+ --iron-icon-fill-color: var(--google-red-600);
+ }
+
+ .warning {
+ color: var(--cr-secondary-text-color);
+ }
+
+ .warning > iron-icon {
+ --iron-icon-fill-color: var(--google-grey-refresh-700);
+ }
+
+ #problemDiv {
+ align-items: center;
+ display: flex;
+ flex-direction: row;
+ height: 32px;
+ min-height: 0;
+ }
+
+ /* Hide this using visibility: hidden instead of hidden so that the
+ dialog does not resize when there are no problems to display. */
+ #problemDiv[invisible] {
+ visibility: hidden;
+ }
+
+ #problemMessage {
+ font-size: 10px;
+ }
+ </style>
+ <pin-keyboard id="pinKeyboard" on-pin-change="onPinChange_"
+ on-submit="onPinSubmit_" value="{{pinKeyboardValue_}}"
+ has-error="[[hasError_(problemMessageId_, problemClass_)]]"
+ enable-placeholder="[[enablePlaceholder]]"
+ is-incognito-ui="[[isIncognitoUi]]">
+ <!-- Warning/error; only shown if title is hidden. -->
+ <div id="problemDiv" class$="[[problemClass_]]"
+ invisible$="[[!problemMessageId_]]" problem>
+ <div>
+ <iron-icon icon="cr:error-outline"></iron-icon>
+ <span id="problemMessage">
+ [[formatProblemMessage_(locale, problemMessageId_,
+ problemMessageParameters_)]]
+ </span>
+ </div>
+ </div>
+ </pin-keyboard>
+ </template>
+ <script
+ src="chrome://resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.js">
+ </script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.js b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.js
new file mode 100644
index 00000000000..9dde5f4717f
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/quick_unlock/setup_pin_keyboard.js
@@ -0,0 +1,377 @@
+// 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.
+
+/**
+ * @fileoverview
+ * 'setup-pin-keyboard' is the keyboard/input field for choosing a PIN.
+ *
+ * See usage documentation in setup_pin_keyboard.html.
+ *
+ */
+
+(function() {
+'use strict';
+
+/**
+ * Keep in sync with the string keys provided by settings.
+ * @enum {string}
+ */
+const MessageType = {
+ TOO_SHORT: 'configurePinTooShort',
+ TOO_LONG: 'configurePinTooLong',
+ TOO_WEAK: 'configurePinWeakPin',
+ MISMATCH: 'configurePinMismatched'
+};
+
+/** @enum {string} */
+const ProblemType = {
+ WARNING: 'warning',
+ ERROR: 'error'
+};
+
+Polymer({
+ is: 'setup-pin-keyboard',
+
+ behaviors: [I18nBehavior],
+
+ properties: {
+ /**
+ * Reflects property set in password_prompt_dialog.js.
+ * @type {?Object}
+ */
+ setModes: {
+ type: Object,
+ notify: true,
+ },
+
+ /**
+ * The current PIN keyboard value.
+ * @private
+ */
+ pinKeyboardValue_: String,
+
+ /**
+ * Stores the initial PIN value so it can be confirmed.
+ * @private
+ */
+ initialPin_: String,
+
+ /**
+ * The message ID of actual problem message to display.
+ * @private
+ */
+ problemMessageId_: {
+ type: String,
+ value: '',
+ },
+
+ /**
+ * The additional parameters to format for the problem message string.
+ * @private
+ */
+ problemMessageParameters_: {
+ type: String,
+ value: '',
+ },
+
+ /**
+ * The type of problem class to show (warning or error).
+ * @private
+ */
+ problemClass_: String,
+
+ /**
+ * Should the step-specific submit button be displayed?
+ * This has upward data flow only.
+ */
+ enableSubmit: {
+ notify: true,
+ type: Boolean,
+ value: false,
+ },
+
+ /**
+ * writeUma is a function that handles writing uma stats.
+ *
+ * @type {function(LockScreenProgress)}
+ */
+ writeUma: {
+ type: Object,
+ value: function() {
+ return function() {};
+ }
+ },
+
+ /**
+ * The current step/subpage we are on.
+ * This is has upward data flow only.
+ */
+ isConfirmStep: {
+ notify: true,
+ type: Boolean,
+ value: false,
+ },
+
+ /**
+ * Interface for chrome.quickUnlockPrivate calls.
+ * @type {QuickUnlockPrivate}
+ */
+ quickUnlockPrivate: Object,
+
+ /**
+ * |pinHasPassedMinimumLength_| tracks whether a user has passed the minimum
+ * length threshold at least once, and all subsequent PIN too short messages
+ * will be displayed as errors. They will be displayed as warnings prior to
+ * this.
+ * @private
+ */
+ pinHasPassedMinimumLength_: {type: Boolean, value: false},
+
+ /**
+ * Enables pin placeholder.
+ */
+ enablePlaceholder: {
+ type: Boolean,
+ value: false,
+ },
+
+ /**
+ * Turns on "incognito mode". (FIXME after https://crbug.com/900351 is
+ * fixed).
+ */
+ isIncognitoUi: {
+ type: Boolean,
+ value: false,
+ },
+ },
+
+ focus: function() {
+ this.$.pinKeyboard.focus();
+ },
+
+ /** @override */
+ attached: function() {
+ this.resetState();
+
+ // Show the pin is too short error when first displaying the PIN dialog.
+ this.problemClass_ = ProblemType.WARNING;
+ this.quickUnlockPrivate.getCredentialRequirements(
+ chrome.quickUnlockPrivate.QuickUnlockMode.PIN,
+ this.processPinRequirements_.bind(this, MessageType.TOO_SHORT));
+ },
+
+ /**
+ * Resets the element to the initial state.
+ */
+ resetState: function() {
+ this.initialPin_ = '';
+ this.pinKeyboardValue_ = '';
+ this.enableSubmit = false;
+ this.isConfirmStep = false;
+ this.hideProblem_();
+ this.onPinChange_();
+ },
+
+ /**
+ * Returns true if the PIN is ready to be changed to a new value.
+ * @private
+ * @return {boolean}
+ */
+ canSubmit_: function() {
+ return this.initialPin_ == this.pinKeyboardValue_;
+ },
+
+ /**
+ * Handles writing the appropriate message to |problemMessageId_| &&
+ * |problemMessageParameters_|.
+ * @private
+ * @param {string} messageId
+ * @param {chrome.quickUnlockPrivate.CredentialRequirements} requirements
+ * The requirements received from getCredentialRequirements.
+ */
+ processPinRequirements_: function(messageId, requirements) {
+ let additionalInformation = '';
+ switch (messageId) {
+ case MessageType.TOO_SHORT:
+ additionalInformation = requirements.minLength.toString();
+ break;
+ case MessageType.TOO_LONG:
+ additionalInformation = (requirements.maxLength + 1).toString();
+ break;
+ case MessageType.TOO_WEAK:
+ case MessageType.MISMATCH:
+ break;
+ default:
+ assertNotReached();
+ break;
+ }
+ this.problemMessageId_ = messageId;
+ this.problemMessageParameters_ = additionalInformation;
+ },
+
+ /**
+ * Notify the user about a problem.
+ * @private
+ * @param {string} messageId
+ * @param {string} problemClass
+ */
+ showProblem_: function(messageId, problemClass) {
+ this.quickUnlockPrivate.getCredentialRequirements(
+ chrome.quickUnlockPrivate.QuickUnlockMode.PIN,
+ this.processPinRequirements_.bind(this, messageId));
+ this.problemClass_ = problemClass;
+ this.updateStyles();
+ this.enableSubmit =
+ problemClass != ProblemType.ERROR && messageId != MessageType.TOO_SHORT;
+ },
+
+ /** @private */
+ hideProblem_: function() {
+ this.problemMessageId_ = '';
+ this.problemClass_ = '';
+ },
+
+ /**
+ * Processes the message received from the quick unlock api and hides/shows
+ * the problem based on the message.
+ * @private
+ * @param {chrome.quickUnlockPrivate.CredentialCheck} message The message
+ * received from checkCredential.
+ */
+ processPinProblems_: function(message) {
+ if (!message.errors.length && !message.warnings.length) {
+ this.hideProblem_();
+ this.enableSubmit = true;
+ this.pinHasPassedMinimumLength_ = true;
+ return;
+ }
+
+ if (!message.errors.length ||
+ message.errors[0] !=
+ chrome.quickUnlockPrivate.CredentialProblem.TOO_SHORT) {
+ this.pinHasPassedMinimumLength_ = true;
+ }
+
+ if (message.warnings.length) {
+ assert(
+ message.warnings[0] ==
+ chrome.quickUnlockPrivate.CredentialProblem.TOO_WEAK);
+ this.showProblem_(MessageType.TOO_WEAK, ProblemType.WARNING);
+ }
+
+ if (message.errors.length) {
+ switch (message.errors[0]) {
+ case chrome.quickUnlockPrivate.CredentialProblem.TOO_SHORT:
+ this.showProblem_(
+ MessageType.TOO_SHORT,
+ this.pinHasPassedMinimumLength_ ? ProblemType.ERROR :
+ ProblemType.WARNING);
+ break;
+ case chrome.quickUnlockPrivate.CredentialProblem.TOO_LONG:
+ this.showProblem_(MessageType.TOO_LONG, ProblemType.ERROR);
+ break;
+ case chrome.quickUnlockPrivate.CredentialProblem.TOO_WEAK:
+ this.showProblem_(MessageType.TOO_WEAK, ProblemType.ERROR);
+ break;
+ default:
+ assertNotReached();
+ break;
+ }
+ }
+ },
+
+ /** @private */
+ onPinChange_: function() {
+ if (!this.isConfirmStep) {
+ if (this.pinKeyboardValue_) {
+ this.quickUnlockPrivate.checkCredential(
+ chrome.quickUnlockPrivate.QuickUnlockMode.PIN,
+ this.pinKeyboardValue_, this.processPinProblems_.bind(this));
+ } else {
+ this.enableSubmit = false;
+ }
+ return;
+ }
+
+ this.hideProblem_();
+ this.enableSubmit = this.pinKeyboardValue_.length > 0;
+ },
+
+ /** @private */
+ onPinSubmit_: function() {
+ // Notify container object.
+ this.fire('pin-submit');
+ },
+
+ /**
+ * This is callback for quickUnlockPrivate.QuickUnlockMode.PIN API.
+ *
+ * @private
+ * @param {boolean} didSet
+ */
+ onSetModesCompleted_: function(didSet) {
+ if (!didSet) {
+ console.error('Failed to update pin');
+ return;
+ }
+
+ this.resetState();
+ this.fire('set-pin-done');
+ },
+
+ /** This is called by container object when user initiated submit. */
+ doSubmit: function() {
+ if (!this.isConfirmStep) {
+ if (!this.enableSubmit)
+ return;
+ this.initialPin_ = this.pinKeyboardValue_;
+ this.pinKeyboardValue_ = '';
+ this.isConfirmStep = true;
+ this.onPinChange_();
+ this.$.pinKeyboard.focus();
+ this.writeUma(LockScreenProgress.ENTER_PIN);
+ return;
+ }
+ // onPinSubmit gets called if the user hits enter on the PIN keyboard.
+ // The PIN is not guaranteed to be valid in that case.
+ if (!this.canSubmit_()) {
+ this.showProblem_(MessageType.MISMATCH, ProblemType.ERROR);
+ this.enableSubmit = false;
+ // Focus the PIN keyboard and highlight the entire PIN.
+ this.$.pinKeyboard.focus(0, this.pinKeyboardValue_.length + 1);
+ return;
+ }
+
+ assert(this.setModes);
+ this.setModes.call(
+ null, [chrome.quickUnlockPrivate.QuickUnlockMode.PIN],
+ [this.pinKeyboardValue_], this.onSetModesCompleted_.bind(this));
+ this.writeUma(LockScreenProgress.CONFIRM_PIN);
+ },
+
+ /**
+ * @private
+ * @param {string} problemMessageId
+ * @param {string} problemClass
+ * @return {boolean}
+ */
+ hasError_: function(problemMessageId, problemClass) {
+ return !!problemMessageId && problemClass == ProblemType.ERROR;
+ },
+
+ /**
+ * Formar problem message
+ * @private
+ * @param {string} locale i18n locale data
+ * @param {string} messageId
+ * @param {string} messageParameters
+ * @return {string}
+ */
+ formatProblemMessage_: function(locale, messageId, messageParameters) {
+ return messageId ? this.i18nDynamic(locale, messageId, messageParameters) :
+ '';
+ },
+});
+
+})();
diff --git a/chromium/ui/webui/resources/cr_components/cr_components_images.grdp b/chromium/ui/webui/resources/cr_components/cr_components_images.grdp
new file mode 100644
index 00000000000..9afe1f136f9
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/cr_components_images.grdp
@@ -0,0 +1,21 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+ <if expr="chromeos">
+ <include name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_START_SETUP_ICON_1X_PNG"
+ file="cr_components/chromeos/multidevice_setup/start_setup_icon_1x.png"
+ type="BINDATA"
+ compress="gzip" />
+ <include name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_START_SETUP_ICON_2X_PNG"
+ file="cr_components/chromeos/multidevice_setup/start_setup_icon_2x.png"
+ type="BINDATA"
+ compress="gzip" />
+ <include name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_SETUP_SUCCEEDED_ICON_1X_PNG"
+ file="cr_components/chromeos/multidevice_setup/setup_succeeded_icon_1x.png"
+ type="BINDATA"
+ compress="gzip" />
+ <include name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_SETUP_SUCCEEDED_ICON_2X_PNG"
+ file="cr_components/chromeos/multidevice_setup/setup_succeeded_icon_2x.png"
+ type="BINDATA"
+ compress="gzip" />
+ </if>
+</grit-part>
diff --git a/chromium/ui/webui/resources/cr_components/cr_components_resources.grdp b/chromium/ui/webui/resources/cr_components/cr_components_resources.grdp
index 2ff0de4098b..3bf1f1cdd56 100644
--- a/chromium/ui/webui/resources/cr_components/cr_components_resources.grdp
+++ b/chromium/ui/webui/resources/cr_components/cr_components_resources.grdp
@@ -123,19 +123,19 @@
file="cr_components/chromeos/network/network_choose_mobile.js"
type="chrome_html"
compress="gzip" />
- <structure name="IDR_WEBUI_CHROMEOS__NETWORK_CONFIG_HTML"
+ <structure name="IDR_WEBUI_CHROMEOS_NETWORK_CONFIG_HTML"
file="cr_components/chromeos/network/network_config.html"
type="chrome_html"
compress="gzip" />
- <structure name="IDR_WEBUI_CHROMEOS__NETWORK_CONFIG_JS"
+ <structure name="IDR_WEBUI_CHROMEOS_NETWORK_CONFIG_JS"
file="cr_components/chromeos/network/network_config.js"
type="chrome_html"
compress="gzip" />
- <structure name="IDR_WEBUI_CHROMEOS__NETWORK_CONFIG_SELECT_HTML"
+ <structure name="IDR_WEBUI_CHROMEOS_NETWORK_CONFIG_SELECT_HTML"
file="cr_components/chromeos/network/network_config_select.html"
type="chrome_html"
compress="gzip" />
- <structure name="IDR_WEBUI_CHROMEOS__NETWORK_CONFIG_SELECT_JS"
+ <structure name="IDR_WEBUI_CHROMEOS_NETWORK_CONFIG_SELECT_JS"
file="cr_components/chromeos/network/network_config_select.js"
type="chrome_html"
compress="gzip" />
@@ -155,11 +155,11 @@
file="cr_components/chromeos/network/network_nameservers.js"
type="chrome_html"
compress="gzip" />
- <structure name="IDR_WEBUI_CHROMEOS__NETWORK_PASSWORD_INPUT_HTML"
+ <structure name="IDR_WEBUI_CHROMEOS_NETWORK_PASSWORD_INPUT_HTML"
file="cr_components/chromeos/network/network_password_input.html"
type="chrome_html"
compress="gzip" />
- <structure name="IDR_WEBUI_CHROMEOS__NETWORK_PASSWORD_INPUT_JS"
+ <structure name="IDR_WEBUI_CHROMEOS_NETWORK_PASSWORD_INPUT_JS"
file="cr_components/chromeos/network/network_password_input.js"
type="chrome_html"
compress="gzip" />
@@ -218,5 +218,127 @@
file="cr_components/chromeos/quick_unlock/pin_keyboard.js"
type="chrome_html"
compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_QUICK_UNLOCK_SETUP_PIN_KEYBOARD_JS"
+ file="cr_components/chromeos/quick_unlock/setup_pin_keyboard.js"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_QUICK_UNLOCK_SETUP_PIN_KEYBOARD_HTML"
+ file="cr_components/chromeos/quick_unlock/setup_pin_keyboard.html"
+ type="chrome_html"
+ compress="gzip"/>
+ <structure name="IDR_WEBUI_CHROMEOS_QUICK_UNLOCK_LOCK_SCREEN_CONSTANTS_JS"
+ file="cr_components/chromeos/quick_unlock/lock_screen_constants.js"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_QUICK_UNLOCK_LOCK_SCREEN_CONSTANTS_HTML"
+ file="cr_components/chromeos/quick_unlock/lock_screen_constants.html"
+ type="chrome_html"
+ compress="gzip" />
+
+ <!-- Shared between MultiDevice setup flow and OOBE. -->
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_BROWSER_PROXY_HTML"
+ file="cr_components/chromeos/multidevice_setup/multidevice_setup_browser_proxy.html"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_BROWSER_PROXY_JS"
+ file="cr_components/chromeos/multidevice_setup/multidevice_setup_browser_proxy.js"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_BUTTON_BAR_HTML"
+ file="cr_components/chromeos/multidevice_setup/button_bar.html"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_BUTTON_BAR_JS"
+ file="cr_components/chromeos/multidevice_setup/button_bar.js"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_FAKE_MOJO_SERVICE_HTML"
+ file="cr_components/chromeos/multidevice_setup/fake_mojo_service.html"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_FAKE_MOJO_SERVICE_JS"
+ file="cr_components/chromeos/multidevice_setup/fake_mojo_service.js"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_ICONS_HTML"
+ file="cr_components/chromeos/multidevice_setup/icons.html"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_MOJO_API_HTML"
+ file="cr_components/chromeos/multidevice_setup/mojo_api.html"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_MOJO_API_JS"
+ file="cr_components/chromeos/multidevice_setup/mojo_api.js"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_HTML"
+ file="cr_components/chromeos/multidevice_setup/multidevice_setup.html"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_JS"
+ file="cr_components/chromeos/multidevice_setup/multidevice_setup.js"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_DELEGATE_HTML"
+ file="cr_components/chromeos/multidevice_setup/multidevice_setup_delegate.html"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_DELEGATE_JS"
+ file="cr_components/chromeos/multidevice_setup/multidevice_setup_delegate.js"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_MULTIDEVICE_SETUP_SHARED_CSS_HTML"
+ file="cr_components/chromeos/multidevice_setup/multidevice_setup_shared_css.html"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_PASSWORD_PAGE_HTML"
+ file="cr_components/chromeos/multidevice_setup/password_page.html"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_PASSWORD_PAGE_JS"
+ file="cr_components/chromeos/multidevice_setup/password_page.js"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_SETUP_FAILED_PAGE_HTML"
+ file="cr_components/chromeos/multidevice_setup/setup_failed_page.html"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_SETUP_FAILED_PAGE_JS"
+ file="cr_components/chromeos/multidevice_setup/setup_failed_page.js"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_SETUP_SUCCEEDED_PAGE_HTML"
+ file="cr_components/chromeos/multidevice_setup/setup_succeeded_page.html"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_SETUP_SUCCEEDED_PAGE_JS"
+ file="cr_components/chromeos/multidevice_setup/setup_succeeded_page.js"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_START_SETUP_PAGE_HTML"
+ file="cr_components/chromeos/multidevice_setup/start_setup_page.html"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_START_SETUP_PAGE_JS"
+ file="cr_components/chromeos/multidevice_setup/start_setup_page.js"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_UI_PAGE_CONTAINER_BEHAVIOR_HTML"
+ file="cr_components/chromeos/multidevice_setup/ui_page_container_behavior.html"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_UI_PAGE_CONTAINER_BEHAVIOR_JS"
+ file="cr_components/chromeos/multidevice_setup/ui_page_container_behavior.js"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_UI_PAGE_HTML"
+ file="cr_components/chromeos/multidevice_setup/ui_page.html"
+ type="chrome_html"
+ compress="gzip" />
+ <structure name="IDR_WEBUI_CHROMEOS_MULTIDEVICE_SETUP_UI_PAGE_JS"
+ file="cr_components/chromeos/multidevice_setup/ui_page.js"
+ type="chrome_html"
+ compress="gzip" />
</if>
</grit-part>
diff --git a/chromium/ui/webui/resources/cr_elements/BUILD.gn b/chromium/ui/webui/resources/cr_elements/BUILD.gn
index 90954848f2e..9927b6e60e8 100644
--- a/chromium/ui/webui/resources/cr_elements/BUILD.gn
+++ b/chromium/ui/webui/resources/cr_elements/BUILD.gn
@@ -22,6 +22,7 @@ group("closure_compile") {
"cr_slider:closure_compile",
"cr_toast:closure_compile",
"cr_toggle:closure_compile",
+ "cr_view_manager:closure_compile",
"policy:closure_compile",
]
}
diff --git a/chromium/ui/webui/resources/cr_elements/READE.md b/chromium/ui/webui/resources/cr_elements/README.md
index b8b47ef98b3..b8b47ef98b3 100644
--- a/chromium/ui/webui/resources/cr_elements/READE.md
+++ b/chromium/ui/webui/resources/cr_elements/README.md
diff --git a/chromium/ui/webui/resources/cr_elements/chromeos/network/cr_network_select.js b/chromium/ui/webui/resources/cr_elements/chromeos/network/cr_network_select.js
index 32dfbba4732..66036c7283d 100644
--- a/chromium/ui/webui/resources/cr_elements/chromeos/network/cr_network_select.js
+++ b/chromium/ui/webui/resources/cr_elements/chromeos/network/cr_network_select.js
@@ -159,6 +159,8 @@ Polymer({
if (this.cellularDeviceState_)
this.ensureCellularNetwork_(networkStates);
this.networkStateList_ = networkStates;
+ this.fire('network-list-changed', networkStates);
+
var defaultNetwork;
for (var i = 0; i < networkStates.length; ++i) {
var state = networkStates[i];
diff --git a/chromium/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.html b/chromium/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.html
index 3bb931d9a4b..3c87967d159 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.html
+++ b/chromium/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.html
@@ -60,7 +60,7 @@
outline: none;
}
</style>
- <dialog id="dialog" tabindex="0">
+ <dialog id="dialog" tabindex="0" on-close="onNativeDialogClose_">
<div class="item-wrapper" tabindex="-1" role="menu">
<slot name="item" id="contentNode"></slot>
</div>
diff --git a/chromium/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js b/chromium/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js
index ec1ac2d8fce..9c70ecede80 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js
@@ -197,6 +197,24 @@ Polymer({
* @param {!Event} e
* @private
*/
+ onNativeDialogClose_: function(e) {
+ // Ignore any 'close' events not fired directly by the <dialog> element.
+ if (e.target !== this.$.dialog)
+ return;
+
+ // TODO(dpapad): This is necessary to make the code work both for Polymer 1
+ // and Polymer 2. Remove once migration to Polymer 2 is completed.
+ e.stopPropagation();
+
+ // Catch and re-fire the 'close' event such that it bubbles across Shadow
+ // DOM v1.
+ this.fire('close');
+ },
+
+ /**
+ * @param {!Event} e
+ * @private
+ */
onTap_: function(e) {
if (e.target == this) {
this.close();
@@ -271,7 +289,7 @@ Polymer({
var options = this.querySelectorAll('.dropdown-item');
var numOptions = options.length;
var focusedIndex =
- Array.prototype.indexOf.call(options, this.root.activeElement);
+ Array.prototype.indexOf.call(options, getDeepActiveElement());
// Handle case where nothing is focused and up is pressed.
if (focusedIndex === -1 && step === -1)
diff --git a/chromium/ui/webui/resources/cr_elements/cr_container_shadow_behavior.js b/chromium/ui/webui/resources/cr_elements/cr_container_shadow_behavior.js
index 45d8db171ec..3eb059ebfcf 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_container_shadow_behavior.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_container_shadow_behavior.js
@@ -29,7 +29,7 @@ var CrContainerShadowBehavior = {
var dropShadow = document.createElement('div');
// This ID should match the CSS rules in shared_styles_css.html.
dropShadow.id = 'cr-container-shadow';
- this.shadowRoot.insertBefore(dropShadow, this.$.container);
+ this.$.container.parentNode.insertBefore(dropShadow, this.$.container);
// Dummy element used to detect scrolling. Has a 0px height intentionally.
var intersectionProbe = document.createElement('div');
diff --git a/chromium/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.js b/chromium/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.js
index 864898edab5..ebf0ad52afa 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.js
@@ -52,6 +52,15 @@ Polymer({
},
/**
+ * True if the dialog should consume 'keydown' events. If ignoreEnterKey
+ * is true, 'Enter' key won't be consumed.
+ */
+ consumeKeydownEvent: {
+ type: Boolean,
+ value: false,
+ },
+
+ /**
* True if the dialog should not be able to be cancelled, which will prevent
* 'Escape' key presses from closing the dialog.
*/
@@ -77,6 +86,9 @@ Polymer({
/** @private {?MutationObserver} */
mutationObserver_: null,
+ /** @private {?Function} */
+ boundKeydown_: null,
+
/** @override */
ready: function() {
// If the active history entry changes (i.e. user clicks back button),
@@ -93,10 +105,13 @@ Polymer({
/** @override */
attached: function() {
var mutationObserverCallback = function() {
- if (this.$.dialog.open)
+ if (this.$.dialog.open) {
this.addIntersectionObserver_();
- else
+ this.addKeydownListener_();
+ } else {
this.removeIntersectionObserver_();
+ this.removeKeydownListener_();
+ }
}.bind(this);
this.mutationObserver_ = new MutationObserver(mutationObserverCallback);
@@ -113,6 +128,7 @@ Polymer({
/** @override */
detached: function() {
this.removeIntersectionObserver_();
+ this.removeKeydownListener_();
if (this.mutationObserver_) {
this.mutationObserver_.disconnect();
this.mutationObserver_ = null;
@@ -163,6 +179,31 @@ Polymer({
}
},
+ /** @private */
+ addKeydownListener_: function() {
+ if (!this.consumeKeydownEvent)
+ return;
+
+ this.boundKeydown_ = this.boundKeydown_ || this.onKeydown_.bind(this);
+
+ this.addEventListener('keydown', this.boundKeydown_);
+
+ // Sometimes <body> is key event's target and in that case the event
+ // will bypass cr-dialog. We should consume those events too in order to
+ // behave modally. This prevents accidentally triggering keyboard commands.
+ document.body.addEventListener('keydown', this.boundKeydown_);
+ },
+
+ /** @private */
+ removeKeydownListener_: function() {
+ if (!this.boundKeydown_)
+ return;
+
+ this.removeEventListener('keydown', this.boundKeydown_);
+ document.body.removeEventListener('keydown', this.boundKeydown_);
+ this.boundKeydown_ = null;
+ },
+
showModal: function() {
this.$.dialog.showModal();
assert(this.$.dialog.open);
@@ -216,6 +257,10 @@ Polymer({
* @private
*/
onNativeDialogCancel_: function(e) {
+ // Ignore any 'cancel' events not fired directly by the <dialog> element.
+ if (e.target !== this.getNative())
+ return;
+
if (this.noCancel) {
e.preventDefault();
return;
@@ -265,6 +310,23 @@ Polymer({
}
},
+ /**
+ * @param {!Event} e
+ * @private
+ */
+ onKeydown_: function(e) {
+ assert(this.consumeKeydownEvent);
+
+ if (!this.getNative().open)
+ return;
+
+ if (this.ignoreEnterKey && e.key == 'Enter')
+ return;
+
+ // Stop propagation to behave modally.
+ e.stopPropagation();
+ },
+
/** @param {!PointerEvent} e */
onPointerdown_: function(e) {
// Only show pulse animation if user left-clicked outside of the dialog
diff --git a/chromium/ui/webui/resources/cr_elements/cr_input/cr_input.html b/chromium/ui/webui/resources/cr_elements/cr_input/cr_input.html
index 5be1ea9e8c9..b328ee4b72e 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_input/cr_input.html
+++ b/chromium/ui/webui/resources/cr_elements/cr_input/cr_input.html
@@ -10,18 +10,22 @@
<template>
<style include="cr-hidden-style cr-input-style">
/*
+ A 'suffix' element will be outside the underlined space, while a
+ 'prefix' element will be inside the underlined space by default.
+
Regarding cr-input's width:
- When there's no element in the 'suffix' slot, setting the width of
- cr-input as follows will work as expected:
+ When there's no element in the 'prefix' or 'suffix' slot, setting
+ the width of cr-input as follows will work as expected:
cr-input {
width: 200px;
}
- However, when there's an element in the 'suffix' slot, setting the
- 'width' will dictate the total with of the input field *plus* the
- 'suffix' element. To set the width of the input field itself when
- a 'suffix' is present, use --cr-input-width.
+ However, when there's an element in the 'suffix' and/or 'prefix'
+ slot, setting the 'width' will dictate the total width of the input
+ field *plus* the 'prefix' and 'suffix' elements. To set the width
+ of the input field + 'prefix' when a 'suffix' is present, use
+ --cr-input-width.
cr-input {
--cr-input-width: 200px;
@@ -72,8 +76,8 @@
color: var(--cr-input-error-color);
display: var(--cr-input-error-display, block);
font-size: var(--cr-form-field-label-font-size);
- height: var(--cr-form-field-label-font-size);
- line-height: var(--cr-form-field-label-font-size);
+ height: var(--cr-form-field-label-height);
+ line-height: var(--cr-form-field-label-line-height);
margin: 8px 0;
visibility: hidden;
}
@@ -82,14 +86,17 @@
visibility: visible;
}
- #row-container {
+ #row-container,
+ #inner-input-container {
align-items: center;
display: flex;
/* This will spread the input field and the suffix apart only if the
host element width is intentionally set to something large. */
justify-content: space-between;
position: relative;
+ }
+ #row-container {
@apply --cr-input-row-container;
}
@@ -103,12 +110,17 @@
<!-- Only attributes that are named inconsistently between html and js
need to use attr$="", such as |tabindex| vs .tabIndex and
|readonly| vs .readOnly. -->
- <input id="input" disabled="[[disabled]]" autofocus="[[autofocus]]"
- value="{{value::input}}" tabindex$="[[tabindex]]" type="[[type]]"
- readonly$="[[readonly]]" maxlength$="[[maxlength]]"
- pattern="[[pattern]]" required="[[required]]"
- incremental="[[incremental]]" minlength$="[[minlength]]"
- max="[[max]]" min="[[min]]">
+ <div id="inner-input-container">
+ <slot name="prefix"></slot>
+ <input id="input" disabled="[[disabled]]" autofocus="[[autofocus]]"
+ value="{{value::input}}" tabindex$="[[tabindex]]" type="[[type]]"
+ readonly$="[[readonly]]" maxlength$="[[maxlength]]"
+ pattern$="[[pattern]]" required="[[required]]"
+ minlength$="[[minlength]]"
+ max="[[max]]" min="[[min]]" on-focus="onInputFocus_"
+ on-blur="onInputBlur_" on-change="onInputChange_"
+ on-keydown="onInputKeydown_">
+ </div>
<div id="underline"></div>
</div>
<slot name="suffix"></slot>
diff --git a/chromium/ui/webui/resources/cr_elements/cr_input/cr_input.js b/chromium/ui/webui/resources/cr_elements/cr_input/cr_input.js
index 2cbd52aa289..67b9484a99b 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_input/cr_input.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_input/cr_input.js
@@ -8,7 +8,6 @@
* Native input attributes that are currently supported by cr-inputs are:
* autofocus
* disabled
- * incremental (only applicable when type="search")
* max (only applicable when type="number")
* min (only applicable when type="number")
* maxlength
@@ -72,8 +71,6 @@ Polymer({
reflectToAttribute: true,
},
- incremental: Boolean,
-
invalid: {
type: Boolean,
value: false,
@@ -150,11 +147,7 @@ Polymer({
},
listeners: {
- 'input.focus': 'onInputFocus_',
- 'input.blur': 'onInputBlur_',
- 'input.change': 'onInputChange_',
- 'input.keydown': 'onInputKeydown_',
- 'focus': 'focusInput_',
+ 'focus': 'onFocus_',
'pointerdown': 'onPointerDown_',
},
@@ -219,9 +212,24 @@ Polymer({
},
/** @private */
+ onFocus_: function() {
+ if (!this.focusInput_())
+ return;
+ // Always select the <input> element on focus. TODO(stevenjb/scottchen):
+ // Native <input> elements only do this for keyboard focus, not when
+ // focus() is called directly. Fix this? https://crbug.com/882612.
+ this.inputElement.select();
+ },
+
+ /**
+ * @return {boolean} Whether the <input> element was focused.
+ * @private
+ */
focusInput_: function() {
- if (this.shadowRoot.activeElement != this.inputElement)
- this.inputElement.focus();
+ if (this.shadowRoot.activeElement == this.inputElement)
+ return false;
+ this.inputElement.focus();
+ return true;
},
/** @private */
@@ -328,4 +336,4 @@ Polymer({
this.invalid = !this.inputElement.checkValidity();
return !this.invalid;
},
-}); \ No newline at end of file
+});
diff --git a/chromium/ui/webui/resources/cr_elements/cr_input/cr_input_style_css.html b/chromium/ui/webui/resources/cr_elements/cr_input/cr_input_style_css.html
index 2b3e104397f..a78334b5223 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_input/cr_input_style_css.html
+++ b/chromium/ui/webui/resources/cr_elements/cr_input/cr_input_style_css.html
@@ -35,6 +35,15 @@
@apply --cr-input-container;
}
+ #inner-input-container {
+ background-color: var(--cr-input-background-color,
+ var(--google-grey-refresh-100));
+ box-sizing: border-box;
+ padding: 0;
+
+ @apply --cr-input-inner-container;
+ }
+
#input {
-webkit-appearance: none;
background-color: var(--cr-input-background-color,
@@ -78,11 +87,12 @@
opacity: 0;
position: absolute;
right: 0;
- transition: opacity 120ms ease-out, width 0 linear 180ms;
+ transition: opacity 120ms ease-out, width 0s linear 180ms;
width: 0;
}
:host([invalid]) #underline,
+ :host([force-underline]) #underline,
:host([focused_]:not([readonly])) #underline {
opacity: 1;
transition: width 180ms ease-out, opacity 120ms ease-in;
diff --git a/chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field_behavior.js b/chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field_behavior.js
index 1c41e4a776f..179a09753c2 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field_behavior.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field_behavior.js
@@ -32,6 +32,9 @@ var CrSearchFieldBehavior = {
},
},
+ /** @private {number} */
+ searchDelayTimer_: -1,
+
/**
* @return {!HTMLInputElement} The input field element the behavior should
* use.
@@ -59,6 +62,26 @@ var CrSearchFieldBehavior = {
this.onValueChanged_(value, !!opt_noEvent);
},
+ /** @private */
+ scheduleSearch_: function() {
+ if (this.searchDelayTimer_ >= 0)
+ clearTimeout(this.searchDelayTimer_);
+ // Dispatch 'search' event after:
+ // 0ms if the value is empty
+ // 500ms if the value length is 1
+ // 400ms if the value length is 2
+ // 300ms if the value length is 3
+ // 200ms if the value length is 4 or greater.
+ // The logic here was copied from WebKit's native 'search' event.
+ var length = this.getValue().length;
+ var timeoutMs = length > 0 ? (500 - 100 * (Math.min(length, 4) - 1)) : 0;
+ this.searchDelayTimer_ = setTimeout(() => {
+ this.getSearchInput().dispatchEvent(
+ new CustomEvent('search', {composed: true, detail: this.getValue()}));
+ this.searchDelayTimer_ = -1;
+ }, timeoutMs);
+ },
+
onSearchTermSearch: function() {
this.onValueChanged_(this.getValue(), false);
},
@@ -70,6 +93,7 @@ var CrSearchFieldBehavior = {
*/
onSearchTermInput: function() {
this.hasSearchText = this.$.searchInput.value != '';
+ this.scheduleSearch_();
},
/**
diff --git a/chromium/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html b/chromium/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html
index 168a5fec0e7..209dc714d37 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html
+++ b/chromium/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.html
@@ -49,7 +49,8 @@
immediately as the user types unless the update-value-on-input flag is
explicitly used. -->
<cr-input label="[[label]]" on-click="onClick_" value="[[value]]"
- on-input="onInput_" id="search" autofocus="[[autofocus]]">
+ on-input="onInput_" id="search" autofocus="[[autofocus]]"
+ placeholder="[[placeholder]]">
</cr-input>
<iron-dropdown horizontal-align="left" vertical-align="top"
vertical-offset="52">
diff --git a/chromium/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.js b/chromium/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.js
index 3ce90c6fe13..e7e94edb832 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.js
@@ -20,6 +20,8 @@ Polymer({
reflectToAttribute: true,
},
+ placeholder: String,
+
/** @type {!Array<string>} */
items: Array,
diff --git a/chromium/ui/webui/resources/cr_elements/cr_slider/BUILD.gn b/chromium/ui/webui/resources/cr_elements/cr_slider/BUILD.gn
index 78d6d47bac9..ad5d8f69b5e 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_slider/BUILD.gn
+++ b/chromium/ui/webui/resources/cr_elements/cr_slider/BUILD.gn
@@ -12,6 +12,8 @@ js_type_check("closure_compile") {
js_library("cr_slider") {
deps = [
- "//third_party/polymer/v1_0/components-chromium/paper-slider:paper-slider-extracted",
+ "//third_party/polymer/v1_0/components-chromium/paper-behaviors:paper-ripple-behavior-extracted",
+ "//ui/webui/resources/js:cr",
+ "//ui/webui/resources/js:event_tracker",
]
}
diff --git a/chromium/ui/webui/resources/cr_elements/cr_slider/cr_slider.html b/chromium/ui/webui/resources/cr_elements/cr_slider/cr_slider.html
index 05adf450012..f6203a2f110 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_slider/cr_slider.html
+++ b/chromium/ui/webui/resources/cr_elements/cr_slider/cr_slider.html
@@ -1,52 +1,197 @@
<link rel="import" href="../../html/polymer.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-behaviors/paper-ripple-behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout.html">
+<link rel="import" href="../../html/cr.html">
+<link rel="import" href="../../html/event_tracker.html">
+<link rel="import" href="../hidden_style_css.html">
<link rel="import" href="../shared_vars_css.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-slider/paper-slider.html">
<dom-module id="cr-slider">
<template>
- <style>
- paper-slider {
- --paper-slider-active-color: var(--google-blue-600);
- --paper-slider-container-color: var(--google-blue-600-opacity-24);
- --paper-slider-knob-color: var(--google-blue-600);
- --paper-slider-knob-start-color: var(--google-blue-600);
- --paper-slider-knob-start-border-color: var(--google-blue-600);
- --paper-slider-pin-color: var(--google-blue-600);
- --paper-slider-pin-start-color: var(--google-blue-600);
- --paper-slider-markers-color: rgba(255, 255, 255, 0.54);
- --paper-slider-disabled-active-color: var(--google-grey-600);
- --paper-slider-disabled-knob-color: var(--google-grey-600);
- width: 100%;
-
- --paper-slider-pin-text: {
- font-family: Roboto;
- font-size: 12px;
- font-weight: 500;
- line-height: 14px;
- };
- }
-
- :host-context([dir=rtl]) paper-slider {
- --paper-slider-pin-text: {
- font-family: Roboto;
- font-size: 12px;
- font-weight: 500;
- line-height: 14px;
- transform: scale(-1, 1) translate(0, -17px);
- };
- }
-
- paper-slider[disabled] {
- --paper-slider-container-color: var(--google-grey-600-opacity-24);
+ <style include="cr-hidden-style">
+ :host {
+ -webkit-tap-highlight-color: rgba(0, 0, 0, 0);
+ cursor: default;
+ user-select: none;
+ }
+
+ :host([dragging]) {
+ touch-action: none;
+ }
+
+ #container {
+ height: 32px;
+ position: relative;
+ }
+
+ #barContainer {
+ background-color: var(--google-blue-600-opacity-24);
+ border-radius: 1px;
+ height: 2px;
+ margin: 0 16px;
+ position: absolute;
+ top: 15px;
+ width: calc(100% - 32px);
+ }
+
+ #bar {
+ background-color: var(--google-blue-600);
+ border-radius: 1px;
+ height: 2px;
+ left: 0;
+ position: absolute;
+ transition: width 80ms ease;
+ width: 0;
+ }
+
+ :host-context([dir=rtl]) #bar {
+ left: initial;
+ right: 0;
+ }
+
+ #knobContainer {
+ margin-inline-start: 12px;
+ position: absolute;
+ top: 11px;
+ width: calc(100% - 32px);
+ }
+
+ #knob {
+ background-color: var(--google-blue-600);
+ border: 0;
+ border-radius: 50%;
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.4);
+ height: 10px;
+ margin-inline-start: 0;
+ outline: none;
+ position: absolute;
+ transition: margin-inline-start 80ms ease;
+ width: 10px;
+ }
+
+ paper-ripple {
+ color: var(--google-blue-600);
+ height: 32px;
+ left: -11px;
+ pointer-events: none;
+ top: -11px;
+ transition: color linear 80ms;
+ width: 32px;
+ }
+
+ :host-context([dir=rtl]) paper-ripple {
+ left: auto;
+ right: -11px;
+ }
+
+ #markers {
+ left: 0;
+ pointer-events: none;
+ position: absolute;
+ right: 0;
+ top: 0;
+ @apply --layout-horizontal;
+ }
+
+ .active-marker,
+ .inactive-marker {
+ @apply --layout-flex;
+ }
+ #markers::before,
+ #markers::after,
+ .active-marker::after,
+ .inactive-marker::after {
+ border-radius: 50%;
+ content: '';
+ display: block;
+ height: 2px;
+ margin-left: -1px;
+ width: 2px;
+ }
+
+ #markers::before,
+ .active-marker::after {
+ background-color: rgba(255, 255, 255, 0.54);
+ }
+
+ #markers::after,
+ .inactive-marker::after {
+ background-color: rgba(26, 115, 232, 0.54);
+ }
+
+ #labelContainer {
+ cursor: default;
+ margin-inline-start: 1px;
+ opacity: 0;
+ transition: opacity 80ms ease-in-out;
+ user-select: none;
+ width: calc(100% - 32px);
+ }
+
+ #container:hover #labelContainer,
+ .hover #labelContainer,
+ :host([hold-down_]) #labelContainer {
+ opacity: 1;
+ }
+
+ #label {
+ background: var(--google-blue-600);
+ border-radius: 14px;
+ bottom: 28px;
+ color: white;
+ font-size: 12px;
+ line-height: 1.5em;
+ padding: 0 8px;
+ position: absolute;
+ transition: margin-inline-start 80ms ease;
+ white-space: nowrap;
+ }
+
+ :host([disabled]) {
+ pointer-events: none;
+ }
+
+ :host([disabled]) #barContainer {
+ background-color: var(--google-grey-600-opacity-24);
+ }
+
+ :host([disabled]) #bar {
+ background-color: var(--google-grey-600);
+ }
+
+ :host([disabled]) inactive-marker::after,
+ :host([disabled]) #markers::after {
+ background-color: rgba(255, 255, 255, 0.54);
+ }
+
+ :host([disabled]) #knobContainer {
+ margin-inline-start: 9px;
+ top: 9px;
+ }
+ :host([disabled]) #knob {
+ background-color: var(--google-grey-600);
+ border: 2px solid white;
+ box-shadow: unset;
}
</style>
- <paper-slider id="slider"
- disabled$="[[disabled]]" snaps="[[snaps]]" on-change="onChange_"
- max="[[max]]" min="[[min]]" on-up="resetTrackLock_" value="{{value}}"
- max-markers="[[maxMarkers]]" immediate-value="{{immediateValue}}"
- dragging="{{dragging}}">
- </paper-slider>
+ <div id="container">
+ <div id="barContainer">
+ <div id="bar"></div>
+ <div id="markers" hidden$="[[!markerCount]]">
+ <template is="dom-repeat" items="[[getMarkers_(markerCount)]]">
+ <div class$="[[getMarkerClass_(index, immediateValue_, min, max,
+ markerCount)]]"></div>
+ </template>
+ </div>
+ </div>
+ <div id="knobContainer">
+ <div id="knob" tabindex="0"></div>
+ </div>
+ <div id="labelContainer" aria-label="[[label_]]">
+ <div id="label">[[label_]]</div>
+ </div>
+ </div>
</template>
<script src="cr_slider.js"></script>
</dom-module>
diff --git a/chromium/ui/webui/resources/cr_elements/cr_slider/cr_slider.js b/chromium/ui/webui/resources/cr_elements/cr_slider/cr_slider.js
index 16180c12ec0..97033f5ade8 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_slider/cr_slider.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_slider/cr_slider.js
@@ -3,148 +3,420 @@
// found in the LICENSE file.
/**
- * @fileoverview 'cr-slider' is a wrapper around paper-slider to alter the
- * styling. The behavior of the slider remains the same.
+ * @fileoverview 'cr-slider' is a slider component used to select a number from
+ * a continuous or discrete range of numbers.
*/
-Polymer({
- is: 'cr-slider',
- properties: {
- min: Number,
+cr.exportPath('cr_slider');
- max: Number,
+/**
+ * The |value| is the corresponding value that the current slider tick is
+ * associated with. The string |label| is shown in the UI as the label for the
+ * current slider value. The |ariaValue| number is used for aria-valuemin,
+ * aria-valuemax, and aria-valuenow, and is optional. If missing, |value| will
+ * be used instead.
+ * @typedef {{
+ * value: number,
+ * label: string,
+ * ariaValue: (number|undefined),
+ * }}
+ */
+cr_slider.SliderTick;
+
+(() => {
+ /**
+ * @param {number} min
+ * @param {number} max
+ * @param {number} value
+ * @return {number}
+ */
+ function clamp(min, max, value) {
+ return Math.min(max, Math.max(min, value));
+ }
+
+ Polymer({
+ is: 'cr-slider',
+
+ behaviors: [
+ Polymer.PaperRippleBehavior,
+ ],
+
+ properties: {
+ disabled: {
+ type: Boolean,
+ value: false,
+ reflectToAttribute: true,
+ },
+
+ dragging: {
+ type: Boolean,
+ value: false,
+ reflectToAttribute: true,
+ },
+
+ markerCount: {
+ type: Number,
+ value: 0,
+ },
+
+ max: {
+ type: Number,
+ value: 100,
+ },
+
+ min: {
+ type: Number,
+ value: 0,
+ },
+
+ snaps: {
+ type: Boolean,
+ value: false,
+ },
+
+ /**
+ * The data associated with each tick on the slider. Each element in the
+ * array contains a value and the label corresponding to that value.
+ * @type {!Array<cr_slider.SliderTick>|!Array<number>}
+ */
+ ticks: {
+ type: Array,
+ value: () => [],
+ observer: 'onTicksChanged_',
+ },
+
+ value: {
+ type: Number,
+ value: 0,
+ notify: true,
+ observer: 'onValueChanged_',
+ },
- snaps: {
- type: Boolean,
- value: true,
+ /**
+ * If true, |value| is updated while dragging happens. If false, |value|
+ * is updated only once, when drag gesture finishes.
+ */
+ updateValueInstantly: {
+ type: Boolean,
+ value: true,
+ },
+
+ /**
+ * |immediateValue_| has the most up-to-date value and is used to render
+ * the slider UI. When dragging, |immediateValue_| is always updated, and
+ * |value| is updated at least once when dragging is stopped.
+ * @private
+ */
+ immediateValue_: {
+ type: Number,
+ value: 0,
+ },
+
+ /** @private */
+ holdDown_: {
+ type: Boolean,
+ value: false,
+ observer: 'onHoldDownChanged_',
+ reflectToAttribute: true,
+ },
+
+ /** @private */
+ label_: {
+ type: String,
+ value: '',
+ },
},
- disabled: {
- type: Boolean,
- observer: 'onDisabledChanged_',
+ hostAttributes: {
+ role: 'slider',
},
- value: Number,
- maxMarkers: Number,
+ observers: [
+ 'updateLabelAndAria_(immediateValue_, min, max)',
+ 'updateKnobAndBar_(immediateValue_, min, max)',
+ ],
- immediateValue: {
- type: Number,
- observer: 'onImmediateValueChanged_',
+ listeners: {
+ focus: 'onFocus_',
+ blur: 'onBlur_',
+ keydown: 'onKeyDown_',
+ pointerdown: 'onPointerDown_',
},
- dragging: Boolean,
- },
+ /** @private {Map<string, number>} */
+ deltaKeyMap_: null,
- listeners: {
- 'focus': 'onFocus_',
- 'blur': 'onBlur_',
- 'keydown': 'onKeyDown_',
- 'pointerdown': 'onPointerDown_',
- 'pointerup': 'onPointerUp_',
- },
+ /** @private {boolean} */
+ isRtl_: false,
- /** @private {boolean} */
- usedMouse_: false,
+ /** @private {EventTracker} */
+ draggingEventTracker_: null,
- /** @override */
- attached: function() {
- this.onDisabledChanged_();
- },
+ /** @override */
+ attached: function() {
+ this.isRtl_ = this.matches(':host-context([dir=rtl]) cr-slider');
+ this.deltaKeyMap_ = new Map([
+ ['ArrowDown', -1],
+ ['ArrowUp', 1],
+ ['PageDown', -1],
+ ['PageUp', 1],
+ ['ArrowLeft', this.isRtl_ ? 1 : -1],
+ ['ArrowRight', this.isRtl_ ? -1 : 1],
+ ]);
+ this.draggingEventTracker_ = new EventTracker();
+ },
- /** @private */
- onFocus_: function() {
- this.$.slider.getRipple().holdDown = true;
- this.$.slider._expandKnob();
- },
+ /**
+ * When markers are displayed on the slider, they are evenly spaced across
+ * the entire slider bar container and are rendered on top of the bar and
+ * bar container. The location of the marks correspond to the discrete
+ * values that the slider can have.
+ * @return {!Array} The array items have no type since this is used to
+ * create |markerCount| number of markers.
+ * @private
+ */
+ getMarkers_: function() {
+ return new Array(Math.max(0, this.markerCount - 1));
+ },
- /** @private */
- onBlur_: function() {
- this.$.slider.getRipple().holdDown = false;
- this.$.slider._resetKnob();
- },
+ /**
+ * @param {number} index
+ * @return {string}
+ * @private
+ */
+ getMarkerClass_: function(index) {
+ const currentStep = (this.markerCount - 1) * this.getRatio_();
+ return index < currentStep ? 'active-marker' : 'inactive-marker';
+ },
- /** @private */
- onChange_: function() {
- this.$.slider._setExpand(!this.usedMouse_);
- this.$.slider.getRipple().holdDown = !this.usedMouse_;
- this.usedMouse_ = false;
- },
+ /**
+ * The ratio is a value from 0 to 1.0 corresponding to a location along the
+ * slider bar where 0 is the minimum value and 1.0 is the maximum value.
+ * This is a helper function used to calculate the bar width, knob location
+ * and label location.
+ * @return {number}
+ * @private
+ */
+ getRatio_: function() {
+ return (this.immediateValue_ - this.min) / (this.max - this.min);
+ },
- /** @private */
- onKeyDown_: function() {
- this.usedMouse_ = false;
- if (!this.disabled)
- this.onFocus_();
- },
+ /** @private */
+ ensureValidValue_: function() {
+ if (this.immediateValue_ == undefined || this.value == undefined)
+ return;
+ let validValue = clamp(this.min, this.max, this.immediateValue_);
+ validValue = this.snaps ? Math.round(validValue) : validValue;
+ this.immediateValue_ = validValue;
+ if (!this.dragging || this.updateValueInstantly)
+ this.value = validValue;
+ },
- /**
- * @param {!MouseEvent} event
- * @private
- */
- onPointerDown_: function(event) {
- if (this.disabled || event.button != 0) {
- event.preventDefault();
- return;
- }
- this.usedMouse_ = true;
- setTimeout(() => {
- this.$.slider.getRipple().holdDown = true;
- });
- },
+ /**
+ * Removes all event listeners related to dragging, and cancels ripple.
+ * @param {number} pointerId
+ * @private
+ */
+ stopDragging_: function(pointerId) {
+ this.dragging = false;
+ this.draggingEventTracker_.removeAll();
+ this.value = this.immediateValue_;
+ // If there is a ripple animation in progress, setTimeout will hold off
+ // on updating |holdDown_|.
+ setTimeout(() => {
+ this.holdDown_ = false;
+ });
+ this.releasePointerCapture(pointerId);
+ },
- /**
- * @param {!MouseEvent} event
- * @private
- */
- onPointerUp_: function(event) {
- if (event.button != 0)
- return;
- this.$.slider.getRipple().holdDown = false;
- },
+ /** @private */
+ onBlur_: function() {
+ this.holdDown_ = false;
+ },
- /**
- * The style is being set in this way to keep the knob size the same
- * regardless of the state or properties set in the paper-slider. paper-slider
- * styles alter the size in multiple places making it difficult to introduce
- * one or two mixins to override the existing paper-slider knob styling.
- * @private
- */
- onDisabledChanged_: function() {
- const knob = this.$.slider.$$('.slider-knob-inner');
- knob.style.boxSizing = 'content-box';
- knob.style.height = '10px';
- knob.style.transform = 'unset';
- knob.style.transition = 'unset';
- knob.style.width = '10px';
- this.$.slider.$$('.bar-container').style.left = '0';
- if (this.disabled) {
- knob.style.backgroundColor = 'var(--google-grey-600)';
- knob.style.border = '2px solid white';
- knob.style.boxShadow = 'unset';
- knob.style.margin = '9px';
- } else {
- knob.style.backgroundColor = 'var(--google-blue-600)';
- knob.style.border = '0';
- knob.style.boxShadow = '0 1px 3px 0 rgba(0, 0, 0, 0.4)';
- knob.style.margin = '11px';
- }
- },
-
- /** @private */
- onImmediateValueChanged_: function() {
- // TODO(dpapad): Need to catch and refire the property changed event in
- // Polymer 2 only, since it does not bubble by default. Remove the
- // condition when migration to Polymer 2 is completed.
- if (Polymer.DomIf)
- this.fire('immediate-value-changed', this.immediateValue);
- },
+ /** @private */
+ onFocus_: function() {
+ this.holdDown_ = true;
+ },
- /**
- * TODO(scottchen): temporary fix until polymer gesture bug resolved. See:
- * https://github.com/PolymerElements/paper-slider/issues/186
- * @private
- */
- resetTrackLock_: function() {
- Polymer.Gestures.gestures.tap.reset();
- },
-});
+ /** @private */
+ onHoldDownChanged_: function() {
+ this.getRipple().holdDown = this.holdDown_;
+ },
+
+ /**
+ * @param {!Event} event
+ * @private
+ */
+ onKeyDown_: function(event) {
+ if (this.disabled)
+ return;
+
+ if (event.metaKey || event.shiftKey || event.altKey || event.ctrlKey)
+ return;
+
+ let handled = true;
+ if (event.key == 'Home')
+ this.value = this.min;
+ else if (event.key == 'End')
+ this.value = this.max;
+ else if (this.deltaKeyMap_.has(event.key)) {
+ const newValue = this.value + this.deltaKeyMap_.get(event.key);
+ this.value = clamp(this.min, this.max, newValue);
+ } else
+ handled = false;
+
+ if (handled) {
+ event.preventDefault();
+ setTimeout(() => {
+ this.holdDown_ = true;
+ });
+ }
+ },
+
+ /**
+ * When the left-mouse button is pressed, the knob location is updated and
+ * dragging starts.
+ * @param {!PointerEvent} event
+ * @private
+ */
+ onPointerDown_: function(event) {
+ if (this.disabled || event.buttons != 1 && event.pointerType == 'mouse')
+ return;
+
+ this.dragging = true;
+ // If there is a ripple animation in progress, setTimeout will hold off on
+ // updating |holdDown_|.
+ setTimeout(() => {
+ this.$.knob.focus();
+ this.holdDown_ = true;
+ });
+ this.updateValueFromClientX_(event.clientX);
+
+ this.setPointerCapture(event.pointerId);
+ const stopDragging = this.stopDragging_.bind(this, event.pointerId);
+
+ this.draggingEventTracker_.add(this, 'pointermove', e => {
+ // If the left-button on the mouse is pressed by itself, then update.
+ // Otherwise stop capturing the mouse events because the drag operation
+ // is complete.
+ if (e.buttons != 1 && e.pointerType == 'mouse') {
+ stopDragging();
+ return;
+ }
+ this.updateValueFromClientX_(e.clientX);
+ });
+ this.draggingEventTracker_.add(this, 'pointercancel', stopDragging);
+ this.draggingEventTracker_.add(this, 'pointerdown', stopDragging);
+ this.draggingEventTracker_.add(this, 'pointerup', stopDragging);
+ this.draggingEventTracker_.add(this, 'keydown', e => {
+ if (e.key == 'Escape' || e.key == 'Tab')
+ stopDragging();
+ });
+ },
+
+ /** @private */
+ onTicksChanged_: function() {
+ if (this.ticks.length == 0) {
+ this.disabled = false;
+ this.snaps = false;
+ } else if (this.ticks.length == 1) {
+ this.disabled = true;
+ } else {
+ this.disabled = false;
+ this.snaps = true;
+ this.max = this.ticks.length - 1;
+ this.min = 0;
+ }
+ this.ensureValidValue_();
+ this.updateLabelAndAria_();
+ },
+
+ /**
+ * Update |immediateValue_| which is used for rendering when |value| is
+ * updated either programmatically or from a keyboard input or a mouse drag
+ * (when |updateValueInstantly| is true).
+ * @private
+ */
+ onValueChanged_: function() {
+ if (this.immediateValue_ == this.value)
+ return;
+
+ this.immediateValue_ = this.value;
+ this.ensureValidValue_();
+ },
+
+ /** @private */
+ updateKnobAndBar_: function() {
+ const percent = `${this.getRatio_() * 100}%`;
+ this.$.bar.style.width = percent;
+ this.$.knob.style.marginInlineStart = percent;
+ },
+
+ /** @private */
+ updateLabelAndAria_: function() {
+ const ticks = this.ticks;
+ const index = this.immediateValue_;
+ if (!ticks || ticks.length == 0 || index >= ticks.length ||
+ !Number.isInteger(index) || !this.snaps) {
+ this.setAttribute('aria-valuetext', index);
+ this.setAttribute('aria-valuemin', this.min);
+ this.setAttribute('aria-valuemax', this.max);
+ this.setAttribute('aria-valuenow', index);
+ return;
+ }
+ const tick = ticks[index];
+ this.label_ = Number.isFinite(tick) ? '' : tick.label;
+
+ // Update label location after it has been rendered.
+ this.async(() => {
+ const label = this.$.label;
+ const parentWidth = label.parentElement.offsetWidth;
+ const labelWidth = label.offsetWidth;
+ // The left and right margin are 16px.
+ const margin = 16;
+ const knobLocation = parentWidth * this.getRatio_() + margin;
+ const offsetStart = knobLocation - (labelWidth / 2);
+ // The label should be centered over the knob. Clamping the offset to a
+ // min and max value prevents the label from being cutoff.
+ const max = parentWidth + 2 * margin - labelWidth;
+ label.style.marginInlineStart =
+ `${Math.round(clamp(0, max, offsetStart))}px`;
+ });
+
+ const ariaValues = [tick, ticks[0], ticks[ticks.length - 1]].map(t => {
+ if (Number.isFinite(t))
+ return t;
+ return Number.isFinite(t.ariaValue) ? t.ariaValue : t.value;
+ });
+ this.setAttribute(
+ 'aria-valuetext',
+ this.label_.length > 0 ? this.label_ : ariaValues[0]);
+ this.setAttribute('aria-valuenow', ariaValues[0]);
+ this.setAttribute('aria-valuemin', ariaValues[1]);
+ this.setAttribute('aria-valuemax', ariaValues[2]);
+ },
+
+ /**
+ * @param {number} clientX
+ * @private
+ */
+ updateValueFromClientX_: function(clientX) {
+ const rect = this.$.barContainer.getBoundingClientRect();
+ let ratio = (clientX - rect.left) / rect.width;
+ if (this.isRtl_)
+ ratio = 1 - ratio;
+ this.immediateValue_ = ratio * (this.max - this.min) + this.min;
+ this.ensureValidValue_();
+ },
+
+ _createRipple: function() {
+ this._rippleContainer = this.$.knob;
+ const ripple = Polymer.PaperRippleBehavior._createRipple();
+ ripple.id = 'ink';
+ ripple.setAttribute('recenters', '');
+ ripple.classList.add('circle', 'toggle-ink');
+ return ripple;
+ },
+ });
+})();
diff --git a/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html b/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html
index 635bfe77f64..0f03fdf8a69 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html
+++ b/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html
@@ -150,7 +150,6 @@
on-keydown="onSearchTermKeydown_"
on-focus="onInputFocus_"
on-blur="onInputBlur_"
- incremental
autofocus
spellcheck="false">
</div>
diff --git a/chromium/ui/webui/resources/cr_elements/cr_view_manager/BUILD.gn b/chromium/ui/webui/resources/cr_elements/cr_view_manager/BUILD.gn
new file mode 100644
index 00000000000..e1de4429a50
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/cr_view_manager/BUILD.gn
@@ -0,0 +1,19 @@
+# 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")
+
+js_type_check("closure_compile") {
+ deps = [
+ ":cr_view_manager",
+ ]
+}
+
+js_library("cr_view_manager") {
+ deps = [
+ "//ui/webui/resources/js:assert",
+ "//ui/webui/resources/js:cr",
+ ]
+ externs_list = [ "$externs_path/web_animations.js" ]
+}
diff --git a/chromium/ui/webui/resources/cr_elements/cr_view_manager/cr_view_manager.html b/chromium/ui/webui/resources/cr_elements/cr_view_manager/cr_view_manager.html
new file mode 100644
index 00000000000..45ff7d81938
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/cr_view_manager/cr_view_manager.html
@@ -0,0 +1,26 @@
+<link rel="import" href="../../html/polymer.html">
+
+<link rel="import" href="../../html/assert.html">
+<link rel="import" href="../../html/cr.html">
+
+<dom-module id="cr-view-manager">
+ <template>
+ <style>
+ :host ::slotted([slot=view]) {
+ bottom: 0;
+ display: none;
+ left: 0;
+ position: absolute;
+ right: 0;
+ top: 0;
+ }
+
+ :host ::slotted(.active),
+ :host ::slotted(.closing) {
+ display: block;
+ }
+ </style>
+ <slot name="view"></slot>
+ </template>
+ <script src="cr_view_manager.js"></script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_elements/cr_view_manager/cr_view_manager.js b/chromium/ui/webui/resources/cr_elements/cr_view_manager/cr_view_manager.js
new file mode 100644
index 00000000000..44f67b9877d
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/cr_view_manager/cr_view_manager.js
@@ -0,0 +1,115 @@
+// 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.
+
+(function() {
+/**
+ * TODO(scottchen): shim for not having Animation.finished implemented. Can
+ * replace with Animation.finished if Chrome implements it (see:
+ * crbug.com/257235).
+ * @param {!Animation} animation
+ * @return {!Promise}
+ */
+function whenFinished(animation) {
+ return new Promise(function(resolve, reject) {
+ animation.addEventListener('finish', resolve);
+ });
+}
+
+/** @type {!Map<string, function(!Element): !Promise>} */
+const viewAnimations = new Map();
+viewAnimations.set('no-animation', () => Promise.resolve());
+viewAnimations.set('fade-in', element => {
+ const animation = element.animate(
+ {
+ opacity: [0, 1],
+ },
+ /** @type {!KeyframeEffectOptions} */ ({
+ duration: 180,
+ easing: 'ease-in-out',
+ iterations: 1,
+ }));
+
+ return whenFinished(animation);
+});
+viewAnimations.set('fade-out', element => {
+ const animation = element.animate(
+ {
+ opacity: [1, 0],
+ },
+ /** @type {!KeyframeEffectOptions} */ ({
+ duration: 180,
+ easing: 'ease-in-out',
+ iterations: 1,
+ }));
+
+ return whenFinished(animation);
+});
+
+Polymer({
+ is: 'cr-view-manager',
+
+ /**
+ * @param {!Element} element
+ * @param {string} animation
+ * @return {!Promise}
+ * @private
+ */
+ exit_: function(element, animation) {
+ const animationFunction = viewAnimations.get(animation);
+ assert(animationFunction);
+
+ element.classList.remove('active');
+ element.classList.add('closing');
+ element.dispatchEvent(
+ new CustomEvent('view-exit-start', {bubbles: true, composed: true}));
+ return animationFunction(element).then(function() {
+ element.classList.remove('closing');
+ element.dispatchEvent(
+ new CustomEvent('view-exit-finish', {bubbles: true, composed: true}));
+ });
+ },
+
+ /**
+ * @param {!Element} view
+ * @param {string} animation
+ * @return {!Promise}
+ * @private
+ */
+ enter_: function(view, animation) {
+ const animationFunction = viewAnimations.get(animation);
+ assert(animationFunction);
+
+ let effectiveView = view.matches('cr-lazy-render') ? view.get() : view;
+
+ effectiveView.classList.add('active');
+ effectiveView.dispatchEvent(
+ new CustomEvent('view-enter-start', {bubbles: true, composed: true}));
+ return animationFunction(effectiveView).then(() => {
+ effectiveView.dispatchEvent(new CustomEvent(
+ 'view-enter-finish', {bubbles: true, composed: true}));
+ });
+ },
+
+ /**
+ * @param {string} newViewId
+ * @param {string=} enterAnimation
+ * @param {string=} exitAnimation
+ * @return {!Promise}
+ */
+ switchView: function(newViewId, enterAnimation, exitAnimation) {
+ const previousView = this.querySelector('.active');
+ const newView = assert(this.querySelector('#' + newViewId));
+
+ const promises = [];
+ if (previousView) {
+ promises.push(this.exit_(previousView, exitAnimation || 'fade-out'));
+ promises.push(this.enter_(newView, enterAnimation || 'fade-in'));
+ } else {
+ promises.push(this.enter_(newView, 'no-animation'));
+ }
+
+ return Promise.all(promises);
+ },
+});
+})(); \ No newline at end of file
diff --git a/chromium/ui/webui/resources/cr_elements/policy/BUILD.gn b/chromium/ui/webui/resources/cr_elements/policy/BUILD.gn
index 244f3a615eb..743f98969f3 100644
--- a/chromium/ui/webui/resources/cr_elements/policy/BUILD.gn
+++ b/chromium/ui/webui/resources/cr_elements/policy/BUILD.gn
@@ -54,6 +54,7 @@ js_library("cr_policy_network_indicator") {
deps = [
":cr_policy_indicator_behavior",
":cr_policy_network_behavior",
+ ":cr_tooltip_icon",
"../chromeos/network:cr_onc_types",
]
}
diff --git a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_behavior.js b/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_behavior.js
index eb89b2b66db..c20b1ca4ec6 100644
--- a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_behavior.js
+++ b/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_behavior.js
@@ -53,22 +53,42 @@ var CrPolicyNetworkBehavior = {
/**
* @param {!CrOnc.ManagedProperty|undefined} property
- * @return {boolean} True if the network property is enforced by a policy.
+ * @return {boolean} True if the network property is editable.
*/
- isNetworkPolicyEnforced: function(property) {
- if (!this.isNetworkPolicyControlled(property))
+ isEditable: function(property) {
+ // If the property is not a dictionary, then the property is not editable.
+ if (typeof property != 'object')
return false;
+
// If the property has a UserEditable sub-property, that determines whether
- // or not it is editable (not enforced).
+ // or not it is editable.
if (typeof property.UserEditable != 'undefined')
- return !property.UserEditable;
+ return property.UserEditable;
// Otherwise if the property has a DeviceEditable sub-property, check that.
if (typeof property.DeviceEditable != 'undefined')
- return !property.DeviceEditable;
+ return property.DeviceEditable;
+
+ // If no 'Editable' sub-property exists, the policy value is not editable.
+ return false;
+ },
+
+ /**
+ * @param {!CrOnc.ManagedProperty|undefined} property
+ * @return {boolean} True if the network property is enforced by a policy.
+ */
+ isNetworkPolicyEnforced: function(property) {
+ return this.isNetworkPolicyControlled(property) &&
+ !this.isEditable(property);
+ },
- // If no 'Editable' sub-property exists, the policy value is enforced.
- return true;
+ /**
+ * @param {!CrOnc.ManagedProperty|undefined} property
+ * @return {boolean} True if the network property is recommended by a policy.
+ */
+ isNetworkPolicyRecommended: function(property) {
+ return this.isNetworkPolicyControlled(property) &&
+ this.isEditable(property);
},
/**
diff --git a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js b/chromium/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js
index 447aa7fb810..b83f94971b0 100644
--- a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js
+++ b/chromium/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.js
@@ -78,4 +78,9 @@ Polymer({
return this.getIndicatorTooltip(
indicatorType, this.pref.controlledByName || '', matches);
},
+
+ /** @return {!Element} */
+ getFocusableElement: function() {
+ return this.$$('cr-tooltip-icon').getFocusableElement();
+ },
});
diff --git a/chromium/ui/webui/resources/cr_elements/policy/cr_tooltip_icon.js b/chromium/ui/webui/resources/cr_elements/policy/cr_tooltip_icon.js
index ba918fb0ca7..cd8cd9cc2ab 100644
--- a/chromium/ui/webui/resources/cr_elements/policy/cr_tooltip_icon.js
+++ b/chromium/ui/webui/resources/cr_elements/policy/cr_tooltip_icon.js
@@ -9,4 +9,9 @@ Polymer({
iconClass: String,
tooltipText: String,
},
+
+ /** @return {!Element} */
+ getFocusableElement: function() {
+ return this.$.indicator;
+ },
}); \ No newline at end of file
diff --git a/chromium/ui/webui/resources/cr_elements/shared_vars_css.html b/chromium/ui/webui/resources/cr_elements/shared_vars_css.html
index b98339dcb19..f774f420268 100644
--- a/chromium/ui/webui/resources/cr_elements/shared_vars_css.html
+++ b/chromium/ui/webui/resources/cr_elements/shared_vars_css.html
@@ -142,13 +142,15 @@
--cr-disabled-opacity: 0.38;
--cr-form-field-bottom-spacing: 16px;
--cr-form-field-label-font-size: 0.625rem;
+ --cr-form-field-label-height: 0.625rem;
+ --cr-form-field-label-line-height: 0.625rem;
--cr-form-field-label: {
color: var(--google-grey-refresh-700);
display: block;
font-size: var(--cr-form-field-label-font-size);
font-weight: 500;
letter-spacing: 0.4px;
- line-height: var(--cr-form-field-label-font-size);
+ line-height: var(--cr-form-field-label-line-height);
margin-bottom: 8px;
}
--google-blue-50: #E8F0FE;
diff --git a/chromium/ui/webui/resources/cr_elements_resources.grdp b/chromium/ui/webui/resources/cr_elements_resources.grdp
index 26c467315df..040b089fbef 100644
--- a/chromium/ui/webui/resources/cr_elements_resources.grdp
+++ b/chromium/ui/webui/resources/cr_elements_resources.grdp
@@ -126,6 +126,12 @@
file="cr_elements/cr_searchable_drop_down/cr_searchable_drop_down.js"
type="chrome_html"
compress="gzip" />
+ <structure name="IDR_CR_ELEMENTS_CR_VIEW_MANAGER_HTML"
+ file="cr_elements/cr_view_manager/cr_view_manager.html"
+ type="chrome_html" />
+ <structure name="IDR_CR_ELEMENTS_CR_VIEW_MANAGER_JS"
+ file="cr_elements/cr_view_manager/cr_view_manager.js"
+ type="chrome_html" />
<if expr="chromeos">
<structure name="IDR_CR_ELEMENTS_CHROMEOS_CR_PICTURE_CR_CAMERA_HTML"
file="cr_elements/chromeos/cr_picture/cr_camera.html"
diff --git a/chromium/ui/webui/resources/js/assert.js b/chromium/ui/webui/resources/js/assert.js
index 42fb523fb07..e46a056778e 100644
--- a/chromium/ui/webui/resources/js/assert.js
+++ b/chromium/ui/webui/resources/js/assert.js
@@ -22,6 +22,8 @@ function assert(condition, opt_message) {
message = message + ': ' + opt_message;
var error = new Error(message);
var global = function() {
+ /** @type {boolean} */
+ this.traceAssertionsForTesting;
return this;
}();
if (global.traceAssertionsForTesting)
diff --git a/chromium/ui/webui/resources/js/cr/ui/dialogs.js b/chromium/ui/webui/resources/js/cr/ui/dialogs.js
index 40e86f6c368..a2aff076194 100644
--- a/chromium/ui/webui/resources/js/cr/ui/dialogs.js
+++ b/chromium/ui/webui/resources/js/cr/ui/dialogs.js
@@ -19,6 +19,9 @@ cr.define('cr.ui.dialogs', function() {
this.previousActiveElement_ = null;
this.initDom_();
+
+ /** @private{boolean} */
+ this.showing_ = false;
}
/**
@@ -214,6 +217,7 @@ cr.define('cr.ui.dialogs', function() {
*/
BaseDialog.prototype.show_ = function(
title, opt_onOk, opt_onCancel, opt_onShow) {
+ this.showing_ = true;
// Make all outside nodes unfocusable while the dialog is active.
this.deactivatedNodes_ = this.findFocusableElements_(this.document_);
this.tabIndexes_ = this.deactivatedNodes_.map(function(n) {
@@ -239,10 +243,11 @@ cr.define('cr.ui.dialogs', function() {
var self = this;
setTimeout(function() {
- // Note that we control the opacity of the *container*, but the top/left
- // of the *frame*.
- self.container_.classList.add('shown');
- self.initialFocusElement_.focus();
+ // Check that hide() was not called in between.
+ if (self.showing_) {
+ self.container_.classList.add('shown');
+ self.initialFocusElement_.focus();
+ }
setTimeout(function() {
if (opt_onShow)
opt_onShow();
@@ -252,6 +257,7 @@ cr.define('cr.ui.dialogs', function() {
/** @param {Function=} opt_onHide */
BaseDialog.prototype.hide = function(opt_onHide) {
+ this.showing_ = false;
// Restore focusability.
for (var i = 0; i < this.deactivatedNodes_.length; i++) {
var node = this.deactivatedNodes_[i];
@@ -263,8 +269,6 @@ cr.define('cr.ui.dialogs', function() {
this.deactivatedNodes_ = null;
this.tabIndexes_ = null;
- // Note that we control the opacity of the *container*, but the top/left
- // of the *frame*.
this.container_.classList.remove('shown');
if (this.previousActiveElement_) {
@@ -277,9 +281,10 @@ cr.define('cr.ui.dialogs', function() {
var self = this;
setTimeout(function() {
// Wait until the transition is done before removing the dialog.
- // It is possible to show/hide/show/hide and have hide called twice
+ // Check show() was not called in between.
+ // It is also possible to show/hide/show/hide and have hide called twice
// and container_ already removed from parentNode_.
- if (self.parentNode_ === self.container_.parentNode)
+ if (!self.showing_ && self.parentNode_ === self.container_.parentNode)
self.parentNode_.removeChild(self.container_);
if (opt_onHide)
opt_onHide();
diff --git a/chromium/ui/webui/resources/js/cr/ui/focus_grid.js b/chromium/ui/webui/resources/js/cr/ui/focus_grid.js
index 000fb051966..de710112a36 100644
--- a/chromium/ui/webui/resources/js/cr/ui/focus_grid.js
+++ b/chromium/ui/webui/resources/js/cr/ui/focus_grid.js
@@ -25,7 +25,7 @@ cr.define('cr.ui', function() {
* focusable focusable focusable
*
* @constructor
- * @implements {cr.ui.FocusRow.Delegate}
+ * @implements {cr.ui.FocusRowDelegate}
*/
function FocusGrid() {
/** @type {!Array<!cr.ui.FocusRow>} */
diff --git a/chromium/ui/webui/resources/js/cr/ui/focus_row.js b/chromium/ui/webui/resources/js/cr/ui/focus_row.js
index 91399fb5250..8915b114a4a 100644
--- a/chromium/ui/webui/resources/js/cr/ui/focus_row.js
+++ b/chromium/ui/webui/resources/js/cr/ui/focus_row.js
@@ -14,84 +14,76 @@ cr.define('cr.ui', function() {
* If no items in this row are focused, the row can stay active until focus
* changes to a node inside |this.boundary_|. If |boundary| isn't specified,
* any focus change deactivates the row.
- *
- * @param {!Element} root The root of this focus row. Focus classes are
- * applied to |root| and all added elements must live within |root|.
- * @param {?Element} boundary Focus events are ignored outside of this
- * element.
- * @param {cr.ui.FocusRow.Delegate=} opt_delegate An optional event delegate.
- * @constructor
*/
- function FocusRow(root, boundary, opt_delegate) {
- /** @type {!Element} */
- this.root = root;
-
- /** @private {!Element} */
- this.boundary_ = boundary || document.documentElement;
-
- /** @type {cr.ui.FocusRow.Delegate|undefined} */
- this.delegate = opt_delegate;
-
- /** @protected {!EventTracker} */
- this.eventTracker = new EventTracker;
- }
-
- /** @interface */
- FocusRow.Delegate = function() {};
-
- FocusRow.Delegate.prototype = {
+ class FocusRow {
/**
- * Called when a key is pressed while on a FocusRow's item. If true is
- * returned, further processing is skipped.
- * @param {!cr.ui.FocusRow} row The row that detected a keydown.
- * @param {!Event} e
- * @return {boolean} Whether the event was handled.
+ * @param {!Element} root The root of this focus row. Focus classes are
+ * applied to |root| and all added elements must live within |root|.
+ * @param {?Element} boundary Focus events are ignored outside of this
+ * element.
+ * @param {cr.ui.FocusRowDelegate=} delegate An optional event
+ * delegate.
*/
- onKeydown: assertNotReached,
+ constructor(root, boundary, delegate) {
+ /** @type {!Element} */
+ this.root = root;
- /**
- * @param {!cr.ui.FocusRow} row
- * @param {!Event} e
- */
- onFocus: assertNotReached,
- };
+ /** @private {!Element} */
+ this.boundary_ = boundary || document.documentElement;
- /** @const {string} */
- FocusRow.ACTIVE_CLASS = 'focus-row-active';
+ /** @type {cr.ui.FocusRowDelegate|undefined} */
+ this.delegate = delegate;
- /**
- * Whether it's possible that |element| can be focused.
- * @param {Element} element
- * @return {boolean} Whether the item is focusable.
- */
- FocusRow.isFocusable = function(element) {
- if (!element || element.disabled)
- return false;
+ /** @protected {!EventTracker} */
+ this.eventTracker = new EventTracker;
+ }
- // We don't check that element.tabIndex >= 0 here because inactive rows set
- // a tabIndex of -1.
+ /**
+ * Whether it's possible that |element| can be focused.
+ * @param {Element} element
+ * @return {boolean} Whether the item is focusable.
+ */
+ static isFocusable(element) {
+ if (!element || element.disabled)
+ return false;
- function isVisible(element) {
- assertInstanceof(element, Element);
+ // We don't check that element.tabIndex >= 0 here because inactive rows
+ // set a tabIndex of -1.
+ let current = element;
+ while (true) {
+ assertInstanceof(current, Element);
- var style = window.getComputedStyle(element);
- if (style.visibility == 'hidden' || style.display == 'none')
- return false;
+ var style = window.getComputedStyle(current);
+ if (style.visibility == 'hidden' || style.display == 'none')
+ return false;
- var parent = element.parentNode;
- if (!parent)
- return false;
+ var parent = current.parentNode;
+ if (!parent)
+ return false;
- if (parent == element.ownerDocument || parent instanceof DocumentFragment)
- return true;
+ if (parent == current.ownerDocument ||
+ parent instanceof DocumentFragment)
+ return true;
- return isVisible(parent);
+ current = /** @type {Element} */ (parent);
+ }
}
- return isVisible(element);
- };
+ /**
+ * A focus override is a function that returns an element that should gain
+ * focus. The element may not be directly selectable for example the element
+ * that can gain focus is in a shadow DOM. Allowing an override via a
+ * function leaves the details of how the element is retrieved to the
+ * component.
+ * @param {!Element} element
+ * @return {!Element}
+ */
+ static getFocusableElement(element) {
+ if (element.getFocusableElement)
+ return element.getFocusableElement();
+ return element;
+ }
- FocusRow.prototype = {
/**
* Register a new type of focusable element (or add to an existing one).
*
@@ -100,7 +92,7 @@ cr.define('cr.ui', function() {
* When FocusRow is used within a FocusGrid, these types are used to
* determine equivalent controls when Up/Down are pressed to change rows.
*
- * Another example: mutually exclusive controls that hide eachother on
+ * Another example: mutually exclusive controls that hide each other on
* activation (i.e. Play/Pause) could use the same type (i.e. 'play-pause')
* to indicate they're equivalent.
*
@@ -109,7 +101,7 @@ cr.define('cr.ui', function() {
* from this row's root, or the element itself.
* @return {boolean} Whether a new item was added.
*/
- addItem: function(type, selectorOrElement) {
+ addItem(type, selectorOrElement) {
assert(type);
var element;
@@ -128,30 +120,30 @@ cr.define('cr.ui', function() {
this.eventTracker.add(element, 'keydown', this.onKeydown_.bind(this));
this.eventTracker.add(element, 'mousedown', this.onMousedown_.bind(this));
return true;
- },
+ }
/** Dereferences nodes and removes event handlers. */
- destroy: function() {
+ destroy() {
this.eventTracker.removeAll();
- },
+ }
/**
* @param {!Element} sampleElement An element for to find an equivalent for.
* @return {!Element} An equivalent element to focus for |sampleElement|.
* @protected
*/
- getCustomEquivalent: function(sampleElement) {
+ getCustomEquivalent(sampleElement) {
return assert(this.getFirstFocusable());
- },
+ }
/**
* @return {!Array<!Element>} All registered elements (regardless of
* focusability).
*/
- getElements: function() {
- var elements = this.root.querySelectorAll('[focus-type]');
- return Array.prototype.slice.call(elements);
- },
+ getElements() {
+ return Array.from(this.root.querySelectorAll('[focus-type]'))
+ .map(cr.ui.FocusRow.getFocusableElement);
+ }
/**
* Find the element that best matches |sampleElement|.
@@ -159,7 +151,7 @@ cr.define('cr.ui', function() {
* which previously held focus.
* @return {!Element} The element that best matches sampleElement.
*/
- getEquivalentElement: function(sampleElement) {
+ getEquivalentElement(sampleElement) {
if (this.getFocusableElements().indexOf(sampleElement) >= 0)
return sampleElement;
@@ -171,46 +163,42 @@ cr.define('cr.ui', function() {
}
return this.getCustomEquivalent(sampleElement);
- },
+ }
/**
* @param {string=} opt_type An optional type to search for.
* @return {?Element} The first focusable element with |type|.
*/
- getFirstFocusable: function(opt_type) {
- var filter = opt_type ? '="' + opt_type + '"' : '';
- var elements = this.root.querySelectorAll('[focus-type' + filter + ']');
- for (var i = 0; i < elements.length; ++i) {
- if (cr.ui.FocusRow.isFocusable(elements[i]))
- return elements[i];
- }
- return null;
- },
+ getFirstFocusable(opt_type) {
+ const element = this.getFocusableElements().find(
+ el => !opt_type || el.getAttribute('focus-type') == opt_type);
+ return element || null;
+ }
/** @return {!Array<!Element>} Registered, focusable elements. */
- getFocusableElements: function() {
+ getFocusableElements() {
return this.getElements().filter(cr.ui.FocusRow.isFocusable);
- },
+ }
/**
* @param {!Element} element An element to determine a focus type for.
* @return {string} The focus type for |element| or '' if none.
*/
- getTypeForElement: function(element) {
+ getTypeForElement(element) {
return element.getAttribute('focus-type') || '';
- },
+ }
/** @return {boolean} Whether this row is currently active. */
- isActive: function() {
+ isActive() {
return this.root.classList.contains(FocusRow.ACTIVE_CLASS);
- },
+ }
/**
* Enables/disables the tabIndex of the focusable elements in the FocusRow.
* tabIndex can be set properly.
* @param {boolean} active True if tab is allowed for this row.
*/
- makeActive: function(active) {
+ makeActive(active) {
if (active == this.isActive())
return;
@@ -219,35 +207,35 @@ cr.define('cr.ui', function() {
});
this.root.classList.toggle(FocusRow.ACTIVE_CLASS, active);
- },
+ }
/**
* @param {!Event} e
* @private
*/
- onBlur_: function(e) {
+ onBlur_(e) {
if (!this.boundary_.contains(/** @type {Element} */ (e.relatedTarget)))
return;
var currentTarget = /** @type {!Element} */ (e.currentTarget);
if (this.getFocusableElements().indexOf(currentTarget) >= 0)
this.makeActive(false);
- },
+ }
/**
* @param {!Event} e
* @private
*/
- onFocus_: function(e) {
+ onFocus_(e) {
if (this.delegate)
this.delegate.onFocus(this, e);
- },
+ }
/**
* @param {!Event} e A mousedown event.
* @private
*/
- onMousedown_: function(e) {
+ onMousedown_(e) {
// Only accept left mouse clicks.
if (e.button)
return;
@@ -255,13 +243,13 @@ cr.define('cr.ui', function() {
// Allow the element under the mouse cursor to be focusable.
if (!e.currentTarget.disabled)
e.currentTarget.tabIndex = 0;
- },
+ }
/**
* @param {!Event} e The keydown event.
* @private
*/
- onKeydown_: function(e) {
+ onKeydown_(e) {
var elements = this.getFocusableElements();
var currentElement = /** @type {!Element} */ (e.currentTarget);
var elementIndex = elements.indexOf(currentElement);
@@ -289,10 +277,33 @@ cr.define('cr.ui', function() {
this.getEquivalentElement(elementToFocus).focus();
e.preventDefault();
}
- },
- };
+ }
+ }
+
+ /** @const {string} */
+ FocusRow.ACTIVE_CLASS = 'focus-row-active';
+
+
+ /** @interface */
+ class FocusRowDelegate {
+ /**
+ * Called when a key is pressed while on a FocusRow's item. If true is
+ * returned, further processing is skipped.
+ * @param {!cr.ui.FocusRow} row The row that detected a keydown.
+ * @param {!Event} e
+ * @return {boolean} Whether the event was handled.
+ */
+ onKeydown(row, e) {}
+
+ /**
+ * @param {!cr.ui.FocusRow} row
+ * @param {!Event} e
+ */
+ onFocus(row, e) {}
+ }
return {
- FocusRow: FocusRow,
+ FocusRow,
+ FocusRowDelegate,
};
});
diff --git a/chromium/ui/webui/resources/js/util.js b/chromium/ui/webui/resources/js/util.js
index a5099bf9b56..7139d9baede 100644
--- a/chromium/ui/webui/resources/js/util.js
+++ b/chromium/ui/webui/resources/js/util.js
@@ -33,6 +33,18 @@ function getSVGElement(id) {
}
/**
+ * @return {?Element} The currently focused element (including elements that are
+ * behind a shadow root), or null if nothing is focused.
+ */
+function getDeepActiveElement() {
+ var a = document.activeElement;
+ while (a && a.shadowRoot && a.shadowRoot.activeElement) {
+ a = a.shadowRoot.activeElement;
+ }
+ return a;
+}
+
+/**
* Add an accessible message to the page that will be announced to
* users who have spoken feedback on, but will be invisible to all
* other users. It's removed right away so it doesn't clutter the DOM.
diff --git a/chromium/ui/webui/resources/js/webui_resource_test.js b/chromium/ui/webui/resources/js/webui_resource_test.js
index ed8d79e401c..ea7089b0bac 100644
--- a/chromium/ui/webui/resources/js/webui_resource_test.js
+++ b/chromium/ui/webui/resources/js/webui_resource_test.js
@@ -116,9 +116,28 @@ function assertDeepEquals(expected, observed, opt_message) {
}
/**
- * Defines runTests.
+ * Decorates |window| with runTests() and endTests().
+ *
+ * @param {{
+ * runTests: (function(Object=):void|undefined),
+ * endTests: (function(boolean):void|undefined)
+ * }} exports
*/
(function(exports) {
+
+/**
+ * Optional setup and teardown hooks that can be defined in a test scope.
+ * |setUpPage| is invoked once. |setUp|/|tearDown| are invoked before/after each
+ * test*() declared in the test scope.
+ *
+ * @typedef {{
+ * setUpPage: (function(): void|undefined),
+ * setUp: (function(): void|undefined),
+ * tearDown: (function(): void|undefined),
+ * }}
+ */
+var WebUiTestHarness;
+
/**
* Scope containing testXXX functions.
* @type {!Object}
@@ -126,6 +145,12 @@ function assertDeepEquals(expected, observed, opt_message) {
var testScope = {};
/**
+ * Test harness entrypoints on |testScope|.
+ * @type {!WebUiTestHarness}
+ */
+var testHarness = {};
+
+/**
* List of test cases.
* @type {Array<string>} List of function names for tests to run.
*/
@@ -170,6 +195,7 @@ var runnerStartTime = 0;
function runTests(opt_testScope) {
runnerStartTime = performance.now();
testScope = opt_testScope || window;
+ testHarness = /** @type{!WebUiTestHarness} */ (testScope);
for (var name in testScope) {
// To avoid unnecessary getting properties, test name first.
if (/^test/.test(name) && typeof testScope[name] == 'function')
@@ -180,11 +206,22 @@ function runTests(opt_testScope) {
cleanTestRun = false;
}
try {
- if (testScope.setUpPage)
- testScope.setUpPage();
+ if (testHarness.setUpPage)
+ testHarness.setUpPage();
} catch (err) {
cleanTestRun = false;
}
+ startTesting();
+}
+
+/**
+ * @suppress {missingProperties}
+ */
+function startTesting() {
+ if (window.waitUser) {
+ setTimeout(startTesting, 1000);
+ return;
+ }
continueTesting();
}
@@ -216,9 +253,9 @@ function continueTesting(opt_asyncTestFailure) {
var isAsyncTest = testScope[testName].length;
var testError = false;
try {
- if (testScope.setUp)
- testScope.setUp();
- pendingTearDown = testScope.tearDown || null;
+ if (testHarness.setUp)
+ testHarness.setUp();
+ pendingTearDown = testHarness.tearDown || null;
testScope[testName](continueTesting);
} catch (err) {
console.error('Failure in test ' + testName + '\n' + err);
@@ -257,6 +294,16 @@ exports.runTests = runTests;
exports.endTests = endTests;
})(window);
+/**
+ * @type {!function(Object=):void}
+ */
+window.runTests;
+
+/**
+ * @type {!function(boolean):void}
+ */
+window.endTests;
+
window.onerror = function() {
window.endTests(false);
};
diff --git a/chromium/ui/webui/resources/webui_resources.grd b/chromium/ui/webui/resources/webui_resources.grd
index a24f4983bf4..a2b2e2d14bc 100644
--- a/chromium/ui/webui/resources/webui_resources.grd
+++ b/chromium/ui/webui/resources/webui_resources.grd
@@ -200,6 +200,7 @@ without changes to the corresponding grd file. -->
file="images/trash.png" type="BINDATA" />
<if expr="not is_android">
+ <part file="cr_components/cr_components_images.grdp" />
<part file="cr_elements_images.grdp" />
</if>
</includes>
diff --git a/chromium/ui/wm/BUILD.gn b/chromium/ui/wm/BUILD.gn
index 3df69ca6fc4..38d53f54b50 100644
--- a/chromium/ui/wm/BUILD.gn
+++ b/chromium/ui/wm/BUILD.gn
@@ -98,7 +98,7 @@ jumbo_component("wm") {
}
}
-static_library("test_support") {
+jumbo_static_library("test_support") {
testonly = true
sources = [
"test/testing_cursor_client_observer.cc",
@@ -113,6 +113,7 @@ static_library("test_support") {
"//services/ws/public/cpp",
"//services/ws/public/cpp/input_devices",
"//services/ws/public/mojom",
+ "//services/ws/test_ws:mojom",
"//skia",
"//ui/aura",
"//ui/aura:test_support",
@@ -130,7 +131,6 @@ test("wm_unittests") {
"core/compound_event_filter_unittest.cc",
"core/coordinate_conversion_unittest.cc",
"core/cursor_manager_unittest.cc",
- "core/easy_resize_window_targeter_unittest.cc",
"core/focus_controller_unittest.cc",
"core/shadow_controller_unittest.cc",
"core/transient_window_manager_unittest.cc",
diff --git a/chromium/ui/wm/core/base_focus_rules.cc b/chromium/ui/wm/core/base_focus_rules.cc
index 73e95142f12..eb446ee0fc9 100644
--- a/chromium/ui/wm/core/base_focus_rules.cc
+++ b/chromium/ui/wm/core/base_focus_rules.cc
@@ -178,9 +178,7 @@ aura::Window* BaseFocusRules::GetNextActivatableWindow(
const aura::Window::Windows& siblings = ignore->parent()->children();
DCHECK(!siblings.empty());
- for (aura::Window::Windows::const_reverse_iterator rit = siblings.rbegin();
- rit != siblings.rend();
- ++rit) {
+ for (auto rit = siblings.rbegin(); rit != siblings.rend(); ++rit) {
aura::Window* cur = *rit;
if (cur == ignore)
continue;
diff --git a/chromium/ui/wm/core/easy_resize_window_targeter.cc b/chromium/ui/wm/core/easy_resize_window_targeter.cc
index 2ada01797de..7707c2d2df7 100644
--- a/chromium/ui/wm/core/easy_resize_window_targeter.cc
+++ b/chromium/ui/wm/core/easy_resize_window_targeter.cc
@@ -6,104 +6,23 @@
#include <algorithm>
-#include "services/ws/public/mojom/window_manager.mojom.h"
+#include "services/ws/public/mojom/window_tree_constants.mojom.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/transient_window_client.h"
-#include "ui/aura/env.h"
-#include "ui/aura/mus/window_port_mus.h"
-#include "ui/aura/mus/window_tree_client.h"
#include "ui/aura/window.h"
#include "ui/events/event.h"
-#include "ui/gfx/geometry/insets_f.h"
-#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/insets.h"
namespace wm {
-namespace {
-
-gfx::Insets InsetsWithOnlyPositiveValues(const gfx::Insets& insets) {
- return gfx::Insets(std::max(0, insets.top()), std::max(0, insets.left()),
- std::max(0, insets.bottom()), std::max(0, insets.right()));
-}
-
-} // namespace
-
-// HitMaskSetter is responsible for setting the hit-test mask on a Window.
-class EasyResizeWindowTargeter::HitMaskSetter : public aura::WindowObserver {
- public:
- explicit HitMaskSetter(aura::Window* window) : window_(window) {
- window_->AddObserver(this);
- }
- ~HitMaskSetter() override {
- if (window_) {
- aura::WindowPortMus::Get(window_)->SetHitTestMask(base::nullopt);
- window_->RemoveObserver(this);
- }
- }
-
- void SetHitMaskInsets(const gfx::Insets& insets) {
- if (insets == insets_)
- return;
-
- insets_ = insets;
- ApplyHitTestMask();
- }
-
- private:
- void ApplyHitTestMask() {
- base::Optional<gfx::Rect> hit_test_mask(
- gfx::Rect(window_->bounds().size()));
- hit_test_mask->Inset(insets_);
- aura::WindowPortMus::Get(window_)->SetHitTestMask(hit_test_mask);
- }
-
- // aura::WindowObserver:
- void OnWindowDestroying(aura::Window* window) override {
- window_->RemoveObserver(this);
- window_ = nullptr;
- }
- void OnWindowBoundsChanged(aura::Window* window,
- const gfx::Rect& old_bounds,
- const gfx::Rect& new_bounds,
- ui::PropertyChangeReason reason) override {
- ApplyHitTestMask();
- }
-
- private:
- aura::Window* window_;
- gfx::Insets insets_;
-
- DISALLOW_COPY_AND_ASSIGN(HitMaskSetter);
-};
EasyResizeWindowTargeter::EasyResizeWindowTargeter(
- aura::Window* container,
const gfx::Insets& mouse_extend,
- const gfx::Insets& touch_extend)
- : container_(container) {
- DCHECK(container_);
+ const gfx::Insets& touch_extend) {
SetInsets(mouse_extend, touch_extend);
}
EasyResizeWindowTargeter::~EasyResizeWindowTargeter() {}
-void EasyResizeWindowTargeter::OnSetInsets(
- const gfx::Insets& last_mouse_extend,
- const gfx::Insets& last_touch_extend) {
- if (container_->env()->mode() != aura::Env::Mode::MUS)
- return;
-
- // Positive values equate to a hit test mask.
- const gfx::Insets positive_mouse_insets =
- InsetsWithOnlyPositiveValues(mouse_extend());
- if (positive_mouse_insets.IsEmpty()) {
- hit_mask_setter_.reset();
- } else {
- if (!hit_mask_setter_)
- hit_mask_setter_ = std::make_unique<HitMaskSetter>(container_);
- hit_mask_setter_->SetHitMaskInsets(positive_mouse_insets);
- }
-}
-
bool EasyResizeWindowTargeter::EventLocationInsideBounds(
aura::Window* target,
const ui::LocatedEvent& event) const {
@@ -111,28 +30,28 @@ bool EasyResizeWindowTargeter::EventLocationInsideBounds(
}
bool EasyResizeWindowTargeter::ShouldUseExtendedBounds(
- const aura::Window* window) const {
- // Use the extended bounds only for immediate child windows of |container_|.
+ const aura::Window* w) const {
+ DCHECK(window());
+ // Use the extended bounds only for immediate child windows of window().
// Use the default targeter otherwise.
- if (window->parent() != container_)
+ if (w->parent() != window())
return false;
// Only resizable windows benefit from the extended hit-test region.
- if ((window->GetProperty(aura::client::kResizeBehaviorKey) &
+ if ((w->GetProperty(aura::client::kResizeBehaviorKey) &
ws::mojom::kResizeBehaviorCanResize) == 0) {
return false;
}
// For transient children use extended bounds if a transient parent or if
- // transient parent's parent is a top level window in |container_|.
+ // transient parent's parent is a top level window in window().
aura::client::TransientWindowClient* transient_window_client =
aura::client::GetTransientWindowClient();
const aura::Window* transient_parent =
- transient_window_client
- ? transient_window_client->GetTransientParent(window)
- : nullptr;
- return !transient_parent || transient_parent == container_ ||
- transient_parent->parent() == container_;
+ transient_window_client ? transient_window_client->GetTransientParent(w)
+ : nullptr;
+ return !transient_parent || transient_parent == window() ||
+ transient_parent->parent() == window();
}
} // namespace wm
diff --git a/chromium/ui/wm/core/easy_resize_window_targeter.h b/chromium/ui/wm/core/easy_resize_window_targeter.h
index d8ffa701b3b..560c4b26f60 100644
--- a/chromium/ui/wm/core/easy_resize_window_targeter.h
+++ b/chromium/ui/wm/core/easy_resize_window_targeter.h
@@ -7,44 +7,36 @@
#include "base/macros.h"
#include "ui/aura/window_targeter.h"
-#include "ui/gfx/geometry/insets.h"
#include "ui/wm/core/wm_core_export.h"
+namespace gfx {
+class Insets;
+}
+
namespace wm {
// An EventTargeter for a container window that uses a slightly larger
-// hit-target region for easier resize.
-// TODO(sky): make this class final.
+// hit-target region for easier resize. It extends the hit test region for child
+// windows (top level Widgets that are resizable) to outside their bounds. For
+// Ash, this correlates to ash::kResizeOutsideBoundsSize. For the interior
+// resize area, see ash::wm::InstallResizeHandleWindowTargeterForWindow().
class WM_CORE_EXPORT EasyResizeWindowTargeter : public aura::WindowTargeter {
public:
- // |container| window is the owner of this targeter.
// NOTE: the insets must be negative.
- EasyResizeWindowTargeter(aura::Window* container,
- const gfx::Insets& mouse_extend,
+ EasyResizeWindowTargeter(const gfx::Insets& mouse_extend,
const gfx::Insets& touch_extend);
~EasyResizeWindowTargeter() override;
- protected:
- // aura::WindowTargeter:
- void OnSetInsets(const gfx::Insets& last_mouse_extend,
- const gfx::Insets& last_touch_extend) override;
-
private:
- class HitMaskSetter;
-
// aura::WindowTargeter:
// Delegates to WindowTargeter's impl and prevents overriding in subclasses.
bool EventLocationInsideBounds(aura::Window* target,
- const ui::LocatedEvent& event) const final;
+ const ui::LocatedEvent& event) const override;
// Returns true if the hit testing (GetHitTestRects()) should use the
// extended bounds.
- bool ShouldUseExtendedBounds(const aura::Window* window) const override;
-
- aura::Window* container_;
-
- std::unique_ptr<HitMaskSetter> hit_mask_setter_;
+ bool ShouldUseExtendedBounds(const aura::Window* w) const override;
DISALLOW_COPY_AND_ASSIGN(EasyResizeWindowTargeter);
};
diff --git a/chromium/ui/wm/core/easy_resize_window_targeter_unittest.cc b/chromium/ui/wm/core/easy_resize_window_targeter_unittest.cc
deleted file mode 100644
index a8cb4edf258..00000000000
--- a/chromium/ui/wm/core/easy_resize_window_targeter_unittest.cc
+++ /dev/null
@@ -1,66 +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/wm/core/easy_resize_window_targeter.h"
-
-#include "ui/aura/mus/window_port_mus.h"
-#include "ui/aura/test/aura_mus_test_base.h"
-#include "ui/aura/test/mus/test_window_tree.h"
-#include "ui/aura/window.h"
-#include "ui/compositor/layer_type.h"
-#include "ui/gfx/geometry/insets.h"
-#include "ui/gfx/geometry/rect.h"
-
-namespace wm {
-
-namespace {
-
-class TestEasyResizeWindowTargeter : public EasyResizeWindowTargeter {
- public:
- explicit TestEasyResizeWindowTargeter(aura::Window* window)
- : EasyResizeWindowTargeter(window, gfx::Insets(), gfx::Insets()) {}
-};
-
-} // namespace
-
-using EasyResizeWindowTargeterTest = aura::test::AuraMusClientTestBase;
-
-TEST_F(EasyResizeWindowTargeterTest, SetHitTestMask) {
- aura::Window window(nullptr);
- window.Init(ui::LAYER_NOT_DRAWN);
- TestEasyResizeWindowTargeter window_targeter(&window);
- const gfx::Rect bounds1 = gfx::Rect(10, 20, 200, 300);
- window.SetBounds(bounds1);
- const gfx::Insets insets1(1, 2, 3, 4);
- window_targeter.SetInsets(insets1, insets1);
- ASSERT_TRUE(window_tree()->last_hit_test_mask().has_value());
- EXPECT_EQ(gfx::Rect(insets1.left(), insets1.top(),
- bounds1.width() - insets1.width(),
- bounds1.height() - insets1.height()),
- *window_tree()->last_hit_test_mask());
-
- // Adjusting the bounds should trigger resetting the mask.
- const gfx::Rect bounds2 = gfx::Rect(10, 20, 300, 400);
- window.SetBounds(bounds2);
- ASSERT_TRUE(window_tree()->last_hit_test_mask().has_value());
- EXPECT_EQ(gfx::Rect(insets1.left(), insets1.top(),
- bounds2.width() - insets1.width(),
- bounds2.height() - insets1.height()),
- *window_tree()->last_hit_test_mask());
-
- // Empty insets should reset the mask.
- window_targeter.SetInsets(gfx::Insets(), gfx::Insets());
- EXPECT_FALSE(window_tree()->last_hit_test_mask().has_value());
-
- const gfx::Insets insets2(-1, 3, 4, 5);
- const gfx::Insets effective_insets2(0, 3, 4, 5);
- window_targeter.SetInsets(insets2, insets2);
- ASSERT_TRUE(window_tree()->last_hit_test_mask().has_value());
- EXPECT_EQ(gfx::Rect(effective_insets2.left(), effective_insets2.top(),
- bounds2.width() - effective_insets2.width(),
- bounds2.height() - effective_insets2.height()),
- *window_tree()->last_hit_test_mask());
-}
-
-} // namespace wm
diff --git a/chromium/ui/wm/core/transient_window_manager.cc b/chromium/ui/wm/core/transient_window_manager.cc
index dd65f45d603..80a57bab880 100644
--- a/chromium/ui/wm/core/transient_window_manager.cc
+++ b/chromium/ui/wm/core/transient_window_manager.cc
@@ -84,7 +84,7 @@ void TransientWindowManager::AddTransientChild(Window* child) {
}
void TransientWindowManager::RemoveTransientChild(Window* child) {
- Windows::iterator i =
+ auto i =
std::find(transient_children_.begin(), transient_children_.end(), child);
DCHECK(i != transient_children_.end());
transient_children_.erase(i);
@@ -131,8 +131,7 @@ void TransientWindowManager::RestackTransientDescendants() {
// |window_|. The existing stacking order is preserved by iterating backwards
// and always stacking on top.
Window::Windows children(parent->children());
- for (Window::Windows::reverse_iterator it = children.rbegin();
- it != children.rend(); ++it) {
+ for (auto it = children.rbegin(); it != children.rend(); ++it) {
if ((*it) != window_ && HasTransientAncestor(*it, window_)) {
TransientWindowManager* descendant_manager = GetOrCreate(*it);
base::AutoReset<Window*> resetter(
@@ -205,10 +204,8 @@ void TransientWindowManager::OnWindowStackingChanged(Window* window) {
// Do nothing if we initiated the stacking change.
const TransientWindowManager* transient_manager = GetIfExists(window);
if (transient_manager && transient_manager->stacking_target_) {
- Windows::const_iterator window_i = std::find(
- window->parent()->children().begin(),
- window->parent()->children().end(),
- window);
+ auto window_i = std::find(window->parent()->children().begin(),
+ window->parent()->children().end(), window);
DCHECK(window_i != window->parent()->children().end());
if (window_i != window->parent()->children().begin() &&
(*(window_i - 1) == transient_manager->stacking_target_))
diff --git a/chromium/ui/wm/core/transient_window_stacking_client.cc b/chromium/ui/wm/core/transient_window_stacking_client.cc
index 18110983413..ff3737626b6 100644
--- a/chromium/ui/wm/core/transient_window_stacking_client.cc
+++ b/chromium/ui/wm/core/transient_window_stacking_client.cc
@@ -45,8 +45,8 @@ void FindCommonTransientAncestor(Window** window1, Window** window2) {
return;
}
// Walk the two chains backwards and look for the first difference.
- Window::Windows::reverse_iterator it1 = ancestors1.rbegin();
- Window::Windows::reverse_iterator it2 = ancestors2.rbegin();
+ auto it1 = ancestors1.rbegin();
+ auto it2 = ancestors2.rbegin();
for (; it1 != ancestors1.rend() && it2 != ancestors2.rend(); ++it1, ++it2) {
if (*it1 != *it2) {
*window1 = *it1;
diff --git a/chromium/ui/wm/core/window_animations.cc b/chromium/ui/wm/core/window_animations.cc
index 7b18c37fbda..d61a35a8b6c 100644
--- a/chromium/ui/wm/core/window_animations.cc
+++ b/chromium/ui/wm/core/window_animations.cc
@@ -35,17 +35,13 @@
#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/geometry/vector3d_f.h"
#include "ui/gfx/interpolated_transform.h"
+#include "ui/wm/core/window_properties.h"
#include "ui/wm/core/window_util.h"
#include "ui/wm/core/wm_core_switches.h"
#include "ui/wm/public/animation_host.h"
-DEFINE_UI_CLASS_PROPERTY_TYPE(::wm::WindowVisibilityAnimationType)
-DEFINE_UI_CLASS_PROPERTY_TYPE(::wm::WindowVisibilityAnimationTransition)
-DEFINE_UI_CLASS_PROPERTY_TYPE(float)
-
namespace wm {
namespace {
-const float kWindowAnimation_Vertical_TranslateY = 15.f;
// A base class for hiding animation observer which has two roles:
// 1) Notifies AnimationHost at the end of hiding animation.
@@ -89,10 +85,8 @@ class HidingWindowAnimationObserverBase : public aura::WindowObserver {
if (window_->parent()) {
const aura::Window::Windows& transient_children =
GetTransientChildren(window_);
- aura::Window::Windows::const_iterator iter =
- std::find(window_->parent()->children().begin(),
- window_->parent()->children().end(),
- window_);
+ auto iter = std::find(window_->parent()->children().begin(),
+ window_->parent()->children().end(), window_);
DCHECK(iter != window_->parent()->children().end());
aura::Window* topmost_transient_child = NULL;
for (++iter; iter != window_->parent()->children().end(); ++iter) {
@@ -161,19 +155,6 @@ base::LazyInstance<HidingWindowMetricsReporter>::Leaky g_reporter_hide =
} // namespace
-DEFINE_UI_CLASS_PROPERTY_KEY(int,
- kWindowVisibilityAnimationTypeKey,
- WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT);
-DEFINE_UI_CLASS_PROPERTY_KEY(base::TimeDelta,
- kWindowVisibilityAnimationDurationKey,
- base::TimeDelta());
-DEFINE_UI_CLASS_PROPERTY_KEY(WindowVisibilityAnimationTransition,
- kWindowVisibilityAnimationTransitionKey,
- ANIMATE_BOTH);
-DEFINE_UI_CLASS_PROPERTY_KEY(float,
- kWindowVisibilityAnimationVerticalPositionKey,
- kWindowAnimation_Vertical_TranslateY);
-
// A HidingWindowAnimationObserver that deletes observer and detached
// layers upon the completion of the implicit animation.
class ImplicitHidingWindowAnimationObserver
diff --git a/chromium/ui/wm/core/window_animations.h b/chromium/ui/wm/core/window_animations.h
index 598623482c8..2881b15fd52 100644
--- a/chromium/ui/wm/core/window_animations.h
+++ b/chromium/ui/wm/core/window_animations.h
@@ -9,6 +9,7 @@
#include "base/macros.h"
#include "ui/compositor/scoped_layer_animation_settings.h"
+#include "ui/wm/core/window_properties.h"
#include "ui/wm/core/wm_core_export.h"
namespace aura {
@@ -40,15 +41,6 @@ enum WindowAnimationType {
WINDOW_ANIMATION_TYPE_BOUNCE = 0, // Window scales up and down.
};
-// Type of visibility change transition that a window should animate.
-// Default behavior is to animate both show and hide.
-enum WindowVisibilityAnimationTransition {
- ANIMATE_SHOW = 0x1,
- ANIMATE_HIDE = 0x2,
- ANIMATE_BOTH = ANIMATE_SHOW | ANIMATE_HIDE,
- ANIMATE_NONE = 0x4,
-};
-
// These two methods use int for type rather than WindowVisibilityAnimationType
// since downstream libraries can extend the set of animations.
WM_CORE_EXPORT void SetWindowVisibilityAnimationType(aura::Window* window,
diff --git a/chromium/ui/wm/core/window_animations_unittest.cc b/chromium/ui/wm/core/window_animations_unittest.cc
index 3b8a82470fb..f8e993a6814 100644
--- a/chromium/ui/wm/core/window_animations_unittest.cc
+++ b/chromium/ui/wm/core/window_animations_unittest.cc
@@ -31,8 +31,7 @@ namespace {
template<typename T>int GetZPosition(const T* child) {
const T* parent = child->parent();
const std::vector<T*> children = parent->children();
- typename std::vector<T*>::const_iterator iter =
- std::find(children.begin(), children.end(), child);
+ auto iter = std::find(children.begin(), children.end(), child);
DCHECK(iter != children.end());
return iter - children.begin();
}
diff --git a/chromium/ui/wm/core/window_properties.cc b/chromium/ui/wm/core/window_properties.cc
index bfa24b8ce82..3cc7b6859e7 100644
--- a/chromium/ui/wm/core/window_properties.cc
+++ b/chromium/ui/wm/core/window_properties.cc
@@ -4,9 +4,28 @@
#include "ui/wm/core/window_properties.h"
+#include "ui/wm/core/window_animations.h"
+
+DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(WM_CORE_EXPORT,
+ wm::WindowVisibilityAnimationTransition)
+
+DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(WM_CORE_EXPORT, float)
+
namespace wm {
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kSnapChildrenToPixelBoundary, false);
DEFINE_UI_CLASS_PROPERTY_KEY(bool, kUsesScreenCoordinatesKey, false);
+DEFINE_UI_CLASS_PROPERTY_KEY(base::TimeDelta,
+ kWindowVisibilityAnimationDurationKey,
+ base::TimeDelta());
+DEFINE_UI_CLASS_PROPERTY_KEY(WindowVisibilityAnimationTransition,
+ kWindowVisibilityAnimationTransitionKey,
+ ANIMATE_BOTH);
+DEFINE_UI_CLASS_PROPERTY_KEY(int,
+ kWindowVisibilityAnimationTypeKey,
+ WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT);
+DEFINE_UI_CLASS_PROPERTY_KEY(float,
+ kWindowVisibilityAnimationVerticalPositionKey,
+ 15.f);
} // namespace wm
diff --git a/chromium/ui/wm/core/window_properties.h b/chromium/ui/wm/core/window_properties.h
index 1eb15dea40b..ec2268067ec 100644
--- a/chromium/ui/wm/core/window_properties.h
+++ b/chromium/ui/wm/core/window_properties.h
@@ -10,6 +10,15 @@
namespace wm {
+// Type of visibility change transition that a window should animate.
+// Default behavior is to animate both show and hide.
+enum WindowVisibilityAnimationTransition {
+ ANIMATE_SHOW = 0x1,
+ ANIMATE_HIDE = 0x2,
+ ANIMATE_BOTH = ANIMATE_SHOW | ANIMATE_HIDE,
+ ANIMATE_NONE = 0x4,
+};
+
// Alphabetical sort.
// Containers with this property (true) are aligned with physical pixel
@@ -22,6 +31,25 @@ WM_CORE_EXPORT extern const ui::ClassProperty<bool>* const
WM_CORE_EXPORT extern const ui::ClassProperty<bool>* const
kUsesScreenCoordinatesKey;
+WM_CORE_EXPORT extern const ui::ClassProperty<base::TimeDelta>* const
+ kWindowVisibilityAnimationDurationKey;
+
+WM_CORE_EXPORT extern const ui::ClassProperty<
+ WindowVisibilityAnimationTransition>* const
+ kWindowVisibilityAnimationTransitionKey;
+
+WM_CORE_EXPORT extern const ui::ClassProperty<int>* const
+ kWindowVisibilityAnimationTypeKey;
+
+// Used if the animation-type is WINDOW_VISIBILITY_ANIMATION_TYPE_VERTICAL.
+WM_CORE_EXPORT extern const ui::ClassProperty<float>* const
+ kWindowVisibilityAnimationVerticalPositionKey;
+
} // namespace wm
+// These need to be declared here for jumbo builds.
+DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(WM_CORE_EXPORT,
+ wm::WindowVisibilityAnimationTransition)
+DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(WM_CORE_EXPORT, float)
+
#endif // UI_WM_CORE_WINDOW_PROPERTIES_H_
diff --git a/chromium/ui/wm/public/BUILD.gn b/chromium/ui/wm/public/BUILD.gn
index a60f7da5cb9..799fb90a7b7 100644
--- a/chromium/ui/wm/public/BUILD.gn
+++ b/chromium/ui/wm/public/BUILD.gn
@@ -12,7 +12,6 @@ jumbo_component("public") {
"activation_client.h",
"activation_delegate.h",
"animation_host.h",
- "scoped_drag_drop_disabler.h",
"scoped_tooltip_disabler.h",
"tooltip_client.h",
"window_move_client.h",
@@ -23,7 +22,6 @@ jumbo_component("public") {
"activation_client.cc",
"activation_delegate.cc",
"animation_host.cc",
- "scoped_drag_drop_disabler.cc",
"scoped_tooltip_disabler.cc",
"tooltip_client.cc",
"window_move_client.cc",
diff --git a/chromium/ui/wm/public/scoped_drag_drop_disabler.cc b/chromium/ui/wm/public/scoped_drag_drop_disabler.cc
deleted file mode 100644
index 2f30f647510..00000000000
--- a/chromium/ui/wm/public/scoped_drag_drop_disabler.cc
+++ /dev/null
@@ -1,53 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/wm/public/scoped_drag_drop_disabler.h"
-
-#include "ui/aura/client/drag_drop_client.h"
-#include "ui/aura/window.h"
-
-namespace wm {
-
-class NopDragDropClient : public aura::client::DragDropClient {
- public:
- ~NopDragDropClient() override {}
- int StartDragAndDrop(const ui::OSExchangeData& data,
- aura::Window* root_window,
- aura::Window* source_window,
- const gfx::Point& screen_location,
- int operation,
- ui::DragDropTypes::DragEventSource source) override {
- return 0;
- }
- void DragCancel() override {}
- bool IsDragDropInProgress() override {
- return false;
- }
- void AddObserver(aura::client::DragDropClientObserver* observer) override {}
- void RemoveObserver(aura::client::DragDropClientObserver* observer) override {
- }
-};
-
-ScopedDragDropDisabler::ScopedDragDropDisabler(aura::Window* window)
- : window_(window),
- old_client_(aura::client::GetDragDropClient(window)),
- new_client_(new NopDragDropClient()) {
- SetDragDropClient(window_, new_client_.get());
- window_->AddObserver(this);
-}
-
-ScopedDragDropDisabler::~ScopedDragDropDisabler() {
- if (window_) {
- window_->RemoveObserver(this);
- SetDragDropClient(window_, old_client_);
- }
-}
-
-void ScopedDragDropDisabler::OnWindowDestroyed(aura::Window* window) {
- CHECK_EQ(window_, window);
- window_ = NULL;
- new_client_.reset();
-}
-
-} // namespace wm
diff --git a/chromium/ui/wm/public/scoped_drag_drop_disabler.h b/chromium/ui/wm/public/scoped_drag_drop_disabler.h
deleted file mode 100644
index 13207b1890d..00000000000
--- a/chromium/ui/wm/public/scoped_drag_drop_disabler.h
+++ /dev/null
@@ -1,45 +0,0 @@
-// Copyright 2015 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_WM_PUBLIC_SCOPED_DRAG_DROP_DISABLER_H_
-#define UI_WM_PUBLIC_SCOPED_DRAG_DROP_DISABLER_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "ui/aura/window_observer.h"
-#include "ui/wm/public/wm_public_export.h"
-
-namespace aura {
-class Window;
-
-namespace client {
-class DragDropClient;
-}
-}
-
-namespace wm {
-
-// ScopedDragDropDisabler is used to temporarily replace the drag'n'drop client
-// for a window with a "no-op" client. Upon construction, it installs a new
-// client on the window, and upon destruction, it restores the previous one.
-class WM_PUBLIC_EXPORT ScopedDragDropDisabler : public aura::WindowObserver {
- public:
- explicit ScopedDragDropDisabler(aura::Window* window);
- ~ScopedDragDropDisabler() override;
-
- private:
- // WindowObserver:
- void OnWindowDestroyed(aura::Window* window) override;
-
- aura::Window* window_;
- aura::client::DragDropClient* old_client_;
- std::unique_ptr<aura::client::DragDropClient> new_client_;
-
- DISALLOW_COPY_AND_ASSIGN(ScopedDragDropDisabler);
-};
-
-} // namespace wm
-
-#endif // UI_WM_PUBLIC_SCOPED_DRAG_DROP_DISABLER_H_