summaryrefslogtreecommitdiff
path: root/chromium/ui
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2017-11-20 10:33:36 +0100
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2017-11-22 11:45:12 +0000
commitbe59a35641616a4cf23c4a13fa0632624b021c1b (patch)
tree9da183258bdf9cc413f7562079d25ace6955467f /chromium/ui
parentd702e4b6a64574e97fc7df8fe3238cde70242080 (diff)
downloadqtwebengine-chromium-be59a35641616a4cf23c4a13fa0632624b021c1b.tar.gz
BASELINE: Update Chromium to 62.0.3202.101
Change-Id: I2d5eca8117600df6d331f6166ab24d943d9814ac Reviewed-by: Alexandru Croitor <alexandru.croitor@qt.io>
Diffstat (limited to 'chromium/ui')
-rw-r--r--chromium/ui/accelerated_widget_mac/display_link_mac.cc18
-rw-r--r--chromium/ui/accelerated_widget_mac/io_surface_context.mm3
-rw-r--r--chromium/ui/accessibility/BUILD.gn7
-rw-r--r--chromium/ui/accessibility/OWNERS3
-rw-r--r--chromium/ui/accessibility/PRESUBMIT.py114
-rw-r--r--chromium/ui/accessibility/ax_action_data.cc2
-rw-r--r--chromium/ui/accessibility/ax_action_data.h9
-rw-r--r--chromium/ui/accessibility/ax_enums.idl58
-rw-r--r--chromium/ui/accessibility/ax_event_generator.cc305
-rw-r--r--chromium/ui/accessibility/ax_event_generator.h161
-rw-r--r--chromium/ui/accessibility/ax_event_generator_unittest.cc567
-rw-r--r--chromium/ui/accessibility/ax_mode_observer.h23
-rw-r--r--chromium/ui/accessibility/ax_modes.h92
-rw-r--r--chromium/ui/accessibility/ax_node_data.cc22
-rw-r--r--chromium/ui/accessibility/ax_node_position_unittest.cc1052
-rw-r--r--chromium/ui/accessibility/ax_position.h298
-rw-r--r--chromium/ui/accessibility/ax_role_properties.cc1
-rw-r--r--chromium/ui/accessibility/ax_tree.cc26
-rw-r--r--chromium/ui/accessibility/ax_tree.h1
-rw-r--r--chromium/ui/accessibility/ax_tree_unittest.cc27
-rw-r--r--chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_ca.xtb6
-rw-r--r--chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_id.xtb10
-rw-r--r--chromium/ui/accessibility/platform/atk_util_auralinux.cc75
-rw-r--r--chromium/ui/accessibility/platform/atk_util_auralinux.h15
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node.cc38
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node.h21
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_auralinux.cc10
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_auralinux.h10
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_base.cc130
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_base.h42
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_delegate.h8
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_mac.h4
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_mac.mm42
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_win.cc1510
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_win.h191
-rw-r--r--chromium/ui/accessibility/platform/ax_platform_node_win_unittest.cc855
-rw-r--r--chromium/ui/accessibility/platform/ax_snapshot_node_android_platform.cc216
-rw-r--r--chromium/ui/accessibility/platform/ax_snapshot_node_android_platform.h2
-rw-r--r--chromium/ui/accessibility/platform/ax_system_caret_win.cc7
-rw-r--r--chromium/ui/accessibility/platform/ax_system_caret_win.h6
-rw-r--r--chromium/ui/accessibility/platform/test_ax_node_wrapper.cc9
-rw-r--r--chromium/ui/accessibility/platform/test_ax_node_wrapper.h6
-rw-r--r--chromium/ui/android/BUILD.gn27
-rw-r--r--chromium/ui/android/DEPS3
-rw-r--r--chromium/ui/android/OWNERS1
-rw-r--r--chromium/ui/android/delegated_frame_host_android.cc38
-rw-r--r--chromium/ui/android/delegated_frame_host_android.h30
-rw-r--r--chromium/ui/android/display_android_manager.cc11
-rw-r--r--chromium/ui/android/event_forwarder.cc26
-rw-r--r--chromium/ui/android/event_forwarder.h2
-rw-r--r--chromium/ui/android/overscroll_glow.cc8
-rw-r--r--chromium/ui/android/overscroll_glow.h11
-rw-r--r--chromium/ui/android/overscroll_refresh.cc13
-rw-r--r--chromium/ui/android/overscroll_refresh.h22
-rw-r--r--chromium/ui/android/overscroll_refresh_unittest.cc19
-rw-r--r--chromium/ui/android/resources/resource_factory.cc6
-rw-r--r--chromium/ui/android/resources/resource_factory.h16
-rw-r--r--chromium/ui/android/resources/resource_manager_impl.cc5
-rw-r--r--chromium/ui/android/resources/resource_manager_impl.h2
-rw-r--r--chromium/ui/android/run_all_unittests.cc5
-rw-r--r--chromium/ui/android/screen_android.h2
-rw-r--r--chromium/ui/android/view_android.cc87
-rw-r--r--chromium/ui/android/view_android.h30
-rw-r--r--chromium/ui/android/view_android_observer.h28
-rw-r--r--chromium/ui/android/view_android_unittests.cc65
-rw-r--r--chromium/ui/android/view_client.cc3
-rw-r--r--chromium/ui/android/view_client.h3
-rw-r--r--chromium/ui/android/window_android.cc53
-rw-r--r--chromium/ui/android/window_android.h17
-rw-r--r--chromium/ui/android/window_android_compositor.h4
-rw-r--r--chromium/ui/app_list/BUILD.gn1
-rw-r--r--chromium/ui/app_list/presenter/app_list_presenter.mojom32
-rw-r--r--chromium/ui/arc/BUILD.gn4
-rw-r--r--chromium/ui/arc/notification/arc_notification_content_view.cc75
-rw-r--r--chromium/ui/arc/notification/arc_notification_content_view.h3
-rw-r--r--chromium/ui/arc/notification/arc_notification_content_view_delegate.h2
-rw-r--r--chromium/ui/arc/notification/arc_notification_content_view_unittest.cc411
-rw-r--r--chromium/ui/arc/notification/arc_notification_item.h2
-rw-r--r--chromium/ui/arc/notification/arc_notification_item_impl.cc5
-rw-r--r--chromium/ui/arc/notification/arc_notification_item_impl.h3
-rw-r--r--chromium/ui/arc/notification/arc_notification_manager.cc7
-rw-r--r--chromium/ui/arc/notification/arc_notification_surface_impl.cc81
-rw-r--r--chromium/ui/arc/notification/arc_notification_surface_impl.h4
-rw-r--r--chromium/ui/arc/notification/arc_notification_view.cc45
-rw-r--r--chromium/ui/arc/notification/arc_notification_view.h8
-rw-r--r--chromium/ui/arc/notification/arc_notification_view_unittest.cc2
-rw-r--r--chromium/ui/aura/BUILD.gn8
-rw-r--r--chromium/ui/aura/DEPS1
-rw-r--r--chromium/ui/aura/client/aura_constants.cc3
-rw-r--r--chromium/ui/aura/client/aura_constants.h3
-rw-r--r--chromium/ui/aura/client/drag_drop_client.h8
-rw-r--r--chromium/ui/aura/client/drag_drop_client_observer.h28
-rw-r--r--chromium/ui/aura/env.cc8
-rw-r--r--chromium/ui/aura/env_input_state_controller.h4
-rw-r--r--chromium/ui/aura/gestures/gesture_recognizer_unittest.cc8
-rw-r--r--chromium/ui/aura/local/DEPS1
-rw-r--r--chromium/ui/aura/local/layer_tree_frame_sink_local.cc57
-rw-r--r--chromium/ui/aura/local/layer_tree_frame_sink_local.h33
-rw-r--r--chromium/ui/aura/local/window_port_local.cc50
-rw-r--r--chromium/ui/aura/local/window_port_local.h14
-rw-r--r--chromium/ui/aura/mus/DEPS12
-rw-r--r--chromium/ui/aura/mus/client_surface_embedder.cc4
-rw-r--r--chromium/ui/aura/mus/drag_drop_controller_mus.cc26
-rw-r--r--chromium/ui/aura/mus/drag_drop_controller_mus.h8
-rw-r--r--chromium/ui/aura/mus/drag_drop_controller_mus_unittest.cc170
-rw-r--r--chromium/ui/aura/mus/hit_test_data_provider_aura.cc133
-rw-r--r--chromium/ui/aura/mus/hit_test_data_provider_aura.h41
-rw-r--r--chromium/ui/aura/mus/hit_test_data_provider_aura_unittest.cc290
-rw-r--r--chromium/ui/aura/mus/in_flight_change.h1
-rw-r--r--chromium/ui/aura/mus/mus_context_factory.cc8
-rw-r--r--chromium/ui/aura/mus/mus_context_factory.h3
-rw-r--r--chromium/ui/aura/mus/os_exchange_data_provider_mus.cc2
-rw-r--r--chromium/ui/aura/mus/os_exchange_data_provider_mus.h2
-rw-r--r--chromium/ui/aura/mus/user_activity_forwarder.h2
-rw-r--r--chromium/ui/aura/mus/user_activity_forwarder_unittest.cc3
-rw-r--r--chromium/ui/aura/mus/window_manager_delegate.cc2
-rw-r--r--chromium/ui/aura/mus/window_manager_delegate.h26
-rw-r--r--chromium/ui/aura/mus/window_mus.h13
-rw-r--r--chromium/ui/aura/mus/window_port_mus.cc62
-rw-r--r--chromium/ui/aura/mus/window_port_mus.h18
-rw-r--r--chromium/ui/aura/mus/window_tree_client.cc294
-rw-r--r--chromium/ui/aura/mus/window_tree_client.h49
-rw-r--r--chromium/ui/aura/mus/window_tree_client_unittest.cc252
-rw-r--r--chromium/ui/aura/mus/window_tree_host_mus.cc39
-rw-r--r--chromium/ui/aura/mus/window_tree_host_mus.h4
-rw-r--r--chromium/ui/aura/mus/window_tree_host_mus_delegate.h6
-rw-r--r--chromium/ui/aura/window.cc48
-rw-r--r--chromium/ui/aura/window.h27
-rw-r--r--chromium/ui/aura/window_delegate.h4
-rw-r--r--chromium/ui/aura/window_event_dispatcher.cc24
-rw-r--r--chromium/ui/aura/window_event_dispatcher_unittest.cc95
-rw-r--r--chromium/ui/aura/window_port.h15
-rw-r--r--chromium/ui/aura/window_port_for_shutdown.cc12
-rw-r--r--chromium/ui/aura/window_port_for_shutdown.h8
-rw-r--r--chromium/ui/aura/window_targeter.cc71
-rw-r--r--chromium/ui/aura/window_targeter.h49
-rw-r--r--chromium/ui/aura/window_tree_host.cc42
-rw-r--r--chromium/ui/aura/window_tree_host.h11
-rw-r--r--chromium/ui/aura/window_tree_host_mac.h53
-rw-r--r--chromium/ui/aura/window_tree_host_mac.mm105
-rw-r--r--chromium/ui/aura/window_tree_host_observer.h8
-rw-r--r--chromium/ui/aura/window_tree_host_platform.cc4
-rw-r--r--chromium/ui/aura/window_tree_host_platform.h5
-rw-r--r--chromium/ui/aura/window_tree_host_unittest.cc8
-rw-r--r--chromium/ui/aura/window_tree_host_x11.cc12
-rw-r--r--chromium/ui/aura/window_unittest.cc55
-rw-r--r--chromium/ui/base/BUILD.gn17
-rw-r--r--chromium/ui/base/accelerators/accelerator_manager.cc26
-rw-r--r--chromium/ui/base/accelerators/accelerator_manager.h2
-rw-r--r--chromium/ui/base/accelerators/accelerator_manager_unittest.cc6
-rw-r--r--chromium/ui/base/class_property.h14
-rw-r--r--chromium/ui/base/class_property_unittest.cc48
-rw-r--r--chromium/ui/base/clipboard/clipboard.h16
-rw-r--r--chromium/ui/base/clipboard/clipboard_android.cc4
-rw-r--r--chromium/ui/base/clipboard/clipboard_android.h3
-rw-r--r--chromium/ui/base/clipboard/clipboard_fuchsia.cc281
-rw-r--r--chromium/ui/base/clipboard/clipboard_fuchsia.h71
-rw-r--r--chromium/ui/base/clipboard/clipboard_monitor.h3
-rw-r--r--chromium/ui/base/cocoa/hover_button.h32
-rw-r--r--chromium/ui/base/cocoa/hover_button.mm110
-rw-r--r--chromium/ui/base/cocoa/hover_button_unittest.mm199
-rw-r--r--chromium/ui/base/cocoa/menu_controller.mm40
-rw-r--r--chromium/ui/base/cocoa/menu_controller_unittest.mm161
-rw-r--r--chromium/ui/base/cocoa/touch_bar_util.h8
-rw-r--r--chromium/ui/base/cursor/cursor_loader.h1
-rw-r--r--chromium/ui/base/cursor/cursor_loader_ozone.cc4
-rw-r--r--chromium/ui/base/cursor/ozone/cursor_data_factory_ozone.cc4
-rw-r--r--chromium/ui/base/cursor/ozone/cursor_data_factory_ozone.h2
-rw-r--r--chromium/ui/base/dragdrop/os_exchange_data.h2
-rw-r--r--chromium/ui/base/dragdrop/os_exchange_data_provider_factory.cc9
-rw-r--r--chromium/ui/base/dragdrop/os_exchange_data_provider_win.cc6
-rw-r--r--chromium/ui/base/idle/idle_fuchsia.cc23
-rw-r--r--chromium/ui/base/ime/BUILD.gn30
-rw-r--r--chromium/ui/base/ime/composition_text.cc15
-rw-r--r--chromium/ui/base/ime/composition_text.h21
-rw-r--r--chromium/ui/base/ime/composition_text_unittest.cc42
-rw-r--r--chromium/ui/base/ime/composition_text_util_pango.cc33
-rw-r--r--chromium/ui/base/ime/composition_text_util_pango_unittest.cc22
-rw-r--r--chromium/ui/base/ime/composition_underline.h68
-rw-r--r--chromium/ui/base/ime/ime_text_span.cc46
-rw-r--r--chromium/ui/base/ime/ime_text_span.h79
-rw-r--r--chromium/ui/base/ime/input_method_auralinux.cc12
-rw-r--r--chromium/ui/base/ime/input_method_base.h2
-rw-r--r--chromium/ui/base/ime/input_method_chromeos.cc58
-rw-r--r--chromium/ui/base/ime/mock_ime_input_context_handler.cc2
-rw-r--r--chromium/ui/base/ime/mock_input_method.h3
-rw-r--r--chromium/ui/base/ime/win/imm32_manager.cc74
-rw-r--r--chromium/ui/base/l10n/l10n_util.cc2
-rw-r--r--chromium/ui/base/l10n/l10n_util_android.cc4
-rw-r--r--chromium/ui/base/l10n/l10n_util_android.h2
-rw-r--r--chromium/ui/base/material_design/material_design_controller.cc2
-rw-r--r--chromium/ui/base/models/button_menu_item_model.h3
-rw-r--r--chromium/ui/base/models/simple_menu_model.h3
-rw-r--r--chromium/ui/base/page_transition_types.h4
-rw-r--r--chromium/ui/base/resource/data_pack.cc226
-rw-r--r--chromium/ui/base/resource/data_pack.h7
-rw-r--r--chromium/ui/base/resource/data_pack_literal.cc100
-rw-r--r--chromium/ui/base/resource/data_pack_literal.h23
-rw-r--r--chromium/ui/base/resource/data_pack_unittest.cc53
-rw-r--r--chromium/ui/base/resource/resource_bundle.cc5
-rw-r--r--chromium/ui/base/resource/resource_bundle_unittest.cc13
-rw-r--r--chromium/ui/base/ui_base_switches.cc49
-rw-r--r--chromium/ui/base/ui_base_switches.h21
-rw-r--r--chromium/ui/base/ui_features.gni3
-rw-r--r--chromium/ui/base/user_activity/user_activity_detector_unittest.cc24
-rw-r--r--chromium/ui/base/webui/OWNERS2
-rw-r--r--chromium/ui/base/win/accessibility_misc_utils.h2
-rw-r--r--chromium/ui/base/win/shell.cc20
-rw-r--r--chromium/ui/base/x/x11_util.cc6
-rw-r--r--chromium/ui/chromeos/BUILD.gn2
-rw-r--r--chromium/ui/compositor/BUILD.gn12
-rw-r--r--chromium/ui/compositor/DEPS5
-rw-r--r--chromium/ui/compositor/canvas_painter.cc8
-rw-r--r--chromium/ui/compositor/canvas_painter.h3
-rw-r--r--chromium/ui/compositor/clip_recorder.cc26
-rw-r--r--chromium/ui/compositor/compositing_recorder.cc10
-rw-r--r--chromium/ui/compositor/compositor.cc100
-rw-r--r--chromium/ui/compositor/compositor.h66
-rw-r--r--chromium/ui/compositor/compositor_constants.h18
-rw-r--r--chromium/ui/compositor/compositor_switches.cc13
-rw-r--r--chromium/ui/compositor/compositor_switches.h4
-rw-r--r--chromium/ui/compositor/compositor_unittest.cc12
-rw-r--r--chromium/ui/compositor/compositor_util.cc46
-rw-r--r--chromium/ui/compositor/compositor_util.h24
-rw-r--r--chromium/ui/compositor/external_begin_frame_client.h23
-rw-r--r--chromium/ui/compositor/layer.cc73
-rw-r--r--chromium/ui/compositor/layer.h52
-rw-r--r--chromium/ui/compositor/layer_animation_delegate.h2
-rw-r--r--chromium/ui/compositor/layer_animation_element.cc84
-rw-r--r--chromium/ui/compositor/layer_animation_element.h8
-rw-r--r--chromium/ui/compositor/layer_animation_element_unittest.cc14
-rw-r--r--chromium/ui/compositor/layer_animation_sequence.cc20
-rw-r--r--chromium/ui/compositor/layer_animation_sequence.h4
-rw-r--r--chromium/ui/compositor/layer_animation_sequence_unittest.cc41
-rw-r--r--chromium/ui/compositor/layer_animator.cc13
-rw-r--r--chromium/ui/compositor/layer_animator.h17
-rw-r--r--chromium/ui/compositor/layer_animator_unittest.cc172
-rw-r--r--chromium/ui/compositor/layer_observer.h2
-rw-r--r--chromium/ui/compositor/layer_owner_unittest.cc3
-rw-r--r--chromium/ui/compositor/layer_unittest.cc42
-rw-r--r--chromium/ui/compositor/paint_cache.cc19
-rw-r--r--chromium/ui/compositor/paint_cache.h7
-rw-r--r--chromium/ui/compositor/paint_context.cc14
-rw-r--r--chromium/ui/compositor/paint_context.h12
-rw-r--r--chromium/ui/compositor/paint_recorder.cc38
-rw-r--r--chromium/ui/compositor/paint_recorder.h4
-rw-r--r--chromium/ui/compositor/scoped_layer_animation_settings.cc43
-rw-r--r--chromium/ui/compositor/scoped_layer_animation_settings.h3
-rw-r--r--chromium/ui/compositor/test/test_compositor_host_ozone.cc3
-rw-r--r--chromium/ui/compositor/transform_animation_curve_adapter_unittest.cc3
-rw-r--r--chromium/ui/compositor/transform_recorder.cc10
-rw-r--r--chromium/ui/display/BUILD.gn10
-rw-r--r--chromium/ui/display/display.cc30
-rw-r--r--chromium/ui/display/display.h6
-rw-r--r--chromium/ui/display/display_switches.cc12
-rw-r--r--chromium/ui/display/display_switches.h9
-rw-r--r--chromium/ui/display/display_unittest.cc25
-rw-r--r--chromium/ui/display/fake_display_delegate.cc27
-rw-r--r--chromium/ui/display/fake_display_delegate.h11
-rw-r--r--chromium/ui/display/fake_display_snapshot.cc70
-rw-r--r--chromium/ui/display/fake_display_snapshot.h10
-rw-r--r--chromium/ui/display/mac/screen_mac.mm6
-rw-r--r--chromium/ui/display/manager/BUILD.gn30
-rw-r--r--chromium/ui/display/manager/chromeos/DEPS1
-rw-r--r--chromium/ui/display/manager/chromeos/default_touch_transform_setter.cc16
-rw-r--r--chromium/ui/display/manager/chromeos/default_touch_transform_setter.h3
-rw-r--r--chromium/ui/display/manager/chromeos/display_change_observer.cc173
-rw-r--r--chromium/ui/display/manager/chromeos/display_change_observer.h8
-rw-r--r--chromium/ui/display/manager/chromeos/display_change_observer_unittest.cc3
-rw-r--r--chromium/ui/display/manager/chromeos/display_configurator.cc78
-rw-r--r--chromium/ui/display/manager/chromeos/display_configurator.h32
-rw-r--r--chromium/ui/display/manager/chromeos/display_configurator_unittest.cc444
-rw-r--r--chromium/ui/display/manager/chromeos/display_layout_manager.h12
-rw-r--r--chromium/ui/display/manager/chromeos/mojo/BUILD.gn15
-rw-r--r--chromium/ui/display/manager/chromeos/mojo/OWNERS8
-rw-r--r--chromium/ui/display/manager/chromeos/mojo/touch_device_transform.typemap15
-rw-r--r--chromium/ui/display/manager/chromeos/mojo/typemaps.gni6
-rw-r--r--chromium/ui/display/manager/chromeos/touch_device_transform.h26
-rw-r--r--chromium/ui/display/manager/chromeos/touch_transform_controller.cc23
-rw-r--r--chromium/ui/display/manager/chromeos/touch_transform_controller.h15
-rw-r--r--chromium/ui/display/manager/chromeos/touch_transform_controller_unittest.cc167
-rw-r--r--chromium/ui/display/manager/chromeos/touch_transform_setter.h11
-rw-r--r--chromium/ui/display/manager/chromeos/update_display_configuration_task.cc19
-rw-r--r--chromium/ui/display/manager/chromeos/update_display_configuration_task.h17
-rw-r--r--chromium/ui/display/manager/chromeos/update_display_configuration_task_unittest.cc90
-rw-r--r--chromium/ui/display/manager/chromeos/x11/DEPS4
-rw-r--r--chromium/ui/display/manager/chromeos/x11/display_mode_x11.cc24
-rw-r--r--chromium/ui/display/manager/chromeos/x11/display_mode_x11.h37
-rw-r--r--chromium/ui/display/manager/chromeos/x11/display_snapshot_x11.cc61
-rw-r--r--chromium/ui/display/manager/chromeos/x11/display_snapshot_x11.h62
-rw-r--r--chromium/ui/display/manager/chromeos/x11/display_util_x11.cc43
-rw-r--r--chromium/ui/display/manager/chromeos/x11/display_util_x11.h25
-rw-r--r--chromium/ui/display/manager/chromeos/x11/display_util_x11_unittest.cc68
-rw-r--r--chromium/ui/display/manager/chromeos/x11/native_display_delegate_x11.cc656
-rw-r--r--chromium/ui/display/manager/chromeos/x11/native_display_delegate_x11.h182
-rw-r--r--chromium/ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11.cc117
-rw-r--r--chromium/ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11.h55
-rw-r--r--chromium/ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11_unittest.cc325
-rw-r--r--chromium/ui/display/manager/display_layout_store.cc2
-rw-r--r--chromium/ui/display/manager/display_manager.cc54
-rw-r--r--chromium/ui/display/manager/display_manager.h13
-rw-r--r--chromium/ui/display/manager/forwarding_display_delegate.cc31
-rw-r--r--chromium/ui/display/manager/forwarding_display_delegate.h19
-rw-r--r--chromium/ui/display/manager/managed_display_info.cc18
-rw-r--r--chromium/ui/display/manager/managed_display_info.h24
-rw-r--r--chromium/ui/display/mojo/BUILD.gn2
-rw-r--r--chromium/ui/display/mojo/display_snapshot.mojom (renamed from chromium/ui/display/mojo/display_snapshot_mojo.mojom)4
-rw-r--r--chromium/ui/display/mojo/display_snapshot.typemap17
-rw-r--r--chromium/ui/display/mojo/display_snapshot_mojo.typemap17
-rw-r--r--chromium/ui/display/mojo/display_snapshot_struct_traits.cc (renamed from chromium/ui/display/mojo/display_snapshot_mojo_struct_traits.cc)35
-rw-r--r--chromium/ui/display/mojo/display_snapshot_struct_traits.h (renamed from chromium/ui/display/mojo/display_snapshot_mojo_struct_traits.h)46
-rw-r--r--chromium/ui/display/mojo/display_struct_traits_unittest.cc72
-rw-r--r--chromium/ui/display/mojo/native_display_delegate.mojom7
-rw-r--r--chromium/ui/display/mojo/typemaps.gni2
-rw-r--r--chromium/ui/display/types/BUILD.gn2
-rw-r--r--chromium/ui/display/types/display_constants.h10
-rw-r--r--chromium/ui/display/types/display_snapshot.cc89
-rw-r--r--chromium/ui/display/types/display_snapshot.h11
-rw-r--r--chromium/ui/display/types/display_snapshot_mojo.cc104
-rw-r--r--chromium/ui/display/types/display_snapshot_mojo.h67
-rw-r--r--chromium/ui/display/types/native_display_delegate.h33
-rw-r--r--chromium/ui/display/win/color_profile_reader.cc7
-rw-r--r--chromium/ui/display/win/screen_win.cc29
-rw-r--r--chromium/ui/display/win/screen_win.h5
-rw-r--r--chromium/ui/display/win/screen_win_unittest.cc2
-rw-r--r--chromium/ui/events/BUILD.gn60
-rw-r--r--chromium/ui/events/android/motion_event_android.cc19
-rw-r--r--chromium/ui/events/android/motion_event_android.h8
-rw-r--r--chromium/ui/events/android/motion_event_android_unittest.cc15
-rw-r--r--chromium/ui/events/android/scroller.cc4
-rw-r--r--chromium/ui/events/blink/DEPS1
-rw-r--r--chromium/ui/events/blink/did_overscroll_params.h2
-rw-r--r--chromium/ui/events/blink/event_with_callback.cc31
-rw-r--r--chromium/ui/events/blink/input_handler_proxy.cc76
-rw-r--r--chromium/ui/events/blink/input_handler_proxy.h15
-rw-r--r--chromium/ui/events/blink/input_handler_proxy_client.h8
-rw-r--r--chromium/ui/events/blink/input_handler_proxy_unittest.cc119
-rw-r--r--chromium/ui/events/blink/input_scroll_elasticity_controller_unittest.cc3
-rw-r--r--chromium/ui/events/devices/BUILD.gn5
-rw-r--r--chromium/ui/events/devices/device_data_manager.cc73
-rw-r--r--chromium/ui/events/devices/device_data_manager.h37
-rw-r--r--chromium/ui/events/devices/device_data_manager_unittest.cc109
-rw-r--r--chromium/ui/events/devices/input_device_event_observer.h4
-rw-r--r--chromium/ui/events/devices/input_device_manager.h4
-rw-r--r--chromium/ui/events/devices/input_device_observer_android.cc6
-rw-r--r--chromium/ui/events/devices/input_device_observer_android.h2
-rw-r--r--chromium/ui/events/devices/mojo/BUILD.gn2
-rw-r--r--chromium/ui/events/devices/mojo/OWNERS3
-rw-r--r--chromium/ui/events/devices/mojo/touch_device_transform.mojom (renamed from chromium/ui/display/manager/chromeos/mojo/touch_device_transform.mojom)3
-rw-r--r--chromium/ui/events/devices/mojo/touch_device_transform.typemap14
-rw-r--r--chromium/ui/events/devices/mojo/touch_device_transform_struct_traits.h (renamed from chromium/ui/display/manager/chromeos/mojo/touch_device_transform_struct_traits.h)23
-rw-r--r--chromium/ui/events/devices/mojo/touch_device_transform_struct_traits_unittest.cc (renamed from chromium/ui/display/manager/chromeos/mojo/touch_device_transform_struct_traits_unittest.cc)12
-rw-r--r--chromium/ui/events/devices/mojo/typemaps.gni5
-rw-r--r--chromium/ui/events/devices/touch_device_transform.cc (renamed from chromium/ui/display/manager/chromeos/touch_device_transform.cc)6
-rw-r--r--chromium/ui/events/devices/touch_device_transform.h30
-rw-r--r--chromium/ui/events/devices/touchscreen_device.cc14
-rw-r--r--chromium/ui/events/devices/touchscreen_device.h12
-rw-r--r--chromium/ui/events/devices/x11/device_data_manager_x11.cc2
-rw-r--r--chromium/ui/events/devices/x11/touch_factory_x11.cc2
-rw-r--r--chromium/ui/events/event.cc52
-rw-r--r--chromium/ui/events/event.h13
-rw-r--r--chromium/ui/events/event_constants.h4
-rw-r--r--chromium/ui/events/event_unittest.cc45
-rw-r--r--chromium/ui/events/gesture_detection/gesture_detector.cc8
-rw-r--r--chromium/ui/events/gesture_detection/gesture_provider.cc4
-rw-r--r--chromium/ui/events/gesture_detection/gesture_provider_unittest.cc11
-rw-r--r--chromium/ui/events/gesture_detection/motion_event_buffer_unittest.cc2
-rw-r--r--chromium/ui/events/gesture_detection/motion_event_generic.cc3
-rw-r--r--chromium/ui/events/gestures/blink/web_gesture_curve_impl.cc29
-rw-r--r--chromium/ui/events/gestures/blink/web_gesture_curve_impl.h3
-rw-r--r--chromium/ui/events/gestures/gesture_recognizer_impl.h8
-rw-r--r--chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm27
-rw-r--r--chromium/ui/events/mojo/BUILD.gn1
-rw-r--r--chromium/ui/events/mojo/event.mojom9
-rw-r--r--chromium/ui/events/mojo/event_struct_traits.cc35
-rw-r--r--chromium/ui/events/mojo/event_struct_traits.h2
-rw-r--r--chromium/ui/events/mojo/struct_traits_unittest.cc28
-rw-r--r--chromium/ui/events/ozone/evdev/event_factory_evdev.cc12
-rw-r--r--chromium/ui/events/ozone/evdev/input_controller_evdev.cc5
-rw-r--r--chromium/ui/events/ozone/evdev/input_controller_evdev.h1
-rw-r--r--chromium/ui/events/ozone/evdev/input_device_factory_evdev.cc3
-rw-r--r--chromium/ui/events/ozone/evdev/input_device_settings_evdev.h1
-rw-r--r--chromium/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc37
-rw-r--r--chromium/ui/events/ozone/evdev/touch_filter/horizontally_aligned_touch_noise_filter.cc12
-rw-r--r--chromium/ui/events/x/events_x_unittest.cc34
-rw-r--r--chromium/ui/gfx/BUILD.gn40
-rw-r--r--chromium/ui/gfx/DEPS1
-rw-r--r--chromium/ui/gfx/android/view_configuration.cc4
-rw-r--r--chromium/ui/gfx/android/view_configuration.h3
-rw-r--r--chromium/ui/gfx/animation/animation_container.cc49
-rw-r--r--chromium/ui/gfx/animation/animation_container.h24
-rw-r--r--chromium/ui/gfx/animation/animation_unittest.cc3
-rw-r--r--chromium/ui/gfx/animation/linear_animation.cc2
-rw-r--r--chromium/ui/gfx/animation/linear_animation.h2
-rw-r--r--chromium/ui/gfx/animation/test_animation_delegate.h6
-rw-r--r--chromium/ui/gfx/animation/tween.cc4
-rw-r--r--chromium/ui/gfx/buffer_types.h6
-rw-r--r--chromium/ui/gfx/canvas.cc12
-rw-r--r--chromium/ui/gfx/color_space.cc148
-rw-r--r--chromium/ui/gfx/color_space.h27
-rw-r--r--chromium/ui/gfx/color_space_unittest.cc17
-rw-r--r--chromium/ui/gfx/color_transform.cc10
-rw-r--r--chromium/ui/gfx/color_transform_unittest.cc8
-rw-r--r--chromium/ui/gfx/font_fallback_fuchsia.cc18
-rw-r--r--chromium/ui/gfx/font_render_params.h3
-rw-r--r--chromium/ui/gfx/font_render_params_fuchsia.cc38
-rw-r--r--chromium/ui/gfx/geometry/point.h18
-rw-r--r--chromium/ui/gfx/geometry/rect.cc18
-rw-r--r--chromium/ui/gfx/geometry/rect.h37
-rw-r--r--chromium/ui/gfx/geometry/size.cc6
-rw-r--r--chromium/ui/gfx/geometry/vector2d.cc10
-rw-r--r--chromium/ui/gfx/gpu_memory_buffer_tracing.cc21
-rw-r--r--chromium/ui/gfx/gpu_memory_buffer_tracing.h15
-rw-r--r--chromium/ui/gfx/icc_profile.cc421
-rw-r--r--chromium/ui/gfx/icc_profile.h52
-rw-r--r--chromium/ui/gfx/icc_profile_unittest.cc96
-rw-r--r--chromium/ui/gfx/image/canvas_image_source.h4
-rw-r--r--chromium/ui/gfx/image/image.cc311
-rw-r--r--chromium/ui/gfx/image/image.h26
-rw-r--r--chromium/ui/gfx/image/image_family.cc9
-rw-r--r--chromium/ui/gfx/image/image_family.h13
-rw-r--r--chromium/ui/gfx/image/image_family_unittest.cc20
-rw-r--r--chromium/ui/gfx/image/image_generic.cc123
-rw-r--r--chromium/ui/gfx/image/image_ios.mm2
-rw-r--r--chromium/ui/gfx/image/image_mac.mm2
-rw-r--r--chromium/ui/gfx/image/image_platform.h57
-rw-r--r--chromium/ui/gfx/image/image_skia.cc3
-rw-r--r--chromium/ui/gfx/image/image_skia.h4
-rw-r--r--chromium/ui/gfx/image/image_skia_operations.cc50
-rw-r--r--chromium/ui/gfx/image/image_skia_unittest.cc33
-rw-r--r--chromium/ui/gfx/image/image_unittest.cc73
-rw-r--r--chromium/ui/gfx/image/mojo/image_skia_struct_traits.cc26
-rw-r--r--chromium/ui/gfx/image/mojo/image_skia_struct_traits.h10
-rw-r--r--chromium/ui/gfx/image/mojo/image_traits_unittest.cc21
-rw-r--r--chromium/ui/gfx/linux/client_native_pixmap_factory_dmabuf.cc16
-rw-r--r--chromium/ui/gfx/mojo/BUILD.gn12
-rw-r--r--chromium/ui/gfx/mojo/buffer_types.mojom2
-rw-r--r--chromium/ui/gfx/mojo/buffer_types_struct_traits.cc23
-rw-r--r--chromium/ui/gfx/mojo/buffer_types_struct_traits.h19
-rw-r--r--chromium/ui/gfx/mojo/selection_bound.typemap3
-rw-r--r--chromium/ui/gfx/mojo/transform.typemap3
-rw-r--r--chromium/ui/gfx/native_widget_types.h18
-rw-r--r--chromium/ui/gfx/paint_vector_icon.cc17
-rw-r--r--chromium/ui/gfx/platform_font_fuchsia.cc26
-rw-r--r--chromium/ui/gfx/platform_font_win.cc7
-rw-r--r--chromium/ui/gfx/platform_font_win.h2
-rw-r--r--chromium/ui/gfx/render_text.cc46
-rw-r--r--chromium/ui/gfx/render_text.h1
-rw-r--r--chromium/ui/gfx/render_text_harfbuzz.cc42
-rw-r--r--chromium/ui/gfx/render_text_unittest.cc328
-rw-r--r--chromium/ui/gfx/sequential_id_generator.cc5
-rw-r--r--chromium/ui/gfx/sequential_id_generator.h3
-rw-r--r--chromium/ui/gfx/sequential_id_generator_unittest.cc10
-rw-r--r--chromium/ui/gfx/shadow_util.cc3
-rw-r--r--chromium/ui/gfx/skia_color_space_util.cc130
-rw-r--r--chromium/ui/gfx/skia_paint_util.cc8
-rw-r--r--chromium/ui/gfx/vector_icon_types.h2
-rw-r--r--chromium/ui/gl/BUILD.gn11
-rw-r--r--chromium/ui/gl/android/scoped_java_surface.cc2
-rw-r--r--chromium/ui/gl/android/surface_texture_listener.cc5
-rw-r--r--chromium/ui/gl/android/surface_texture_listener.h2
-rw-r--r--chromium/ui/gl/angle_platform_impl.cc95
-rw-r--r--chromium/ui/gl/angle_platform_impl.h15
-rw-r--r--chromium/ui/gl/egl_api_unittest.cc34
-rw-r--r--chromium/ui/gl/extension_set.cc20
-rw-r--r--chromium/ui/gl/extension_set.h30
-rwxr-xr-xchromium/ui/gl/generate_bindings.py53
-rw-r--r--chromium/ui/gl/gl_angle_util_win.cc2
-rw-r--r--chromium/ui/gl/gl_api_unittest.cc47
-rw-r--r--chromium/ui/gl/gl_bindings.cc21
-rw-r--r--chromium/ui/gl/gl_bindings.h13
-rw-r--r--chromium/ui/gl/gl_bindings_api_autogen_gl.h12
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_egl.cc56
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_egl.h4
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_gl.cc355
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_gl.h54
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_glx.cc24
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_glx.h4
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_mock.cc97
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_mock.h36
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_osmesa.cc4
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_osmesa.h4
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_wgl.cc19
-rw-r--r--chromium/ui/gl/gl_bindings_autogen_wgl.h4
-rw-r--r--chromium/ui/gl/gl_context.cc107
-rw-r--r--chromium/ui/gl/gl_context.h50
-rw-r--r--chromium/ui/gl/gl_context_cgl.cc39
-rw-r--r--chromium/ui/gl/gl_context_cgl.h8
-rw-r--r--chromium/ui/gl/gl_context_egl.cc13
-rw-r--r--chromium/ui/gl/gl_context_egl.h1
-rw-r--r--chromium/ui/gl/gl_context_glx.cc23
-rw-r--r--chromium/ui/gl/gl_context_glx.h1
-rw-r--r--chromium/ui/gl/gl_context_stub.cc15
-rw-r--r--chromium/ui/gl/gl_context_stub.h2
-rw-r--r--chromium/ui/gl/gl_context_wgl.cc13
-rw-r--r--chromium/ui/gl/gl_context_wgl.h1
-rw-r--r--chromium/ui/gl/gl_egl_api_implementation.cc50
-rw-r--r--chromium/ui/gl/gl_egl_api_implementation.h14
-rw-r--r--chromium/ui/gl/gl_enums_implementation_autogen.h15
-rw-r--r--chromium/ui/gl/gl_gl_api_implementation.cc108
-rw-r--r--chromium/ui/gl/gl_gl_api_implementation.h18
-rw-r--r--chromium/ui/gl/gl_glx_api_implementation.cc38
-rw-r--r--chromium/ui/gl/gl_glx_api_implementation.h16
-rw-r--r--chromium/ui/gl/gl_image.h9
-rw-r--r--chromium/ui/gl/gl_image_io_surface.h7
-rw-r--r--chromium/ui/gl/gl_image_io_surface.mm11
-rw-r--r--chromium/ui/gl/gl_image_io_surface_unittest.cc8
-rw-r--r--chromium/ui/gl/gl_image_shared_memory.cc5
-rw-r--r--chromium/ui/gl/gl_image_stub.cc4
-rw-r--r--chromium/ui/gl/gl_implementation.cc12
-rw-r--r--chromium/ui/gl/gl_implementation.h3
-rw-r--r--chromium/ui/gl/gl_mock_autogen_gl.h12
-rw-r--r--chromium/ui/gl/gl_stub_api.cc6
-rw-r--r--chromium/ui/gl/gl_stub_api.h3
-rw-r--r--chromium/ui/gl/gl_stub_autogen_gl.cc6
-rw-r--r--chromium/ui/gl/gl_stub_autogen_gl.h12
-rw-r--r--chromium/ui/gl/gl_surface.cc12
-rw-r--r--chromium/ui/gl/gl_surface.h13
-rw-r--r--chromium/ui/gl/gl_surface_egl.cc50
-rw-r--r--chromium/ui/gl/gl_surface_egl.h7
-rw-r--r--chromium/ui/gl/gl_surface_egl_unittest.cc2
-rw-r--r--chromium/ui/gl/gl_surface_egl_x11.cc1
-rw-r--r--chromium/ui/gl/gl_surface_egl_x11.h1
-rw-r--r--chromium/ui/gl/gl_surface_glx.cc66
-rw-r--r--chromium/ui/gl/gl_surface_glx.h3
-rw-r--r--chromium/ui/gl/gl_surface_osmesa.cc3
-rw-r--r--chromium/ui/gl/gl_surface_osmesa.h1
-rw-r--r--chromium/ui/gl/gl_surface_osmesa_x11.cc3
-rw-r--r--chromium/ui/gl/gl_surface_osmesa_x11.h1
-rw-r--r--chromium/ui/gl/gl_surface_stub.cc1
-rw-r--r--chromium/ui/gl/gl_surface_stub.h1
-rw-r--r--chromium/ui/gl/gl_surface_wgl.cc18
-rw-r--r--chromium/ui/gl/gl_surface_wgl.h3
-rw-r--r--chromium/ui/gl/gl_switches.cc15
-rw-r--r--chromium/ui/gl/gl_switches.h6
-rw-r--r--chromium/ui/gl/gl_utils.cc8
-rw-r--r--chromium/ui/gl/gl_utils.h8
-rw-r--r--chromium/ui/gl/gl_version_info.cc40
-rw-r--r--chromium/ui/gl/gl_version_info.h14
-rw-r--r--chromium/ui/gl/gl_version_info_unittest.cc7
-rw-r--r--chromium/ui/gl/gl_wgl_api_implementation.cc37
-rw-r--r--chromium/ui/gl/gl_wgl_api_implementation.h14
-rw-r--r--chromium/ui/gl/gl_workarounds.h3
-rw-r--r--chromium/ui/gl/glx_api_unittest.cc21
-rw-r--r--chromium/ui/gl/gpu_preference.h1
-rw-r--r--chromium/ui/gl/gpu_switching_manager.cc127
-rw-r--r--chromium/ui/gl/gpu_switching_manager.h42
-rw-r--r--chromium/ui/gl/init/BUILD.gn5
-rw-r--r--chromium/ui/gl/init/gl_factory.cc29
-rw-r--r--chromium/ui/gl/init/gl_factory.h16
-rw-r--r--chromium/ui/gl/init/gl_factory_android.cc41
-rw-r--r--chromium/ui/gl/init/gl_factory_fuchsia.cc45
-rw-r--r--chromium/ui/gl/init/gl_factory_mac.cc13
-rw-r--r--chromium/ui/gl/init/gl_factory_ozone.cc43
-rw-r--r--chromium/ui/gl/init/gl_factory_win.cc39
-rw-r--r--chromium/ui/gl/init/gl_factory_x11.cc39
-rw-r--r--chromium/ui/gl/init/gl_initializer_fuchsia.cc31
-rw-r--r--chromium/ui/gl/init/gl_initializer_mac.cc3
-rw-r--r--chromium/ui/gl/sync_control_vsync_provider.cc24
-rw-r--r--chromium/ui/gl/vsync_provider_win.cc2
-rw-r--r--chromium/ui/gl/wgl_api_unittest.cc26
-rw-r--r--chromium/ui/gl/yuv_to_rgb_converter.cc21
-rw-r--r--chromium/ui/gl/yuv_to_rgb_converter.h7
-rw-r--r--chromium/ui/keyboard/content/keyboard_ui_content.cc1
-rw-r--r--chromium/ui/keyboard/keyboard_controller.cc125
-rw-r--r--chromium/ui/keyboard/keyboard_controller.h28
-rw-r--r--chromium/ui/keyboard/keyboard_controller_unittest.cc134
-rw-r--r--chromium/ui/keyboard/keyboard_layout_manager.cc40
-rw-r--r--chromium/ui/keyboard/keyboard_test_util.cc4
-rw-r--r--chromium/ui/keyboard/keyboard_test_util.h7
-rw-r--r--chromium/ui/latency/latency_info.cc4
-rw-r--r--chromium/ui/latency/latency_info_unittest.cc43
-rw-r--r--chromium/ui/login/account_picker/md_screen_account_picker.js12
-rw-r--r--chromium/ui/login/account_picker/md_user_pod_row.js31
-rw-r--r--chromium/ui/login/account_picker/screen_account_picker.js12
-rw-r--r--chromium/ui/login/account_picker/user_pod_row.css2
-rw-r--r--chromium/ui/login/account_picker/user_pod_row.js22
-rw-r--r--chromium/ui/message_center/BUILD.gn104
-rw-r--r--chromium/ui/message_center/OWNERS1
-rw-r--r--chromium/ui/message_center/dummy_message_center.cc6
-rw-r--r--chromium/ui/message_center/fake_message_center.cc14
-rw-r--r--chromium/ui/message_center/fake_message_center.h2
-rw-r--r--chromium/ui/message_center/message_center.cc17
-rw-r--r--chromium/ui/message_center/message_center.h9
-rw-r--r--chromium/ui/message_center/message_center_impl.cc10
-rw-r--r--chromium/ui/message_center/message_center_impl.h4
-rw-r--r--chromium/ui/message_center/message_center_style.h11
-rw-r--r--chromium/ui/message_center/message_center_tray.h4
-rw-r--r--chromium/ui/message_center/notification.cc86
-rw-r--r--chromium/ui/message_center/notification.h117
-rw-r--r--chromium/ui/message_center/vector_icons/notification_expand_less.icon14
-rw-r--r--chromium/ui/message_center/vector_icons/notification_expand_more.icon14
-rw-r--r--chromium/ui/message_center/views/desktop_popup_alignment_delegate.cc1
-rw-r--r--chromium/ui/message_center/views/message_bubble_base.cc66
-rw-r--r--chromium/ui/message_center/views/message_bubble_base.h76
-rw-r--r--chromium/ui/message_center/views/message_center_bubble.cc126
-rw-r--r--chromium/ui/message_center/views/message_center_bubble.h55
-rw-r--r--chromium/ui/message_center/views/message_center_button_bar.cc6
-rw-r--r--chromium/ui/message_center/views/message_center_view.cc46
-rw-r--r--chromium/ui/message_center/views/message_center_view_unittest.cc5
-rw-r--r--chromium/ui/message_center/views/message_list_view.cc51
-rw-r--r--chromium/ui/message_center/views/message_list_view.h2
-rw-r--r--chromium/ui/message_center/views/message_list_view_unittest.cc18
-rw-r--r--chromium/ui/message_center/views/message_popup_collection.cc15
-rw-r--r--chromium/ui/message_center/views/message_view.cc17
-rw-r--r--chromium/ui/message_center/views/message_view.h17
-rw-r--r--chromium/ui/message_center/views/message_view_factory.cc16
-rw-r--r--chromium/ui/message_center/views/notification_button.cc4
-rw-r--r--chromium/ui/message_center/views/notification_button.h6
-rw-r--r--chromium/ui/message_center/views/notification_control_buttons_view.cc10
-rw-r--r--chromium/ui/message_center/views/notification_control_buttons_view.h8
-rw-r--r--chromium/ui/message_center/views/notification_header_view.cc229
-rw-r--r--chromium/ui/message_center/views/notification_header_view.h36
-rw-r--r--chromium/ui/message_center/views/notification_view.cc21
-rw-r--r--chromium/ui/message_center/views/notification_view.h5
-rw-r--r--chromium/ui/message_center/views/notification_view_md.cc455
-rw-r--r--chromium/ui/message_center/views/notification_view_md.h42
-rw-r--r--chromium/ui/message_center/views/notification_view_md_unittest.cc117
-rw-r--r--chromium/ui/message_center/views/notification_view_unittest.cc74
-rw-r--r--chromium/ui/message_center/views/notifier_settings_view.cc4
-rw-r--r--chromium/ui/message_center/views/notifier_settings_view.h5
-rw-r--r--chromium/ui/native_theme/common_theme.cc2
-rw-r--r--chromium/ui/native_theme/native_theme_features.cc21
-rw-r--r--chromium/ui/native_theme/native_theme_features.h6
-rw-r--r--chromium/ui/native_theme/native_theme_win.cc4
-rw-r--r--chromium/ui/ozone/common/BUILD.gn2
-rw-r--r--chromium/ui/ozone/common/display_snapshot_proxy.cc61
-rw-r--r--chromium/ui/ozone/common/display_snapshot_proxy.h26
-rw-r--r--chromium/ui/ozone/common/gl_ozone_osmesa.cc8
-rw-r--r--chromium/ui/ozone/common/gpu/ozone_gpu_message_params.cc15
-rw-r--r--chromium/ui/ozone/common/gpu/ozone_gpu_message_params.h2
-rw-r--r--chromium/ui/ozone/common/gpu/ozone_gpu_messages.h1
-rw-r--r--chromium/ui/ozone/demo/gl_renderer.cc2
-rw-r--r--chromium/ui/ozone/demo/ozone_demo.cc4
-rw-r--r--chromium/ui/ozone/demo/surfaceless_gl_renderer.cc144
-rw-r--r--chromium/ui/ozone/demo/surfaceless_gl_renderer.h4
-rw-r--r--chromium/ui/ozone/gl/gl_image_ozone_native_pixmap_unittest.cc12
-rw-r--r--chromium/ui/ozone/platform/cast/DEPS1
-rw-r--r--chromium/ui/ozone/platform/cast/gl_surface_cast.cc19
-rw-r--r--chromium/ui/ozone/platform/cast/gl_surface_cast.h1
-rw-r--r--chromium/ui/ozone/platform/cast/surface_factory_cast.cc4
-rw-r--r--chromium/ui/ozone/platform/drm/BUILD.gn8
-rw-r--r--chromium/ui/ozone/platform/drm/OWNERS1
-rw-r--r--chromium/ui/ozone/platform/drm/common/display_types.h4
-rw-r--r--chromium/ui/ozone/platform/drm/common/drm_util.cc84
-rw-r--r--chromium/ui/ozone/platform/drm/common/drm_util.h17
-rw-r--r--chromium/ui/ozone/platform/drm/common/drm_util_unittest.cc51
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/crtc_controller.cc35
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/crtc_controller.h12
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_device.cc27
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_device.h7
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_device_manager.cc3
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_device_manager.h4
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_thread.cc81
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_thread.h94
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.cc23
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.h8
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc19
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.h5
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/drm_window.cc17
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_buffer.cc17
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_surface.cc4
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/gbm_surface.h1
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc13
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h3
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_controller_unittest.cc34
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane.h1
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h4
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.cc40
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_atomic.h1
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.cc11
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/hardware_display_plane_manager_legacy.h1
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc4
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/mock_hardware_display_plane_manager.cc14
-rw-r--r--chromium/ui/ozone/platform/drm/gpu/mock_hardware_display_plane_manager.h1
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_display_host.cc6
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_display_host_manager.cc5
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc20
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.h4
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_native_display_delegate.cc34
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_native_display_delegate.h16
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_overlay_manager.cc61
-rw-r--r--chromium/ui/ozone/platform/drm/host/drm_overlay_manager.h15
-rw-r--r--chromium/ui/ozone/platform/drm/host/gpu_thread_adapter.h4
-rw-r--r--chromium/ui/ozone/platform/drm/host/host_cursor_proxy.cc (renamed from chromium/ui/ozone/platform/drm/cursor_proxy_mojo.cc)16
-rw-r--r--chromium/ui/ozone/platform/drm/host/host_cursor_proxy.h (renamed from chromium/ui/ozone/platform/drm/cursor_proxy_mojo.h)15
-rw-r--r--chromium/ui/ozone/platform/drm/host/host_drm_device.cc348
-rw-r--r--chromium/ui/ozone/platform/drm/host/host_drm_device.h (renamed from chromium/ui/ozone/platform/drm/mus_thread_proxy.h)90
-rw-r--r--chromium/ui/ozone/platform/drm/mus_thread_proxy.cc444
-rw-r--r--chromium/ui/ozone/platform/drm/ozone_platform_gbm.cc144
-rw-r--r--chromium/ui/ozone/platform/headless/headless_surface_factory.cc12
-rw-r--r--chromium/ui/ozone/platform/headless/headless_window_manager.h4
-rw-r--r--chromium/ui/ozone/platform/wayland/gl_surface_wayland.cc1
-rw-r--r--chromium/ui/ozone/platform/wayland/gl_surface_wayland.h1
-rw-r--r--chromium/ui/ozone/platform/wayland/wayland_window.cc2
-rw-r--r--chromium/ui/ozone/platform/x11/gl_surface_egl_ozone_x11.cc1
-rw-r--r--chromium/ui/ozone/platform/x11/gl_surface_egl_ozone_x11.h1
-rw-r--r--chromium/ui/ozone/platform/x11/ozone_platform_x11.cc15
-rw-r--r--chromium/ui/ozone/public/input_controller.cc4
-rw-r--r--chromium/ui/ozone/public/input_controller.h1
-rw-r--r--chromium/ui/ozone/public/interfaces/BUILD.gn3
-rw-r--r--chromium/ui/ozone/public/interfaces/drm_device.mojom86
-rw-r--r--chromium/ui/ozone/public/overlay_candidates_ozone.h2
-rw-r--r--chromium/ui/ozone/public/overlay_surface_candidate.cc16
-rw-r--r--chromium/ui/ozone/public/overlay_surface_candidate.h7
-rw-r--r--chromium/ui/platform_window/android/platform_ime_controller_android.cc5
-rw-r--r--chromium/ui/platform_window/android/platform_ime_controller_android.h2
-rw-r--r--chromium/ui/platform_window/android/platform_window_android.cc5
-rw-r--r--chromium/ui/platform_window/android/platform_window_android.h2
-rw-r--r--chromium/ui/platform_window/stub/stub_window.h2
-rw-r--r--chromium/ui/platform_window/win/win_window.h2
-rw-r--r--chromium/ui/resources/BUILD.gn2
-rw-r--r--chromium/ui/shell_dialogs/BUILD.gn6
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog.cc27
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog.h23
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog_android.cc26
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog_android.h7
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog_factory.h6
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog_fuchsia.cc19
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog_mac.h3
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog_mac.mm20
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog_win.cc25
-rw-r--r--chromium/ui/shell_dialogs/select_file_dialog_win.h3
-rw-r--r--chromium/ui/shell_dialogs/select_file_policy.cc2
-rw-r--r--chromium/ui/shell_dialogs/shell_dialog_linux.cc9
-rw-r--r--chromium/ui/shell_dialogs/shell_dialog_linux.h2
-rw-r--r--chromium/ui/snapshot/DEPS3
-rw-r--r--chromium/ui/snapshot/screenshot_grabber.cc19
-rw-r--r--chromium/ui/snapshot/screenshot_grabber.h12
-rw-r--r--chromium/ui/snapshot/snapshot.cc20
-rw-r--r--chromium/ui/snapshot/snapshot.h7
-rw-r--r--chromium/ui/snapshot/snapshot_android.cc17
-rw-r--r--chromium/ui/snapshot/snapshot_async.cc13
-rw-r--r--chromium/ui/snapshot/snapshot_async.h13
-rw-r--r--chromium/ui/snapshot/snapshot_aura.cc21
-rw-r--r--chromium/ui/snapshot/snapshot_aura.h1
-rw-r--r--chromium/ui/snapshot/snapshot_aura_unittest.cc1
-rw-r--r--chromium/ui/snapshot/snapshot_ios.mm1
-rw-r--r--chromium/ui/snapshot/snapshot_mac.mm2
-rw-r--r--chromium/ui/snapshot/snapshot_win.cc6
-rw-r--r--chromium/ui/strings/translations/ui_strings_am.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_ar.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_bg.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_bn.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_ca.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_cs.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_da.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_de.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_el.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_en-GB.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_es-419.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_es.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_et.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_fa.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_fi.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_fil.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_fr.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_gu.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_hi.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_hr.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_hu.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_id.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_it.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_iw.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_ja.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_kn.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_ko.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_lt.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_lv.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_ml.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_mr.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_ms.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_nl.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_no.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_pl.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_pt-BR.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_pt-PT.xtb6
-rw-r--r--chromium/ui/strings/translations/ui_strings_ro.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_ru.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_sk.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_sl.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_sr.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_sv.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_sw.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_ta.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_te.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_th.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_tr.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_uk.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_vi.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_zh-CN.xtb2
-rw-r--r--chromium/ui/strings/translations/ui_strings_zh-TW.xtb2
-rw-r--r--chromium/ui/strings/ui_strings.grd6
-rw-r--r--chromium/ui/touch_selection/BUILD.gn5
-rw-r--r--chromium/ui/touch_selection/DEPS1
-rw-r--r--chromium/ui/touch_selection/touch_handle.cc60
-rw-r--r--chromium/ui/touch_selection/touch_handle.h1
-rw-r--r--chromium/ui/touch_selection/touch_handle_drawable_aura.cc3
-rw-r--r--chromium/ui/touch_selection/touch_handle_unittest.cc7
-rw-r--r--chromium/ui/touch_selection/touch_selection_controller_test_api.cc14
-rw-r--r--chromium/ui/touch_selection/touch_selection_controller_test_api.h2
-rw-r--r--chromium/ui/touch_selection/touch_selection_controller_unittest.cc18
-rw-r--r--chromium/ui/views/BUILD.gn26
-rw-r--r--chromium/ui/views/DEPS3
-rw-r--r--chromium/ui/views/accessibility/OWNERS3
-rw-r--r--chromium/ui/views/accessibility/ax_system_caret_win_interactive_uitest.cc4
-rw-r--r--chromium/ui/views/accessibility/native_view_accessibility_auralinux.cc7
-rw-r--r--chromium/ui/views/accessibility/native_view_accessibility_win.cc2
-rw-r--r--chromium/ui/views/animation/OWNERS2
-rw-r--r--chromium/ui/views/animation/flood_fill_ink_drop_ripple.cc35
-rw-r--r--chromium/ui/views/animation/flood_fill_ink_drop_ripple_unittest.cc41
-rw-r--r--chromium/ui/views/animation/ink_drop_highlight.cc6
-rw-r--r--chromium/ui/views/animation/ink_drop_highlight_unittest.cc32
-rw-r--r--chromium/ui/views/animation/ink_drop_host_view.cc5
-rw-r--r--chromium/ui/views/animation/ink_drop_mask.cc12
-rw-r--r--chromium/ui/views/animation/ink_drop_ripple.cc3
-rw-r--r--chromium/ui/views/animation/ink_drop_util.cc54
-rw-r--r--chromium/ui/views/animation/ink_drop_util.h27
-rw-r--r--chromium/ui/views/animation/square_ink_drop_ripple.cc33
-rw-r--r--chromium/ui/views/bubble/bubble_border_unittest.cc100
-rw-r--r--chromium/ui/views/bubble/bubble_dialog_delegate.cc14
-rw-r--r--chromium/ui/views/bubble/bubble_dialog_delegate.h11
-rw-r--r--chromium/ui/views/bubble/bubble_dialog_delegate_unittest.cc80
-rw-r--r--chromium/ui/views/bubble/bubble_frame_view.cc58
-rw-r--r--chromium/ui/views/bubble/bubble_frame_view.h9
-rw-r--r--chromium/ui/views/bubble/bubble_frame_view_unittest.cc251
-rw-r--r--chromium/ui/views/bubble/bubble_window_targeter.cc29
-rw-r--r--chromium/ui/views/bubble/bubble_window_targeter.h34
-rw-r--r--chromium/ui/views/bubble/bubble_window_targeter_unittest.cc123
-rw-r--r--chromium/ui/views/bubble/tray_bubble_view.cc61
-rw-r--r--chromium/ui/views/bubble/tray_bubble_view.h10
-rw-r--r--chromium/ui/views/button_drag_utils.cc7
-rw-r--r--chromium/ui/views/cocoa/bridged_content_view.mm20
-rw-r--r--chromium/ui/views/cocoa/bridged_native_widget.h13
-rw-r--r--chromium/ui/views/cocoa/bridged_native_widget.mm99
-rw-r--r--chromium/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm1
-rw-r--r--chromium/ui/views/cocoa/bridged_native_widget_unittest.mm1
-rw-r--r--chromium/ui/views/cocoa/native_widget_mac_nswindow.mm41
-rw-r--r--chromium/ui/views/cocoa/views_nswindow_delegate.mm6
-rw-r--r--chromium/ui/views/controls/button/button.cc471
-rw-r--r--chromium/ui/views/controls/button/button.h201
-rw-r--r--chromium/ui/views/controls/button/button_unittest.cc (renamed from chromium/ui/views/controls/button/custom_button_unittest.cc)163
-rw-r--r--chromium/ui/views/controls/button/checkbox.cc33
-rw-r--r--chromium/ui/views/controls/button/checkbox.h2
-rw-r--r--chromium/ui/views/controls/button/custom_button.cc525
-rw-r--r--chromium/ui/views/controls/button/custom_button.h232
-rw-r--r--chromium/ui/views/controls/button/image_button.cc15
-rw-r--r--chromium/ui/views/controls/button/image_button.h7
-rw-r--r--chromium/ui/views/controls/button/image_button_factory.cc8
-rw-r--r--chromium/ui/views/controls/button/image_button_factory_unittest.cc4
-rw-r--r--chromium/ui/views/controls/button/image_button_unittest.cc18
-rw-r--r--chromium/ui/views/controls/button/label_button.cc12
-rw-r--r--chromium/ui/views/controls/button/label_button.h9
-rw-r--r--chromium/ui/views/controls/button/label_button_unittest.cc4
-rw-r--r--chromium/ui/views/controls/button/md_text_button.cc64
-rw-r--r--chromium/ui/views/controls/button/menu_button.cc4
-rw-r--r--chromium/ui/views/controls/button/menu_button.h2
-rw-r--r--chromium/ui/views/controls/button/menu_button_unittest.cc16
-rw-r--r--chromium/ui/views/controls/button/radio_button_unittest.cc96
-rw-r--r--chromium/ui/views/controls/button/toggle_button.cc43
-rw-r--r--chromium/ui/views/controls/button/toggle_button.h21
-rw-r--r--chromium/ui/views/controls/button/toggle_button_unittest.cc59
-rw-r--r--chromium/ui/views/controls/combobox/combobox.cc8
-rw-r--r--chromium/ui/views/controls/combobox/combobox.h6
-rw-r--r--chromium/ui/views/controls/focusable_border.cc12
-rw-r--r--chromium/ui/views/controls/image_view.cc13
-rw-r--r--chromium/ui/views/controls/image_view.h1
-rw-r--r--chromium/ui/views/controls/label.cc31
-rw-r--r--chromium/ui/views/controls/label.h6
-rw-r--r--chromium/ui/views/controls/label_unittest.cc73
-rw-r--r--chromium/ui/views/controls/menu/menu_controller.cc26
-rw-r--r--chromium/ui/views/controls/menu/menu_controller.h6
-rw-r--r--chromium/ui/views/controls/menu/menu_controller_unittest.cc40
-rw-r--r--chromium/ui/views/controls/menu/menu_item_view.cc98
-rw-r--r--chromium/ui/views/controls/menu/menu_item_view.h8
-rw-r--r--chromium/ui/views/controls/menu/menu_item_view_unittest.cc84
-rw-r--r--chromium/ui/views/controls/menu/menu_runner_impl.h5
-rw-r--r--chromium/ui/views/controls/menu/menu_runner_impl_adapter.h3
-rw-r--r--chromium/ui/views/controls/menu/submenu_view.cc14
-rw-r--r--chromium/ui/views/controls/menu/submenu_view.h5
-rw-r--r--chromium/ui/views/controls/native/native_view_host.cc4
-rw-r--r--chromium/ui/views/controls/native/native_view_host.h6
-rw-r--r--chromium/ui/views/controls/native/native_view_host_aura.cc34
-rw-r--r--chromium/ui/views/controls/native/native_view_host_aura.h16
-rw-r--r--chromium/ui/views/controls/native/native_view_host_mac.h3
-rw-r--r--chromium/ui/views/controls/native/native_view_host_mac.mm5
-rw-r--r--chromium/ui/views/controls/native/native_view_host_wrapper.h6
-rw-r--r--chromium/ui/views/controls/scroll_view.cc5
-rw-r--r--chromium/ui/views/controls/scroll_view.h2
-rw-r--r--chromium/ui/views/controls/scrollbar/base_scroll_bar.h2
-rw-r--r--chromium/ui/views/controls/scrollbar/base_scroll_bar_button.cc5
-rw-r--r--chromium/ui/views/controls/scrollbar/base_scroll_bar_button.h4
-rw-r--r--chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc19
-rw-r--r--chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.h8
-rw-r--r--chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.mm8
-rw-r--r--chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc4
-rw-r--r--chromium/ui/views/controls/scrollbar/scroll_bar_views.cc27
-rw-r--r--chromium/ui/views/controls/slider.cc18
-rw-r--r--chromium/ui/views/controls/slider.h2
-rw-r--r--chromium/ui/views/controls/table/table_view.cc68
-rw-r--r--chromium/ui/views/controls/table/table_view.h8
-rw-r--r--chromium/ui/views/controls/textfield/textfield.cc17
-rw-r--r--chromium/ui/views/controls/textfield/textfield_model.cc9
-rw-r--r--chromium/ui/views/controls/textfield/textfield_model_unittest.cc16
-rw-r--r--chromium/ui/views/controls/textfield/textfield_test_api.cc6
-rw-r--r--chromium/ui/views/controls/textfield/textfield_test_api.h3
-rw-r--r--chromium/ui/views/controls/textfield/textfield_unittest.cc107
-rw-r--r--chromium/ui/views/corewm/tooltip_controller_unittest.cc2
-rw-r--r--chromium/ui/views/examples/box_layout_example.h2
-rw-r--r--chromium/ui/views/examples/button_example.cc2
-rw-r--r--chromium/ui/views/examples/examples_main.cc5
-rw-r--r--chromium/ui/views/examples/examples_window.cc4
-rw-r--r--chromium/ui/views/layout/layout_provider.cc63
-rw-r--r--chromium/ui/views/layout/layout_provider.h42
-rw-r--r--chromium/ui/views/linux_ui/linux_ui.h5
-rw-r--r--chromium/ui/views/mus/BUILD.gn1
-rw-r--r--chromium/ui/views/mus/OWNERS5
-rw-r--r--chromium/ui/views/mus/desktop_window_tree_host_mus.cc5
-rw-r--r--chromium/ui/views/mus/desktop_window_tree_host_mus.h2
-rw-r--r--chromium/ui/views/mus/desktop_window_tree_host_mus_unittest.cc1
-rw-r--r--chromium/ui/views/mus/drag_interactive_uitest.cc5
-rw-r--r--chromium/ui/views/mus/screen_mus.h5
-rw-r--r--chromium/ui/views/paint_info.cc127
-rw-r--r--chromium/ui/views/paint_info.h122
-rw-r--r--chromium/ui/views/paint_info_unittest.cc254
-rw-r--r--chromium/ui/views/painter.cc44
-rw-r--r--chromium/ui/views/painter.h8
-rw-r--r--chromium/ui/views/style/platform_style.cc9
-rw-r--r--chromium/ui/views/style/platform_style.h9
-rw-r--r--chromium/ui/views/style/platform_style_mac.mm9
-rw-r--r--chromium/ui/views/style/typography.h3
-rw-r--r--chromium/ui/views/style/typography_provider.cc29
-rw-r--r--chromium/ui/views/style/typography_provider.h13
-rw-r--r--chromium/ui/views/touchui/touch_selection_controller_impl.cc80
-rw-r--r--chromium/ui/views/view.cc245
-rw-r--r--chromium/ui/views/view.h151
-rw-r--r--chromium/ui/views/view_properties.cc5
-rw-r--r--chromium/ui/views/view_tracker.cc2
-rw-r--r--chromium/ui/views/view_tracker_unittest.cc11
-rw-r--r--chromium/ui/views/view_unittest.cc221
-rw-r--r--chromium/ui/views/views_delegate.cc4
-rw-r--r--chromium/ui/views/views_delegate.h4
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc10
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h3
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc10
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h8
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc12
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h10
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc5
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.h4
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc54
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h9
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc31
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h5
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc15
-rw-r--r--chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc23
-rw-r--r--chromium/ui/views/widget/native_widget_aura.cc19
-rw-r--r--chromium/ui/views/widget/native_widget_aura.h2
-rw-r--r--chromium/ui/views/widget/native_widget_mac.h2
-rw-r--r--chromium/ui/views/widget/native_widget_mac.mm34
-rw-r--r--chromium/ui/views/widget/native_widget_mac_accessibility_unittest.mm296
-rw-r--r--chromium/ui/views/widget/native_widget_mac_interactive_uitest.mm52
-rw-r--r--chromium/ui/views/widget/native_widget_mac_unittest.mm95
-rw-r--r--chromium/ui/views/widget/native_widget_private.h2
-rw-r--r--chromium/ui/views/widget/root_view.cc13
-rw-r--r--chromium/ui/views/widget/root_view.h6
-rw-r--r--chromium/ui/views/widget/widget.cc6
-rw-r--r--chromium/ui/views/widget/widget.h11
-rw-r--r--chromium/ui/views/widget/widget_interactive_uitest.cc2
-rw-r--r--chromium/ui/views/widget/widget_unittest.cc5
-rw-r--r--chromium/ui/views/win/hwnd_message_handler.cc130
-rw-r--r--chromium/ui/views/win/hwnd_message_handler.h26
-rw-r--r--chromium/ui/views/win/hwnd_message_handler_delegate.h4
-rw-r--r--chromium/ui/views/win/pen_event_processor.cc197
-rw-r--r--chromium/ui/views/win/pen_event_processor.h63
-rw-r--r--chromium/ui/views/win/pen_event_processor_unittest.cc151
-rw-r--r--chromium/ui/views/win/windows_session_change_observer.cc25
-rw-r--r--chromium/ui/views/window/custom_frame_view.cc12
-rw-r--r--chromium/ui/views/window/dialog_client_view.cc17
-rw-r--r--chromium/ui/views/window/dialog_client_view_unittest.cc14
-rw-r--r--chromium/ui/views/window/dialog_delegate.cc13
-rw-r--r--chromium/ui/views/window/dialog_delegate.h12
-rw-r--r--chromium/ui/views/window/nav_button_provider.h54
-rw-r--r--chromium/ui/webui/PLATFORM_OWNERS2
-rw-r--r--chromium/ui/webui/resources/PRESUBMIT.py5
-rw-r--r--chromium/ui/webui/resources/cr_components/OWNERS2
-rw-r--r--chromium/ui/webui/resources/cr_components/README.md12
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/ca_trust_edit_dialog.html57
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/ca_trust_edit_dialog.js80
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/certificate_delete_confirmation_dialog.html30
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/certificate_delete_confirmation_dialog.js97
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/certificate_entry.html39
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/certificate_entry.js29
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/certificate_list.html41
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/certificate_list.js158
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/certificate_manager.html106
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/certificate_manager.js189
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/certificate_manager_types.html1
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/certificate_manager_types.js44
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/certificate_password_decryption_dialog.html34
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/certificate_password_decryption_dialog.js53
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/certificate_password_encryption_dialog.html44
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/certificate_password_encryption_dialog.js69
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/certificate_shared_css.html35
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/certificate_subentry.html63
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/certificate_subentry.js150
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/certificates_browser_proxy.html1
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/certificates_browser_proxy.js271
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/certificates_error_dialog.html29
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/certificates_error_dialog.js38
-rw-r--r--chromium/ui/webui/resources/cr_components/certificate_manager/compiled_resources2.gyp125
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/bluetooth_dialog.html137
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/bluetooth_dialog.js459
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/compiled_resources2.gyp30
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/compiled_resources2.gyp63
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.html43
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.js271
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.html30
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.js214
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_nameservers.html43
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_nameservers.js214
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_property_list.html71
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_property_list.js214
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy.html154
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy.js428
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy_exclusions.html37
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy_exclusions.js46
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.html50
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.js57
-rw-r--r--chromium/ui/webui/resources/cr_components/chromeos/network/network_shared_css.html51
-rw-r--r--chromium/ui/webui/resources/cr_components/compiled_resources2.gyp15
-rw-r--r--chromium/ui/webui/resources/cr_components_resources.grdp131
-rw-r--r--chromium/ui/webui/resources/cr_elements/OWNERS1
-rw-r--r--chromium/ui/webui/resources/cr_elements/READE.md16
-rw-r--r--chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.html2
-rw-r--r--chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.js1
-rw-r--r--chromium/ui/webui/resources/cr_elements/chromeos/network/cr_network_list_item.js4
-rw-r--r--chromium/ui/webui/resources/cr_elements/chromeos/network/cr_network_select.js39
-rw-r--r--chromium/ui/webui/resources/cr_elements/chromeos/network/cr_onc_types.js1
-rw-r--r--chromium/ui/webui/resources/cr_elements/compiled_resources2.gyp1
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.html8
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_action_menu/cr_action_menu.js25
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html9
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html4
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_icons_css.html19
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_link_row/compiled_resources2.gyp (renamed from chromium/ui/webui/resources/js/chromeos/compiled_resources2.gyp)8
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html74
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.js27
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html2
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.js4
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_scrollable_behavior.js9
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_search_field/cr_search_field_behavior.js3
-rw-r--r--chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.html17
-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/icons.html3
-rw-r--r--chromium/ui/webui/resources/cr_elements/paper_checkbox_style_css.html19
-rw-r--r--chromium/ui/webui/resources/cr_elements/paper_toggle_style_css.html42
-rw-r--r--chromium/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp5
-rw-r--r--chromium/ui/webui/resources/cr_elements/policy/cr_policy_indicator.html29
-rw-r--r--chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_indicator.html28
-rw-r--r--chromium/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.html29
-rw-r--r--chromium/ui/webui/resources/cr_elements/policy/cr_policy_vars_css.html17
-rw-r--r--chromium/ui/webui/resources/cr_elements/policy/cr_tooltip_icon.html34
-rw-r--r--chromium/ui/webui/resources/cr_elements/policy/cr_tooltip_icon.js12
-rw-r--r--chromium/ui/webui/resources/cr_elements/shared_vars_css.html33
-rw-r--r--chromium/ui/webui/resources/cr_elements_images.grdp6
-rw-r--r--chromium/ui/webui/resources/cr_elements_resources.grdp19
-rw-r--r--chromium/ui/webui/resources/css/chrome_shared.css3
-rw-r--r--chromium/ui/webui/resources/css/chromeos/ui_account_tweaks.css14
-rw-r--r--chromium/ui/webui/resources/css/widgets.css2
-rw-r--r--chromium/ui/webui/resources/html/chromeos/ui_account_tweaks.html1
-rw-r--r--chromium/ui/webui/resources/images/icon_arrow_back.svg1
-rw-r--r--chromium/ui/webui/resources/images/icon_menu_white.svg1
-rw-r--r--chromium/ui/webui/resources/images/icon_refresh.svg1
-rw-r--r--chromium/ui/webui/resources/images/info.svg4
-rw-r--r--chromium/ui/webui/resources/js/chromeos/ui_account_tweaks.js178
-rw-r--r--chromium/ui/webui/resources/js/cr/ui/menu.js1
-rw-r--r--chromium/ui/webui/resources/webui_resources.grd12
-rw-r--r--chromium/ui/wm/BUILD.gn2
-rw-r--r--chromium/ui/wm/core/compound_event_filter.cc3
-rw-r--r--chromium/ui/wm/core/easy_resize_window_targeter.cc42
-rw-r--r--chromium/ui/wm/core/easy_resize_window_targeter.h23
-rw-r--r--chromium/ui/wm/core/focus_controller.cc38
-rw-r--r--chromium/ui/wm/core/focus_controller_unittest.cc53
-rw-r--r--chromium/ui/wm/core/masked_window_targeter.cc43
-rw-r--r--chromium/ui/wm/core/masked_window_targeter.h40
-rw-r--r--chromium/ui/wm/core/window_animations.cc20
-rw-r--r--chromium/ui/wm/core/window_modality_controller.cc23
-rw-r--r--chromium/ui/wm/public/activation_client.cc1
-rw-r--r--chromium/ui/wm/public/scoped_drag_drop_disabler.cc3
1090 files changed, 26979 insertions, 14012 deletions
diff --git a/chromium/ui/accelerated_widget_mac/display_link_mac.cc b/chromium/ui/accelerated_widget_mac/display_link_mac.cc
index a1d5b730965..f74c509812f 100644
--- a/chromium/ui/accelerated_widget_mac/display_link_mac.cc
+++ b/chromium/ui/accelerated_widget_mac/display_link_mac.cc
@@ -8,6 +8,7 @@
#include "base/location.h"
#include "base/logging.h"
+#include "base/numerics/safe_conversions.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
@@ -153,10 +154,18 @@ void DisplayLinkMac::Tick(const CVTimeStamp& cv_time) {
return;
}
- timebase_ = base::TimeTicks::FromInternalValue(
- cv_time.hostTime / 1000);
- interval_ = base::TimeDelta::FromMicroseconds(
- 1000000 * static_cast<int64_t>(numerator) / denominator);
+ base::CheckedNumeric<int64_t> interval_us(base::Time::kMicrosecondsPerSecond);
+ interval_us *= numerator;
+ interval_us /= denominator;
+ if (!interval_us.IsValid()) {
+ LOG(DFATAL) << "Bailing due to overflow: "
+ << base::Time::kMicrosecondsPerSecond << " * " << numerator
+ << " / " << denominator;
+ return;
+ }
+
+ timebase_ = base::TimeTicks::FromMachAbsoluteTime(cv_time.hostTime);
+ interval_ = base::TimeDelta::FromMicroseconds(interval_us.ValueOrDie());
timebase_and_interval_valid_ = true;
// Don't restart the display link for 10 seconds.
@@ -218,4 +227,3 @@ base::LazyInstance<DisplayLinkMac::DisplayMap>::DestructorAtExit
DisplayLinkMac::display_map_ = LAZY_INSTANCE_INITIALIZER;
} // ui
-
diff --git a/chromium/ui/accelerated_widget_mac/io_surface_context.mm b/chromium/ui/accelerated_widget_mac/io_surface_context.mm
index 31840130656..2823342185f 100644
--- a/chromium/ui/accelerated_widget_mac/io_surface_context.mm
+++ b/chromium/ui/accelerated_widget_mac/io_surface_context.mm
@@ -11,6 +11,7 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "base/trace_event/trace_event.h"
+#include "ui/gl/gl_context.h"
#include "ui/gl/gl_switches.h"
#include "ui/gl/gpu_switching_manager.h"
@@ -48,7 +49,7 @@ IOSurfaceContext::Get(Type type) {
std::vector<CGLPixelFormatAttribute> attribs;
attribs.push_back(kCGLPFADepthSize);
attribs.push_back(static_cast<CGLPixelFormatAttribute>(0));
- if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus())
+ if (gl::GLContext::SwitchableGPUsSupported())
attribs.push_back(kCGLPFAAllowOfflineRenderers);
attribs.push_back(static_cast<CGLPixelFormatAttribute>(0));
GLint number_virtual_screens = 0;
diff --git a/chromium/ui/accessibility/BUILD.gn b/chromium/ui/accessibility/BUILD.gn
index 324df01891f..e0ebf1a3ba9 100644
--- a/chromium/ui/accessibility/BUILD.gn
+++ b/chromium/ui/accessibility/BUILD.gn
@@ -18,6 +18,8 @@ component("accessibility") {
sources = [
"ax_action_data.cc",
"ax_action_data.h",
+ "ax_event_generator.cc",
+ "ax_event_generator.h",
"ax_export.h",
"ax_host_delegate.cc",
"ax_host_delegate.h",
@@ -51,6 +53,8 @@ component("accessibility") {
"ax_tree_update.h",
"platform/ax_android_constants.cc",
"platform/ax_android_constants.h",
+ "platform/ax_platform_node.cc",
+ "platform/ax_platform_node.h",
"platform/ax_platform_unique_id.cc",
"platform/ax_platform_unique_id.h",
"platform/ax_snapshot_node_android_platform.cc",
@@ -59,8 +63,6 @@ component("accessibility") {
if (has_native_accessibility) {
sources += [
- "platform/ax_platform_node.cc",
- "platform/ax_platform_node.h",
"platform/ax_platform_node_base.cc",
"platform/ax_platform_node_base.h",
"platform/ax_platform_node_delegate.h",
@@ -159,6 +161,7 @@ static_library("test_support") {
test("accessibility_unittests") {
testonly = true
sources = [
+ "ax_event_generator_unittest.cc",
"ax_generated_tree_unittest.cc",
"ax_node_position_unittest.cc",
"ax_text_utils_unittest.cc",
diff --git a/chromium/ui/accessibility/OWNERS b/chromium/ui/accessibility/OWNERS
index 6ca07b4968a..84c7ff5d181 100644
--- a/chromium/ui/accessibility/OWNERS
+++ b/chromium/ui/accessibility/OWNERS
@@ -1,6 +1,7 @@
dmazzoni@chromium.org
dtseng@chromium.org
aboxhall@chromium.org
+nektar@chromium.org
# TEAM: chromium-accessibility@chromium.org
-# COMPONENT: UI>Accessibility
+# COMPONENT: Internals>Accessibility
diff --git a/chromium/ui/accessibility/PRESUBMIT.py b/chromium/ui/accessibility/PRESUBMIT.py
index 9e1b82937ff..31b9a6ed158 100644
--- a/chromium/ui/accessibility/PRESUBMIT.py
+++ b/chromium/ui/accessibility/PRESUBMIT.py
@@ -9,6 +9,9 @@ import os, re
AX_IDL = 'ui/accessibility/ax_enums.idl'
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'
+
def InitialLowerCamelCase(unix_name):
words = unix_name.split('_')
return words[0] + ''.join(word.capitalize() for word in words[1:])
@@ -64,17 +67,31 @@ def CheckMatchingEnum(ax_enums,
src = ax_enums[ax_enum_name]
dst = automation_enums[automation_enum_name]
for value in src:
- if InitialLowerCamelCase(value) not in dst:
+ lower_value = InitialLowerCamelCase(value)
+ if lower_value in dst:
+ dst.remove(lower_value) # Any remaining at end are extra and a mismatch.
+ else:
errs.append(output_api.PresubmitError(
'Found %s.%s in %s, but did not find %s.%s in %s' % (
ax_enum_name, value, AX_IDL,
automation_enum_name, InitialLowerCamelCase(value),
AUTOMATION_IDL)))
+ # Should be no remaining items
+ for value in dst:
+ errs.append(output_api.PresubmitError(
+ 'Found %s.%s in %s, but did not find %s.%s in %s' % (
+ automation_enum_name, value, AUTOMATION_IDL,
+ ax_enum_name, InitialLowerCamelCase(value),
+ AX_IDL)))
def CheckEnumsMatch(input_api, output_api):
repo_root = input_api.change.RepositoryRoot()
ax_enums = GetEnumsFromFile(os.path.join(repo_root, AX_IDL))
automation_enums = GetEnumsFromFile(os.path.join(repo_root, AUTOMATION_IDL))
+
+ # Focused state only exists in automation.
+ automation_enums['StateType'].remove('focused')
+
errs = []
CheckMatchingEnum(ax_enums, 'AXRole', automation_enums, 'RoleType', errs,
output_api)
@@ -88,12 +105,95 @@ def CheckEnumsMatch(input_api, output_api):
'Restriction', errs, output_api)
return errs
+# Given a full path to c++ header, return an array of the first static
+# constexpr defined. (Note there can be more than one defined in a C++
+# header)
+def GetConstexprFromFile(fullpath):
+ values = []
+ for line in open(fullpath).readlines():
+ # Strip out comments
+ line = re.sub('//.*', '', line)
+
+ # Look for lines of the form "static constexpr <type> NAME "
+ m = re.search('static constexpr [\w]+ ([\w]+)', line)
+ if m:
+ values.append(m.group(1))
+
+ return values
+
+# Given a full path to js file, return the AXMode consts
+# defined
+def GetAccessibilityModesFromFile(fullpath):
+ values = []
+ inside = False
+ for line in open(fullpath).readlines():
+ # Strip out comments
+ line = re.sub('//.*', '', line)
+
+ # Look for the block of code that defines AXMode
+ m = re.search('const AXMode = {', line)
+ if m:
+ inside = True
+ continue
+
+ # Look for a "}" character signifying the end of an enum
+ if line.find('};') >= 0:
+ return values
+
+ if not inside:
+ continue
+
+ m = re.search('([\w]+):', line)
+ if m:
+ values.append(m.group(1))
+ continue
+
+ # getters
+ m = re.search('get ([\w]+)\(\)', line)
+ if m:
+ values.append(m.group(1))
+ return values
+
+# Make sure that the modes defined in the C++ header match those defined in
+# the js file. Note that this doesn't guarantee that the values are the same,
+# but does make sure if we add or remove we can signal to the developer that
+# they should be aware that this dependency exists.
+def CheckModesMatch(input_api, output_api):
+ errs = []
+ repo_root = input_api.change.RepositoryRoot()
+
+ ax_modes_in_header = GetConstexprFromFile(
+ os.path.join(repo_root,AX_MODE_HEADER))
+ ax_modes_in_js = GetAccessibilityModesFromFile(
+ os.path.join(repo_root, AX_JS_FILE))
+
+ for value in ax_modes_in_header:
+ if value not in ax_modes_in_js:
+ errs.append(output_api.PresubmitError(
+ 'Found %s in %s, but did not find %s in %s' % (
+ value, AX_MODE_HEADER, value, AX_JS_FILE)))
+ return errs
+
def CheckChangeOnUpload(input_api, output_api):
- if AX_IDL not in input_api.LocalPaths():
- return []
- return CheckEnumsMatch(input_api, output_api)
+ errs = []
+ for path in input_api.LocalPaths():
+ path = path.replace('\\', '/')
+ if AX_IDL == path:
+ errs.extend(CheckEnumsMatch(input_api, output_api))
+
+ if AX_MODE_HEADER == path:
+ errs.extend(CheckModesMatch(input_api, output_api))
+
+ return errs
def CheckChangeOnCommit(input_api, output_api):
- if AX_IDL not in input_api.LocalPaths():
- return []
- return CheckEnumsMatch(input_api, output_api)
+ errs = []
+ for path in input_api.LocalPaths():
+ path = path.replace('\\', '/')
+ if AX_IDL == path:
+ errs.extend(CheckEnumsMatch(input_api, output_api))
+
+ if AX_MODE_HEADER == path:
+ errs.extend(CheckModesMatch(input_api, output_api))
+
+ return errs
diff --git a/chromium/ui/accessibility/ax_action_data.cc b/chromium/ui/accessibility/ax_action_data.cc
index 7769b27951c..b5da425bf25 100644
--- a/chromium/ui/accessibility/ax_action_data.cc
+++ b/chromium/ui/accessibility/ax_action_data.cc
@@ -17,7 +17,9 @@ namespace ui {
AXActionData::AXActionData()
: action(AX_ACTION_NONE),
+ target_tree_id(-1),
target_node_id(-1),
+ request_id(-1),
flags(0),
anchor_node_id(-1),
anchor_offset(-1),
diff --git a/chromium/ui/accessibility/ax_action_data.h b/chromium/ui/accessibility/ax_action_data.h
index a80f4a5b7e6..2993449066c 100644
--- a/chromium/ui/accessibility/ax_action_data.h
+++ b/chromium/ui/accessibility/ax_action_data.h
@@ -31,9 +31,18 @@ struct AX_EXPORT AXActionData {
// The action to take.
AXAction action;
+ // The ID of the tree that this action should be performed on.
+ int target_tree_id;
+
+ // The source extension id (if any) of this action.
+ std::string source_extension_id;
+
// The ID of the node that this action should be performed on.
int target_node_id;
+ // The request id of this action tracked by the client.
+ int request_id;
+
// Use enums from AXActionFlags
int flags;
diff --git a/chromium/ui/accessibility/ax_enums.idl b/chromium/ui/accessibility/ax_enums.idl
index 428c4c7e056..2492065931b 100644
--- a/chromium/ui/accessibility/ax_enums.idl
+++ b/chromium/ui/accessibility/ax_enums.idl
@@ -3,8 +3,7 @@
// found in the LICENSE file.
// TODO(nektar): Migrate entire file to Mojoq.
-// These should be kept in sync with third_party/WebKit/public/web/WebAXEnums.h
-// until the Chromium and Blink trees are merged.
+// Must also be kept in sync with chrome/common/extensions/api/automation.idl.
[camel_case_enum_to_string=true] namespace ui {
// For new entries to the following four enums, also add to
@@ -87,8 +86,6 @@
audio,
banner,
blockquote,
- // TODO(nektar): Remove busy_indicator because it's used nowhere.
- busy_indicator,
button,
button_drop_down, // Not used on Web.
canvas,
@@ -128,7 +125,6 @@
iframe,
iframe_presentational,
ignored,
- image_map_link,
image_map,
image,
inline_text_box,
@@ -159,7 +155,6 @@
meter,
navigation,
note,
- outline,
pane,
paragraph,
pop_up_button,
@@ -173,11 +168,8 @@
row_header,
row,
ruby,
- ruler,
svg_root,
- scroll_area,
scroll_bar,
- seamless_web_area,
search,
search_box,
slider,
@@ -188,7 +180,6 @@
static_text,
status,
switch,
- tab_group,
tab_list,
tab_panel,
tab,
@@ -213,7 +204,6 @@
};
enum AXState {
- busy,
collapsed,
default,
editable,
@@ -264,10 +254,24 @@
// Increment a slider or range control by one step value.
increment,
+ // Load inline text boxes for this subtree, providing information
+ // about word boundaries, line layout, and individual character
+ // bounding boxes.
+ load_inline_text_boxes,
+
// Delete any selected text in the control's text value and
// insert |AXActionData::value| in its place, like when typing or pasting.
replace_selected_text,
+ // Scrolls by approximately one screen in a specific direction. Should be
+ // called on a node that has scrollable boolean set to true.
+ scroll_backward,
+ scroll_forward,
+ scroll_up,
+ scroll_down,
+ scroll_left,
+ scroll_right,
+
// Scroll any scrollable containers to make the target object visible
// on the screen. Optionally pass a subfocus rect in
// AXActionData.target_rect.
@@ -277,7 +281,6 @@
// global screen coordinates. Pass a point in AXActionData.target_point.
scroll_to_point,
- set_accessibility_focus,
set_scroll_offset,
set_selection,
@@ -462,11 +465,16 @@
};
[cpp_enum_prefix_override="ax_attr"] enum AXBoolAttribute {
+ // Generic busy state, does not have to be on a live region.
+ busy,
+ // The object is at the root of an editable field, such as a content
+ // editable.
+ editable_root,
+
// Live region attributes.
container_live_atomic,
container_live_busy,
live_atomic,
- live_busy,
// If a dialog box is marked as explicitly modal
modal,
@@ -476,7 +484,10 @@
update_location_only,
// Set on a canvas element if it has fallback content.
- canvas_has_fallback
+ canvas_has_fallback,
+
+ // Indicates this node is scrollable (Android only).
+ scrollable
};
[cpp_enum_prefix_override="ax_attr"] enum AXIntListAttribute {
@@ -566,7 +577,24 @@
text_match_active_suggestion = 20,
spelling_text_match_active_suggestion = 21,
grammar_text_match_active_suggestion = 22,
- spelling_grammar_text_match_active_suggestion = 23
+ spelling_grammar_text_match_active_suggestion = 23,
+ suggestion = 32,
+ spelling_suggestion = 33,
+ grammar_suggestion = 34,
+ spelling_grammar_suggestion = 35,
+ text_match_suggestion = 36,
+ spelling_text_match_suggestion = 37,
+ grammar_text_match_suggestion = 38,
+ spelling_grammar_text_match_suggestion = 39,
+ // We again skip over DocumentMarker::MarkerType::Composition = 8 here
+ active_suggestion_suggestion = 48,
+ spelling_active_suggestion_suggestion = 49,
+ grammar_active_suggestion_suggestion = 50,
+ spelling_grammar_active_suggestion_suggestion = 51,
+ text_match_active_suggestion_suggestion = 52,
+ spelling_text_match_active_suggestion_suggestion = 53,
+ grammar_text_match_active_suggestion_suggestion = 54,
+ spelling_grammar_text_match_active_suggestion_suggestion = 55
};
enum AXTextDirection {
diff --git a/chromium/ui/accessibility/ax_event_generator.cc b/chromium/ui/accessibility/ax_event_generator.cc
new file mode 100644
index 00000000000..dfe82d7b254
--- /dev/null
+++ b/chromium/ui/accessibility/ax_event_generator.cc
@@ -0,0 +1,305 @@
+// 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/accessibility/ax_event_generator.h"
+
+#include "ui/accessibility/ax_node.h"
+#include "ui/accessibility/ax_role_properties.h"
+
+namespace ui {
+
+AXEventGenerator::TargetedEvent::TargetedEvent(ui::AXNode* node, Event event)
+ : node(node), event(event) {}
+
+AXEventGenerator::Iterator::Iterator(
+ const std::map<AXNode*, std::set<Event>>& map,
+ const std::map<AXNode*, std::set<Event>>::const_iterator& head)
+ : map_(map), map_iter_(head) {
+ if (map_iter_ != map.end())
+ set_iter_ = map_iter_->second.begin();
+}
+
+AXEventGenerator::Iterator::Iterator(const AXEventGenerator::Iterator& other) =
+ default;
+
+bool AXEventGenerator::Iterator::operator!=(
+ const AXEventGenerator::Iterator& rhs) const {
+ return map_iter_ != rhs.map_iter_ ||
+ (map_iter_ != map_.end() && set_iter_ != rhs.set_iter_);
+}
+
+AXEventGenerator::Iterator& AXEventGenerator::Iterator::operator++() {
+ if (map_iter_ == map_.end())
+ return *this;
+
+ set_iter_++;
+ while (map_iter_ != map_.end() && set_iter_ == map_iter_->second.end()) {
+ map_iter_++;
+ if (map_iter_ != map_.end())
+ set_iter_ = map_iter_->second.begin();
+ }
+
+ return *this;
+}
+
+AXEventGenerator::TargetedEvent AXEventGenerator::Iterator::operator*() const {
+ DCHECK(map_iter_ != map_.end() && set_iter_ != map_iter_->second.end());
+ return AXEventGenerator::TargetedEvent(map_iter_->first, *set_iter_);
+}
+
+AXEventGenerator::AXEventGenerator(AXTree* tree) : tree_(tree) {
+ DCHECK(tree_);
+ tree_->SetDelegate(this);
+}
+
+AXEventGenerator::~AXEventGenerator() {
+ DCHECK(tree_);
+ tree_->SetDelegate(nullptr);
+}
+
+void AXEventGenerator::Clear() {
+ tree_events_.clear();
+}
+
+void AXEventGenerator::AddEvent(ui::AXNode* node,
+ AXEventGenerator::Event event) {
+ tree_events_[node].insert(event);
+}
+
+void AXEventGenerator::OnNodeDataWillChange(AXTree* tree,
+ const AXNodeData& old_node_data,
+ const AXNodeData& new_node_data) {
+ DCHECK_EQ(tree_, tree);
+ // Fire CHILDREN_CHANGED events when the list of children updates.
+ // Internally we store inline text box nodes as children of a static text
+ // node, which enables us to determine character bounds and line layout.
+ // We don't expose those to platform APIs, though, so suppress
+ // CHILDREN_CHANGED events on static text nodes.
+ if (new_node_data.child_ids != old_node_data.child_ids &&
+ new_node_data.role != ui::AX_ROLE_STATIC_TEXT) {
+ AXNode* node = tree_->GetFromId(new_node_data.id);
+ tree_events_[node].insert(Event::CHILDREN_CHANGED);
+ }
+}
+
+void AXEventGenerator::OnRoleChanged(AXTree* tree,
+ AXNode* node,
+ AXRole old_role,
+ AXRole new_role) {
+ DCHECK_EQ(tree_, tree);
+ AddEvent(node, Event::ROLE_CHANGED);
+}
+
+void AXEventGenerator::OnStateChanged(AXTree* tree,
+ AXNode* node,
+ AXState state,
+ bool new_value) {
+ DCHECK_EQ(tree_, tree);
+
+ AddEvent(node, Event::STATE_CHANGED);
+ if (state == ui::AX_STATE_EXPANDED) {
+ AddEvent(node, new_value ? Event::EXPANDED : Event::COLLAPSED);
+ if (node->data().role == ui::AX_ROLE_ROW ||
+ node->data().role == ui::AX_ROLE_TREE_ITEM) {
+ ui::AXNode* container = node;
+ while (container && !ui::IsRowContainer(container->data().role))
+ container = container->parent();
+ if (container)
+ AddEvent(container, Event::ROW_COUNT_CHANGED);
+ }
+ }
+ if (state == ui::AX_STATE_SELECTED) {
+ AddEvent(node, Event::SELECTED_CHANGED);
+ ui::AXNode* container = node;
+ while (container &&
+ !ui::IsContainerWithSelectableChildrenRole(container->data().role))
+ container = container->parent();
+ if (container)
+ AddEvent(container, Event::SELECTED_CHILDREN_CHANGED);
+ }
+}
+
+void AXEventGenerator::OnStringAttributeChanged(AXTree* tree,
+ AXNode* node,
+ AXStringAttribute attr,
+ const std::string& old_value,
+ const std::string& new_value) {
+ DCHECK_EQ(tree_, tree);
+
+ switch (attr) {
+ case ui::AX_ATTR_NAME:
+ AddEvent(node, Event::NAME_CHANGED);
+ break;
+ case ui::AX_ATTR_DESCRIPTION:
+ AddEvent(node, Event::DESCRIPTION_CHANGED);
+ break;
+ case ui::AX_ATTR_VALUE:
+ AddEvent(node, Event::VALUE_CHANGED);
+ break;
+ case ui::AX_ATTR_ARIA_INVALID_VALUE:
+ AddEvent(node, Event::INVALID_STATUS_CHANGED);
+ break;
+ case ui::AX_ATTR_LIVE_STATUS:
+ if (node->data().role != ui::AX_ROLE_ALERT)
+ AddEvent(node, Event::LIVE_REGION_CREATED);
+ break;
+ default:
+ AddEvent(node, Event::OTHER_ATTRIBUTE_CHANGED);
+ break;
+ }
+}
+
+void AXEventGenerator::OnIntAttributeChanged(AXTree* tree,
+ AXNode* node,
+ AXIntAttribute attr,
+ int32_t old_value,
+ int32_t new_value) {
+ DCHECK_EQ(tree_, tree);
+
+ switch (attr) {
+ case ui::AX_ATTR_ACTIVEDESCENDANT_ID:
+ AddEvent(node, Event::ACTIVE_DESCENDANT_CHANGED);
+ break;
+ case ui::AX_ATTR_CHECKED_STATE:
+ AddEvent(node, Event::CHECKED_STATE_CHANGED);
+ break;
+ case ui::AX_ATTR_INVALID_STATE:
+ AddEvent(node, Event::INVALID_STATUS_CHANGED);
+ break;
+ case ui::AX_ATTR_RESTRICTION:
+ AddEvent(node, Event::STATE_CHANGED);
+ break;
+ case ui::AX_ATTR_SCROLL_X:
+ case ui::AX_ATTR_SCROLL_Y:
+ AddEvent(node, Event::SCROLL_POSITION_CHANGED);
+ break;
+ default:
+ AddEvent(node, Event::OTHER_ATTRIBUTE_CHANGED);
+ break;
+ }
+}
+
+void AXEventGenerator::OnFloatAttributeChanged(AXTree* tree,
+ AXNode* node,
+ AXFloatAttribute attr,
+ float old_value,
+ float new_value) {
+ DCHECK_EQ(tree_, tree);
+
+ if (attr == ui::AX_ATTR_VALUE_FOR_RANGE)
+ AddEvent(node, Event::VALUE_CHANGED);
+ else
+ AddEvent(node, Event::OTHER_ATTRIBUTE_CHANGED);
+}
+
+void AXEventGenerator::OnBoolAttributeChanged(AXTree* tree,
+ AXNode* node,
+ AXBoolAttribute attr,
+ bool new_value) {
+ DCHECK_EQ(tree_, tree);
+
+ AddEvent(node, Event::OTHER_ATTRIBUTE_CHANGED);
+}
+
+void AXEventGenerator::OnIntListAttributeChanged(
+ AXTree* tree,
+ AXNode* node,
+ AXIntListAttribute attr,
+ const std::vector<int32_t>& old_value,
+ const std::vector<int32_t>& new_value) {
+ DCHECK_EQ(tree_, tree);
+ AddEvent(node, Event::OTHER_ATTRIBUTE_CHANGED);
+}
+
+void AXEventGenerator::OnStringListAttributeChanged(
+ AXTree* tree,
+ AXNode* node,
+ AXStringListAttribute attr,
+ const std::vector<std::string>& old_value,
+ const std::vector<std::string>& new_value) {
+ DCHECK_EQ(tree_, tree);
+}
+
+void AXEventGenerator::OnTreeDataChanged(AXTree* tree,
+ const ui::AXTreeData& old_tree_data,
+ const ui::AXTreeData& new_tree_data) {
+ DCHECK_EQ(tree_, tree);
+
+ if (new_tree_data.loaded && !old_tree_data.loaded)
+ 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 ||
+ new_tree_data.sel_anchor_affinity != old_tree_data.sel_anchor_affinity ||
+ new_tree_data.sel_focus_object_id != old_tree_data.sel_focus_object_id ||
+ new_tree_data.sel_focus_offset != old_tree_data.sel_focus_offset ||
+ new_tree_data.sel_focus_affinity != old_tree_data.sel_focus_affinity) {
+ AddEvent(tree->root(), Event::DOCUMENT_SELECTION_CHANGED);
+ }
+ if (new_tree_data.title != old_tree_data.title)
+ AddEvent(tree->root(), Event::DOCUMENT_TITLE_CHANGED);
+}
+
+void AXEventGenerator::OnNodeWillBeDeleted(AXTree* tree, AXNode* node) {
+ DCHECK_EQ(tree_, tree);
+ tree_events_.erase(node);
+}
+
+void AXEventGenerator::OnSubtreeWillBeDeleted(AXTree* tree, AXNode* node) {
+ DCHECK_EQ(tree_, tree);
+}
+
+void AXEventGenerator::OnNodeWillBeReparented(AXTree* tree, AXNode* node) {
+ DCHECK_EQ(tree_, tree);
+}
+
+void AXEventGenerator::OnSubtreeWillBeReparented(AXTree* tree, AXNode* node) {
+ DCHECK_EQ(tree_, tree);
+}
+
+void AXEventGenerator::OnNodeCreated(AXTree* tree, AXNode* node) {
+ DCHECK_EQ(tree_, tree);
+}
+
+void AXEventGenerator::OnNodeReparented(AXTree* tree, AXNode* node) {
+ DCHECK_EQ(tree_, tree);
+}
+
+void AXEventGenerator::OnNodeChanged(AXTree* tree, AXNode* node) {
+ DCHECK_EQ(tree_, tree);
+}
+
+void AXEventGenerator::OnAtomicUpdateFinished(
+ AXTree* tree,
+ bool root_changed,
+ const std::vector<Change>& changes) {
+ DCHECK_EQ(tree_, tree);
+
+ if (root_changed && tree->data().loaded)
+ AddEvent(tree->root(), Event::LOAD_COMPLETE);
+
+ for (const auto& change : changes) {
+ if ((change.type == NODE_CREATED || change.type == SUBTREE_CREATED) &&
+ change.node->data().HasStringAttribute(ui::AX_ATTR_LIVE_STATUS)) {
+ if (change.node->data().role == ui::AX_ROLE_ALERT)
+ AddEvent(change.node, Event::ALERT);
+ else
+ AddEvent(change.node, Event::LIVE_REGION_CREATED);
+ continue;
+ }
+ if (change.node->data().HasStringAttribute(
+ ui::AX_ATTR_CONTAINER_LIVE_STATUS)) {
+ if (!change.node->data().GetStringAttribute(ui::AX_ATTR_NAME).empty())
+ AddEvent(change.node, Event::LIVE_REGION_NODE_CHANGED);
+ ui::AXNode* live_root = change.node;
+ while (live_root &&
+ !live_root->data().HasStringAttribute(ui::AX_ATTR_LIVE_STATUS))
+ live_root = live_root->parent();
+ if (live_root)
+ AddEvent(live_root, Event::LIVE_REGION_CHANGED);
+ }
+ }
+}
+
+} // namespace ui
diff --git a/chromium/ui/accessibility/ax_event_generator.h b/chromium/ui/accessibility/ax_event_generator.h
new file mode 100644
index 00000000000..ee4996858f0
--- /dev/null
+++ b/chromium/ui/accessibility/ax_event_generator.h
@@ -0,0 +1,161 @@
+// 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_ACCESSIBILITY_AX_EVENT_GENERATOR_H_
+#define UI_ACCESSIBILITY_AX_EVENT_GENERATOR_H_
+
+#include <map>
+#include <set>
+#include <vector>
+
+#include "ui/accessibility/ax_export.h"
+#include "ui/accessibility/ax_tree.h"
+
+namespace ui {
+
+// Subclass of AXTreeDelegate that automatically generates AXEvents to fire
+// based on changes to an accessibility tree. Every platform
+// tends to want different events, so this class lets each platform
+// handle the events it wants and ignore the others.
+class AX_EXPORT AXEventGenerator : public AXTreeDelegate {
+ public:
+ enum class Event : int32_t {
+ ACTIVE_DESCENDANT_CHANGED,
+ ALERT,
+ CHECKED_STATE_CHANGED,
+ CHILDREN_CHANGED,
+ COLLAPSED,
+ DESCRIPTION_CHANGED,
+ DOCUMENT_SELECTION_CHANGED,
+ DOCUMENT_TITLE_CHANGED,
+ EXPANDED,
+ INVALID_STATUS_CHANGED,
+ LIVE_REGION_CHANGED,
+ LIVE_REGION_CREATED,
+ LIVE_REGION_NODE_CHANGED,
+ LOAD_COMPLETE,
+ NAME_CHANGED,
+ OTHER_ATTRIBUTE_CHANGED,
+ ROLE_CHANGED,
+ ROW_COUNT_CHANGED,
+ SCROLL_POSITION_CHANGED,
+ SELECTED_CHANGED,
+ SELECTED_CHILDREN_CHANGED,
+ STATE_CHANGED,
+ VALUE_CHANGED,
+ };
+
+ struct TargetedEvent {
+ TargetedEvent(ui::AXNode* node, Event event);
+ ui::AXNode* node;
+ Event event;
+ };
+
+ class AX_EXPORT Iterator
+ : public std::iterator<std::input_iterator_tag, TargetedEvent> {
+ public:
+ Iterator(const std::map<AXNode*, std::set<Event>>& map,
+ const std::map<AXNode*, std::set<Event>>::const_iterator& head);
+ Iterator(const Iterator& other);
+
+ bool operator!=(const Iterator& rhs) const;
+ Iterator& operator++();
+ TargetedEvent operator*() const;
+
+ private:
+ const std::map<AXNode*, std::set<Event>>& map_;
+ std::map<AXNode*, std::set<Event>>::const_iterator map_iter_;
+ std::set<Event>::const_iterator set_iter_;
+ };
+
+ // Automatically registers itself as the delegate of |tree| and
+ // clears it on desctruction. |tree| must be valid for the lifetime
+ // of this object.
+ AXEventGenerator(AXTree* tree);
+
+ ~AXEventGenerator() override;
+
+ Iterator begin() const {
+ return Iterator(tree_events_, tree_events_.begin());
+ }
+ Iterator end() const { return Iterator(tree_events_, tree_events_.end()); }
+
+ // Clear any previously added events.
+ void Clear();
+
+ // This is called automatically based on changes to the tree observed
+ // by AXTreeDelegate, but you can also call it directly to add events
+ // and retrieve them later.
+ //
+ // Note that events are organized by node and then by event id to
+ // efficiently remove duplicates, so events won't be retrieved in the
+ // same order they were added.
+ void AddEvent(ui::AXNode* node, Event event);
+
+ protected:
+ // AXTreeDelegate overrides.
+ void OnNodeDataWillChange(AXTree* tree,
+ const AXNodeData& old_node_data,
+ const AXNodeData& new_node_data) override;
+ void OnRoleChanged(AXTree* tree,
+ AXNode* node,
+ AXRole old_role,
+ AXRole new_role) override;
+ void OnStateChanged(AXTree* tree,
+ AXNode* node,
+ AXState state,
+ bool new_value) override;
+ void OnStringAttributeChanged(AXTree* tree,
+ AXNode* node,
+ AXStringAttribute attr,
+ const std::string& old_value,
+ const std::string& new_value) override;
+ void OnIntAttributeChanged(AXTree* tree,
+ AXNode* node,
+ AXIntAttribute attr,
+ int32_t old_value,
+ int32_t new_value) override;
+ void OnFloatAttributeChanged(AXTree* tree,
+ AXNode* node,
+ AXFloatAttribute attr,
+ float old_value,
+ float new_value) override;
+ void OnBoolAttributeChanged(AXTree* tree,
+ AXNode* node,
+ AXBoolAttribute attr,
+ bool new_value) override;
+ void OnIntListAttributeChanged(
+ AXTree* tree,
+ AXNode* node,
+ AXIntListAttribute attr,
+ const std::vector<int32_t>& old_value,
+ const std::vector<int32_t>& new_value) override;
+ void OnStringListAttributeChanged(
+ AXTree* tree,
+ AXNode* node,
+ AXStringListAttribute attr,
+ const std::vector<std::string>& old_value,
+ const std::vector<std::string>& new_value) override;
+ void OnTreeDataChanged(AXTree* tree,
+ const ui::AXTreeData& old_data,
+ const ui::AXTreeData& new_data) override;
+ void OnNodeWillBeDeleted(AXTree* tree, AXNode* node) override;
+ void OnSubtreeWillBeDeleted(AXTree* tree, AXNode* node) override;
+ void OnNodeWillBeReparented(AXTree* tree, AXNode* node) override;
+ void OnSubtreeWillBeReparented(AXTree* tree, AXNode* node) override;
+ void OnNodeCreated(AXTree* tree, AXNode* node) override;
+ void OnNodeReparented(AXTree* tree, AXNode* node) override;
+ void OnNodeChanged(AXTree* tree, AXNode* node) override;
+ void OnAtomicUpdateFinished(AXTree* tree,
+ bool root_changed,
+ const std::vector<Change>& changes) override;
+
+ private:
+ AXTree* tree_; // Not owned.
+ std::map<AXNode*, std::set<Event>> tree_events_;
+};
+
+} // namespace ui
+
+#endif // UI_ACCESSIBILITY_AX_EVENT_GENERATOR_H_
diff --git a/chromium/ui/accessibility/ax_event_generator_unittest.cc b/chromium/ui/accessibility/ax_event_generator_unittest.cc
new file mode 100644
index 00000000000..c9bbb07ccf0
--- /dev/null
+++ b/chromium/ui/accessibility/ax_event_generator_unittest.cc
@@ -0,0 +1,567 @@
+// 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/accessibility/ax_event_generator.h"
+
+#include "base/strings/string_util.h"
+#include "base/strings/stringprintf.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/accessibility/ax_node.h"
+#include "ui/accessibility/ax_serializable_tree.h"
+#include "ui/accessibility/ax_tree_serializer.h"
+
+namespace ui {
+
+namespace {
+
+std::string DumpEvents(AXEventGenerator* generator) {
+ std::vector<std::string> event_strs;
+ for (auto targeted_event : *generator) {
+ const char* event_name;
+ switch (targeted_event.event) {
+ case AXEventGenerator::Event::ACTIVE_DESCENDANT_CHANGED:
+ event_name = "ACTIVE_DESCENDANT_CHANGED";
+ break;
+ case AXEventGenerator::Event::ALERT:
+ event_name = "ALERT";
+ break;
+ case AXEventGenerator::Event::CHECKED_STATE_CHANGED:
+ event_name = "CHECKED_STATE_CHANGED";
+ break;
+ case AXEventGenerator::Event::CHILDREN_CHANGED:
+ event_name = "CHILDREN_CHANGED";
+ break;
+ case AXEventGenerator::Event::COLLAPSED:
+ event_name = "COLLAPSED";
+ break;
+ case AXEventGenerator::Event::DESCRIPTION_CHANGED:
+ event_name = "DESCRIPTION_CHANGED";
+ break;
+ case AXEventGenerator::Event::DOCUMENT_SELECTION_CHANGED:
+ event_name = "DOCUMENT_SELECTION_CHANGED";
+ break;
+ case AXEventGenerator::Event::DOCUMENT_TITLE_CHANGED:
+ event_name = "DOCUMENT_TITLE_CHANGED";
+ break;
+ case AXEventGenerator::Event::EXPANDED:
+ event_name = "EXPANDED";
+ break;
+ case AXEventGenerator::Event::INVALID_STATUS_CHANGED:
+ event_name = "INVALID_STATUS_CHANGED";
+ break;
+ case AXEventGenerator::Event::LIVE_REGION_CHANGED:
+ event_name = "LIVE_REGION_CHANGED";
+ break;
+ case AXEventGenerator::Event::LIVE_REGION_CREATED:
+ event_name = "LIVE_REGION_CREATED";
+ break;
+ case AXEventGenerator::Event::LIVE_REGION_NODE_CHANGED:
+ event_name = "LIVE_REGION_NODE_CHANGED";
+ break;
+ case AXEventGenerator::Event::LOAD_COMPLETE:
+ event_name = "LOAD_COMPLETE";
+ break;
+ case AXEventGenerator::Event::NAME_CHANGED:
+ event_name = "NAME_CHANGED";
+ break;
+ case AXEventGenerator::Event::OTHER_ATTRIBUTE_CHANGED:
+ event_name = "OTHER_ATTRIBUTE_CHANGED";
+ break;
+ case AXEventGenerator::Event::ROLE_CHANGED:
+ event_name = "ROLE_CHANGED";
+ break;
+ case AXEventGenerator::Event::ROW_COUNT_CHANGED:
+ event_name = "ROW_COUNT_CHANGED";
+ break;
+ case AXEventGenerator::Event::SCROLL_POSITION_CHANGED:
+ event_name = "SCROLL_POSITION_CHANGED";
+ break;
+ case AXEventGenerator::Event::SELECTED_CHANGED:
+ event_name = "SELECTED_CHANGED";
+ break;
+ case AXEventGenerator::Event::SELECTED_CHILDREN_CHANGED:
+ event_name = "SELECTED_CHILDREN_CHANGED";
+ break;
+ case AXEventGenerator::Event::STATE_CHANGED:
+ event_name = "STATE_CHANGED";
+ break;
+ case AXEventGenerator::Event::VALUE_CHANGED:
+ event_name = "VALUE_CHANGED";
+ break;
+ default:
+ NOTREACHED();
+ event_name = "UNKNOWN";
+ break;
+ }
+ event_strs.push_back(
+ base::StringPrintf("%s on %d", event_name, targeted_event.node->id()));
+ }
+
+ // The order of events is arbitrary, so just sort the strings
+ // alphabetically to make the test output predictable.
+ std::sort(event_strs.begin(), event_strs.end());
+
+ return base::JoinString(event_strs, ", ");
+}
+
+} // namespace
+
+TEST(AXEventGeneratorTest, LoadCompleteSameTree) {
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(1);
+ initial_state.nodes[0].id = 1;
+ initial_state.has_tree_data = true;
+ AXTree tree(initial_state);
+
+ AXEventGenerator event_generator(&tree);
+ AXTreeUpdate load_complete_update = initial_state;
+ load_complete_update.tree_data.loaded = true;
+ EXPECT_TRUE(tree.Unserialize(load_complete_update));
+ EXPECT_EQ("LOAD_COMPLETE on 1", DumpEvents(&event_generator));
+}
+
+TEST(AXEventGeneratorTest, LoadCompleteNewTree) {
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(1);
+ initial_state.nodes[0].id = 1;
+ initial_state.has_tree_data = true;
+ initial_state.tree_data.loaded = true;
+ AXTree tree(initial_state);
+
+ AXEventGenerator event_generator(&tree);
+ AXTreeUpdate load_complete_update;
+ load_complete_update.root_id = 2;
+ load_complete_update.nodes.resize(1);
+ load_complete_update.nodes[0].id = 2;
+ 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));
+}
+
+TEST(AXEventGeneratorTest, DocumentSelectionChanged) {
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(1);
+ initial_state.nodes[0].id = 1;
+ initial_state.has_tree_data = true;
+ initial_state.tree_data.sel_focus_object_id = 1;
+ initial_state.tree_data.sel_focus_offset = 1;
+ AXTree tree(initial_state);
+
+ AXEventGenerator event_generator(&tree);
+ AXTreeUpdate update = initial_state;
+ update.tree_data.sel_focus_offset = 2;
+ EXPECT_TRUE(tree.Unserialize(update));
+ EXPECT_EQ("DOCUMENT_SELECTION_CHANGED on 1", DumpEvents(&event_generator));
+}
+
+TEST(AXEventGeneratorTest, DocumentTitleChanged) {
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(1);
+ initial_state.nodes[0].id = 1;
+ initial_state.has_tree_data = true;
+ initial_state.tree_data.title = "Before";
+ AXTree tree(initial_state);
+
+ AXEventGenerator event_generator(&tree);
+ AXTreeUpdate update = initial_state;
+ update.tree_data.title = "After";
+ EXPECT_TRUE(tree.Unserialize(update));
+ EXPECT_EQ("DOCUMENT_TITLE_CHANGED on 1", DumpEvents(&event_generator));
+}
+
+TEST(AXEventGeneratorTest, ExpandedAndRowCount) {
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(4);
+ initial_state.nodes[0].id = 1;
+ initial_state.nodes[0].role = ui::AX_ROLE_ROOT_WEB_AREA;
+ initial_state.nodes[0].child_ids.push_back(2);
+ initial_state.nodes[0].child_ids.push_back(4);
+ initial_state.nodes[1].id = 2;
+ initial_state.nodes[1].role = ui::AX_ROLE_TABLE;
+ initial_state.nodes[1].child_ids.push_back(3);
+ initial_state.nodes[2].id = 3;
+ initial_state.nodes[2].role = ui::AX_ROLE_ROW;
+ initial_state.nodes[3].id = 4;
+ initial_state.nodes[3].role = ui::AX_ROLE_POP_UP_BUTTON;
+ initial_state.nodes[3].AddState(ui::AX_STATE_EXPANDED);
+ AXTree tree(initial_state);
+
+ AXEventGenerator event_generator(&tree);
+ AXTreeUpdate update = initial_state;
+ update.nodes[2].AddState(ui::AX_STATE_EXPANDED);
+ update.nodes[3].state = 0;
+ EXPECT_TRUE(tree.Unserialize(update));
+ EXPECT_EQ(
+ "COLLAPSED on 4, "
+ "EXPANDED on 3, "
+ "ROW_COUNT_CHANGED on 2, "
+ "STATE_CHANGED on 3, "
+ "STATE_CHANGED on 4",
+ DumpEvents(&event_generator));
+}
+
+TEST(AXEventGeneratorTest, SelectedAndSelectedChildren) {
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(4);
+ initial_state.nodes[0].id = 1;
+ initial_state.nodes[0].role = ui::AX_ROLE_ROOT_WEB_AREA;
+ initial_state.nodes[0].child_ids.push_back(2);
+ initial_state.nodes[0].child_ids.push_back(4);
+ initial_state.nodes[1].id = 2;
+ initial_state.nodes[1].role = ui::AX_ROLE_MENU;
+ initial_state.nodes[1].child_ids.push_back(3);
+ initial_state.nodes[2].id = 3;
+ initial_state.nodes[2].role = ui::AX_ROLE_MENU_ITEM;
+ initial_state.nodes[3].id = 4;
+ initial_state.nodes[3].role = ui::AX_ROLE_LIST_BOX_OPTION;
+ initial_state.nodes[3].AddState(ui::AX_STATE_SELECTED);
+ AXTree tree(initial_state);
+
+ AXEventGenerator event_generator(&tree);
+ AXTreeUpdate update = initial_state;
+ update.nodes[2].AddState(ui::AX_STATE_SELECTED);
+ update.nodes[3].state = 0;
+ EXPECT_TRUE(tree.Unserialize(update));
+ EXPECT_EQ(
+ "SELECTED_CHANGED on 3, "
+ "SELECTED_CHANGED on 4, "
+ "SELECTED_CHILDREN_CHANGED on 2, "
+ "STATE_CHANGED on 3, "
+ "STATE_CHANGED on 4",
+ DumpEvents(&event_generator));
+}
+
+TEST(AXEventGeneratorTest, StringValueChanged) {
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(1);
+ initial_state.nodes[0].id = 1;
+ initial_state.nodes[0].role = ui::AX_ROLE_TEXT_FIELD;
+ initial_state.nodes[0].AddStringAttribute(ui::AX_ATTR_VALUE, "Before");
+ AXTree tree(initial_state);
+
+ AXEventGenerator event_generator(&tree);
+ AXTreeUpdate update = initial_state;
+ update.nodes[0].string_attributes.clear();
+ update.nodes[0].AddStringAttribute(ui::AX_ATTR_VALUE, "After");
+ EXPECT_TRUE(tree.Unserialize(update));
+ EXPECT_EQ("VALUE_CHANGED on 1", DumpEvents(&event_generator));
+}
+
+TEST(AXEventGeneratorTest, FloatValueChanged) {
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(1);
+ initial_state.nodes[0].id = 1;
+ initial_state.nodes[0].role = ui::AX_ROLE_SLIDER;
+ initial_state.nodes[0].AddFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE, 1.0);
+ AXTree tree(initial_state);
+
+ AXEventGenerator event_generator(&tree);
+ AXTreeUpdate update = initial_state;
+ update.nodes[0].float_attributes.clear();
+ update.nodes[0].AddFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE, 2.0);
+ EXPECT_TRUE(tree.Unserialize(update));
+ EXPECT_EQ("VALUE_CHANGED on 1", DumpEvents(&event_generator));
+}
+
+TEST(AXEventGeneratorTest, InvalidStatusChanged) {
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(1);
+ initial_state.nodes[0].id = 1;
+ initial_state.nodes[0].role = ui::AX_ROLE_TEXT_FIELD;
+ initial_state.nodes[0].AddStringAttribute(ui::AX_ATTR_VALUE, "Text");
+ AXTree tree(initial_state);
+
+ AXEventGenerator event_generator(&tree);
+ AXTreeUpdate update = initial_state;
+ update.nodes[0].AddIntAttribute(ui::AX_ATTR_INVALID_STATE,
+ ui::AX_INVALID_STATE_SPELLING);
+ EXPECT_TRUE(tree.Unserialize(update));
+ EXPECT_EQ("INVALID_STATUS_CHANGED on 1", DumpEvents(&event_generator));
+}
+
+TEST(AXEventGeneratorTest, AddLiveRegionAttribute) {
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(1);
+ initial_state.nodes[0].id = 1;
+ AXTree tree(initial_state);
+
+ AXEventGenerator event_generator(&tree);
+ AXTreeUpdate update = initial_state;
+ update.nodes[0].AddStringAttribute(ui::AX_ATTR_LIVE_STATUS, "polite");
+ EXPECT_TRUE(tree.Unserialize(update));
+ EXPECT_EQ("LIVE_REGION_CREATED on 1", DumpEvents(&event_generator));
+}
+
+TEST(AXEventGeneratorTest, CheckedStateChanged) {
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(1);
+ initial_state.nodes[0].id = 1;
+ initial_state.nodes[0].role = ui::AX_ROLE_CHECK_BOX;
+ AXTree tree(initial_state);
+
+ AXEventGenerator event_generator(&tree);
+ AXTreeUpdate update = initial_state;
+ update.nodes[0].AddIntAttribute(ui::AX_ATTR_CHECKED_STATE,
+ ui::AX_CHECKED_STATE_TRUE);
+ EXPECT_TRUE(tree.Unserialize(update));
+ EXPECT_EQ("CHECKED_STATE_CHANGED on 1", DumpEvents(&event_generator));
+}
+
+TEST(AXEventGeneratorTest, ActiveDescendantChanged) {
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(3);
+ initial_state.nodes[0].id = 1;
+ initial_state.nodes[0].role = ui::AX_ROLE_LIST_BOX;
+ initial_state.nodes[0].child_ids.push_back(2);
+ initial_state.nodes[0].child_ids.push_back(3);
+ initial_state.nodes[0].AddIntAttribute(ui::AX_ATTR_ACTIVEDESCENDANT_ID, 2);
+ initial_state.nodes[1].id = 2;
+ initial_state.nodes[1].role = ui::AX_ROLE_LIST_BOX_OPTION;
+ initial_state.nodes[2].id = 3;
+ initial_state.nodes[2].role = ui::AX_ROLE_LIST_BOX_OPTION;
+ AXTree tree(initial_state);
+
+ AXEventGenerator event_generator(&tree);
+ AXTreeUpdate update = initial_state;
+ update.nodes[0].int_attributes.clear();
+ update.nodes[0].AddIntAttribute(ui::AX_ATTR_ACTIVEDESCENDANT_ID, 3);
+ EXPECT_TRUE(tree.Unserialize(update));
+ EXPECT_EQ("ACTIVE_DESCENDANT_CHANGED on 1", DumpEvents(&event_generator));
+}
+
+TEST(AXEventGeneratorTest, CreateAlertAndLiveRegion) {
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(1);
+ initial_state.nodes[0].id = 1;
+ AXTree tree(initial_state);
+
+ AXEventGenerator event_generator(&tree);
+ AXTreeUpdate update = initial_state;
+ update.nodes.resize(3);
+ update.nodes[0].child_ids.push_back(2);
+ update.nodes[0].child_ids.push_back(3);
+ update.nodes[1].id = 2;
+ update.nodes[1].AddStringAttribute(ui::AX_ATTR_LIVE_STATUS, "polite");
+ update.nodes[2].id = 3;
+ update.nodes[2].role = ui::AX_ROLE_ALERT;
+ update.nodes[2].AddStringAttribute(ui::AX_ATTR_LIVE_STATUS, "polite");
+
+ EXPECT_TRUE(tree.Unserialize(update));
+ EXPECT_EQ(
+ "ALERT on 3, "
+ "CHILDREN_CHANGED on 1, "
+ "LIVE_REGION_CREATED on 2",
+ DumpEvents(&event_generator));
+}
+
+TEST(AXEventGeneratorTest, LiveRegionChanged) {
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(3);
+ initial_state.nodes[0].id = 1;
+ initial_state.nodes[0].AddStringAttribute(ui::AX_ATTR_LIVE_STATUS, "polite");
+ initial_state.nodes[0].AddStringAttribute(ui::AX_ATTR_CONTAINER_LIVE_STATUS,
+ "polite");
+ initial_state.nodes[0].child_ids.push_back(2);
+ initial_state.nodes[0].child_ids.push_back(3);
+ initial_state.nodes[1].id = 2;
+ initial_state.nodes[1].role = ui::AX_ROLE_STATIC_TEXT;
+ initial_state.nodes[1].AddStringAttribute(ui::AX_ATTR_CONTAINER_LIVE_STATUS,
+ "polite");
+ initial_state.nodes[1].AddStringAttribute(ui::AX_ATTR_NAME, "Before 1");
+ initial_state.nodes[2].id = 3;
+ initial_state.nodes[2].role = ui::AX_ROLE_STATIC_TEXT;
+ initial_state.nodes[2].AddStringAttribute(ui::AX_ATTR_CONTAINER_LIVE_STATUS,
+ "polite");
+ initial_state.nodes[2].AddStringAttribute(ui::AX_ATTR_NAME, "Before 2");
+ AXTree tree(initial_state);
+
+ AXEventGenerator event_generator(&tree);
+ AXTreeUpdate update = initial_state;
+ update.nodes[1].string_attributes.clear();
+ update.nodes[1].AddStringAttribute(ui::AX_ATTR_CONTAINER_LIVE_STATUS,
+ "polite");
+ update.nodes[1].AddStringAttribute(ui::AX_ATTR_NAME, "After 1");
+ update.nodes[2].string_attributes.clear();
+ update.nodes[2].AddStringAttribute(ui::AX_ATTR_CONTAINER_LIVE_STATUS,
+ "polite");
+ update.nodes[2].AddStringAttribute(ui::AX_ATTR_NAME, "After 2");
+
+ EXPECT_TRUE(tree.Unserialize(update));
+ EXPECT_EQ(
+ "LIVE_REGION_CHANGED on 1, "
+ "LIVE_REGION_NODE_CHANGED on 2, "
+ "LIVE_REGION_NODE_CHANGED on 3, "
+ "NAME_CHANGED on 2, "
+ "NAME_CHANGED on 3",
+ DumpEvents(&event_generator));
+}
+
+TEST(AXEventGeneratorTest, AddChild) {
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(2);
+ initial_state.nodes[0].id = 1;
+ initial_state.nodes[0].child_ids.push_back(2);
+ initial_state.nodes[1].id = 2;
+ AXTree tree(initial_state);
+
+ AXEventGenerator event_generator(&tree);
+ AXTreeUpdate update = initial_state;
+ update.nodes.resize(3);
+ update.nodes[0].child_ids.push_back(3);
+ update.nodes[2].id = 3;
+
+ EXPECT_TRUE(tree.Unserialize(update));
+ EXPECT_EQ("CHILDREN_CHANGED on 1", DumpEvents(&event_generator));
+}
+
+TEST(AXEventGeneratorTest, RemoveChild) {
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(3);
+ initial_state.nodes[0].id = 1;
+ initial_state.nodes[0].child_ids.push_back(2);
+ initial_state.nodes[0].child_ids.push_back(3);
+ initial_state.nodes[1].id = 2;
+ initial_state.nodes[2].id = 3;
+ AXTree tree(initial_state);
+
+ AXEventGenerator event_generator(&tree);
+ AXTreeUpdate update = initial_state;
+ update.nodes.resize(2);
+ update.nodes[0].child_ids.clear();
+ update.nodes[0].child_ids.push_back(2);
+
+ EXPECT_TRUE(tree.Unserialize(update));
+ EXPECT_EQ("CHILDREN_CHANGED on 1", DumpEvents(&event_generator));
+}
+
+TEST(AXEventGeneratorTest, ReorderChildren) {
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(3);
+ initial_state.nodes[0].id = 1;
+ initial_state.nodes[0].child_ids.push_back(2);
+ initial_state.nodes[0].child_ids.push_back(3);
+ initial_state.nodes[1].id = 2;
+ initial_state.nodes[2].id = 3;
+ AXTree tree(initial_state);
+
+ AXEventGenerator event_generator(&tree);
+ AXTreeUpdate update = initial_state;
+ update.nodes[0].child_ids.clear();
+ update.nodes[0].child_ids.push_back(3);
+ update.nodes[0].child_ids.push_back(2);
+
+ EXPECT_TRUE(tree.Unserialize(update));
+ EXPECT_EQ("CHILDREN_CHANGED on 1", DumpEvents(&event_generator));
+}
+
+TEST(AXEventGeneratorTest, ScrollPositionChanged) {
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(1);
+ initial_state.nodes[0].id = 1;
+ AXTree tree(initial_state);
+
+ AXEventGenerator event_generator(&tree);
+ AXTreeUpdate update = initial_state;
+ update.nodes[0].AddIntAttribute(ui::AX_ATTR_SCROLL_Y, 10);
+ EXPECT_TRUE(tree.Unserialize(update));
+ EXPECT_EQ("SCROLL_POSITION_CHANGED on 1", DumpEvents(&event_generator));
+}
+
+TEST(AXEventGeneratorTest, OtherAttributeChanged) {
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(6);
+ initial_state.nodes[0].id = 1;
+ initial_state.nodes[0].child_ids.push_back(2);
+ initial_state.nodes[0].child_ids.push_back(3);
+ initial_state.nodes[0].child_ids.push_back(4);
+ initial_state.nodes[0].child_ids.push_back(5);
+ initial_state.nodes[0].child_ids.push_back(6);
+ initial_state.nodes[1].id = 2;
+ initial_state.nodes[2].id = 3;
+ initial_state.nodes[3].id = 4;
+ initial_state.nodes[4].id = 5;
+ initial_state.nodes[5].id = 6;
+ AXTree tree(initial_state);
+
+ AXEventGenerator event_generator(&tree);
+ AXTreeUpdate update = initial_state;
+ update.nodes[1].AddStringAttribute(ui::AX_ATTR_LANGUAGE, "de");
+ update.nodes[2].AddIntAttribute(ui::AX_ATTR_ARIA_CELL_COLUMN_INDEX, 7);
+ update.nodes[3].AddFloatAttribute(ui::AX_ATTR_FONT_SIZE, 12.0f);
+ update.nodes[4].AddBoolAttribute(ui::AX_ATTR_MODAL, true);
+ std::vector<int> ids = {2};
+ update.nodes[5].AddIntListAttribute(ui::AX_ATTR_CONTROLS_IDS, ids);
+ EXPECT_TRUE(tree.Unserialize(update));
+ EXPECT_EQ(
+ "OTHER_ATTRIBUTE_CHANGED on 2, "
+ "OTHER_ATTRIBUTE_CHANGED on 3, "
+ "OTHER_ATTRIBUTE_CHANGED on 4, "
+ "OTHER_ATTRIBUTE_CHANGED on 5, "
+ "OTHER_ATTRIBUTE_CHANGED on 6",
+ DumpEvents(&event_generator));
+}
+
+TEST(AXEventGeneratorTest, NameChanged) {
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(1);
+ initial_state.nodes[0].id = 1;
+ AXTree tree(initial_state);
+
+ AXEventGenerator event_generator(&tree);
+ AXTreeUpdate update = initial_state;
+ update.nodes[0].AddStringAttribute(ui::AX_ATTR_NAME, "Hello");
+ EXPECT_TRUE(tree.Unserialize(update));
+ EXPECT_EQ("NAME_CHANGED on 1", DumpEvents(&event_generator));
+}
+
+TEST(AXEventGeneratorTest, DescriptionChanged) {
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(1);
+ initial_state.nodes[0].id = 1;
+ AXTree tree(initial_state);
+
+ AXEventGenerator event_generator(&tree);
+ AXTreeUpdate update = initial_state;
+ update.nodes[0].AddStringAttribute(ui::AX_ATTR_DESCRIPTION, "Hello");
+ EXPECT_TRUE(tree.Unserialize(update));
+ EXPECT_EQ("DESCRIPTION_CHANGED on 1", DumpEvents(&event_generator));
+}
+
+TEST(AXEventGeneratorTest, RoleChanged) {
+ AXTreeUpdate initial_state;
+ initial_state.root_id = 1;
+ initial_state.nodes.resize(1);
+ initial_state.nodes[0].id = 1;
+ AXTree tree(initial_state);
+
+ AXEventGenerator event_generator(&tree);
+ AXTreeUpdate update = initial_state;
+ update.nodes[0].role = ui::AX_ROLE_CHECK_BOX;
+ EXPECT_TRUE(tree.Unserialize(update));
+ EXPECT_EQ("ROLE_CHANGED on 1", DumpEvents(&event_generator));
+}
+
+} // namespace ui
diff --git a/chromium/ui/accessibility/ax_mode_observer.h b/chromium/ui/accessibility/ax_mode_observer.h
new file mode 100644
index 00000000000..c1fa63c9129
--- /dev/null
+++ b/chromium/ui/accessibility/ax_mode_observer.h
@@ -0,0 +1,23 @@
+// 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_ACCESSIBILITY_PLATFORM_AX_MODE_OBSERVER_H_
+#define UI_ACCESSIBILITY_PLATFORM_AX_MODE_OBSERVER_H_
+
+#include "ui/accessibility/ax_export.h"
+#include "ui/accessibility/ax_modes.h"
+
+namespace ui {
+
+class AX_EXPORT AXModeObserver {
+ public:
+ virtual ~AXModeObserver() {}
+
+ // Notifies when accessibility mode changes.
+ virtual void OnAXModeAdded(ui::AXMode mode) = 0;
+};
+
+} // namespace ui
+
+#endif // UI_ACCESSIBILITY_PLATFORM_AX_MODE_OBSERVER_H_ \ No newline at end of file
diff --git a/chromium/ui/accessibility/ax_modes.h b/chromium/ui/accessibility/ax_modes.h
new file mode 100644
index 00000000000..b6015763e1e
--- /dev/null
+++ b/chromium/ui/accessibility/ax_modes.h
@@ -0,0 +1,92 @@
+// 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_ACCESSIBILITY_PLATFORM_AX_MODE_H_
+#define UI_ACCESSIBILITY_PLATFORM_AX_MODE_H_
+
+namespace ui {
+
+class AXMode {
+ public:
+ // Native accessibility APIs, specific to each platform, are enabled.
+ // When this mode is set that indicates the presence of a third-party
+ // client accessing Chrome via accessibility APIs. However, unless one
+ // of the modes below is set, the contents of web pages will not be
+ // accessible.
+ static constexpr uint32_t kNativeAPIs = 1 << 0;
+
+ // The renderer process will generate an accessibility tree containing
+ // basic information about all nodes, including role, name, value,
+ // state, and location. This is the minimum mode required in order for
+ // web contents to be accessible, and the remaining modes are meaningless
+ // unless this one is set.
+ //
+ // Note that sometimes this mode will be set when kNativeAPI is not, when the
+ // content layer embedder is providing accessibility support via some other
+ // mechanism other than what's implemented in content/browser.
+ static constexpr uint32_t kWebContents = 1 << 1;
+
+ // The accessibility tree will contain inline text boxes, which are
+ // necessary to expose information about line breaks and word boundaries.
+ // Without this mode, you can retrieve the plaintext value of a text field
+ // but not the information about how it's broken down into lines.
+ //
+ // Note that when this mode is off it's still possible to request inline
+ // text boxes for a specific node on-demand, asynchronously.
+ static constexpr uint32_t kInlineTextBoxes = 1 << 2;
+
+ // The accessibility tree will contain extra accessibility
+ // attributes typically only needed by screen readers and other
+ // assistive technology for blind users. Examples include text style
+ // attributes, table cell information, live region properties, range
+ // values, and relationship attributes.
+ static constexpr uint32_t kScreenReader = 1 << 3;
+
+ // The accessibility tree will contain the HTML tag name and HTML attributes
+ // for all accessibility nodes that come from web content.
+ static constexpr uint32_t kHTML = 1 << 4;
+
+ constexpr AXMode() : flags_(0) {}
+ constexpr AXMode(uint32_t flags) : flags_(flags) {}
+
+ bool has_mode(uint32_t flag) const { return (flags_ & flag) > 0; }
+
+ void set_mode(uint32_t flag, bool value) {
+ flags_ = value ? (flags_ | flag) : (flags_ & ~flag);
+ }
+
+ uint32_t mode() const { return flags_; }
+
+ bool operator==(AXMode rhs) const {
+ if (flags_ == rhs.flags_)
+ return true;
+ return false;
+ }
+
+ bool is_mode_off() const { return flags_ == 0; }
+
+ bool operator!=(AXMode rhs) const { return !(*this == rhs); }
+
+ AXMode& operator|=(const AXMode& rhs) {
+ flags_ |= rhs.flags_;
+ return *this;
+ }
+
+ private:
+ uint32_t flags_;
+};
+
+static constexpr AXMode kAXModeWebContentsOnly(AXMode::kWebContents |
+ AXMode::kInlineTextBoxes |
+ AXMode::kScreenReader |
+ AXMode::kHTML);
+
+static constexpr AXMode kAXModeComplete(AXMode::kNativeAPIs |
+ AXMode::kWebContents |
+ AXMode::kInlineTextBoxes |
+ AXMode::kScreenReader | AXMode::kHTML);
+
+} // namespace ui
+
+#endif // UI_ACCESSIBILITY_PLATFORM_AX_MODE_H_
diff --git a/chromium/ui/accessibility/ax_node_data.cc b/chromium/ui/accessibility/ax_node_data.cc
index b06b4a29265..5509131d8ae 100644
--- a/chromium/ui/accessibility/ax_node_data.cc
+++ b/chromium/ui/accessibility/ax_node_data.cc
@@ -35,7 +35,7 @@ std::string StateBitfieldToString(uint32_t state) {
std::string str;
for (uint32_t i = AX_STATE_NONE + 1; i <= AX_STATE_LAST; ++i) {
if (IsFlagSet(state, i))
- str += " " + base::ToUpperASCII(ToString(static_cast<AXState>(i)));
+ str += " " + base::ToUpperASCII(ui::ToString(static_cast<AXState>(i)));
}
return str;
}
@@ -44,7 +44,7 @@ std::string ActionsBitfieldToString(uint32_t actions) {
std::string str;
for (uint32_t i = AX_ACTION_NONE + 1; i <= AX_ACTION_LAST; ++i) {
if (IsFlagSet(actions, i)) {
- str += ToString(static_cast<AXAction>(i));
+ str += ui::ToString(static_cast<AXAction>(i));
actions = ModifyFlag(actions, i, false);
str += actions ? "," : "";
}
@@ -525,15 +525,21 @@ void AXNodeData::AddAction(AXAction action_enum) {
case AX_ACTION_GET_IMAGE_DATA:
case AX_ACTION_HIT_TEST:
case AX_ACTION_INCREMENT:
+ case AX_ACTION_LOAD_INLINE_TEXT_BOXES:
case AX_ACTION_REPLACE_SELECTED_TEXT:
case AX_ACTION_SCROLL_TO_MAKE_VISIBLE:
case AX_ACTION_SCROLL_TO_POINT:
- case AX_ACTION_SET_ACCESSIBILITY_FOCUS:
case AX_ACTION_SET_SCROLL_OFFSET:
case AX_ACTION_SET_SELECTION:
case AX_ACTION_SET_SEQUENTIAL_FOCUS_NAVIGATION_STARTING_POINT:
case AX_ACTION_SET_VALUE:
case AX_ACTION_SHOW_CONTEXT_MENU:
+ case AX_ACTION_SCROLL_BACKWARD:
+ case AX_ACTION_SCROLL_FORWARD:
+ case AX_ACTION_SCROLL_UP:
+ case AX_ACTION_SCROLL_DOWN:
+ case AX_ACTION_SCROLL_LEFT:
+ case AX_ACTION_SCROLL_RIGHT:
break;
}
@@ -909,10 +915,13 @@ std::string AXNodeData::ToString() const {
for (size_t i = 0; i < bool_attributes.size(); ++i) {
std::string value = bool_attributes[i].second ? "true" : "false";
switch (bool_attributes[i].first) {
+ case AX_ATTR_EDITABLE_ROOT:
+ result += " editable_root=" + value;
+ break;
case AX_ATTR_LIVE_ATOMIC:
result += " atomic=" + value;
break;
- case AX_ATTR_LIVE_BUSY:
+ case AX_ATTR_BUSY:
result += " busy=" + value;
break;
case AX_ATTR_CONTAINER_LIVE_ATOMIC:
@@ -930,6 +939,9 @@ std::string AXNodeData::ToString() const {
case AX_ATTR_MODAL:
result += " modal=" + value;
break;
+ case AX_ATTR_SCROLLABLE:
+ result += " scrollable=" + value;
+ break;
case AX_BOOL_ATTRIBUTE_NONE:
break;
}
@@ -977,6 +989,8 @@ std::string AXNodeData::ToString() const {
types_str += "text_match&";
if (type & AX_MARKER_TYPE_ACTIVE_SUGGESTION)
types_str += "active_suggestion&";
+ if (type & AX_MARKER_TYPE_SUGGESTION)
+ types_str += "suggestion&";
if (!types_str.empty())
types_str = types_str.substr(0, types_str.size() - 1);
diff --git a/chromium/ui/accessibility/ax_node_position_unittest.cc b/chromium/ui/accessibility/ax_node_position_unittest.cc
index c6641e0ba2f..6fdbe6d15a4 100644
--- a/chromium/ui/accessibility/ax_node_position_unittest.cc
+++ b/chromium/ui/accessibility/ax_node_position_unittest.cc
@@ -419,10 +419,18 @@ TEST_F(AXPositionTest, AtEndOfLineWithTextPosition) {
ASSERT_NE(nullptr, text_position);
EXPECT_TRUE(text_position->AtEndOfLine());
+ // A "before text" position anchored at the line break should visually be the
+ // same as a text position at the end of the previous line.
text_position = AXNodePosition::CreateTextPosition(
tree_.data().tree_id, line_break_.id, 0 /* text_offset */,
AX_TEXT_AFFINITY_DOWNSTREAM);
ASSERT_NE(nullptr, text_position);
+ EXPECT_TRUE(text_position->AtEndOfLine());
+
+ text_position = AXNodePosition::CreateTextPosition(
+ tree_.data().tree_id, line_break_.id, 1 /* text_offset */,
+ AX_TEXT_AFFINITY_DOWNSTREAM);
+ ASSERT_NE(nullptr, text_position);
EXPECT_FALSE(text_position->AtEndOfLine());
text_position = AXNodePosition::CreateTextPosition(
@@ -1142,10 +1150,12 @@ TEST_F(AXPositionTest, CreatePreviousTextAnchorPosition) {
TEST_F(AXPositionTest, CreateNextAndPreviousCharacterPositionWithNullPosition) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
- TestPositionType test_position = null_position->CreateNextCharacterPosition();
+ TestPositionType test_position = null_position->CreateNextCharacterPosition(
+ AXBoundaryBehavior::CrossBoundary);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
- test_position = null_position->CreatePreviousCharacterPosition();
+ test_position = null_position->CreatePreviousCharacterPosition(
+ AXBoundaryBehavior::CrossBoundary);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
@@ -1155,7 +1165,8 @@ TEST_F(AXPositionTest, CreateNextCharacterPosition) {
tree_.data().tree_id, inline_box1_.id, 4 /* text_offset */,
AX_TEXT_AFFINITY_DOWNSTREAM);
ASSERT_NE(nullptr, text_position);
- TestPositionType test_position = text_position->CreateNextCharacterPosition();
+ TestPositionType test_position = text_position->CreateNextCharacterPosition(
+ AXBoundaryBehavior::CrossBoundary);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
@@ -1165,19 +1176,34 @@ TEST_F(AXPositionTest, CreateNextCharacterPosition) {
tree_.data().tree_id, inline_box1_.id, 5 /* text_offset */,
AX_TEXT_AFFINITY_DOWNSTREAM);
ASSERT_NE(nullptr, text_position);
- test_position = text_position->CreateNextCharacterPosition();
+ test_position = text_position->CreateNextCharacterPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTextPosition());
+ EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
+ EXPECT_EQ(5, test_position->text_offset());
+ test_position = text_position->CreateNextCharacterPosition(
+ AXBoundaryBehavior::CrossBoundary);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
- test_position = test_position->CreateNextCharacterPosition();
+ test_position = test_position->CreateNextCharacterPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTextPosition());
+ EXPECT_EQ(line_break_.id, test_position->anchor_id());
+ EXPECT_EQ(0, test_position->text_offset());
+ test_position = test_position->CreateNextCharacterPosition(
+ AXBoundaryBehavior::CrossBoundary);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
- test_position = test_position->CreateNextCharacterPosition();
+ test_position = test_position->CreateNextCharacterPosition(
+ AXBoundaryBehavior::CrossBoundary);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
@@ -1187,7 +1213,14 @@ TEST_F(AXPositionTest, CreateNextCharacterPosition) {
tree_.data().tree_id, check_box_.id, 9 /* text_offset */,
AX_TEXT_AFFINITY_DOWNSTREAM);
ASSERT_NE(nullptr, text_position);
- test_position = text_position->CreateNextCharacterPosition();
+ test_position = text_position->CreateNextCharacterPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTextPosition());
+ EXPECT_EQ(check_box_.id, test_position->anchor_id());
+ EXPECT_EQ(9, test_position->text_offset());
+ test_position = text_position->CreateNextCharacterPosition(
+ AXBoundaryBehavior::CrossBoundary);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
@@ -1197,7 +1230,8 @@ TEST_F(AXPositionTest, CreateNextCharacterPosition) {
tree_.data().tree_id, text_field_.id, 0 /* text_offset */,
AX_TEXT_AFFINITY_UPSTREAM);
ASSERT_NE(nullptr, text_position);
- test_position = text_position->CreateNextCharacterPosition();
+ test_position = text_position->CreateNextCharacterPosition(
+ AXBoundaryBehavior::CrossBoundary);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(text_field_.id, test_position->anchor_id());
@@ -1212,7 +1246,8 @@ TEST_F(AXPositionTest, CreatePreviousCharacterPosition) {
AX_TEXT_AFFINITY_DOWNSTREAM);
ASSERT_NE(nullptr, text_position);
TestPositionType test_position =
- text_position->CreatePreviousCharacterPosition();
+ text_position->CreatePreviousCharacterPosition(
+ AXBoundaryBehavior::CrossBoundary);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
@@ -1222,19 +1257,34 @@ TEST_F(AXPositionTest, CreatePreviousCharacterPosition) {
tree_.data().tree_id, inline_box2_.id, 0 /* text_offset */,
AX_TEXT_AFFINITY_DOWNSTREAM);
ASSERT_NE(nullptr, text_position);
- test_position = text_position->CreatePreviousCharacterPosition();
+ test_position = text_position->CreatePreviousCharacterPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTextPosition());
+ EXPECT_EQ(inline_box2_.id, test_position->anchor_id());
+ EXPECT_EQ(0, test_position->text_offset());
+ test_position = text_position->CreatePreviousCharacterPosition(
+ AXBoundaryBehavior::CrossBoundary);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(line_break_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
- test_position = test_position->CreatePreviousCharacterPosition();
+ test_position = test_position->CreatePreviousCharacterPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTextPosition());
+ EXPECT_EQ(line_break_.id, test_position->anchor_id());
+ EXPECT_EQ(0, test_position->text_offset());
+ test_position = test_position->CreatePreviousCharacterPosition(
+ AXBoundaryBehavior::CrossBoundary);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
EXPECT_EQ(5, test_position->text_offset());
- test_position = test_position->CreatePreviousCharacterPosition();
+ test_position = test_position->CreatePreviousCharacterPosition(
+ AXBoundaryBehavior::CrossBoundary);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
@@ -1244,7 +1294,14 @@ TEST_F(AXPositionTest, CreatePreviousCharacterPosition) {
tree_.data().tree_id, inline_box1_.id, 0 /* text_offset */,
AX_TEXT_AFFINITY_DOWNSTREAM);
ASSERT_NE(nullptr, text_position);
- test_position = text_position->CreatePreviousCharacterPosition();
+ test_position = text_position->CreatePreviousCharacterPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ EXPECT_NE(nullptr, test_position);
+ EXPECT_TRUE(test_position->IsTextPosition());
+ EXPECT_EQ(inline_box1_.id, test_position->anchor_id());
+ EXPECT_EQ(0, test_position->text_offset());
+ test_position = text_position->CreatePreviousCharacterPosition(
+ AXBoundaryBehavior::CrossBoundary);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(check_box_.id, test_position->anchor_id());
@@ -1254,21 +1311,25 @@ TEST_F(AXPositionTest, CreatePreviousCharacterPosition) {
tree_.data().tree_id, text_field_.id, 1 /* text_offset */,
AX_TEXT_AFFINITY_UPSTREAM);
ASSERT_NE(nullptr, text_position);
- test_position = text_position->CreatePreviousCharacterPosition();
+ test_position = text_position->CreatePreviousCharacterPosition(
+ AXBoundaryBehavior::CrossBoundary);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsTextPosition());
EXPECT_EQ(text_field_.id, test_position->anchor_id());
EXPECT_EQ(0, test_position->text_offset());
+ // Affinity should have been reset to downstream.
EXPECT_EQ(AX_TEXT_AFFINITY_DOWNSTREAM, test_position->affinity());
}
TEST_F(AXPositionTest, CreateNextAndPreviousWordStartPositionWithNullPosition) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
- TestPositionType test_position = null_position->CreateNextWordStartPosition();
+ TestPositionType test_position = null_position->CreateNextWordStartPosition(
+ AXBoundaryBehavior::CrossBoundary);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
- test_position = null_position->CreatePreviousWordStartPosition();
+ test_position = null_position->CreatePreviousWordStartPosition(
+ AXBoundaryBehavior::CrossBoundary);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
@@ -1276,10 +1337,12 @@ TEST_F(AXPositionTest, CreateNextAndPreviousWordStartPositionWithNullPosition) {
TEST_F(AXPositionTest, CreateNextAndPreviousWordEndPositionWithNullPosition) {
TestPositionType null_position = AXNodePosition::CreateNullPosition();
ASSERT_NE(nullptr, null_position);
- TestPositionType test_position = null_position->CreateNextWordEndPosition();
+ TestPositionType test_position = null_position->CreateNextWordEndPosition(
+ AXBoundaryBehavior::CrossBoundary);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
- test_position = null_position->CreatePreviousWordEndPosition();
+ test_position = null_position->CreatePreviousWordEndPosition(
+ AXBoundaryBehavior::CrossBoundary);
EXPECT_NE(nullptr, test_position);
EXPECT_TRUE(test_position->IsNullPosition());
}
@@ -1488,11 +1551,12 @@ TEST_P(AXPositionTestWithParam, TraverseTreeStartingWithAffinityUpstream) {
//
INSTANTIATE_TEST_CASE_P(
- CreateNextWordStartPosition,
+ CreateNextWordStartPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTestWithParam,
testing::Values(
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreateNextWordStartPosition();
+ return position->CreateNextWordStartPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
ROOT_ID,
0 /* text_offset */,
@@ -1516,7 +1580,8 @@ INSTANTIATE_TEST_CASE_P(
"1\nLine <2>",
"NullPosition"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreateNextWordStartPosition();
+ return position->CreateNextWordStartPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
TEXT_FIELD_ID,
0 /* text_offset */,
@@ -1528,7 +1593,8 @@ INSTANTIATE_TEST_CASE_P(
"affinity=downstream annotated_text=Line 1\nLine <2>",
"NullPosition"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreateNextWordStartPosition();
+ return position->CreateNextWordStartPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
STATIC_TEXT1_ID,
1 /* text_offset */,
@@ -1540,7 +1606,8 @@ INSTANTIATE_TEST_CASE_P(
"affinity=downstream annotated_text=Line <2>",
"NullPosition"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreateNextWordStartPosition();
+ return position->CreateNextWordStartPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
INLINE_BOX2_ID,
4 /* text_offset */,
@@ -1549,11 +1616,125 @@ INSTANTIATE_TEST_CASE_P(
"NullPosition"}}));
INSTANTIATE_TEST_CASE_P(
- CreatePreviousWordStartPosition,
+ CreateNextWordStartPositionWithBoundaryBehaviorStopAtAnchorBoundary,
+ AXPositionTestWithParam,
+ testing::Values(
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextWordStartPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ ROOT_ID,
+ 0 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=1 text_offset=6 "
+ "affinity=downstream annotated_text=Button<C>heck boxLine "
+ "1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=12 "
+ "affinity=downstream annotated_text=ButtonCheck <b>oxLine "
+ "1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+ "affinity=downstream annotated_text=ButtonCheck box<L>ine "
+ "1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=20 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "<1>\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=22 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1\n<L>ine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=27 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1\nLine <2>",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=28 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1\nLine 2<>"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextWordStartPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ TEXT_FIELD_ID,
+ 0 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=4 text_offset=5 "
+ "affinity=downstream annotated_text=Line <1>\nLine 2",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=7 "
+ "affinity=downstream annotated_text=Line 1\n<L>ine 2",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=12 "
+ "affinity=downstream annotated_text=Line 1\nLine <2>",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=13 "
+ "affinity=downstream annotated_text=Line 1\nLine 2<>"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextWordStartPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ STATIC_TEXT1_ID,
+ 1 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=5 text_offset=5 "
+ "affinity=downstream annotated_text=Line <1>",
+ "TextPosition tree_id=0 anchor_id=5 text_offset=6 "
+ "affinity=downstream annotated_text=Line 1<>"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextWordStartPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ INLINE_BOX2_ID,
+ 4 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=9 text_offset=5 "
+ "affinity=downstream annotated_text=Line <2>",
+ "TextPosition tree_id=0 anchor_id=9 text_offset=6 "
+ "affinity=downstream annotated_text=Line 2<>"}}));
+
+INSTANTIATE_TEST_CASE_P(
+ CreateNextWordStartPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary,
AXPositionTestWithParam,
testing::Values(
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreatePreviousWordStartPosition();
+ return position->CreateNextWordStartPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ ROOT_ID,
+ 0 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=1 text_offset=0 "
+ "affinity=downstream annotated_text=<B>uttonCheck boxLine "
+ "1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=0 "
+ "affinity=downstream annotated_text=<B>uttonCheck boxLine "
+ "1\nLine 2"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextWordStartPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ TEXT_FIELD_ID,
+ 0 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=4 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextWordStartPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ STATIC_TEXT1_ID,
+ 1 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=5 text_offset=5 "
+ "affinity=downstream annotated_text=Line <1>",
+ "TextPosition tree_id=0 anchor_id=5 text_offset=5 "
+ "affinity=downstream annotated_text=Line <1>"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextWordStartPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ INLINE_BOX2_ID,
+ 4 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=9 text_offset=5 "
+ "affinity=downstream annotated_text=Line <2>",
+ "TextPosition tree_id=0 anchor_id=9 text_offset=5 "
+ "affinity=downstream annotated_text=Line <2>"}}));
+
+INSTANTIATE_TEST_CASE_P(
+ CreatePreviousWordStartPositionWithBoundaryBehaviorCrossBoundary,
+ AXPositionTestWithParam,
+ testing::Values(
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousWordStartPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
ROOT_ID,
28 /* text_offset at end of root. */,
@@ -1580,7 +1761,8 @@ INSTANTIATE_TEST_CASE_P(
"1\nLine 2",
"NullPosition"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreatePreviousWordStartPosition();
+ return position->CreatePreviousWordStartPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
TEXT_FIELD_ID,
13 /* text_offset at end of text field */,
@@ -1600,7 +1782,8 @@ INSTANTIATE_TEST_CASE_P(
"affinity=downstream annotated_text=<B>utton",
"NullPosition"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreatePreviousWordStartPosition();
+ return position->CreatePreviousWordStartPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
STATIC_TEXT1_ID,
5 /* text_offset */,
@@ -1614,7 +1797,8 @@ INSTANTIATE_TEST_CASE_P(
"affinity=downstream annotated_text=<B>utton",
"NullPosition"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreatePreviousWordStartPosition();
+ return position->CreatePreviousWordStartPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
INLINE_BOX2_ID,
4 /* text_offset */,
@@ -1633,11 +1817,128 @@ INSTANTIATE_TEST_CASE_P(
"NullPosition"}}));
INSTANTIATE_TEST_CASE_P(
- CreateNextWordEndPosition,
+ CreatePreviousWordStartPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTestWithParam,
testing::Values(
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreateNextWordEndPosition();
+ return position->CreatePreviousWordStartPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ ROOT_ID,
+ 28 /* text_offset at end of root. */,
+ {"TextPosition tree_id=0 anchor_id=1 text_offset=27 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1\nLine <2>",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=22 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1\n<L>ine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=20 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "<1>\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+ "affinity=downstream annotated_text=ButtonCheck box<L>ine "
+ "1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=12 "
+ "affinity=downstream annotated_text=ButtonCheck <b>oxLine "
+ "1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=6 "
+ "affinity=downstream annotated_text=Button<C>heck boxLine "
+ "1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=0 "
+ "affinity=downstream annotated_text=<B>uttonCheck boxLine "
+ "1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=0 "
+ "affinity=downstream annotated_text=<B>uttonCheck boxLine "
+ "1\nLine 2"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousWordStartPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ TEXT_FIELD_ID,
+ 13 /* text_offset at end of text field */,
+ {"TextPosition tree_id=0 anchor_id=4 text_offset=12 "
+ "affinity=downstream annotated_text=Line 1\nLine <2>",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=7 "
+ "affinity=downstream annotated_text=Line 1\n<L>ine 2",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=5 "
+ "affinity=downstream annotated_text=Line <1>\nLine 2",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousWordStartPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ STATIC_TEXT1_ID,
+ 5 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=5 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 1",
+ "TextPosition tree_id=0 anchor_id=5 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 1"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousWordStartPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ INLINE_BOX2_ID,
+ 4 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 2",
+ "TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 2"}}));
+
+INSTANTIATE_TEST_CASE_P(
+ CreatePreviousWordStartPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary,
+ AXPositionTestWithParam,
+ testing::Values(
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousWordStartPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ ROOT_ID,
+ 28 /* text_offset at end of root. */,
+ {"TextPosition tree_id=0 anchor_id=1 text_offset=27 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1\nLine <2>",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=27 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1\nLine <2>"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousWordStartPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ TEXT_FIELD_ID,
+ 13 /* text_offset at end of text field */,
+ {"TextPosition tree_id=0 anchor_id=4 text_offset=12 "
+ "affinity=downstream annotated_text=Line 1\nLine <2>",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=12 "
+ "affinity=downstream annotated_text=Line 1\nLine <2>"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousWordStartPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ STATIC_TEXT1_ID,
+ 5 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=5 text_offset=5 "
+ "affinity=downstream annotated_text=Line <1>"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousWordStartPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ INLINE_BOX2_ID,
+ 4 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 2",
+ "TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 2"}}));
+
+INSTANTIATE_TEST_CASE_P(
+ CreateNextWordEndPositionWithBoundaryBehaviorCrossBoundary,
+ AXPositionTestWithParam,
+ testing::Values(
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextWordEndPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
ROOT_ID,
0 /* text_offset */,
@@ -1664,7 +1965,8 @@ INSTANTIATE_TEST_CASE_P(
"1\nLine 2<>",
"NullPosition"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreateNextWordEndPosition();
+ return position->CreateNextWordEndPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
TEXT_FIELD_ID,
0 /* text_offset */,
@@ -1678,7 +1980,8 @@ INSTANTIATE_TEST_CASE_P(
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"NullPosition"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreateNextWordEndPosition();
+ return position->CreateNextWordEndPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
STATIC_TEXT1_ID,
1 /* text_offset */,
@@ -1692,7 +1995,8 @@ INSTANTIATE_TEST_CASE_P(
"affinity=downstream annotated_text=Line 2<>",
"NullPosition"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreateNextWordEndPosition();
+ return position->CreateNextWordEndPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
INLINE_BOX2_ID,
4 /* text_offset */,
@@ -1701,11 +2005,130 @@ INSTANTIATE_TEST_CASE_P(
"NullPosition"}}));
INSTANTIATE_TEST_CASE_P(
- CreatePreviousWordEndPosition,
+ CreateNextWordEndPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTestWithParam,
testing::Values(
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreatePreviousWordEndPosition();
+ return position->CreateNextWordEndPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ ROOT_ID,
+ 0 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=1 text_offset=6 "
+ "affinity=downstream annotated_text=Button<C>heck boxLine "
+ "1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=11 "
+ "affinity=downstream annotated_text=ButtonCheck< >boxLine "
+ "1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+ "affinity=downstream annotated_text=ButtonCheck box<L>ine "
+ "1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=19 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine< "
+ ">1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=21 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1<\n>Line 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=26 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1\nLine< >2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=28 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1\nLine 2<>",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=28 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1\nLine 2<>"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextWordEndPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ TEXT_FIELD_ID,
+ 0 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=4 text_offset=4 "
+ "affinity=downstream annotated_text=Line< >1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=6 "
+ "affinity=downstream annotated_text=Line 1<\n>Line 2",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=11 "
+ "affinity=downstream annotated_text=Line 1\nLine< >2",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=13 "
+ "affinity=downstream annotated_text=Line 1\nLine 2<>",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=13 "
+ "affinity=downstream annotated_text=Line 1\nLine 2<>"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextWordEndPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ STATIC_TEXT1_ID,
+ 1 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=5 text_offset=4 "
+ "affinity=downstream annotated_text=Line< >1",
+ "TextPosition tree_id=0 anchor_id=5 text_offset=6 "
+ "affinity=downstream annotated_text=Line 1<>",
+ "TextPosition tree_id=0 anchor_id=5 text_offset=6 "
+ "affinity=downstream annotated_text=Line 1<>"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextWordEndPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ INLINE_BOX2_ID,
+ 4 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=9 text_offset=6 "
+ "affinity=downstream annotated_text=Line 2<>",
+ "TextPosition tree_id=0 anchor_id=9 text_offset=6 "
+ "affinity=downstream annotated_text=Line 2<>"}}));
+
+INSTANTIATE_TEST_CASE_P(
+ CreateNextWordEndPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary,
+ AXPositionTestWithParam,
+ testing::Values(
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextWordEndPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ ROOT_ID,
+ 6 /* text_offset before "Check". */,
+ {"TextPosition tree_id=0 anchor_id=1 text_offset=11 "
+ "affinity=downstream annotated_text=ButtonCheck< >boxLine "
+ "1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=11 "
+ "affinity=downstream annotated_text=ButtonCheck< >boxLine "
+ "1\nLine 2"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextWordEndPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ TEXT_FIELD_ID,
+ 0 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=4 text_offset=4 "
+ "affinity=downstream annotated_text=Line< >1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=4 "
+ "affinity=downstream annotated_text=Line< >1\nLine 2"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextWordEndPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ STATIC_TEXT1_ID,
+ 1 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=5 text_offset=4 "
+ "affinity=downstream annotated_text=Line< >1",
+ "TextPosition tree_id=0 anchor_id=5 text_offset=4 "
+ "affinity=downstream annotated_text=Line< >1"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextWordEndPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ INLINE_BOX2_ID,
+ 4 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=9 text_offset=4 "
+ "affinity=downstream annotated_text=Line< >2"}}));
+
+INSTANTIATE_TEST_CASE_P(
+ CreatePreviousWordEndPositionWithBoundaryBehaviorCrossBoundary,
+ AXPositionTestWithParam,
+ testing::Values(
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousWordEndPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
ROOT_ID,
28 /* text_offset at end of root. */,
@@ -1729,7 +2152,8 @@ INSTANTIATE_TEST_CASE_P(
"1\nLine 2",
"NullPosition"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreatePreviousWordEndPosition();
+ return position->CreatePreviousWordEndPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
TEXT_FIELD_ID,
13 /* text_offset at end of text field */,
@@ -1747,7 +2171,8 @@ INSTANTIATE_TEST_CASE_P(
"affinity=downstream annotated_text=Button<>",
"NullPosition"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreatePreviousWordEndPosition();
+ return position->CreatePreviousWordEndPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
STATIC_TEXT1_ID,
5 /* text_offset */,
@@ -1761,7 +2186,8 @@ INSTANTIATE_TEST_CASE_P(
"affinity=downstream annotated_text=Button<>",
"NullPosition"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreatePreviousWordEndPosition();
+ return position->CreatePreviousWordEndPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
INLINE_BOX2_ID,
4 /* text_offset */,
@@ -1778,11 +2204,116 @@ INSTANTIATE_TEST_CASE_P(
"NullPosition"}}));
INSTANTIATE_TEST_CASE_P(
- CreateNextLineStartPosition,
+ CreatePreviousWordEndPositionWithBoundaryBehaviorStopAtAnchorBoundary,
+ AXPositionTestWithParam,
+ testing::Values(
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousWordEndPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ ROOT_ID,
+ 28 /* text_offset at end of root. */,
+ {"TextPosition tree_id=0 anchor_id=1 text_offset=26 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1\nLine< >2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=21 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1<\n>Line 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=19 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine< "
+ ">1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+ "affinity=downstream annotated_text=ButtonCheck box<L>ine "
+ "1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=11 "
+ "affinity=downstream annotated_text=ButtonCheck< >boxLine "
+ "1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=6 "
+ "affinity=downstream annotated_text=Button<C>heck boxLine "
+ "1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=0 "
+ "affinity=downstream annotated_text=<B>uttonCheck boxLine "
+ "1\nLine 2"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousWordEndPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ TEXT_FIELD_ID,
+ 13 /* text_offset at end of text field */,
+ {"TextPosition tree_id=0 anchor_id=4 text_offset=11 "
+ "affinity=downstream annotated_text=Line 1\nLine< >2",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=6 "
+ "affinity=downstream annotated_text=Line 1<\n>Line 2",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=4 "
+ "affinity=downstream annotated_text=Line< >1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousWordEndPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ STATIC_TEXT1_ID,
+ 5 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=5 text_offset=4 "
+ "affinity=downstream annotated_text=Line< >1",
+ "TextPosition tree_id=0 anchor_id=5 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 1"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousWordEndPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ INLINE_BOX2_ID,
+ 4 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 2"}}));
+
+INSTANTIATE_TEST_CASE_P(
+ CreatePreviousWordEndPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary,
AXPositionTestWithParam,
testing::Values(
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreateNextLineStartPosition();
+ return position->CreatePreviousWordEndPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ ROOT_ID,
+ 28 /* text_offset at end of root. */,
+ {"TextPosition tree_id=0 anchor_id=1 text_offset=28 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1\nLine 2<>"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousWordEndPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ TEXT_FIELD_ID,
+ 13 /* text_offset at end of text field */,
+ {"TextPosition tree_id=0 anchor_id=4 text_offset=13 "
+ "affinity=downstream annotated_text=Line 1\nLine 2<>"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousWordEndPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ STATIC_TEXT1_ID,
+ 5 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=5 text_offset=4 "
+ "affinity=downstream annotated_text=Line< >1",
+ "TextPosition tree_id=0 anchor_id=5 text_offset=4 "
+ "affinity=downstream annotated_text=Line< >1"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousWordEndPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ INLINE_BOX2_ID,
+ 4 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=9 text_offset=4 "
+ "affinity=downstream annotated_text=Line< >2"}}));
+
+INSTANTIATE_TEST_CASE_P(
+ CreateNextLineStartPositionWithBoundaryBehaviorCrossBoundary,
+ AXPositionTestWithParam,
+ testing::Values(
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextLineStartPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
ROOT_ID,
0 /* text_offset */,
@@ -1794,7 +2325,8 @@ INSTANTIATE_TEST_CASE_P(
"1\n<L>ine 2",
"NullPosition"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreateNextLineStartPosition();
+ return position->CreateNextLineStartPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
TEXT_FIELD_ID,
0 /* text_offset */,
@@ -1802,7 +2334,8 @@ INSTANTIATE_TEST_CASE_P(
"affinity=downstream annotated_text=Line 1\n<L>ine 2",
"NullPosition"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreateNextLineStartPosition();
+ return position->CreateNextLineStartPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
STATIC_TEXT1_ID,
1 /* text_offset */,
@@ -1810,18 +2343,105 @@ INSTANTIATE_TEST_CASE_P(
"affinity=downstream annotated_text=<L>ine 2",
"NullPosition"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreateNextLineStartPosition();
+ return position->CreateNextLineStartPosition(
+ AXBoundaryBehavior::CrossBoundary);
+ }),
+ INLINE_BOX2_ID,
+ 4 /* text_offset */,
+ {"NullPosition"}}));
+
+INSTANTIATE_TEST_CASE_P(
+ CreateNextLineStartPositionWithBoundaryBehaviorStopAtAnchorBoundary,
+ AXPositionTestWithParam,
+ testing::Values(
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextLineStartPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ ROOT_ID,
+ 0 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+ "affinity=downstream annotated_text=ButtonCheck box<L>ine "
+ "1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=22 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1\n<L>ine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=28 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1\nLine 2<>"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextLineStartPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ TEXT_FIELD_ID,
+ 0 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=4 text_offset=7 "
+ "affinity=downstream annotated_text=Line 1\n<L>ine 2",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=13 "
+ "affinity=downstream annotated_text=Line 1\nLine 2<>"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextLineStartPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ STATIC_TEXT1_ID,
+ 1 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=5 text_offset=6 "
+ "affinity=downstream annotated_text=Line 1<>"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextLineStartPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ INLINE_BOX2_ID,
+ 4 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=9 text_offset=6 "
+ "affinity=downstream annotated_text=Line 2<>"}}));
+
+INSTANTIATE_TEST_CASE_P(
+ CreateNextLineStartPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary,
+ AXPositionTestWithParam,
+ testing::Values(
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextLineStartPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ ROOT_ID,
+ 0 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=1 text_offset=0 "
+ "affinity=downstream annotated_text=<B>uttonCheck boxLine "
+ "1\nLine 2"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextLineStartPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ TEXT_FIELD_ID,
+ 0 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=4 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextLineStartPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ STATIC_TEXT1_ID,
+ 1 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 2",
+ "TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 2"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextLineStartPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
}),
INLINE_BOX2_ID,
4 /* text_offset */,
{"NullPosition"}}));
INSTANTIATE_TEST_CASE_P(
- CreatePreviousLineStartPosition,
+ CreatePreviousLineStartPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTestWithParam,
testing::Values(
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreatePreviousLineStartPosition();
+ return position->CreatePreviousLineStartPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
ROOT_ID,
28 /* text_offset at the end of root. */,
@@ -1836,7 +2456,8 @@ INSTANTIATE_TEST_CASE_P(
"1\nLine 2",
"NullPosition"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreatePreviousLineStartPosition();
+ return position->CreatePreviousLineStartPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
TEXT_FIELD_ID,
13 /* text_offset at end of text field */,
@@ -1848,7 +2469,8 @@ INSTANTIATE_TEST_CASE_P(
"affinity=downstream annotated_text=<B>utton",
"NullPosition"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreatePreviousLineStartPosition();
+ return position->CreatePreviousLineStartPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
STATIC_TEXT1_ID,
5 /* text_offset */,
@@ -1858,7 +2480,8 @@ INSTANTIATE_TEST_CASE_P(
"affinity=downstream annotated_text=<B>utton",
"NullPosition"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreatePreviousLineStartPosition();
+ return position->CreatePreviousLineStartPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
INLINE_BOX2_ID,
4 /* text_offset */,
@@ -1871,11 +2494,114 @@ INSTANTIATE_TEST_CASE_P(
"NullPosition"}}));
INSTANTIATE_TEST_CASE_P(
- CreateNextLineEndPosition,
+ CreatePreviousLineStartPositionWithBoundaryBehaviorStopAtAnchorBoundary,
AXPositionTestWithParam,
testing::Values(
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreateNextLineEndPosition();
+ return position->CreatePreviousLineStartPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ ROOT_ID,
+ 28 /* text_offset at the end of root. */,
+ {"TextPosition tree_id=0 anchor_id=1 text_offset=22 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1\n<L>ine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+ "affinity=downstream annotated_text=ButtonCheck box<L>ine "
+ "1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=0 "
+ "affinity=downstream annotated_text=<B>uttonCheck boxLine "
+ "1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=0 "
+ "affinity=downstream annotated_text=<B>uttonCheck boxLine "
+ "1\nLine 2"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousLineStartPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ TEXT_FIELD_ID,
+ 13 /* text_offset at end of text field */,
+ {"TextPosition tree_id=0 anchor_id=4 text_offset=7 "
+ "affinity=downstream annotated_text=Line 1\n<L>ine 2",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousLineStartPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ STATIC_TEXT1_ID,
+ 5 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=5 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 1",
+ "TextPosition tree_id=0 anchor_id=5 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 1"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousLineStartPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ INLINE_BOX2_ID,
+ 4 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 2",
+ "TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 2"}}));
+
+INSTANTIATE_TEST_CASE_P(
+ CreatePreviousLineStartPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary,
+ AXPositionTestWithParam,
+ testing::Values(
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousLineStartPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ ROOT_ID,
+ 28 /* text_offset at the end of root. */,
+ {"TextPosition tree_id=0 anchor_id=1 text_offset=22 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1\n<L>ine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=22 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1\n<L>ine 2"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousLineStartPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ TEXT_FIELD_ID,
+ 13 /* text_offset at end of text field */,
+ {"TextPosition tree_id=0 anchor_id=4 text_offset=7 "
+ "affinity=downstream annotated_text=Line 1\n<L>ine 2",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=7 "
+ "affinity=downstream annotated_text=Line 1\n<L>ine 2"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousLineStartPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ STATIC_TEXT1_ID,
+ 5 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=5 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 1",
+ "TextPosition tree_id=0 anchor_id=5 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 1"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousLineStartPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ INLINE_BOX2_ID,
+ 4 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 2",
+ "TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 2"}}));
+
+INSTANTIATE_TEST_CASE_P(
+ CreateNextLineEndPositionWithBoundaryBehaviorCrossBoundary,
+ AXPositionTestWithParam,
+ testing::Values(
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextLineEndPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
ROOT_ID,
0 /* text_offset */,
@@ -1890,7 +2616,8 @@ INSTANTIATE_TEST_CASE_P(
"1\nLine 2<>",
"NullPosition"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreateNextLineEndPosition();
+ return position->CreateNextLineEndPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
TEXT_FIELD_ID,
0 /* text_offset */,
@@ -1900,7 +2627,8 @@ INSTANTIATE_TEST_CASE_P(
"affinity=downstream annotated_text=Line 1\nLine 2<>",
"NullPosition"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreateNextLineEndPosition();
+ return position->CreateNextLineEndPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
STATIC_TEXT1_ID,
1 /* text_offset */,
@@ -1910,7 +2638,8 @@ INSTANTIATE_TEST_CASE_P(
"affinity=downstream annotated_text=Line 2<>",
"NullPosition"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreateNextLineEndPosition();
+ return position->CreateNextLineEndPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
INLINE_BOX2_ID,
4 /* text_offset */,
@@ -1919,7 +2648,112 @@ INSTANTIATE_TEST_CASE_P(
"NullPosition"}}));
INSTANTIATE_TEST_CASE_P(
- CreatePreviousLineEndPosition,
+ CreateNextLineEndPositionWithBoundaryBehaviorStopAtAnchorBoundary,
+ AXPositionTestWithParam,
+ testing::Values(
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextLineEndPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ ROOT_ID,
+ 0 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+ "affinity=downstream annotated_text=ButtonCheck box<L>ine "
+ "1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=21 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine 1"
+ "<\n>Line 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=28 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1\nLine 2<>",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=28 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1\nLine 2<>"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextLineEndPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ TEXT_FIELD_ID,
+ 0 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=4 text_offset=6 "
+ "affinity=downstream annotated_text=Line 1<\n>Line 2",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=13 "
+ "affinity=downstream annotated_text=Line 1\nLine 2<>",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=13 "
+ "affinity=downstream annotated_text=Line 1\nLine 2<>"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextLineEndPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ STATIC_TEXT1_ID,
+ 1 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=5 text_offset=6 "
+ "affinity=downstream annotated_text=Line 1<>",
+ "TextPosition tree_id=0 anchor_id=5 text_offset=6 "
+ "affinity=downstream annotated_text=Line 1<>"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextLineEndPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ INLINE_BOX2_ID,
+ 4 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=9 text_offset=6 "
+ "affinity=downstream annotated_text=Line 2<>",
+ "TextPosition tree_id=0 anchor_id=9 text_offset=6 "
+ "affinity=downstream annotated_text=Line 2<>"}}));
+
+INSTANTIATE_TEST_CASE_P(
+ CreateNextLineEndPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary,
+ AXPositionTestWithParam,
+ testing::Values(
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextLineEndPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ ROOT_ID,
+ 0 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+ "affinity=downstream annotated_text=ButtonCheck box<L>ine "
+ "1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=21 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1<\n>Line 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=21 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1<\n>Line 2"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextLineEndPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ TEXT_FIELD_ID,
+ 0 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=4 text_offset=6 "
+ "affinity=downstream annotated_text=Line 1<\n>Line 2",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=6 "
+ "affinity=downstream annotated_text=Line 1<\n>Line 2"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextLineEndPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ STATIC_TEXT1_ID,
+ 1 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=5 text_offset=6 "
+ "affinity=downstream annotated_text=Line 1<>",
+ "TextPosition tree_id=0 anchor_id=5 text_offset=6 "
+ "affinity=downstream annotated_text=Line 1<>"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreateNextLineEndPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ INLINE_BOX2_ID,
+ 4 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=9 text_offset=6 "
+ "affinity=downstream annotated_text=Line 2<>",
+ "TextPosition tree_id=0 anchor_id=9 text_offset=6 "
+ "affinity=downstream annotated_text=Line 2<>"}}));
+
+INSTANTIATE_TEST_CASE_P(
+ CreatePreviousLineEndPositionWithBoundaryBehaviorCrossBoundary,
AXPositionTestWithParam,
testing::Values(
// Note that for the first test, we can't go past the line ending at the
@@ -1928,7 +2762,8 @@ INSTANTIATE_TEST_CASE_P(
// the beginning of the first line in the text field, and so an infinite
// recursion will occur.
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreatePreviousLineEndPosition();
+ return position->CreatePreviousLineEndPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
ROOT_ID,
28 /* text_offset at end of root. */,
@@ -1939,7 +2774,8 @@ INSTANTIATE_TEST_CASE_P(
"affinity=downstream annotated_text=ButtonCheck box<L>ine "
"1\nLine 2"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreatePreviousLineEndPosition();
+ return position->CreatePreviousLineEndPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
TEXT_FIELD_ID,
13 /* text_offset at end of text field */,
@@ -1949,7 +2785,8 @@ INSTANTIATE_TEST_CASE_P(
"affinity=downstream annotated_text=Check box<>",
"NullPosition"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreatePreviousLineEndPosition();
+ return position->CreatePreviousLineEndPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
INLINE_BOX2_ID,
4 /* text_offset */,
@@ -1959,7 +2796,8 @@ INSTANTIATE_TEST_CASE_P(
"affinity=downstream annotated_text=Check box<>",
"NullPosition"}},
TestParam{base::BindRepeating([](const TestPositionType& position) {
- return position->CreatePreviousLineEndPosition();
+ return position->CreatePreviousLineEndPosition(
+ AXBoundaryBehavior::CrossBoundary);
}),
INLINE_BOX2_ID,
0 /* text_offset */,
@@ -1969,6 +2807,104 @@ INSTANTIATE_TEST_CASE_P(
"affinity=downstream annotated_text=Check box<>",
"NullPosition"}}));
+INSTANTIATE_TEST_CASE_P(
+ CreatePreviousLineEndPositionWithBoundaryBehaviorStopAtAnchorBoundary,
+ AXPositionTestWithParam,
+ testing::Values(
+ // Note that for the first test, we can't go past the line ending at the
+ // check box to test for a position at start of anchor, because the tree
+ // position that is at the end of the check box is equivalent to the one
+ // that is at the beginning of the first line in the text field, and so
+ // an infinite recursion will occur.
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousLineEndPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ ROOT_ID,
+ 28 /* text_offset at end of root. */,
+ {"TextPosition tree_id=0 anchor_id=1 text_offset=21 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1<\n>Line 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+ "affinity=downstream annotated_text=ButtonCheck box<L>ine "
+ "1\nLine 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=15 "
+ "affinity=downstream annotated_text=ButtonCheck box<L>ine "
+ "1\nLine 2"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousLineEndPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ TEXT_FIELD_ID,
+ 13 /* text_offset at end of text field */,
+ {"TextPosition tree_id=0 anchor_id=4 text_offset=6 "
+ "affinity=downstream annotated_text=Line 1<\n>Line 2",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 1\nLine 2"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousLineEndPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ INLINE_BOX2_ID,
+ 4 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 2"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousLineEndPosition(
+ AXBoundaryBehavior::StopAtAnchorBoundary);
+ }),
+ INLINE_BOX2_ID,
+ 0 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=9 text_offset=0 "
+ "affinity=downstream annotated_text=<L>ine 2"}}));
+
+INSTANTIATE_TEST_CASE_P(
+ CreatePreviousLineEndPositionWithBoundaryBehaviorStopIfAlreadyAtBoundary,
+ AXPositionTestWithParam,
+ testing::Values(
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousLineEndPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ ROOT_ID,
+ 27 /* text_offset one before the end of root. */,
+ {"TextPosition tree_id=0 anchor_id=1 text_offset=21 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1<\n>Line 2",
+ "TextPosition tree_id=0 anchor_id=1 text_offset=21 "
+ "affinity=downstream annotated_text=ButtonCheck boxLine "
+ "1<\n>Line 2"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousLineEndPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ TEXT_FIELD_ID,
+ 12 /* text_offset one before the end of text field */,
+ {"TextPosition tree_id=0 anchor_id=4 text_offset=6 "
+ "affinity=downstream annotated_text=Line 1<\n>Line 2",
+ "TextPosition tree_id=0 anchor_id=4 text_offset=6 "
+ "affinity=downstream annotated_text=Line 1<\n>Line 2"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousLineEndPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ INLINE_BOX2_ID,
+ 4 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=6 text_offset=6 "
+ "affinity=downstream annotated_text=Line 1<>",
+ "TextPosition tree_id=0 anchor_id=6 text_offset=6 "
+ "affinity=downstream annotated_text=Line 1<>"}},
+ TestParam{base::BindRepeating([](const TestPositionType& position) {
+ return position->CreatePreviousLineEndPosition(
+ AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ }),
+ INLINE_BOX2_ID,
+ 0 /* text_offset */,
+ {"TextPosition tree_id=0 anchor_id=6 text_offset=6 "
+ "affinity=downstream annotated_text=Line 1<>",
+ "TextPosition tree_id=0 anchor_id=6 text_offset=6 "
+ "affinity=downstream annotated_text=Line 1<>"}}));
+
//
// Tests for |AXRange|.
//
diff --git a/chromium/ui/accessibility/ax_position.h b/chromium/ui/accessibility/ax_position.h
index c38d9511128..9e70b2521df 100644
--- a/chromium/ui/accessibility/ax_position.h
+++ b/chromium/ui/accessibility/ax_position.h
@@ -30,6 +30,15 @@ namespace ui {
// a boundary has been reached.
enum class AXPositionKind { NULL_POSITION, TREE_POSITION, TEXT_POSITION };
+// Defines how creating the next or previous position should behave whenever we
+// are at or are crossing a boundary, such as at the start of an anchor, a word
+// or a line.
+enum class AXBoundaryBehavior {
+ CrossBoundary,
+ StopAtAnchorBoundary,
+ StopIfAlreadyAtBoundary
+};
+
// Forward declarations.
template <class AXPositionType, class AXNodeType>
class AXPosition;
@@ -296,8 +305,15 @@ class AXPosition {
NOTREACHED();
return false;
case AXPositionKind::TEXT_POSITION:
- return !text_position->IsInLineBreak() &&
- GetNextOnLineID(text_position->anchor_id_) ==
+ // Special case, when the caret is right before a line break and the
+ // previous position is not another line break. We should return |true|
+ // because visually the caret is at the end of the current line.
+ if (text_position->IsInLineBreak()) {
+ return text_position->AtStartOfAnchor() &&
+ !text_position->CreatePreviousTextAnchorPosition()
+ ->IsInLineBreak();
+ }
+ return GetNextOnLineID(text_position->anchor_id_) ==
INVALID_ANCHOR_ID &&
text_position->AtEndOfAnchor();
}
@@ -343,31 +359,34 @@ class AXPosition {
AXPositionInstance copy = Clone();
DCHECK(copy);
- DCHECK_NE(copy->text_offset_, INVALID_OFFSET);
- // If the anchor node has no text inside it then the child index should be
- // set to |BEFORE_TEXT|, hence the check if |MaxTextOffset| is greater than
- // 0.
- if (copy->MaxTextOffset() > 0 &&
- copy->text_offset_ >= copy->MaxTextOffset()) {
- copy->child_index_ = copy->AnchorChildCount();
- } else {
- DCHECK_GE(copy->text_offset_, 0);
+ DCHECK_GE(copy->text_offset_, 0);
+ if (!copy->AnchorChildCount() &&
+ copy->text_offset_ != copy->MaxTextOffset()) {
copy->child_index_ = BEFORE_TEXT;
+ } else {
+ copy->child_index_ = 0;
+ }
- int current_offset = 0;
- for (int i = 0; i < copy->AnchorChildCount(); ++i) {
- AXPositionInstance child = copy->CreateChildPositionAt(i);
- DCHECK(child);
- int child_length = child->MaxTextOffsetInParent();
- if (copy->text_offset_ >= current_offset &&
- copy->text_offset_ < (current_offset + child_length)) {
- copy->child_index_ = i;
- break;
- }
-
- current_offset += child_length;
+ // Blink doesn't always remove all deleted whitespace at the end of a
+ // textarea even though it will have adjusted its value attribute, because
+ // the extra layout objects are invisible. Therefore, we will stop at the
+ // last child that we can reach with the current text offset and ignore any
+ // remaining children.
+ int current_offset = 0;
+ for (int i = 0; i < copy->AnchorChildCount(); ++i) {
+ AXPositionInstance child = copy->CreateChildPositionAt(i);
+ DCHECK(child);
+ int child_length = child->MaxTextOffsetInParent();
+ if (copy->text_offset_ >= current_offset &&
+ copy->text_offset_ < (current_offset + child_length)) {
+ copy->child_index_ = i;
+ break;
}
+
+ current_offset += child_length;
}
+ if (current_offset >= copy->MaxTextOffset())
+ copy->child_index_ = copy->AnchorChildCount();
copy->kind_ = AXPositionKind::TREE_POSITION;
return copy;
@@ -422,34 +441,22 @@ class AXPosition {
if (IsNullPosition() || !AnchorChildCount())
return AsTextPosition();
- AXPositionInstance child_position;
AXPositionInstance tree_position = AsTreePosition();
- // If we get an "after children" position, we should return an "after
- // children" position on the last child and recurse.
- if (tree_position->AtEndOfAnchor()) {
- child_position =
- tree_position->CreateChildPositionAt(AnchorChildCount() - 1);
- // Affinity needs to be maintained, because we are not moving the position
- // but simply changing the anchor to the deepest leaf.
- child_position->affinity_ = affinity_;
- return child_position->CreatePositionAtEndOfAnchor()
- ->AsLeafTextPosition();
- }
-
// Adjust the text offset.
// No need to check for "before text" positions here because they are only
// present on leaf anchor nodes.
int adjusted_offset = AsTextPosition()->text_offset_;
- for (int i = 0; i < tree_position->child_index_; ++i) {
+ AXPositionInstance child_position = tree_position->CreateChildPositionAt(0);
+ DCHECK(child_position);
+ for (int i = 1; i <= tree_position->child_index_ &&
+ i < tree_position->AnchorChildCount();
+ ++i) {
+ adjusted_offset -= child_position->MaxTextOffsetInParent();
child_position = tree_position->CreateChildPositionAt(i);
DCHECK(child_position);
- adjusted_offset -= child_position->MaxTextOffsetInParent();
}
- DCHECK_GE(adjusted_offset, 0);
- child_position =
- tree_position->CreateChildPositionAt(tree_position->child_index_)
- ->AsTextPosition();
+ child_position = child_position->AsTextPosition();
child_position->text_offset_ = adjusted_offset;
// Affinity needs to be maintained, because we are not moving the position
// but simply changing the anchor to the deepest leaf.
@@ -580,14 +587,21 @@ class AXPosition {
return previous_leaf->AsTextPosition();
}
- // The following methods work across anchors.
-
- AXPositionInstance CreateNextCharacterPosition() const {
+ AXPositionInstance CreateNextCharacterPosition(
+ AXBoundaryBehavior boundary_behavior) const {
bool was_tree_position = IsTreePosition();
AXPositionInstance text_position = AsTextPosition();
if (text_position->IsNullPosition())
return text_position;
+ // Note that |BoundaryBehavior::StopIfAlreadyAtBoundary| doesn't make
+ // sense for character boundaries.
+ DCHECK_NE(boundary_behavior, AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary &&
+ (text_position->text_offset_ + 1) >= text_position->MaxTextOffset()) {
+ return Clone();
+ }
+
if ((text_position->text_offset_ + 1) < text_position->MaxTextOffset()) {
text_position->text_offset_ += 1;
// Even if our affinity was upstream, moving to the next character should
@@ -606,7 +620,16 @@ class AXPosition {
return text_position;
}
- AXPositionInstance CreatePreviousCharacterPosition() const {
+ AXPositionInstance CreatePreviousCharacterPosition(
+ AXBoundaryBehavior boundary_behavior) const {
+ // Note that |BoundaryBehavior::StopIfAlreadyAtBoundary| doesn't make
+ // sense for character boundaries.
+ DCHECK_NE(boundary_behavior, AXBoundaryBehavior::StopIfAlreadyAtBoundary);
+ if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary &&
+ AtStartOfAnchor()) {
+ return Clone();
+ }
+
bool was_tree_position = IsTreePosition();
AXPositionInstance text_position = AsTextPosition();
if (text_position->IsNullPosition())
@@ -629,11 +652,18 @@ class AXPosition {
return text_position;
}
- AXPositionInstance CreateNextWordStartPosition() const {
+ AXPositionInstance CreateNextWordStartPosition(
+ AXBoundaryBehavior boundary_behavior) const {
bool was_tree_position = IsTreePosition();
AXPositionInstance text_position = AsLeafTextPosition();
if (text_position->IsNullPosition())
return text_position;
+ if (boundary_behavior == AXBoundaryBehavior::StopIfAlreadyAtBoundary &&
+ text_position->AtStartOfWord()) {
+ AXPositionInstance clone = Clone();
+ clone->affinity_ = AX_TEXT_AFFINITY_DOWNSTREAM;
+ return clone;
+ }
const std::vector<int32_t> word_starts =
text_position->GetWordStartOffsets();
@@ -647,8 +677,11 @@ class AXPosition {
} while (!text_position->IsNullPosition() &&
(!text_position->MaxTextOffset() ||
text_position->GetWordStartOffsets().empty()));
- if (text_position->IsNullPosition())
+ if (text_position->IsNullPosition()) {
+ if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary)
+ return CreatePositionAtEndOfAnchor();
return text_position;
+ }
const std::vector<int32_t> word_starts =
text_position->GetWordStartOffsets();
@@ -665,24 +698,37 @@ class AXPosition {
// be in the shadow DOM if the original position was not.
AXPositionInstance common_ancestor =
text_position->LowestCommonAncestor(*this);
- if (GetAnchor() == common_ancestor->GetAnchor())
+ if (GetAnchor() == common_ancestor->GetAnchor()) {
text_position = std::move(common_ancestor);
+ } else if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) {
+ return CreatePositionAtEndOfAnchor();
+ }
if (was_tree_position)
text_position = text_position->AsTreePosition();
return text_position;
}
- AXPositionInstance CreatePreviousWordStartPosition() const {
+ AXPositionInstance CreatePreviousWordStartPosition(
+ AXBoundaryBehavior boundary_behavior) const {
bool was_tree_position = IsTreePosition();
AXPositionInstance text_position = AsLeafTextPosition();
+ if (boundary_behavior == AXBoundaryBehavior::StopIfAlreadyAtBoundary &&
+ text_position->AtStartOfWord()) {
+ AXPositionInstance clone = Clone();
+ clone->affinity_ = AX_TEXT_AFFINITY_DOWNSTREAM;
+ return clone;
+ }
if (text_position->AtStartOfAnchor()) {
text_position = text_position->CreatePreviousTextAnchorPosition();
text_position = text_position->CreatePositionAtEndOfAnchor();
}
- if (text_position->IsNullPosition())
+ if (text_position->IsNullPosition()) {
+ if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary)
+ return CreatePositionAtStartOfAnchor();
return text_position;
+ }
const std::vector<int32_t> word_starts =
text_position->GetWordStartOffsets();
@@ -696,8 +742,11 @@ class AXPosition {
} while (!text_position->IsNullPosition() &&
(!text_position->MaxTextOffset() ||
text_position->GetWordStartOffsets().empty()));
- if (text_position->IsNullPosition())
+ if (text_position->IsNullPosition()) {
+ if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary)
+ return CreatePositionAtStartOfAnchor();
return text_position;
+ }
const std::vector<int32_t> word_starts =
text_position->GetWordStartOffsets();
@@ -714,8 +763,11 @@ class AXPosition {
// be in the shadow DOM if the original position was not.
AXPositionInstance common_ancestor =
text_position->LowestCommonAncestor(*this);
- if (GetAnchor() == common_ancestor->GetAnchor())
+ if (GetAnchor() == common_ancestor->GetAnchor()) {
text_position = std::move(common_ancestor);
+ } else if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) {
+ return CreatePositionAtStartOfAnchor();
+ }
if (was_tree_position)
text_position = text_position->AsTreePosition();
@@ -723,14 +775,24 @@ class AXPosition {
}
// Word end positions are one past the last character of the word.
- AXPositionInstance CreateNextWordEndPosition() const {
+ AXPositionInstance CreateNextWordEndPosition(
+ AXBoundaryBehavior boundary_behavior) const {
bool was_tree_position = IsTreePosition();
AXPositionInstance text_position = AsLeafTextPosition();
+ if (boundary_behavior == AXBoundaryBehavior::StopIfAlreadyAtBoundary &&
+ text_position->AtEndOfWord()) {
+ AXPositionInstance clone = Clone();
+ clone->affinity_ = AX_TEXT_AFFINITY_DOWNSTREAM;
+ return clone;
+ }
if (text_position->AtEndOfAnchor())
text_position = text_position->CreateNextTextAnchorPosition();
- if (text_position->IsNullPosition())
+ if (text_position->IsNullPosition()) {
+ if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary)
+ return CreatePositionAtEndOfAnchor();
return text_position;
+ }
const std::vector<int32_t> word_ends = text_position->GetWordEndOffsets();
auto iterator =
@@ -743,8 +805,11 @@ class AXPosition {
} while (!text_position->IsNullPosition() &&
(!text_position->MaxTextOffset() ||
text_position->GetWordEndOffsets().empty()));
- if (text_position->IsNullPosition())
+ if (text_position->IsNullPosition()) {
+ if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary)
+ return CreatePositionAtEndOfAnchor();
return text_position;
+ }
const std::vector<int32_t> word_ends = text_position->GetWordEndOffsets();
DCHECK(!word_ends.empty());
@@ -760,8 +825,11 @@ class AXPosition {
// be in the shadow DOM if the original position was not.
AXPositionInstance common_ancestor =
text_position->LowestCommonAncestor(*this);
- if (GetAnchor() == common_ancestor->GetAnchor())
+ if (GetAnchor() == common_ancestor->GetAnchor()) {
text_position = std::move(common_ancestor);
+ } else if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) {
+ return CreatePositionAtEndOfAnchor();
+ }
if (was_tree_position)
text_position = text_position->AsTreePosition();
@@ -769,16 +837,26 @@ class AXPosition {
}
// Word end positions are one past the last character of the word.
- AXPositionInstance CreatePreviousWordEndPosition() const {
+ AXPositionInstance CreatePreviousWordEndPosition(
+ AXBoundaryBehavior boundary_behavior) const {
bool was_tree_position = IsTreePosition();
AXPositionInstance text_position = AsLeafTextPosition();
+ if (boundary_behavior == AXBoundaryBehavior::StopIfAlreadyAtBoundary &&
+ text_position->AtEndOfWord()) {
+ AXPositionInstance clone = Clone();
+ clone->affinity_ = AX_TEXT_AFFINITY_DOWNSTREAM;
+ return clone;
+ }
if (text_position->AtStartOfAnchor()) {
text_position = text_position->CreatePreviousTextAnchorPosition();
text_position = text_position->CreatePositionAtEndOfAnchor();
}
- if (text_position->IsNullPosition())
+ if (text_position->IsNullPosition()) {
+ if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary)
+ return CreatePositionAtStartOfAnchor();
return text_position;
+ }
const std::vector<int32_t> word_ends = text_position->GetWordEndOffsets();
auto iterator =
@@ -791,8 +869,11 @@ class AXPosition {
} while (!text_position->IsNullPosition() &&
(!text_position->MaxTextOffset() ||
text_position->GetWordStartOffsets().empty()));
- if (text_position->IsNullPosition())
+ if (text_position->IsNullPosition()) {
+ if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary)
+ return CreatePositionAtStartOfAnchor();
return text_position;
+ }
const std::vector<int32_t> word_ends = text_position->GetWordEndOffsets();
DCHECK(!word_ends.empty());
@@ -808,19 +889,29 @@ class AXPosition {
// be in the shadow DOM if the original position was not.
AXPositionInstance common_ancestor =
text_position->LowestCommonAncestor(*this);
- if (GetAnchor() == common_ancestor->GetAnchor())
+ if (GetAnchor() == common_ancestor->GetAnchor()) {
text_position = std::move(common_ancestor);
+ } else if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) {
+ return CreatePositionAtStartOfAnchor();
+ }
if (was_tree_position)
text_position = text_position->AsTreePosition();
return text_position;
}
- AXPositionInstance CreateNextLineStartPosition() const {
+ AXPositionInstance CreateNextLineStartPosition(
+ AXBoundaryBehavior boundary_behavior) const {
bool was_tree_position = IsTreePosition();
AXPositionInstance text_position = AsLeafTextPosition();
if (text_position->IsNullPosition())
return text_position;
+ if (boundary_behavior == AXBoundaryBehavior::StopIfAlreadyAtBoundary &&
+ text_position->AtStartOfLine()) {
+ AXPositionInstance clone = Clone();
+ clone->affinity_ = AX_TEXT_AFFINITY_DOWNSTREAM;
+ return clone;
+ }
// Find the next line break.
int32_t next_on_line_id = text_position->anchor_id_;
@@ -833,8 +924,11 @@ class AXPosition {
text_position->AsLeafTextPosition()->CreateNextTextAnchorPosition();
while (text_position->IsInLineBreak())
text_position = text_position->CreateNextTextAnchorPosition();
- if (text_position->IsNullPosition())
+ if (text_position->IsNullPosition()) {
+ if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary)
+ return CreatePositionAtEndOfAnchor();
return text_position;
+ }
// If the line boundary is in the same subtree, return a position rooted at
// the current position.
@@ -842,21 +936,35 @@ class AXPosition {
// be in the shadow DOM if the original position was not.
AXPositionInstance common_ancestor =
text_position->LowestCommonAncestor(*this);
- if (GetAnchor() == common_ancestor->GetAnchor())
+ if (GetAnchor() == common_ancestor->GetAnchor()) {
text_position = std::move(common_ancestor);
+ } else if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) {
+ return CreatePositionAtEndOfAnchor();
+ }
if (was_tree_position)
text_position = text_position->AsTreePosition();
return text_position;
}
- AXPositionInstance CreatePreviousLineStartPosition() const {
+ AXPositionInstance CreatePreviousLineStartPosition(
+ AXBoundaryBehavior boundary_behavior) const {
bool was_tree_position = IsTreePosition();
AXPositionInstance text_position = AsLeafTextPosition();
+ if (boundary_behavior == AXBoundaryBehavior::StopIfAlreadyAtBoundary &&
+ text_position->AtStartOfLine()) {
+ AXPositionInstance clone = Clone();
+ clone->affinity_ = AX_TEXT_AFFINITY_DOWNSTREAM;
+ return clone;
+ }
+
if (text_position->IsInLineBreak() || text_position->AtStartOfAnchor())
text_position = text_position->CreatePreviousTextAnchorPosition();
- if (text_position->IsNullPosition())
+ if (text_position->IsNullPosition()) {
+ if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary)
+ return CreatePositionAtStartOfAnchor();
return text_position;
+ }
int32_t previous_on_line_id = text_position->anchor_id_;
while (GetPreviousOnLineID(previous_on_line_id) != INVALID_ANCHOR_ID)
@@ -865,8 +973,11 @@ class AXPosition {
CreateTextPosition(tree_id_, previous_on_line_id, 0 /* text_offset */,
AX_TEXT_AFFINITY_DOWNSTREAM);
text_position = text_position->AsLeafTextPosition();
- if (text_position->IsNullPosition())
+ if (text_position->IsNullPosition()) {
+ if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary)
+ return CreatePositionAtStartOfAnchor();
return text_position;
+ }
// If the line boundary is in the same subtree, return a position rooted at
// the current position.
@@ -874,8 +985,11 @@ class AXPosition {
// be in the shadow DOM if the original position was not.
AXPositionInstance common_ancestor =
text_position->LowestCommonAncestor(*this);
- if (GetAnchor() == common_ancestor->GetAnchor())
+ if (GetAnchor() == common_ancestor->GetAnchor()) {
text_position = std::move(common_ancestor);
+ } else if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) {
+ return CreatePositionAtStartOfAnchor();
+ }
if (was_tree_position)
text_position = text_position->AsTreePosition();
@@ -884,15 +998,26 @@ class AXPosition {
// Line end positions are one past the last character of the line, excluding
// any newline characters.
- AXPositionInstance CreateNextLineEndPosition() const {
+ AXPositionInstance CreateNextLineEndPosition(
+ AXBoundaryBehavior boundary_behavior) const {
bool was_tree_position = IsTreePosition();
AXPositionInstance text_position = AsLeafTextPosition();
+ if (boundary_behavior == AXBoundaryBehavior::StopIfAlreadyAtBoundary &&
+ text_position->AtEndOfLine()) {
+ AXPositionInstance clone = Clone();
+ clone->affinity_ = AX_TEXT_AFFINITY_DOWNSTREAM;
+ return clone;
+ }
+
// Skip forward to the next line if we are at the end of one.
// Note that not all lines end with a hard line break.
while (text_position->IsInLineBreak() || text_position->AtEndOfAnchor())
text_position = text_position->CreateNextTextAnchorPosition();
- if (text_position->IsNullPosition())
+ if (text_position->IsNullPosition()) {
+ if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary)
+ return CreatePositionAtEndOfAnchor();
return text_position;
+ }
// Find the next line break.
int32_t next_on_line_id = text_position->anchor_id_;
@@ -904,8 +1029,11 @@ class AXPosition {
text_position = text_position->AsLeafTextPosition();
while (text_position->IsInLineBreak())
text_position = text_position->CreatePreviousTextAnchorPosition();
- if (text_position->IsNullPosition())
+ if (text_position->IsNullPosition()) {
+ if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary)
+ return CreatePositionAtEndOfAnchor();
return text_position;
+ }
text_position = text_position->CreatePositionAtEndOfAnchor();
// If the line boundary is in the same subtree, return a position rooted at
@@ -914,8 +1042,11 @@ class AXPosition {
// be in the shadow DOM if the original position was not.
AXPositionInstance common_ancestor =
text_position->LowestCommonAncestor(*this);
- if (GetAnchor() == common_ancestor->GetAnchor())
+ if (GetAnchor() == common_ancestor->GetAnchor()) {
text_position = std::move(common_ancestor);
+ } else if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) {
+ return CreatePositionAtEndOfAnchor();
+ }
if (was_tree_position)
text_position = text_position->AsTreePosition();
@@ -924,11 +1055,18 @@ class AXPosition {
// Line end positions are one past the last character of the line, excluding
// any newline characters.
- AXPositionInstance CreatePreviousLineEndPosition() const {
+ AXPositionInstance CreatePreviousLineEndPosition(
+ AXBoundaryBehavior boundary_behavior) const {
bool was_tree_position = IsTreePosition();
AXPositionInstance text_position = AsLeafTextPosition();
if (text_position->IsNullPosition())
return text_position;
+ if (boundary_behavior == AXBoundaryBehavior::StopIfAlreadyAtBoundary &&
+ text_position->AtEndOfLine()) {
+ AXPositionInstance clone = Clone();
+ clone->affinity_ = AX_TEXT_AFFINITY_DOWNSTREAM;
+ return clone;
+ }
int32_t previous_on_line_id = text_position->anchor_id_;
while (GetPreviousOnLineID(previous_on_line_id) != INVALID_ANCHOR_ID)
@@ -940,8 +1078,11 @@ class AXPosition {
text_position->AsLeafTextPosition()->CreatePreviousTextAnchorPosition();
while (text_position->IsInLineBreak())
text_position = text_position->CreatePreviousTextAnchorPosition();
- if (text_position->IsNullPosition())
+ if (text_position->IsNullPosition()) {
+ if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary)
+ return CreatePositionAtStartOfAnchor();
return text_position;
+ }
text_position = text_position->CreatePositionAtEndOfAnchor();
// If the line boundary is in the same subtree, return a position rooted at
@@ -950,8 +1091,11 @@ class AXPosition {
// be in the shadow DOM if the original position was not.
AXPositionInstance common_ancestor =
text_position->LowestCommonAncestor(*this);
- if (GetAnchor() == common_ancestor->GetAnchor())
+ if (GetAnchor() == common_ancestor->GetAnchor()) {
text_position = std::move(common_ancestor);
+ } else if (boundary_behavior == AXBoundaryBehavior::StopAtAnchorBoundary) {
+ return CreatePositionAtStartOfAnchor();
+ }
if (was_tree_position)
text_position = text_position->AsTreePosition();
@@ -1047,7 +1191,7 @@ class AXPosition {
if (parent_position->IsNullPosition())
return CreateNullPosition();
- // Get the previous sibling's deepest first child if a previous sibling
+ // Get the previous sibling's deepest last child if a previous sibling
// exists, otherwise move up to the parent.
int index_in_parent = AnchorIndexInParent();
if (index_in_parent <= 0)
@@ -1056,7 +1200,7 @@ class AXPosition {
AXPositionInstance leaf =
parent_position->CreateChildPositionAt(index_in_parent - 1);
while (!leaf->IsNullPosition() && leaf->AnchorChildCount())
- leaf = leaf->CreateChildPositionAt(0);
+ leaf = leaf->CreateChildPositionAt(leaf->AnchorChildCount() - 1);
return leaf;
}
diff --git a/chromium/ui/accessibility/ax_role_properties.cc b/chromium/ui/accessibility/ax_role_properties.cc
index 34355fea453..e0e44547018 100644
--- a/chromium/ui/accessibility/ax_role_properties.cc
+++ b/chromium/ui/accessibility/ax_role_properties.cc
@@ -12,7 +12,6 @@ bool IsRoleClickable(AXRole role) {
case AX_ROLE_CHECK_BOX:
case AX_ROLE_COLOR_WELL:
case AX_ROLE_DISCLOSURE_TRIANGLE:
- case AX_ROLE_IMAGE_MAP_LINK:
case AX_ROLE_LINK:
case AX_ROLE_LIST_BOX_OPTION:
case AX_ROLE_MENU_BUTTON:
diff --git a/chromium/ui/accessibility/ax_tree.cc b/chromium/ui/accessibility/ax_tree.cc
index d2c7f0d524f..734be5fefee 100644
--- a/chromium/ui/accessibility/ax_tree.cc
+++ b/chromium/ui/accessibility/ax_tree.cc
@@ -189,19 +189,31 @@ gfx::RectF AXTree::RelativeToTreeBounds(const AXNode* node,
while (node != nullptr) {
if (node->data().transform)
node->data().transform->TransformRect(&bounds);
- auto* container = GetFromId(node->data().offset_container_id);
- if (!container) {
- if (node == root())
- container = node->parent();
- else
- container = root();
- }
+ const AXNode* container;
+
+ // Normally we apply any transforms and offsets for each node and
+ // then walk up to its offset container - however, if the node has
+ // no width or height, walk up to its nearest ancestor until we find
+ // one that has bounds.
+ if (bounds.width() == 0 && bounds.height() == 0)
+ container = node->parent();
+ else
+ container = GetFromId(node->data().offset_container_id);
+ if (!container && container != root())
+ container = root();
if (!container || container == node)
break;
gfx::RectF container_bounds = container->data().location;
bounds.Offset(container_bounds.x(), container_bounds.y());
+ // If we don't have any size yet, take the size from this ancestor.
+ // The rationale is that it's not useful to the user for an object to
+ // have no width or height and it's probably a bug; it's better to
+ // reflect the bounds of the nearest ancestor rather than a 0x0 box.
+ if (bounds.width() == 0 && bounds.height() == 0)
+ bounds.set_size(container_bounds.size());
+
int scroll_x = 0;
int scroll_y = 0;
if (container->data().GetIntAttribute(ui::AX_ATTR_SCROLL_X, &scroll_x) &&
diff --git a/chromium/ui/accessibility/ax_tree.h b/chromium/ui/accessibility/ax_tree.h
index 95885decacb..c45f53afbad 100644
--- a/chromium/ui/accessibility/ax_tree.h
+++ b/chromium/ui/accessibility/ax_tree.h
@@ -163,6 +163,7 @@ class AX_EXPORT AXTree {
virtual ~AXTree();
virtual void SetDelegate(AXTreeDelegate* delegate);
+ AXTreeDelegate* delegate() const { return delegate_; }
AXNode* root() const { return root_; }
diff --git a/chromium/ui/accessibility/ax_tree_unittest.cc b/chromium/ui/accessibility/ax_tree_unittest.cc
index 144b9f93833..0bcc650ae13 100644
--- a/chromium/ui/accessibility/ax_tree_unittest.cc
+++ b/chromium/ui/accessibility/ax_tree_unittest.cc
@@ -662,7 +662,7 @@ TEST(AXTreeTest, AttributeChangeCallbacks) {
initial_state.nodes[0].AddStringAttribute(AX_ATTR_NAME, "N1");
initial_state.nodes[0].AddStringAttribute(AX_ATTR_DESCRIPTION, "D1");
initial_state.nodes[0].AddBoolAttribute(AX_ATTR_LIVE_ATOMIC, true);
- initial_state.nodes[0].AddBoolAttribute(AX_ATTR_LIVE_BUSY, false);
+ initial_state.nodes[0].AddBoolAttribute(AX_ATTR_BUSY, false);
initial_state.nodes[0].AddFloatAttribute(AX_ATTR_MIN_VALUE_FOR_RANGE, 1.0);
initial_state.nodes[0].AddFloatAttribute(AX_ATTR_MAX_VALUE_FOR_RANGE, 10.0);
initial_state.nodes[0].AddIntAttribute(AX_ATTR_SCROLL_X, 5);
@@ -680,7 +680,7 @@ TEST(AXTreeTest, AttributeChangeCallbacks) {
update0.nodes[0].AddStringAttribute(AX_ATTR_NAME, "N2");
update0.nodes[0].AddStringAttribute(AX_ATTR_DESCRIPTION, "D2");
update0.nodes[0].AddBoolAttribute(AX_ATTR_LIVE_ATOMIC, false);
- update0.nodes[0].AddBoolAttribute(AX_ATTR_LIVE_BUSY, true);
+ update0.nodes[0].AddBoolAttribute(AX_ATTR_BUSY, true);
update0.nodes[0].AddFloatAttribute(AX_ATTR_MIN_VALUE_FOR_RANGE, 2.0);
update0.nodes[0].AddFloatAttribute(AX_ATTR_MAX_VALUE_FOR_RANGE, 9.0);
update0.nodes[0].AddIntAttribute(AX_ATTR_SCROLL_X, 6);
@@ -693,7 +693,7 @@ TEST(AXTreeTest, AttributeChangeCallbacks) {
EXPECT_EQ("name changed from N1 to N2", change_log[0]);
EXPECT_EQ("description changed from D1 to D2", change_log[1]);
EXPECT_EQ("liveAtomic changed to false", change_log[2]);
- EXPECT_EQ("liveBusy changed to true", change_log[3]);
+ EXPECT_EQ("busy changed to true", change_log[3]);
EXPECT_EQ("minValueForRange changed from 1 to 2", change_log[4]);
EXPECT_EQ("maxValueForRange changed from 10 to 9", change_log[5]);
EXPECT_EQ("scrollX changed from 5 to 6", change_log[6]);
@@ -722,7 +722,7 @@ TEST(AXTreeTest, AttributeChangeCallbacks) {
EXPECT_EQ("name changed from N2 to ", change_log2[0]);
EXPECT_EQ("description changed from D2 to D3", change_log2[1]);
EXPECT_EQ("value changed from to V3", change_log2[2]);
- EXPECT_EQ("liveBusy changed to false", change_log2[3]);
+ EXPECT_EQ("busy changed to false", change_log2[3]);
EXPECT_EQ("modal changed to true", change_log2[4]);
EXPECT_EQ("minValueForRange changed from 2 to 0", change_log2[5]);
EXPECT_EQ("valueForRange changed from 0 to 5", change_log2[6]);
@@ -901,4 +901,23 @@ TEST(AXTreeTest, GetBoundsWithScrolling) {
EXPECT_EQ("(115, 70) size (50 x 5)", GetBoundsAsString(tree, 3));
}
+TEST(AXTreeTest, GetBoundsEmptyBoundsInheritsFromParent) {
+ AXTreeUpdate tree_update;
+ tree_update.root_id = 1;
+ tree_update.nodes.resize(3);
+ tree_update.nodes[0].id = 1;
+ tree_update.nodes[0].location = gfx::RectF(0, 0, 800, 600);
+ tree_update.nodes[0].child_ids.push_back(2);
+ tree_update.nodes[1].id = 2;
+ tree_update.nodes[1].location = gfx::RectF(300, 200, 100, 100);
+ tree_update.nodes[1].child_ids.push_back(3);
+ tree_update.nodes[2].id = 3;
+ tree_update.nodes[2].location = gfx::RectF();
+
+ AXTree tree(tree_update);
+ EXPECT_EQ("(0, 0) size (800 x 600)", GetBoundsAsString(tree, 1));
+ EXPECT_EQ("(300, 200) size (100 x 100)", GetBoundsAsString(tree, 2));
+ EXPECT_EQ("(300, 200) size (100 x 100)", GetBoundsAsString(tree, 3));
+}
+
} // namespace ui
diff --git a/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_ca.xtb b/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_ca.xtb
index 0642f954f6d..2cad7bee434 100644
--- a/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_ca.xtb
+++ b/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_ca.xtb
@@ -14,7 +14,7 @@
<translation id="2179565792157161713">Obre la descripció llarga en una pestanya nova</translation>
<translation id="2223143012868735942">Un filtre de color personalitzable que s'aplica en pàgines web per millorar la percepció del color.</translation>
<translation id="2394933097471027016">Proveu-ho ara. La navegació mitjançant la marca d'inserció està sempre activada en aquesta pàgina.</translation>
-<translation id="2471847333270902538">Esquema de color per a <ph name="SITE" />:</translation>
+<translation id="2471847333270902538">Paleta de colors per a <ph name="SITE" />:</translation>
<translation id="2648340354586434750">Manteniu premuda la tecla d'&lt;span class='key'&gt;opció&lt;/span&gt; per desplaçar-vos per les paraules.</translation>
<translation id="2795227192542594043">Aquesta extensió proporciona un cursor mòbil a la pàgina web que permet seleccionar el text amb el teclat.</translation>
<translation id="2808027189040546825">Pas 1: seleccioneu la fila amb les estrelles més tènues</translation>
@@ -40,9 +40,9 @@
<translation id="5555153510860501336">El contrast elevat està desactivat.</translation>
<translation id="5558600050691192317">Ordres del teclat</translation>
<translation id="5594989420907487559">Executeu les animacions només una vegada o desactiveu-les completament.</translation>
-<translation id="5631241868147802353">Esquema de colors predeterminat:</translation>
+<translation id="5631241868147802353">Paleta de colors predeterminada:</translation>
<translation id="5650358096585648000">Suggeriments visuals</translation>
-<translation id="5710185147685935461">Canvia o inverteix l'esquema de colors perquè les pàgines web siguin més fàcils de llegir.</translation>
+<translation id="5710185147685935461">Canvia o inverteix la paleta de colors perquè les pàgines web siguin més fàcils de llegir.</translation>
<translation id="5939518447894949180">Restableix</translation>
<translation id="595639123821853262">Escala de grisos invertida</translation>
<translation id="6017514345406065928">Verd</translation>
diff --git a/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_id.xtb b/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_id.xtb
index 25550595ea0..2da42fe4ca8 100644
--- a/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_id.xtb
+++ b/chromium/ui/accessibility/extensions/strings/accessibility_extensions_strings_id.xtb
@@ -12,11 +12,11 @@
<translation id="1996252509865389616">Aktifkan?</translation>
<translation id="2079545284768500474">Urungkan</translation>
<translation id="2179565792157161713">Buka Deskripsi Panjang di Tab Baru</translation>
-<translation id="2223143012868735942">Filter warna yang disesuaikan diterapkan ke laman web untuk meningkatkan persepsi warna.</translation>
-<translation id="2394933097471027016">Cobalah sekarang - Penjelajahan Caret selalu diaktifkan pada laman ini!</translation>
+<translation id="2223143012868735942">Filter warna yang disesuaikan diterapkan ke halaman web untuk meningkatkan persepsi warna.</translation>
+<translation id="2394933097471027016">Cobalah sekarang - Penjelajahan Caret selalu diaktifkan pada halaman ini!</translation>
<translation id="2471847333270902538">Skema warna untuk <ph name="SITE" />:</translation>
<translation id="2648340354586434750">Tahan &lt;span class='key'&gt;Opsi&lt;/span&gt; untuk berpindah berdasarkan kata.</translation>
-<translation id="2795227192542594043">Ekstensi ini memberi Anda kursor yang dapat digerakkan di laman web, memungkinkan Anda memilih teks dengan keyboard.</translation>
+<translation id="2795227192542594043">Ekstensi ini memberi Anda kursor yang dapat digerakkan di halaman web, memungkinkan Anda memilih teks dengan keyboard.</translation>
<translation id="2808027189040546825">Langkah 1: Pilih baris dengan bintang paling redup:</translation>
<translation id="2965611304828530558">&lt;p&gt;Saat Anda mengjangkau tautan atau kontrol, tautan atau kontrol tersebut akan otomatis terfokus. Tekan &lt;span class='key'&gt;Enter&lt;/span&gt; untuk mengeklik tautan atau tombol. &lt;/p&gt; &lt;p&gt; Saat kontrol terfokus (seperti kotak teks atau kotak daftar) menangkap tombol panah, tekan &lt;span class='key'&gt;Esc&lt;/span&gt; diikuti dengan tanda panah kiri atau kanan untuk melanjutkan Penjelajahan Caret. &lt;/p&gt; &lt;p&gt; Atau, tekan &lt;span class='key'&gt;Tab&lt;/span&gt; untuk berpindah ke kontrol yang dapat difokuskan berikutnya. &lt;/p&gt;</translation>
<translation id="3252573918265662711">Penyiapan</translation>
@@ -25,7 +25,7 @@
<translation id="3622586652998721735">Ditetapkan sebagai skema default</translation>
<translation id="3812541808639806898">Penampil Teks Alternatif Gambar</translation>
<translation id="381767806621926835">Klik kanan pada item apa pun yang memiliki atribut "longdesc" atau "aria-describedat" untuk mengakses deskripsi lognya.</translation>
-<translation id="4023902424053835668">Menjelajahi teks laman web menggunakan tombol panah.</translation>
+<translation id="4023902424053835668">Menjelajahi teks halaman web menggunakan tombol panah.</translation>
<translation id="4388820049312272371">Sorot posisi kursor dengan lampu kilat cepat.</translation>
<translation id="4394049700291259645">Nonaktifkan</translation>
<translation id="4769065380738716500">Gambar telah diganti dengan teks alternatif.</translation>
@@ -42,7 +42,7 @@
<translation id="5594989420907487559">Menjalankan animasi hanya satu kali, atau menonaktifkan animasi sepenuhnya.</translation>
<translation id="5631241868147802353">Skema warna default:</translation>
<translation id="5650358096585648000">Masukan Visual</translation>
-<translation id="5710185147685935461">Mengubah atau membalikkan skema warna untuk membuat laman web lebih mudah dibaca.</translation>
+<translation id="5710185147685935461">Mengubah atau membalikkan skema warna untuk membuat halaman web lebih mudah dibaca.</translation>
<translation id="5939518447894949180">Setel ulang</translation>
<translation id="595639123821853262">Abu-Abu Terbalik</translation>
<translation id="6017514345406065928">Hijau</translation>
diff --git a/chromium/ui/accessibility/platform/atk_util_auralinux.cc b/chromium/ui/accessibility/platform/atk_util_auralinux.cc
index 0b25fcb10fe..207260ef57d 100644
--- a/chromium/ui/accessibility/platform/atk_util_auralinux.cc
+++ b/chromium/ui/accessibility/platform/atk_util_auralinux.cc
@@ -13,23 +13,26 @@
#include "base/memory/singleton.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
-#include "base/task_runner.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/threading/thread_restrictions.h"
#include "ui/accessibility/platform/atk_util_auralinux.h"
#include "ui/accessibility/platform/ax_platform_node_auralinux.h"
namespace {
-typedef void (*gnome_accessibility_module_init)();
+typedef void (*GnomeAccessibilityModuleInitFunc)();
const char kAccessibilityEnabled[] = "ACCESSIBILITY_ENABLED";
-const char kAtkBridgeModule[] = "gail:atk-bridge";
+const char kAtkBridgeModule[] = "atk-bridge";
const char kAtkBridgePath[] = "gtk-2.0/modules/libatk-bridge.so";
const char kAtkBridgeSymbolName[] = "gnome_accessibility_module_init";
const char kGtkModules[] = "GTK_MODULES";
-gnome_accessibility_module_init g_accessibility_module_init = nullptr;
+// Returns a function pointer to be invoked on the main thread to init
+// the gnome accessibility module if it's enabled (nullptr otherwise).
+GnomeAccessibilityModuleInitFunc GetAccessibilityModuleInitFunc() {
+ base::ThreadRestrictions::AssertIOAllowed();
-bool AccessibilityModuleInitOnFileThread() {
// Try to load libatk-bridge.so.
base::FilePath atk_bridge_path(ATK_LIB_DIR);
atk_bridge_path = atk_bridge_path.Append(kAtkBridgePath);
@@ -37,18 +40,28 @@ bool AccessibilityModuleInitOnFileThread() {
static_cast<GModuleFlags>(0));
if (!bridge) {
VLOG(1) << "Unable to open module " << atk_bridge_path.value();
- return false;
+ return nullptr;
}
- if (!g_module_symbol(bridge, kAtkBridgeSymbolName,
- (gpointer *)&g_accessibility_module_init)) {
+ GnomeAccessibilityModuleInitFunc init_func = nullptr;
+
+ if (!g_module_symbol(bridge, kAtkBridgeSymbolName, (gpointer*)&init_func)) {
VLOG(1) << "Unable to get symbol pointer from " << atk_bridge_path.value();
- // Just to make sure it's null;
- g_accessibility_module_init = nullptr;
- return false;
+ return nullptr;
}
- return true;
+ DCHECK(init_func);
+ return init_func;
+}
+
+void FinishAccessibilityInitOnMainThread(
+ GnomeAccessibilityModuleInitFunc init_func) {
+ if (!init_func) {
+ VLOG(1) << "Will not enable ATK accessibility support.";
+ return;
+ }
+
+ init_func();
}
bool PlatformShouldEnableAccessibility() {
@@ -58,8 +71,8 @@ bool PlatformShouldEnableAccessibility() {
return false;
for (const std::string& module :
- base::SplitString(gtk_modules, base::kWhitespaceASCII,
- base::TRIM_WHITESPACE, base::SPLIT_WANT_NONEMPTY)) {
+ base::SplitString(gtk_modules, ":", base::TRIM_WHITESPACE,
+ base::SPLIT_WANT_NONEMPTY)) {
if (module == kAtkBridgeModule)
return true;
}
@@ -161,42 +174,18 @@ AtkUtilAuraLinux* AtkUtilAuraLinux::GetInstance() {
return base::Singleton<AtkUtilAuraLinux>::get();
}
-AtkUtilAuraLinux::AtkUtilAuraLinux() : is_enabled_(false) {}
-
-void AtkUtilAuraLinux::Initialize(
- scoped_refptr<base::TaskRunner> init_task_runner) {
-
+void AtkUtilAuraLinux::InitializeAsync() {
// Register our util class.
g_type_class_unref(g_type_class_ref(ATK_UTIL_AURALINUX_TYPE));
if (!ShouldEnableAccessibility())
return;
- init_task_runner->PostTaskAndReply(
+ base::PostTaskWithTraitsAndReplyWithResult(
FROM_HERE,
- base::Bind(
- &AtkUtilAuraLinux::CheckIfAccessibilityIsEnabledOnFileThread,
- base::Unretained(this)),
- base::Bind(
- &AtkUtilAuraLinux::FinishAccessibilityInitOnUIThread,
- base::Unretained(this)));
-}
-
-AtkUtilAuraLinux::~AtkUtilAuraLinux() {
-}
-
-void AtkUtilAuraLinux::CheckIfAccessibilityIsEnabledOnFileThread() {
- is_enabled_ = AccessibilityModuleInitOnFileThread();
-}
-
-void AtkUtilAuraLinux::FinishAccessibilityInitOnUIThread() {
- if (!is_enabled_) {
- VLOG(1) << "Will not enable ATK accessibility support.";
- return;
- }
-
- DCHECK(g_accessibility_module_init);
- g_accessibility_module_init();
+ {base::MayBlock(), base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+ base::Bind(&GetAccessibilityModuleInitFunc),
+ base::Bind(&FinishAccessibilityInitOnMainThread));
}
} // namespace ui
diff --git a/chromium/ui/accessibility/platform/atk_util_auralinux.h b/chromium/ui/accessibility/platform/atk_util_auralinux.h
index 06cd8881bed..8119fb781c1 100644
--- a/chromium/ui/accessibility/platform/atk_util_auralinux.h
+++ b/chromium/ui/accessibility/platform/atk_util_auralinux.h
@@ -5,13 +5,10 @@
#ifndef UI_ACCESSIBILITY_AX_UTIL_AURALINUX_H_
#define UI_ACCESSIBILITY_AX_UTIL_AURALINUX_H_
+#include "base/macros.h"
#include "base/memory/singleton.h"
#include "ui/accessibility/ax_export.h"
-namespace base {
-class TaskRunner;
-}
-
namespace ui {
// This singleton class initializes ATK (accessibility toolkit) and
@@ -22,18 +19,14 @@ class AtkUtilAuraLinux {
// Get the single instance of this class.
static AtkUtilAuraLinux* GetInstance();
- AtkUtilAuraLinux();
- virtual ~AtkUtilAuraLinux();
+ AtkUtilAuraLinux() = default;
- void Initialize(scoped_refptr<base::TaskRunner> init_task_runner);
+ void InitializeAsync();
private:
friend struct base::DefaultSingletonTraits<AtkUtilAuraLinux>;
- void CheckIfAccessibilityIsEnabledOnFileThread();
- void FinishAccessibilityInitOnUIThread();
-
- bool is_enabled_;
+ DISALLOW_COPY_AND_ASSIGN(AtkUtilAuraLinux);
};
} // namespace ui
diff --git a/chromium/ui/accessibility/platform/ax_platform_node.cc b/chromium/ui/accessibility/platform/ax_platform_node.cc
index 93a374abbac..d7f68012f77 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node.cc
@@ -9,39 +9,35 @@
#include "build/build_config.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/platform/ax_platform_node_delegate.h"
-#include "ui/accessibility/platform/ax_platform_unique_id.h"
namespace ui {
-namespace {
+// static
+base::LazyInstance<base::ObserverList<AXModeObserver>>::Leaky
+ AXPlatformNode::ax_mode_observers_ = LAZY_INSTANCE_INITIALIZER;
-using UniqueIdMap = base::hash_map<int32_t, AXPlatformNode*>;
-// Map from each AXPlatformNode's unique id to its instance.
-base::LazyInstance<UniqueIdMap>::DestructorAtExit g_unique_id_map =
- LAZY_INSTANCE_INITIALIZER;
-}
-
-AXPlatformNode::AXPlatformNode() : unique_id_(GetNextAXPlatformNodeUniqueId()) {
- g_unique_id_map.Get()[unique_id_] = this;
-}
+AXPlatformNode::AXPlatformNode() {}
AXPlatformNode::~AXPlatformNode() {
- if (unique_id_)
- g_unique_id_map.Get().erase(unique_id_);
}
void AXPlatformNode::Destroy() {
- g_unique_id_map.Get().erase(unique_id_);
- unique_id_ = 0;
}
-AXPlatformNode* AXPlatformNode::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;
+// static
+void AXPlatformNode::AddAXModeObserver(AXModeObserver* observer) {
+ ax_mode_observers_.Get().AddObserver(observer);
+}
+
+// static
+void AXPlatformNode::RemoveAXModeObserver(AXModeObserver* observer) {
+ ax_mode_observers_.Get().RemoveObserver(observer);
+}
- return nullptr;
+// static
+void AXPlatformNode::NotifyAddAXModeFlags(AXMode mode_flags) {
+ for (auto& observer : ax_mode_observers_.Get())
+ observer.OnAXModeAdded(mode_flags);
}
} // namespace ui
diff --git a/chromium/ui/accessibility/platform/ax_platform_node.h b/chromium/ui/accessibility/platform/ax_platform_node.h
index 7204c23aa88..8aa38ad0a82 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node.h
+++ b/chromium/ui/accessibility/platform/ax_platform_node.h
@@ -5,9 +5,12 @@
#ifndef UI_ACCESSIBILITY_PLATFORM_AX_PLATFORM_NODE_H_
#define UI_ACCESSIBILITY_PLATFORM_AX_PLATFORM_NODE_H_
+#include "base/lazy_instance.h"
+#include "base/observer_list.h"
#include "build/build_config.h"
#include "ui/accessibility/ax_enums.h"
#include "ui/accessibility/ax_export.h"
+#include "ui/accessibility/ax_mode_observer.h"
#include "ui/gfx/native_widget_types.h"
namespace ui {
@@ -30,6 +33,15 @@ class AX_EXPORT AXPlatformNode {
static AXPlatformNode* FromNativeViewAccessible(
gfx::NativeViewAccessible accessible);
+ // Register and unregister to receive notifications about AXMode changes
+ // for this node.
+ static void AddAXModeObserver(AXModeObserver* observer);
+ static void RemoveAXModeObserver(AXModeObserver* observer);
+
+ // Helper static function to notify all global observers about
+ // the addition of an AXMode flag.
+ static void NotifyAddAXModeFlags(AXMode mode_flags);
+
// Call Destroy rather than deleting this, because the subclass may
// use reference counting.
virtual void Destroy();
@@ -41,7 +53,7 @@ class AX_EXPORT AXPlatformNode {
// Fire a platform-specific notification that an event has occurred on
// this object.
- virtual void NotifyAccessibilityEvent(ui::AXEvent event_type) = 0;
+ virtual void NotifyAccessibilityEvent(AXEvent event_type) = 0;
// Return this object's delegate.
virtual AXPlatformNodeDelegate* GetDelegate() const = 0;
@@ -50,9 +62,10 @@ class AX_EXPORT AXPlatformNode {
AXPlatformNode();
virtual ~AXPlatformNode();
- virtual AXPlatformNode* GetFromUniqueId(int32_t unique_id);
-
- int32_t unique_id_;
+ private:
+ // Global ObserverList for AXMode changes.
+ static base::LazyInstance<base::ObserverList<AXModeObserver>>::Leaky
+ ax_mode_observers_;
};
} // 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 c73d7a93abf..1350607a562 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_auralinux.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_auralinux.cc
@@ -8,7 +8,6 @@
#include "base/command_line.h"
#include "base/strings/sys_string_conversions.h"
-#include "base/task_runner.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/platform/atk_util_auralinux.h"
#include "ui/accessibility/platform/ax_platform_node_delegate.h"
@@ -392,9 +391,8 @@ void AXPlatformNodeAuraLinux::SetApplication(AXPlatformNode* application) {
}
// static
-void AXPlatformNodeAuraLinux::StaticInitialize(
- scoped_refptr<base::TaskRunner> init_task_runner) {
- AtkUtilAuraLinux::GetInstance()->Initialize(init_task_runner);
+void AXPlatformNodeAuraLinux::StaticInitialize() {
+ AtkUtilAuraLinux::GetInstance()->InitializeAsync();
}
AtkRole AXPlatformNodeAuraLinux::GetAtkRole() {
@@ -474,8 +472,12 @@ void AXPlatformNodeAuraLinux::GetAtkState(AtkStateSet* atk_state_set) {
atk_state_set_add_state(atk_state_set, ATK_STATE_EXPANDED);
if (data.HasState(ui::AX_STATE_FOCUSABLE))
atk_state_set_add_state(atk_state_set, ATK_STATE_FOCUSABLE);
+#if defined(ATK_CHECK_VERSION)
+#if ATK_CHECK_VERSION(2, 11, 2)
if (data.HasState(ui::AX_STATE_HASPOPUP))
atk_state_set_add_state(atk_state_set, ATK_STATE_HAS_POPUP);
+#endif
+#endif
if (data.HasState(ui::AX_STATE_SELECTED))
atk_state_set_add_state(atk_state_set, ATK_STATE_SELECTED);
if (data.HasState(ui::AX_STATE_SELECTABLE))
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_auralinux.h b/chromium/ui/accessibility/platform/ax_platform_node_auralinux.h
index 00581d93646..1504bfbf67b 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_auralinux.h
+++ b/chromium/ui/accessibility/platform/ax_platform_node_auralinux.h
@@ -8,14 +8,9 @@
#include <atk/atk.h>
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
#include "ui/accessibility/ax_export.h"
#include "ui/accessibility/platform/ax_platform_node_base.h"
-namespace base {
-class TaskRunner;
-}
-
namespace ui {
// Implements accessibility on Aura Linux using ATK.
@@ -28,9 +23,8 @@ class AXPlatformNodeAuraLinux : public AXPlatformNodeBase {
AX_EXPORT static void SetApplication(AXPlatformNode* application);
static AXPlatformNode* application() { return application_; }
- // Do static initialization using the given task runner for file operations.
- AX_EXPORT static void StaticInitialize(
- scoped_refptr<base::TaskRunner> init_task_runner);
+ // Do asynchronous static initialization.
+ AX_EXPORT static void StaticInitialize();
AtkRole GetAtkRole();
void GetAtkState(AtkStateSet* state_set);
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_base.cc b/chromium/ui/accessibility/platform/ax_platform_node_base.cc
index e16ba20c084..abdf04bba2b 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_base.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_base.cc
@@ -19,7 +19,7 @@ void AXPlatformNodeBase::Init(AXPlatformNodeDelegate* delegate) {
}
const AXNodeData& AXPlatformNodeBase::GetData() const {
- CR_DEFINE_STATIC_LOCAL(ui::AXNodeData, empty_data, ());
+ CR_DEFINE_STATIC_LOCAL(AXNodeData, empty_data, ());
if (delegate_)
return delegate_->GetData();
return empty_data;
@@ -115,115 +115,107 @@ bool AXPlatformNodeBase::IsDescendant(AXPlatformNodeBase* node) {
return IsDescendant(parent);
}
-bool AXPlatformNodeBase::HasBoolAttribute(
- ui::AXBoolAttribute attribute) const {
+bool AXPlatformNodeBase::HasBoolAttribute(AXBoolAttribute attribute) const {
if (!delegate_)
return false;
return GetData().HasBoolAttribute(attribute);
}
-bool AXPlatformNodeBase::GetBoolAttribute(
- ui::AXBoolAttribute attribute) const {
+bool AXPlatformNodeBase::GetBoolAttribute(AXBoolAttribute attribute) const {
if (!delegate_)
return false;
return GetData().GetBoolAttribute(attribute);
}
-bool AXPlatformNodeBase::GetBoolAttribute(
- ui::AXBoolAttribute attribute, bool* value) const {
+bool AXPlatformNodeBase::GetBoolAttribute(AXBoolAttribute attribute,
+ bool* value) const {
if (!delegate_)
return false;
return GetData().GetBoolAttribute(attribute, value);
}
-bool AXPlatformNodeBase::HasFloatAttribute(
- ui::AXFloatAttribute attribute) const {
+bool AXPlatformNodeBase::HasFloatAttribute(AXFloatAttribute attribute) const {
if (!delegate_)
return false;
return GetData().HasFloatAttribute(attribute);
}
-float AXPlatformNodeBase::GetFloatAttribute(
- ui::AXFloatAttribute attribute) const {
+float AXPlatformNodeBase::GetFloatAttribute(AXFloatAttribute attribute) const {
if (!delegate_)
return false;
return GetData().GetFloatAttribute(attribute);
}
-bool AXPlatformNodeBase::GetFloatAttribute(
- ui::AXFloatAttribute attribute, float* value) const {
+bool AXPlatformNodeBase::GetFloatAttribute(AXFloatAttribute attribute,
+ float* value) const {
if (!delegate_)
return false;
return GetData().GetFloatAttribute(attribute, value);
}
-bool AXPlatformNodeBase::HasIntAttribute(
- ui::AXIntAttribute attribute) const {
+bool AXPlatformNodeBase::HasIntAttribute(AXIntAttribute attribute) const {
if (!delegate_)
return false;
return GetData().HasIntAttribute(attribute);
}
-int AXPlatformNodeBase::GetIntAttribute(
- ui::AXIntAttribute attribute) const {
+int AXPlatformNodeBase::GetIntAttribute(AXIntAttribute attribute) const {
if (!delegate_)
return false;
return GetData().GetIntAttribute(attribute);
}
-bool AXPlatformNodeBase::GetIntAttribute(
- ui::AXIntAttribute attribute, int* value) const {
+bool AXPlatformNodeBase::GetIntAttribute(AXIntAttribute attribute,
+ int* value) const {
if (!delegate_)
return false;
return GetData().GetIntAttribute(attribute, value);
}
-bool AXPlatformNodeBase::HasStringAttribute(
- ui::AXStringAttribute attribute) const {
+bool AXPlatformNodeBase::HasStringAttribute(AXStringAttribute attribute) const {
if (!delegate_)
return false;
return GetData().HasStringAttribute(attribute);
}
const std::string& AXPlatformNodeBase::GetStringAttribute(
- ui::AXStringAttribute attribute) const {
+ AXStringAttribute attribute) const {
CR_DEFINE_STATIC_LOCAL(std::string, empty_data, ());
if (!delegate_)
return empty_data;
return GetData().GetStringAttribute(attribute);
}
-bool AXPlatformNodeBase::GetStringAttribute(
- ui::AXStringAttribute attribute, std::string* value) const {
+bool AXPlatformNodeBase::GetStringAttribute(AXStringAttribute attribute,
+ std::string* value) const {
if (!delegate_)
return false;
return GetData().GetStringAttribute(attribute, value);
}
base::string16 AXPlatformNodeBase::GetString16Attribute(
- ui::AXStringAttribute attribute) const {
+ AXStringAttribute attribute) const {
if (!delegate_)
return base::string16();
return GetData().GetString16Attribute(attribute);
}
-bool AXPlatformNodeBase::GetString16Attribute(
- ui::AXStringAttribute attribute,
- base::string16* value) const {
+bool AXPlatformNodeBase::GetString16Attribute(AXStringAttribute attribute,
+ base::string16* value) const {
if (!delegate_)
return false;
return GetData().GetString16Attribute(attribute, value);
}
bool AXPlatformNodeBase::HasIntListAttribute(
- ui::AXIntListAttribute attribute) const {
+ AXIntListAttribute attribute) const {
if (!delegate_)
return false;
return GetData().HasIntListAttribute(attribute);
}
const std::vector<int32_t>& AXPlatformNodeBase::GetIntListAttribute(
- ui::AXIntListAttribute attribute) const {
+ AXIntListAttribute attribute) const {
CR_DEFINE_STATIC_LOCAL(std::vector<int32_t>, empty_data, ());
if (!delegate_)
return empty_data;
@@ -231,7 +223,7 @@ const std::vector<int32_t>& AXPlatformNodeBase::GetIntListAttribute(
}
bool AXPlatformNodeBase::GetIntListAttribute(
- ui::AXIntListAttribute attribute,
+ AXIntListAttribute attribute,
std::vector<int32_t>* value) const {
if (!delegate_)
return false;
@@ -252,8 +244,8 @@ AXPlatformNodeBase* AXPlatformNodeBase::FromNativeViewAccessible(
}
bool AXPlatformNodeBase::SetTextSelection(int start_offset, int end_offset) {
- ui::AXActionData action_data;
- action_data.action = ui::AX_ACTION_SET_SELECTION;
+ AXActionData action_data;
+ action_data.action = AX_ACTION_SET_SELECTION;
action_data.anchor_node_id = action_data.focus_node_id = GetData().id;
action_data.anchor_offset = start_offset;
action_data.focus_offset = end_offset;
@@ -264,13 +256,13 @@ bool AXPlatformNodeBase::SetTextSelection(int start_offset, int end_offset) {
}
bool AXPlatformNodeBase::IsTextOnlyObject() const {
- return GetData().role == ui::AX_ROLE_STATIC_TEXT ||
- GetData().role == ui::AX_ROLE_LINE_BREAK ||
- GetData().role == ui::AX_ROLE_INLINE_TEXT_BOX;
+ return GetData().role == AX_ROLE_STATIC_TEXT ||
+ GetData().role == AX_ROLE_LINE_BREAK ||
+ GetData().role == AX_ROLE_INLINE_TEXT_BOX;
}
bool AXPlatformNodeBase::IsNativeTextControl() const {
- const std::string& html_tag = GetStringAttribute(ui::AX_ATTR_HTML_TAG);
+ const std::string& html_tag = GetStringAttribute(AX_ATTR_HTML_TAG);
if (html_tag == "input") {
std::string input_type;
if (!GetData().GetHtmlAttribute("type", &input_type))
@@ -287,11 +279,11 @@ bool AXPlatformNodeBase::IsSimpleTextControl() const {
// Time fields, color wells and spinner buttons might also use text fields as
// constituent parts, but they are not considered text fields as a whole.
switch (GetData().role) {
- case ui::AX_ROLE_COMBO_BOX:
- case ui::AX_ROLE_SEARCH_BOX:
+ case AX_ROLE_COMBO_BOX:
+ case AX_ROLE_SEARCH_BOX:
return true;
- case ui::AX_ROLE_TEXT_FIELD:
- return !GetData().HasState(ui::AX_STATE_RICHLY_EDITABLE);
+ case AX_ROLE_TEXT_FIELD:
+ return !GetData().HasState(AX_STATE_RICHLY_EDITABLE);
default:
return false;
}
@@ -304,13 +296,13 @@ bool AXPlatformNodeBase::IsRichTextControl() {
if (!parent)
return false;
- return GetData().HasState(ui::AX_STATE_RICHLY_EDITABLE) &&
- (!parent || !parent->GetData().HasState(ui::AX_STATE_RICHLY_EDITABLE));
+ return GetData().HasState(AX_STATE_RICHLY_EDITABLE) &&
+ (!parent || !parent->GetData().HasState(AX_STATE_RICHLY_EDITABLE));
}
base::string16 AXPlatformNodeBase::GetInnerText() {
if (IsTextOnlyObject())
- return GetString16Attribute(ui::AX_ATTR_NAME);
+ return GetString16Attribute(AX_ATTR_NAME);
base::string16 text;
for (int i = 0; i < GetChildCount(); ++i) {
@@ -326,13 +318,13 @@ base::string16 AXPlatformNodeBase::GetInnerText() {
bool AXPlatformNodeBase::IsRangeValueSupported() const {
switch (GetData().role) {
- case ui::AX_ROLE_PROGRESS_INDICATOR:
- case ui::AX_ROLE_SLIDER:
- case ui::AX_ROLE_SPIN_BUTTON:
- case ui::AX_ROLE_SCROLL_BAR:
+ case AX_ROLE_PROGRESS_INDICATOR:
+ case AX_ROLE_SLIDER:
+ case AX_ROLE_SPIN_BUTTON:
+ case AX_ROLE_SCROLL_BAR:
return true;
- case ui::AX_ROLE_SPLITTER:
- return GetData().HasState(ui::AX_STATE_FOCUSABLE);
+ case AX_ROLE_SPLITTER:
+ return GetData().HasState(AX_STATE_FOCUSABLE);
default:
return false;
}
@@ -340,9 +332,9 @@ bool AXPlatformNodeBase::IsRangeValueSupported() const {
base::string16 AXPlatformNodeBase::GetRangeValueText() {
float fval;
- base::string16 value = GetString16Attribute(ui::AX_ATTR_VALUE);
+ base::string16 value = GetString16Attribute(AX_ATTR_VALUE);
- if (value.empty() && GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE, &fval)) {
+ if (value.empty() && GetFloatAttribute(AX_ATTR_VALUE_FOR_RANGE, &fval)) {
value = base::UTF8ToUTF16(base::DoubleToString(fval));
}
return value;
@@ -352,7 +344,7 @@ AXPlatformNodeBase* AXPlatformNodeBase::GetTable() const {
if (!delegate_)
return nullptr;
AXPlatformNodeBase* table = const_cast<AXPlatformNodeBase*>(this);
- while (table && !ui::IsTableLikeRole(table->GetData().role)) {
+ while (table && !IsTableLikeRole(table->GetData().role)) {
gfx::NativeViewAccessible parent_accessible = table->GetParent();
AXPlatformNodeBase* parent = FromNativeViewAccessible(parent_accessible);
@@ -364,15 +356,15 @@ AXPlatformNodeBase* AXPlatformNodeBase::GetTable() const {
AXPlatformNodeBase* AXPlatformNodeBase::GetTableCell(int index) const {
if (!delegate_)
return nullptr;
- if (!ui::IsTableLikeRole(GetData().role) &&
- !ui::IsCellOrTableHeaderRole(GetData().role))
+ if (!IsTableLikeRole(GetData().role) &&
+ !IsCellOrTableHeaderRole(GetData().role))
return nullptr;
AXPlatformNodeBase* table = GetTable();
if (!table)
return nullptr;
const std::vector<int32_t>& unique_cell_ids =
- table->GetIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS);
+ table->GetIntListAttribute(AX_ATTR_UNIQUE_CELL_IDS);
if (index < 0 || index >= static_cast<int>(unique_cell_ids.size()))
return nullptr;
@@ -382,8 +374,8 @@ AXPlatformNodeBase* AXPlatformNodeBase::GetTableCell(int index) const {
AXPlatformNodeBase* AXPlatformNodeBase::GetTableCell(int row,
int column) const {
- if (!ui::IsTableLikeRole(GetData().role) &&
- !ui::IsCellOrTableHeaderRole(GetData().role))
+ if (!IsTableLikeRole(GetData().role) &&
+ !IsCellOrTableHeaderRole(GetData().role))
return nullptr;
if (row < 0 || row >= GetTableRowCount() || column < 0 ||
@@ -398,7 +390,7 @@ AXPlatformNodeBase* AXPlatformNodeBase::GetTableCell(int row,
// In contrast to unique cell IDs, these are duplicated whenever a cell spans
// multiple columns or rows.
const std::vector<int32_t>& cell_ids =
- table->GetIntListAttribute(ui::AX_ATTR_CELL_IDS);
+ table->GetIntListAttribute(AX_ATTR_CELL_IDS);
DCHECK_EQ(GetTableRowCount() * GetTableColumnCount(),
static_cast<int>(cell_ids.size()));
int position = row * GetTableColumnCount() + column;
@@ -410,7 +402,7 @@ AXPlatformNodeBase* AXPlatformNodeBase::GetTableCell(int row,
}
int AXPlatformNodeBase::GetTableCellIndex() const {
- if (!ui::IsCellOrTableHeaderRole(GetData().role))
+ if (!IsCellOrTableHeaderRole(GetData().role))
return -1;
AXPlatformNodeBase* table = GetTable();
@@ -418,7 +410,7 @@ int AXPlatformNodeBase::GetTableCellIndex() const {
return -1;
const std::vector<int32_t>& unique_cell_ids =
- table->GetIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS);
+ table->GetIntListAttribute(AX_ATTR_UNIQUE_CELL_IDS);
auto iter =
std::find(unique_cell_ids.begin(), unique_cell_ids.end(), GetData().id);
if (iter == unique_cell_ids.end())
@@ -428,7 +420,7 @@ int AXPlatformNodeBase::GetTableCellIndex() const {
}
int AXPlatformNodeBase::GetTableColumn() const {
- return GetIntAttribute(ui::AX_ATTR_TABLE_CELL_COLUMN_INDEX);
+ return GetIntAttribute(AX_ATTR_TABLE_CELL_COLUMN_INDEX);
}
int AXPlatformNodeBase::GetTableColumnCount() const {
@@ -436,21 +428,21 @@ int AXPlatformNodeBase::GetTableColumnCount() const {
if (!table)
return 0;
- return table->GetIntAttribute(ui::AX_ATTR_TABLE_COLUMN_COUNT);
+ return table->GetIntAttribute(AX_ATTR_TABLE_COLUMN_COUNT);
}
int AXPlatformNodeBase::GetTableColumnSpan() const {
- if (!ui::IsCellOrTableHeaderRole(GetData().role))
+ if (!IsCellOrTableHeaderRole(GetData().role))
return 0;
int column_span;
- if (GetIntAttribute(ui::AX_ATTR_TABLE_CELL_COLUMN_SPAN, &column_span))
+ if (GetIntAttribute(AX_ATTR_TABLE_CELL_COLUMN_SPAN, &column_span))
return column_span;
return 1;
}
int AXPlatformNodeBase::GetTableRow() const {
- return GetIntAttribute(ui::AX_ATTR_TABLE_CELL_ROW_INDEX);
+ return GetIntAttribute(AX_ATTR_TABLE_CELL_ROW_INDEX);
}
int AXPlatformNodeBase::GetTableRowCount() const {
@@ -458,15 +450,15 @@ int AXPlatformNodeBase::GetTableRowCount() const {
if (!table)
return 0;
- return table->GetIntAttribute(ui::AX_ATTR_TABLE_ROW_COUNT);
+ return table->GetIntAttribute(AX_ATTR_TABLE_ROW_COUNT);
}
int AXPlatformNodeBase::GetTableRowSpan() const {
- if (!ui::IsCellOrTableHeaderRole(GetData().role))
+ if (!IsCellOrTableHeaderRole(GetData().role))
return 0;
int row_span;
- if (GetIntAttribute(ui::AX_ATTR_TABLE_CELL_ROW_SPAN, &row_span))
+ if (GetIntAttribute(AX_ATTR_TABLE_CELL_ROW_SPAN, &row_span))
return row_span;
return 1;
}
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_base.h b/chromium/ui/accessibility/platform/ax_platform_node_base.h
index 98aa7f5623e..1481ed97e87 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_base.h
+++ b/chromium/ui/accessibility/platform/ax_platform_node_base.h
@@ -40,33 +40,31 @@ class AX_EXPORT AXPlatformNodeBase : public AXPlatformNode {
AXPlatformNodeBase* GetNextSibling();
bool IsDescendant(AXPlatformNodeBase* descendant);
- bool HasBoolAttribute(ui::AXBoolAttribute attr) const;
- bool GetBoolAttribute(ui::AXBoolAttribute attr) const;
- bool GetBoolAttribute(ui::AXBoolAttribute attr, bool* value) const;
-
- bool HasFloatAttribute(ui::AXFloatAttribute attr) const;
- float GetFloatAttribute(ui::AXFloatAttribute attr) const;
- bool GetFloatAttribute(ui::AXFloatAttribute attr, float* value) const;
-
- bool HasIntAttribute(ui::AXIntAttribute attribute) const;
- int GetIntAttribute(ui::AXIntAttribute attribute) const;
- bool GetIntAttribute(ui::AXIntAttribute attribute, int* value) const;
-
- bool HasStringAttribute(
- ui::AXStringAttribute attribute) const;
- const std::string& GetStringAttribute(ui::AXStringAttribute attribute) const;
- bool GetStringAttribute(ui::AXStringAttribute attribute,
+ bool HasBoolAttribute(AXBoolAttribute attr) const;
+ bool GetBoolAttribute(AXBoolAttribute attr) const;
+ bool GetBoolAttribute(AXBoolAttribute attr, bool* value) const;
+
+ bool HasFloatAttribute(AXFloatAttribute attr) const;
+ float GetFloatAttribute(AXFloatAttribute attr) const;
+ bool GetFloatAttribute(AXFloatAttribute attr, float* value) const;
+
+ bool HasIntAttribute(AXIntAttribute attribute) const;
+ int GetIntAttribute(AXIntAttribute attribute) const;
+ bool GetIntAttribute(AXIntAttribute attribute, int* value) const;
+
+ bool HasStringAttribute(AXStringAttribute attribute) const;
+ const std::string& GetStringAttribute(AXStringAttribute attribute) const;
+ bool GetStringAttribute(AXStringAttribute attribute,
std::string* value) const;
- bool GetString16Attribute(ui::AXStringAttribute attribute,
+ bool GetString16Attribute(AXStringAttribute attribute,
base::string16* value) const;
- base::string16 GetString16Attribute(
- ui::AXStringAttribute attribute) const;
+ base::string16 GetString16Attribute(AXStringAttribute attribute) const;
- bool HasIntListAttribute(ui::AXIntListAttribute attribute) const;
+ bool HasIntListAttribute(AXIntListAttribute attribute) const;
const std::vector<int32_t>& GetIntListAttribute(
- ui::AXIntListAttribute attribute) const;
+ AXIntListAttribute attribute) const;
- bool GetIntListAttribute(ui::AXIntListAttribute attribute,
+ bool GetIntListAttribute(AXIntListAttribute attribute,
std::vector<int32_t>* value) const;
// Returns the table or ARIA grid if inside one.
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_delegate.h b/chromium/ui/accessibility/platform/ax_platform_node_delegate.h
index 052eeb1adf6..ad548c90726 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_delegate.h
+++ b/chromium/ui/accessibility/platform/ax_platform_node_delegate.h
@@ -38,7 +38,7 @@ class AX_EXPORT AXPlatformNodeDelegate {
virtual const AXNodeData& GetData() const = 0;
// Get the accessibility tree data for this node.
- virtual const ui::AXTreeData& GetTreeData() const = 0;
+ virtual const AXTreeData& GetTreeData() const = 0;
// Get the window the node is contained in.
virtual gfx::NativeWindow GetTopLevelWidget() = 0;
@@ -73,7 +73,7 @@ class AX_EXPORT AXPlatformNodeDelegate {
// has focus.
virtual gfx::NativeViewAccessible GetFocus() = 0;
- virtual ui::AXPlatformNode* GetFromNodeID(int32_t id) = 0;
+ virtual AXPlatformNode* GetFromNodeID(int32_t id) = 0;
//
// Events.
@@ -87,9 +87,9 @@ class AX_EXPORT AXPlatformNodeDelegate {
// Actions.
//
- // Perform an accessibility action, switching on the ui::AXAction
+ // Perform an accessibility action, switching on the AXAction
// provided in |data|.
- virtual bool AccessibilityPerformAction(const ui::AXActionData& data) = 0;
+ virtual bool AccessibilityPerformAction(const AXActionData& data) = 0;
//
// Testing.
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_mac.h b/chromium/ui/accessibility/platform/ax_platform_node_mac.h
index 73657fb986d..36ee00335e2 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_mac.h
+++ b/chromium/ui/accessibility/platform/ax_platform_node_mac.h
@@ -36,6 +36,10 @@ class AXPlatformNodeMac : public AXPlatformNodeBase {
DISALLOW_COPY_AND_ASSIGN(AXPlatformNodeMac);
};
+// Convenience function to determine whether an internal object role should
+// expose its accessible name in AXValue (as opposed to AXTitle/AXDescription).
+AX_EXPORT bool IsNameExposedInAXValueForRole(AXRole role);
+
} // namespace ui
AX_EXPORT
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_mac.mm b/chromium/ui/accessibility/platform/ax_platform_node_mac.mm
index c2513cb46d8..bb310ebbb84 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_mac.mm
+++ b/chromium/ui/accessibility/platform/ax_platform_node_mac.mm
@@ -36,7 +36,6 @@ RoleMap BuildRoleMap() {
{ui::AX_ROLE_AUDIO, NSAccessibilityGroupRole},
{ui::AX_ROLE_BANNER, NSAccessibilityGroupRole},
{ui::AX_ROLE_BLOCKQUOTE, NSAccessibilityGroupRole},
- {ui::AX_ROLE_BUSY_INDICATOR, NSAccessibilityBusyIndicatorRole},
{ui::AX_ROLE_BUTTON, NSAccessibilityButtonRole},
{ui::AX_ROLE_CANVAS, NSAccessibilityImageRole},
{ui::AX_ROLE_CAPTION, NSAccessibilityGroupRole},
@@ -69,7 +68,9 @@ RoleMap BuildRoleMap() {
{ui::AX_ROLE_FOOTER, NSAccessibilityGroupRole},
{ui::AX_ROLE_FORM, NSAccessibilityGroupRole},
{ui::AX_ROLE_GENERIC_CONTAINER, NSAccessibilityGroupRole},
- {ui::AX_ROLE_GRID, NSAccessibilityGridRole},
+ // Should be NSAccessibilityGridRole but VoiceOver treating it like
+ // a list as of 10.12.6, so following WebKit and using table role:
+ {ui::AX_ROLE_GRID, NSAccessibilityTableRole}, // crbug.com/753925
{ui::AX_ROLE_GROUP, NSAccessibilityGroupRole},
{ui::AX_ROLE_HEADING, @"AXHeading"},
{ui::AX_ROLE_IFRAME, NSAccessibilityGroupRole},
@@ -77,7 +78,6 @@ RoleMap BuildRoleMap() {
{ui::AX_ROLE_IGNORED, NSAccessibilityUnknownRole},
{ui::AX_ROLE_IMAGE, NSAccessibilityImageRole},
{ui::AX_ROLE_IMAGE_MAP, NSAccessibilityGroupRole},
- {ui::AX_ROLE_IMAGE_MAP_LINK, NSAccessibilityLinkRole},
{ui::AX_ROLE_INPUT_TIME, @"AXTimeField"},
{ui::AX_ROLE_LABEL_TEXT, NSAccessibilityGroupRole},
{ui::AX_ROLE_LEGEND, NSAccessibilityGroupRole},
@@ -104,7 +104,6 @@ RoleMap BuildRoleMap() {
{ui::AX_ROLE_NAVIGATION, NSAccessibilityGroupRole},
{ui::AX_ROLE_NONE, NSAccessibilityGroupRole},
{ui::AX_ROLE_NOTE, NSAccessibilityGroupRole},
- {ui::AX_ROLE_OUTLINE, NSAccessibilityOutlineRole},
{ui::AX_ROLE_PARAGRAPH, NSAccessibilityGroupRole},
{ui::AX_ROLE_POP_UP_BUTTON, NSAccessibilityPopUpButtonRole},
{ui::AX_ROLE_PRE, NSAccessibilityGroupRole},
@@ -116,7 +115,6 @@ RoleMap BuildRoleMap() {
{ui::AX_ROLE_ROOT_WEB_AREA, @"AXWebArea"},
{ui::AX_ROLE_ROW, NSAccessibilityRowRole},
{ui::AX_ROLE_ROW_HEADER, @"AXCell"},
- {ui::AX_ROLE_RULER, NSAccessibilityRulerRole},
{ui::AX_ROLE_SCROLL_BAR, NSAccessibilityScrollBarRole},
{ui::AX_ROLE_SEARCH, NSAccessibilityGroupRole},
{ui::AX_ROLE_SEARCH_BOX, NSAccessibilityTextFieldRole},
@@ -146,10 +144,6 @@ RoleMap BuildRoleMap() {
{ui::AX_ROLE_VIDEO, NSAccessibilityGroupRole},
{ui::AX_ROLE_WEB_AREA, @"AXWebArea"},
{ui::AX_ROLE_WINDOW, NSAccessibilityWindowRole},
-
- // TODO(dtseng): we don't correctly support the attributes for these
- // roles.
- // { ui::AX_ROLE_SCROLL_AREA, NSAccessibilityScrollAreaRole },
};
return RoleMap(begin(roles), end(roles));
@@ -636,14 +630,13 @@ bool AlsoUseShowMenuActionForDefaultAction(const ui::AXNodeData& data) {
}
- (id)AXValue {
- switch (node_->GetData().role) {
- case ui::AX_ROLE_TAB:
- return [self AXSelected];
- case ui::AX_ROLE_STATIC_TEXT:
- return [self AXTitle];
- default:
- break;
- }
+ ui::AXRole role = node_->GetData().role;
+ if (role == ui::AX_ROLE_TAB)
+ return [self AXSelected];
+
+ if (ui::IsNameExposedInAXValueForRole(role))
+ return [self getStringAttribute:ui::AX_ATTR_NAME];
+
return [self getStringAttribute:ui::AX_ATTR_VALUE];
}
@@ -693,6 +686,9 @@ bool AlsoUseShowMenuActionForDefaultAction(const ui::AXNodeData& data) {
}
- (NSString*)AXTitle {
+ if (ui::IsNameExposedInAXValueForRole(node_->GetData().role))
+ return @"";
+
return [self getStringAttribute:ui::AX_ATTR_NAME];
}
@@ -860,4 +856,16 @@ int AXPlatformNodeMac::GetIndexInParent() {
return -1;
}
+bool IsNameExposedInAXValueForRole(AXRole role) {
+ switch (role) {
+ case AX_ROLE_LIST_BOX_OPTION:
+ case AX_ROLE_LIST_MARKER:
+ case AX_ROLE_MENU_LIST_OPTION:
+ case AX_ROLE_STATIC_TEXT:
+ return true;
+ default:
+ return false;
+ }
+}
+
} // namespace ui
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_win.cc b/chromium/ui/accessibility/platform/ax_platform_node_win.cc
index 25c8c227dd9..57db0173a5a 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_win.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_win.cc
@@ -2,12 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include <atlbase.h>
-#include <atlcom.h>
-#include <limits.h>
-#include <oleacc.h>
-#include <stdint.h>
-
+#include "ui/accessibility/platform/ax_platform_node_win.h"
#include "base/containers/hash_tables.h"
#include "base/lazy_instance.h"
#include "base/strings/string_number_conversions.h"
@@ -19,12 +14,13 @@
#include "third_party/iaccessible2/ia2_api_all.h"
#include "third_party/skia/include/core/SkColor.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_role_properties.h"
#include "ui/accessibility/ax_text_utils.h"
#include "ui/accessibility/ax_tree_data.h"
#include "ui/accessibility/platform/ax_platform_node_delegate.h"
-#include "ui/accessibility/platform/ax_platform_node_win.h"
+#include "ui/accessibility/platform/ax_platform_unique_id.h"
#include "ui/base/win/atl_module.h"
#include "ui/gfx/geometry/rect_conversions.h"
@@ -155,6 +151,12 @@ base::LazyInstance<base::ObserverList<IAccessible2UsageObserver>>::
} // namespace
+// There is no easy way to decouple |kScreenReader| and |kHTML| accessibility
+// modes when Windows screen readers are used. For example, certain roles use
+// the HTML tag name. Input fields require their type attribute to be exposed.
+const uint32_t kScreenReaderAndHTMLAccessibilityModes =
+ AXMode::kScreenReader | AXMode::kHTML;
+
//
// IAccessible2UsageObserver
//
@@ -172,7 +174,7 @@ base::ObserverList<IAccessible2UsageObserver>&
}
AXPlatformNodeRelationWin::AXPlatformNodeRelationWin() {
- ui::win::CreateATLModuleIfNeeded();
+ win::CreateATLModuleIfNeeded();
}
AXPlatformNodeRelationWin::~AXPlatformNodeRelationWin() {}
@@ -205,16 +207,16 @@ STDMETHODIMP AXPlatformNodeRelationWin::get_relationType(BSTR* relation_type) {
return S_OK;
}
-STDMETHODIMP AXPlatformNodeRelationWin::get_nTargets(long* n_targets) {
+STDMETHODIMP AXPlatformNodeRelationWin::get_nTargets(LONG* n_targets) {
if (!n_targets)
return E_INVALIDARG;
if (!owner_->delegate_)
return E_FAIL;
- *n_targets = static_cast<long>(target_ids_.size());
+ *n_targets = static_cast<LONG>(target_ids_.size());
- for (long i = *n_targets - 1; i >= 0; --i) {
+ for (LONG i = *n_targets - 1; i >= 0; --i) {
AXPlatformNodeWin* result = static_cast<AXPlatformNodeWin*>(
owner_->delegate_->GetFromNodeID(target_ids_[i]));
if (!result || !result->delegate_) {
@@ -225,7 +227,7 @@ STDMETHODIMP AXPlatformNodeRelationWin::get_nTargets(long* n_targets) {
return S_OK;
}
-STDMETHODIMP AXPlatformNodeRelationWin::get_target(long target_index,
+STDMETHODIMP AXPlatformNodeRelationWin::get_target(LONG target_index,
IUnknown** target) {
if (!target)
return E_INVALIDARG;
@@ -234,7 +236,7 @@ STDMETHODIMP AXPlatformNodeRelationWin::get_target(long target_index,
return E_FAIL;
if (target_index < 0 ||
- target_index >= static_cast<long>(target_ids_.size())) {
+ target_index >= static_cast<LONG>(target_ids_.size())) {
return E_INVALIDARG;
}
@@ -248,16 +250,16 @@ STDMETHODIMP AXPlatformNodeRelationWin::get_target(long target_index,
return S_OK;
}
-STDMETHODIMP AXPlatformNodeRelationWin::get_targets(long max_targets,
+STDMETHODIMP AXPlatformNodeRelationWin::get_targets(LONG max_targets,
IUnknown** targets,
- long* n_targets) {
+ LONG* n_targets) {
if (!targets || !n_targets)
return E_INVALIDARG;
if (!owner_->delegate_)
return E_FAIL;
- long count = static_cast<long>(target_ids_.size());
+ LONG count = static_cast<LONG>(target_ids_.size());
if (count > max_targets)
count = max_targets;
@@ -265,7 +267,7 @@ STDMETHODIMP AXPlatformNodeRelationWin::get_targets(long max_targets,
if (count == 0)
return S_FALSE;
- for (long i = 0; i < count; ++i) {
+ for (LONG i = 0; i < count; ++i) {
HRESULT result = get_target(i, &targets[i]);
if (result != S_OK)
return result;
@@ -286,7 +288,7 @@ AXPlatformNodeRelationWin::get_localizedRelationType(BSTR* relation_type) {
// static
AXPlatformNode* AXPlatformNode::Create(AXPlatformNodeDelegate* delegate) {
// Make sure ATL is initialized in this module.
- ui::win::CreateATLModuleIfNeeded();
+ win::CreateATLModuleIfNeeded();
CComObject<AXPlatformNodeWin>* instance = nullptr;
HRESULT hr = CComObject<AXPlatformNodeWin>::CreateInstance(&instance);
@@ -306,33 +308,50 @@ AXPlatformNode* AXPlatformNode::FromNativeViewAccessible(
return ax_platform_node.Get();
}
+using UniqueIdMap = base::hash_map<int32_t, AXPlatformNode*>;
+// Map from each AXPlatformNode's unique id to its instance.
+base::LazyInstance<UniqueIdMap>::DestructorAtExit g_unique_id_map =
+ LAZY_INSTANCE_INITIALIZER;
+
+// static
+AXPlatformNode* AXPlatformNodeWin::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;
+}
//
// AXPlatformNodeWin
//
-AXPlatformNodeWin::AXPlatformNodeWin() {
+AXPlatformNodeWin::AXPlatformNodeWin()
+ : unique_id_(GetNextAXPlatformNodeUniqueId()) {
+ g_unique_id_map.Get()[unique_id_] = this;
}
AXPlatformNodeWin::~AXPlatformNodeWin() {
- for (ui::AXPlatformNodeRelationWin* relation : relations_)
+ for (AXPlatformNodeRelationWin* relation : relations_)
relation->Release();
+ if (unique_id_)
+ g_unique_id_map.Get().erase(unique_id_);
}
void AXPlatformNodeWin::CalculateRelationships() {
ClearOwnRelations();
AddBidirectionalRelations(IA2_RELATION_CONTROLLER_FOR,
- IA2_RELATION_CONTROLLED_BY,
- ui::AX_ATTR_CONTROLS_IDS);
+ IA2_RELATION_CONTROLLED_BY, AX_ATTR_CONTROLS_IDS);
AddBidirectionalRelations(IA2_RELATION_DESCRIBED_BY,
IA2_RELATION_DESCRIPTION_FOR,
- ui::AX_ATTR_DESCRIBEDBY_IDS);
+ AX_ATTR_DESCRIBEDBY_IDS);
AddBidirectionalRelations(IA2_RELATION_FLOWS_TO, IA2_RELATION_FLOWS_FROM,
- ui::AX_ATTR_FLOWTO_IDS);
+ AX_ATTR_FLOWTO_IDS);
AddBidirectionalRelations(IA2_RELATION_LABELLED_BY, IA2_RELATION_LABEL_FOR,
- ui::AX_ATTR_LABELLEDBY_IDS);
+ AX_ATTR_LABELLEDBY_IDS);
int32_t details_id;
- if (GetIntAttribute(ui::AX_ATTR_DETAILS_ID, &details_id)) {
+ if (GetIntAttribute(AX_ATTR_DETAILS_ID, &details_id)) {
std::vector<int32_t> details_ids;
details_ids.push_back(details_id);
AddBidirectionalRelations(IA2_RELATION_DETAILS, IA2_RELATION_DETAILS_FOR,
@@ -340,11 +359,11 @@ void AXPlatformNodeWin::CalculateRelationships() {
}
int member_of_id;
- if (GetIntAttribute(ui::AX_ATTR_MEMBER_OF_ID, &member_of_id))
+ if (GetIntAttribute(AX_ATTR_MEMBER_OF_ID, &member_of_id))
AddRelation(IA2_RELATION_MEMBER_OF, member_of_id);
int error_message_id;
- if (GetIntAttribute(ui::AX_ATTR_ERRORMESSAGE_ID, &error_message_id))
+ if (GetIntAttribute(AX_ATTR_ERRORMESSAGE_ID, &error_message_id))
AddRelation(IA2_RELATION_ERROR_MESSAGE, error_message_id);
}
@@ -354,9 +373,8 @@ void AXPlatformNodeWin::AddRelation(const base::string16& relation_type,
if (target_id == GetData().id)
return;
- CComObject<ui::AXPlatformNodeRelationWin>* relation;
- HRESULT hr =
- CComObject<ui::AXPlatformNodeRelationWin>::CreateInstance(&relation);
+ CComObject<AXPlatformNodeRelationWin>* relation;
+ HRESULT hr = CComObject<AXPlatformNodeRelationWin>::CreateInstance(&relation);
DCHECK(SUCCEEDED(hr));
relation->AddRef();
relation->Initialize(this, relation_type);
@@ -367,7 +385,7 @@ void AXPlatformNodeWin::AddRelation(const base::string16& relation_type,
void AXPlatformNodeWin::AddBidirectionalRelations(
const base::string16& relation_type,
const base::string16& reverse_relation_type,
- ui::AXIntListAttribute attribute) {
+ AXIntListAttribute attribute) {
if (!HasIntListAttribute(attribute))
return;
@@ -388,9 +406,8 @@ void AXPlatformNodeWin::AddBidirectionalRelations(
if (filtered_target_ids.empty())
return;
- CComObject<ui::AXPlatformNodeRelationWin>* relation;
- HRESULT hr =
- CComObject<ui::AXPlatformNodeRelationWin>::CreateInstance(&relation);
+ CComObject<AXPlatformNodeRelationWin>* relation;
+ HRESULT hr = CComObject<AXPlatformNodeRelationWin>::CreateInstance(&relation);
DCHECK(SUCCEEDED(hr));
relation->AddRef();
relation->Initialize(this, relation_type);
@@ -423,7 +440,7 @@ void AXPlatformNodeWin::ClearOwnRelations() {
relations_.erase(
std::remove_if(relations_.begin(), relations_.end(),
- [](ui::AXPlatformNodeRelationWin* relation) {
+ [](AXPlatformNodeRelationWin* relation) {
if (relation->get_type() == IA2_RELATION_MEMBER_OF) {
relation->Release();
return true;
@@ -437,7 +454,7 @@ void AXPlatformNodeWin::RemoveBidirectionalRelationsOfType(
const base::string16& relation_type,
const base::string16& reverse_relation_type) {
for (auto iter = relations_.begin(); iter != relations_.end();) {
- ui::AXPlatformNodeRelationWin* relation = *iter;
+ AXPlatformNodeRelationWin* relation = *iter;
DCHECK(relation);
if (relation->get_type() == relation_type) {
for (int target_id : relation->get_target_ids()) {
@@ -460,7 +477,7 @@ void AXPlatformNodeWin::RemoveTargetFromRelation(
const base::string16& relation_type,
int target_id) {
for (auto iter = relations_.begin(); iter != relations_.end();) {
- ui::AXPlatformNodeRelationWin* relation = *iter;
+ AXPlatformNodeRelationWin* relation = *iter;
DCHECK(relation);
if (relation->get_type() == relation_type) {
// If |target_id| is not present, |RemoveTarget| will do nothing.
@@ -492,7 +509,7 @@ void AXPlatformNodeWin::SanitizeStringAttributeForIA2(
void AXPlatformNodeWin::StringAttributeToIA2(
std::vector<base::string16>& attributes,
- ui::AXStringAttribute attribute,
+ AXStringAttribute attribute,
const char* ia2_attr) {
base::string16 value;
if (GetString16Attribute(attribute, &value)) {
@@ -503,7 +520,7 @@ void AXPlatformNodeWin::StringAttributeToIA2(
void AXPlatformNodeWin::BoolAttributeToIA2(
std::vector<base::string16>& attributes,
- ui::AXBoolAttribute attribute,
+ AXBoolAttribute attribute,
const char* ia2_attr) {
bool value;
if (GetBoolAttribute(attribute, &value)) {
@@ -514,7 +531,7 @@ void AXPlatformNodeWin::BoolAttributeToIA2(
void AXPlatformNodeWin::IntAttributeToIA2(
std::vector<base::string16>& attributes,
- ui::AXIntAttribute attribute,
+ AXIntAttribute attribute,
const char* ia2_attr) {
int value;
if (GetIntAttribute(attribute, &value)) {
@@ -532,7 +549,13 @@ void AXPlatformNodeWin::Dispose() {
}
void AXPlatformNodeWin::Destroy() {
+ g_unique_id_map.Get().erase(unique_id_);
+ unique_id_ = 0;
+
RemoveAlertTarget();
+
+ // This will end up calling Dispose() which may result in deleting this object
+ // if there are no more outstanding references.
AXPlatformNodeBase::Destroy();
}
@@ -544,16 +567,15 @@ gfx::NativeViewAccessible AXPlatformNodeWin::GetNativeViewAccessible() {
return this;
}
-void AXPlatformNodeWin::NotifyAccessibilityEvent(ui::AXEvent event_type) {
+void AXPlatformNodeWin::NotifyAccessibilityEvent(AXEvent event_type) {
HWND hwnd = delegate_->GetTargetForNativeAccessibilityEvent();
if (!hwnd)
return;
// Menu items fire selection events but Windows screen readers work reliably
// with focus events. Remap here.
- if (event_type == ui::AX_EVENT_SELECTION &&
- GetData().role == ui::AX_ROLE_MENU_ITEM)
- event_type = ui::AX_EVENT_FOCUS;
+ if (event_type == AX_EVENT_SELECTION && GetData().role == AX_ROLE_MENU_ITEM)
+ event_type = AX_EVENT_FOCUS;
int native_event = MSAAEvent(event_type);
if (native_event < EVENT_MIN)
@@ -562,7 +584,7 @@ void AXPlatformNodeWin::NotifyAccessibilityEvent(ui::AXEvent event_type) {
::NotifyWinEvent(native_event, hwnd, OBJID_CLIENT, -unique_id_);
// Keep track of objects that are a target of an alert event.
- if (event_type == ui::AX_EVENT_ALERT)
+ if (event_type == AX_EVENT_ALERT)
AddAlertTarget();
}
@@ -645,7 +667,7 @@ HRESULT AXPlatformNodeWin::accDoDefaultAction(VARIANT var_id) {
AXPlatformNodeWin* target;
COM_OBJECT_VALIDATE_VAR_ID_AND_GET_TARGET(var_id, target);
AXActionData data;
- data.action = ui::AX_ACTION_DO_DEFAULT;
+ data.action = AX_ACTION_DO_DEFAULT;
if (target->delegate_->AccessibilityPerformAction(data))
return S_OK;
@@ -712,8 +734,8 @@ STDMETHODIMP AXPlatformNodeWin::accNavigate(
case NAVDIR_DOWN: {
// This direction is not implemented except in tables.
- if (!ui::IsTableLikeRole(GetData().role) &&
- !ui::IsCellOrTableHeaderRole(GetData().role))
+ if (!IsTableLikeRole(GetData().role) &&
+ !IsCellOrTableHeaderRole(GetData().role))
return E_NOTIMPL;
AXPlatformNodeBase* next = target->GetTableCell(
@@ -727,8 +749,8 @@ STDMETHODIMP AXPlatformNodeWin::accNavigate(
case NAVDIR_UP: {
// This direction is not implemented except in tables.
- if (!ui::IsTableLikeRole(GetData().role) &&
- !ui::IsCellOrTableHeaderRole(GetData().role))
+ if (!IsTableLikeRole(GetData().role) &&
+ !IsCellOrTableHeaderRole(GetData().role))
return E_NOTIMPL;
AXPlatformNodeBase* next =
@@ -742,8 +764,8 @@ STDMETHODIMP AXPlatformNodeWin::accNavigate(
case NAVDIR_LEFT: {
// This direction is not implemented except in tables.
- if (!ui::IsTableLikeRole(GetData().role) &&
- !ui::IsCellOrTableHeaderRole(GetData().role))
+ if (!IsTableLikeRole(GetData().role) &&
+ !IsCellOrTableHeaderRole(GetData().role))
return E_NOTIMPL;
AXPlatformNodeBase* next =
@@ -758,8 +780,8 @@ STDMETHODIMP AXPlatformNodeWin::accNavigate(
case NAVDIR_RIGHT: {
// This direction is not implemented except in tables.
- if (!ui::IsTableLikeRole(GetData().role) &&
- !ui::IsCellOrTableHeaderRole(GetData().role))
+ if (!IsTableLikeRole(GetData().role) &&
+ !IsCellOrTableHeaderRole(GetData().role))
return E_NOTIMPL;
AXPlatformNodeBase* next = target->GetTableCell(
@@ -798,7 +820,6 @@ STDMETHODIMP AXPlatformNodeWin::get_accChild(VARIANT var_child,
STDMETHODIMP AXPlatformNodeWin::get_accChildCount(LONG* child_count) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_ACC_CHILD_COUNT);
-
COM_OBJECT_VALIDATE_1_ARG(child_count);
*child_count = delegate_->GetChildCount();
return S_OK;
@@ -809,6 +830,7 @@ STDMETHODIMP AXPlatformNodeWin::get_accDefaultAction(
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_ACC_DEFAULT_ACTION);
AXPlatformNodeWin* target;
COM_OBJECT_VALIDATE_VAR_ID_1_ARG_AND_GET_TARGET(var_id, def_action, target);
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
int action;
if (!target->GetIntAttribute(AX_ATTR_DEFAULT_ACTION_VERB, &action)) {
@@ -834,7 +856,7 @@ STDMETHODIMP AXPlatformNodeWin::get_accDescription(
AXPlatformNodeWin* target;
COM_OBJECT_VALIDATE_VAR_ID_1_ARG_AND_GET_TARGET(var_id, desc, target);
- return target->GetStringAttributeAsBstr(ui::AX_ATTR_DESCRIPTION, desc);
+ return target->GetStringAttributeAsBstr(AX_ATTR_DESCRIPTION, desc);
}
STDMETHODIMP AXPlatformNodeWin::get_accFocus(VARIANT* focus_child) {
@@ -862,7 +884,7 @@ STDMETHODIMP AXPlatformNodeWin::get_accKeyboardShortcut(
AXPlatformNodeWin* target;
COM_OBJECT_VALIDATE_VAR_ID_1_ARG_AND_GET_TARGET(var_id, acc_key, target);
- return target->GetStringAttributeAsBstr(ui::AX_ATTR_KEY_SHORTCUTS, acc_key);
+ return target->GetStringAttributeAsBstr(AX_ATTR_KEY_SHORTCUTS, acc_key);
}
STDMETHODIMP AXPlatformNodeWin::get_accName(
@@ -871,7 +893,7 @@ STDMETHODIMP AXPlatformNodeWin::get_accName(
AXPlatformNodeWin* target;
COM_OBJECT_VALIDATE_VAR_ID_1_ARG_AND_GET_TARGET(var_id, name, target);
- HRESULT result = target->GetStringAttributeAsBstr(ui::AX_ATTR_NAME, name);
+ HRESULT result = target->GetStringAttributeAsBstr(AX_ATTR_NAME, name);
if (FAILED(result) && MSAARole() == ROLE_SYSTEM_DOCUMENT && GetParent()) {
// Hack: Some versions of JAWS crash if they get an empty name on
// a document that's the child of an iframe, so always return a
@@ -956,9 +978,9 @@ STDMETHODIMP AXPlatformNodeWin::get_accValue(VARIANT var_id, BSTR* value) {
//
// Color Well special case (Use AX_ATTR_COLOR_VALUE)
//
- if (target->GetData().role == ui::AX_ROLE_COLOR_WELL) {
+ if (target->GetData().role == AX_ROLE_COLOR_WELL) {
unsigned int color = static_cast<unsigned int>(target->GetIntAttribute(
- ui::AX_ATTR_COLOR_VALUE)); // todo, why the static cast?
+ AX_ATTR_COLOR_VALUE)); // todo, why the static cast?
unsigned int red = SkColorGetR(color);
unsigned int green = SkColorGetG(color);
@@ -975,8 +997,8 @@ STDMETHODIMP AXPlatformNodeWin::get_accValue(VARIANT var_id, BSTR* value) {
//
// Document special case (Use the document's url)
//
- if (target->GetData().role == ui::AX_ROLE_ROOT_WEB_AREA ||
- target->GetData().role == ui::AX_ROLE_WEB_AREA) {
+ if (target->GetData().role == AX_ROLE_ROOT_WEB_AREA ||
+ target->GetData().role == AX_ROLE_WEB_AREA) {
result = base::UTF8ToUTF16(target->delegate_->GetTreeData().url);
*value = SysAllocString(result.c_str());
DCHECK(*value);
@@ -986,9 +1008,8 @@ STDMETHODIMP AXPlatformNodeWin::get_accValue(VARIANT var_id, BSTR* value) {
//
// Links (Use AX_ATTR_URL)
//
- if (target->GetData().role == ui::AX_ROLE_LINK ||
- target->GetData().role == ui::AX_ROLE_IMAGE_MAP_LINK) {
- result = target->GetString16Attribute(ui::AX_ATTR_URL);
+ if (target->GetData().role == AX_ROLE_LINK) {
+ result = target->GetString16Attribute(AX_ATTR_URL);
*value = SysAllocString(result.c_str());
DCHECK(*value);
return S_OK;
@@ -997,14 +1018,14 @@ STDMETHODIMP AXPlatformNodeWin::get_accValue(VARIANT var_id, BSTR* value) {
// After this point, the role based special cases should test for an empty
// result.
- result = target->GetString16Attribute(ui::AX_ATTR_VALUE);
+ result = target->GetString16Attribute(AX_ATTR_VALUE);
//
// RangeValue (Use AX_ATTR_VALUE_FOR_RANGE)
//
if (result.empty() && target->IsRangeValueSupported()) {
float fval;
- if (target->GetFloatAttribute(ui::AX_ATTR_VALUE_FOR_RANGE, &fval)) {
+ if (target->GetFloatAttribute(AX_ATTR_VALUE_FOR_RANGE, &fval)) {
result = base::UTF8ToUTF16(base::DoubleToString(fval));
*value = SysAllocString(result.c_str());
DCHECK(*value);
@@ -1030,7 +1051,7 @@ STDMETHODIMP AXPlatformNodeWin::put_accValue(VARIANT var_id,
COM_OBJECT_VALIDATE_VAR_ID_AND_GET_TARGET(var_id, target);
AXActionData data;
- data.action = ui::AX_ACTION_SET_VALUE;
+ data.action = AX_ACTION_SET_VALUE;
data.value = new_value;
if (target->delegate_->AccessibilityPerformAction(data))
return S_OK;
@@ -1041,7 +1062,7 @@ STDMETHODIMP AXPlatformNodeWin::get_accSelection(VARIANT* selected) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_ACC_SELECTION);
COM_OBJECT_VALIDATE_1_ARG(selected);
- if (GetData().role != ui::AX_ROLE_LIST_BOX)
+ if (GetData().role != AX_ROLE_LIST_BOX)
return E_NOTIMPL;
unsigned long selected_count = 0;
@@ -1049,7 +1070,7 @@ STDMETHODIMP AXPlatformNodeWin::get_accSelection(VARIANT* selected) {
AXPlatformNodeWin* node = static_cast<AXPlatformNodeWin*>(
FromNativeViewAccessible(delegate_->ChildAtIndex(i)));
- if (node && node->GetData().state & (1 << ui::AX_STATE_SELECTED))
+ if (node && node->GetData().HasState(AX_STATE_SELECTED))
++selected_count;
}
@@ -1063,7 +1084,7 @@ STDMETHODIMP AXPlatformNodeWin::get_accSelection(VARIANT* selected) {
AXPlatformNodeWin* node = static_cast<AXPlatformNodeWin*>(
FromNativeViewAccessible(delegate_->ChildAtIndex(i)));
- if (node && node->GetData().state & (1 << ui::AX_STATE_SELECTED)) {
+ if (node && node->GetData().HasState(AX_STATE_SELECTED)) {
selected->vt = VT_DISPATCH;
selected->pdispVal = node;
node->AddRef();
@@ -1081,7 +1102,7 @@ STDMETHODIMP AXPlatformNodeWin::get_accSelection(VARIANT* selected) {
AXPlatformNodeWin* node = static_cast<AXPlatformNodeWin*>(
FromNativeViewAccessible(delegate_->ChildAtIndex(i)));
- if (node && node->GetData().state & (1 << ui::AX_STATE_SELECTED)) {
+ if (node && node->GetData().HasState(AX_STATE_SELECTED)) {
enum_variant->ItemAt(index)->vt = VT_DISPATCH;
enum_variant->ItemAt(index)->pdispVal = node;
node->AddRef();
@@ -1101,8 +1122,8 @@ STDMETHODIMP AXPlatformNodeWin::accSelect(
COM_OBJECT_VALIDATE_VAR_ID_AND_GET_TARGET(var_id, target);
if (flagsSelect & SELFLAG_TAKEFOCUS) {
- ui::AXActionData action_data;
- action_data.action = ui::AX_ACTION_FOCUS;
+ AXActionData action_data;
+ action_data.action = AX_ACTION_FOCUS;
target->delegate_->AccessibilityPerformAction(action_data);
return S_OK;
}
@@ -1151,27 +1172,30 @@ STDMETHODIMP AXPlatformNodeWin::role(LONG* role) {
STDMETHODIMP AXPlatformNodeWin::get_states(AccessibleStates* states) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_STATES);
COM_OBJECT_VALIDATE_1_ARG(states);
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
*states = ComputeIA2State();
return S_OK;
}
STDMETHODIMP AXPlatformNodeWin::get_uniqueID(LONG* unique_id) {
+ WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_UNIQUE_ID);
COM_OBJECT_VALIDATE_1_ARG(unique_id);
*unique_id = -unique_id_;
return S_OK;
}
STDMETHODIMP AXPlatformNodeWin::get_windowHandle(HWND* window_handle) {
+ WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_WINDOW_HANDLE);
COM_OBJECT_VALIDATE_1_ARG(window_handle);
*window_handle = delegate_->GetTargetForNativeAccessibilityEvent();
return *window_handle ? S_OK : S_FALSE;
}
-STDMETHODIMP AXPlatformNodeWin::get_relationTargetsOfType(
- BSTR type_bstr,
- long max_targets,
- IUnknown ***targets,
- long *n_targets) {
+STDMETHODIMP AXPlatformNodeWin::get_relationTargetsOfType(BSTR type_bstr,
+ LONG max_targets,
+ IUnknown*** targets,
+ LONG* n_targets) {
COM_OBJECT_VALIDATE_2_ARGS(targets, n_targets);
*n_targets = 0;
@@ -1193,7 +1217,7 @@ STDMETHODIMP AXPlatformNodeWin::get_relationTargetsOfType(
alert_targets.push_back(target);
}
- long count = static_cast<long>(alert_targets.size());
+ LONG count = static_cast<LONG>(alert_targets.size());
if (count == 0)
return S_FALSE;
@@ -1208,7 +1232,7 @@ STDMETHODIMP AXPlatformNodeWin::get_relationTargetsOfType(
// Allocate COM memory for the result array and populate it.
*targets = static_cast<IUnknown**>(
CoTaskMemAlloc(count * sizeof(IUnknown*)));
- for (long i = 0; i < count; ++i) {
+ for (LONG i = 0; i < count; ++i) {
(*targets)[i] = static_cast<IAccessible*>(alert_targets[i]);
(*targets)[i]->AddRef();
}
@@ -1216,17 +1240,18 @@ STDMETHODIMP AXPlatformNodeWin::get_relationTargetsOfType(
}
STDMETHODIMP AXPlatformNodeWin::get_attributes(BSTR* attributes) {
+ WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_IA2_GET_ATTRIBUTES);
COM_OBJECT_VALIDATE_1_ARG(attributes);
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+ *attributes = nullptr;
+
base::string16 attributes_str;
+ std::vector<base::string16> computed_attributes = ComputeIA2Attributes();
+ for (const base::string16& attribute : computed_attributes)
+ attributes_str += attribute + L';';
- // Text fields need to report the attribute "text-model:a1" to instruct
- // screen readers to use IAccessible2 APIs to handle text editing in this
- // object (as opposed to treating it like a native Windows text box).
- // The text-model:a1 attribute is documented here:
- // http://www.linuxfoundation.org/collaborate/workgroups/accessibility/ia2/ia2_implementation_guide
- if (GetData().role == ui::AX_ROLE_TEXT_FIELD) {
- attributes_str = L"text-model:a1;";
- }
+ if (attributes_str.empty())
+ return S_FALSE;
*attributes = SysAllocString(attributes_str.c_str());
DCHECK(*attributes);
@@ -1234,6 +1259,7 @@ STDMETHODIMP AXPlatformNodeWin::get_attributes(BSTR* attributes) {
}
STDMETHODIMP AXPlatformNodeWin::get_indexInParent(LONG* index_in_parent) {
+ WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_INDEX_IN_PARENT);
COM_OBJECT_VALIDATE_1_ARG(index_in_parent);
*index_in_parent = GetIndexInParent();
if (*index_in_parent < 0)
@@ -1243,16 +1269,20 @@ STDMETHODIMP AXPlatformNodeWin::get_indexInParent(LONG* index_in_parent) {
}
STDMETHODIMP AXPlatformNodeWin::get_nRelations(LONG* n_relations) {
+ WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_N_RELATIONS);
COM_OBJECT_VALIDATE_1_ARG(n_relations);
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
*n_relations = static_cast<LONG>(relations_.size());
return S_OK;
}
STDMETHODIMP AXPlatformNodeWin::get_relation(LONG relation_index,
IAccessibleRelation** relation) {
+ WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_RELATION);
COM_OBJECT_VALIDATE_1_ARG(relation);
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (relation_index < 0 ||
- relation_index >= static_cast<long>(relations_.size())) {
+ relation_index >= static_cast<LONG>(relations_.size())) {
return E_INVALIDARG;
}
@@ -1264,13 +1294,16 @@ STDMETHODIMP AXPlatformNodeWin::get_relation(LONG relation_index,
STDMETHODIMP AXPlatformNodeWin::get_relations(LONG max_relations,
IAccessibleRelation** relations,
LONG* n_relations) {
+ WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_RELATIONS);
COM_OBJECT_VALIDATE_2_ARGS(relations, n_relations);
- long count = static_cast<long>(relations_.size());
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
+ LONG count = static_cast<LONG>(relations_.size());
*n_relations = count;
if (count == 0)
return S_FALSE;
- for (long i = 0; i < count; ++i) {
+ for (LONG i = 0; i < count; ++i) {
relations_[i]->AddRef();
relations[i] = relations_[i];
}
@@ -1278,6 +1311,33 @@ STDMETHODIMP AXPlatformNodeWin::get_relations(LONG max_relations,
return S_OK;
}
+STDMETHODIMP AXPlatformNodeWin::get_groupPosition(LONG* group_level,
+ LONG* similar_items_in_group,
+ LONG* position_in_group) {
+ WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_GROUP_POSITION);
+ COM_OBJECT_VALIDATE_3_ARGS(group_level, similar_items_in_group,
+ position_in_group);
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
+ *group_level = GetIntAttribute(ui::AX_ATTR_HIERARCHICAL_LEVEL);
+ *similar_items_in_group = GetIntAttribute(ui::AX_ATTR_SET_SIZE);
+ *position_in_group = GetIntAttribute(ui::AX_ATTR_POS_IN_SET);
+
+ if (*group_level == *similar_items_in_group == *position_in_group == 0)
+ return S_FALSE;
+ return S_OK;
+}
+
+STDMETHODIMP AXPlatformNodeWin::get_localizedExtendedRole(
+ BSTR* localized_extended_role) {
+ WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_LOCALIZED_EXTENDED_ROLE);
+ COM_OBJECT_VALIDATE_1_ARG(localized_extended_role);
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
+ return GetStringAttributeAsBstr(ui::AX_ATTR_ROLE_DESCRIPTION,
+ localized_extended_role);
+}
+
//
// IAccessible2 methods not implemented.
//
@@ -1300,17 +1360,6 @@ STDMETHODIMP AXPlatformNodeWin::scrollToPoint(
return E_NOTIMPL;
}
-STDMETHODIMP AXPlatformNodeWin::get_groupPosition(LONG* group_level,
- LONG* similar_items_in_group,
- LONG* position_in_group) {
- return E_NOTIMPL;
-}
-
-STDMETHODIMP AXPlatformNodeWin::get_localizedExtendedRole(
- BSTR* localized_extended_role) {
- return E_NOTIMPL;
-}
-
STDMETHODIMP AXPlatformNodeWin::get_nExtendedStates(LONG* n_extended_states) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_N_EXTENDED_STATES);
return E_NOTIMPL;
@@ -1338,7 +1387,7 @@ STDMETHODIMP AXPlatformNodeWin::get_locale(IA2Locale* locale) {
}
STDMETHODIMP AXPlatformNodeWin::get_accessibleWithCaret(IUnknown** accessible,
- long* caret_offset) {
+ LONG* caret_offset) {
return E_NOTIMPL;
}
@@ -1346,10 +1395,12 @@ STDMETHODIMP AXPlatformNodeWin::get_accessibleWithCaret(IUnknown** accessible,
// IAccessibleTable methods.
//
-STDMETHODIMP AXPlatformNodeWin::get_accessibleAt(long row,
- long column,
+STDMETHODIMP AXPlatformNodeWin::get_accessibleAt(LONG row,
+ LONG column,
IUnknown** accessible) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_ACCESSIBLE_AT);
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
if (!accessible)
return E_INVALIDARG;
@@ -1369,6 +1420,8 @@ STDMETHODIMP AXPlatformNodeWin::get_accessibleAt(long row,
STDMETHODIMP AXPlatformNodeWin::get_caption(IUnknown** accessible) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_CAPTION);
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
if (!accessible)
return E_INVALIDARG;
@@ -1377,14 +1430,17 @@ STDMETHODIMP AXPlatformNodeWin::get_caption(IUnknown** accessible) {
return S_FALSE;
}
-STDMETHODIMP AXPlatformNodeWin::get_childIndex(long row,
- long column,
- long* cell_index) {
+STDMETHODIMP AXPlatformNodeWin::get_childIndex(LONG row,
+ LONG column,
+ LONG* cell_index) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_CHILD_INDEX);
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
if (!cell_index)
return E_INVALIDARG;
- auto* cell = GetTableCell(static_cast<int>(row), static_cast<int>(column));
+ AXPlatformNodeBase* cell =
+ GetTableCell(static_cast<int>(row), static_cast<int>(column));
if (cell) {
*cell_index = static_cast<LONG>(cell->GetTableCellIndex());
return S_OK;
@@ -1394,9 +1450,11 @@ STDMETHODIMP AXPlatformNodeWin::get_childIndex(long row,
return E_INVALIDARG;
}
-STDMETHODIMP AXPlatformNodeWin::get_columnDescription(long column,
+STDMETHODIMP AXPlatformNodeWin::get_columnDescription(LONG column,
BSTR* description) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_COLUMN_DESCRIPTION);
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
if (!description)
return E_INVALIDARG;
@@ -1410,16 +1468,16 @@ STDMETHODIMP AXPlatformNodeWin::get_columnDescription(long column,
return S_FALSE;
}
- for (int i = 0; i < rows; ++i) {
- auto* cell = GetTableCell(i, column);
- if (cell && cell->GetData().role == ui::AX_ROLE_COLUMN_HEADER) {
- base::string16 cell_name = cell->GetString16Attribute(ui::AX_ATTR_NAME);
+ for (int r = 0; r < rows; ++r) {
+ AXPlatformNodeBase* cell = GetTableCell(r, column);
+ if (cell && cell->GetData().role == AX_ROLE_COLUMN_HEADER) {
+ base::string16 cell_name = cell->GetString16Attribute(AX_ATTR_NAME);
if (cell_name.size() > 0) {
*description = SysAllocString(cell_name.c_str());
return S_OK;
}
- cell_name = cell->GetString16Attribute(ui::AX_ATTR_DESCRIPTION);
+ cell_name = cell->GetString16Attribute(AX_ATTR_DESCRIPTION);
if (cell_name.size() > 0) {
*description = SysAllocString(cell_name.c_str());
return S_OK;
@@ -1431,14 +1489,17 @@ STDMETHODIMP AXPlatformNodeWin::get_columnDescription(long column,
return S_FALSE;
}
-STDMETHODIMP AXPlatformNodeWin::get_columnExtentAt(long row,
- long column,
- long* n_columns_spanned) {
+STDMETHODIMP AXPlatformNodeWin::get_columnExtentAt(LONG row,
+ LONG column,
+ LONG* n_columns_spanned) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_COLUMN_EXTENT_AT);
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
if (!n_columns_spanned)
return E_INVALIDARG;
- auto* cell = GetTableCell(static_cast<int>(row), static_cast<int>(column));
+ AXPlatformNodeBase* cell =
+ GetTableCell(static_cast<int>(row), static_cast<int>(column));
if (!cell)
return E_INVALIDARG;
@@ -1448,27 +1509,33 @@ STDMETHODIMP AXPlatformNodeWin::get_columnExtentAt(long row,
STDMETHODIMP AXPlatformNodeWin::get_columnHeader(
IAccessibleTable** accessible_table,
- long* starting_row_index) {
+ LONG* starting_row_index) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_COLUMN_HEADER);
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
// TODO(dmazzoni): implement
return E_NOTIMPL;
}
-STDMETHODIMP AXPlatformNodeWin::get_columnIndex(long cell_index,
- long* column_index) {
+STDMETHODIMP AXPlatformNodeWin::get_columnIndex(LONG cell_index,
+ LONG* column_index) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_COLUMN_INDEX);
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
if (!column_index)
return E_INVALIDARG;
- auto* cell = GetTableCell(cell_index);
+ AXPlatformNodeBase* cell = GetTableCell(cell_index);
if (!cell)
return E_INVALIDARG;
*column_index = cell->GetTableColumn();
return S_OK;
}
-STDMETHODIMP AXPlatformNodeWin::get_nColumns(long* column_count) {
+STDMETHODIMP AXPlatformNodeWin::get_nColumns(LONG* column_count) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_N_COLUMNS);
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
if (!column_count)
return E_INVALIDARG;
@@ -1476,8 +1543,10 @@ STDMETHODIMP AXPlatformNodeWin::get_nColumns(long* column_count) {
return S_OK;
}
-STDMETHODIMP AXPlatformNodeWin::get_nRows(long* row_count) {
+STDMETHODIMP AXPlatformNodeWin::get_nRows(LONG* row_count) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_N_ROWS);
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
if (!row_count)
return E_INVALIDARG;
@@ -1485,37 +1554,96 @@ STDMETHODIMP AXPlatformNodeWin::get_nRows(long* row_count) {
return S_OK;
}
-STDMETHODIMP AXPlatformNodeWin::get_nSelectedChildren(long* cell_count) {
+STDMETHODIMP AXPlatformNodeWin::get_nSelectedChildren(LONG* cell_count) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_N_SELECTED_CHILDREN);
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
if (!cell_count)
return E_INVALIDARG;
-
- // TODO(dmazzoni): add support for selected cells/rows/columns in tables.
*cell_count = 0;
- return S_FALSE;
+
+ int columns = GetTableColumnCount();
+ int rows = GetTableRowCount();
+ if (columns <= 0 || rows <= 0)
+ return S_FALSE;
+
+ LONG result = 0;
+ for (int r = 0; r < rows; ++r) {
+ for (int c = 0; c < columns; ++c) {
+ AXPlatformNodeBase* cell = GetTableCell(r, c);
+ if (cell && cell->GetData().HasState(AX_STATE_SELECTED))
+ result++;
+ }
+ }
+ *cell_count = result;
+ return S_OK;
}
-STDMETHODIMP AXPlatformNodeWin::get_nSelectedColumns(long* column_count) {
+STDMETHODIMP AXPlatformNodeWin::get_nSelectedColumns(LONG* column_count) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_N_SELECTED_COLUMNS);
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
if (!column_count)
return E_INVALIDARG;
-
*column_count = 0;
- return S_FALSE;
+
+ int columns = GetTableColumnCount();
+ int rows = GetTableRowCount();
+ if (columns <= 0 || rows <= 0)
+ return S_FALSE;
+
+ // If every cell in a column is selected, then that column is selected.
+ LONG result = 0;
+ for (int c = 0; c < columns; ++c) {
+ bool selected = true;
+ for (int r = 0; r < rows && selected == true; ++r) {
+ AXPlatformNodeBase* cell = GetTableCell(r, c);
+ if (!cell || !(cell->GetData().HasState(AX_STATE_SELECTED)))
+ selected = false;
+ }
+ if (selected)
+ result++;
+ }
+
+ *column_count = result;
+ return S_OK;
}
-STDMETHODIMP AXPlatformNodeWin::get_nSelectedRows(long* row_count) {
+STDMETHODIMP AXPlatformNodeWin::get_nSelectedRows(LONG* row_count) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_N_SELECTED_ROWS);
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
if (!row_count)
return E_INVALIDARG;
-
*row_count = 0;
- return S_FALSE;
+
+ int columns = GetTableColumnCount();
+ int rows = GetTableRowCount();
+ if (columns <= 0 || rows <= 0)
+ return S_FALSE;
+
+ // If every cell in a row is selected, then that row is selected.
+ LONG result = 0;
+ for (int r = 0; r < rows; ++r) {
+ bool selected = true;
+ for (int c = 0; c < columns && selected == true; ++c) {
+ AXPlatformNodeBase* cell = GetTableCell(r, c);
+ if (!cell || !(cell->GetData().HasState(AX_STATE_SELECTED)))
+ selected = false;
+ }
+ if (selected)
+ result++;
+ }
+
+ *row_count = result;
+ return S_OK;
}
-STDMETHODIMP AXPlatformNodeWin::get_rowDescription(long row,
+STDMETHODIMP AXPlatformNodeWin::get_rowDescription(LONG row,
BSTR* description) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_ROW_DESCRIPTION);
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
if (!description)
return E_INVALIDARG;
@@ -1528,15 +1656,15 @@ STDMETHODIMP AXPlatformNodeWin::get_rowDescription(long row,
return S_FALSE;
}
- for (int i = 0; i < columns; ++i) {
- auto* cell = GetTableCell(row, i);
- if (cell && cell->GetData().role == ui::AX_ROLE_ROW_HEADER) {
- base::string16 cell_name = cell->GetString16Attribute(ui::AX_ATTR_NAME);
+ for (int c = 0; c < columns; ++c) {
+ AXPlatformNodeBase* cell = GetTableCell(row, c);
+ if (cell && cell->GetData().role == AX_ROLE_ROW_HEADER) {
+ base::string16 cell_name = cell->GetString16Attribute(AX_ATTR_NAME);
if (cell_name.size() > 0) {
*description = SysAllocString(cell_name.c_str());
return S_OK;
}
- cell_name = cell->GetString16Attribute(ui::AX_ATTR_DESCRIPTION);
+ cell_name = cell->GetString16Attribute(AX_ATTR_DESCRIPTION);
if (cell_name.size() > 0) {
*description = SysAllocString(cell_name.c_str());
return S_OK;
@@ -1548,14 +1676,16 @@ STDMETHODIMP AXPlatformNodeWin::get_rowDescription(long row,
return S_FALSE;
}
-STDMETHODIMP AXPlatformNodeWin::get_rowExtentAt(long row,
- long column,
- long* n_rows_spanned) {
+STDMETHODIMP AXPlatformNodeWin::get_rowExtentAt(LONG row,
+ LONG column,
+ LONG* n_rows_spanned) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_ROW_EXTENT_AT);
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
if (!n_rows_spanned)
return E_INVALIDARG;
- auto* cell = GetTableCell(row, column);
+ AXPlatformNodeBase* cell = GetTableCell(row, column);
if (!cell)
return E_INVALIDARG;
@@ -1565,17 +1695,22 @@ STDMETHODIMP AXPlatformNodeWin::get_rowExtentAt(long row,
STDMETHODIMP AXPlatformNodeWin::get_rowHeader(
IAccessibleTable** accessible_table,
- long* starting_column_index) {
+ LONG* starting_column_index) {
WIN_ACCESSIBILITY_API_HISTOGRAM(UMA_API_GET_ROW_HEADER);
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
// TODO(dmazzoni): implement
return E_NOTIMPL;
}
-STDMETHODIMP AXPlatformNodeWin::get_rowIndex(long cell_index, long* row_index) {
+STDMETHODIMP AXPlatformNodeWin::get_rowIndex(LONG cell_index, LONG* row_index) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
if (!row_index)
return E_INVALIDARG;
- auto* cell = GetTableCell(cell_index);
+ AXPlatformNodeBase* cell = GetTableCell(cell_index);
if (!cell)
return E_INVALIDARG;
@@ -1583,40 +1718,95 @@ STDMETHODIMP AXPlatformNodeWin::get_rowIndex(long cell_index, long* row_index) {
return S_OK;
}
-STDMETHODIMP AXPlatformNodeWin::get_selectedChildren(long max_children,
- long** children,
- long* n_children) {
- if (!children || !n_children)
+STDMETHODIMP AXPlatformNodeWin::get_selectedChildren(LONG max_children,
+ LONG** children,
+ LONG* n_children) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
+ if (!children || !n_children || max_children <= 0)
return E_INVALIDARG;
- // TODO(dmazzoni): Implement this.
- *n_children = 0;
- return S_FALSE;
+ int columns = GetTableColumnCount();
+ int rows = GetTableRowCount();
+ if (columns <= 0 || rows <= 0)
+ return S_FALSE;
+
+ std::vector<LONG> results;
+ for (int r = 0; r < rows; ++r) {
+ for (int c = 0; c < columns; ++c) {
+ AXPlatformNodeBase* cell = GetTableCell(r, c);
+ if (cell && cell->GetData().HasState(AX_STATE_SELECTED))
+ // index is row index * column count + column index.
+ results.push_back(r * columns + c);
+ }
+ }
+
+ return AllocateComArrayFromVector(results, max_children, children,
+ n_children);
}
-STDMETHODIMP AXPlatformNodeWin::get_selectedColumns(long max_columns,
- long** columns,
- long* n_columns) {
- if (!columns || !n_columns)
+STDMETHODIMP AXPlatformNodeWin::get_selectedColumns(LONG max_columns,
+ LONG** columns,
+ LONG* n_columns) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
+ if (!columns || !n_columns || max_columns <= 0)
return E_INVALIDARG;
- // TODO(dmazzoni): Implement this.
- *n_columns = 0;
- return S_FALSE;
+ int column_count = GetTableColumnCount();
+ int row_count = GetTableRowCount();
+ if (column_count <= 0 || row_count <= 0)
+ return S_FALSE;
+
+ std::vector<LONG> results;
+ for (int c = 0; c < column_count; ++c) {
+ bool selected = true;
+ for (int r = 0; r < row_count && selected == true; ++r) {
+ AXPlatformNodeBase* cell = GetTableCell(r, c);
+ if (!cell || !(cell->GetData().HasState(AX_STATE_SELECTED)))
+ selected = false;
+ }
+ if (selected)
+ results.push_back(c);
+ }
+
+ return AllocateComArrayFromVector(results, max_columns, columns, n_columns);
}
-STDMETHODIMP AXPlatformNodeWin::get_selectedRows(long max_rows,
- long** rows,
- long* n_rows) {
- if (!rows || !n_rows)
+STDMETHODIMP AXPlatformNodeWin::get_selectedRows(LONG max_rows,
+ LONG** rows,
+ LONG* n_rows) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+ if (!rows || !n_rows || max_rows <= 0)
return E_INVALIDARG;
- // TODO(dmazzoni): Implement this.
- *n_rows = 0;
- return S_FALSE;
+ int column_count = GetTableColumnCount();
+ int row_count = GetTableRowCount();
+ if (column_count <= 0 || row_count <= 0)
+ return S_FALSE;
+
+ std::vector<LONG> results;
+ for (int r = 0; r < row_count; ++r) {
+ bool selected = true;
+ for (int c = 0; c < column_count && selected == true; ++c) {
+ AXPlatformNodeBase* cell = GetTableCell(r, c);
+ if (!cell || !(cell->GetData().HasState(AX_STATE_SELECTED)))
+ selected = false;
+ }
+ if (selected)
+ results.push_back(r);
+ }
+
+ return AllocateComArrayFromVector(results, max_rows, rows, n_rows);
}
STDMETHODIMP AXPlatformNodeWin::get_summary(IUnknown** accessible) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
if (!accessible)
return E_INVALIDARG;
@@ -1625,48 +1815,88 @@ STDMETHODIMP AXPlatformNodeWin::get_summary(IUnknown** accessible) {
return S_FALSE;
}
-STDMETHODIMP AXPlatformNodeWin::get_isColumnSelected(long column,
+STDMETHODIMP AXPlatformNodeWin::get_isColumnSelected(LONG column,
boolean* is_selected) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!is_selected)
return E_INVALIDARG;
-
- // TODO(dmazzoni): Implement this.
*is_selected = false;
+
+ int columns = GetTableColumnCount();
+ int rows = GetTableRowCount();
+ if (columns <= 0 || rows <= 0 || column >= columns || column < 0)
+ return S_FALSE;
+
+ for (int r = 0; r < rows; ++r) {
+ AXPlatformNodeBase* cell = GetTableCell(r, column);
+ if (!cell || !(cell->GetData().HasState(AX_STATE_SELECTED)))
+ return S_OK;
+ }
+
+ *is_selected = true;
return S_OK;
}
-STDMETHODIMP AXPlatformNodeWin::get_isRowSelected(long row,
+STDMETHODIMP AXPlatformNodeWin::get_isRowSelected(LONG row,
boolean* is_selected) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!is_selected)
return E_INVALIDARG;
-
- // TODO(dmazzoni): Implement this.
*is_selected = false;
+
+ int columns = GetTableColumnCount();
+ int rows = GetTableRowCount();
+ if (columns <= 0 || rows <= 0 || row >= rows || row < 0)
+ return S_FALSE;
+
+ for (int c = 0; c < columns; ++c) {
+ AXPlatformNodeBase* cell = GetTableCell(row, c);
+ if (!cell || !(cell->GetData().HasState(AX_STATE_SELECTED)))
+ return S_OK;
+ }
+
+ *is_selected = true;
return S_OK;
}
-STDMETHODIMP AXPlatformNodeWin::get_isSelected(long row,
- long column,
+STDMETHODIMP AXPlatformNodeWin::get_isSelected(LONG row,
+ LONG column,
boolean* is_selected) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!is_selected)
return E_INVALIDARG;
-
- // TODO(dmazzoni): Implement this.
*is_selected = false;
+
+ int columns = GetTableColumnCount();
+ int rows = GetTableRowCount();
+ if (columns <= 0 || rows <= 0 || row >= rows || row < 0 ||
+ column >= columns || column < 0)
+ return S_FALSE;
+
+ AXPlatformNodeBase* cell = GetTableCell(row, column);
+ if (cell && cell->GetData().HasState(AX_STATE_SELECTED))
+ *is_selected = true;
+
return S_OK;
}
STDMETHODIMP AXPlatformNodeWin::get_rowColumnExtentsAtIndex(
- long index,
- long* row,
- long* column,
- long* row_extents,
- long* column_extents,
+ LONG index,
+ LONG* row,
+ LONG* column,
+ LONG* row_extents,
+ LONG* column_extents,
boolean* is_selected) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
if (!row || !column || !row_extents || !column_extents || !is_selected)
return E_INVALIDARG;
- auto* cell = GetTableCell(index);
+ AXPlatformNodeBase* cell = GetTableCell(index);
if (!cell)
return E_INVALIDARG;
@@ -1679,24 +1909,37 @@ STDMETHODIMP AXPlatformNodeWin::get_rowColumnExtentsAtIndex(
return S_OK;
}
-STDMETHODIMP AXPlatformNodeWin::selectRow(long row) {
+STDMETHODIMP AXPlatformNodeWin::selectRow(LONG row) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
return E_NOTIMPL;
}
-STDMETHODIMP AXPlatformNodeWin::selectColumn(long column) {
+STDMETHODIMP AXPlatformNodeWin::selectColumn(LONG column) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
return E_NOTIMPL;
}
-STDMETHODIMP AXPlatformNodeWin::unselectRow(long row) {
+STDMETHODIMP AXPlatformNodeWin::unselectRow(LONG row) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
return E_NOTIMPL;
}
-STDMETHODIMP AXPlatformNodeWin::unselectColumn(long column) {
+STDMETHODIMP AXPlatformNodeWin::unselectColumn(LONG column) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
return E_NOTIMPL;
}
STDMETHODIMP
AXPlatformNodeWin::get_modelChange(IA2TableModelChange* model_change) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
return E_NOTIMPL;
}
@@ -1704,9 +1947,11 @@ AXPlatformNodeWin::get_modelChange(IA2TableModelChange* model_change) {
// IAccessibleTable2 methods.
//
-STDMETHODIMP AXPlatformNodeWin::get_cellAt(long row,
- long column,
+STDMETHODIMP AXPlatformNodeWin::get_cellAt(LONG row,
+ LONG column,
IUnknown** cell) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(AXMode::kScreenReader);
if (!cell)
return E_INVALIDARG;
@@ -1723,44 +1968,65 @@ STDMETHODIMP AXPlatformNodeWin::get_cellAt(long row,
return E_INVALIDARG;
}
-STDMETHODIMP AXPlatformNodeWin::get_nSelectedCells(long* cell_count) {
+STDMETHODIMP AXPlatformNodeWin::get_nSelectedCells(LONG* cell_count) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ // Note that this method does not need to set any ax mode since it
+ // calls into get_nSelectedChildren() which does.
return get_nSelectedChildren(cell_count);
}
STDMETHODIMP AXPlatformNodeWin::get_selectedCells(IUnknown*** cells,
- long* n_selected_cells) {
+ LONG* n_selected_cells) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!cells || !n_selected_cells)
return E_INVALIDARG;
- // TODO(dmazzoni): Implement this.
+ *cells = nullptr;
*n_selected_cells = 0;
- return S_OK;
-}
-STDMETHODIMP AXPlatformNodeWin::get_selectedColumns(long** columns,
- long* n_columns) {
- if (!columns || !n_columns)
- return E_INVALIDARG;
+ int columns = GetTableColumnCount();
+ int rows = GetTableRowCount();
+ if (columns <= 0 || rows <= 0)
+ return S_FALSE;
- // TODO(dmazzoni): Implement this.
- *n_columns = 0;
+ std::vector<AXPlatformNodeBase*> selected;
+ for (int r = 0; r < rows; ++r) {
+ for (int c = 0; c < columns; ++c) {
+ AXPlatformNodeBase* cell = GetTableCell(r, c);
+ if (cell && cell->GetData().HasState(AX_STATE_SELECTED))
+ selected.push_back(cell);
+ }
+ }
+
+ *n_selected_cells = static_cast<LONG>(selected.size());
+ *cells = static_cast<IUnknown**>(
+ CoTaskMemAlloc((*n_selected_cells) * sizeof(cells[0])));
+
+ for (size_t i = 0; i < selected.size(); ++i) {
+ auto* node_win = static_cast<AXPlatformNodeWin*>(selected[i]);
+ node_win->AddRef();
+ (*cells)[i] = static_cast<IAccessible*>(node_win);
+ }
return S_OK;
}
-STDMETHODIMP AXPlatformNodeWin::get_selectedRows(long** rows, long* n_rows) {
- if (!rows || !n_rows)
- return E_INVALIDARG;
+STDMETHODIMP AXPlatformNodeWin::get_selectedColumns(LONG** columns,
+ LONG* n_columns) {
+ return get_selectedColumns(INT_MAX, columns, n_columns);
+}
- // TODO(dmazzoni): Implement this.
- *n_rows = 0;
- return S_OK;
+STDMETHODIMP AXPlatformNodeWin::get_selectedRows(LONG** rows, LONG* n_rows) {
+ return get_selectedRows(INT_MAX, rows, n_rows);
}
//
// IAccessibleTableCell methods.
//
-STDMETHODIMP AXPlatformNodeWin::get_columnExtent(long* n_columns_spanned) {
+STDMETHODIMP AXPlatformNodeWin::get_columnExtent(LONG* n_columns_spanned) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!n_columns_spanned)
return E_INVALIDARG;
@@ -1770,12 +2036,14 @@ STDMETHODIMP AXPlatformNodeWin::get_columnExtent(long* n_columns_spanned) {
STDMETHODIMP AXPlatformNodeWin::get_columnHeaderCells(
IUnknown*** cell_accessibles,
- long* n_column_header_cells) {
+ LONG* n_column_header_cells) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
if (!cell_accessibles || !n_column_header_cells)
return E_INVALIDARG;
*n_column_header_cells = 0;
- auto* table = GetTable();
+ AXPlatformNodeBase* table = GetTable();
if (!table) {
return S_FALSE;
}
@@ -1786,18 +2054,18 @@ STDMETHODIMP AXPlatformNodeWin::get_columnHeaderCells(
if (columns <= 0 || rows <= 0 || column < 0 || column >= columns)
return S_FALSE;
- for (int i = 0; i < rows; ++i) {
- auto* cell = GetTableCell(i, column);
- if (cell && cell->GetData().role == ui::AX_ROLE_COLUMN_HEADER)
+ for (int r = 0; r < rows; ++r) {
+ AXPlatformNodeBase* cell = GetTableCell(r, column);
+ if (cell && cell->GetData().role == AX_ROLE_COLUMN_HEADER)
(*n_column_header_cells)++;
}
*cell_accessibles = static_cast<IUnknown**>(
CoTaskMemAlloc((*n_column_header_cells) * sizeof(cell_accessibles[0])));
int index = 0;
- for (int i = 0; i < rows; ++i) {
- AXPlatformNodeBase* cell = GetTableCell(i, column);
- if (cell && cell->GetData().role == ui::AX_ROLE_COLUMN_HEADER) {
+ for (int r = 0; r < rows; ++r) {
+ AXPlatformNodeBase* cell = GetTableCell(r, column);
+ if (cell && cell->GetData().role == AX_ROLE_COLUMN_HEADER) {
auto* node_win = static_cast<AXPlatformNodeWin*>(cell);
node_win->AddRef();
@@ -1809,7 +2077,10 @@ STDMETHODIMP AXPlatformNodeWin::get_columnHeaderCells(
return S_OK;
}
-STDMETHODIMP AXPlatformNodeWin::get_columnIndex(long* column_index) {
+STDMETHODIMP AXPlatformNodeWin::get_columnIndex(LONG* column_index) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
if (!column_index)
return E_INVALIDARG;
@@ -1817,7 +2088,10 @@ STDMETHODIMP AXPlatformNodeWin::get_columnIndex(long* column_index) {
return S_OK;
}
-STDMETHODIMP AXPlatformNodeWin::get_rowExtent(long* n_rows_spanned) {
+STDMETHODIMP AXPlatformNodeWin::get_rowExtent(LONG* n_rows_spanned) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
if (!n_rows_spanned)
return E_INVALIDARG;
@@ -1826,12 +2100,15 @@ STDMETHODIMP AXPlatformNodeWin::get_rowExtent(long* n_rows_spanned) {
}
STDMETHODIMP AXPlatformNodeWin::get_rowHeaderCells(IUnknown*** cell_accessibles,
- long* n_row_header_cells) {
+ LONG* n_row_header_cells) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
if (!cell_accessibles || !n_row_header_cells)
return E_INVALIDARG;
*n_row_header_cells = 0;
- auto* table = GetTable();
+ AXPlatformNodeBase* table = GetTable();
if (!table) {
return S_FALSE;
}
@@ -1842,18 +2119,18 @@ STDMETHODIMP AXPlatformNodeWin::get_rowHeaderCells(IUnknown*** cell_accessibles,
if (columns <= 0 || rows <= 0 || row < 0 || row >= rows)
return S_FALSE;
- for (int i = 0; i < columns; ++i) {
- auto* cell = GetTableCell(row, i);
- if (cell && cell->GetData().role == ui::AX_ROLE_ROW_HEADER)
+ for (int c = 0; c < columns; ++c) {
+ AXPlatformNodeBase* cell = GetTableCell(row, c);
+ if (cell && cell->GetData().role == AX_ROLE_ROW_HEADER)
(*n_row_header_cells)++;
}
*cell_accessibles = static_cast<IUnknown**>(
CoTaskMemAlloc((*n_row_header_cells) * sizeof(cell_accessibles[0])));
int index = 0;
- for (int i = 0; i < columns; ++i) {
- AXPlatformNodeBase* cell = GetTableCell(row, i);
- if (cell && cell->GetData().role == ui::AX_ROLE_ROW_HEADER) {
+ for (int c = 0; c < columns; ++c) {
+ AXPlatformNodeBase* cell = GetTableCell(row, c);
+ if (cell && cell->GetData().role == AX_ROLE_ROW_HEADER) {
auto* node_win = static_cast<AXPlatformNodeWin*>(cell);
node_win->AddRef();
@@ -1865,7 +2142,10 @@ STDMETHODIMP AXPlatformNodeWin::get_rowHeaderCells(IUnknown*** cell_accessibles,
return S_OK;
}
-STDMETHODIMP AXPlatformNodeWin::get_rowIndex(long* row_index) {
+STDMETHODIMP AXPlatformNodeWin::get_rowIndex(LONG* row_index) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
if (!row_index)
return E_INVALIDARG;
@@ -1874,6 +2154,9 @@ STDMETHODIMP AXPlatformNodeWin::get_rowIndex(long* row_index) {
}
STDMETHODIMP AXPlatformNodeWin::get_isSelected(boolean* is_selected) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
if (!is_selected)
return E_INVALIDARG;
@@ -1881,11 +2164,14 @@ STDMETHODIMP AXPlatformNodeWin::get_isSelected(boolean* is_selected) {
return S_OK;
}
-STDMETHODIMP AXPlatformNodeWin::get_rowColumnExtents(long* row_index,
- long* column_index,
- long* row_extents,
- long* column_extents,
+STDMETHODIMP AXPlatformNodeWin::get_rowColumnExtents(LONG* row_index,
+ LONG* column_index,
+ LONG* row_extents,
+ LONG* column_extents,
boolean* is_selected) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
if (!row_index || !column_index || !row_extents || !column_extents ||
!is_selected) {
return E_INVALIDARG;
@@ -1901,10 +2187,13 @@ STDMETHODIMP AXPlatformNodeWin::get_rowColumnExtents(long* row_index,
}
STDMETHODIMP AXPlatformNodeWin::get_table(IUnknown** table) {
+ // TODO(dougt) WIN_ACCESSIBILITY_API_HISTOGRAM?
+ AXPlatformNode::NotifyAddAXModeFlags(kScreenReaderAndHTMLAccessibilityModes);
+
if (!table)
return E_INVALIDARG;
- auto* find_table = GetTable();
+ AXPlatformNodeBase* find_table = GetTable();
if (!find_table) {
*table = nullptr;
return S_FALSE;
@@ -1933,14 +2222,14 @@ STDMETHODIMP AXPlatformNodeWin::get_nCharacters(LONG* n_characters) {
STDMETHODIMP AXPlatformNodeWin::get_caretOffset(LONG* offset) {
COM_OBJECT_VALIDATE_1_ARG(offset);
- *offset = static_cast<LONG>(GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END));
+ *offset = static_cast<LONG>(GetIntAttribute(AX_ATTR_TEXT_SEL_END));
return S_OK;
}
STDMETHODIMP AXPlatformNodeWin::get_nSelections(LONG* n_selections) {
COM_OBJECT_VALIDATE_1_ARG(n_selections);
- int sel_start = GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START);
- int sel_end = GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END);
+ int sel_start = GetIntAttribute(AX_ATTR_TEXT_SEL_START);
+ int sel_end = GetIntAttribute(AX_ATTR_TEXT_SEL_END);
if (sel_start != sel_end)
*n_selections = 1;
else
@@ -1955,10 +2244,8 @@ STDMETHODIMP AXPlatformNodeWin::get_selection(LONG selection_index,
if (selection_index != 0)
return E_INVALIDARG;
- *start_offset = static_cast<LONG>(
- GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START));
- *end_offset = static_cast<LONG>(
- GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END));
+ *start_offset = static_cast<LONG>(GetIntAttribute(AX_ATTR_TEXT_SEL_START));
+ *end_offset = static_cast<LONG>(GetIntAttribute(AX_ATTR_TEXT_SEL_END));
return S_OK;
}
@@ -1966,7 +2253,7 @@ STDMETHODIMP AXPlatformNodeWin::get_text(LONG start_offset,
LONG end_offset,
BSTR* text) {
COM_OBJECT_VALIDATE_1_ARG(text);
- int sel_end = GetIntAttribute(ui::AX_ATTR_TEXT_SEL_START);
+ int sel_end = GetIntAttribute(AX_ATTR_TEXT_SEL_START);
base::string16 text_str = TextForIAccessibleText();
LONG len = static_cast<LONG>(text_str.size());
@@ -2022,10 +2309,10 @@ STDMETHODIMP AXPlatformNodeWin::get_textAtOffset(
const base::string16& text_str = TextForIAccessibleText();
- *start_offset = FindBoundary(
- text_str, boundary_type, offset, ui::BACKWARDS_DIRECTION);
- *end_offset = FindBoundary(
- text_str, boundary_type, offset, ui::FORWARDS_DIRECTION);
+ *start_offset =
+ FindBoundary(text_str, boundary_type, offset, BACKWARDS_DIRECTION);
+ *end_offset =
+ FindBoundary(text_str, boundary_type, offset, FORWARDS_DIRECTION);
return get_text(*start_offset, *end_offset, text);
}
@@ -2048,8 +2335,8 @@ STDMETHODIMP AXPlatformNodeWin::get_textBeforeOffset(
const base::string16& text_str = TextForIAccessibleText();
- *start_offset = FindBoundary(
- text_str, boundary_type, offset, ui::BACKWARDS_DIRECTION);
+ *start_offset =
+ FindBoundary(text_str, boundary_type, offset, BACKWARDS_DIRECTION);
*end_offset = offset;
return get_text(*start_offset, *end_offset, text);
}
@@ -2074,8 +2361,8 @@ STDMETHODIMP AXPlatformNodeWin::get_textAfterOffset(
const base::string16& text_str = TextForIAccessibleText();
*start_offset = offset;
- *end_offset = FindBoundary(
- text_str, boundary_type, offset, ui::FORWARDS_DIRECTION);
+ *end_offset =
+ FindBoundary(text_str, boundary_type, offset, FORWARDS_DIRECTION);
return get_text(*start_offset, *end_offset, text);
}
@@ -2099,7 +2386,7 @@ STDMETHODIMP AXPlatformNodeWin::removeSelection(LONG selection_index) {
return E_INVALIDARG;
// Simply collapse the selection to the position of the caret if a caret is
// visible, otherwise set the selection to 0.
- return setCaretOffset(GetIntAttribute(ui::AX_ATTR_TEXT_SEL_END));
+ return setCaretOffset(GetIntAttribute(AX_ATTR_TEXT_SEL_END));
}
STDMETHODIMP AXPlatformNodeWin::setCaretOffset(LONG offset) {
@@ -2205,326 +2492,314 @@ int AXPlatformNodeWin::MSAARole() {
// If this is a web area for a presentational iframe, give it a role of
// something other than DOCUMENT so that the fact that it's a separate doc
// is not exposed to AT.
- if (IsWebAreaForPresentationalIframe()) {
+ if (IsWebAreaForPresentationalIframe())
return ROLE_SYSTEM_GROUPING;
- }
switch (GetData().role) {
- case ui::AX_ROLE_ALERT:
+ case AX_ROLE_ALERT:
return ROLE_SYSTEM_ALERT;
- case ui::AX_ROLE_ALERT_DIALOG:
+ case AX_ROLE_ALERT_DIALOG:
return ROLE_SYSTEM_DIALOG;
- case ui::AX_ROLE_ANCHOR:
+ case AX_ROLE_ANCHOR:
return ROLE_SYSTEM_LINK;
- case ui::AX_ROLE_APPLICATION:
+ case AX_ROLE_APPLICATION:
return ROLE_SYSTEM_APPLICATION;
- case ui::AX_ROLE_ARTICLE:
+ case AX_ROLE_ARTICLE:
return ROLE_SYSTEM_DOCUMENT;
- case ui::AX_ROLE_AUDIO:
+ case AX_ROLE_AUDIO:
return ROLE_SYSTEM_GROUPING;
- case ui::AX_ROLE_BANNER:
+ case AX_ROLE_BANNER:
return ROLE_SYSTEM_GROUPING;
- case ui::AX_ROLE_BUSY_INDICATOR:
- return ROLE_SYSTEM_ANIMATION;
-
- case ui::AX_ROLE_BUTTON:
+ case AX_ROLE_BUTTON:
return ROLE_SYSTEM_PUSHBUTTON;
- case ui::AX_ROLE_CANVAS:
+ case AX_ROLE_CANVAS:
return ROLE_SYSTEM_GRAPHIC;
- case ui::AX_ROLE_CAPTION:
+ case AX_ROLE_CAPTION:
return ROLE_SYSTEM_TEXT;
- case ui::AX_ROLE_CELL:
+ case AX_ROLE_CELL:
return ROLE_SYSTEM_CELL;
- case ui::AX_ROLE_CHECK_BOX:
+ case AX_ROLE_CHECK_BOX:
return ROLE_SYSTEM_CHECKBUTTON;
- case ui::AX_ROLE_COLOR_WELL:
+ case AX_ROLE_COLOR_WELL:
return ROLE_SYSTEM_TEXT;
- case ui::AX_ROLE_COLUMN:
+ case AX_ROLE_COLUMN:
return ROLE_SYSTEM_COLUMN;
- case ui::AX_ROLE_COLUMN_HEADER:
+ case AX_ROLE_COLUMN_HEADER:
return ROLE_SYSTEM_COLUMNHEADER;
- case ui::AX_ROLE_COMBO_BOX:
+ case AX_ROLE_COMBO_BOX:
return ROLE_SYSTEM_COMBOBOX;
- case ui::AX_ROLE_COMPLEMENTARY:
+ case AX_ROLE_COMPLEMENTARY:
return ROLE_SYSTEM_GROUPING;
- case ui::AX_ROLE_CONTENT_INFO:
+ case AX_ROLE_CONTENT_INFO:
return ROLE_SYSTEM_TEXT;
- case ui::AX_ROLE_DATE:
- case ui::AX_ROLE_DATE_TIME:
+ case AX_ROLE_DATE:
+ case AX_ROLE_DATE_TIME:
return ROLE_SYSTEM_DROPLIST;
- case ui::AX_ROLE_DESCRIPTION_LIST_DETAIL:
+ case AX_ROLE_DESCRIPTION_LIST_DETAIL:
return ROLE_SYSTEM_TEXT;
- case ui::AX_ROLE_DESCRIPTION_LIST:
+ case AX_ROLE_DESCRIPTION_LIST:
return ROLE_SYSTEM_LIST;
- case ui::AX_ROLE_DESCRIPTION_LIST_TERM:
+ case AX_ROLE_DESCRIPTION_LIST_TERM:
return ROLE_SYSTEM_LISTITEM;
- case ui::AX_ROLE_DETAILS:
+ case AX_ROLE_DETAILS:
return ROLE_SYSTEM_GROUPING;
- case ui::AX_ROLE_DIALOG:
+ case AX_ROLE_DIALOG:
return ROLE_SYSTEM_DIALOG;
- case ui::AX_ROLE_DISCLOSURE_TRIANGLE:
+ case AX_ROLE_DISCLOSURE_TRIANGLE:
return ROLE_SYSTEM_PUSHBUTTON;
- case ui::AX_ROLE_DOCUMENT:
- case ui::AX_ROLE_ROOT_WEB_AREA:
- case ui::AX_ROLE_WEB_AREA:
+ case AX_ROLE_DOCUMENT:
+ case AX_ROLE_ROOT_WEB_AREA:
+ case AX_ROLE_WEB_AREA:
return ROLE_SYSTEM_DOCUMENT;
- case ui::AX_ROLE_EMBEDDED_OBJECT:
+ case AX_ROLE_EMBEDDED_OBJECT:
if (delegate_->GetChildCount()) {
return ROLE_SYSTEM_GROUPING;
} else {
return ROLE_SYSTEM_CLIENT;
}
- case ui::AX_ROLE_FIGURE:
+ case AX_ROLE_FIGURE:
return ROLE_SYSTEM_GROUPING;
- case ui::AX_ROLE_FEED:
+ case AX_ROLE_FEED:
return ROLE_SYSTEM_GROUPING;
- case ui::AX_ROLE_GENERIC_CONTAINER:
+ case AX_ROLE_GENERIC_CONTAINER:
return ROLE_SYSTEM_GROUPING;
- case ui::AX_ROLE_GRID:
+ case AX_ROLE_GRID:
return ROLE_SYSTEM_TABLE;
- case ui::AX_ROLE_GROUP:
+ case AX_ROLE_GROUP:
return ROLE_SYSTEM_GROUPING;
- case ui::AX_ROLE_HEADING:
+ case AX_ROLE_HEADING:
return ROLE_SYSTEM_GROUPING;
- case ui::AX_ROLE_IFRAME:
+ case AX_ROLE_IFRAME:
return ROLE_SYSTEM_DOCUMENT;
- case ui::AX_ROLE_IFRAME_PRESENTATIONAL:
+ case AX_ROLE_IFRAME_PRESENTATIONAL:
return ROLE_SYSTEM_GROUPING;
- case ui::AX_ROLE_IMAGE:
+ case AX_ROLE_IMAGE:
return ROLE_SYSTEM_GRAPHIC;
- case ui::AX_ROLE_IMAGE_MAP_LINK:
- return ROLE_SYSTEM_LINK;
-
- case ui::AX_ROLE_INPUT_TIME:
+ case AX_ROLE_INPUT_TIME:
return ROLE_SYSTEM_GROUPING;
- case ui::AX_ROLE_LABEL_TEXT:
- case ui::AX_ROLE_LEGEND:
+ case AX_ROLE_LABEL_TEXT:
+ case AX_ROLE_LEGEND:
return ROLE_SYSTEM_TEXT;
- case ui::AX_ROLE_LINK:
+ case AX_ROLE_LINK:
return ROLE_SYSTEM_LINK;
- case ui::AX_ROLE_LIST:
+ case AX_ROLE_LIST:
return ROLE_SYSTEM_LIST;
- case ui::AX_ROLE_LIST_BOX:
+ case AX_ROLE_LIST_BOX:
return ROLE_SYSTEM_LIST;
- case ui::AX_ROLE_LIST_BOX_OPTION:
+ case AX_ROLE_LIST_BOX_OPTION:
return ROLE_SYSTEM_LISTITEM;
- case ui::AX_ROLE_LIST_ITEM:
+ case AX_ROLE_LIST_ITEM:
return ROLE_SYSTEM_LISTITEM;
- case ui::AX_ROLE_MAIN:
+ case AX_ROLE_MAIN:
return ROLE_SYSTEM_GROUPING;
- case ui::AX_ROLE_MARK:
+ case AX_ROLE_MARK:
return ROLE_SYSTEM_TEXT;
- case ui::AX_ROLE_MARQUEE:
+ case AX_ROLE_MARQUEE:
return ROLE_SYSTEM_ANIMATION;
- case ui::AX_ROLE_MATH:
+ case AX_ROLE_MATH:
return ROLE_SYSTEM_EQUATION;
- case ui::AX_ROLE_MENU:
- case ui::AX_ROLE_MENU_BUTTON:
+ case AX_ROLE_MENU:
+ case AX_ROLE_MENU_BUTTON:
return ROLE_SYSTEM_MENUPOPUP;
- case ui::AX_ROLE_MENU_BAR:
+ case AX_ROLE_MENU_BAR:
return ROLE_SYSTEM_MENUBAR;
- case ui::AX_ROLE_MENU_ITEM:
+ case AX_ROLE_MENU_ITEM:
return ROLE_SYSTEM_MENUITEM;
- case ui::AX_ROLE_MENU_ITEM_CHECK_BOX:
+ case AX_ROLE_MENU_ITEM_CHECK_BOX:
return ROLE_SYSTEM_MENUITEM;
- case ui::AX_ROLE_MENU_ITEM_RADIO:
+ case AX_ROLE_MENU_ITEM_RADIO:
return ROLE_SYSTEM_MENUITEM;
case ui::AX_ROLE_MENU_LIST_POPUP:
+ if (IsAncestorComboBox())
+ return ROLE_SYSTEM_LIST;
return ROLE_SYSTEM_MENUPOPUP;
case ui::AX_ROLE_MENU_LIST_OPTION:
+ if (IsAncestorComboBox())
+ return ROLE_SYSTEM_LISTITEM;
return ROLE_SYSTEM_MENUITEM;
- case ui::AX_ROLE_METER:
+ case AX_ROLE_METER:
return ROLE_SYSTEM_PROGRESSBAR;
- case ui::AX_ROLE_NAVIGATION:
+ case AX_ROLE_NAVIGATION:
return ROLE_SYSTEM_GROUPING;
- case ui::AX_ROLE_NOTE:
+ case AX_ROLE_NOTE:
return ROLE_SYSTEM_GROUPING;
- case ui::AX_ROLE_OUTLINE:
- return ROLE_SYSTEM_OUTLINE;
-
- case ui::AX_ROLE_POP_UP_BUTTON: {
- std::string html_tag = GetData().GetStringAttribute(ui::AX_ATTR_HTML_TAG);
+ case AX_ROLE_POP_UP_BUTTON: {
+ std::string html_tag = GetData().GetStringAttribute(AX_ATTR_HTML_TAG);
if (html_tag == "select")
return ROLE_SYSTEM_COMBOBOX;
return ROLE_SYSTEM_BUTTONMENU;
}
- case ui::AX_ROLE_PRE:
+ case AX_ROLE_PRE:
return ROLE_SYSTEM_TEXT;
- case ui::AX_ROLE_PROGRESS_INDICATOR:
+ case AX_ROLE_PROGRESS_INDICATOR:
return ROLE_SYSTEM_PROGRESSBAR;
- case ui::AX_ROLE_RADIO_BUTTON:
+ case AX_ROLE_RADIO_BUTTON:
return ROLE_SYSTEM_RADIOBUTTON;
- case ui::AX_ROLE_RADIO_GROUP:
+ case AX_ROLE_RADIO_GROUP:
return ROLE_SYSTEM_GROUPING;
- case ui::AX_ROLE_REGION: {
- std::string html_tag = GetData().GetStringAttribute(ui::AX_ATTR_HTML_TAG);
+ case AX_ROLE_REGION: {
+ std::string html_tag = GetData().GetStringAttribute(AX_ATTR_HTML_TAG);
if (html_tag == "section")
return ROLE_SYSTEM_GROUPING;
return ROLE_SYSTEM_PANE;
}
- case ui::AX_ROLE_ROW: {
+ case AX_ROLE_ROW: {
// Role changes depending on whether row is inside a treegrid
// https://www.w3.org/TR/core-aam-1.1/#role-map-row
return IsInTreeGrid() ? ROLE_SYSTEM_OUTLINEITEM : ROLE_SYSTEM_ROW;
}
- case ui::AX_ROLE_ROW_HEADER:
+ case AX_ROLE_ROW_HEADER:
return ROLE_SYSTEM_ROWHEADER;
- case ui::AX_ROLE_RUBY:
+ case AX_ROLE_RUBY:
return ROLE_SYSTEM_TEXT;
- case ui::AX_ROLE_RULER:
- return ROLE_SYSTEM_CLIENT;
-
- case ui::AX_ROLE_SCROLL_AREA:
- return ROLE_SYSTEM_CLIENT;
-
- case ui::AX_ROLE_SCROLL_BAR:
+ case AX_ROLE_SCROLL_BAR:
return ROLE_SYSTEM_SCROLLBAR;
- case ui::AX_ROLE_SEARCH:
+ case AX_ROLE_SEARCH:
return ROLE_SYSTEM_GROUPING;
- case ui::AX_ROLE_SLIDER:
+ case AX_ROLE_SLIDER:
return ROLE_SYSTEM_SLIDER;
- case ui::AX_ROLE_SPIN_BUTTON:
+ case AX_ROLE_SPIN_BUTTON:
return ROLE_SYSTEM_SPINBUTTON;
- case ui::AX_ROLE_SPIN_BUTTON_PART:
+ case AX_ROLE_SPIN_BUTTON_PART:
return ROLE_SYSTEM_PUSHBUTTON;
- case ui::AX_ROLE_ANNOTATION:
- case ui::AX_ROLE_LIST_MARKER:
- case ui::AX_ROLE_STATIC_TEXT:
+ case AX_ROLE_ANNOTATION:
+ case AX_ROLE_LIST_MARKER:
+ case AX_ROLE_STATIC_TEXT:
return ROLE_SYSTEM_STATICTEXT;
- case ui::AX_ROLE_STATUS:
+ case AX_ROLE_STATUS:
return ROLE_SYSTEM_STATUSBAR;
- case ui::AX_ROLE_SPLITTER:
+ case AX_ROLE_SPLITTER:
return ROLE_SYSTEM_SEPARATOR;
- case ui::AX_ROLE_SVG_ROOT:
+ case AX_ROLE_SVG_ROOT:
return ROLE_SYSTEM_GRAPHIC;
- case ui::AX_ROLE_TAB:
+ case AX_ROLE_TAB:
return ROLE_SYSTEM_PAGETAB;
- case ui::AX_ROLE_TABLE:
+ case AX_ROLE_TABLE:
return ROLE_SYSTEM_TABLE;
- case ui::AX_ROLE_TABLE_HEADER_CONTAINER:
+ case AX_ROLE_TABLE_HEADER_CONTAINER:
return ROLE_SYSTEM_GROUPING;
- case ui::AX_ROLE_TAB_LIST:
+ case AX_ROLE_TAB_LIST:
return ROLE_SYSTEM_PAGETABLIST;
- case ui::AX_ROLE_TAB_PANEL:
+ case AX_ROLE_TAB_PANEL:
return ROLE_SYSTEM_PROPERTYPAGE;
- case ui::AX_ROLE_TERM:
+ case AX_ROLE_TERM:
return ROLE_SYSTEM_LISTITEM;
- case ui::AX_ROLE_TOGGLE_BUTTON:
+ case AX_ROLE_TOGGLE_BUTTON:
return ROLE_SYSTEM_PUSHBUTTON;
- case ui::AX_ROLE_TEXT_FIELD:
- case ui::AX_ROLE_SEARCH_BOX:
+ case AX_ROLE_TEXT_FIELD:
+ case AX_ROLE_SEARCH_BOX:
return ROLE_SYSTEM_TEXT;
- case ui::AX_ROLE_ABBR:
- case ui::AX_ROLE_TIME:
+ case AX_ROLE_ABBR:
+ case AX_ROLE_TIME:
return ROLE_SYSTEM_TEXT;
- case ui::AX_ROLE_TIMER:
+ case AX_ROLE_TIMER:
return ROLE_SYSTEM_CLOCK;
- case ui::AX_ROLE_TOOLBAR:
+ case AX_ROLE_TOOLBAR:
return ROLE_SYSTEM_TOOLBAR;
- case ui::AX_ROLE_TOOLTIP:
+ case AX_ROLE_TOOLTIP:
return ROLE_SYSTEM_TOOLTIP;
- case ui::AX_ROLE_TREE:
+ case AX_ROLE_TREE:
return ROLE_SYSTEM_OUTLINE;
- case ui::AX_ROLE_TREE_GRID:
+ case AX_ROLE_TREE_GRID:
return ROLE_SYSTEM_OUTLINE;
- case ui::AX_ROLE_TREE_ITEM:
+ case AX_ROLE_TREE_ITEM:
return ROLE_SYSTEM_OUTLINEITEM;
- case ui::AX_ROLE_LINE_BREAK:
+ case AX_ROLE_LINE_BREAK:
return ROLE_SYSTEM_WHITESPACE;
- case ui::AX_ROLE_VIDEO:
+ case AX_ROLE_VIDEO:
return ROLE_SYSTEM_GROUPING;
- case ui::AX_ROLE_WINDOW:
+ case AX_ROLE_WINDOW:
return ROLE_SYSTEM_WINDOW;
// TODO(dmazzoni): figure out the proper MSAA role for roles listed below.
@@ -2547,10 +2822,8 @@ int AXPlatformNodeWin::MSAARole() {
case AX_ROLE_PANE:
case AX_ROLE_PARAGRAPH:
case AX_ROLE_PRESENTATIONAL:
- case AX_ROLE_SEAMLESS_WEB_AREA:
case AX_ROLE_SLIDER_THUMB:
case AX_ROLE_SWITCH:
- case AX_ROLE_TAB_GROUP:
case AX_ROLE_TITLE_BAR:
case AX_ROLE_UNKNOWN:
case AX_ROLE_WEB_VIEW:
@@ -2562,40 +2835,40 @@ int AXPlatformNodeWin::MSAARole() {
}
std::string AXPlatformNodeWin::StringOverrideForMSAARole() {
- std::string html_tag = GetData().GetStringAttribute(ui::AX_ATTR_HTML_TAG);
+ std::string html_tag = GetData().GetStringAttribute(AX_ATTR_HTML_TAG);
switch (GetData().role) {
- case ui::AX_ROLE_BLOCKQUOTE:
- case ui::AX_ROLE_DEFINITION:
- case ui::AX_ROLE_IMAGE_MAP:
+ case AX_ROLE_BLOCKQUOTE:
+ case AX_ROLE_DEFINITION:
+ case AX_ROLE_IMAGE_MAP:
return html_tag;
- case ui::AX_ROLE_CANVAS:
- if (GetData().GetBoolAttribute(ui::AX_ATTR_CANVAS_HAS_FALLBACK)) {
+ case AX_ROLE_CANVAS:
+ if (GetData().GetBoolAttribute(AX_ATTR_CANVAS_HAS_FALLBACK)) {
return html_tag;
}
break;
- case ui::AX_ROLE_FORM:
+ case AX_ROLE_FORM:
// This could be a div with the role of form
// so we return just the string "form".
return "form";
- case ui::AX_ROLE_HEADING:
+ case AX_ROLE_HEADING:
if (!html_tag.empty())
return html_tag;
break;
- case ui::AX_ROLE_PARAGRAPH:
+ case AX_ROLE_PARAGRAPH:
return html_tag;
- case ui::AX_ROLE_GENERIC_CONTAINER:
+ case AX_ROLE_GENERIC_CONTAINER:
// TODO(dougt) why can't we always use div in this case?
if (html_tag.empty())
return "div";
return html_tag;
- case ui::AX_ROLE_SWITCH:
+ case AX_ROLE_SWITCH:
return "switch";
default:
@@ -2606,16 +2879,16 @@ std::string AXPlatformNodeWin::StringOverrideForMSAARole() {
}
bool AXPlatformNodeWin::IsWebAreaForPresentationalIframe() {
- if (GetData().role != ui::AX_ROLE_WEB_AREA &&
- GetData().role != ui::AX_ROLE_ROOT_WEB_AREA) {
+ if (GetData().role != AX_ROLE_WEB_AREA &&
+ GetData().role != AX_ROLE_ROOT_WEB_AREA) {
return false;
}
- auto* parent = FromNativeViewAccessible(GetParent());
+ AXPlatformNodeBase* parent = FromNativeViewAccessible(GetParent());
if (!parent)
return false;
- return parent->GetData().role == ui::AX_ROLE_IFRAME_PRESENTATIONAL;
+ return parent->GetData().role == AX_ROLE_IFRAME_PRESENTATIONAL;
}
int32_t AXPlatformNodeWin::ComputeIA2State() {
@@ -2623,57 +2896,54 @@ int32_t AXPlatformNodeWin::ComputeIA2State() {
int32_t ia2_state = IA2_STATE_OPAQUE;
- const auto checked_state = static_cast<ui::AXCheckedState>(
- GetIntAttribute(ui::AX_ATTR_CHECKED_STATE));
+ const auto checked_state =
+ static_cast<AXCheckedState>(GetIntAttribute(AX_ATTR_CHECKED_STATE));
if (checked_state) {
ia2_state |= IA2_STATE_CHECKABLE;
}
- if (HasIntAttribute(ui::AX_ATTR_INVALID_STATE) &&
- GetIntAttribute(ui::AX_ATTR_INVALID_STATE) != ui::AX_INVALID_STATE_FALSE)
+ if (HasIntAttribute(AX_ATTR_INVALID_STATE) &&
+ GetIntAttribute(AX_ATTR_INVALID_STATE) != AX_INVALID_STATE_FALSE)
ia2_state |= IA2_STATE_INVALID_ENTRY;
- if (data.HasState(ui::AX_STATE_REQUIRED))
+ if (data.HasState(AX_STATE_REQUIRED))
ia2_state |= IA2_STATE_REQUIRED;
- if (data.HasState(ui::AX_STATE_VERTICAL))
+ if (data.HasState(AX_STATE_VERTICAL))
ia2_state |= IA2_STATE_VERTICAL;
- if (data.HasState(ui::AX_STATE_HORIZONTAL))
+ if (data.HasState(AX_STATE_HORIZONTAL))
ia2_state |= IA2_STATE_HORIZONTAL;
- const bool is_editable = data.HasState(ui::AX_STATE_EDITABLE);
+ const bool is_editable = data.HasState(AX_STATE_EDITABLE);
if (is_editable)
ia2_state |= IA2_STATE_EDITABLE;
- if (IsRichTextControl() || ui::IsEditField(data.role)) {
+ if (IsRichTextControl() || IsEditField(data.role)) {
// Support multi/single line states if root editable or appropriate role.
// We support the edit box roles even if the area is not actually editable,
// because it is technically feasible for JS to implement the edit box
// by controlling selection.
- if (data.HasState(ui::AX_STATE_MULTILINE)) {
+ if (data.HasState(AX_STATE_MULTILINE)) {
ia2_state |= IA2_STATE_MULTI_LINE;
} else {
ia2_state |= IA2_STATE_SINGLE_LINE;
}
}
- if (!GetStringAttribute(ui::AX_ATTR_AUTO_COMPLETE).empty())
+ if (!GetStringAttribute(AX_ATTR_AUTO_COMPLETE).empty())
ia2_state |= IA2_STATE_SUPPORTS_AUTOCOMPLETION;
- if (GetBoolAttribute(ui::AX_ATTR_MODAL))
+ if (GetBoolAttribute(AX_ATTR_MODAL))
ia2_state |= IA2_STATE_MODAL;
switch (data.role) {
- case ui::AX_ROLE_MENU_LIST_POPUP:
+ case AX_ROLE_MENU_LIST_POPUP:
ia2_state &= ~(IA2_STATE_EDITABLE);
break;
- case ui::AX_ROLE_MENU_LIST_OPTION:
+ case AX_ROLE_MENU_LIST_OPTION:
ia2_state &= ~(IA2_STATE_EDITABLE);
break;
- case ui::AX_ROLE_SCROLL_AREA:
- ia2_state &= ~(IA2_STATE_EDITABLE);
- break;
- case ui::AX_ROLE_TEXT_FIELD:
- case ui::AX_ROLE_SEARCH_BOX:
- if (data.HasState(ui::AX_STATE_MULTILINE)) {
+ case AX_ROLE_TEXT_FIELD:
+ case AX_ROLE_SEARCH_BOX:
+ if (data.HasState(AX_STATE_MULTILINE)) {
ia2_state |= IA2_STATE_MULTI_LINE;
} else {
ia2_state |= IA2_STATE_SINGLE_LINE;
@@ -2699,123 +2969,117 @@ int32_t AXPlatformNodeWin::ComputeIA2Role() {
int32_t ia2_role = 0;
switch (GetData().role) {
- case ui::AX_ROLE_BANNER:
+ case AX_ROLE_BANNER:
ia2_role = IA2_ROLE_HEADER;
break;
- case ui::AX_ROLE_BLOCKQUOTE:
+ case AX_ROLE_BLOCKQUOTE:
ia2_role = IA2_ROLE_SECTION;
break;
- case ui::AX_ROLE_CANVAS:
- if (GetBoolAttribute(ui::AX_ATTR_CANVAS_HAS_FALLBACK)) {
+ case AX_ROLE_CANVAS:
+ if (GetBoolAttribute(AX_ATTR_CANVAS_HAS_FALLBACK)) {
ia2_role = IA2_ROLE_CANVAS;
}
break;
- case ui::AX_ROLE_CAPTION:
+ case AX_ROLE_CAPTION:
ia2_role = IA2_ROLE_CAPTION;
break;
- case ui::AX_ROLE_COLOR_WELL:
+ case AX_ROLE_COLOR_WELL:
ia2_role = IA2_ROLE_COLOR_CHOOSER;
break;
- case ui::AX_ROLE_COMPLEMENTARY:
+ case AX_ROLE_COMPLEMENTARY:
ia2_role = IA2_ROLE_NOTE;
break;
- case ui::AX_ROLE_CONTENT_INFO:
+ case AX_ROLE_CONTENT_INFO:
ia2_role = IA2_ROLE_PARAGRAPH;
break;
- case ui::AX_ROLE_DATE:
- case ui::AX_ROLE_DATE_TIME:
+ case AX_ROLE_DATE:
+ case AX_ROLE_DATE_TIME:
ia2_role = IA2_ROLE_DATE_EDITOR;
break;
- case ui::AX_ROLE_DEFINITION:
+ case AX_ROLE_DEFINITION:
ia2_role = IA2_ROLE_PARAGRAPH;
break;
- case ui::AX_ROLE_DESCRIPTION_LIST_DETAIL:
+ case AX_ROLE_DESCRIPTION_LIST_DETAIL:
ia2_role = IA2_ROLE_PARAGRAPH;
break;
- case ui::AX_ROLE_EMBEDDED_OBJECT:
+ case AX_ROLE_EMBEDDED_OBJECT:
if (!delegate_->GetChildCount()) {
ia2_role = IA2_ROLE_EMBEDDED_OBJECT;
}
break;
- case ui::AX_ROLE_FIGCAPTION:
+ case AX_ROLE_FIGCAPTION:
ia2_role = IA2_ROLE_CAPTION;
break;
- case ui::AX_ROLE_FORM:
+ case AX_ROLE_FORM:
ia2_role = IA2_ROLE_FORM;
break;
- case ui::AX_ROLE_FOOTER:
+ case AX_ROLE_FOOTER:
ia2_role = IA2_ROLE_FOOTER;
break;
- case ui::AX_ROLE_GENERIC_CONTAINER:
+ case AX_ROLE_GENERIC_CONTAINER:
ia2_role = IA2_ROLE_SECTION;
break;
- case ui::AX_ROLE_HEADING:
+ case AX_ROLE_HEADING:
ia2_role = IA2_ROLE_HEADING;
break;
- case ui::AX_ROLE_IFRAME:
+ case AX_ROLE_IFRAME:
ia2_role = IA2_ROLE_INTERNAL_FRAME;
break;
- case ui::AX_ROLE_IMAGE_MAP:
+ case AX_ROLE_IMAGE_MAP:
ia2_role = IA2_ROLE_IMAGE_MAP;
break;
- case ui::AX_ROLE_LABEL_TEXT:
- case ui::AX_ROLE_LEGEND:
+ case AX_ROLE_LABEL_TEXT:
+ case AX_ROLE_LEGEND:
ia2_role = IA2_ROLE_LABEL;
break;
- case ui::AX_ROLE_MAIN:
+ case AX_ROLE_MAIN:
ia2_role = IA2_ROLE_PARAGRAPH;
break;
- case ui::AX_ROLE_MARK:
+ case AX_ROLE_MARK:
ia2_role = IA2_ROLE_TEXT_FRAME;
break;
- case ui::AX_ROLE_MENU_ITEM_CHECK_BOX:
+ case AX_ROLE_MENU_ITEM_CHECK_BOX:
ia2_role = IA2_ROLE_CHECK_MENU_ITEM;
break;
- case ui::AX_ROLE_MENU_ITEM_RADIO:
+ case AX_ROLE_MENU_ITEM_RADIO:
ia2_role = IA2_ROLE_RADIO_MENU_ITEM;
break;
- case ui::AX_ROLE_NAVIGATION:
+ case AX_ROLE_NAVIGATION:
ia2_role = IA2_ROLE_SECTION;
break;
- case ui::AX_ROLE_NOTE:
+ case AX_ROLE_NOTE:
ia2_role = IA2_ROLE_NOTE;
break;
- case ui::AX_ROLE_PARAGRAPH:
+ case AX_ROLE_PARAGRAPH:
ia2_role = IA2_ROLE_PARAGRAPH;
break;
- case ui::AX_ROLE_PRE:
+ case AX_ROLE_PRE:
ia2_role = IA2_ROLE_PARAGRAPH;
break;
- case ui::AX_ROLE_REGION: {
- base::string16 html_tag = GetString16Attribute(ui::AX_ATTR_HTML_TAG);
+ case AX_ROLE_REGION: {
+ base::string16 html_tag = GetString16Attribute(AX_ATTR_HTML_TAG);
if (html_tag == L"section") {
ia2_role = IA2_ROLE_SECTION;
}
} break;
- case ui::AX_ROLE_RUBY:
+ case AX_ROLE_RUBY:
ia2_role = IA2_ROLE_TEXT_FRAME;
break;
- case ui::AX_ROLE_RULER:
- ia2_role = IA2_ROLE_RULER;
- break;
- case ui::AX_ROLE_SCROLL_AREA:
- ia2_role = IA2_ROLE_SCROLL_PANE;
- break;
- case ui::AX_ROLE_SEARCH:
+ case AX_ROLE_SEARCH:
ia2_role = IA2_ROLE_SECTION;
break;
- case ui::AX_ROLE_SWITCH:
+ case AX_ROLE_SWITCH:
ia2_role = IA2_ROLE_TOGGLE_BUTTON;
break;
- case ui::AX_ROLE_TABLE_HEADER_CONTAINER:
+ case AX_ROLE_TABLE_HEADER_CONTAINER:
ia2_role = IA2_ROLE_SECTION;
break;
- case ui::AX_ROLE_TOGGLE_BUTTON:
+ case AX_ROLE_TOGGLE_BUTTON:
ia2_role = IA2_ROLE_TOGGLE_BUTTON;
break;
- case ui::AX_ROLE_ABBR:
- case ui::AX_ROLE_TIME:
+ case AX_ROLE_ABBR:
+ case AX_ROLE_TIME:
ia2_role = IA2_ROLE_TEXT_FRAME;
break;
default:
@@ -2831,84 +3095,83 @@ std::vector<base::string16> AXPlatformNodeWin::ComputeIA2Attributes() {
// historical reasons. Aside from that virtually every ARIA attribute
// is exposed in a really straightforward way, i.e. "aria-foo" is exposed
// as "foo".
- StringAttributeToIA2(result, ui::AX_ATTR_DISPLAY, "display");
- StringAttributeToIA2(result, ui::AX_ATTR_HTML_TAG, "tag");
- StringAttributeToIA2(result, ui::AX_ATTR_ROLE, "xml-roles");
- StringAttributeToIA2(result, ui::AX_ATTR_PLACEHOLDER, "placeholder");
+ StringAttributeToIA2(result, AX_ATTR_DISPLAY, "display");
+ StringAttributeToIA2(result, AX_ATTR_HTML_TAG, "tag");
+ StringAttributeToIA2(result, AX_ATTR_ROLE, "xml-roles");
+ StringAttributeToIA2(result, AX_ATTR_PLACEHOLDER, "placeholder");
- StringAttributeToIA2(result, ui::AX_ATTR_AUTO_COMPLETE, "autocomplete");
- StringAttributeToIA2(result, ui::AX_ATTR_ROLE_DESCRIPTION, "roledescription");
- StringAttributeToIA2(result, ui::AX_ATTR_KEY_SHORTCUTS, "keyshortcuts");
+ StringAttributeToIA2(result, AX_ATTR_AUTO_COMPLETE, "autocomplete");
+ StringAttributeToIA2(result, AX_ATTR_ROLE_DESCRIPTION, "roledescription");
+ StringAttributeToIA2(result, AX_ATTR_KEY_SHORTCUTS, "keyshortcuts");
- IntAttributeToIA2(result, ui::AX_ATTR_HIERARCHICAL_LEVEL, "level");
- IntAttributeToIA2(result, ui::AX_ATTR_SET_SIZE, "setsize");
- IntAttributeToIA2(result, ui::AX_ATTR_POS_IN_SET, "posinset");
+ IntAttributeToIA2(result, AX_ATTR_HIERARCHICAL_LEVEL, "level");
+ IntAttributeToIA2(result, AX_ATTR_SET_SIZE, "setsize");
+ IntAttributeToIA2(result, AX_ATTR_POS_IN_SET, "posinset");
- if (HasIntAttribute(ui::AX_ATTR_CHECKED_STATE))
+ if (HasIntAttribute(AX_ATTR_CHECKED_STATE))
result.push_back(L"checkable:true");
// Expose live region attributes.
- StringAttributeToIA2(result, ui::AX_ATTR_LIVE_STATUS, "live");
- StringAttributeToIA2(result, ui::AX_ATTR_LIVE_RELEVANT, "relevant");
- BoolAttributeToIA2(result, ui::AX_ATTR_LIVE_ATOMIC, "atomic");
- BoolAttributeToIA2(result, ui::AX_ATTR_LIVE_BUSY, "busy");
+ StringAttributeToIA2(result, AX_ATTR_LIVE_STATUS, "live");
+ StringAttributeToIA2(result, AX_ATTR_LIVE_RELEVANT, "relevant");
+ BoolAttributeToIA2(result, AX_ATTR_LIVE_ATOMIC, "atomic");
+ // Busy is usually associated with live regions but can occur anywhere:
+ BoolAttributeToIA2(result, AX_ATTR_BUSY, "busy");
// Expose container live region attributes.
- StringAttributeToIA2(result, ui::AX_ATTR_CONTAINER_LIVE_STATUS,
- "container-live");
- StringAttributeToIA2(result, ui::AX_ATTR_CONTAINER_LIVE_RELEVANT,
+ StringAttributeToIA2(result, AX_ATTR_CONTAINER_LIVE_STATUS, "container-live");
+ StringAttributeToIA2(result, AX_ATTR_CONTAINER_LIVE_RELEVANT,
"container-relevant");
- BoolAttributeToIA2(result, ui::AX_ATTR_CONTAINER_LIVE_ATOMIC,
- "container-atomic");
- BoolAttributeToIA2(result, ui::AX_ATTR_CONTAINER_LIVE_BUSY, "container-busy");
+ BoolAttributeToIA2(result, AX_ATTR_CONTAINER_LIVE_ATOMIC, "container-atomic");
+ BoolAttributeToIA2(result, AX_ATTR_CONTAINER_LIVE_BUSY, "container-busy");
// Expose the non-standard explicit-name IA2 attribute.
int name_from;
- if (GetIntAttribute(ui::AX_ATTR_NAME_FROM, &name_from) &&
- name_from != ui::AX_NAME_FROM_CONTENTS) {
+ if (GetIntAttribute(AX_ATTR_NAME_FROM, &name_from) &&
+ name_from != AX_NAME_FROM_CONTENTS) {
result.push_back(L"explicit-name:true");
}
// Expose the aria-current attribute.
int32_t aria_current_state;
- if (GetIntAttribute(ui::AX_ATTR_ARIA_CURRENT_STATE, &aria_current_state)) {
- switch (static_cast<ui::AXAriaCurrentState>(aria_current_state)) {
- case ui::AX_ARIA_CURRENT_STATE_NONE:
+ if (GetIntAttribute(AX_ATTR_ARIA_CURRENT_STATE, &aria_current_state)) {
+ switch (static_cast<AXAriaCurrentState>(aria_current_state)) {
+ case AX_ARIA_CURRENT_STATE_NONE:
break;
- case ui::AX_ARIA_CURRENT_STATE_FALSE:
+ case AX_ARIA_CURRENT_STATE_FALSE:
result.push_back(L"current:false");
break;
- case ui::AX_ARIA_CURRENT_STATE_TRUE:
+ case AX_ARIA_CURRENT_STATE_TRUE:
result.push_back(L"current:true");
break;
- case ui::AX_ARIA_CURRENT_STATE_PAGE:
+ case AX_ARIA_CURRENT_STATE_PAGE:
result.push_back(L"current:page");
break;
- case ui::AX_ARIA_CURRENT_STATE_STEP:
+ case AX_ARIA_CURRENT_STATE_STEP:
result.push_back(L"current:step");
break;
- case ui::AX_ARIA_CURRENT_STATE_LOCATION:
+ case AX_ARIA_CURRENT_STATE_LOCATION:
result.push_back(L"current:location");
break;
- case ui::AX_ARIA_CURRENT_STATE_DATE:
+ case AX_ARIA_CURRENT_STATE_DATE:
result.push_back(L"current:date");
break;
- case ui::AX_ARIA_CURRENT_STATE_TIME:
+ case AX_ARIA_CURRENT_STATE_TIME:
result.push_back(L"current:time");
break;
}
}
// Expose table cell index.
- if (ui::IsCellOrTableHeaderRole(GetData().role)) {
+ if (IsCellOrTableHeaderRole(GetData().role)) {
AXPlatformNodeBase* table = FromNativeViewAccessible(GetParent());
- while (table && !ui::IsTableLikeRole(table->GetData().role))
+ while (table && !IsTableLikeRole(table->GetData().role))
table = FromNativeViewAccessible(table->GetParent());
if (table) {
const std::vector<int32_t>& unique_cell_ids =
- table->GetIntListAttribute(ui::AX_ATTR_UNIQUE_CELL_IDS);
+ table->GetIntListAttribute(AX_ATTR_UNIQUE_CELL_IDS);
for (size_t i = 0; i < unique_cell_ids.size(); ++i) {
if (unique_cell_ids[i] == GetData().id) {
result.push_back(base::string16(L"table-cell-index:") +
@@ -2919,43 +3182,43 @@ std::vector<base::string16> AXPlatformNodeWin::ComputeIA2Attributes() {
}
// Expose aria-colcount and aria-rowcount in a table, grid or treegrid.
- if (ui::IsTableLikeRole(GetData().role)) {
- IntAttributeToIA2(result, ui::AX_ATTR_ARIA_COLUMN_COUNT, "colcount");
- IntAttributeToIA2(result, ui::AX_ATTR_ARIA_ROW_COUNT, "rowcount");
+ if (IsTableLikeRole(GetData().role)) {
+ IntAttributeToIA2(result, AX_ATTR_ARIA_COLUMN_COUNT, "colcount");
+ IntAttributeToIA2(result, AX_ATTR_ARIA_ROW_COUNT, "rowcount");
}
// Expose aria-colindex and aria-rowindex in a cell or row.
- if (ui::IsCellOrTableHeaderRole(GetData().role) ||
- GetData().role == ui::AX_ROLE_ROW) {
- if (GetData().role != ui::AX_ROLE_ROW)
- IntAttributeToIA2(result, ui::AX_ATTR_ARIA_CELL_COLUMN_INDEX, "colindex");
- IntAttributeToIA2(result, ui::AX_ATTR_ARIA_CELL_ROW_INDEX, "rowindex");
+ if (IsCellOrTableHeaderRole(GetData().role) ||
+ GetData().role == AX_ROLE_ROW) {
+ if (GetData().role != AX_ROLE_ROW)
+ IntAttributeToIA2(result, AX_ATTR_ARIA_CELL_COLUMN_INDEX, "colindex");
+ IntAttributeToIA2(result, AX_ATTR_ARIA_CELL_ROW_INDEX, "rowindex");
}
// Expose row or column header sort direction.
int32_t sort_direction;
if ((MSAARole() == ROLE_SYSTEM_COLUMNHEADER ||
MSAARole() == ROLE_SYSTEM_ROWHEADER) &&
- GetIntAttribute(ui::AX_ATTR_SORT_DIRECTION, &sort_direction)) {
- switch (static_cast<ui::AXSortDirection>(sort_direction)) {
- case ui::AX_SORT_DIRECTION_NONE:
+ GetIntAttribute(AX_ATTR_SORT_DIRECTION, &sort_direction)) {
+ switch (static_cast<AXSortDirection>(sort_direction)) {
+ case AX_SORT_DIRECTION_NONE:
break;
- case ui::AX_SORT_DIRECTION_UNSORTED:
+ case AX_SORT_DIRECTION_UNSORTED:
result.push_back(L"sort:none");
break;
- case ui::AX_SORT_DIRECTION_ASCENDING:
+ case AX_SORT_DIRECTION_ASCENDING:
result.push_back(L"sort:ascending");
break;
- case ui::AX_SORT_DIRECTION_DESCENDING:
+ case AX_SORT_DIRECTION_DESCENDING:
result.push_back(L"sort:descending");
break;
- case ui::AX_SORT_DIRECTION_OTHER:
+ case AX_SORT_DIRECTION_OTHER:
result.push_back(L"sort:other");
break;
}
}
- if (ui::IsCellOrTableHeaderRole(GetData().role)) {
+ if (IsCellOrTableHeaderRole(GetData().role)) {
// Expose colspan attribute.
base::string16 colspan;
if (GetData().GetHtmlAttribute("aria-colspan", &colspan)) {
@@ -3000,7 +3263,7 @@ std::vector<base::string16> AXPlatformNodeWin::ComputeIA2Attributes() {
// Expose datetime attribute.
base::string16 datetime;
- if (GetData().role == ui::AX_ROLE_TIME &&
+ if (GetData().role == AX_ROLE_TIME &&
GetData().GetHtmlAttribute("datetime", &datetime)) {
SanitizeStringAttributeForIA2(datetime, &datetime);
result.push_back(L"datetime:" + datetime);
@@ -3015,15 +3278,24 @@ std::vector<base::string16> AXPlatformNodeWin::ComputeIA2Attributes() {
// Expose src attribute.
base::string16 src;
- if (GetData().role == ui::AX_ROLE_IMAGE &&
+ if (GetData().role == AX_ROLE_IMAGE &&
GetData().GetHtmlAttribute("src", &src)) {
SanitizeStringAttributeForIA2(src, &src);
result.push_back(L"src:" + src);
}
+ // Text fields need to report the attribute "text-model:a1" to instruct
+ // screen readers to use IAccessible2 APIs to handle text editing in this
+ // object (as opposed to treating it like a native Windows text box).
+ // The text-model:a1 attribute is documented here:
+ // http://www.linuxfoundation.org/collaborate/workgroups/accessibility/ia2/ia2_implementation_guide
+ if (GetData().role == AX_ROLE_TEXT_FIELD) {
+ result.push_back(L"text-model:a1;");
+ }
+
// Expose input-text type attribute.
base::string16 type;
- base::string16 html_tag = GetString16Attribute(ui::AX_ATTR_HTML_TAG);
+ base::string16 html_tag = GetString16Attribute(AX_ATTR_HTML_TAG);
if (IsSimpleTextControl() && html_tag == L"input" &&
GetData().GetHtmlAttribute("type", &type)) {
SanitizeStringAttributeForIA2(type, &type);
@@ -3036,30 +3308,26 @@ std::vector<base::string16> AXPlatformNodeWin::ComputeIA2Attributes() {
bool AXPlatformNodeWin::ShouldNodeHaveReadonlyStateByDefault(
const AXNodeData& data) const {
switch (data.role) {
- case ui::AX_ROLE_ARTICLE:
- case ui::AX_ROLE_BUSY_INDICATOR:
- case ui::AX_ROLE_DEFINITION:
- case ui::AX_ROLE_DESCRIPTION_LIST:
- case ui::AX_ROLE_DESCRIPTION_LIST_TERM:
- case ui::AX_ROLE_DOCUMENT:
- case ui::AX_ROLE_IFRAME:
- case ui::AX_ROLE_IMAGE:
- case ui::AX_ROLE_IMAGE_MAP:
- case ui::AX_ROLE_IMAGE_MAP_LINK:
- case ui::AX_ROLE_LIST:
- case ui::AX_ROLE_LIST_ITEM:
- case ui::AX_ROLE_PROGRESS_INDICATOR:
- case ui::AX_ROLE_ROOT_WEB_AREA:
- case ui::AX_ROLE_RULER:
- case ui::AX_ROLE_SCROLL_AREA:
- case ui::AX_ROLE_TERM:
- case ui::AX_ROLE_TIMER:
- case ui::AX_ROLE_TOOLBAR:
- case ui::AX_ROLE_TOOLTIP:
- case ui::AX_ROLE_WEB_AREA:
+ case AX_ROLE_ARTICLE:
+ case AX_ROLE_DEFINITION:
+ case AX_ROLE_DESCRIPTION_LIST:
+ case AX_ROLE_DESCRIPTION_LIST_TERM:
+ case AX_ROLE_DOCUMENT:
+ case AX_ROLE_IFRAME:
+ case AX_ROLE_IMAGE:
+ case AX_ROLE_IMAGE_MAP:
+ case AX_ROLE_LIST:
+ case AX_ROLE_LIST_ITEM:
+ case AX_ROLE_PROGRESS_INDICATOR:
+ case AX_ROLE_ROOT_WEB_AREA:
+ case AX_ROLE_TERM:
+ case AX_ROLE_TIMER:
+ case AX_ROLE_TOOLBAR:
+ case AX_ROLE_TOOLTIP:
+ case AX_ROLE_WEB_AREA:
return true;
- case ui::AX_ROLE_GRID:
+ case AX_ROLE_GRID:
// TODO(aleventhal) this changed between ARIA 1.0 and 1.1,
// need to determine whether grids/treegrids should really be readonly
// or editable by default
@@ -3075,24 +3343,24 @@ bool AXPlatformNodeWin::ShouldNodeHaveReadonlyStateByDefault(
bool AXPlatformNodeWin::ShouldNodeHaveFocusableState(
const AXNodeData& data) const {
switch (data.role) {
- case ui::AX_ROLE_DOCUMENT:
- case ui::AX_ROLE_ROOT_WEB_AREA:
- case ui::AX_ROLE_WEB_AREA:
+ case AX_ROLE_DOCUMENT:
+ case AX_ROLE_ROOT_WEB_AREA:
+ case AX_ROLE_WEB_AREA:
return true;
- case ui::AX_ROLE_IFRAME:
+ case AX_ROLE_IFRAME:
return false;
- case ui::AX_ROLE_LIST_BOX_OPTION:
- case ui::AX_ROLE_MENU_LIST_OPTION:
- if (data.HasState(ui::AX_STATE_SELECTABLE))
+ case AX_ROLE_LIST_BOX_OPTION:
+ case AX_ROLE_MENU_LIST_OPTION:
+ if (data.HasState(AX_STATE_SELECTABLE))
return true;
default:
break;
}
- return data.HasState(ui::AX_STATE_FOCUSABLE);
+ return data.HasState(AX_STATE_FOCUSABLE);
}
int AXPlatformNodeWin::MSAAState() {
@@ -3102,29 +3370,29 @@ int AXPlatformNodeWin::MSAAState() {
// Map the AXState to MSAA state. Note that some of the states are not
// currently handled.
- if (data.HasState(ui::AX_STATE_BUSY))
+ if (data.GetBoolAttribute(AX_ATTR_BUSY))
msaa_state |= STATE_SYSTEM_BUSY;
- if (data.HasState(ui::AX_STATE_COLLAPSED))
+ if (data.HasState(AX_STATE_COLLAPSED))
msaa_state |= STATE_SYSTEM_COLLAPSED;
- if (data.HasState(ui::AX_STATE_DEFAULT))
+ if (data.HasState(AX_STATE_DEFAULT))
msaa_state |= STATE_SYSTEM_DEFAULT;
// TODO(dougt) unhandled ux::AX_STATE_EDITABLE
- if (data.HasState(ui::AX_STATE_EXPANDED))
+ if (data.HasState(AX_STATE_EXPANDED))
msaa_state |= STATE_SYSTEM_EXPANDED;
if (ShouldNodeHaveFocusableState(data))
msaa_state |= STATE_SYSTEM_FOCUSABLE;
- if (data.HasState(ui::AX_STATE_HASPOPUP))
+ if (data.HasState(AX_STATE_HASPOPUP))
msaa_state |= STATE_SYSTEM_HASPOPUP;
// TODO(dougt) unhandled ux::AX_STATE_HORIZONTAL
- if (data.HasState(ui::AX_STATE_HOVERED)) {
+ if (data.HasState(AX_STATE_HOVERED)) {
// Expose whether or not the mouse is over an element, but suppress
// this for tests because it can make the test results flaky depending
// on the position of the mouse.
@@ -3133,52 +3401,50 @@ int AXPlatformNodeWin::MSAAState() {
}
// TODO(dougt) Why do we set any state on AX_ROLE_IGNORED?
- if (data.HasState(ui::AX_STATE_INVISIBLE) ||
- GetData().role == ui::AX_ROLE_IGNORED) {
+ if (data.HasState(AX_STATE_INVISIBLE) || GetData().role == AX_ROLE_IGNORED) {
msaa_state |= STATE_SYSTEM_INVISIBLE;
}
- if (data.HasState(ui::AX_STATE_LINKED))
+ if (data.HasState(AX_STATE_LINKED))
msaa_state |= STATE_SYSTEM_LINKED;
// TODO(dougt) unhandled ux::AX_STATE_MULTILINE
- if (data.HasState(ui::AX_STATE_MULTISELECTABLE)) {
+ if (data.HasState(AX_STATE_MULTISELECTABLE)) {
msaa_state |= STATE_SYSTEM_EXTSELECTABLE;
msaa_state |= STATE_SYSTEM_MULTISELECTABLE;
}
- if (data.HasState(ui::AX_STATE_OFFSCREEN))
+ if (data.HasState(AX_STATE_OFFSCREEN))
msaa_state |= STATE_SYSTEM_OFFSCREEN;
- if (data.HasState(ui::AX_STATE_PROTECTED))
+ if (data.HasState(AX_STATE_PROTECTED))
msaa_state |= STATE_SYSTEM_PROTECTED;
// TODO(dougt) unhandled ux::AX_STATE_REQUIRED
// TODO(dougt) unhandled ux::AX_STATE_RICHLY_EDITABLE
- if (data.HasState(ui::AX_STATE_SELECTABLE))
+ if (data.HasState(AX_STATE_SELECTABLE))
msaa_state |= STATE_SYSTEM_SELECTABLE;
- if (data.HasState(ui::AX_STATE_SELECTED))
+ if (data.HasState(AX_STATE_SELECTED))
msaa_state |= STATE_SYSTEM_SELECTED;
// TODO(dougt) unhandled VERTICAL
- if (data.HasState(ui::AX_STATE_VISITED))
+ if (data.HasState(AX_STATE_VISITED))
msaa_state |= STATE_SYSTEM_TRAVERSED;
//
// Checked state
//
- const auto checked_state = static_cast<ui::AXCheckedState>(
- GetIntAttribute(ui::AX_ATTR_CHECKED_STATE));
+ const auto checked_state =
+ static_cast<AXCheckedState>(GetIntAttribute(AX_ATTR_CHECKED_STATE));
switch (checked_state) {
- case ui::AX_CHECKED_STATE_TRUE:
- msaa_state |= data.role == ui::AX_ROLE_TOGGLE_BUTTON
- ? STATE_SYSTEM_PRESSED
- : STATE_SYSTEM_CHECKED;
+ case AX_CHECKED_STATE_TRUE:
+ msaa_state |= data.role == AX_ROLE_TOGGLE_BUTTON ? STATE_SYSTEM_PRESSED
+ : STATE_SYSTEM_CHECKED;
break;
- case ui::AX_CHECKED_STATE_MIXED:
+ case AX_CHECKED_STATE_MIXED:
msaa_state |= STATE_SYSTEM_MIXED;
break;
default:
@@ -3186,12 +3452,12 @@ int AXPlatformNodeWin::MSAAState() {
}
const auto restriction =
- static_cast<ui::AXRestriction>(GetIntAttribute(ui::AX_ATTR_RESTRICTION));
+ static_cast<AXRestriction>(GetIntAttribute(AX_ATTR_RESTRICTION));
switch (restriction) {
- case ui::AX_RESTRICTION_DISABLED:
+ case AX_RESTRICTION_DISABLED:
msaa_state |= STATE_SYSTEM_UNAVAILABLE;
break;
- case ui::AX_RESTRICTION_READ_ONLY:
+ case AX_RESTRICTION_READ_ONLY:
msaa_state |= STATE_SYSTEM_READONLY;
break;
default:
@@ -3218,54 +3484,50 @@ int AXPlatformNodeWin::MSAAState() {
// TODO(dmazzoni): this should probably check if focus is actually inside
// the menu bar, but we don't currently track focus inside menu pop-ups,
// and Chrome only has one menu visible at a time so this works for now.
- if (data.role == ui::AX_ROLE_MENU_BAR &&
- !(data.HasState(ui::AX_STATE_INVISIBLE))) {
+ if (data.role == AX_ROLE_MENU_BAR && !(data.HasState(AX_STATE_INVISIBLE))) {
msaa_state |= STATE_SYSTEM_FOCUSED;
}
// Handle STATE_SYSTEM_LINKED
- if (GetData().role == ui::AX_ROLE_IMAGE_MAP_LINK ||
- GetData().role == ui::AX_ROLE_LINK) {
+ if (GetData().role == AX_ROLE_LINK)
msaa_state |= STATE_SYSTEM_LINKED;
- }
return msaa_state;
}
-int AXPlatformNodeWin::MSAAEvent(ui::AXEvent event) {
+int AXPlatformNodeWin::MSAAEvent(AXEvent event) {
switch (event) {
- case ui::AX_EVENT_ALERT:
+ case AX_EVENT_ALERT:
return EVENT_SYSTEM_ALERT;
- case ui::AX_EVENT_FOCUS:
+ case AX_EVENT_FOCUS:
return EVENT_OBJECT_FOCUS;
- case ui::AX_EVENT_MENU_START:
+ case AX_EVENT_MENU_START:
return EVENT_SYSTEM_MENUSTART;
- case ui::AX_EVENT_MENU_END:
+ case AX_EVENT_MENU_END:
return EVENT_SYSTEM_MENUEND;
- case ui::AX_EVENT_MENU_POPUP_START:
+ case AX_EVENT_MENU_POPUP_START:
return EVENT_SYSTEM_MENUPOPUPSTART;
- case ui::AX_EVENT_MENU_POPUP_END:
+ case AX_EVENT_MENU_POPUP_END:
return EVENT_SYSTEM_MENUPOPUPEND;
- case ui::AX_EVENT_SELECTION:
+ case AX_EVENT_SELECTION:
return EVENT_OBJECT_SELECTION;
- case ui::AX_EVENT_SELECTION_ADD:
+ case AX_EVENT_SELECTION_ADD:
return EVENT_OBJECT_SELECTIONADD;
- case ui::AX_EVENT_SELECTION_REMOVE:
+ case AX_EVENT_SELECTION_REMOVE:
return EVENT_OBJECT_SELECTIONREMOVE;
- case ui::AX_EVENT_TEXT_CHANGED:
+ case AX_EVENT_TEXT_CHANGED:
return EVENT_OBJECT_NAMECHANGE;
- case ui::AX_EVENT_TEXT_SELECTION_CHANGED:
+ case AX_EVENT_TEXT_SELECTION_CHANGED:
return IA2_EVENT_TEXT_CARET_MOVED;
- case ui::AX_EVENT_VALUE_CHANGED:
+ case AX_EVENT_VALUE_CHANGED:
return EVENT_OBJECT_VALUECHANGE;
default:
return -1;
}
}
-HRESULT AXPlatformNodeWin::GetStringAttributeAsBstr(
- ui::AXStringAttribute attribute,
- BSTR* value_bstr) const {
+HRESULT AXPlatformNodeWin::GetStringAttributeAsBstr(AXStringAttribute attribute,
+ BSTR* value_bstr) const {
base::string16 str;
if (!GetString16Attribute(attribute, &str))
@@ -3287,9 +3549,9 @@ void AXPlatformNodeWin::RemoveAlertTarget() {
}
base::string16 AXPlatformNodeWin::TextForIAccessibleText() {
- if (GetData().role == ui::AX_ROLE_TEXT_FIELD)
- return GetString16Attribute(ui::AX_ATTR_VALUE);
- return GetString16Attribute(ui::AX_ATTR_NAME);
+ if (GetData().role == AX_ROLE_TEXT_FIELD)
+ return GetString16Attribute(AX_ATTR_VALUE);
+ return GetString16Attribute(AX_ATTR_NAME);
}
void AXPlatformNodeWin::HandleSpecialTextOffset(LONG* offset) {
@@ -3300,32 +3562,37 @@ void AXPlatformNodeWin::HandleSpecialTextOffset(LONG* offset) {
}
}
-ui::TextBoundaryType AXPlatformNodeWin::IA2TextBoundaryToTextBoundary(
+TextBoundaryType AXPlatformNodeWin::IA2TextBoundaryToTextBoundary(
IA2TextBoundaryType ia2_boundary) {
switch(ia2_boundary) {
- case IA2_TEXT_BOUNDARY_CHAR: return ui::CHAR_BOUNDARY;
- case IA2_TEXT_BOUNDARY_WORD: return ui::WORD_BOUNDARY;
- case IA2_TEXT_BOUNDARY_LINE: return ui::LINE_BOUNDARY;
- case IA2_TEXT_BOUNDARY_SENTENCE: return ui::SENTENCE_BOUNDARY;
- case IA2_TEXT_BOUNDARY_PARAGRAPH: return ui::PARAGRAPH_BOUNDARY;
- case IA2_TEXT_BOUNDARY_ALL: return ui::ALL_BOUNDARY;
+ case IA2_TEXT_BOUNDARY_CHAR:
+ return CHAR_BOUNDARY;
+ case IA2_TEXT_BOUNDARY_WORD:
+ return WORD_BOUNDARY;
+ case IA2_TEXT_BOUNDARY_LINE:
+ return LINE_BOUNDARY;
+ case IA2_TEXT_BOUNDARY_SENTENCE:
+ return SENTENCE_BOUNDARY;
+ case IA2_TEXT_BOUNDARY_PARAGRAPH:
+ return PARAGRAPH_BOUNDARY;
+ case IA2_TEXT_BOUNDARY_ALL:
+ return ALL_BOUNDARY;
default:
NOTREACHED();
- return ui::CHAR_BOUNDARY;
+ return CHAR_BOUNDARY;
}
}
-LONG AXPlatformNodeWin::FindBoundary(
- const base::string16& text,
- IA2TextBoundaryType ia2_boundary,
- LONG start_offset,
- ui::TextBoundaryDirection direction) {
+LONG AXPlatformNodeWin::FindBoundary(const base::string16& text,
+ IA2TextBoundaryType ia2_boundary,
+ LONG start_offset,
+ TextBoundaryDirection direction) {
HandleSpecialTextOffset(&start_offset);
- ui::TextBoundaryType boundary = IA2TextBoundaryToTextBoundary(ia2_boundary);
+ TextBoundaryType boundary = IA2TextBoundaryToTextBoundary(ia2_boundary);
std::vector<int32_t> line_breaks;
- return static_cast<LONG>(ui::FindAccessibleTextBoundary(
- text, line_breaks, boundary, start_offset, direction,
- AX_TEXT_AFFINITY_DOWNSTREAM));
+ return static_cast<LONG>(
+ FindAccessibleTextBoundary(text, line_breaks, boundary, start_offset,
+ direction, AX_TEXT_AFFINITY_DOWNSTREAM));
}
AXPlatformNodeWin* AXPlatformNodeWin::GetTargetFromChildID(
@@ -3362,16 +3629,45 @@ AXPlatformNodeWin* AXPlatformNodeWin::GetTargetFromChildID(
}
bool AXPlatformNodeWin::IsInTreeGrid() {
- auto* container = FromNativeViewAccessible(GetParent());
+ AXPlatformNodeBase* container = FromNativeViewAccessible(GetParent());
// If parent was a rowgroup, we need to look at the grandparent
- if (container && container->GetData().role == ui::AX_ROLE_GROUP)
+ if (container && container->GetData().role == AX_ROLE_GROUP)
container = FromNativeViewAccessible(container->GetParent());
if (!container)
return false;
- return container->GetData().role == ui::AX_ROLE_TREE_GRID;
+ return container->GetData().role == AX_ROLE_TREE_GRID;
+}
+
+HRESULT AXPlatformNodeWin::AllocateComArrayFromVector(
+ std::vector<LONG>& results,
+ LONG max,
+ LONG** selected,
+ LONG* n_selected) {
+ DCHECK_GT(max, 0);
+ DCHECK(selected);
+ DCHECK(n_selected);
+
+ auto count = std::min((LONG)results.size(), max);
+ *n_selected = count;
+ *selected = static_cast<LONG*>(CoTaskMemAlloc(sizeof(LONG) * count));
+
+ for (LONG i = 0; i < count; i++)
+ (*selected)[i] = results[i];
+ return S_OK;
+}
+
+// TODO(dmazzoni): Remove this function once combo box refactoring is complete.
+bool AXPlatformNodeWin::IsAncestorComboBox() {
+ auto* parent =
+ static_cast<AXPlatformNodeWin*>(FromNativeViewAccessible(GetParent()));
+ if (!parent)
+ return false;
+ if (parent->MSAARole() == ROLE_SYSTEM_COMBOBOX)
+ return true;
+ return parent->IsAncestorComboBox();
}
} // namespace ui
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_win.h b/chromium/ui/accessibility/platform/ax_platform_node_win.h
index e85a3c1855b..ecf7e8062b4 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_win.h
+++ b/chromium/ui/accessibility/platform/ax_platform_node_win.h
@@ -224,17 +224,17 @@ class AXPlatformNodeRelationWin : public CComObjectRootEx<CComMultiThreadModel>,
AXPlatformNodeRelationWin();
virtual ~AXPlatformNodeRelationWin();
- void Initialize(ui::AXPlatformNodeWin* owner, const base::string16& type);
+ void Initialize(AXPlatformNodeWin* owner, const base::string16& type);
void AddTarget(int target_id);
void RemoveTarget(int target_id);
// IAccessibleRelation methods.
STDMETHODIMP get_relationType(BSTR* relation_type) override;
- STDMETHODIMP get_nTargets(long* n_targets) override;
- STDMETHODIMP get_target(long target_index, IUnknown** target) override;
- STDMETHODIMP get_targets(long max_targets,
+ STDMETHODIMP get_nTargets(LONG* n_targets) override;
+ STDMETHODIMP get_target(LONG target_index, IUnknown** target) override;
+ STDMETHODIMP get_targets(LONG max_targets,
IUnknown** targets,
- long* n_targets) override;
+ LONG* n_targets) override;
STDMETHODIMP get_localizedRelationType(BSTR* relation_type) override;
// Accessors.
@@ -243,22 +243,21 @@ class AXPlatformNodeRelationWin : public CComObjectRootEx<CComMultiThreadModel>,
private:
base::string16 type_;
- base::win::ScopedComPtr<ui::AXPlatformNodeWin> owner_;
+ base::win::ScopedComPtr<AXPlatformNodeWin> owner_;
std::vector<int> target_ids_;
};
class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
- AXPlatformNodeWin
- : public NON_EXPORTED_BASE(CComObjectRootEx<CComMultiThreadModel>),
- public IDispatchImpl<IAccessible2_2,
- &IID_IAccessible2,
- &LIBID_IAccessible2Lib>,
- public IAccessibleText,
- public IAccessibleTable,
- public IAccessibleTable2,
- public IAccessibleTableCell,
- public IServiceProvider,
- public AXPlatformNodeBase {
+ AXPlatformNodeWin : public CComObjectRootEx<CComMultiThreadModel>,
+ public IDispatchImpl<IAccessible2_2,
+ &IID_IAccessible2,
+ &LIBID_IAccessible2Lib>,
+ public IAccessibleText,
+ public IAccessibleTable,
+ public IAccessibleTable2,
+ public IAccessibleTableCell,
+ public IServiceProvider,
+ public AXPlatformNodeBase {
public:
BEGIN_COM_MAP(AXPlatformNodeWin)
COM_INTERFACE_ENTRY2(IDispatch, IAccessible2_2)
@@ -277,10 +276,12 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
// Clear node's current relationships and set them to the default values.
void CalculateRelationships();
+ static AXPlatformNode* GetFromUniqueId(int32_t unique_id);
+ int32_t unique_id() const { return unique_id_; }
// AXPlatformNode overrides.
gfx::NativeViewAccessible GetNativeViewAccessible() override;
- void NotifyAccessibilityEvent(ui::AXEvent event_type) override;
+ void NotifyAccessibilityEvent(AXEvent event_type) override;
// AXPlatformNodeBase overrides.
void Destroy() override;
@@ -368,9 +369,9 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
STDMETHODIMP get_windowHandle(HWND* window_handle) override;
STDMETHODIMP get_relationTargetsOfType(BSTR type,
- long max_targets,
+ LONG max_targets,
IUnknown*** targets,
- long* n_targets) override;
+ LONG* n_targets) override;
STDMETHODIMP get_attributes(BSTR* attributes) override;
@@ -409,7 +410,7 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
LONG* n_localized_extended_states) override;
STDMETHODIMP get_locale(IA2Locale* locale) override;
STDMETHODIMP get_accessibleWithCaret(IUnknown** accessible,
- long* caret_offset) override;
+ LONG* caret_offset) override;
//
// IAccessibleText methods.
@@ -458,87 +459,87 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
// get_description - also used by IAccessibleImage
- STDMETHODIMP get_accessibleAt(long row,
- long column,
+ STDMETHODIMP get_accessibleAt(LONG row,
+ LONG column,
IUnknown** accessible) override;
STDMETHODIMP get_caption(IUnknown** accessible) override;
- STDMETHODIMP get_childIndex(long row_index,
- long column_index,
- long* cell_index) override;
+ STDMETHODIMP get_childIndex(LONG row_index,
+ LONG column_index,
+ LONG* cell_index) override;
- STDMETHODIMP get_columnDescription(long column, BSTR* description) override;
+ STDMETHODIMP get_columnDescription(LONG column, BSTR* description) override;
STDMETHODIMP
- get_columnExtentAt(long row, long column, long* n_columns_spanned) override;
+ get_columnExtentAt(LONG row, LONG column, LONG* n_columns_spanned) override;
STDMETHODIMP
get_columnHeader(IAccessibleTable** accessible_table,
- long* starting_row_index) override;
+ LONG* starting_row_index) override;
- STDMETHODIMP get_columnIndex(long cell_index, long* column_index) override;
+ STDMETHODIMP get_columnIndex(LONG cell_index, LONG* column_index) override;
- STDMETHODIMP get_nColumns(long* column_count) override;
+ STDMETHODIMP get_nColumns(LONG* column_count) override;
- STDMETHODIMP get_nRows(long* row_count) override;
+ STDMETHODIMP get_nRows(LONG* row_count) override;
- STDMETHODIMP get_nSelectedChildren(long* cell_count) override;
+ STDMETHODIMP get_nSelectedChildren(LONG* cell_count) override;
- STDMETHODIMP get_nSelectedColumns(long* column_count) override;
+ STDMETHODIMP get_nSelectedColumns(LONG* column_count) override;
- STDMETHODIMP get_nSelectedRows(long* row_count) override;
+ STDMETHODIMP get_nSelectedRows(LONG* row_count) override;
- STDMETHODIMP get_rowDescription(long row, BSTR* description) override;
+ STDMETHODIMP get_rowDescription(LONG row, BSTR* description) override;
- STDMETHODIMP get_rowExtentAt(long row,
- long column,
- long* n_rows_spanned) override;
+ STDMETHODIMP get_rowExtentAt(LONG row,
+ LONG column,
+ LONG* n_rows_spanned) override;
STDMETHODIMP
get_rowHeader(IAccessibleTable** accessible_table,
- long* starting_column_index) override;
+ LONG* starting_column_index) override;
- STDMETHODIMP get_rowIndex(long cell_index, long* row_index) override;
+ STDMETHODIMP get_rowIndex(LONG cell_index, LONG* row_index) override;
- STDMETHODIMP get_selectedChildren(long max_children,
- long** children,
- long* n_children) override;
+ STDMETHODIMP get_selectedChildren(LONG max_children,
+ LONG** children,
+ LONG* n_children) override;
- STDMETHODIMP get_selectedColumns(long max_columns,
- long** columns,
- long* n_columns) override;
+ STDMETHODIMP get_selectedColumns(LONG max_columns,
+ LONG** columns,
+ LONG* n_columns) override;
- STDMETHODIMP get_selectedRows(long max_rows,
- long** rows,
- long* n_rows) override;
+ STDMETHODIMP get_selectedRows(LONG max_rows,
+ LONG** rows,
+ LONG* n_rows) override;
STDMETHODIMP get_summary(IUnknown** accessible) override;
STDMETHODIMP
- get_isColumnSelected(long column, boolean* is_selected) override;
+ get_isColumnSelected(LONG column, boolean* is_selected) override;
- STDMETHODIMP get_isRowSelected(long row, boolean* is_selected) override;
+ STDMETHODIMP get_isRowSelected(LONG row, boolean* is_selected) override;
- STDMETHODIMP get_isSelected(long row,
- long column,
+ STDMETHODIMP get_isSelected(LONG row,
+ LONG column,
boolean* is_selected) override;
STDMETHODIMP
- get_rowColumnExtentsAtIndex(long index,
- long* row,
- long* column,
- long* row_extents,
- long* column_extents,
+ get_rowColumnExtentsAtIndex(LONG index,
+ LONG* row,
+ LONG* column,
+ LONG* row_extents,
+ LONG* column_extents,
boolean* is_selected) override;
- STDMETHODIMP selectRow(long row) override;
+ STDMETHODIMP selectRow(LONG row) override;
- STDMETHODIMP selectColumn(long column) override;
+ STDMETHODIMP selectColumn(LONG column) override;
- STDMETHODIMP unselectRow(long row) override;
+ STDMETHODIMP unselectRow(LONG row) override;
- STDMETHODIMP unselectColumn(long column) override;
+ STDMETHODIMP unselectColumn(LONG column) override;
STDMETHODIMP
get_modelChange(IA2TableModelChange* model_change) override;
@@ -550,45 +551,45 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
// unique ones are included here.)
//
- STDMETHODIMP get_cellAt(long row, long column, IUnknown** cell) override;
+ STDMETHODIMP get_cellAt(LONG row, LONG column, IUnknown** cell) override;
- STDMETHODIMP get_nSelectedCells(long* cell_count) override;
+ STDMETHODIMP get_nSelectedCells(LONG* cell_count) override;
STDMETHODIMP
- get_selectedCells(IUnknown*** cells, long* n_selected_cells) override;
+ get_selectedCells(IUnknown*** cells, LONG* n_selected_cells) override;
- STDMETHODIMP get_selectedColumns(long** columns, long* n_columns) override;
+ STDMETHODIMP get_selectedColumns(LONG** columns, LONG* n_columns) override;
- STDMETHODIMP get_selectedRows(long** rows, long* n_rows) override;
+ STDMETHODIMP get_selectedRows(LONG** rows, LONG* n_rows) override;
//
// IAccessibleTableCell methods.
//
STDMETHODIMP
- get_columnExtent(long* n_columns_spanned) override;
+ get_columnExtent(LONG* n_columns_spanned) override;
STDMETHODIMP
get_columnHeaderCells(IUnknown*** cell_accessibles,
- long* n_column_header_cells) override;
+ LONG* n_column_header_cells) override;
- STDMETHODIMP get_columnIndex(long* column_index) override;
+ STDMETHODIMP get_columnIndex(LONG* column_index) override;
- STDMETHODIMP get_rowExtent(long* n_rows_spanned) override;
+ STDMETHODIMP get_rowExtent(LONG* n_rows_spanned) override;
STDMETHODIMP
get_rowHeaderCells(IUnknown*** cell_accessibles,
- long* n_row_header_cells) override;
+ LONG* n_row_header_cells) override;
- STDMETHODIMP get_rowIndex(long* row_index) override;
+ STDMETHODIMP get_rowIndex(LONG* row_index) override;
STDMETHODIMP get_isSelected(boolean* is_selected) override;
STDMETHODIMP
- get_rowColumnExtents(long* row,
- long* column,
- long* row_extents,
- long* column_extents,
+ get_rowColumnExtents(LONG* row,
+ LONG* column,
+ LONG* row_extents,
+ LONG* column_extents,
boolean* is_selected) override;
STDMETHODIMP get_table(IUnknown** table) override;
@@ -650,14 +651,15 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
void Dispose() override;
private:
- int MSAAEvent(ui::AXEvent event);
+ int32_t unique_id_;
+
+ int MSAAEvent(AXEvent event);
bool IsWebAreaForPresentationalIframe();
bool ShouldNodeHaveReadonlyStateByDefault(const AXNodeData& data) const;
bool ShouldNodeHaveFocusableState(const AXNodeData& data) const;
- HRESULT GetStringAttributeAsBstr(
- ui::AXStringAttribute attribute,
- BSTR* value_bstr) const;
+ HRESULT GetStringAttributeAsBstr(AXStringAttribute attribute,
+ BSTR* value_bstr) const;
// Escapes characters in string attributes as required by the IA2 Spec.
// It's okay for input to be the same as output.
@@ -670,19 +672,19 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
// If the string attribute |attribute| is present, add its value as an
// IAccessible2 attribute with the name |ia2_attr|.
void StringAttributeToIA2(std::vector<base::string16>& attributes,
- ui::AXStringAttribute attribute,
+ AXStringAttribute attribute,
const char* ia2_attr);
// If the bool attribute |attribute| is present, add its value as an
// IAccessible2 attribute with the name |ia2_attr|.
void BoolAttributeToIA2(std::vector<base::string16>& attributes,
- ui::AXBoolAttribute attribute,
+ AXBoolAttribute attribute,
const char* ia2_attr);
// If the int attribute |attribute| is present, add its value as an
// IAccessible2 attribute with the name |ia2_attr|.
void IntAttributeToIA2(std::vector<base::string16>& attributes,
- ui::AXIntAttribute attribute,
+ AXIntAttribute attribute,
const char* ia2_attr);
void AddAlertTarget();
@@ -695,8 +697,8 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
// value of offset and returns, otherwise offset remains unchanged.
void HandleSpecialTextOffset(LONG* offset);
- // Convert from a IA2TextBoundaryType to a ui::TextBoundaryType.
- ui::TextBoundaryType IA2TextBoundaryToTextBoundary(IA2TextBoundaryType type);
+ // Convert from a IA2TextBoundaryType to a TextBoundaryType.
+ TextBoundaryType IA2TextBoundaryToTextBoundary(IA2TextBoundaryType type);
// Search forwards (direction == 1) or backwards (direction == -1)
// from the given offset until the given boundary is found, and
@@ -704,7 +706,7 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
LONG FindBoundary(const base::string16& text,
IA2TextBoundaryType ia2_boundary,
LONG start_offset,
- ui::TextBoundaryDirection direction);
+ TextBoundaryDirection direction);
// Many MSAA methods take a var_id parameter indicating that the operation
// should be performed on a particular child ID, rather than this object.
@@ -722,7 +724,7 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
void AddRelation(const base::string16& relation_type, int target_id);
void AddBidirectionalRelations(const base::string16& relation_type,
const base::string16& reverse_relation_type,
- ui::AXIntListAttribute attribute);
+ AXIntListAttribute attribute);
void AddBidirectionalRelations(const base::string16& relation_type,
const base::string16& reverse_relation_type,
const std::vector<int32_t>& target_ids);
@@ -736,8 +738,17 @@ class AX_EXPORT __declspec(uuid("26f5641a-246d-457b-a96d-07f3fae6acf2"))
void RemoveTargetFromRelation(const base::string16& relation_type,
int target_id);
+ // Helper method for returning selected indicies. It is expected that the
+ // caller ensures that the input has been validated.
+ HRESULT AllocateComArrayFromVector(std::vector<LONG>& results,
+ LONG max,
+ LONG** selected,
+ LONG* n_selected);
+
+ bool IsAncestorComboBox();
+
// Relationships between this node and other nodes.
- std::vector<ui::AXPlatformNodeRelationWin*> relations_;
+ std::vector<AXPlatformNodeRelationWin*> relations_;
};
} // namespace ui
diff --git a/chromium/ui/accessibility/platform/ax_platform_node_win_unittest.cc b/chromium/ui/accessibility/platform/ax_platform_node_win_unittest.cc
index 9fe0108e065..8fcf2ee718a 100644
--- a/chromium/ui/accessibility/platform/ax_platform_node_win_unittest.cc
+++ b/chromium/ui/accessibility/platform/ax_platform_node_win_unittest.cc
@@ -148,14 +148,14 @@ class AXPlatformNodeWinTest : public testing::Test {
void CheckIUnknownHasName(ScopedComPtr<IUnknown> unknown,
const wchar_t* expected_name) {
ScopedComPtr<IAccessible2> accessible = ToIAccessible2(unknown);
- ASSERT_NE(nullptr, accessible);
+ ASSERT_NE(nullptr, accessible.Get());
ScopedBstr name;
EXPECT_EQ(S_OK, accessible->get_accName(SELF, name.Receive()));
EXPECT_STREQ(expected_name, name);
}
- void Build3X3Table() {
+ AXTreeUpdate Build3X3Table() {
/*
Build a table the looks like:
@@ -170,7 +170,7 @@ class AXPlatformNodeWinTest : public testing::Test {
AXNodeData table;
table.id = 0;
- table.role = ui::AX_ROLE_TABLE;
+ table.role = AX_ROLE_TABLE;
table.AddIntAttribute(AX_ATTR_TABLE_ROW_COUNT, 3);
table.AddIntAttribute(AX_ATTR_TABLE_COLUMN_COUNT, 3);
@@ -190,23 +190,23 @@ class AXPlatformNodeWinTest : public testing::Test {
// Table column header
AXNodeData table_row_header;
table_row_header.id = 50;
- table_row_header.role = ui::AX_ROLE_ROW;
+ table_row_header.role = AX_ROLE_ROW;
table_row_header.child_ids.push_back(51);
table_row_header.child_ids.push_back(52);
table_row_header.child_ids.push_back(53);
AXNodeData table_column_header_1;
table_column_header_1.id = 51;
- table_column_header_1.role = ui::AX_ROLE_COLUMN_HEADER;
+ table_column_header_1.role = AX_ROLE_COLUMN_HEADER;
AXNodeData table_column_header_2;
table_column_header_2.id = 52;
- table_column_header_2.role = ui::AX_ROLE_COLUMN_HEADER;
+ table_column_header_2.role = AX_ROLE_COLUMN_HEADER;
table_column_header_2.AddStringAttribute(AX_ATTR_NAME, "column header 1");
AXNodeData table_column_header_3;
table_column_header_3.id = 53;
- table_column_header_3.role = ui::AX_ROLE_COLUMN_HEADER;
+ table_column_header_3.role = AX_ROLE_COLUMN_HEADER;
// Either AX_ATTR_NAME -or- AX_ATTR_DESCRIPTION is acceptable for a
// description
table_column_header_3.AddStringAttribute(AX_ATTR_DESCRIPTION,
@@ -215,72 +215,75 @@ class AXPlatformNodeWinTest : public testing::Test {
// Row 1
AXNodeData table_row_1;
table_row_1.id = 1;
- table_row_1.role = ui::AX_ROLE_ROW;
+ table_row_1.role = AX_ROLE_ROW;
table_row_1.child_ids.push_back(2);
table_row_1.child_ids.push_back(3);
table_row_1.child_ids.push_back(4);
AXNodeData table_row_header_1;
table_row_header_1.id = 2;
- table_row_header_1.role = ui::AX_ROLE_ROW_HEADER;
+ table_row_header_1.role = AX_ROLE_ROW_HEADER;
table_row_header_1.AddStringAttribute(AX_ATTR_NAME, "row header 1");
AXNodeData table_cell_1;
table_cell_1.id = 3;
- table_cell_1.role = ui::AX_ROLE_CELL;
+ table_cell_1.role = AX_ROLE_CELL;
table_cell_1.AddStringAttribute(AX_ATTR_NAME, "1");
AXNodeData table_cell_2;
table_cell_2.id = 4;
- table_cell_2.role = ui::AX_ROLE_CELL;
+ table_cell_2.role = AX_ROLE_CELL;
table_cell_2.AddStringAttribute(AX_ATTR_NAME, "2");
// Row 2
AXNodeData table_row_2;
table_row_2.id = 10;
- table_row_2.role = ui::AX_ROLE_ROW;
+ table_row_2.role = AX_ROLE_ROW;
table_row_2.child_ids.push_back(11);
table_row_2.child_ids.push_back(12);
table_row_2.child_ids.push_back(13);
AXNodeData table_row_header_2;
table_row_header_2.id = 11;
- table_row_header_2.role = ui::AX_ROLE_ROW_HEADER;
+ table_row_header_2.role = AX_ROLE_ROW_HEADER;
// Either AX_ATTR_NAME -or- AX_ATTR_DESCRIPTION is acceptable for a
// description
table_row_header_2.AddStringAttribute(AX_ATTR_DESCRIPTION, "row header 2");
AXNodeData table_cell_3;
table_cell_3.id = 12;
- table_cell_3.role = ui::AX_ROLE_CELL;
+ table_cell_3.role = AX_ROLE_CELL;
table_cell_3.AddStringAttribute(AX_ATTR_NAME, "3");
AXNodeData table_cell_4;
table_cell_4.id = 13;
- table_cell_4.role = ui::AX_ROLE_CELL;
+ table_cell_4.role = AX_ROLE_CELL;
table_cell_4.AddStringAttribute(AX_ATTR_NAME, "4");
AXTreeUpdate update;
update.root_id = table.id;
- update.nodes.push_back(table);
+ // Some of the table testing code will index into |nodes|
+ // and change the state of the given node. If you reorder
+ // these, you're going to need to update the tests.
+ update.nodes.push_back(table); // 0
- update.nodes.push_back(table_row_header);
- update.nodes.push_back(table_column_header_1);
- update.nodes.push_back(table_column_header_2);
- update.nodes.push_back(table_column_header_3);
+ update.nodes.push_back(table_row_header); // 1
+ update.nodes.push_back(table_column_header_1); // 2
+ update.nodes.push_back(table_column_header_2); // 3
+ update.nodes.push_back(table_column_header_3); // 4
- update.nodes.push_back(table_row_1);
- update.nodes.push_back(table_row_header_1);
- update.nodes.push_back(table_cell_1);
- update.nodes.push_back(table_cell_2);
+ update.nodes.push_back(table_row_1); // 5
+ update.nodes.push_back(table_row_header_1); // 6
+ update.nodes.push_back(table_cell_1); // 7
+ update.nodes.push_back(table_cell_2); // 8
- update.nodes.push_back(table_row_2);
- update.nodes.push_back(table_row_header_2);
- update.nodes.push_back(table_cell_3);
- update.nodes.push_back(table_cell_4);
+ update.nodes.push_back(table_row_2); // 9
+ update.nodes.push_back(table_row_header_2); // 10
+ update.nodes.push_back(table_cell_3); // 11
+ update.nodes.push_back(table_cell_4); // 12
- Init(update);
+ return update;
}
ScopedComPtr<IAccessibleTableCell> GetCellInTable() {
@@ -483,7 +486,7 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleSelectionOneSelected) {
AXNodeData list_item_2;
list_item_2.id = 2;
list_item_2.role = AX_ROLE_LIST_BOX_OPTION;
- list_item_2.state = 1 << ui::AX_STATE_SELECTED;
+ list_item_2.state = 1 << AX_STATE_SELECTED;
list_item_2.AddStringAttribute(AX_ATTR_NAME, "Name2");
AXNodeData list_item_3;
@@ -516,13 +519,13 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleSelectionMultipleSelected) {
AXNodeData list_item_2;
list_item_2.id = 2;
list_item_2.role = AX_ROLE_LIST_BOX_OPTION;
- list_item_2.state = 1 << ui::AX_STATE_SELECTED;
+ list_item_2.state = 1 << AX_STATE_SELECTED;
list_item_2.AddStringAttribute(AX_ATTR_NAME, "Name2");
AXNodeData list_item_3;
list_item_3.id = 3;
list_item_3.role = AX_ROLE_LIST_BOX_OPTION;
- list_item_3.state = 1 << ui::AX_STATE_SELECTED;
+ list_item_3.state = 1 << AX_STATE_SELECTED;
list_item_3.AddStringAttribute(AX_ATTR_NAME, "Name3");
AXNodeData list_item_4;
@@ -682,7 +685,7 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleChildAndParent) {
ScopedComPtr<IDispatch> result;
EXPECT_EQ(S_OK,
root_iaccessible->get_accChild(SELF, result.GetAddressOf()));
- EXPECT_EQ(result.Get(), root_iaccessible);
+ EXPECT_EQ(result.Get(), root_iaccessible.Get());
}
{
@@ -690,7 +693,7 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleChildAndParent) {
ScopedVariant child1(1);
EXPECT_EQ(S_OK,
root_iaccessible->get_accChild(child1, result.GetAddressOf()));
- EXPECT_EQ(result.Get(), button_iaccessible);
+ EXPECT_EQ(result.Get(), button_iaccessible.Get());
}
{
@@ -698,7 +701,7 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleChildAndParent) {
ScopedVariant child2(2);
EXPECT_EQ(S_OK,
root_iaccessible->get_accChild(child2, result.GetAddressOf()));
- EXPECT_EQ(result.Get(), checkbox_iaccessible);
+ EXPECT_EQ(result.Get(), checkbox_iaccessible.Get());
}
{
@@ -720,7 +723,7 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleChildAndParent) {
ScopedVariant button_id_variant(button_unique_id);
EXPECT_EQ(S_OK, root_iaccessible->get_accChild(button_id_variant,
result.GetAddressOf()));
- EXPECT_EQ(result.Get(), button_iaccessible);
+ EXPECT_EQ(result.Get(), button_iaccessible.Get());
}
// We shouldn't be able to ask for the root node by its unique ID
@@ -741,13 +744,13 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleChildAndParent) {
{
ScopedComPtr<IDispatch> result;
EXPECT_EQ(S_OK, button_iaccessible->get_accParent(result.GetAddressOf()));
- EXPECT_EQ(result.Get(), root_iaccessible);
+ EXPECT_EQ(result.Get(), root_iaccessible.Get());
}
{
ScopedComPtr<IDispatch> result;
EXPECT_EQ(S_OK, checkbox_iaccessible->get_accParent(result.GetAddressOf()));
- EXPECT_EQ(result.Get(), root_iaccessible);
+ EXPECT_EQ(result.Get(), root_iaccessible.Get());
}
{
@@ -887,8 +890,8 @@ TEST_F(AXPlatformNodeWinTest, TestAccNavigate) {
TEST_F(AXPlatformNodeWinTest, TestIAccessible2SetSelection) {
AXNodeData text_field_node;
text_field_node.id = 1;
- text_field_node.role = ui::AX_ROLE_TEXT_FIELD;
- text_field_node.state = 1 << ui::AX_STATE_EDITABLE;
+ text_field_node.role = AX_ROLE_TEXT_FIELD;
+ text_field_node.state = 1 << AX_STATE_EDITABLE;
text_field_node.SetValue("Hi");
Init(text_field_node);
@@ -896,7 +899,7 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessible2SetSelection) {
ToIAccessible2(GetRootIAccessible());
ScopedComPtr<IAccessibleText> text_field;
ia2_text_field.CopyTo(text_field.GetAddressOf());
- ASSERT_NE(nullptr, text_field);
+ ASSERT_NE(nullptr, text_field.Get());
EXPECT_HRESULT_SUCCEEDED(text_field->setSelection(0, 0, 1));
EXPECT_HRESULT_SUCCEEDED(text_field->setSelection(0, 1, 0));
@@ -909,13 +912,13 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessible2SetSelection) {
}
TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetAccessibilityAt) {
- Build3X3Table();
+ Init(Build3X3Table());
ScopedComPtr<IAccessible> root_obj(GetRootIAccessible());
ScopedComPtr<IAccessibleTable> result;
root_obj.CopyTo(result.GetAddressOf());
- ASSERT_NE(nullptr, result);
+ ASSERT_NE(nullptr, result.Get());
ScopedComPtr<IUnknown> cell_1;
EXPECT_EQ(S_OK, result->get_accessibleAt(1, 1, cell_1.GetAddressOf()));
@@ -936,13 +939,13 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetAccessibilityAt) {
TEST_F(AXPlatformNodeWinTest,
TestIAccessibleTableGetAccessibilityAtOutOfBounds) {
- Build3X3Table();
+ Init(Build3X3Table());
ScopedComPtr<IAccessible> root_obj(GetRootIAccessible());
ScopedComPtr<IAccessibleTable> result;
root_obj.CopyTo(result.GetAddressOf());
- ASSERT_NE(nullptr, result);
+ ASSERT_NE(nullptr, result.Get());
{
ScopedComPtr<IUnknown> cell;
@@ -970,13 +973,13 @@ TEST_F(AXPlatformNodeWinTest,
}
TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetChildIndex) {
- Build3X3Table();
+ Init(Build3X3Table());
ScopedComPtr<IAccessible> root_obj(GetRootIAccessible());
ScopedComPtr<IAccessibleTable> result;
root_obj.CopyTo(result.GetAddressOf());
- ASSERT_NE(nullptr, result);
+ ASSERT_NE(nullptr, result.Get());
long id;
EXPECT_EQ(S_OK, result->get_childIndex(0, 0, &id));
@@ -998,13 +1001,13 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetChildIndex) {
}
TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetColumnDescription) {
- Build3X3Table();
+ Init(Build3X3Table());
ScopedComPtr<IAccessible> root_obj(GetRootIAccessible());
ScopedComPtr<IAccessibleTable> result;
root_obj.CopyTo(result.GetAddressOf());
- ASSERT_NE(nullptr, result);
+ ASSERT_NE(nullptr, result.Get());
{
ScopedBstr name;
@@ -1026,13 +1029,13 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetColumnDescription) {
TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetColumnExtentAt) {
// TODO(dougt) This table doesn't have any spanning cells. This test
// tests get_columnExtentAt for (1) and an invalid input.
- Build3X3Table();
+ Init(Build3X3Table());
ScopedComPtr<IAccessible> root_obj(GetRootIAccessible());
ScopedComPtr<IAccessibleTable> result;
root_obj.CopyTo(result.GetAddressOf());
- ASSERT_NE(nullptr, result);
+ ASSERT_NE(nullptr, result.Get());
long columns_spanned;
EXPECT_EQ(S_OK, result->get_columnExtentAt(1, 1, &columns_spanned));
@@ -1042,13 +1045,13 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetColumnExtentAt) {
}
TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetColumnIndex) {
- Build3X3Table();
+ Init(Build3X3Table());
ScopedComPtr<IAccessible> root_obj(GetRootIAccessible());
ScopedComPtr<IAccessibleTable> result;
root_obj.CopyTo(result.GetAddressOf());
- ASSERT_NE(nullptr, result);
+ ASSERT_NE(nullptr, result.Get());
long index;
EXPECT_EQ(S_OK, result->get_columnIndex(1, &index));
@@ -1058,13 +1061,13 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetColumnIndex) {
}
TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetNColumns) {
- Build3X3Table();
+ Init(Build3X3Table());
ScopedComPtr<IAccessible> root_obj(GetRootIAccessible());
ScopedComPtr<IAccessibleTable> result;
root_obj.CopyTo(result.GetAddressOf());
- ASSERT_NE(nullptr, result);
+ ASSERT_NE(nullptr, result.Get());
long count;
EXPECT_EQ(S_OK, result->get_nColumns(&count));
@@ -1072,13 +1075,13 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetNColumns) {
}
TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetNRows) {
- Build3X3Table();
+ Init(Build3X3Table());
ScopedComPtr<IAccessible> root_obj(GetRootIAccessible());
ScopedComPtr<IAccessibleTable> result;
root_obj.CopyTo(result.GetAddressOf());
- ASSERT_NE(nullptr, result);
+ ASSERT_NE(nullptr, result.Get());
long count;
EXPECT_EQ(S_OK, result->get_nRows(&count));
@@ -1086,13 +1089,13 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetNRows) {
}
TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetRowDescription) {
- Build3X3Table();
+ Init(Build3X3Table());
ScopedComPtr<IAccessible> root_obj(GetRootIAccessible());
ScopedComPtr<IAccessibleTable> result;
root_obj.CopyTo(result.GetAddressOf());
- ASSERT_NE(nullptr, result);
+ ASSERT_NE(nullptr, result.Get());
{
ScopedBstr name;
@@ -1114,13 +1117,13 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetRowDescription) {
TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetRowExtentAt) {
// TODO(dougt) This table doesn't have any spanning cells. This test
// tests get_rowExtentAt for (1) and an invalid input.
- Build3X3Table();
+ Init(Build3X3Table());
ScopedComPtr<IAccessible> root_obj(GetRootIAccessible());
ScopedComPtr<IAccessibleTable> result;
root_obj.CopyTo(result.GetAddressOf());
- ASSERT_NE(nullptr, result);
+ ASSERT_NE(nullptr, result.Get());
long rows_spanned;
EXPECT_EQ(S_OK, result->get_rowExtentAt(0, 1, &rows_spanned));
@@ -1130,13 +1133,13 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetRowExtentAt) {
}
TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetRowIndex) {
- Build3X3Table();
+ Init(Build3X3Table());
ScopedComPtr<IAccessible> root_obj(GetRootIAccessible());
ScopedComPtr<IAccessibleTable> result;
root_obj.CopyTo(result.GetAddressOf());
- ASSERT_NE(nullptr, result);
+ ASSERT_NE(nullptr, result.Get());
long index;
EXPECT_EQ(S_OK, result->get_rowIndex(1, &index));
@@ -1146,13 +1149,13 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetRowIndex) {
}
TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetRowColumnExtentsAtIndex) {
- Build3X3Table();
+ Init(Build3X3Table());
ScopedComPtr<IAccessible> root_obj(GetRootIAccessible());
ScopedComPtr<IAccessibleTable> result;
root_obj.CopyTo(result.GetAddressOf());
- ASSERT_NE(nullptr, result);
+ ASSERT_NE(nullptr, result.Get());
long row, column, row_extents, column_extents;
boolean is_selected;
@@ -1171,13 +1174,13 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetRowColumnExtentsAtIndex) {
}
TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetCellAt) {
- Build3X3Table();
+ Init(Build3X3Table());
ScopedComPtr<IAccessible> root_obj(GetRootIAccessible());
ScopedComPtr<IAccessibleTable2> result;
root_obj.CopyTo(result.GetAddressOf());
- ASSERT_NE(nullptr, result);
+ ASSERT_NE(nullptr, result.Get());
{
ScopedComPtr<IUnknown> cell;
@@ -1192,10 +1195,10 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetCellAt) {
}
TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableCellGetColumnExtent) {
- Build3X3Table();
+ Init(Build3X3Table());
ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
- ASSERT_NE(nullptr, cell);
+ ASSERT_NE(nullptr, cell.Get());
long column_spanned;
EXPECT_EQ(S_OK, cell->get_columnExtent(&column_spanned));
@@ -1203,10 +1206,10 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableCellGetColumnExtent) {
}
TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableCellGetColumnHeaderCells) {
- Build3X3Table();
+ Init(Build3X3Table());
ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
- ASSERT_NE(nullptr, cell);
+ ASSERT_NE(nullptr, cell.Get());
IUnknown** cell_accessibles;
@@ -1217,10 +1220,10 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableCellGetColumnHeaderCells) {
}
TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableCellGetColumnIndex) {
- Build3X3Table();
+ Init(Build3X3Table());
ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
- ASSERT_NE(nullptr, cell);
+ ASSERT_NE(nullptr, cell.Get());
long index;
EXPECT_EQ(S_OK, cell->get_columnIndex(&index));
@@ -1228,10 +1231,10 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableCellGetColumnIndex) {
}
TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableCellGetRowExtent) {
- Build3X3Table();
+ Init(Build3X3Table());
ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
- ASSERT_NE(nullptr, cell);
+ ASSERT_NE(nullptr, cell.Get());
long rows_spanned;
EXPECT_EQ(S_OK, cell->get_rowExtent(&rows_spanned));
@@ -1239,10 +1242,10 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableCellGetRowExtent) {
}
TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableCellGetRowHeaderCells) {
- Build3X3Table();
+ Init(Build3X3Table());
ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
- ASSERT_NE(nullptr, cell);
+ ASSERT_NE(nullptr, cell.Get());
IUnknown** cell_accessibles;
@@ -1255,10 +1258,10 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableCellGetRowHeaderCells) {
}
TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableCellGetRowIndex) {
- Build3X3Table();
+ Init(Build3X3Table());
ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
- ASSERT_NE(nullptr, cell);
+ ASSERT_NE(nullptr, cell.Get());
long index;
EXPECT_EQ(S_OK, cell->get_rowIndex(&index));
@@ -1266,10 +1269,10 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableCellGetRowIndex) {
}
TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableCellGetRowColumnExtent) {
- Build3X3Table();
+ Init(Build3X3Table());
ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
- ASSERT_NE(nullptr, cell);
+ ASSERT_NE(nullptr, cell.Get());
long row, column, row_extents, column_extents;
boolean is_selected;
@@ -1282,17 +1285,17 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableCellGetRowColumnExtent) {
}
TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableCellGetTable) {
- Build3X3Table();
+ Init(Build3X3Table());
ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
- ASSERT_NE(nullptr, cell);
+ ASSERT_NE(nullptr, cell.Get());
ScopedComPtr<IUnknown> table;
EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
ScopedComPtr<IAccessibleTable> result;
table.CopyTo(result.GetAddressOf());
- ASSERT_NE(nullptr, result);
+ ASSERT_NE(nullptr, result.Get());
// Check to make sure that this is the right table by checking one cell.
ScopedComPtr<IUnknown> cell_1;
@@ -1304,22 +1307,22 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessible2GetNRelations) {
// This is is a duplicated of
// BrowserAccessibilityTest::TestIAccessible2Relations but without the
// specific COM/BrowserAccessibility knowledge.
- ui::AXNodeData root;
+ AXNodeData root;
root.id = 1;
- root.role = ui::AX_ROLE_ROOT_WEB_AREA;
+ root.role = AX_ROLE_ROOT_WEB_AREA;
std::vector<int32_t> describedby_ids = {1, 2, 3};
- root.AddIntListAttribute(ui::AX_ATTR_DESCRIBEDBY_IDS, describedby_ids);
+ root.AddIntListAttribute(AX_ATTR_DESCRIBEDBY_IDS, describedby_ids);
- ui::AXNodeData child1;
+ AXNodeData child1;
child1.id = 2;
- child1.role = ui::AX_ROLE_STATIC_TEXT;
+ child1.role = AX_ROLE_STATIC_TEXT;
root.child_ids.push_back(2);
- ui::AXNodeData child2;
+ AXNodeData child2;
child2.id = 3;
- child2.role = ui::AX_ROLE_STATIC_TEXT;
+ child2.role = AX_ROLE_STATIC_TEXT;
root.child_ids.push_back(3);
@@ -1413,4 +1416,674 @@ TEST_F(AXPlatformNodeWinTest, TestIAccessible2GetNRelations) {
// TODO(dougt): Try adding one more relation.
}
+TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetNSelectedChildrenZero) {
+ Init(Build3X3Table());
+
+ ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
+ ASSERT_NE(nullptr, cell.Get());
+
+ ScopedComPtr<IUnknown> table;
+ EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
+
+ ScopedComPtr<IAccessibleTable> result;
+ table.CopyTo(result.GetAddressOf());
+ ASSERT_NE(nullptr, result.Get());
+
+ LONG selectedChildren;
+ EXPECT_EQ(S_OK, result->get_nSelectedChildren(&selectedChildren));
+ EXPECT_EQ(0, selectedChildren);
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetNSelectedChildrenOne) {
+ AXTreeUpdate update = Build3X3Table();
+
+ // 7 == table_cell_1
+ update.nodes[7].state = 1 << AX_STATE_SELECTED;
+ Init(update);
+
+ ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
+ ASSERT_NE(nullptr, cell.Get());
+
+ ScopedComPtr<IUnknown> table;
+ EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
+
+ ScopedComPtr<IAccessibleTable> result;
+ table.CopyTo(result.GetAddressOf());
+ ASSERT_NE(nullptr, result.Get());
+
+ LONG selectedChildren;
+ EXPECT_EQ(S_OK, result->get_nSelectedChildren(&selectedChildren));
+ EXPECT_EQ(1, selectedChildren);
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetNSelectedChildrenMany) {
+ AXTreeUpdate update = Build3X3Table();
+
+ // 7 == table_cell_1
+ // 8 == table_cell_2
+ // 11 == table_cell_3
+ // 12 == table_cell_4
+ update.nodes[7].state = 1 << AX_STATE_SELECTED;
+ update.nodes[8].state = 1 << AX_STATE_SELECTED;
+ update.nodes[11].state = 1 << AX_STATE_SELECTED;
+ update.nodes[12].state = 1 << AX_STATE_SELECTED;
+
+ Init(update);
+
+ ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
+ ASSERT_NE(nullptr, cell.Get());
+
+ ScopedComPtr<IUnknown> table;
+ EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
+
+ ScopedComPtr<IAccessibleTable> result;
+ table.CopyTo(result.GetAddressOf());
+ ASSERT_NE(nullptr, result.Get());
+
+ LONG selectedChildren;
+ EXPECT_EQ(S_OK, result->get_nSelectedChildren(&selectedChildren));
+ EXPECT_EQ(4, selectedChildren);
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetNSelectedColumnsZero) {
+ Init(Build3X3Table());
+
+ ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
+ ASSERT_NE(nullptr, cell.Get());
+
+ ScopedComPtr<IUnknown> table;
+ EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
+
+ ScopedComPtr<IAccessibleTable> result;
+ table.CopyTo(result.GetAddressOf());
+ ASSERT_NE(nullptr, result.Get());
+
+ LONG selectedColumns;
+ EXPECT_EQ(S_OK, result->get_nSelectedColumns(&selectedColumns));
+ EXPECT_EQ(0, selectedColumns);
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetNSelectedColumnsOne) {
+ AXTreeUpdate update = Build3X3Table();
+
+ // 3 == table_column_header_2
+ // 7 == table_cell_1
+ // 11 == table_cell_3
+ update.nodes[3].state = 1 << AX_STATE_SELECTED;
+ update.nodes[7].state = 1 << AX_STATE_SELECTED;
+ update.nodes[11].state = 1 << AX_STATE_SELECTED;
+
+ Init(update);
+
+ ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
+ ASSERT_NE(nullptr, cell.Get());
+
+ ScopedComPtr<IUnknown> table;
+ EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
+
+ ScopedComPtr<IAccessibleTable> result;
+ table.CopyTo(result.GetAddressOf());
+ ASSERT_NE(nullptr, result.Get());
+
+ LONG selectedColumns;
+ EXPECT_EQ(S_OK, result->get_nSelectedColumns(&selectedColumns));
+ EXPECT_EQ(1, selectedColumns);
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetNSelectedColumnsMany) {
+ AXTreeUpdate update = Build3X3Table();
+
+ // 3 == table_column_header_2
+ // 7 == table_cell_1
+ // 11 == table_cell_3
+ update.nodes[3].state = 1 << AX_STATE_SELECTED;
+ update.nodes[7].state = 1 << AX_STATE_SELECTED;
+ update.nodes[11].state = 1 << AX_STATE_SELECTED;
+
+ // 4 == table_column_header_3
+ // 8 == table_cell_2
+ // 12 == table_cell_4
+ update.nodes[4].state = 1 << AX_STATE_SELECTED;
+ update.nodes[8].state = 1 << AX_STATE_SELECTED;
+ update.nodes[12].state = 1 << AX_STATE_SELECTED;
+
+ Init(update);
+
+ ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
+ ASSERT_NE(nullptr, cell.Get());
+
+ ScopedComPtr<IUnknown> table;
+ EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
+
+ ScopedComPtr<IAccessibleTable> result;
+ table.CopyTo(result.GetAddressOf());
+ ASSERT_NE(nullptr, result.Get());
+
+ LONG selectedColumns;
+ EXPECT_EQ(S_OK, result->get_nSelectedColumns(&selectedColumns));
+ EXPECT_EQ(2, selectedColumns);
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetNSelectedRowsZero) {
+ Init(Build3X3Table());
+
+ ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
+ ASSERT_NE(nullptr, cell.Get());
+
+ ScopedComPtr<IUnknown> table;
+ EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
+
+ ScopedComPtr<IAccessibleTable> result;
+ table.CopyTo(result.GetAddressOf());
+ ASSERT_NE(nullptr, result.Get());
+
+ LONG selectedRows;
+ EXPECT_EQ(S_OK, result->get_nSelectedRows(&selectedRows));
+ EXPECT_EQ(0, selectedRows);
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetNSelectedRowsOne) {
+ AXTreeUpdate update = Build3X3Table();
+
+ // 6 == table_row_header_1
+ // 7 == table_cell_1
+ // 8 == table_cell_2
+ update.nodes[6].state = 1 << AX_STATE_SELECTED;
+ update.nodes[7].state = 1 << AX_STATE_SELECTED;
+ update.nodes[8].state = 1 << AX_STATE_SELECTED;
+
+ Init(update);
+
+ ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
+ ASSERT_NE(nullptr, cell.Get());
+
+ ScopedComPtr<IUnknown> table;
+ EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
+
+ ScopedComPtr<IAccessibleTable> result;
+ table.CopyTo(result.GetAddressOf());
+ ASSERT_NE(nullptr, result.Get());
+
+ LONG selectedRows;
+ EXPECT_EQ(S_OK, result->get_nSelectedRows(&selectedRows));
+ EXPECT_EQ(1, selectedRows);
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetNSelectedRowsMany) {
+ AXTreeUpdate update = Build3X3Table();
+
+ // 6 == table_row_header_3
+ // 7 == table_cell_1
+ // 8 == table_cell_2
+ update.nodes[6].state = 1 << AX_STATE_SELECTED;
+ update.nodes[7].state = 1 << AX_STATE_SELECTED;
+ update.nodes[8].state = 1 << AX_STATE_SELECTED;
+
+ // 10 == table_row_header_3
+ // 11 == table_cell_1
+ // 12 == table_cell_2
+ update.nodes[10].state = 1 << AX_STATE_SELECTED;
+ update.nodes[11].state = 1 << AX_STATE_SELECTED;
+ update.nodes[12].state = 1 << AX_STATE_SELECTED;
+
+ Init(update);
+
+ ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
+ ASSERT_NE(nullptr, cell.Get());
+
+ ScopedComPtr<IUnknown> table;
+ EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
+
+ ScopedComPtr<IAccessibleTable> result;
+ table.CopyTo(result.GetAddressOf());
+ ASSERT_NE(nullptr, result.Get());
+
+ LONG selectedRows;
+ EXPECT_EQ(S_OK, result->get_nSelectedRows(&selectedRows));
+ EXPECT_EQ(2, selectedRows);
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetSelectedChildren) {
+ AXTreeUpdate update = Build3X3Table();
+
+ // 7 == table_cell_1
+ // 12 == table_cell_4
+ update.nodes[7].state = 1 << AX_STATE_SELECTED;
+ update.nodes[12].state = 1 << AX_STATE_SELECTED;
+
+ Init(update);
+
+ ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
+ ASSERT_NE(nullptr, cell.Get());
+
+ ScopedComPtr<IUnknown> table;
+ EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
+
+ ScopedComPtr<IAccessibleTable> result;
+ table.CopyTo(result.GetAddressOf());
+ ASSERT_NE(nullptr, result.Get());
+
+ LONG max = 10;
+ LONG* indices;
+ LONG count;
+ EXPECT_EQ(S_OK, result->get_selectedChildren(max, &indices, &count));
+ EXPECT_EQ(2, count);
+ EXPECT_EQ(4, indices[0]);
+ EXPECT_EQ(8, indices[1]);
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetSelectedChildrenZeroMax) {
+ AXTreeUpdate update = Build3X3Table();
+
+ // 7 == table_cell_1
+ // 12 == table_cell_4
+ update.nodes[7].state = 1 << AX_STATE_SELECTED;
+ update.nodes[12].state = 1 << AX_STATE_SELECTED;
+
+ Init(update);
+
+ ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
+ ASSERT_NE(nullptr, cell.Get());
+
+ ScopedComPtr<IUnknown> table;
+ EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
+
+ ScopedComPtr<IAccessibleTable> result;
+ table.CopyTo(result.GetAddressOf());
+ ASSERT_NE(nullptr, result.Get());
+
+ LONG* indices;
+ LONG count;
+ EXPECT_EQ(E_INVALIDARG, result->get_selectedChildren(0, &indices, &count));
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetSelectedColumnsZero) {
+ AXTreeUpdate update = Build3X3Table();
+
+ // 7 == table_cell_1
+ // 11 == table_cell_3
+ update.nodes[7].state = 1 << AX_STATE_SELECTED;
+ update.nodes[11].state = 1 << AX_STATE_SELECTED;
+
+ Init(update);
+
+ ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
+ ASSERT_NE(nullptr, cell.Get());
+
+ ScopedComPtr<IUnknown> table;
+ EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
+
+ ScopedComPtr<IAccessibleTable> result;
+ table.CopyTo(result.GetAddressOf());
+ ASSERT_NE(nullptr, result.Get());
+
+ long max_columns = 10;
+ long* columns;
+ long n_columns;
+ EXPECT_EQ(S_OK,
+ result->get_selectedColumns(max_columns, &columns, &n_columns));
+ EXPECT_EQ(0, n_columns);
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetSelectedColumnsOne) {
+ AXTreeUpdate update = Build3X3Table();
+
+ // 3 == table_column_header_2
+ // 7 == table_cell_1
+ // 11 == table_cell_3
+ update.nodes[3].state = 1 << AX_STATE_SELECTED;
+ update.nodes[7].state = 1 << AX_STATE_SELECTED;
+ update.nodes[11].state = 1 << AX_STATE_SELECTED;
+
+ Init(update);
+
+ ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
+ ASSERT_NE(nullptr, cell.Get());
+
+ ScopedComPtr<IUnknown> table;
+ EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
+
+ ScopedComPtr<IAccessibleTable> result;
+ table.CopyTo(result.GetAddressOf());
+ ASSERT_NE(nullptr, result.Get());
+
+ long max_columns = 10;
+ long* columns;
+ long n_columns;
+ EXPECT_EQ(S_OK,
+ result->get_selectedColumns(max_columns, &columns, &n_columns));
+ EXPECT_EQ(1, n_columns);
+ EXPECT_EQ(1, columns[0]);
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetSelectedColumnsMany) {
+ AXTreeUpdate update = Build3X3Table();
+
+ // 3 == table_column_header_2
+ // 7 == table_cell_1
+ // 11 == table_cell_3
+ update.nodes[3].state = 1 << AX_STATE_SELECTED;
+ update.nodes[7].state = 1 << AX_STATE_SELECTED;
+ update.nodes[11].state = 1 << AX_STATE_SELECTED;
+
+ // 4 == table_column_header_3
+ // 8 == table_cell_2
+ // 12 == table_cell_4
+ update.nodes[4].state = 1 << AX_STATE_SELECTED;
+ update.nodes[8].state = 1 << AX_STATE_SELECTED;
+ update.nodes[12].state = 1 << AX_STATE_SELECTED;
+
+ Init(update);
+
+ ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
+ ASSERT_NE(nullptr, cell.Get());
+
+ ScopedComPtr<IUnknown> table;
+ EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
+
+ ScopedComPtr<IAccessibleTable> result;
+ table.CopyTo(result.GetAddressOf());
+ ASSERT_NE(nullptr, result.Get());
+
+ long max_columns = 10;
+ long* columns;
+ long n_columns;
+ EXPECT_EQ(S_OK,
+ result->get_selectedColumns(max_columns, &columns, &n_columns));
+ EXPECT_EQ(2, n_columns);
+ EXPECT_EQ(1, columns[0]);
+ EXPECT_EQ(2, columns[1]);
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetSelectedRowsZero) {
+ Init(Build3X3Table());
+
+ ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
+ ASSERT_NE(nullptr, cell.Get());
+
+ ScopedComPtr<IUnknown> table;
+ EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
+
+ ScopedComPtr<IAccessibleTable> result;
+ table.CopyTo(result.GetAddressOf());
+ ASSERT_NE(nullptr, result.Get());
+
+ long max_rows = 10;
+ long* rows;
+ long n_rows;
+ EXPECT_EQ(S_OK, result->get_selectedRows(max_rows, &rows, &n_rows));
+ EXPECT_EQ(0, n_rows);
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetSelectedRowsOne) {
+ AXTreeUpdate update = Build3X3Table();
+
+ // 6 == table_row_header_1
+ // 7 == table_cell_1
+ // 8 == table_cell_2
+ update.nodes[6].state = 1 << AX_STATE_SELECTED;
+ update.nodes[7].state = 1 << AX_STATE_SELECTED;
+ update.nodes[8].state = 1 << AX_STATE_SELECTED;
+
+ Init(update);
+
+ ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
+ ASSERT_NE(nullptr, cell.Get());
+
+ ScopedComPtr<IUnknown> table;
+ EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
+
+ ScopedComPtr<IAccessibleTable> result;
+ table.CopyTo(result.GetAddressOf());
+ ASSERT_NE(nullptr, result.Get());
+
+ long max_rows = 10;
+ long* rows;
+ long n_rows;
+ EXPECT_EQ(S_OK, result->get_selectedRows(max_rows, &rows, &n_rows));
+ EXPECT_EQ(1, n_rows);
+ EXPECT_EQ(1, rows[0]);
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableGetSelectedRowsMany) {
+ AXTreeUpdate update = Build3X3Table();
+
+ // 6 == table_row_header_3
+ // 7 == table_cell_1
+ // 8 == table_cell_2
+ update.nodes[6].state = 1 << AX_STATE_SELECTED;
+ update.nodes[7].state = 1 << AX_STATE_SELECTED;
+ update.nodes[8].state = 1 << AX_STATE_SELECTED;
+
+ // 10 == table_row_header_3
+ // 11 == table_cell_1
+ // 12 == table_cell_2
+ update.nodes[10].state = 1 << AX_STATE_SELECTED;
+ update.nodes[11].state = 1 << AX_STATE_SELECTED;
+ update.nodes[12].state = 1 << AX_STATE_SELECTED;
+
+ Init(update);
+
+ ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
+ ASSERT_NE(nullptr, cell.Get());
+
+ ScopedComPtr<IUnknown> table;
+ EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
+
+ ScopedComPtr<IAccessibleTable> result;
+ table.CopyTo(result.GetAddressOf());
+ ASSERT_NE(nullptr, result.Get());
+
+ long max_rows = 10;
+ long* rows;
+ long n_rows;
+ EXPECT_EQ(S_OK, result->get_selectedRows(max_rows, &rows, &n_rows));
+ EXPECT_EQ(2, n_rows);
+ EXPECT_EQ(1, rows[0]);
+ EXPECT_EQ(2, rows[1]);
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableIsColumnSelected) {
+ AXTreeUpdate update = Build3X3Table();
+
+ // 3 == table_column_header_2
+ // 7 == table_cell_1
+ // 11 == table_cell_3
+ update.nodes[3].state = 1 << AX_STATE_SELECTED;
+ update.nodes[7].state = 1 << AX_STATE_SELECTED;
+ update.nodes[11].state = 1 << AX_STATE_SELECTED;
+
+ Init(update);
+
+ ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
+ ASSERT_NE(nullptr, cell.Get());
+
+ ScopedComPtr<IUnknown> table;
+ EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
+
+ ScopedComPtr<IAccessibleTable> result;
+ table.CopyTo(result.GetAddressOf());
+ ASSERT_NE(nullptr, result.Get());
+
+ boolean selected;
+ EXPECT_EQ(S_OK, result->get_isColumnSelected(0, &selected));
+ EXPECT_FALSE(selected);
+
+ EXPECT_EQ(S_OK, result->get_isColumnSelected(1, &selected));
+ EXPECT_TRUE(selected);
+
+ EXPECT_EQ(S_OK, result->get_isColumnSelected(2, &selected));
+ EXPECT_FALSE(selected);
+
+ EXPECT_EQ(S_FALSE, result->get_isColumnSelected(3, &selected));
+ EXPECT_EQ(S_FALSE, result->get_isColumnSelected(-3, &selected));
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableIsRowSelected) {
+ AXTreeUpdate update = Build3X3Table();
+
+ // 6 == table_row_header_3
+ // 7 == table_cell_1
+ // 8 == table_cell_2
+ update.nodes[6].state = 1 << AX_STATE_SELECTED;
+ update.nodes[7].state = 1 << AX_STATE_SELECTED;
+ update.nodes[8].state = 1 << AX_STATE_SELECTED;
+
+ Init(update);
+
+ ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
+ ASSERT_NE(nullptr, cell.Get());
+
+ ScopedComPtr<IUnknown> table;
+ EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
+
+ ScopedComPtr<IAccessibleTable> result;
+ table.CopyTo(result.GetAddressOf());
+ ASSERT_NE(nullptr, result.Get());
+
+ boolean selected;
+ EXPECT_EQ(S_OK, result->get_isRowSelected(0, &selected));
+ EXPECT_FALSE(selected);
+
+ EXPECT_EQ(S_OK, result->get_isRowSelected(1, &selected));
+ EXPECT_TRUE(selected);
+
+ EXPECT_EQ(S_OK, result->get_isRowSelected(2, &selected));
+ EXPECT_FALSE(selected);
+
+ EXPECT_EQ(S_FALSE, result->get_isRowSelected(3, &selected));
+ EXPECT_EQ(S_FALSE, result->get_isRowSelected(-3, &selected));
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIAccessibleTableIsSelected) {
+ AXTreeUpdate update = Build3X3Table();
+
+ // 6 == table_row_header_3
+ // 7 == table_cell_1
+ // 8 == table_cell_2
+ update.nodes[6].state = 1 << AX_STATE_SELECTED;
+ update.nodes[7].state = 1 << AX_STATE_SELECTED;
+ update.nodes[8].state = 1 << AX_STATE_SELECTED;
+
+ Init(update);
+
+ ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
+ ASSERT_NE(nullptr, cell.Get());
+
+ ScopedComPtr<IUnknown> table;
+ EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
+
+ ScopedComPtr<IAccessibleTable> result;
+ table.CopyTo(result.GetAddressOf());
+ ASSERT_NE(nullptr, result.Get());
+
+ boolean selected;
+
+ EXPECT_EQ(S_OK, result->get_isSelected(0, 0, &selected));
+ EXPECT_FALSE(selected);
+
+ EXPECT_EQ(S_OK, result->get_isSelected(0, 1, &selected));
+ EXPECT_FALSE(selected);
+
+ EXPECT_EQ(S_OK, result->get_isSelected(0, 2, &selected));
+ EXPECT_FALSE(selected);
+
+ EXPECT_EQ(S_FALSE, result->get_isSelected(0, 4, &selected));
+
+ EXPECT_EQ(S_OK, result->get_isSelected(1, 0, &selected));
+ EXPECT_TRUE(selected);
+
+ EXPECT_EQ(S_OK, result->get_isSelected(1, 1, &selected));
+ EXPECT_TRUE(selected);
+
+ EXPECT_EQ(S_OK, result->get_isSelected(1, 2, &selected));
+ EXPECT_TRUE(selected);
+
+ EXPECT_EQ(S_FALSE, result->get_isSelected(1, 4, &selected));
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIAccessibleTable2GetSelectedChildrenZero) {
+ Init(Build3X3Table());
+
+ ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
+ ASSERT_NE(nullptr, cell.Get());
+
+ ScopedComPtr<IUnknown> table;
+ EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
+
+ ScopedComPtr<IAccessibleTable2> result;
+ table.CopyTo(result.GetAddressOf());
+ ASSERT_NE(nullptr, result.Get());
+
+ IUnknown** cell_accessibles;
+ LONG count;
+ EXPECT_EQ(S_OK, result->get_selectedCells(&cell_accessibles, &count));
+ EXPECT_EQ(0, count);
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIAccessibleTable2GetSelectedChildren) {
+ AXTreeUpdate update = Build3X3Table();
+
+ // 7 == table_cell_1
+ // 12 == table_cell_4
+ update.nodes[7].state = 1 << AX_STATE_SELECTED;
+ update.nodes[12].state = 1 << AX_STATE_SELECTED;
+
+ Init(update);
+
+ ScopedComPtr<IAccessibleTableCell> cell = GetCellInTable();
+ ASSERT_NE(nullptr, cell.Get());
+
+ ScopedComPtr<IUnknown> table;
+ EXPECT_EQ(S_OK, cell->get_table(table.GetAddressOf()));
+
+ ScopedComPtr<IAccessibleTable2> result;
+ table.CopyTo(result.GetAddressOf());
+ ASSERT_NE(nullptr, result.Get());
+
+ IUnknown** cell_accessibles;
+ LONG count;
+ EXPECT_EQ(S_OK, result->get_selectedCells(&cell_accessibles, &count));
+ EXPECT_EQ(2, count);
+
+ ScopedComPtr<IUnknown> table_cell_1(cell_accessibles[0]);
+ CheckIUnknownHasName(table_cell_1, L"1");
+
+ ScopedComPtr<IUnknown> table_cell_4(cell_accessibles[1]);
+ CheckIUnknownHasName(table_cell_4, L"4");
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIAccessible2GetGroupPosition) {
+ AXNodeData root;
+ root.id = 1;
+ root.AddIntAttribute(AX_ATTR_HIERARCHICAL_LEVEL, 1);
+ root.AddIntAttribute(AX_ATTR_SET_SIZE, 1);
+ root.AddIntAttribute(AX_ATTR_POS_IN_SET, 1);
+ Init(root);
+
+ ScopedComPtr<IAccessible> root_obj(GetRootIAccessible());
+ ScopedComPtr<IAccessible2> iaccessible2 = ToIAccessible2(root_obj);
+ LONG level, similar, position;
+ EXPECT_EQ(S_OK, iaccessible2->get_groupPosition(&level, &similar, &position));
+ EXPECT_EQ(1, level);
+ EXPECT_EQ(1, similar);
+ EXPECT_EQ(1, position);
+
+ EXPECT_EQ(E_INVALIDARG,
+ iaccessible2->get_groupPosition(nullptr, nullptr, nullptr));
+}
+
+TEST_F(AXPlatformNodeWinTest, TestIAccessible2GetLocalizedExtendedRole) {
+ AXNodeData root;
+ root.id = 1;
+ root.AddStringAttribute(AX_ATTR_ROLE_DESCRIPTION, "extended role");
+ Init(root);
+
+ ScopedComPtr<IAccessible> root_obj(GetRootIAccessible());
+ ScopedComPtr<IAccessible2> iaccessible2 = ToIAccessible2(root_obj);
+ ScopedBstr role;
+ EXPECT_EQ(S_OK, iaccessible2->get_localizedExtendedRole(role.Receive()));
+ EXPECT_STREQ(L"extended role", role);
+}
+
} // namespace ui
diff --git a/chromium/ui/accessibility/platform/ax_snapshot_node_android_platform.cc b/chromium/ui/accessibility/platform/ax_snapshot_node_android_platform.cc
index 1d62fefc5ef..4d0bfe41d93 100644
--- a/chromium/ui/accessibility/platform/ax_snapshot_node_android_platform.cc
+++ b/chromium/ui/accessibility/platform/ax_snapshot_node_android_platform.cc
@@ -23,7 +23,7 @@ namespace {
bool HasFocusableChild(const AXNode* node) {
for (auto* child : node->children()) {
- if ((child->data().state & ui::AX_STATE_FOCUSABLE) != 0 ||
+ if (child->data().HasState(AX_STATE_FOCUSABLE) ||
HasFocusableChild(child)) {
return true;
}
@@ -40,13 +40,13 @@ bool HasOnlyTextChildren(const AXNode* node) {
}
// TODO(muyuanli): share with BrowserAccessibility.
-bool IsSimpleTextControl(AXRole role, uint32_t state) {
- switch (role) {
- case ui::AX_ROLE_COMBO_BOX:
- case ui::AX_ROLE_SEARCH_BOX:
+bool IsSimpleTextControl(const AXNode* node, uint32_t state) {
+ switch (node->data().role) {
+ case AX_ROLE_COMBO_BOX:
+ case AX_ROLE_SEARCH_BOX:
return true;
- case ui::AX_ROLE_TEXT_FIELD:
- return (state & ui::AX_STATE_RICHLY_EDITABLE) == 0;
+ case AX_ROLE_TEXT_FIELD:
+ return !node->data().HasState(AX_STATE_RICHLY_EDITABLE);
default:
return false;
}
@@ -54,14 +54,13 @@ bool IsSimpleTextControl(AXRole role, uint32_t state) {
bool IsRichTextEditable(const AXNode* node) {
const AXNode* parent = node->parent();
- return (node->data().state & ui::AX_STATE_RICHLY_EDITABLE) != 0 &&
- (!parent ||
- (parent->data().state & ui::AX_STATE_RICHLY_EDITABLE) == 0);
+ return node->data().HasState(AX_STATE_RICHLY_EDITABLE) &&
+ (!parent || !parent->data().HasState(AX_STATE_RICHLY_EDITABLE));
}
bool IsNativeTextControl(const AXNode* node) {
const std::string& html_tag =
- node->data().GetStringAttribute(ui::AX_ATTR_HTML_TAG);
+ node->data().GetStringAttribute(AX_ATTR_HTML_TAG);
if (html_tag == "input") {
std::string input_type;
if (!node->data().GetHtmlAttribute("type", &input_type))
@@ -83,15 +82,15 @@ bool IsLeaf(const AXNode* node) {
}
switch (node->data().role) {
- case ui::AX_ROLE_IMAGE:
- case ui::AX_ROLE_METER:
- case ui::AX_ROLE_SCROLL_BAR:
- case ui::AX_ROLE_SLIDER:
- case ui::AX_ROLE_SPLITTER:
- case ui::AX_ROLE_PROGRESS_INDICATOR:
- case ui::AX_ROLE_DATE:
- case ui::AX_ROLE_DATE_TIME:
- case ui::AX_ROLE_INPUT_TIME:
+ case AX_ROLE_IMAGE:
+ case AX_ROLE_METER:
+ case AX_ROLE_SCROLL_BAR:
+ case AX_ROLE_SLIDER:
+ case AX_ROLE_SPLITTER:
+ case AX_ROLE_PROGRESS_INDICATOR:
+ case AX_ROLE_DATE:
+ case AX_ROLE_DATE_TIME:
+ case AX_ROLE_INPUT_TIME:
return true;
default:
return false;
@@ -100,7 +99,7 @@ bool IsLeaf(const AXNode* node) {
base::string16 GetInnerText(const AXNode* node) {
if (node->IsTextNode()) {
- return node->data().GetString16Attribute(ui::AX_ATTR_NAME);
+ return node->data().GetString16Attribute(AX_ATTR_NAME);
}
base::string16 text;
for (auto* child : node->children()) {
@@ -110,16 +109,16 @@ base::string16 GetInnerText(const AXNode* node) {
}
base::string16 GetValue(const AXNode* node, bool show_password) {
- base::string16 value = node->data().GetString16Attribute(ui::AX_ATTR_VALUE);
+ base::string16 value = node->data().GetString16Attribute(AX_ATTR_VALUE);
if (value.empty() &&
- (IsSimpleTextControl(node->data().role, node->data().state) ||
+ (IsSimpleTextControl(node, node->data().state) ||
IsRichTextEditable(node)) &&
!IsNativeTextControl(node)) {
value = GetInnerText(node);
}
- if ((node->data().state & ui::AX_STATE_PROTECTED) != 0) {
+ if (node->data().HasState(AX_STATE_PROTECTED)) {
if (!show_password) {
value = base::string16(value.size(), kSecurePasswordBullet);
}
@@ -130,8 +129,8 @@ base::string16 GetValue(const AXNode* node, bool show_password) {
bool HasOnlyTextAndImageChildren(const AXNode* node) {
for (auto* child : node->children()) {
- if (child->data().role != ui::AX_ROLE_STATIC_TEXT &&
- child->data().role != ui::AX_ROLE_IMAGE) {
+ if (child->data().role != AX_ROLE_STATIC_TEXT &&
+ child->data().role != AX_ROLE_IMAGE) {
return false;
}
}
@@ -139,24 +138,24 @@ bool HasOnlyTextAndImageChildren(const AXNode* node) {
}
bool IsFocusable(const AXNode* node) {
- if (node->data().role == ui::AX_ROLE_IFRAME ||
- node->data().role == ui::AX_ROLE_IFRAME_PRESENTATIONAL ||
- (node->data().role == ui::AX_ROLE_ROOT_WEB_AREA && node->parent())) {
- return node->data().HasStringAttribute(ui::AX_ATTR_NAME);
+ if (node->data().role == AX_ROLE_IFRAME ||
+ node->data().role == AX_ROLE_IFRAME_PRESENTATIONAL ||
+ (node->data().role == AX_ROLE_ROOT_WEB_AREA && node->parent())) {
+ return node->data().HasStringAttribute(AX_ATTR_NAME);
}
- return (node->data().state & ui::AX_STATE_FOCUSABLE) != 0;
+ return node->data().HasState(AX_STATE_FOCUSABLE);
}
base::string16 GetText(const AXNode* node, bool show_password) {
- if (node->data().role == ui::AX_ROLE_WEB_AREA ||
- node->data().role == ui::AX_ROLE_IFRAME ||
- node->data().role == ui::AX_ROLE_IFRAME_PRESENTATIONAL) {
+ if (node->data().role == AX_ROLE_WEB_AREA ||
+ node->data().role == AX_ROLE_IFRAME ||
+ node->data().role == AX_ROLE_IFRAME_PRESENTATIONAL) {
return base::string16();
}
- if (node->data().role == ui::AX_ROLE_LIST_ITEM &&
- node->data().GetIntAttribute(ui::AX_ATTR_NAME_FROM) ==
- ui::AX_NAME_FROM_CONTENTS) {
+ if (node->data().role == AX_ROLE_LIST_ITEM &&
+ node->data().GetIntAttribute(AX_ATTR_NAME_FROM) ==
+ AX_NAME_FROM_CONTENTS) {
if (node->child_count() > 0 && !HasOnlyTextChildren(node))
return base::string16();
}
@@ -164,22 +163,22 @@ base::string16 GetText(const AXNode* node, bool show_password) {
base::string16 value = GetValue(node, show_password);
if (!value.empty()) {
- if ((node->data().state & ui::AX_STATE_EDITABLE) != 0)
+ if (node->data().HasState(AX_STATE_EDITABLE))
return value;
switch (node->data().role) {
- case ui::AX_ROLE_COMBO_BOX:
- case ui::AX_ROLE_POP_UP_BUTTON:
- case ui::AX_ROLE_TEXT_FIELD:
+ case AX_ROLE_COMBO_BOX:
+ case AX_ROLE_POP_UP_BUTTON:
+ case AX_ROLE_TEXT_FIELD:
return value;
default:
break;
}
}
- if (node->data().role == ui::AX_ROLE_COLOR_WELL) {
+ if (node->data().role == AX_ROLE_COLOR_WELL) {
unsigned int color = static_cast<unsigned int>(
- node->data().GetIntAttribute(ui::AX_ATTR_COLOR_VALUE));
+ node->data().GetIntAttribute(AX_ATTR_COLOR_VALUE));
unsigned int red = color >> 16 & 0xFF;
unsigned int green = color >> 8 & 0xFF;
unsigned int blue = color >> 0 & 0xFF;
@@ -187,9 +186,9 @@ base::string16 GetText(const AXNode* node, bool show_password) {
base::StringPrintf("#%02X%02X%02X", red, green, blue));
}
- base::string16 text = node->data().GetString16Attribute(ui::AX_ATTR_NAME);
+ base::string16 text = node->data().GetString16Attribute(AX_ATTR_NAME);
base::string16 description =
- node->data().GetString16Attribute(ui::AX_ATTR_DESCRIPTION);
+ node->data().GetString16Attribute(AX_ATTR_DESCRIPTION);
if (!description.empty()) {
if (!text.empty())
text += base::ASCIIToUTF16(" ");
@@ -199,7 +198,7 @@ base::string16 GetText(const AXNode* node, bool show_password) {
if (text.empty())
text = value;
- if (node->data().role == ui::AX_ROLE_ROOT_WEB_AREA)
+ if (node->data().role == AX_ROLE_ROOT_WEB_AREA)
return text;
if (text.empty() &&
@@ -211,8 +210,8 @@ base::string16 GetText(const AXNode* node, bool show_password) {
}
if (text.empty() && (AXSnapshotNodeAndroid::AXRoleIsLink(node->data().role) ||
- node->data().role == ui::AX_ROLE_IMAGE)) {
- base::string16 url = node->data().GetString16Attribute(ui::AX_ATTR_URL);
+ node->data().role == AX_ROLE_IMAGE)) {
+ base::string16 url = node->data().GetString16Attribute(AX_ATTR_URL);
text = AXSnapshotNodeAndroid::AXUrlBaseText(url);
}
return text;
@@ -271,7 +270,7 @@ AX_EXPORT AXSnapshotNodeAndroid::~AXSnapshotNodeAndroid() = default;
AX_EXPORT std::unique_ptr<AXSnapshotNodeAndroid> AXSnapshotNodeAndroid::Create(
const AXTreeUpdate& update,
bool show_password) {
- auto tree = base::MakeUnique<ui::AXSerializableTree>();
+ auto tree = base::MakeUnique<AXSerializableTree>();
if (!tree->Unserialize(update)) {
LOG(FATAL) << tree->error();
}
@@ -286,7 +285,7 @@ AX_EXPORT std::unique_ptr<AXSnapshotNodeAndroid> AXSnapshotNodeAndroid::Create(
// static
AX_EXPORT bool AXSnapshotNodeAndroid::AXRoleIsLink(AXRole role) {
- return role == ui::AX_ROLE_LINK || role == ui::AX_ROLE_IMAGE_MAP_LINK;
+ return role == AX_ROLE_LINK;
}
// static
@@ -315,55 +314,55 @@ AX_EXPORT const char* AXSnapshotNodeAndroid::AXRoleToAndroidClassName(
AXRole role,
bool has_parent) {
switch (role) {
- case ui::AX_ROLE_SEARCH_BOX:
- case ui::AX_ROLE_SPIN_BUTTON:
- case ui::AX_ROLE_TEXT_FIELD:
- return ui::kAXEditTextClassname;
- case ui::AX_ROLE_SLIDER:
- return ui::kAXSeekBarClassname;
- case ui::AX_ROLE_COLOR_WELL:
- case ui::AX_ROLE_COMBO_BOX:
- case ui::AX_ROLE_DATE:
- case ui::AX_ROLE_POP_UP_BUTTON:
- case ui::AX_ROLE_INPUT_TIME:
- return ui::kAXSpinnerClassname;
- case ui::AX_ROLE_BUTTON:
- case ui::AX_ROLE_MENU_BUTTON:
- return ui::kAXButtonClassname;
- case ui::AX_ROLE_CHECK_BOX:
- case ui::AX_ROLE_SWITCH:
- return ui::kAXCheckBoxClassname;
- case ui::AX_ROLE_RADIO_BUTTON:
- return ui::kAXRadioButtonClassname;
- case ui::AX_ROLE_TOGGLE_BUTTON:
- return ui::kAXToggleButtonClassname;
- case ui::AX_ROLE_CANVAS:
- case ui::AX_ROLE_IMAGE:
- case ui::AX_ROLE_SVG_ROOT:
- return ui::kAXImageClassname;
- case ui::AX_ROLE_METER:
- case ui::AX_ROLE_PROGRESS_INDICATOR:
- return ui::kAXProgressBarClassname;
- case ui::AX_ROLE_TAB_LIST:
- return ui::kAXTabWidgetClassname;
- case ui::AX_ROLE_GRID:
- case ui::AX_ROLE_TREE_GRID:
- case ui::AX_ROLE_TABLE:
- return ui::kAXGridViewClassname;
- case ui::AX_ROLE_LIST:
- case ui::AX_ROLE_LIST_BOX:
- case ui::AX_ROLE_DESCRIPTION_LIST:
- return ui::kAXListViewClassname;
- case ui::AX_ROLE_DIALOG:
- return ui::kAXDialogClassname;
- case ui::AX_ROLE_ROOT_WEB_AREA:
- return has_parent ? ui::kAXViewClassname : ui::kAXWebViewClassname;
- case ui::AX_ROLE_MENU_ITEM:
- case ui::AX_ROLE_MENU_ITEM_CHECK_BOX:
- case ui::AX_ROLE_MENU_ITEM_RADIO:
- return ui::kAXMenuItemClassname;
+ case AX_ROLE_SEARCH_BOX:
+ case AX_ROLE_SPIN_BUTTON:
+ case AX_ROLE_TEXT_FIELD:
+ return kAXEditTextClassname;
+ case AX_ROLE_SLIDER:
+ return kAXSeekBarClassname;
+ case AX_ROLE_COLOR_WELL:
+ case AX_ROLE_COMBO_BOX:
+ case AX_ROLE_DATE:
+ case AX_ROLE_POP_UP_BUTTON:
+ case AX_ROLE_INPUT_TIME:
+ return kAXSpinnerClassname;
+ case AX_ROLE_BUTTON:
+ case AX_ROLE_MENU_BUTTON:
+ return kAXButtonClassname;
+ case AX_ROLE_CHECK_BOX:
+ case AX_ROLE_SWITCH:
+ return kAXCheckBoxClassname;
+ case AX_ROLE_RADIO_BUTTON:
+ return kAXRadioButtonClassname;
+ case AX_ROLE_TOGGLE_BUTTON:
+ return kAXToggleButtonClassname;
+ case AX_ROLE_CANVAS:
+ case AX_ROLE_IMAGE:
+ case AX_ROLE_SVG_ROOT:
+ return kAXImageClassname;
+ case AX_ROLE_METER:
+ case AX_ROLE_PROGRESS_INDICATOR:
+ return kAXProgressBarClassname;
+ case AX_ROLE_TAB_LIST:
+ return kAXTabWidgetClassname;
+ case AX_ROLE_GRID:
+ case AX_ROLE_TREE_GRID:
+ case AX_ROLE_TABLE:
+ return kAXGridViewClassname;
+ case AX_ROLE_LIST:
+ case AX_ROLE_LIST_BOX:
+ case AX_ROLE_DESCRIPTION_LIST:
+ return kAXListViewClassname;
+ case AX_ROLE_DIALOG:
+ return kAXDialogClassname;
+ case AX_ROLE_ROOT_WEB_AREA:
+ return has_parent ? kAXViewClassname : kAXWebViewClassname;
+ case AX_ROLE_MENU_ITEM:
+ case AX_ROLE_MENU_ITEM_CHECK_BOX:
+ case AX_ROLE_MENU_ITEM_RADIO:
+ return kAXMenuItemClassname;
default:
- return ui::kAXViewClassname;
+ return kAXViewClassname;
}
}
@@ -372,7 +371,7 @@ std::unique_ptr<AXSnapshotNodeAndroid>
AXSnapshotNodeAndroid::WalkAXTreeDepthFirst(
const AXNode* node,
gfx::Rect rect,
- const ui::AXTreeUpdate& update,
+ const AXTreeUpdate& update,
const AXTree* tree,
AXSnapshotNodeAndroid::WalkAXTreeConfig& config) {
auto result =
@@ -390,21 +389,20 @@ AXSnapshotNodeAndroid::WalkAXTreeDepthFirst(
result->line_through = 0;
result->underline = 0;
- if (node->data().HasFloatAttribute(ui::AX_ATTR_FONT_SIZE)) {
+ if (node->data().HasFloatAttribute(AX_ATTR_FONT_SIZE)) {
gfx::RectF text_size_rect(
- 0, 0, 1, node->data().GetFloatAttribute(ui::AX_ATTR_FONT_SIZE));
+ 0, 0, 1, node->data().GetFloatAttribute(AX_ATTR_FONT_SIZE));
gfx::Rect scaled_text_size_rect =
gfx::ToEnclosingRect(tree->RelativeToTreeBounds(node, text_size_rect));
result->text_size = scaled_text_size_rect.height();
- const int text_style = node->data().GetIntAttribute(ui::AX_ATTR_TEXT_STYLE);
- result->color = node->data().GetIntAttribute(ui::AX_ATTR_COLOR);
- result->bgcolor =
- node->data().GetIntAttribute(ui::AX_ATTR_BACKGROUND_COLOR);
- result->bold = (text_style & ui::AX_TEXT_STYLE_BOLD) != 0;
- result->italic = (text_style & ui::AX_TEXT_STYLE_ITALIC) != 0;
- result->line_through = (text_style & ui::AX_TEXT_STYLE_LINE_THROUGH) != 0;
- result->underline = (text_style & ui::AX_TEXT_STYLE_UNDERLINE) != 0;
+ const int text_style = node->data().GetIntAttribute(AX_ATTR_TEXT_STYLE);
+ result->color = node->data().GetIntAttribute(AX_ATTR_COLOR);
+ result->bgcolor = node->data().GetIntAttribute(AX_ATTR_BACKGROUND_COLOR);
+ result->bold = (text_style & AX_TEXT_STYLE_BOLD) != 0;
+ result->italic = (text_style & AX_TEXT_STYLE_ITALIC) != 0;
+ result->line_through = (text_style & AX_TEXT_STYLE_LINE_THROUGH) != 0;
+ result->underline = (text_style & AX_TEXT_STYLE_UNDERLINE) != 0;
}
const gfx::Rect& absolute_rect =
diff --git a/chromium/ui/accessibility/platform/ax_snapshot_node_android_platform.h b/chromium/ui/accessibility/platform/ax_snapshot_node_android_platform.h
index 7314a2e0e03..be01b51bcee 100644
--- a/chromium/ui/accessibility/platform/ax_snapshot_node_android_platform.h
+++ b/chromium/ui/accessibility/platform/ax_snapshot_node_android_platform.h
@@ -71,7 +71,7 @@ struct AXSnapshotNodeAndroid {
static std::unique_ptr<AXSnapshotNodeAndroid> WalkAXTreeDepthFirst(
const AXNode* node,
gfx::Rect rect,
- const ui::AXTreeUpdate& update,
+ const AXTreeUpdate& update,
const AXTree* tree,
WalkAXTreeConfig& config);
diff --git a/chromium/ui/accessibility/platform/ax_system_caret_win.cc b/chromium/ui/accessibility/platform/ax_system_caret_win.cc
index d09bc04b8f7..b4a1d38c872 100644
--- a/chromium/ui/accessibility/platform/ax_system_caret_win.cc
+++ b/chromium/ui/accessibility/platform/ax_system_caret_win.cc
@@ -55,8 +55,8 @@ const AXNodeData& AXSystemCaretWin::GetData() const {
return data_;
}
-const ui::AXTreeData& AXSystemCaretWin::GetTreeData() const {
- CR_DEFINE_STATIC_LOCAL(ui::AXTreeData, empty_data, ());
+const AXTreeData& AXSystemCaretWin::GetTreeData() const {
+ CR_DEFINE_STATIC_LOCAL(AXTreeData, empty_data, ());
return empty_data;
}
@@ -103,8 +103,7 @@ AXSystemCaretWin::GetTargetForNativeAccessibilityEvent() {
return event_target_;
}
-bool AXSystemCaretWin::AccessibilityPerformAction(
- const ui::AXActionData& data) {
+bool AXSystemCaretWin::AccessibilityPerformAction(const AXActionData& data) {
return false;
}
diff --git a/chromium/ui/accessibility/platform/ax_system_caret_win.h b/chromium/ui/accessibility/platform/ax_system_caret_win.h
index ec093e48e29..6c2d51dfdf8 100644
--- a/chromium/ui/accessibility/platform/ax_system_caret_win.h
+++ b/chromium/ui/accessibility/platform/ax_system_caret_win.h
@@ -35,7 +35,7 @@ class AX_EXPORT AXSystemCaretWin : private AXPlatformNodeDelegate {
private:
// |AXPlatformNodeDelegate| members.
const AXNodeData& GetData() const override;
- const ui::AXTreeData& GetTreeData() const override;
+ const AXTreeData& GetTreeData() const override;
gfx::NativeWindow GetTopLevelWidget() override;
gfx::NativeViewAccessible GetParent() override;
int GetChildCount() override;
@@ -43,9 +43,9 @@ class AX_EXPORT AXSystemCaretWin : private AXPlatformNodeDelegate {
gfx::Rect GetScreenBoundsRect() const override;
gfx::NativeViewAccessible HitTestSync(int x, int y) override;
gfx::NativeViewAccessible GetFocus() override;
- ui::AXPlatformNode* GetFromNodeID(int32_t id) override;
+ AXPlatformNode* GetFromNodeID(int32_t id) override;
gfx::AcceleratedWidget GetTargetForNativeAccessibilityEvent() override;
- bool AccessibilityPerformAction(const ui::AXActionData& data) override;
+ bool AccessibilityPerformAction(const AXActionData& data) override;
bool ShouldIgnoreHoveredStateForTesting() override;
AXPlatformNodeWin* caret_;
diff --git a/chromium/ui/accessibility/platform/test_ax_node_wrapper.cc b/chromium/ui/accessibility/platform/test_ax_node_wrapper.cc
index e0b153ef512..bfb7b4f1d99 100644
--- a/chromium/ui/accessibility/platform/test_ax_node_wrapper.cc
+++ b/chromium/ui/accessibility/platform/test_ax_node_wrapper.cc
@@ -24,8 +24,8 @@ class TestAXTreeDelegate : public AXTreeDelegate {
const AXNodeData& old_node_data,
const AXNodeData& new_node_data) override {}
void OnTreeDataChanged(AXTree* tree,
- const ui::AXTreeData& old_data,
- const ui::AXTreeData& new_data) override {}
+ const AXTreeData& old_data,
+ const AXTreeData& new_data) override {}
void OnNodeWillBeDeleted(AXTree* tree, AXNode* node) override {
auto iter = g_node_to_wrapper_map.find(node);
if (iter != g_node_to_wrapper_map.end()) {
@@ -76,7 +76,7 @@ const AXNodeData& TestAXNodeWrapper::GetData() const {
return node_->data();
}
-const ui::AXTreeData& TestAXNodeWrapper::GetTreeData() const {
+const AXTreeData& TestAXNodeWrapper::GetTreeData() const {
return tree_->data();
}
@@ -171,8 +171,7 @@ TestAXNodeWrapper::GetTargetForNativeAccessibilityEvent() {
return gfx::kNullAcceleratedWidget;
}
-bool TestAXNodeWrapper::AccessibilityPerformAction(
- const ui::AXActionData& data) {
+bool TestAXNodeWrapper::AccessibilityPerformAction(const AXActionData& data) {
return true;
}
diff --git a/chromium/ui/accessibility/platform/test_ax_node_wrapper.h b/chromium/ui/accessibility/platform/test_ax_node_wrapper.h
index 9ce258e31ed..a65b0c05281 100644
--- a/chromium/ui/accessibility/platform/test_ax_node_wrapper.h
+++ b/chromium/ui/accessibility/platform/test_ax_node_wrapper.h
@@ -32,7 +32,7 @@ class TestAXNodeWrapper : public AXPlatformNodeDelegate {
// AXPlatformNodeDelegate.
const AXNodeData& GetData() const override;
- const ui::AXTreeData& GetTreeData() const override;
+ const AXTreeData& GetTreeData() const override;
gfx::NativeWindow GetTopLevelWidget() override;
gfx::NativeViewAccessible GetParent() override;
int GetChildCount() override;
@@ -40,9 +40,9 @@ class TestAXNodeWrapper : public AXPlatformNodeDelegate {
gfx::Rect GetScreenBoundsRect() const override;
gfx::NativeViewAccessible HitTestSync(int x, int y) override;
gfx::NativeViewAccessible GetFocus() override;
- ui::AXPlatformNode* GetFromNodeID(int32_t id) override;
+ AXPlatformNode* GetFromNodeID(int32_t id) override;
gfx::AcceleratedWidget GetTargetForNativeAccessibilityEvent() override;
- bool AccessibilityPerformAction(const ui::AXActionData& data) override;
+ bool AccessibilityPerformAction(const AXActionData& data) override;
bool ShouldIgnoreHoveredStateForTesting() override;
private:
diff --git a/chromium/ui/android/BUILD.gn b/chromium/ui/android/BUILD.gn
index df557616dcc..cbf034ca945 100644
--- a/chromium/ui/android/BUILD.gn
+++ b/chromium/ui/android/BUILD.gn
@@ -34,17 +34,15 @@ component("android") {
"resources/resource.cc",
"resources/resource.h",
"resources/resource_factory.cc",
- "resources/resource_factory.h",
"resources/resource_manager.h",
"resources/resource_manager_impl.cc",
"resources/resource_manager_impl.h",
"resources/ui_resource_provider.h",
"screen_android.h",
"ui_android_export.h",
- "ui_android_jni_registrar.cc",
- "ui_android_jni_registrar.h",
"view_android.cc",
"view_android.h",
+ "view_android_observer.h",
"view_client.cc",
"view_client.h",
"window_android.cc",
@@ -60,11 +58,11 @@ component("android") {
":ui_android_jni_headers",
"//base",
"//cc",
- "//cc/surfaces",
"//components/viz/common",
"//components/viz/host",
"//components/viz/service",
"//skia",
+ "//third_party/WebKit/public:blink_headers",
"//ui/base",
"//ui/display",
"//ui/events",
@@ -210,6 +208,7 @@ android_library("ui_full_java") {
"java/src/org/chromium/ui/base/SPenSupport.java",
"java/src/org/chromium/ui/base/TouchDevice.java",
"java/src/org/chromium/ui/base/ViewAndroidDelegate.java",
+ "java/src/org/chromium/ui/base/ViewUtils.java",
"java/src/org/chromium/ui/base/WindowAndroid.java",
"java/src/org/chromium/ui/display/DisplayAndroid.java",
"java/src/org/chromium/ui/display/DisplayAndroidManager.java",
@@ -251,7 +250,25 @@ android_library("ui_full_java") {
"//third_party/android_tools:android_support_annotations_java",
"//third_party/android_tools:android_support_v7_appcompat_java",
]
- srcjar_deps = [ ":java_enums_srcjar" ]
+ srcjar_deps = [
+ ":java_enums_srcjar",
+ "//third_party/WebKit/public:blink_cursor_type_java_enums_srcjar",
+ ]
+}
+
+android_library("ui_java_test_support") {
+ testonly = true
+ java_files = [
+ "javatests/src/org/chromium/ui/test/util/UiDisableIf.java",
+ "javatests/src/org/chromium/ui/test/util/UiDisableIfSkipCheck.java",
+ "javatests/src/org/chromium/ui/test/util/UiRestriction.java",
+ "javatests/src/org/chromium/ui/test/util/UiRestrictionSkipCheck.java",
+ ]
+ deps = [
+ ":ui_java",
+ "//base:base_java",
+ "//base:base_java_test_support",
+ ]
}
junit_binary("ui_junit_tests") {
diff --git a/chromium/ui/android/DEPS b/chromium/ui/android/DEPS
index 410819d2634..54c50b66600 100644
--- a/chromium/ui/android/DEPS
+++ b/chromium/ui/android/DEPS
@@ -3,15 +3,16 @@ include_rules = [
"+cc/output",
"+cc/resources",
"+cc/scheduler/begin_frame_source.h",
- "+cc/surfaces",
"+cc/test/stub_layer_tree_host_client.h",
"+cc/test/test_task_graph_runner.h",
"+cc/trees/layer_tree_host.h",
"+components/viz/common",
"+components/viz/host",
"+components/viz/service/frame_sinks",
+ "+components/viz/service/surfaces",
"+jni",
"+skia/ext",
+ "+third_party/WebKit/public/platform/WebCursorInfo.h",
"+third_party/skia",
"+ui/base",
"+ui/display",
diff --git a/chromium/ui/android/OWNERS b/chromium/ui/android/OWNERS
index dd1d5e5064c..8dd68c8015f 100644
--- a/chromium/ui/android/OWNERS
+++ b/chromium/ui/android/OWNERS
@@ -10,3 +10,4 @@ boliu@chromium.org
jinsukkim@chromium.org
# COMPONENT: UI
+# OS: Android
diff --git a/chromium/ui/android/delegated_frame_host_android.cc b/chromium/ui/android/delegated_frame_host_android.cc
index 847f15a12e8..7cc00f5422e 100644
--- a/chromium/ui/android/delegated_frame_host_android.cc
+++ b/chromium/ui/android/delegated_frame_host_android.cc
@@ -10,11 +10,11 @@
#include "cc/layers/solid_color_layer.h"
#include "cc/layers/surface_layer.h"
#include "cc/output/compositor_frame.h"
-#include "cc/output/copy_output_result.h"
-#include "cc/surfaces/surface.h"
+#include "components/viz/common/quads/copy_output_result.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
+#include "components/viz/service/surfaces/surface.h"
#include "ui/android/view_android.h"
#include "ui/android/window_android_compositor.h"
#include "ui/display/display.h"
@@ -26,7 +26,7 @@ namespace ui {
namespace {
scoped_refptr<cc::SurfaceLayer> CreateSurfaceLayer(
- cc::SurfaceManager* surface_manager,
+ viz::SurfaceManager* surface_manager,
viz::SurfaceInfo surface_info,
bool surface_opaque) {
// manager must outlive compositors using it.
@@ -42,8 +42,8 @@ scoped_refptr<cc::SurfaceLayer> CreateSurfaceLayer(
void CopyOutputRequestCallback(
scoped_refptr<cc::Layer> readback_layer,
- cc::CopyOutputRequest::CopyOutputRequestCallback result_callback,
- std::unique_ptr<cc::CopyOutputResult> copy_output_result) {
+ viz::CopyOutputRequest::CopyOutputRequestCallback result_callback,
+ std::unique_ptr<viz::CopyOutputResult> copy_output_result) {
readback_layer->RemoveFromParent();
std::move(result_callback).Run(std::move(copy_output_result));
}
@@ -65,7 +65,7 @@ DelegatedFrameHostAndroid::DelegatedFrameHostAndroid(
DCHECK(view_);
DCHECK(client_);
- frame_sink_manager_->surface_manager()->RegisterFrameSinkId(frame_sink_id_);
+ host_frame_sink_manager_->RegisterFrameSinkId(frame_sink_id_, this);
CreateNewCompositorFrameSinkSupport();
}
@@ -73,7 +73,7 @@ DelegatedFrameHostAndroid::~DelegatedFrameHostAndroid() {
DestroyDelegatedContent();
DetachFromCompositor();
support_.reset();
- frame_sink_manager_->surface_manager()->InvalidateFrameSinkId(frame_sink_id_);
+ host_frame_sink_manager_->InvalidateFrameSinkId(frame_sink_id_);
}
void DelegatedFrameHostAndroid::SubmitCompositorFrame(
@@ -103,7 +103,7 @@ void DelegatedFrameHostAndroid::SubmitCompositorFrame(
}
void DelegatedFrameHostAndroid::DidNotProduceFrame(
- const cc::BeginFrameAck& ack) {
+ const viz::BeginFrameAck& ack) {
support_->DidNotProduceFrame(ack);
}
@@ -114,7 +114,7 @@ viz::FrameSinkId DelegatedFrameHostAndroid::GetFrameSinkId() const {
void DelegatedFrameHostAndroid::RequestCopyOfSurface(
WindowAndroidCompositor* compositor,
const gfx::Rect& src_subrect_in_pixel,
- cc::CopyOutputRequest::CopyOutputRequestCallback result_callback) {
+ viz::CopyOutputRequest::CopyOutputRequestCallback result_callback) {
DCHECK(surface_info_.is_valid());
DCHECK(!result_callback.is_null());
@@ -123,8 +123,8 @@ void DelegatedFrameHostAndroid::RequestCopyOfSurface(
!has_transparent_background_);
readback_layer->SetHideLayerAndSubtree(true);
compositor->AttachLayerForReadback(readback_layer);
- std::unique_ptr<cc::CopyOutputRequest> copy_output_request =
- cc::CopyOutputRequest::CreateRequest(
+ std::unique_ptr<viz::CopyOutputRequest> copy_output_request =
+ viz::CopyOutputRequest::CreateRequest(
base::BindOnce(&CopyOutputRequestCallback, readback_layer,
std::move(result_callback)));
@@ -176,17 +176,17 @@ void DelegatedFrameHostAndroid::DetachFromCompositor() {
}
void DelegatedFrameHostAndroid::DidReceiveCompositorFrameAck(
- const std::vector<cc::ReturnedResource>& resources) {
+ const std::vector<viz::ReturnedResource>& resources) {
client_->ReclaimResources(resources);
client_->DidReceiveCompositorFrameAck();
}
-void DelegatedFrameHostAndroid::OnBeginFrame(const cc::BeginFrameArgs& args) {
+void DelegatedFrameHostAndroid::OnBeginFrame(const viz::BeginFrameArgs& args) {
begin_frame_source_.OnBeginFrame(args);
}
void DelegatedFrameHostAndroid::ReclaimResources(
- const std::vector<cc::ReturnedResource>& resources) {
+ const std::vector<viz::ReturnedResource>& resources) {
client_->ReclaimResources(resources);
}
@@ -202,14 +202,18 @@ void DelegatedFrameHostAndroid::OnNeedsBeginFrames(bool needs_begin_frames) {
support_->SetNeedsBeginFrame(needs_begin_frames);
}
+void DelegatedFrameHostAndroid::OnFirstSurfaceActivation(
+ const viz::SurfaceInfo& surface_info) {
+ // TODO(fsamuel): Once surface synchronization is turned on, the fallback
+ // surface should be set here.
+}
+
void DelegatedFrameHostAndroid::CreateNewCompositorFrameSinkSupport() {
constexpr bool is_root = false;
- constexpr bool handles_frame_sink_id_invalidation = false;
constexpr bool needs_sync_points = true;
support_.reset();
support_ = host_frame_sink_manager_->CreateCompositorFrameSinkSupport(
- this, frame_sink_id_, is_root, handles_frame_sink_id_invalidation,
- needs_sync_points);
+ this, frame_sink_id_, is_root, needs_sync_points);
}
viz::SurfaceId DelegatedFrameHostAndroid::SurfaceId() const {
diff --git a/chromium/ui/android/delegated_frame_host_android.h b/chromium/ui/android/delegated_frame_host_android.h
index 3d2605cedc8..00a03ae167a 100644
--- a/chromium/ui/android/delegated_frame_host_android.h
+++ b/chromium/ui/android/delegated_frame_host_android.h
@@ -7,9 +7,10 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/resources/returned_resource.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/resources/returned_resource.h"
#include "components/viz/common/surfaces/surface_info.h"
+#include "components/viz/host/host_frame_sink_client.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support_client.h"
#include "ui/android/ui_android_export.h"
@@ -33,14 +34,16 @@ class WindowAndroidCompositor;
class UI_ANDROID_EXPORT DelegatedFrameHostAndroid
: public viz::CompositorFrameSinkSupportClient,
- public cc::ExternalBeginFrameSourceClient {
+ public viz::ExternalBeginFrameSourceClient,
+ public viz::HostFrameSinkClient {
public:
class Client {
public:
virtual void SetBeginFrameSource(
- cc::BeginFrameSource* begin_frame_source) = 0;
+ viz::BeginFrameSource* begin_frame_source) = 0;
virtual void DidReceiveCompositorFrameAck() = 0;
- virtual void ReclaimResources(const std::vector<cc::ReturnedResource>&) = 0;
+ virtual void ReclaimResources(
+ const std::vector<viz::ReturnedResource>&) = 0;
};
DelegatedFrameHostAndroid(ViewAndroid* view,
@@ -53,7 +56,7 @@ class UI_ANDROID_EXPORT DelegatedFrameHostAndroid
void SubmitCompositorFrame(const viz::LocalSurfaceId& local_surface_id,
cc::CompositorFrame frame);
- void DidNotProduceFrame(const cc::BeginFrameAck& ack);
+ void DidNotProduceFrame(const viz::BeginFrameAck& ack);
void DestroyDelegatedContent();
@@ -65,7 +68,7 @@ class UI_ANDROID_EXPORT DelegatedFrameHostAndroid
void RequestCopyOfSurface(
WindowAndroidCompositor* compositor,
const gfx::Rect& src_subrect_in_pixel,
- cc::CopyOutputRequest::CopyOutputRequestCallback result_callback);
+ viz::CopyOutputRequest::CopyOutputRequestCallback result_callback);
void CompositorFrameSinkChanged();
@@ -80,17 +83,20 @@ class UI_ANDROID_EXPORT DelegatedFrameHostAndroid
private:
// viz::CompositorFrameSinkSupportClient implementation.
void DidReceiveCompositorFrameAck(
- const std::vector<cc::ReturnedResource>& resources) override;
- void OnBeginFrame(const cc::BeginFrameArgs& args) override;
+ const std::vector<viz::ReturnedResource>& resources) override;
+ void OnBeginFrame(const viz::BeginFrameArgs& args) override;
void ReclaimResources(
- const std::vector<cc::ReturnedResource>& resources) override;
+ const std::vector<viz::ReturnedResource>& resources) override;
void WillDrawSurface(const viz::LocalSurfaceId& local_surface_id,
const gfx::Rect& damage_rect) override;
void OnBeginFramePausedChanged(bool paused) override;
- // cc::ExternalBeginFrameSourceClient implementation.
+ // viz::ExternalBeginFrameSourceClient implementation.
void OnNeedsBeginFrames(bool needs_begin_frames) override;
+ // viz::HostFrameSinkClient implementation.
+ void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
+
void CreateNewCompositorFrameSinkSupport();
const viz::FrameSinkId frame_sink_id_;
@@ -103,7 +109,7 @@ class UI_ANDROID_EXPORT DelegatedFrameHostAndroid
Client* client_;
std::unique_ptr<viz::CompositorFrameSinkSupport> support_;
- cc::ExternalBeginFrameSource begin_frame_source_;
+ viz::ExternalBeginFrameSource begin_frame_source_;
viz::SurfaceInfo surface_info_;
bool has_transparent_background_ = false;
diff --git a/chromium/ui/android/display_android_manager.cc b/chromium/ui/android/display_android_manager.cc
index 4904bc8b331..b7c04d5e362 100644
--- a/chromium/ui/android/display_android_manager.cc
+++ b/chromium/ui/android/display_android_manager.cc
@@ -32,10 +32,6 @@ void SetScreenAndroid() {
Java_DisplayAndroidManager_onNativeSideCreated(env, (jlong)manager);
}
-bool RegisterScreenAndroid(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
DisplayAndroidManager::DisplayAndroidManager() {}
DisplayAndroidManager::~DisplayAndroidManager() {}
@@ -94,10 +90,9 @@ void DisplayAndroidManager::UpdateDisplay(
if (!Display::HasForceDeviceScaleFactor())
display.set_device_scale_factor(dipScale);
if (!Display::HasForceColorProfile()) {
- if (isWideColorGamut)
- display.set_color_space(gfx::ColorSpace::CreateDisplayP3D65());
- else
- display.set_color_space(gfx::ColorSpace::CreateSRGB());
+ // TODO(ccameron): Use CreateDisplayP3D65 if isWideColorGamut is true, once
+ // the feature is ready to use.
+ display.set_color_space(gfx::ColorSpace::CreateSRGB());
}
display.set_size_in_pixels(bounds_in_pixels.size());
diff --git a/chromium/ui/android/event_forwarder.cc b/chromium/ui/android/event_forwarder.cc
index 0a19b41732c..023bc6e754a 100644
--- a/chromium/ui/android/event_forwarder.cc
+++ b/chromium/ui/android/event_forwarder.cc
@@ -67,7 +67,7 @@ jboolean EventForwarder::OnTouchEvent(JNIEnv* env,
jint android_tool_type_1,
jint android_button_state,
jint android_meta_state,
- jboolean is_touch_handle_event) {
+ jboolean for_touch_handle) {
ui::MotionEventAndroid::Pointer pointer0(
pointer_id_0, pos_x_0, pos_y_0, touch_major_0, touch_minor_0,
orientation_0, tilt_0, android_tool_type_0);
@@ -78,8 +78,9 @@ jboolean EventForwarder::OnTouchEvent(JNIEnv* env,
env, motion_event.obj(), 1.f / view_->GetDipScale(), 0.f, 0.f, 0.f,
time_ms, android_action, pointer_count, history_size, action_index,
0 /* action_button */, android_button_state, android_meta_state,
- raw_pos_x - pos_x_0, raw_pos_y - pos_y_0, &pointer0, &pointer1);
- return view_->OnTouchEvent(event, is_touch_handle_event);
+ raw_pos_x - pos_x_0, raw_pos_y - pos_y_0, for_touch_handle, &pointer0,
+ &pointer1);
+ return view_->OnTouchEvent(event);
}
void EventForwarder::OnMouseEvent(JNIEnv* env,
@@ -107,7 +108,8 @@ void EventForwarder::OnMouseEvent(JNIEnv* env,
time_ms, android_action, 1 /* pointer_count */, 0 /* history_size */,
0 /* action_index */, android_action_button, android_button_state,
android_meta_state, 0 /* raw_offset_x_pixels */,
- 0 /* raw_offset_y_pixels */, &pointer, nullptr);
+ 0 /* raw_offset_y_pixels */, false /* for_touch_handle */, &pointer,
+ nullptr);
view_->OnMouseEvent(event);
}
@@ -131,12 +133,12 @@ void EventForwarder::OnMouseWheelEvent(JNIEnv* env,
delta.InMicroseconds(), 1, 1000000, 50);
ui::MotionEventAndroid::Pointer pointer(
0, x, y, 0.0f /* touch_major */, 0.0f /* touch_minor */, 0.0f, 0.0f, 0);
- ui::MotionEventAndroid event(env, nullptr, 1.f / view_->GetDipScale(),
- ticks_x, ticks_y, pixels_per_tick, time_ms,
- 0 /* action */, 1 /* pointer_count */,
- 0 /* history_size */, 0 /* action_index */, 0, 0,
- 0, 0 /* raw_offset_x_pixels */,
- 0 /* raw_offset_y_pixels */, &pointer, nullptr);
+ ui::MotionEventAndroid event(
+ env, nullptr, 1.f / view_->GetDipScale(), ticks_x, ticks_y,
+ pixels_per_tick, time_ms, 0 /* action */, 1 /* pointer_count */,
+ 0 /* history_size */, 0 /* action_index */, 0, 0, 0,
+ 0 /* raw_offset_x_pixels */, 0 /* raw_offset_y_pixels */,
+ false /* for_touch_handle */, &pointer, nullptr);
view_->OnMouseWheelEvent(event);
}
@@ -161,8 +163,4 @@ void EventForwarder::OnDragEvent(JNIEnv* env,
view_->OnDragEvent(event);
}
-bool RegisterEventForwarder(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
} // namespace ui
diff --git a/chromium/ui/android/event_forwarder.h b/chromium/ui/android/event_forwarder.h
index ddc02b9f18d..86cf413b39f 100644
--- a/chromium/ui/android/event_forwarder.h
+++ b/chromium/ui/android/event_forwarder.h
@@ -93,8 +93,6 @@ class EventForwarder {
DISALLOW_COPY_AND_ASSIGN(EventForwarder);
};
-bool RegisterEventForwarder(JNIEnv* env);
-
} // namespace ui
#endif // UI_ANDROID_EVENT_FORWARDER_H_
diff --git a/chromium/ui/android/overscroll_glow.cc b/chromium/ui/android/overscroll_glow.cc
index 7f3c43da306..0470d11ad17 100644
--- a/chromium/ui/android/overscroll_glow.cc
+++ b/chromium/ui/android/overscroll_glow.cc
@@ -74,10 +74,10 @@ float OverscrollGlow::GetVisibleAlpha() const {
}
bool OverscrollGlow::OnOverscrolled(base::TimeTicks current_time,
- const gfx::Vector2dF& accumulated_overscroll,
- gfx::Vector2dF overscroll_delta,
- gfx::Vector2dF velocity,
- const gfx::Vector2dF& overscroll_location) {
+ gfx::Vector2dF accumulated_overscroll,
+ gfx::Vector2dF overscroll_delta,
+ gfx::Vector2dF velocity,
+ gfx::Vector2dF overscroll_location) {
// The size of the glow determines the relative effect of the inputs; an
// empty-sized effect is effectively disabled.
if (viewport_size_.IsEmpty())
diff --git a/chromium/ui/android/overscroll_glow.h b/chromium/ui/android/overscroll_glow.h
index 8253de04575..64cb4ce82f8 100644
--- a/chromium/ui/android/overscroll_glow.h
+++ b/chromium/ui/android/overscroll_glow.h
@@ -47,11 +47,12 @@ class UI_ANDROID_EXPORT OverscrollGlow {
// |velocity| is in device pixels / second.
// |overscroll_location| is the coordinate of the causal overscrolling event.
// Returns true if the effect still needs animation ticks.
- bool OnOverscrolled(base::TimeTicks current_time,
- const gfx::Vector2dF& accumulated_overscroll,
- gfx::Vector2dF overscroll_delta,
- gfx::Vector2dF velocity,
- const gfx::Vector2dF& overscroll_location);
+ // This method is made virtual for mocking.
+ virtual bool OnOverscrolled(base::TimeTicks current_time,
+ gfx::Vector2dF accumulated_overscroll,
+ gfx::Vector2dF overscroll_delta,
+ gfx::Vector2dF velocity,
+ gfx::Vector2dF overscroll_location);
// Returns true if the effect still needs animation ticks, with effect layers
// attached to |parent_layer| if necessary.
diff --git a/chromium/ui/android/overscroll_refresh.cc b/chromium/ui/android/overscroll_refresh.cc
index 2f2af62d8cd..60b54aa3dc1 100644
--- a/chromium/ui/android/overscroll_refresh.cc
+++ b/chromium/ui/android/overscroll_refresh.cc
@@ -24,6 +24,12 @@ OverscrollRefresh::OverscrollRefresh(OverscrollRefreshHandler* handler)
DCHECK(handler);
}
+OverscrollRefresh::OverscrollRefresh()
+ : scrolled_to_top_(true),
+ overflow_y_hidden_(false),
+ scroll_consumption_state_(DISABLED),
+ handler_(nullptr) {}
+
OverscrollRefresh::~OverscrollRefresh() {
}
@@ -43,15 +49,10 @@ void OverscrollRefresh::OnScrollEnd(const gfx::Vector2dF& scroll_velocity) {
Release(allow_activation);
}
-void OverscrollRefresh::OnScrollUpdateAck(bool was_consumed) {
+void OverscrollRefresh::OnOverscrolled() {
if (scroll_consumption_state_ != AWAITING_SCROLL_UPDATE_ACK)
return;
- if (was_consumed) {
- scroll_consumption_state_ = DISABLED;
- return;
- }
-
scroll_consumption_state_ = handler_->PullStart() ? ENABLED : DISABLED;
}
diff --git a/chromium/ui/android/overscroll_refresh.h b/chromium/ui/android/overscroll_refresh.h
index 7cb98e272ce..f69b2f74cbf 100644
--- a/chromium/ui/android/overscroll_refresh.h
+++ b/chromium/ui/android/overscroll_refresh.h
@@ -30,6 +30,7 @@ class UI_ANDROID_EXPORT OverscrollRefresh {
enum { kMinPullsToActivate = 3 };
explicit OverscrollRefresh(OverscrollRefreshHandler* handler);
+
~OverscrollRefresh();
// Scroll event stream listening methods.
@@ -37,9 +38,11 @@ class UI_ANDROID_EXPORT OverscrollRefresh {
// Returns whether the refresh was activated.
void OnScrollEnd(const gfx::Vector2dF& velocity);
- // Scroll ack listener. The effect will only be activated if the initial
- // updates go unconsumed.
- void OnScrollUpdateAck(bool was_consumed);
+ // Scroll ack listener. The effect will only be activated if |can_navigate|
+ // is true which happens when the scroll update is not consumed and the
+ // scroll_boundary_behavior on y axis is 'auto'.
+ // This method is made virtual for mocking.
+ virtual void OnOverscrolled();
// Returns true if the effect has consumed the |scroll_delta|.
bool WillHandleScrollUpdate(const gfx::Vector2dF& scroll_delta);
@@ -55,13 +58,20 @@ class UI_ANDROID_EXPORT OverscrollRefresh {
// Reset the effect to its inactive state, immediately detaching and
// disabling any active effects.
- void Reset();
+ // This method is made virtual for mocking.
+ virtual void Reset();
// Returns true if the refresh effect is either being manipulated or animated.
- bool IsActive() const;
+ // This method is made virtual for mocking.
+ virtual bool IsActive() const;
// Returns true if the effect is waiting for an unconsumed scroll to start.
- bool IsAwaitingScrollUpdateAck() const;
+ // This method is made virtual for mocking.
+ virtual bool IsAwaitingScrollUpdateAck() const;
+
+ protected:
+ // This constructor is for mocking only.
+ OverscrollRefresh();
private:
void Release(bool allow_refresh);
diff --git a/chromium/ui/android/overscroll_refresh_unittest.cc b/chromium/ui/android/overscroll_refresh_unittest.cc
index c133d759a8e..f31b85f4504 100644
--- a/chromium/ui/android/overscroll_refresh_unittest.cc
+++ b/chromium/ui/android/overscroll_refresh_unittest.cc
@@ -86,7 +86,7 @@ TEST_F(OverscrollRefreshTest, Basic) {
EXPECT_TRUE(effect.IsAwaitingScrollUpdateAck());
// The unconsumed, overscrolling scroll will trigger the effect.
- effect.OnScrollUpdateAck(false);
+ effect.OnOverscrolled();
EXPECT_TRUE(effect.IsActive());
EXPECT_FALSE(effect.IsAwaitingScrollUpdateAck());
EXPECT_TRUE(GetAndResetPullStarted());
@@ -124,7 +124,7 @@ TEST_F(OverscrollRefreshTest, NotTriggeredIfInitialYOffsetIsNotZero) {
ASSERT_FALSE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 10)));
EXPECT_FALSE(effect.IsActive());
EXPECT_FALSE(effect.IsAwaitingScrollUpdateAck());
- effect.OnScrollUpdateAck(false);
+ effect.OnOverscrolled();
EXPECT_FALSE(effect.IsActive());
EXPECT_FALSE(effect.IsAwaitingScrollUpdateAck());
EXPECT_FALSE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 500)));
@@ -145,7 +145,7 @@ TEST_F(OverscrollRefreshTest, NotTriggeredIfOverflowYHidden) {
ASSERT_FALSE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 10)));
EXPECT_FALSE(effect.IsActive());
EXPECT_FALSE(effect.IsAwaitingScrollUpdateAck());
- effect.OnScrollUpdateAck(false);
+ effect.OnOverscrolled();
EXPECT_FALSE(effect.IsActive());
EXPECT_FALSE(effect.IsAwaitingScrollUpdateAck());
EXPECT_FALSE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 500)));
@@ -164,7 +164,7 @@ TEST_F(OverscrollRefreshTest, NotTriggeredIfInitialScrollDownward) {
EXPECT_FALSE(effect.IsActive());
EXPECT_FALSE(effect.IsAwaitingScrollUpdateAck());
- effect.OnScrollUpdateAck(false);
+ effect.OnOverscrolled();
EXPECT_FALSE(effect.IsActive());
EXPECT_FALSE(effect.IsAwaitingScrollUpdateAck());
EXPECT_FALSE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 500)));
@@ -180,11 +180,12 @@ TEST_F(OverscrollRefreshTest, NotTriggeredIfInitialScrollOrTouchConsumed) {
// Consumption of the initial touchmove or scroll should prevent future
// activation.
- effect.OnScrollUpdateAck(true);
+ effect.Reset();
+ effect.OnOverscrolled();
EXPECT_FALSE(effect.IsActive());
EXPECT_FALSE(effect.IsAwaitingScrollUpdateAck());
EXPECT_FALSE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 500)));
- effect.OnScrollUpdateAck(false);
+ effect.OnOverscrolled();
EXPECT_FALSE(effect.IsActive());
EXPECT_FALSE(effect.IsAwaitingScrollUpdateAck());
EXPECT_FALSE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 500)));
@@ -198,7 +199,7 @@ TEST_F(OverscrollRefreshTest, NotTriggeredIfFlungDownward) {
effect.OnScrollBegin();
ASSERT_FALSE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 10)));
ASSERT_TRUE(effect.IsAwaitingScrollUpdateAck());
- effect.OnScrollUpdateAck(false);
+ effect.OnOverscrolled();
ASSERT_TRUE(effect.IsActive());
EXPECT_TRUE(GetAndResetPullStarted());
@@ -213,7 +214,7 @@ TEST_F(OverscrollRefreshTest, NotTriggeredIfReleasedWithoutActivation) {
effect.OnScrollBegin();
ASSERT_FALSE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 10)));
ASSERT_TRUE(effect.IsAwaitingScrollUpdateAck());
- effect.OnScrollUpdateAck(false);
+ effect.OnOverscrolled();
ASSERT_TRUE(effect.IsActive());
EXPECT_TRUE(GetAndResetPullStarted());
@@ -229,7 +230,7 @@ TEST_F(OverscrollRefreshTest, NotTriggeredIfReset) {
effect.OnScrollBegin();
ASSERT_FALSE(effect.WillHandleScrollUpdate(gfx::Vector2dF(0, 10)));
ASSERT_TRUE(effect.IsAwaitingScrollUpdateAck());
- effect.OnScrollUpdateAck(false);
+ effect.OnOverscrolled();
ASSERT_TRUE(effect.IsActive());
EXPECT_TRUE(GetAndResetPullStarted());
diff --git a/chromium/ui/android/resources/resource_factory.cc b/chromium/ui/android/resources/resource_factory.cc
index f6ffba329d5..1cbdde23f6b 100644
--- a/chromium/ui/android/resources/resource_factory.cc
+++ b/chromium/ui/android/resources/resource_factory.cc
@@ -2,8 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/android/resources/resource_factory.h"
-
#include "jni/ResourceFactory_jni.h"
#include "ui/android/resources/nine_patch_resource.h"
#include "ui/gfx/geometry/rect.h"
@@ -12,10 +10,6 @@ using base::android::JavaParamRef;
namespace ui {
-bool RegisterResourceFactory(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
jlong CreateBitmapResource(JNIEnv* env, const JavaParamRef<jclass>& clazz) {
return reinterpret_cast<intptr_t>(new Resource());
}
diff --git a/chromium/ui/android/resources/resource_factory.h b/chromium/ui/android/resources/resource_factory.h
deleted file mode 100644
index 670c290d358..00000000000
--- a/chromium/ui/android/resources/resource_factory.h
+++ /dev/null
@@ -1,16 +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_ANDROID_RESOURCES_RESOURCE_FACTORY_H_
-#define UI_ANDROID_RESOURCES_RESOURCE_FACTORY_H_
-
-#include "base/android/jni_android.h"
-
-namespace ui {
-
-bool RegisterResourceFactory(JNIEnv* env);
-
-} // namespace ui
-
-#endif // UI_ANDROID_RESOURCES_RESOURCE_FACTORY_H_
diff --git a/chromium/ui/android/resources/resource_manager_impl.cc b/chromium/ui/android/resources/resource_manager_impl.cc
index c2d5cf938b4..c7c02d9377b 100644
--- a/chromium/ui/android/resources/resource_manager_impl.cc
+++ b/chromium/ui/android/resources/resource_manager_impl.cc
@@ -233,11 +233,6 @@ bool ResourceManagerImpl::OnMemoryDump(
return true;
}
-// static
-bool ResourceManagerImpl::RegisterResourceManager(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
void ResourceManagerImpl::PreloadResourceFromJava(AndroidResourceType res_type,
int res_id) {
TRACE_EVENT2("ui", "ResourceManagerImpl::PreloadResourceFromJava",
diff --git a/chromium/ui/android/resources/resource_manager_impl.h b/chromium/ui/android/resources/resource_manager_impl.h
index 430078717ab..9eb3998d303 100644
--- a/chromium/ui/android/resources/resource_manager_impl.h
+++ b/chromium/ui/android/resources/resource_manager_impl.h
@@ -58,8 +58,6 @@ class UI_ANDROID_EXPORT ResourceManagerImpl
void ClearTintedResourceCache(JNIEnv* env,
const base::android::JavaRef<jobject>& jobj);
- static bool RegisterResourceManager(JNIEnv* env);
-
// base::trace_event::MemoryDumpProvider implementation.
bool OnMemoryDump(const base::trace_event::MemoryDumpArgs& args,
base::trace_event::ProcessMemoryDump* pmd) override;
diff --git a/chromium/ui/android/run_all_unittests.cc b/chromium/ui/android/run_all_unittests.cc
index f15eb51ea02..f4419350176 100644
--- a/chromium/ui/android/run_all_unittests.cc
+++ b/chromium/ui/android/run_all_unittests.cc
@@ -10,10 +10,8 @@
#include "base/test/launcher/unit_test_launcher.h"
#include "base/test/test_suite.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/android/ui_android_jni_registrar.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/base/ui_base_paths.h"
-#include "ui/gfx/android/gfx_jni_registrar.h"
namespace {
@@ -25,9 +23,6 @@ class UIAndroidTestSuite : public base::TestSuite {
void Initialize() override {
base::TestSuite::Initialize();
- gfx::android::RegisterJni(base::android::AttachCurrentThread());
- ui::RegisterUIAndroidJni(base::android::AttachCurrentThread());
-
ui::RegisterPathProvider();
base::FilePath ui_test_pak_path;
diff --git a/chromium/ui/android/screen_android.h b/chromium/ui/android/screen_android.h
index 4352c0e3f26..1482223b0e4 100644
--- a/chromium/ui/android/screen_android.h
+++ b/chromium/ui/android/screen_android.h
@@ -10,8 +10,6 @@
namespace ui {
-bool RegisterScreenAndroid(JNIEnv* env);
-
UI_ANDROID_EXPORT void SetScreenAndroid();
} // namespace display
diff --git a/chromium/ui/android/view_android.cc b/chromium/ui/android/view_android.cc
index f2d1486dbfd..dd7bf1b8efb 100644
--- a/chromium/ui/android/view_android.cc
+++ b/chromium/ui/android/view_android.cc
@@ -12,12 +12,14 @@
#include "base/stl_util.h"
#include "cc/layers/layer.h"
#include "jni/ViewAndroidDelegate_jni.h"
+#include "third_party/WebKit/public/platform/WebCursorInfo.h"
#include "ui/android/event_forwarder.h"
#include "ui/android/view_client.h"
#include "ui/android/window_android.h"
#include "ui/base/layout.h"
#include "ui/events/android/drag_event_android.h"
#include "ui/events/android/motion_event_android.h"
+#include "ui/gfx/android/java_bitmap.h"
#include "url/gurl.h"
namespace ui {
@@ -25,6 +27,7 @@ namespace ui {
using base::android::ConvertUTF8ToJavaString;
using base::android::JavaRef;
using base::android::ScopedJavaLocalRef;
+using blink::WebCursorInfo;
ViewAndroid::ScopedAnchorView::ScopedAnchorView(
JNIEnv* env,
@@ -84,6 +87,7 @@ ViewAndroid::ViewAndroid(ViewClient* view_client)
ViewAndroid::ViewAndroid() : ViewAndroid(nullptr) {}
ViewAndroid::~ViewAndroid() {
+ observer_list_.Clear();
RemoveFromParent();
for (std::list<ViewAndroid*>::iterator it = children_.begin();
@@ -136,6 +140,8 @@ void ViewAndroid::AddChild(ViewAndroid* child) {
// accidentally overwrite the valid ones in the children.
if (!physical_size_.IsEmpty())
child->OnPhysicalBackingSizeChanged(physical_size_);
+ if (GetWindowAndroid())
+ child->OnAttachedToWindow();
}
// static
@@ -210,16 +216,16 @@ ScopedJavaLocalRef<jobject> ViewAndroid::GetContainerView() {
return Java_ViewAndroidDelegate_getContainerView(env, delegate);
}
-gfx::Point ViewAndroid::GetLocationOfContainerViewOnScreen() {
+gfx::Point ViewAndroid::GetLocationOfContainerViewInWindow() {
ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
if (delegate.is_null())
return gfx::Point();
JNIEnv* env = base::android::AttachCurrentThread();
gfx::Point result(
- Java_ViewAndroidDelegate_getXLocationOfContainerViewOnScreen(env,
+ Java_ViewAndroidDelegate_getXLocationOfContainerViewInWindow(env,
delegate),
- Java_ViewAndroidDelegate_getYLocationOfContainerViewOnScreen(env,
+ Java_ViewAndroidDelegate_getYLocationOfContainerViewInWindow(env,
delegate));
return result;
@@ -229,6 +235,8 @@ void ViewAndroid::RemoveChild(ViewAndroid* child) {
DCHECK(child);
DCHECK_EQ(child->parent_, this);
+ if (GetWindowAndroid())
+ child->OnDetachedFromWindow();
std::list<ViewAndroid*>::iterator it =
std::find(children_.begin(), children_.end(), child);
DCHECK(it != children_.end());
@@ -236,6 +244,28 @@ void ViewAndroid::RemoveChild(ViewAndroid* child) {
child->parent_ = nullptr;
}
+void ViewAndroid::AddObserver(ViewAndroidObserver* observer) {
+ observer_list_.AddObserver(observer);
+}
+
+void ViewAndroid::RemoveObserver(ViewAndroidObserver* observer) {
+ observer_list_.RemoveObserver(observer);
+}
+
+void ViewAndroid::OnAttachedToWindow() {
+ for (auto& observer : observer_list_)
+ observer.OnAttachedToWindow();
+ for (auto* child : children_)
+ child->OnAttachedToWindow();
+}
+
+void ViewAndroid::OnDetachedFromWindow() {
+ for (auto& observer : observer_list_)
+ observer.OnDetachedFromWindow();
+ for (auto* child : children_)
+ child->OnDetachedFromWindow();
+}
+
WindowAndroid* ViewAndroid::GetWindowAndroid() const {
return parent_ ? parent_->GetWindowAndroid() : nullptr;
}
@@ -254,6 +284,22 @@ cc::Layer* ViewAndroid::GetLayer() const {
return layer_.get();
}
+bool ViewAndroid::HasFocus() {
+ ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
+ if (delegate.is_null())
+ return false;
+ JNIEnv* env = base::android::AttachCurrentThread();
+ return Java_ViewAndroidDelegate_hasFocus(env, delegate);
+}
+
+void ViewAndroid::RequestFocus() {
+ ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
+ if (delegate.is_null())
+ return;
+ JNIEnv* env = base::android::AttachCurrentThread();
+ Java_ViewAndroidDelegate_requestFocus(env, delegate);
+}
+
void ViewAndroid::SetLayer(scoped_refptr<cc::Layer> layer) {
layer_ = layer;
}
@@ -272,6 +318,28 @@ bool ViewAndroid::StartDragAndDrop(const JavaRef<jstring>& jtext,
jimage);
}
+void ViewAndroid::OnCursorChanged(int type,
+ const SkBitmap& custom_image,
+ const gfx::Point& hotspot) {
+ ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
+ if (delegate.is_null())
+ return;
+ JNIEnv* env = base::android::AttachCurrentThread();
+ if (type == WebCursorInfo::kTypeCustom) {
+ if (custom_image.drawsNothing()) {
+ Java_ViewAndroidDelegate_onCursorChanged(env, delegate,
+ WebCursorInfo::kTypePointer);
+ return;
+ }
+ ScopedJavaLocalRef<jobject> java_bitmap =
+ gfx::ConvertToJavaBitmap(&custom_image);
+ Java_ViewAndroidDelegate_onCursorChangedToCustom(env, delegate, java_bitmap,
+ hotspot.x(), hotspot.y());
+ } else {
+ Java_ViewAndroidDelegate_onCursorChanged(env, delegate, type);
+ }
+}
+
void ViewAndroid::OnBackgroundColorChanged(unsigned int color) {
ScopedJavaLocalRef<jobject> delegate(GetViewAndroidDelegate());
if (delegate.is_null())
@@ -335,20 +403,17 @@ bool ViewAndroid::SendDragEventToClient(ViewClient* client,
return client->OnDragEvent(*e);
}
-bool ViewAndroid::OnTouchEvent(const MotionEventAndroid& event,
- bool for_touch_handle) {
- return HitTest(
- base::Bind(&ViewAndroid::SendTouchEventToClient, for_touch_handle), event,
- event.GetPoint());
+bool ViewAndroid::OnTouchEvent(const MotionEventAndroid& event) {
+ return HitTest(base::Bind(&ViewAndroid::SendTouchEventToClient), event,
+ event.GetPoint());
}
// static
-bool ViewAndroid::SendTouchEventToClient(bool for_touch_handle,
- ViewClient* client,
+bool ViewAndroid::SendTouchEventToClient(ViewClient* client,
const MotionEventAndroid& event,
const gfx::PointF& point) {
std::unique_ptr<MotionEventAndroid> e(event.CreateFor(point));
- return client->OnTouchEvent(*e, for_touch_handle);
+ return client->OnTouchEvent(*e);
}
bool ViewAndroid::OnMouseEvent(const MotionEventAndroid& event) {
diff --git a/chromium/ui/android/view_android.h b/chromium/ui/android/view_android.h
index a9880543ca1..5dc9253034d 100644
--- a/chromium/ui/android/view_android.h
+++ b/chromium/ui/android/view_android.h
@@ -11,19 +11,28 @@
#include "base/android/jni_weak_ref.h"
#include "base/bind.h"
#include "base/memory/ref_counted.h"
+#include "base/observer_list.h"
#include "ui/android/ui_android_export.h"
+#include "ui/android/view_android_observer.h"
#include "ui/gfx/geometry/rect_f.h"
+class SkBitmap;
+
namespace cc {
class Layer;
}
+namespace gfx {
+class Point;
+}
+
namespace ui {
class DragEventAndroid;
class EventForwarder;
class MotionEventAndroid;
class ViewClient;
class WindowAndroid;
+class ViewAndroidObserver;
// View-related parameters from frame updates.
struct FrameInfo {
@@ -135,6 +144,9 @@ class UI_ANDROID_EXPORT ViewAndroid {
// Detaches this view from its parent.
void RemoveFromParent();
+ bool HasFocus();
+ void RequestFocus();
+
// Sets the layout relative to parent. Used to do hit testing against events.
void SetLayout(LayoutParams params);
@@ -143,6 +155,9 @@ class UI_ANDROID_EXPORT ViewAndroid {
gfx::Size GetPhysicalBackingSize();
void OnPhysicalBackingSizeChanged(const gfx::Size& size);
+ void OnCursorChanged(int type,
+ const SkBitmap& custom_image,
+ const gfx::Point& hotspot);
void OnBackgroundColorChanged(unsigned int color);
void OnTopControlsChanged(float top_controls_offset,
float top_content_offset);
@@ -158,7 +173,11 @@ class UI_ANDROID_EXPORT ViewAndroid {
base::android::ScopedJavaLocalRef<jobject> GetContainerView();
// Return the location of the container view in physical pixels.
- gfx::Point GetLocationOfContainerViewOnScreen();
+ gfx::Point GetLocationOfContainerViewInWindow();
+
+ // ViewAndroid does not own |observer|s.
+ void AddObserver(ViewAndroidObserver* observer);
+ void RemoveObserver(ViewAndroidObserver* observer);
float GetDipScale();
@@ -170,12 +189,15 @@ class UI_ANDROID_EXPORT ViewAndroid {
friend class ViewAndroidBoundsTest;
bool OnDragEvent(const DragEventAndroid& event);
- bool OnTouchEvent(const MotionEventAndroid& event, bool for_touch_handle);
+ bool OnTouchEvent(const MotionEventAndroid& event);
bool OnMouseEvent(const MotionEventAndroid& event);
bool OnMouseWheelEvent(const MotionEventAndroid& event);
void RemoveChild(ViewAndroid* child);
+ void OnAttachedToWindow();
+ void OnDetachedFromWindow();
+
template <typename E>
using ViewClientCallback =
const base::Callback<bool(ViewClient*, const E&, const gfx::PointF&)>;
@@ -188,8 +210,7 @@ class UI_ANDROID_EXPORT ViewAndroid {
static bool SendDragEventToClient(ViewClient* client,
const DragEventAndroid& event,
const gfx::PointF& point);
- static bool SendTouchEventToClient(bool for_touch_handle,
- ViewClient* client,
+ static bool SendTouchEventToClient(ViewClient* client,
const MotionEventAndroid& event,
const gfx::PointF& point);
static bool SendMouseEventToClient(ViewClient* client,
@@ -215,6 +236,7 @@ class UI_ANDROID_EXPORT ViewAndroid {
GetViewAndroidDelegate() const;
std::list<ViewAndroid*> children_;
+ base::ObserverList<ViewAndroidObserver> observer_list_;
scoped_refptr<cc::Layer> layer_;
JavaObjectWeakGlobalRef delegate_;
diff --git a/chromium/ui/android/view_android_observer.h b/chromium/ui/android/view_android_observer.h
new file mode 100644
index 00000000000..cb8cbe51de1
--- /dev/null
+++ b/chromium/ui/android/view_android_observer.h
@@ -0,0 +1,28 @@
+// 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_ANDROID_VIEW_ANDROID_OBSERVER_H_
+#define UI_ANDROID_VIEW_ANDROID_OBSERVER_H_
+
+#include "ui/android/ui_android_export.h"
+
+namespace ui {
+
+class UI_ANDROID_EXPORT ViewAndroidObserver {
+ public:
+ // Notifies that view gets attached to window. Note that the notification
+ // is not sent if view is already in attached state.
+ virtual void OnAttachedToWindow() = 0;
+
+ // Notifies that view gets detached from window. Note that the notification
+ // is not sent if view is already in detached state.
+ virtual void OnDetachedFromWindow() = 0;
+
+ protected:
+ virtual ~ViewAndroidObserver() {}
+};
+
+} // namespace ui
+
+#endif // UI_ANDROID_VIEW_ANDROID_OBSERVER_H_
diff --git a/chromium/ui/android/view_android_unittests.cc b/chromium/ui/android/view_android_unittests.cc
index 78a01f68cd0..220566840e5 100644
--- a/chromium/ui/android/view_android_unittests.cc
+++ b/chromium/ui/android/view_android_unittests.cc
@@ -6,7 +6,9 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/android/event_forwarder.h"
#include "ui/android/view_android.h"
+#include "ui/android/view_android_observer.h"
#include "ui/android/view_client.h"
+#include "ui/android/window_android.h"
#include "ui/events/android/motion_event_android.h"
namespace ui {
@@ -18,8 +20,7 @@ class TestViewClient : public ViewClient {
TestViewClient() : handle_event_(true), called_(false) {}
void SetHandleEvent(bool handle_event) { handle_event_ = handle_event; }
- bool OnTouchEvent(const MotionEventAndroid& event,
- bool for_touch_handle) override {
+ bool OnTouchEvent(const MotionEventAndroid& event) override {
called_ = true;
return handle_event_;
}
@@ -54,9 +55,9 @@ class ViewAndroidBoundsTest : public testing::Test {
ui::MotionEventAndroid::Pointer pointer0(0, x, y, 0, 0, 0, 0, 0);
ui::MotionEventAndroid::Pointer pointer1(0, 0, 0, 0, 0, 0, 0, 0);
ui::MotionEventAndroid event(nullptr, JavaParamRef<jobject>(nullptr), 1.f,
- 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, false,
&pointer0, &pointer1);
- root_.OnTouchEvent(event, false);
+ root_.OnTouchEvent(event);
}
void ExpectHit(const TestViewClient& hitClient) {
@@ -200,4 +201,60 @@ TEST(ViewAndroidTest, ChecksMultipleEventForwarders) {
EXPECT_DCHECK_DEATH(rwhv2.GetEventForwarder());
}
+class Observer : public ViewAndroidObserver {
+ public:
+ Observer() : attached_(false) {}
+
+ void OnAttachedToWindow() override { attached_ = true; }
+
+ void OnDetachedFromWindow() override { attached_ = false; }
+
+ bool attached_;
+};
+
+TEST(ViewAndroidTest, Observer) {
+ std::unique_ptr<WindowAndroid> window(WindowAndroid::CreateForTesting());
+ ViewAndroid top;
+ ViewAndroid bottom;
+
+ Observer top_observer;
+ Observer bottom_observer;
+
+ top.AddObserver(&top_observer);
+ bottom.AddObserver(&bottom_observer);
+
+ top.AddChild(&bottom);
+
+ EXPECT_FALSE(top_observer.attached_);
+ EXPECT_FALSE(bottom_observer.attached_);
+
+ // Views in a tree all get notified of 'attached' event.
+ window->AddChild(&top);
+ EXPECT_TRUE(top_observer.attached_);
+ EXPECT_TRUE(bottom_observer.attached_);
+
+ // Observer, upon addition, does not get notified of the current
+ // attached state.
+ Observer top_observer2;
+ top.AddObserver(&top_observer2);
+ EXPECT_FALSE(top_observer2.attached_);
+
+ bottom.RemoveFromParent();
+ EXPECT_FALSE(bottom_observer.attached_);
+ top.RemoveFromParent();
+ EXPECT_FALSE(top_observer.attached_);
+
+ window->AddChild(&top);
+ EXPECT_TRUE(top_observer.attached_);
+
+ // View, upon addition to a tree in the attached state, should be notified.
+ top.AddChild(&bottom);
+ EXPECT_TRUE(bottom_observer.attached_);
+
+ // Views in a tree all get notified of 'detached' event.
+ top.RemoveFromParent();
+ EXPECT_FALSE(top_observer.attached_);
+ EXPECT_FALSE(bottom_observer.attached_);
+}
+
} // namespace ui
diff --git a/chromium/ui/android/view_client.cc b/chromium/ui/android/view_client.cc
index 2fc2532f521..007ff62de21 100644
--- a/chromium/ui/android/view_client.cc
+++ b/chromium/ui/android/view_client.cc
@@ -6,8 +6,7 @@
namespace ui {
-bool ViewClient::OnTouchEvent(const MotionEventAndroid& event,
- bool for_touch_handle) {
+bool ViewClient::OnTouchEvent(const MotionEventAndroid& event) {
return false;
}
diff --git a/chromium/ui/android/view_client.h b/chromium/ui/android/view_client.h
index 95bbc284017..6a01dff18b9 100644
--- a/chromium/ui/android/view_client.h
+++ b/chromium/ui/android/view_client.h
@@ -19,8 +19,7 @@ class MotionEventAndroid;
// the processing.
class UI_ANDROID_EXPORT ViewClient {
public:
- virtual bool OnTouchEvent(const MotionEventAndroid& event,
- bool for_touch_handle);
+ virtual bool OnTouchEvent(const MotionEventAndroid& event);
virtual bool OnMouseEvent(const MotionEventAndroid& event);
virtual bool OnMouseWheelEvent(const MotionEventAndroid& event);
virtual bool OnDragEvent(const DragEventAndroid& event);
diff --git a/chromium/ui/android/window_android.cc b/chromium/ui/android/window_android.cc
index 388d4c6daad..080ce9ae594 100644
--- a/chromium/ui/android/window_android.cc
+++ b/chromium/ui/android/window_android.cc
@@ -11,8 +11,8 @@
#include "base/android/scoped_java_ref.h"
#include "base/observer_list.h"
#include "base/stl_util.h"
-#include "cc/output/begin_frame_args.h"
-#include "cc/scheduler/begin_frame_source.h"
+#include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "jni/WindowAndroid_jni.h"
#include "ui/android/window_android_compositor.h"
#include "ui/android/window_android_observer.h"
@@ -24,21 +24,21 @@ using base::android::JavaParamRef;
using base::android::JavaRef;
using base::android::ScopedJavaLocalRef;
-class WindowAndroid::WindowBeginFrameSource : public cc::BeginFrameSource {
+class WindowAndroid::WindowBeginFrameSource : public viz::BeginFrameSource {
public:
explicit WindowBeginFrameSource(WindowAndroid* window)
: window_(window),
observers_(
- base::ObserverList<cc::BeginFrameObserver>::NOTIFY_EXISTING_ONLY),
+ base::ObserverList<viz::BeginFrameObserver>::NOTIFY_EXISTING_ONLY),
observer_count_(0),
- next_sequence_number_(cc::BeginFrameArgs::kStartingFrameNumber),
+ next_sequence_number_(viz::BeginFrameArgs::kStartingFrameNumber),
paused_(false) {}
~WindowBeginFrameSource() override {}
- // cc::BeginFrameSource implementation.
- void AddObserver(cc::BeginFrameObserver* obs) override;
- void RemoveObserver(cc::BeginFrameObserver* obs) override;
- void DidFinishFrame(cc::BeginFrameObserver* obs) override {}
+ // viz::BeginFrameSource implementation.
+ void AddObserver(viz::BeginFrameObserver* obs) override;
+ void RemoveObserver(viz::BeginFrameObserver* obs) override;
+ void DidFinishFrame(viz::BeginFrameObserver* obs) override {}
bool IsThrottled() const override { return true; }
void OnVSync(base::TimeTicks frame_time, base::TimeDelta vsync_period);
@@ -46,15 +46,15 @@ class WindowAndroid::WindowBeginFrameSource : public cc::BeginFrameSource {
private:
WindowAndroid* const window_;
- base::ObserverList<cc::BeginFrameObserver> observers_;
+ base::ObserverList<viz::BeginFrameObserver> observers_;
int observer_count_;
- cc::BeginFrameArgs last_begin_frame_args_;
+ viz::BeginFrameArgs last_begin_frame_args_;
uint64_t next_sequence_number_;
bool paused_;
};
void WindowAndroid::WindowBeginFrameSource::AddObserver(
- cc::BeginFrameObserver* obs) {
+ viz::BeginFrameObserver* obs) {
DCHECK(obs);
DCHECK(!observers_.HasObserver(obs));
@@ -65,13 +65,13 @@ void WindowAndroid::WindowBeginFrameSource::AddObserver(
// Send a MISSED BeginFrame if possible and necessary.
if (last_begin_frame_args_.IsValid()) {
- cc::BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs();
+ viz::BeginFrameArgs last_args = obs->LastUsedBeginFrameArgs();
if (!last_args.IsValid() ||
last_args.frame_time < last_begin_frame_args_.frame_time) {
DCHECK(last_args.sequence_number <
last_begin_frame_args_.sequence_number ||
last_args.source_id != last_begin_frame_args_.source_id);
- last_begin_frame_args_.type = cc::BeginFrameArgs::MISSED;
+ last_begin_frame_args_.type = viz::BeginFrameArgs::MISSED;
// TODO(crbug.com/602485): A deadline doesn't make too much sense
// for a missed BeginFrame (the intention rather is 'immediately'),
// but currently the retro frame logic is very strict in discarding
@@ -84,7 +84,7 @@ void WindowAndroid::WindowBeginFrameSource::AddObserver(
}
void WindowAndroid::WindowBeginFrameSource::RemoveObserver(
- cc::BeginFrameObserver* obs) {
+ viz::BeginFrameObserver* obs) {
DCHECK(obs);
DCHECK(observers_.HasObserver(obs));
@@ -99,9 +99,9 @@ void WindowAndroid::WindowBeginFrameSource::OnVSync(
base::TimeDelta vsync_period) {
// frame time is in the past, so give the next vsync period as the deadline.
base::TimeTicks deadline = frame_time + vsync_period;
- last_begin_frame_args_ = cc::BeginFrameArgs::Create(
+ last_begin_frame_args_ = viz::BeginFrameArgs::Create(
BEGINFRAME_FROM_HERE, source_id(), next_sequence_number_, frame_time,
- deadline, vsync_period, cc::BeginFrameArgs::NORMAL);
+ deadline, vsync_period, viz::BeginFrameArgs::NORMAL);
DCHECK(last_begin_frame_args_.IsValid());
next_sequence_number_++;
@@ -131,10 +131,6 @@ ScopedJavaLocalRef<jobject> WindowAndroid::GetJavaObject() {
return base::android::ScopedJavaLocalRef<jobject>(java_window_);
}
-bool WindowAndroid::RegisterWindowAndroid(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
WindowAndroid::~WindowAndroid() {
DCHECK(parent_ == nullptr) << "WindowAndroid must be a root view.";
DCHECK(!compositor_);
@@ -147,10 +143,6 @@ WindowAndroid* WindowAndroid::CreateForTesting() {
return reinterpret_cast<WindowAndroid*>(native_pointer);
}
-void WindowAndroid::DestroyForTesting() {
- delete this;
-}
-
void WindowAndroid::OnCompositingDidCommit() {
for (WindowAndroidObserver& observer : observer_list_)
observer.OnCompositingDidCommit();
@@ -169,7 +161,7 @@ void WindowAndroid::RemoveObserver(WindowAndroidObserver* observer) {
observer_list_.RemoveObserver(observer);
}
-cc::BeginFrameSource* WindowAndroid::GetBeginFrameSource() {
+viz::BeginFrameSource* WindowAndroid::GetBeginFrameSource() {
return begin_frame_source_.get();
}
@@ -217,7 +209,14 @@ void WindowAndroid::OnVSync(JNIEnv* env,
const JavaParamRef<jobject>& obj,
jlong time_micros,
jlong period_micros) {
- base::TimeTicks frame_time(base::TimeTicks::FromInternalValue(time_micros));
+ // Warning: It is generally unsafe to manufacture TimeTicks values. The
+ // following assumption is being made, AND COULD EASILY BREAK AT ANY TIME:
+ // Upstream, Java code is providing "System.nanos() / 1000," and this is the
+ // same timestamp that would be provided by the CLOCK_MONOTONIC POSIX clock.
+ DCHECK_EQ(base::TimeTicks::GetClock(),
+ base::TimeTicks::Clock::LINUX_CLOCK_MONOTONIC);
+ base::TimeTicks frame_time =
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(time_micros);
base::TimeDelta vsync_period(
base::TimeDelta::FromMicroseconds(period_micros));
diff --git a/chromium/ui/android/window_android.h b/chromium/ui/android/window_android.h
index efb267991de..eebe2003bf3 100644
--- a/chromium/ui/android/window_android.h
+++ b/chromium/ui/android/window_android.h
@@ -21,14 +21,14 @@
#include "ui/android/view_android.h"
#include "ui/gfx/geometry/vector2d_f.h"
-namespace cc {
-class BeginFrameSource;
-} // namespace cc
-
namespace display {
class DisplayAndroidManager;
} // namespace display
+namespace viz {
+class BeginFrameSource;
+} // namespace viz
+
namespace ui {
class WindowAndroidCompositor;
@@ -40,12 +40,12 @@ class UI_ANDROID_EXPORT WindowAndroid : public ViewAndroid {
public:
WindowAndroid(JNIEnv* env, jobject obj, int display_id);
+ ~WindowAndroid() override;
+
void Destroy(JNIEnv* env, const base::android::JavaParamRef<jobject>& obj);
base::android::ScopedJavaLocalRef<jobject> GetJavaObject();
- static bool RegisterWindowAndroid(JNIEnv* env);
-
// Compositor callback relay.
void OnCompositingDidCommit();
@@ -56,7 +56,7 @@ class UI_ANDROID_EXPORT WindowAndroid : public ViewAndroid {
void RemoveObserver(WindowAndroidObserver* observer);
WindowAndroidCompositor* GetCompositor() { return compositor_; }
- cc::BeginFrameSource* GetBeginFrameSource();
+ viz::BeginFrameSource* GetBeginFrameSource();
// Runs the provided callback as soon as the current vsync was handled.
void AddVSyncCompleteCallback(const base::Closure& callback);
@@ -84,7 +84,6 @@ class UI_ANDROID_EXPORT WindowAndroid : public ViewAndroid {
bool CanRequestPermission(const std::string& permission);
static WindowAndroid* CreateForTesting();
- void DestroyForTesting();
// Return the window token for this window, if one exists.
base::android::ScopedJavaLocalRef<jobject> GetWindowToken();
@@ -94,8 +93,6 @@ class UI_ANDROID_EXPORT WindowAndroid : public ViewAndroid {
friend class DisplayAndroidManager;
friend class WindowBeginFrameSource;
- ~WindowAndroid() override;
-
void SetNeedsBeginFrames(bool needs_begin_frames);
void RequestVSyncUpdate();
diff --git a/chromium/ui/android/window_android_compositor.h b/chromium/ui/android/window_android_compositor.h
index 00f88e33005..33967bfff20 100644
--- a/chromium/ui/android/window_android_compositor.h
+++ b/chromium/ui/android/window_android_compositor.h
@@ -7,7 +7,7 @@
#include <memory>
-#include "cc/output/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_request.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
#include "ui/android/ui_android_export.h"
@@ -26,7 +26,7 @@ class UI_ANDROID_EXPORT WindowAndroidCompositor {
virtual void AttachLayerForReadback(scoped_refptr<cc::Layer> layer) = 0;
virtual void RequestCopyOfOutputOnRootLayer(
- std::unique_ptr<cc::CopyOutputRequest> request) = 0;
+ std::unique_ptr<viz::CopyOutputRequest> request) = 0;
virtual void SetNeedsAnimate() = 0;
virtual ResourceManager& GetResourceManager() = 0;
virtual viz::FrameSinkId GetFrameSinkId() = 0;
diff --git a/chromium/ui/app_list/BUILD.gn b/chromium/ui/app_list/BUILD.gn
index 75b61ee6f4c..b0092432551 100644
--- a/chromium/ui/app_list/BUILD.gn
+++ b/chromium/ui/app_list/BUILD.gn
@@ -156,7 +156,6 @@ component("app_list") {
"views/search_result_container_view.h",
"views/search_result_list_view.cc",
"views/search_result_list_view.h",
- "views/search_result_list_view_delegate.h",
"views/search_result_page_view.cc",
"views/search_result_page_view.h",
"views/search_result_tile_item_list_view.cc",
diff --git a/chromium/ui/app_list/presenter/app_list_presenter.mojom b/chromium/ui/app_list/presenter/app_list_presenter.mojom
index cba536e9b39..2b54979b6b2 100644
--- a/chromium/ui/app_list/presenter/app_list_presenter.mojom
+++ b/chromium/ui/app_list/presenter/app_list_presenter.mojom
@@ -10,6 +10,24 @@ import "services/ui/public/interfaces/window_manager_constants.mojom";
// TODO(msw): Ash should implement the app list and presenter; chrome should
// just push data about its apps into the app list interface.
+// Matches app_list::AppListView:AppListState.
+enum AppListState {
+ // Closes |app_list_main_view_| and dismisses the delegate.
+ CLOSED = 0,
+ // The initial state for the app list when neither maximize or side shelf
+ // modes are active. If set, the widget will peek over the shelf by
+ // kPeekingAppListHeight DIPs.
+ PEEKING = 1,
+ // Entered when text is entered into the search box from peeking mode.
+ HALF = 2,
+ // Default app list state in maximize and side shelf modes. Entered from an
+ // upward swipe from |PEEKING| or from clicking the chevron.
+ FULLSCREEN_ALL_APPS = 3,
+ // Entered from an upward swipe from |HALF| or by entering text in the
+ // search box from |FULLSCREEN_ALL_APPS|.
+ FULLSCREEN_SEARCH = 4,
+};
+
// Implemented by ash. Used by chrome to set the presenter interface.
interface AppList {
// Set the app list presenter interface, to let ash trigger Chrome's app list.
@@ -40,10 +58,14 @@ interface AppListPresenter {
// Starts or stops a voice interaction session based on the current state.
ToggleVoiceInteractionSession();
- // Updates y position and opacity of app list. |is_end_gesture| means it is
- // the end of the gesture dragging of app list from shelf and should restore
- // the opacity of the app list.
+ // Updates y position and opacity of app list.
UpdateYPositionAndOpacity(int32 y_position_in_screen,
- float background_opacity,
- bool is_end_gesture);
+ float background_opacity);
+
+ // Ends the drag of app list from shelf.
+ EndDragFromShelf(AppListState app_list_state);
+
+ // Passes MouseWheelEvents from the Shelf to the AppListView.
+ ProcessMouseWheelOffset(int32 y_scroll_offset);
+
};
diff --git a/chromium/ui/arc/BUILD.gn b/chromium/ui/arc/BUILD.gn
index b6af6d81c6c..6c5deab5ea7 100644
--- a/chromium/ui/arc/BUILD.gn
+++ b/chromium/ui/arc/BUILD.gn
@@ -62,10 +62,14 @@ test("ui_arc_unittests") {
deps = [
":arc",
+ "//ash:test_support_without_content",
"//base",
"//base/test:test_support",
"//components/arc:arc_test_support",
+ "//components/exo",
+ "//components/exo:test_support",
"//mojo/edk/system",
+ "//testing/gmock",
"//testing/gtest",
"//ui/aura:test_support",
"//ui/base:test_support",
diff --git a/chromium/ui/arc/notification/arc_notification_content_view.cc b/chromium/ui/arc/notification/arc_notification_content_view.cc
index 8a3ad2e2281..f4bb12596ae 100644
--- a/chromium/ui/arc/notification/arc_notification_content_view.cc
+++ b/chromium/ui/arc/notification/arc_notification_content_view.cc
@@ -21,11 +21,11 @@
#include "ui/gfx/transform.h"
#include "ui/message_center/message_center_style.h"
#include "ui/message_center/views/notification_control_buttons_view.h"
-#include "ui/message_center/views/toast_contents_view.h"
#include "ui/strings/grit/ui_strings.h"
#include "ui/views/focus/focus_manager.h"
#include "ui/views/widget/root_view.h"
#include "ui/views/widget/widget.h"
+#include "ui/views/widget/widget_delegate.h"
#include "ui/wm/core/window_util.h"
namespace arc {
@@ -84,7 +84,8 @@ class ArcNotificationContentView::EventForwarder : public ui::EventHandler {
// TODO(yoshiki): Use a better tigger (eg. focusing EditText on
// notification) than clicking (crbug.com/697379).
- if (event->type() == ui::ET_MOUSE_PRESSED)
+ if (event->type() == ui::ET_MOUSE_PRESSED ||
+ event->type() == ui::ET_GESTURE_TAP)
owner_->Activate();
views::Widget* widget = owner_->GetWidget();
@@ -134,8 +135,10 @@ class ArcNotificationContentView::SlideHelper
// Reset opacity to 1 to handle to case when the surface is sliding before
// getting managed by this class, e.g. sliding in a popup before showing
// in a message center view.
- if (owner_->surface_ && owner_->surface_->GetWindow())
+ if (owner_->surface_) {
+ DCHECK(owner_->surface_->GetWindow());
owner_->surface_->GetWindow()->layer()->SetOpacity(1.0f);
+ }
}
~SlideHelper() override {
if (GetSlideOutLayer())
@@ -166,8 +169,9 @@ class ArcNotificationContentView::SlideHelper
}
void OnSlideStart() {
- if (!owner_->surface_ || !owner_->surface_->GetWindow())
+ if (!owner_->surface_)
return;
+ DCHECK(owner_->surface_->GetWindow());
surface_copy_ = ::wm::RecreateLayers(owner_->surface_->GetWindow());
// |surface_copy_| is at (0, 0) in owner_->layer().
surface_copy_->root()->SetBounds(gfx::Rect(surface_copy_->root()->size()));
@@ -176,8 +180,9 @@ class ArcNotificationContentView::SlideHelper
}
void OnSlideEnd() {
- if (!owner_->surface_ || !owner_->surface_->GetWindow())
+ if (!owner_->surface_)
return;
+ DCHECK(owner_->surface_->GetWindow());
owner_->surface_->GetWindow()->layer()->SetOpacity(1.0f);
owner_->Layout();
surface_copy_.reset();
@@ -231,6 +236,10 @@ class ArcNotificationContentView::ContentViewDelegate
return owner_->control_buttons_view_;
}
+ bool IsExpanded() const override { return owner_->IsExpanded(); }
+
+ void SetExpanded(bool expanded) override { owner_->SetExpanded(expanded); }
+
private:
ArcNotificationContentView* const owner_;
@@ -247,6 +256,10 @@ ArcNotificationContentView::ArcNotificationContentView(
notification_key_(item->GetNotificationKey()),
event_forwarder_(new EventForwarder(this)),
mouse_enter_exit_handler_(new MouseEnterExitHandler(this)) {
+ // kNotificationWidth must be 360, since this value is separately defiend in
+ // ArcNotificationWrapperView class in Android side.
+ DCHECK_EQ(360, message_center::kNotificationWidth);
+
SetFocusBehavior(FocusBehavior::ALWAYS);
set_notify_enter_exit_on_child(true);
@@ -312,7 +325,7 @@ void ArcNotificationContentView::MaybeCreateFloatingControlButtons() {
GetControlButtonBackgroundColor(item_->GetShownContents()));
control_buttons_view_->ShowSettingsButton(
item_->IsOpeningSettingsSupported());
- control_buttons_view_->ShowCloseButton(!item_->GetPinned());
+ control_buttons_view_->ShowCloseButton(!notification_view->GetPinned());
views::Widget::InitParams params(views::Widget::InitParams::TYPE_CONTROL);
params.opacity = views::Widget::InitParams::TRANSLUCENT_WINDOW;
@@ -343,8 +356,10 @@ void ArcNotificationContentView::SetSurface(ArcNotificationSurface* surface) {
// Reset |floating_control_buttons_widget_| when |surface_| is changed.
floating_control_buttons_widget_.reset();
- if (surface_ && surface_->GetWindow()) {
- surface_->GetWindow()->RemoveObserver(this);
+ if (surface_) {
+ DCHECK(surface_->GetWindow());
+ DCHECK(surface_->GetContentWindow());
+ surface_->GetContentWindow()->RemoveObserver(this);
surface_->GetWindow()->RemovePreTargetHandler(event_forwarder_.get());
if (surface_->GetAttachedHost() == this) {
@@ -355,8 +370,10 @@ void ArcNotificationContentView::SetSurface(ArcNotificationSurface* surface) {
surface_ = surface;
- if (surface_ && surface_->GetWindow()) {
- surface_->GetWindow()->AddObserver(this);
+ if (surface_) {
+ DCHECK(surface_->GetWindow());
+ DCHECK(surface_->GetContentWindow());
+ surface_->GetContentWindow()->AddObserver(this);
surface_->GetWindow()->AddPreTargetHandler(event_forwarder_.get());
if (GetWidget()) {
@@ -411,18 +428,6 @@ void ArcNotificationContentView::UpdateControlButtonsVisibility() {
floating_control_buttons_widget_->Hide();
}
-void ArcNotificationContentView::UpdatePinnedState() {
- if (!item_)
- return;
-
- // Surface is not attached yet.
- if (!control_buttons_view_)
- return;
-
- control_buttons_view_->ShowCloseButton(!item_->GetPinned());
- Layout();
-}
-
void ArcNotificationContentView::UpdateSnapshot() {
// Bail if we have a |surface_| because it controls the sizes and paints UI.
if (surface_)
@@ -464,6 +469,21 @@ void ArcNotificationContentView::UpdateAccessibleName() {
accessible_name_ = item_->GetAccessibleName();
}
+bool ArcNotificationContentView::IsExpanded() const {
+ return item_->GetExpandState() == mojom::ArcNotificationExpandState::EXPANDED;
+}
+
+void ArcNotificationContentView::SetExpanded(bool expanded) {
+ auto expand_state = item_->GetExpandState();
+ if (expanded) {
+ if (expand_state == mojom::ArcNotificationExpandState::COLLAPSED)
+ item_->ToggleExpansion();
+ } else {
+ if (expand_state == mojom::ArcNotificationExpandState::EXPANDED)
+ item_->ToggleExpansion();
+ }
+}
+
void ArcNotificationContentView::ViewHierarchyChanged(
const views::View::ViewHierarchyChangedDetails& details) {
views::Widget* widget = GetWidget();
@@ -504,11 +524,11 @@ void ArcNotificationContentView::Layout() {
// Scale notification surface if necessary.
gfx::Transform transform;
const gfx::Size surface_size = surface_->GetSize();
- const gfx::Size contents_size = contents_bounds.size();
- if (!surface_size.IsEmpty() && !contents_size.IsEmpty()) {
- transform.Scale(
- static_cast<float>(contents_size.width()) / surface_size.width(),
- static_cast<float>(contents_size.height()) / surface_size.height());
+ if (!surface_size.IsEmpty()) {
+ const float factor =
+ static_cast<float>(message_center::kNotificationWidth) /
+ surface_size.width();
+ transform.Scale(factor, factor);
}
// Apply the transform to the surface content so that close button can
@@ -642,7 +662,6 @@ void ArcNotificationContentView::OnItemDestroying() {
void ArcNotificationContentView::OnItemUpdated() {
UpdateAccessibleName();
- UpdatePinnedState();
UpdateSnapshot();
if (control_buttons_view_) {
DCHECK(floating_control_buttons_widget_);
diff --git a/chromium/ui/arc/notification/arc_notification_content_view.h b/chromium/ui/arc/notification/arc_notification_content_view.h
index 79c396bb579..3e2706d91b6 100644
--- a/chromium/ui/arc/notification/arc_notification_content_view.h
+++ b/chromium/ui/arc/notification/arc_notification_content_view.h
@@ -66,11 +66,12 @@ class ArcNotificationContentView
void SetSurface(ArcNotificationSurface* surface);
void UpdatePreferredSize();
void UpdateControlButtonsVisibility();
- void UpdatePinnedState();
void UpdateSnapshot();
void AttachSurface();
void Activate();
void UpdateAccessibleName();
+ void SetExpanded(bool expanded);
+ bool IsExpanded() const;
// views::NativeViewHost
void ViewHierarchyChanged(
diff --git a/chromium/ui/arc/notification/arc_notification_content_view_delegate.h b/chromium/ui/arc/notification/arc_notification_content_view_delegate.h
index dec7ee848ea..a27cad2a68b 100644
--- a/chromium/ui/arc/notification/arc_notification_content_view_delegate.h
+++ b/chromium/ui/arc/notification/arc_notification_content_view_delegate.h
@@ -22,6 +22,8 @@ class ArcNotificationContentViewDelegate {
virtual void OnSlideChanged() = 0;
virtual message_center::NotificationControlButtonsView*
GetControlButtonsView() const = 0;
+ virtual bool IsExpanded() const = 0;
+ virtual void SetExpanded(bool expanded) = 0;
};
} // namespace arc
diff --git a/chromium/ui/arc/notification/arc_notification_content_view_unittest.cc b/chromium/ui/arc/notification/arc_notification_content_view_unittest.cc
index 3394b011a17..d8eddfc96e0 100644
--- a/chromium/ui/arc/notification/arc_notification_content_view_unittest.cc
+++ b/chromium/ui/arc/notification/arc_notification_content_view_unittest.cc
@@ -8,14 +8,27 @@
#include <string>
#include <utility>
+#include "ash/shell.h"
+#include "ash/test/ash_test_base.h"
#include "base/strings/utf_string_conversions.h"
+#include "components/exo/buffer.h"
+#include "components/exo/keyboard.h"
+#include "components/exo/keyboard_delegate.h"
+#include "components/exo/notification_surface.h"
+#include "components/exo/surface.h"
+#include "components/exo/test/exo_test_helper.h"
+#include "components/exo/wm_helper_ash.h"
+#include "testing/gmock/include/gmock/gmock.h"
#include "ui/arc/notification/arc_notification_content_view.h"
#include "ui/arc/notification/arc_notification_delegate.h"
#include "ui/arc/notification/arc_notification_item.h"
#include "ui/arc/notification/arc_notification_surface.h"
+#include "ui/arc/notification/arc_notification_surface_manager_impl.h"
#include "ui/arc/notification/arc_notification_view.h"
#include "ui/aura/test/test_window_delegate.h"
#include "ui/aura/window.h"
+#include "ui/events/keycodes/dom/dom_code.h"
+#include "ui/events/test/event_generator.h"
#include "ui/message_center/notification.h"
#include "ui/message_center/views/message_center_controller.h"
#include "ui/message_center/views/message_view_factory.h"
@@ -28,85 +41,60 @@ namespace arc {
namespace {
constexpr char kNotificationIdPrefix[] = "ARC_NOTIFICATION_";
+constexpr gfx::Rect kNotificationSurfaceBounds(100, 100, 300, 300);
-class MockNotificationSurface : public ArcNotificationSurface {
+class MockKeyboardDelegate : public exo::KeyboardDelegate {
public:
- MockNotificationSurface(const std::string& notification_key,
- std::unique_ptr<aura::Window> window)
- : notification_key_(notification_key), window_(std::move(window)) {}
-
- gfx::Size GetSize() const override { return gfx::Size(100, 200); }
-
- void Attach(views::NativeViewHost* nvh) override {
- native_view_host_ = nvh;
- nvh->Attach(window_.get());
- }
-
- void Detach() override {
- EXPECT_TRUE(native_view_host_);
- EXPECT_EQ(window_.get(), native_view_host_->native_view());
- native_view_host_->Detach();
- native_view_host_ = nullptr;
- }
-
- bool IsAttached() const override { return native_view_host_; }
- views::NativeViewHost* GetAttachedHost() const override {
- return native_view_host_;
- }
-
- aura::Window* GetWindow() const override { return window_.get(); }
- aura::Window* GetContentWindow() const override { return window_.get(); }
-
- const std::string& GetNotificationKey() const override {
- return notification_key_;
- }
-
- private:
- std::string notification_key_;
- std::unique_ptr<aura::Window> window_;
- views::NativeViewHost* native_view_host_ = nullptr;
-
- DISALLOW_COPY_AND_ASSIGN(MockNotificationSurface);
+ MockKeyboardDelegate() = default;
+
+ // Overridden from KeyboardDelegate:
+ MOCK_METHOD1(OnKeyboardDestroying, void(exo::Keyboard*));
+ MOCK_CONST_METHOD1(CanAcceptKeyboardEventsForSurface, bool(exo::Surface*));
+ MOCK_METHOD2(OnKeyboardEnter,
+ void(exo::Surface*, const std::vector<ui::DomCode>&));
+ MOCK_METHOD1(OnKeyboardLeave, void(exo::Surface*));
+ MOCK_METHOD3(OnKeyboardKey, uint32_t(base::TimeTicks, ui::DomCode, bool));
+ MOCK_METHOD1(OnKeyboardModifiers, void(int));
};
-class TestNotificationSurfaceManager : public ArcNotificationSurfaceManager {
+class TestWMHelper : public exo::WMHelper {
public:
- TestNotificationSurfaceManager() = default;
-
- void PrepareSurface(std::string& notification_key) {
- auto surface_window = base::MakeUnique<aura::Window>(&window_delegate_);
- surface_window->SetType(aura::client::WINDOW_TYPE_CONTROL);
- surface_window->Init(ui::LAYER_NOT_DRAWN);
- surface_window->set_owned_by_parent(false);
- surface_window->SetBounds(gfx::Rect(0, 0, 100, 200));
+ TestWMHelper() = default;
+ ~TestWMHelper() override = default;
- surface_map_[notification_key] = base::MakeUnique<MockNotificationSurface>(
- notification_key, std::move(surface_window));
+ const display::ManagedDisplayInfo& GetDisplayInfo(
+ int64_t display_id) const override {
+ static const display::ManagedDisplayInfo info;
+ return info;
}
- size_t surface_found_count() const { return surface_found_count_; }
-
- ArcNotificationSurface* GetArcSurface(
- const std::string& notification_key) const override {
- auto it = surface_map_.find(notification_key);
- if (it != surface_map_.end()) {
- ++surface_found_count_;
- return it->second.get();
- }
+ aura::Window* GetPrimaryDisplayContainer(int container_id) override {
return nullptr;
}
- void AddObserver(Observer* observer) override {}
- void RemoveObserver(Observer* observer) override {}
+ aura::Window* GetActiveWindow() const override { return nullptr; }
+ aura::Window* GetFocusedWindow() const override { return nullptr; }
+ ui::CursorSize GetCursorSize() const override {
+ return ui::CursorSize::kNormal;
+ }
+ const display::Display& GetCursorDisplay() const override {
+ static const display::Display display;
+ return display;
+ }
+ void AddPreTargetHandler(ui::EventHandler* handler) override {}
+ void PrependPreTargetHandler(ui::EventHandler* handler) override {}
+ void RemovePreTargetHandler(ui::EventHandler* handler) override {}
+ void AddPostTargetHandler(ui::EventHandler* handler) override {}
+ void RemovePostTargetHandler(ui::EventHandler* handler) override {}
+ bool IsTabletModeWindowManagerEnabled() const override { return false; }
private:
- // Mutable for modifying in const method.
- mutable int surface_found_count_ = 0;
-
- aura::test::TestWindowDelegate window_delegate_;
- std::map<std::string, std::unique_ptr<ArcNotificationSurface>> surface_map_;
-
- DISALLOW_COPY_AND_ASSIGN(TestNotificationSurfaceManager);
+ DISALLOW_COPY_AND_ASSIGN(TestWMHelper);
};
+aura::Window* GetFocusedWindow() {
+ DCHECK(exo::WMHelper::HasInstance());
+ return exo::WMHelper::GetInstance()->GetFocusedWindow();
+}
+
} // anonymous namespace
class MockArcNotificationItem : public ArcNotificationItem {
@@ -141,7 +129,6 @@ class MockArcNotificationItem : public ArcNotificationItem {
void RemoveObserver(Observer* observer) override {}
void IncrementWindowRefCount() override {}
void DecrementWindowRefCount() override {}
- bool GetPinned() const override { return false; }
bool IsOpeningSettingsSupported() const override { return true; }
mojom::ArcNotificationExpandState GetExpandState() const override {
return mojom::ArcNotificationExpandState::FIXED_SIZE;
@@ -222,15 +209,19 @@ class DummyEvent : public ui::Event {
~DummyEvent() override = default;
};
-class ArcNotificationContentViewTest : public views::ViewsTestBase {
+class ArcNotificationContentViewTest : public ash::AshTestBase {
public:
ArcNotificationContentViewTest() = default;
~ArcNotificationContentViewTest() override = default;
void SetUp() override {
- views::ViewsTestBase::SetUp();
+ ash::AshTestBase::SetUp();
+
+ wm_helper_ = base::MakeUnique<exo::WMHelperAsh>();
+ exo::WMHelper::SetInstance(wm_helper_.get());
+ DCHECK(exo::WMHelper::HasInstance());
- surface_manager_ = base::MakeUnique<TestNotificationSurfaceManager>();
+ surface_manager_ = base::MakeUnique<ArcNotificationSurfaceManagerImpl>();
}
void TearDown() override {
@@ -238,9 +229,18 @@ class ArcNotificationContentViewTest : public views::ViewsTestBase {
EXPECT_FALSE(wrapper_widget_);
EXPECT_FALSE(notification_view_);
+ // These may have been initialized in PrepareSurface().
+ notification_surface_.reset();
+ surface_.reset();
+ surface_buffer_.reset();
+
surface_manager_.reset();
- views::ViewsTestBase::TearDown();
+ DCHECK(exo::WMHelper::HasInstance());
+ exo::WMHelper::SetInstance(nullptr);
+ wm_helper_.reset();
+
+ ash::AshTestBase::TearDown();
}
void PressCloseButton() {
@@ -248,8 +248,7 @@ class ArcNotificationContentViewTest : public views::ViewsTestBase {
auto* control_buttons_view =
GetArcNotificationContentView()->control_buttons_view_;
ASSERT_TRUE(control_buttons_view);
- message_center::PaddedButton* close_button =
- control_buttons_view->close_button();
+ views::Button* close_button = control_buttons_view->close_button();
ASSERT_NE(nullptr, close_button);
control_buttons_view->ButtonPressed(close_button, dummy_event);
}
@@ -272,10 +271,10 @@ class ArcNotificationContentViewTest : public views::ViewsTestBase {
message_center::MessageViewFactory::Create(controller(),
notification, true)));
notification_view->set_owned_by_client();
- views::Widget::InitParams params(
- CreateParams(views::Widget::InitParams::TYPE_POPUP));
+ views::Widget::InitParams params(views::Widget::InitParams::TYPE_POPUP);
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.context = ash::Shell::GetPrimaryRootWindow();
auto wrapper_widget = base::MakeUnique<views::Widget>();
wrapper_widget->Init(params);
wrapper_widget->SetContentsView(notification_view.get());
@@ -292,6 +291,20 @@ class ArcNotificationContentViewTest : public views::ViewsTestBase {
notification_view_.reset();
}
+ void PrepareSurface(const std::string& notification_key) {
+ surface_ = base::MakeUnique<exo::Surface>();
+ notification_surface_ = base::MakeUnique<exo::NotificationSurface>(
+ surface_manager(), surface_.get(), notification_key);
+
+ exo::test::ExoTestHelper exo_test_helper;
+ surface_buffer_ =
+ base::MakeUnique<exo::Buffer>(exo_test_helper.CreateGpuMemoryBuffer(
+ kNotificationSurfaceBounds.size()));
+ surface_->Attach(surface_buffer_.get());
+
+ surface_->Commit();
+ }
+
message_center::Notification CreateNotification(
MockArcNotificationItem* notification_item) {
return message_center::Notification(
@@ -306,24 +319,40 @@ class ArcNotificationContentViewTest : public views::ViewsTestBase {
}
TestMessageCenterController* controller() { return &controller_; }
- TestNotificationSurfaceManager* surface_manager() {
+ ArcNotificationSurfaceManagerImpl* surface_manager() {
return surface_manager_.get();
}
views::Widget* widget() { return notification_view_->GetWidget(); }
+ exo::Surface* surface() { return surface_.get(); }
+ ArcNotificationView* notification_view() { return notification_view_.get(); }
+
+ message_center::NotificationControlButtonsView* GetControlButtonsView()
+ const {
+ DCHECK(GetArcNotificationContentView());
+ DCHECK(GetArcNotificationContentView()->control_buttons_view_);
+ return GetArcNotificationContentView()->control_buttons_view_;
+ }
+ views::Widget* GetControlButtonsWidget() const {
+ DCHECK(GetControlButtonsView()->GetWidget());
+ return GetControlButtonsView()->GetWidget();
+ }
- ArcNotificationContentView* GetArcNotificationContentView() {
+ ArcNotificationContentView* GetArcNotificationContentView() const {
views::View* view = notification_view_->contents_view_;
EXPECT_EQ(ArcNotificationContentView::kViewClassName, view->GetClassName());
return static_cast<ArcNotificationContentView*>(view);
}
-
- TestNotificationSurfaceManager* surface_manager() const {
- return surface_manager_.get();
+ void ActivateArcNotification() {
+ GetArcNotificationContentView()->Activate();
}
private:
TestMessageCenterController controller_;
- std::unique_ptr<TestNotificationSurfaceManager> surface_manager_;
+ std::unique_ptr<exo::WMHelper> wm_helper_;
+ std::unique_ptr<ArcNotificationSurfaceManagerImpl> surface_manager_;
+ std::unique_ptr<exo::Buffer> surface_buffer_;
+ std::unique_ptr<exo::Surface> surface_;
+ std::unique_ptr<exo::NotificationSurface> notification_surface_;
std::unique_ptr<ArcNotificationView> notification_view_;
std::unique_ptr<views::Widget> wrapper_widget_;
@@ -338,7 +367,7 @@ TEST_F(ArcNotificationContentViewTest, CreateSurfaceAfterNotification) {
message_center::Notification notification =
CreateNotification(notification_item.get());
- surface_manager()->PrepareSurface(notification_key);
+ PrepareSurface(notification_key);
CreateAndShowNotificationView(notification);
CloseNotificationView();
@@ -347,7 +376,7 @@ TEST_F(ArcNotificationContentViewTest, CreateSurfaceAfterNotification) {
TEST_F(ArcNotificationContentViewTest, CreateSurfaceBeforeNotification) {
std::string notification_key("notification id");
- surface_manager()->PrepareSurface(notification_key);
+ PrepareSurface(notification_key);
auto notification_item =
base::MakeUnique<MockArcNotificationItem>(notification_key);
@@ -375,12 +404,11 @@ TEST_F(ArcNotificationContentViewTest, CloseButton) {
auto notification_item =
base::MakeUnique<MockArcNotificationItem>(notification_key);
- surface_manager()->PrepareSurface(notification_key);
+ PrepareSurface(notification_key);
message_center::Notification notification =
CreateNotification(notification_item.get());
CreateAndShowNotificationView(notification);
- EXPECT_EQ(1u, surface_manager()->surface_found_count());
EXPECT_FALSE(controller()->IsRemoved(notification_item->GetNotificationId()));
PressCloseButton();
EXPECT_TRUE(controller()->IsRemoved(notification_item->GetNotificationId()));
@@ -396,7 +424,7 @@ TEST_F(ArcNotificationContentViewTest, ReuseSurfaceAfterClosing) {
message_center::Notification notification =
CreateNotification(notification_item.get());
- surface_manager()->PrepareSurface(notification_key);
+ PrepareSurface(notification_key);
// Use the created surface.
CreateAndShowNotificationView(notification);
@@ -419,7 +447,7 @@ TEST_F(ArcNotificationContentViewTest, ReuseAndCloseSurfaceBeforeClosing) {
message_center::Notification notification =
CreateNotification(notification_item.get());
- surface_manager()->PrepareSurface(notification_key);
+ PrepareSurface(notification_key);
// Create the first view.
auto result = CreateNotificationView(notification);
@@ -446,7 +474,7 @@ TEST_F(ArcNotificationContentViewTest, ReuseSurfaceBeforeClosing) {
message_center::Notification notification =
CreateNotification(notification_item.get());
- surface_manager()->PrepareSurface(notification_key);
+ PrepareSurface(notification_key);
// Create the first view.
auto result = CreateNotificationView(notification);
@@ -466,4 +494,211 @@ TEST_F(ArcNotificationContentViewTest, ReuseSurfaceBeforeClosing) {
CloseNotificationView();
}
+TEST_F(ArcNotificationContentViewTest, Activate) {
+ std::string key("notification id");
+ auto notification_item = base::MakeUnique<MockArcNotificationItem>(key);
+ auto notification = CreateNotification(notification_item.get());
+
+ PrepareSurface(key);
+ CreateAndShowNotificationView(notification);
+
+ EXPECT_FALSE(GetFocusedWindow());
+ ActivateArcNotification();
+ EXPECT_EQ(surface()->window(), GetFocusedWindow());
+
+ CloseNotificationView();
+}
+
+TEST_F(ArcNotificationContentViewTest, ActivateOnClick) {
+ std::string key("notification id");
+ auto notification_item = base::MakeUnique<MockArcNotificationItem>(key);
+ auto notification = CreateNotification(notification_item.get());
+
+ PrepareSurface(key);
+ CreateAndShowNotificationView(notification);
+
+ EXPECT_FALSE(GetFocusedWindow());
+ ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow(),
+ kNotificationSurfaceBounds.CenterPoint());
+ generator.PressLeftButton();
+ EXPECT_EQ(surface()->window(), GetFocusedWindow());
+
+ CloseNotificationView();
+}
+
+TEST_F(ArcNotificationContentViewTest, AcceptInputTextWithActivate) {
+ std::string key("notification id");
+ auto notification_item = base::MakeUnique<MockArcNotificationItem>(key);
+ auto notification = CreateNotification(notification_item.get());
+
+ PrepareSurface(key);
+ CreateAndShowNotificationView(notification);
+
+ EXPECT_FALSE(GetFocusedWindow());
+ ActivateArcNotification();
+ EXPECT_EQ(surface()->window(), GetFocusedWindow());
+
+ MockKeyboardDelegate delegate;
+ EXPECT_CALL(delegate, CanAcceptKeyboardEventsForSurface(surface()))
+ .WillOnce(testing::Return(true));
+ auto keyboard = base::MakeUnique<exo::Keyboard>(&delegate);
+
+ ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
+ EXPECT_CALL(delegate, OnKeyboardKey(testing::_, ui::DomCode::US_A, true));
+ generator.PressKey(ui::VKEY_A, 0);
+
+ keyboard.reset();
+
+ CloseNotificationView();
+}
+
+TEST_F(ArcNotificationContentViewTest, NotAcceptInputTextWithoutActivate) {
+ std::string key("notification id");
+ auto notification_item = base::MakeUnique<MockArcNotificationItem>(key);
+ auto notification = CreateNotification(notification_item.get());
+
+ PrepareSurface(key);
+ CreateAndShowNotificationView(notification);
+ EXPECT_FALSE(GetFocusedWindow());
+
+ MockKeyboardDelegate delegate;
+ EXPECT_CALL(delegate, CanAcceptKeyboardEventsForSurface(surface())).Times(0);
+ auto keyboard = base::MakeUnique<exo::Keyboard>(&delegate);
+
+ ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
+ EXPECT_CALL(delegate, OnKeyboardKey(testing::_, testing::_, testing::_))
+ .Times(0);
+ generator.PressKey(ui::VKEY_A, 0);
+
+ keyboard.reset();
+
+ CloseNotificationView();
+}
+
+TEST_F(ArcNotificationContentViewTest, TraversalFocus) {
+ const bool reverse = false;
+
+ std::string key("notification id");
+ auto notification_item = base::MakeUnique<MockArcNotificationItem>(key);
+ PrepareSurface(key);
+ auto notification = CreateNotification(notification_item.get());
+ CreateAndShowNotificationView(notification);
+
+ views::FocusManager* focus_manager = notification_view()->GetFocusManager();
+
+ views::View* view =
+ focus_manager->GetNextFocusableView(nullptr, widget(), reverse, true);
+ EXPECT_EQ(GetArcNotificationContentView(), view);
+
+ view = focus_manager->GetNextFocusableView(view, nullptr, reverse, true);
+ EXPECT_EQ(GetControlButtonsView()->settings_button(), view);
+
+ view = focus_manager->GetNextFocusableView(view, nullptr, reverse, true);
+ EXPECT_EQ(GetControlButtonsView()->close_button(), view);
+
+ view = focus_manager->GetNextFocusableView(view, nullptr, reverse, true);
+ EXPECT_EQ(nullptr, view);
+
+ CloseNotificationView();
+}
+
+TEST_F(ArcNotificationContentViewTest, TraversalFocusReverse) {
+ const bool reverse = true;
+
+ std::string key("notification id");
+ auto notification_item = base::MakeUnique<MockArcNotificationItem>(key);
+ PrepareSurface(key);
+ auto notification = CreateNotification(notification_item.get());
+ CreateAndShowNotificationView(notification);
+
+ views::FocusManager* focus_manager = notification_view()->GetFocusManager();
+
+ views::View* view =
+ focus_manager->GetNextFocusableView(nullptr, widget(), reverse, true);
+ EXPECT_EQ(GetControlButtonsView()->close_button(), view);
+
+ view = focus_manager->GetNextFocusableView(view, nullptr, reverse, true);
+ EXPECT_EQ(GetControlButtonsView()->settings_button(), view);
+
+ view = focus_manager->GetNextFocusableView(view, nullptr, reverse, true);
+ EXPECT_EQ(GetArcNotificationContentView(), view);
+
+ view = focus_manager->GetNextFocusableView(view, nullptr, reverse, true);
+ EXPECT_EQ(nullptr, view);
+
+ CloseNotificationView();
+}
+
+TEST_F(ArcNotificationContentViewTest, TraversalFocusByTabKey) {
+ const std::string key("notification id");
+ auto notification_item = base::MakeUnique<MockArcNotificationItem>(key);
+ PrepareSurface(key);
+ auto notification = CreateNotification(notification_item.get());
+ CreateAndShowNotificationView(notification);
+ ActivateArcNotification();
+
+ views::FocusManager* focus_manager = notification_view()->GetFocusManager();
+ ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
+
+ focus_manager->ClearFocus();
+ EXPECT_FALSE(focus_manager->GetFocusedView());
+
+ generator.PressKey(ui::VKEY_TAB, 0);
+ EXPECT_TRUE(focus_manager->GetFocusedView());
+ EXPECT_EQ(GetArcNotificationContentView(), focus_manager->GetFocusedView());
+
+ generator.PressKey(ui::VKEY_TAB, 0);
+ EXPECT_TRUE(focus_manager->GetFocusedView());
+ EXPECT_EQ(GetControlButtonsView()->settings_button(),
+ focus_manager->GetFocusedView());
+
+ generator.PressKey(ui::VKEY_TAB, 0);
+ EXPECT_TRUE(focus_manager->GetFocusedView());
+ EXPECT_EQ(GetControlButtonsView()->close_button(),
+ focus_manager->GetFocusedView());
+
+ generator.PressKey(ui::VKEY_TAB, 0);
+ EXPECT_TRUE(focus_manager->GetFocusedView());
+ EXPECT_EQ(GetArcNotificationContentView(), focus_manager->GetFocusedView());
+
+ CloseNotificationView();
+}
+
+TEST_F(ArcNotificationContentViewTest, TraversalFocusReverseByShiftTab) {
+ std::string key("notification id");
+
+ auto notification_item = base::MakeUnique<MockArcNotificationItem>(key);
+ PrepareSurface(key);
+ auto notification = CreateNotification(notification_item.get());
+ CreateAndShowNotificationView(notification);
+ ActivateArcNotification();
+
+ views::FocusManager* focus_manager = notification_view()->GetFocusManager();
+ ui::test::EventGenerator generator(ash::Shell::GetPrimaryRootWindow());
+
+ focus_manager->ClearFocus();
+ EXPECT_FALSE(focus_manager->GetFocusedView());
+
+ generator.PressKey(ui::VKEY_TAB, ui::EF_SHIFT_DOWN);
+ EXPECT_TRUE(focus_manager->GetFocusedView());
+ EXPECT_EQ(GetControlButtonsView()->close_button(),
+ focus_manager->GetFocusedView());
+
+ generator.PressKey(ui::VKEY_TAB, ui::EF_SHIFT_DOWN);
+ EXPECT_TRUE(focus_manager->GetFocusedView());
+ EXPECT_EQ(GetControlButtonsView()->settings_button(),
+ focus_manager->GetFocusedView());
+
+ generator.PressKey(ui::VKEY_TAB, ui::EF_SHIFT_DOWN);
+ EXPECT_TRUE(focus_manager->GetFocusedView());
+ EXPECT_EQ(GetArcNotificationContentView(), focus_manager->GetFocusedView());
+
+ generator.PressKey(ui::VKEY_TAB, ui::EF_SHIFT_DOWN);
+ EXPECT_TRUE(focus_manager->GetFocusedView());
+ EXPECT_EQ(GetControlButtonsView()->close_button(),
+ focus_manager->GetFocusedView());
+
+ CloseNotificationView();
+}
+
} // namespace arc
diff --git a/chromium/ui/arc/notification/arc_notification_item.h b/chromium/ui/arc/notification/arc_notification_item.h
index 4024b3d30d8..5605598b82d 100644
--- a/chromium/ui/arc/notification/arc_notification_item.h
+++ b/chromium/ui/arc/notification/arc_notification_item.h
@@ -65,8 +65,6 @@ class ArcNotificationItem {
// is sent when |window_ref_count_| goes from one to zero.
virtual void DecrementWindowRefCount() = 0;
- // Returns the current pinned state.
- virtual bool GetPinned() const = 0;
// Returns the current snapshot.
virtual const gfx::ImageSkia& GetSnapshot() const = 0;
// Returns the current expand state.
diff --git a/chromium/ui/arc/notification/arc_notification_item_impl.cc b/chromium/ui/arc/notification/arc_notification_item_impl.cc
index b0edb55058f..0d93235a203 100644
--- a/chromium/ui/arc/notification/arc_notification_item_impl.cc
+++ b/chromium/ui/arc/notification/arc_notification_item_impl.cc
@@ -100,7 +100,6 @@ void ArcNotificationItemImpl::OnUpdatedFromAndroid(
new ArcNotificationDelegate(weak_ptr_factory_.GetWeakPtr()));
notification->set_timestamp(base::Time::FromJavaTime(data->time));
- pinned_ = rich_data.pinned;
expand_state_ = data->expand_state;
shown_contents_ = data->shown_contents;
@@ -175,10 +174,6 @@ void ArcNotificationItemImpl::DecrementWindowRefCount() {
manager_->CloseNotificationWindow(notification_key_);
}
-bool ArcNotificationItemImpl::GetPinned() const {
- return pinned_;
-}
-
const gfx::ImageSkia& ArcNotificationItemImpl::GetSnapshot() const {
return snapshot_;
}
diff --git a/chromium/ui/arc/notification/arc_notification_item_impl.h b/chromium/ui/arc/notification/arc_notification_item_impl.h
index 9f69b57bbd7..a90deb0a790 100644
--- a/chromium/ui/arc/notification/arc_notification_item_impl.h
+++ b/chromium/ui/arc/notification/arc_notification_item_impl.h
@@ -42,7 +42,6 @@ class ArcNotificationItemImpl : public ArcNotificationItem {
void RemoveObserver(Observer* observer) override;
void IncrementWindowRefCount() override;
void DecrementWindowRefCount() override;
- bool GetPinned() const override;
const gfx::ImageSkia& GetSnapshot() const override;
mojom::ArcNotificationExpandState GetExpandState() const override;
mojom::ArcNotificationShownContents GetShownContents() const override;
@@ -57,8 +56,6 @@ class ArcNotificationItemImpl : public ArcNotificationItem {
ArcNotificationManager* const manager_;
message_center::MessageCenter* const message_center_;
- // The pinned state of the latest notification.
- bool pinned_ = false;
// The snapshot of the latest notification.
gfx::ImageSkia snapshot_;
// The expand state of the latest notification.
diff --git a/chromium/ui/arc/notification/arc_notification_manager.cc b/chromium/ui/arc/notification/arc_notification_manager.cc
index 4e560108a87..dbdfd1d6009 100644
--- a/chromium/ui/arc/notification/arc_notification_manager.cc
+++ b/chromium/ui/arc/notification/arc_notification_manager.cc
@@ -76,12 +76,7 @@ ArcNotificationManager::ArcNotificationManager(
}
ArcNotificationManager::~ArcNotificationManager() {
- // TODO(hidehiko): Currently, the lifetime of ArcBridgeService and
- // BrowserContextKeyedService is not nested.
- // If ArcServiceManager::Get() returns nullptr, it is already destructed,
- // so do not touch it.
- if (ArcServiceManager::Get())
- arc_bridge_service_->notifications()->RemoveObserver(this);
+ arc_bridge_service_->notifications()->RemoveObserver(this);
}
void ArcNotificationManager::OnInstanceReady() {
diff --git a/chromium/ui/arc/notification/arc_notification_surface_impl.cc b/chromium/ui/arc/notification/arc_notification_surface_impl.cc
index 140da96ae93..964de60692c 100644
--- a/chromium/ui/arc/notification/arc_notification_surface_impl.cc
+++ b/chromium/ui/arc/notification/arc_notification_surface_impl.cc
@@ -8,17 +8,85 @@
#include "components/exo/notification_surface.h"
#include "components/exo/surface.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_delegate.h"
+#include "ui/base/cursor/cursor.h"
+#include "ui/base/hit_test.h"
#include "ui/views/controls/native/native_view_host.h"
+#include "ui/views/widget/widget.h"
namespace arc {
+namespace {
+
+class CustomWindowDelegate : public aura::WindowDelegate {
+ public:
+ explicit CustomWindowDelegate(exo::NotificationSurface* notification_surface)
+ : notification_surface_(notification_surface) {}
+ ~CustomWindowDelegate() override {}
+
+ // Overridden from aura::WindowDelegate:
+ gfx::Size GetMinimumSize() const override { return gfx::Size(); }
+ gfx::Size GetMaximumSize() const override { return gfx::Size(); }
+ void OnBoundsChanged(const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) override {}
+ gfx::NativeCursor GetCursor(const gfx::Point& point) override {
+ return notification_surface_->GetCursor(point);
+ }
+ int GetNonClientComponent(const gfx::Point& point) const override {
+ return HTNOWHERE;
+ }
+ bool ShouldDescendIntoChildForEventHandling(
+ aura::Window* child,
+ const gfx::Point& location) override {
+ return true;
+ }
+ bool CanFocus() override { return true; }
+ void OnCaptureLost() override {}
+ void OnPaint(const ui::PaintContext& context) override {}
+ void OnDeviceScaleFactorChanged(float device_scale_factor) override {}
+ void OnWindowDestroying(aura::Window* window) override {}
+ void OnWindowDestroyed(aura::Window* window) override { delete this; }
+ void OnWindowTargetVisibilityChanged(bool visible) override {}
+ bool HasHitTestMask() const override {
+ return notification_surface_->HasHitTestMask();
+ }
+ void GetHitTestMask(gfx::Path* mask) const override {
+ notification_surface_->GetHitTestMask(mask);
+ }
+ void OnKeyEvent(ui::KeyEvent* event) override {
+ // Propagates the key event upto the top-level views Widget so that we can
+ // trigger proper events in the views/ash level there. Event handling for
+ // Surfaces is done in a post event handler in keyboard.cc.
+ views::Widget* widget = views::Widget::GetTopLevelWidgetForNativeView(
+ notification_surface_->host_window());
+ if (widget)
+ widget->OnKeyEvent(event);
+ }
+
+ private:
+ exo::NotificationSurface* const notification_surface_;
+
+ DISALLOW_COPY_AND_ASSIGN(CustomWindowDelegate);
+};
+
+} // namespace
+
// Handles notification surface role of a given surface.
ArcNotificationSurfaceImpl::ArcNotificationSurfaceImpl(
exo::NotificationSurface* surface)
: surface_(surface) {
DCHECK(surface);
+ native_view_ =
+ base::MakeUnique<aura::Window>(new CustomWindowDelegate(surface));
+ native_view_->SetType(aura::client::WINDOW_TYPE_CONTROL);
+ native_view_->set_owned_by_parent(false);
+ native_view_->Init(ui::LAYER_NOT_DRAWN);
+ native_view_->AddChild(surface_->host_window());
+ native_view_->Show();
}
+ArcNotificationSurfaceImpl::~ArcNotificationSurfaceImpl() = default;
+
gfx::Size ArcNotificationSurfaceImpl::GetSize() const {
return surface_->GetContentSize();
}
@@ -28,12 +96,12 @@ void ArcNotificationSurfaceImpl::Attach(
DCHECK(!native_view_host_);
DCHECK(native_view_host);
native_view_host_ = native_view_host;
- native_view_host->Attach(surface_->host_window());
+ native_view_host->Attach(native_view_.get());
}
void ArcNotificationSurfaceImpl::Detach() {
DCHECK(native_view_host_);
- DCHECK_EQ(surface_->host_window(), native_view_host_->native_view());
+ DCHECK_EQ(native_view_.get(), native_view_host_->native_view());
native_view_host_->Detach();
native_view_host_ = nullptr;
}
@@ -47,17 +115,12 @@ views::NativeViewHost* ArcNotificationSurfaceImpl::GetAttachedHost() const {
}
aura::Window* ArcNotificationSurfaceImpl::GetWindow() const {
- return surface_->host_window();
+ return native_view_.get();
}
aura::Window* ArcNotificationSurfaceImpl::GetContentWindow() const {
DCHECK(surface_->host_window());
- DCHECK(!surface_->host_window()->children().empty());
-
- aura::Window* content_window = surface_->host_window()->children()[0];
-
- DCHECK(!content_window);
- return content_window;
+ return surface_->host_window();
}
const std::string& ArcNotificationSurfaceImpl::GetNotificationKey() const {
diff --git a/chromium/ui/arc/notification/arc_notification_surface_impl.h b/chromium/ui/arc/notification/arc_notification_surface_impl.h
index 122c6d73fe0..3714b073e41 100644
--- a/chromium/ui/arc/notification/arc_notification_surface_impl.h
+++ b/chromium/ui/arc/notification/arc_notification_surface_impl.h
@@ -5,6 +5,8 @@
#ifndef UI_ARC_NOTIFICATION_ARC_NOTIFICATION_SURFACE_IMPL_H_
#define UI_ARC_NOTIFICATION_ARC_NOTIFICATION_SURFACE_IMPL_H_
+#include <memory>
+
#include "ui/arc/notification/arc_notification_surface.h"
namespace exo {
@@ -17,6 +19,7 @@ namespace arc {
class ArcNotificationSurfaceImpl : public ArcNotificationSurface {
public:
explicit ArcNotificationSurfaceImpl(exo::NotificationSurface* surface);
+ ~ArcNotificationSurfaceImpl() override;
// ArcNotificationSurface overrides:
gfx::Size GetSize() const override;
@@ -34,6 +37,7 @@ class ArcNotificationSurfaceImpl : public ArcNotificationSurface {
private:
exo::NotificationSurface* surface_;
views::NativeViewHost* native_view_host_ = nullptr;
+ std::unique_ptr<aura::Window> native_view_;
DISALLOW_COPY_AND_ASSIGN(ArcNotificationSurfaceImpl);
};
diff --git a/chromium/ui/arc/notification/arc_notification_view.cc b/chromium/ui/arc/notification/arc_notification_view.cc
index ef892e6ee82..85f8e818c6a 100644
--- a/chromium/ui/arc/notification/arc_notification_view.cc
+++ b/chromium/ui/arc/notification/arc_notification_view.cc
@@ -14,6 +14,7 @@
#include "ui/gfx/geometry/size.h"
#include "ui/message_center/message_center_style.h"
#include "ui/message_center/views/message_center_controller.h"
+#include "ui/message_center/views/notification_control_buttons_view.h"
#include "ui/views/background.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/image_view.h"
@@ -44,6 +45,8 @@ ArcNotificationView::ArcNotificationView(
contents_view_->background()->get_color());
}
+ UpdateControlButtonsVisibilityWithNotification(notification);
+
focus_painter_ = views::Painter::CreateSolidFocusPainter(
message_center::kFocusBorderColor, gfx::Insets(0, 1, 3, 2));
}
@@ -58,6 +61,13 @@ void ArcNotificationView::OnContentBlured() {
SchedulePaint();
}
+void ArcNotificationView::UpdateWithNotification(
+ const message_center::Notification& notification) {
+ message_center::MessageView::UpdateWithNotification(notification);
+
+ UpdateControlButtonsVisibilityWithNotification(notification);
+}
+
void ArcNotificationView::SetDrawBackgroundAsActive(bool active) {
// Do nothing if |contents_view_| has a background.
if (contents_view_->background())
@@ -96,6 +106,17 @@ ArcNotificationView::GetControlButtonsView() const {
return contents_view_delegate_->GetControlButtonsView();
}
+bool ArcNotificationView::IsExpanded() const {
+ if (contents_view_delegate_)
+ return contents_view_delegate_->IsExpanded();
+ return false;
+}
+
+void ArcNotificationView::SetExpanded(bool expanded) {
+ if (contents_view_delegate_)
+ contents_view_delegate_->SetExpanded(expanded);
+}
+
void ArcNotificationView::OnSlideChanged() {
if (contents_view_delegate_)
contents_view_delegate_->OnSlideChanged();
@@ -103,18 +124,18 @@ void ArcNotificationView::OnSlideChanged() {
gfx::Size ArcNotificationView::CalculatePreferredSize() const {
const gfx::Insets insets = GetInsets();
- const int contents_width =
- message_center::kNotificationWidth - insets.width();
+ const int contents_width = message_center::kNotificationWidth;
const int contents_height = contents_view_->GetHeightForWidth(contents_width);
- return gfx::Size(message_center::kNotificationWidth,
+ return gfx::Size(contents_width + insets.width(),
contents_height + insets.height());
}
void ArcNotificationView::Layout() {
- message_center::MessageView::Layout();
-
+ // Setting the bounds before calling the parent to prevent double Layout.
contents_view_->SetBoundsRect(GetContentsBounds());
+ message_center::MessageView::Layout();
+
// If the content view claims focus, defer focus handling to the content view.
if (contents_view_->IsFocusable())
SetFocusBehavior(FocusBehavior::NEVER);
@@ -176,4 +197,18 @@ bool ArcNotificationView::HandleAccessibleAction(
return false;
}
+// TODO(yoshiki): move this to MessageView and share the code among
+// NotificationView and NotificationViewMD.
+void ArcNotificationView::UpdateControlButtonsVisibilityWithNotification(
+ const message_center::Notification& notification) {
+ if (!GetControlButtonsView())
+ return;
+
+ GetControlButtonsView()->ShowSettingsButton(
+ notification.delegate() &&
+ notification.delegate()->ShouldDisplaySettingsButton());
+ GetControlButtonsView()->ShowCloseButton(!GetPinned());
+ UpdateControlButtonsVisibility();
+}
+
} // namespace message_center
diff --git a/chromium/ui/arc/notification/arc_notification_view.h b/chromium/ui/arc/notification/arc_notification_view.h
index 216361f2f67..7705c4172e0 100644
--- a/chromium/ui/arc/notification/arc_notification_view.h
+++ b/chromium/ui/arc/notification/arc_notification_view.h
@@ -36,6 +36,8 @@ class ArcNotificationView : public message_center::MessageView {
void OnContentBlured();
// Overridden from MessageView:
+ void UpdateWithNotification(
+ const message_center::Notification& notification) override;
void SetDrawBackgroundAsActive(bool active) override;
bool IsCloseButtonFocused() const override;
void RequestFocusOnCloseButton() override;
@@ -43,6 +45,8 @@ class ArcNotificationView : public message_center::MessageView {
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
message_center::NotificationControlButtonsView* GetControlButtonsView()
const override;
+ bool IsExpanded() const override;
+ void SetExpanded(bool expanded) override;
// views::SlideOutController::Delegate:
void OnSlideChanged() override;
@@ -62,6 +66,10 @@ class ArcNotificationView : public message_center::MessageView {
friend class ArcNotificationContentViewTest;
friend class ArcNotificationViewTest;
+ // TODO(yoshiki): Mmove this to message_center::MessageView.
+ void UpdateControlButtonsVisibilityWithNotification(
+ const message_center::Notification& notification);
+
// The view for the custom content. Owned by view hierarchy.
views::View* contents_view_ = nullptr;
std::unique_ptr<ArcNotificationContentViewDelegate> contents_view_delegate_;
diff --git a/chromium/ui/arc/notification/arc_notification_view_unittest.cc b/chromium/ui/arc/notification/arc_notification_view_unittest.cc
index 2130c3d3ca1..dd8646b45c9 100644
--- a/chromium/ui/arc/notification/arc_notification_view_unittest.cc
+++ b/chromium/ui/arc/notification/arc_notification_view_unittest.cc
@@ -82,6 +82,8 @@ class TestContentViewDelegate : public ArcNotificationContentViewDelegate {
const override {
return nullptr;
}
+ bool IsExpanded() const override { return false; }
+ void SetExpanded(bool expanded) override {}
};
class TestNotificationDelegate : public message_center::NotificationDelegate {
diff --git a/chromium/ui/aura/BUILD.gn b/chromium/ui/aura/BUILD.gn
index 2d225353ac2..4bd8c3a3d2b 100644
--- a/chromium/ui/aura/BUILD.gn
+++ b/chromium/ui/aura/BUILD.gn
@@ -15,6 +15,7 @@ component("aura") {
"client/cursor_client_observer.h",
"client/default_capture_client.h",
"client/drag_drop_client.h",
+ "client/drag_drop_client_observer.h",
"client/drag_drop_delegate.h",
"client/event_client.h",
"client/focus_change_observer.h",
@@ -43,6 +44,7 @@ component("aura") {
"mus/focus_synchronizer.h",
"mus/focus_synchronizer_delegate.h",
"mus/focus_synchronizer_observer.h",
+ "mus/hit_test_data_provider_aura.h",
"mus/in_flight_change.h",
"mus/input_method_mus.h",
"mus/mus_context_factory.h",
@@ -72,7 +74,6 @@ component("aura") {
"window_targeter.h",
"window_tracker.h",
"window_tree_host.h",
- "window_tree_host_mac.h",
"window_tree_host_observer.h",
"window_tree_host_platform.h",
]
@@ -105,6 +106,7 @@ component("aura") {
"mus/client_surface_embedder.cc",
"mus/drag_drop_controller_mus.cc",
"mus/focus_synchronizer.cc",
+ "mus/hit_test_data_provider_aura.cc",
"mus/in_flight_change.cc",
"mus/input_method_mus.cc",
"mus/mus_context_factory.cc",
@@ -139,7 +141,6 @@ component("aura") {
"//base:i18n",
"//base/third_party/dynamic_annotations",
"//cc",
- "//cc/surfaces",
"//components/discardable_memory/client",
"//components/discardable_memory/public/interfaces",
"//components/viz/client",
@@ -335,6 +336,8 @@ executable("demo") {
test("aura_unittests") {
sources = [
"gestures/gesture_recognizer_unittest.cc",
+ "mus/drag_drop_controller_mus_unittest.cc",
+ "mus/hit_test_data_provider_aura_unittest.cc",
"mus/input_method_mus_unittest.cc",
"mus/os_exchange_data_provider_mus_unittest.cc",
"mus/property_converter_unittest.cc",
@@ -351,6 +354,7 @@ test("aura_unittests") {
deps = [
":test_support",
"//base/test:test_support",
+ "//components/viz/client",
"//mojo/common",
"//mojo/edk/system",
"//net",
diff --git a/chromium/ui/aura/DEPS b/chromium/ui/aura/DEPS
index cad39bb3678..10caa1bfa7f 100644
--- a/chromium/ui/aura/DEPS
+++ b/chromium/ui/aura/DEPS
@@ -1,7 +1,6 @@
include_rules = [
"+cc/base",
"+cc/output",
- "+cc/surfaces",
"+components/viz/common",
"+components/viz/host",
"+mojo/common",
diff --git a/chromium/ui/aura/client/aura_constants.cc b/chromium/ui/aura/client/aura_constants.cc
index 2792820cd45..1fb0328e221 100644
--- a/chromium/ui/aura/client/aura_constants.cc
+++ b/chromium/ui/aura/client/aura_constants.cc
@@ -9,6 +9,7 @@
#include "ui/gfx/geometry/rect.h"
DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, bool)
+DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, base::TimeDelta)
DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, base::string16*)
DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, ui::ModalType)
DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, gfx::ImageSkia*)
@@ -24,6 +25,7 @@ DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, int64_t)
DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT,
aura::client::WindowEmbedType)
DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, aura::client::FocusClient*)
+DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(AURA_EXPORT, aura::Window*)
namespace aura {
namespace client {
@@ -50,6 +52,7 @@ 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);
DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(gfx::Size, kPreferredSize, nullptr);
diff --git a/chromium/ui/aura/client/aura_constants.h b/chromium/ui/aura/client/aura_constants.h
index 151777dbec1..c6d67043895 100644
--- a/chromium/ui/aura/client/aura_constants.h
+++ b/chromium/ui/aura/client/aura_constants.h
@@ -93,6 +93,9 @@ AURA_EXPORT extern const WindowProperty<gfx::Size*>* const kMinimumSize;
// should render regardless of its actual visibility state.
AURA_EXPORT extern const WindowProperty<bool>* const kMirroringEnabledKey;
+// The modal parent of a child modal window.
+AURA_EXPORT extern const WindowProperty<Window*>* const kChildModalParentKey;
+
// A property key to store the window modality.
AURA_EXPORT extern const WindowProperty<ui::ModalType>* const kModalKey;
diff --git a/chromium/ui/aura/client/drag_drop_client.h b/chromium/ui/aura/client/drag_drop_client.h
index 4015f0f1a93..8e9634807d3 100644
--- a/chromium/ui/aura/client/drag_drop_client.h
+++ b/chromium/ui/aura/client/drag_drop_client.h
@@ -21,6 +21,8 @@ namespace aura {
class Window;
namespace client {
+class DragDropClientObserver;
+
// An interface implemented by an object that controls a drag and drop session.
class AURA_EXPORT DragDropClient {
public:
@@ -28,7 +30,8 @@ class AURA_EXPORT DragDropClient {
// Initiates a drag and drop session. Returns the drag operation that was
// applied at the end of the drag drop session. |screen_location| is in
- // screen coordinates.
+ // screen coordinates. At most one drag and drop operation is allowed.
+ // It must not start drag operation while |IsDragDropInProgress| returns true.
virtual int StartDragAndDrop(const ui::OSExchangeData& data,
aura::Window* root_window,
aura::Window* source_window,
@@ -41,6 +44,9 @@ class AURA_EXPORT DragDropClient {
// Returns true if a drag and drop session is in progress.
virtual bool IsDragDropInProgress() = 0;
+
+ virtual void AddObserver(DragDropClientObserver* observer) = 0;
+ virtual void RemoveObserver(DragDropClientObserver* observer) = 0;
};
AURA_EXPORT void SetDragDropClient(Window* root_window,
diff --git a/chromium/ui/aura/client/drag_drop_client_observer.h b/chromium/ui/aura/client/drag_drop_client_observer.h
new file mode 100644
index 00000000000..e285050b360
--- /dev/null
+++ b/chromium/ui/aura/client/drag_drop_client_observer.h
@@ -0,0 +1,28 @@
+// 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_AURA_CLIENT_DRAG_DROP_CLIENT_OBSERVER_H_
+#define UI_AURA_CLIENT_DRAG_DROP_CLIENT_OBSERVER_H_
+
+#include "ui/aura/aura_export.h"
+
+namespace aura {
+namespace client {
+
+class AURA_EXPORT DragDropClientObserver {
+ public:
+ // Called when dragging started.
+ virtual void OnDragStarted() = 0;
+
+ // Called when dragging ended.
+ virtual void OnDragEnded() = 0;
+
+ protected:
+ virtual ~DragDropClientObserver() = default;
+};
+
+} // namespace client
+} // namespace aura
+
+#endif // UI_AURA_CLIENT_DRAG_DROP_CLIENT_OBSERVER_H_
diff --git a/chromium/ui/aura/env.cc b/chromium/ui/aura/env.cc
index 4493d687a08..5c040ed88b2 100644
--- a/chromium/ui/aura/env.cc
+++ b/chromium/ui/aura/env.cc
@@ -174,7 +174,13 @@ void Env::Init() {
// The ozone platform can provide its own event source. So initialize the
// platform before creating the default event source. If running inside mus
// let the mus process initialize ozone instead.
- ui::OzonePlatform::InitializeForUI();
+ ui::OzonePlatform::InitParams params;
+ base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
+ // TODO(kylechar): Pass in single process information to Env::CreateInstance()
+ // instead of checking flags here.
+ params.single_process = command_line->HasSwitch("single-process") ||
+ command_line->HasSwitch("in-process-gpu");
+ ui::OzonePlatform::InitializeForUI(params);
gfx::ClientNativePixmapFactory::SetInstance(native_pixmap_factory_.get());
#endif
if (!ui::PlatformEventSource::GetInstance())
diff --git a/chromium/ui/aura/env_input_state_controller.h b/chromium/ui/aura/env_input_state_controller.h
index 688774c6769..4ceb29e4db5 100644
--- a/chromium/ui/aura/env_input_state_controller.h
+++ b/chromium/ui/aura/env_input_state_controller.h
@@ -20,6 +20,9 @@ class TouchEvent;
}
namespace aura {
+namespace test {
+class EnvTestHelper;
+}
class Window;
@@ -35,6 +38,7 @@ class AURA_EXPORT EnvInputStateController {
const gfx::Point& location_in_root) const;
private:
+ friend class test::EnvTestHelper;
// Touch ids that are currently down.
uint32_t touch_ids_down_;
diff --git a/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc b/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc
index 8d4bf832546..4294c4fafbd 100644
--- a/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc
+++ b/chromium/ui/aura/gestures/gesture_recognizer_unittest.cc
@@ -1700,8 +1700,8 @@ TEST_F(GestureRecognizerTest, GestureTapFollowedByScroll) {
EXPECT_TRUE(delegate->tap_cancel());
EXPECT_TRUE(delegate->scroll_begin());
EXPECT_TRUE(delegate->scroll_update());
- EXPECT_EQ(15, delegate->scroll_x_hint());
- EXPECT_EQ(15, delegate->scroll_y_hint());
+ EXPECT_EQ(10, delegate->scroll_x_hint());
+ EXPECT_EQ(10, delegate->scroll_y_hint());
delegate->Reset();
@@ -3709,7 +3709,7 @@ TEST_F(GestureRecognizerTest, NoDriftInScroll) {
EXPECT_TRUE(delegate->scroll_update());
// 3 px consumed by touch slop region.
EXPECT_EQ(-1, delegate->scroll_y());
- EXPECT_EQ(-4, delegate->scroll_y_hint());
+ EXPECT_EQ(-1, delegate->scroll_y_hint());
delegate->Reset();
@@ -4096,7 +4096,7 @@ TEST_F(GestureRecognizerTest, TestExceedingSlopSlowly) {
EXPECT_TRUE(delegate->scroll_begin());
EXPECT_TRUE(delegate->scroll_update());
EXPECT_NEAR(0.1, delegate->scroll_x(), 0.0001);
- EXPECT_FLOAT_EQ(3.1f, delegate->scroll_x_hint());
+ EXPECT_NEAR(0.1, delegate->scroll_x_hint(), 0.0001);
delegate->Reset();
ui::TouchEvent move4(
diff --git a/chromium/ui/aura/local/DEPS b/chromium/ui/aura/local/DEPS
index c0790cb5a17..152d4ee35af 100644
--- a/chromium/ui/aura/local/DEPS
+++ b/chromium/ui/aura/local/DEPS
@@ -1,7 +1,6 @@
include_rules = [
"+cc/output",
"+cc/scheduler",
- "+cc/surfaces",
"+components/viz/service/frame_sinks",
]
diff --git a/chromium/ui/aura/local/layer_tree_frame_sink_local.cc b/chromium/ui/aura/local/layer_tree_frame_sink_local.cc
index d87672e5e63..d535bcb4f65 100644
--- a/chromium/ui/aura/local/layer_tree_frame_sink_local.cc
+++ b/chromium/ui/aura/local/layer_tree_frame_sink_local.cc
@@ -5,6 +5,7 @@
#include "ui/aura/local/layer_tree_frame_sink_local.h"
#include "cc/output/layer_tree_frame_sink_client.h"
+#include "components/viz/common/surfaces/surface_info.h"
#include "components/viz/host/host_frame_sink_manager.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support.h"
#include "ui/aura/client/cursor_client.h"
@@ -21,9 +22,14 @@ LayerTreeFrameSinkLocal::LayerTreeFrameSinkLocal(
viz::HostFrameSinkManager* host_frame_sink_manager)
: cc::LayerTreeFrameSink(nullptr, nullptr, nullptr, nullptr),
frame_sink_id_(frame_sink_id),
- host_frame_sink_manager_(host_frame_sink_manager) {}
+ host_frame_sink_manager_(host_frame_sink_manager),
+ weak_factory_(this) {
+ host_frame_sink_manager_->RegisterFrameSinkId(frame_sink_id_, this);
+}
-LayerTreeFrameSinkLocal::~LayerTreeFrameSinkLocal() {}
+LayerTreeFrameSinkLocal::~LayerTreeFrameSinkLocal() {
+ host_frame_sink_manager_->InvalidateFrameSinkId(frame_sink_id_);
+}
bool LayerTreeFrameSinkLocal::BindToClient(
cc::LayerTreeFrameSinkClient* client) {
@@ -34,9 +40,8 @@ bool LayerTreeFrameSinkLocal::BindToClient(
support_ = host_frame_sink_manager_->CreateCompositorFrameSinkSupport(
this, frame_sink_id_, false /* is_root */,
- true /* handles_frame_sink_id_invalidation */,
true /* needs_sync_points */);
- begin_frame_source_ = base::MakeUnique<cc::ExternalBeginFrameSource>(this);
+ begin_frame_source_ = base::MakeUnique<viz::ExternalBeginFrameSource>(this);
client->SetBeginFrameSource(begin_frame_source_.get());
return true;
}
@@ -47,6 +52,10 @@ void LayerTreeFrameSinkLocal::SetSurfaceChangedCallback(
surface_changed_callback_ = callback;
}
+base::WeakPtr<LayerTreeFrameSinkLocal> LayerTreeFrameSinkLocal::GetWeakPtr() {
+ return weak_factory_.GetWeakPtr();
+}
+
void LayerTreeFrameSinkLocal::DetachFromClient() {
DCHECK(thread_checker_);
DCHECK(thread_checker_->CalledOnValidThread());
@@ -58,42 +67,37 @@ void LayerTreeFrameSinkLocal::DetachFromClient() {
cc::LayerTreeFrameSink::DetachFromClient();
}
+void LayerTreeFrameSinkLocal::SetLocalSurfaceId(
+ const viz::LocalSurfaceId& local_surface_id) {
+ DCHECK(local_surface_id.is_valid());
+ local_surface_id_ = local_surface_id;
+}
+
void LayerTreeFrameSinkLocal::SubmitCompositorFrame(cc::CompositorFrame frame) {
DCHECK(thread_checker_);
DCHECK(thread_checker_->CalledOnValidThread());
DCHECK(frame.metadata.begin_frame_ack.has_damage);
- DCHECK_LE(cc::BeginFrameArgs::kStartingFrameNumber,
+ DCHECK_LE(viz::BeginFrameArgs::kStartingFrameNumber,
frame.metadata.begin_frame_ack.sequence_number);
- viz::LocalSurfaceId old_local_surface_id = local_surface_id_;
- const auto& frame_size = frame.render_pass_list.back()->output_rect.size();
- if (frame_size != surface_size_ ||
- frame.metadata.device_scale_factor != device_scale_factor_ ||
- !local_surface_id_.is_valid()) {
- surface_size_ = frame_size;
- device_scale_factor_ = frame.metadata.device_scale_factor;
- local_surface_id_ = id_allocator_.GenerateId();
- }
+ DCHECK(local_surface_id_.is_valid());
+
bool result =
support_->SubmitCompositorFrame(local_surface_id_, std::move(frame));
DCHECK(result);
-
- if (local_surface_id_ != old_local_surface_id) {
- surface_changed_callback_.Run(
- viz::SurfaceId(frame_sink_id_, local_surface_id_), surface_size_);
- }
}
-void LayerTreeFrameSinkLocal::DidNotProduceFrame(const cc::BeginFrameAck& ack) {
+void LayerTreeFrameSinkLocal::DidNotProduceFrame(
+ const viz::BeginFrameAck& ack) {
DCHECK(thread_checker_);
DCHECK(thread_checker_->CalledOnValidThread());
DCHECK(!ack.has_damage);
- DCHECK_LE(cc::BeginFrameArgs::kStartingFrameNumber, ack.sequence_number);
+ DCHECK_LE(viz::BeginFrameArgs::kStartingFrameNumber, ack.sequence_number);
support_->DidNotProduceFrame(ack);
}
void LayerTreeFrameSinkLocal::DidReceiveCompositorFrameAck(
- const std::vector<cc::ReturnedResource>& resources) {
+ const std::vector<viz::ReturnedResource>& resources) {
DCHECK(thread_checker_);
DCHECK(thread_checker_->CalledOnValidThread());
if (!client_)
@@ -103,7 +107,7 @@ void LayerTreeFrameSinkLocal::DidReceiveCompositorFrameAck(
client_->DidReceiveCompositorFrameAck();
}
-void LayerTreeFrameSinkLocal::OnBeginFrame(const cc::BeginFrameArgs& args) {
+void LayerTreeFrameSinkLocal::OnBeginFrame(const viz::BeginFrameArgs& args) {
DCHECK(thread_checker_);
DCHECK(thread_checker_->CalledOnValidThread());
begin_frame_source_->OnBeginFrame(args);
@@ -116,7 +120,7 @@ void LayerTreeFrameSinkLocal::OnBeginFramePausedChanged(bool paused) {
}
void LayerTreeFrameSinkLocal::ReclaimResources(
- const std::vector<cc::ReturnedResource>& resources) {
+ const std::vector<viz::ReturnedResource>& resources) {
DCHECK(thread_checker_);
DCHECK(thread_checker_->CalledOnValidThread());
if (!client_)
@@ -130,4 +134,9 @@ void LayerTreeFrameSinkLocal::OnNeedsBeginFrames(bool needs_begin_frames) {
support_->SetNeedsBeginFrame(needs_begin_frames);
}
+void LayerTreeFrameSinkLocal::OnFirstSurfaceActivation(
+ const viz::SurfaceInfo& surface_info) {
+ surface_changed_callback_.Run(surface_info);
+}
+
} // namespace aura
diff --git a/chromium/ui/aura/local/layer_tree_frame_sink_local.h b/chromium/ui/aura/local/layer_tree_frame_sink_local.h
index ab074b03a8c..116d30e478c 100644
--- a/chromium/ui/aura/local/layer_tree_frame_sink_local.h
+++ b/chromium/ui/aura/local/layer_tree_frame_sink_local.h
@@ -7,10 +7,11 @@
#include "base/callback.h"
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "cc/output/layer_tree_frame_sink.h"
-#include "cc/scheduler/begin_frame_source.h"
+#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
-#include "components/viz/common/surfaces/local_surface_id_allocator.h"
+#include "components/viz/host/host_frame_sink_client.h"
#include "components/viz/service/frame_sinks/compositor_frame_sink_support_client.h"
#include "ui/aura/window_port.h"
#include "ui/base/property_data.h"
@@ -28,47 +29,53 @@ namespace aura {
// aura::Window's ui::Layer.
class LayerTreeFrameSinkLocal : public cc::LayerTreeFrameSink,
public viz::CompositorFrameSinkSupportClient,
- public cc::ExternalBeginFrameSourceClient {
+ public viz::ExternalBeginFrameSourceClient,
+ public viz::HostFrameSinkClient {
public:
LayerTreeFrameSinkLocal(const viz::FrameSinkId& frame_sink_id,
viz::HostFrameSinkManager* host_frame_sink_manager);
~LayerTreeFrameSinkLocal() override;
- using SurfaceChangedCallback =
- base::Callback<void(const viz::SurfaceId&, const gfx::Size&)>;
+ using SurfaceChangedCallback = base::Callback<void(const viz::SurfaceInfo&)>;
+
// Set a callback which will be called when the surface is changed.
void SetSurfaceChangedCallback(const SurfaceChangedCallback& callback);
+ base::WeakPtr<LayerTreeFrameSinkLocal> GetWeakPtr();
+
// cc::LayerTreeFrameSink:
bool BindToClient(cc::LayerTreeFrameSinkClient* client) override;
void DetachFromClient() override;
+ void SetLocalSurfaceId(const viz::LocalSurfaceId& local_surface_id) override;
void SubmitCompositorFrame(cc::CompositorFrame frame) override;
- void DidNotProduceFrame(const cc::BeginFrameAck& ack) override;
+ void DidNotProduceFrame(const viz::BeginFrameAck& ack) override;
// viz::CompositorFrameSinkSupportClient:
void DidReceiveCompositorFrameAck(
- const std::vector<cc::ReturnedResource>& resources) override;
- void OnBeginFrame(const cc::BeginFrameArgs& args) override;
+ const std::vector<viz::ReturnedResource>& resources) override;
+ void OnBeginFrame(const viz::BeginFrameArgs& args) override;
void ReclaimResources(
- const std::vector<cc::ReturnedResource>& resources) override;
+ const std::vector<viz::ReturnedResource>& resources) override;
void WillDrawSurface(const viz::LocalSurfaceId& local_surface_id,
const gfx::Rect& damage_rect) override {}
void OnBeginFramePausedChanged(bool paused) override;
- // cc::ExternalBeginFrameSourceClient:
+ // viz::ExternalBeginFrameSourceClient:
void OnNeedsBeginFrames(bool needs_begin_frames) override;
private:
+ // public viz::HostFrameSinkClient:
+ void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
+
const viz::FrameSinkId frame_sink_id_;
viz::HostFrameSinkManager* const host_frame_sink_manager_;
std::unique_ptr<viz::CompositorFrameSinkSupport> support_;
gfx::Size surface_size_;
- float device_scale_factor_ = 0;
- viz::LocalSurfaceIdAllocator id_allocator_;
viz::LocalSurfaceId local_surface_id_;
- std::unique_ptr<cc::ExternalBeginFrameSource> begin_frame_source_;
+ std::unique_ptr<viz::ExternalBeginFrameSource> begin_frame_source_;
std::unique_ptr<base::ThreadChecker> thread_checker_;
SurfaceChangedCallback surface_changed_callback_;
+ base::WeakPtrFactory<LayerTreeFrameSinkLocal> weak_factory_;
DISALLOW_COPY_AND_ASSIGN(LayerTreeFrameSinkLocal);
};
diff --git a/chromium/ui/aura/local/window_port_local.cc b/chromium/ui/aura/local/window_port_local.cc
index 2ed5ca8134a..fc60d26d5c8 100644
--- a/chromium/ui/aura/local/window_port_local.cc
+++ b/chromium/ui/aura/local/window_port_local.cc
@@ -10,6 +10,7 @@
#include "ui/aura/local/layer_tree_frame_sink_local.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
+#include "ui/base/layout.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
@@ -65,6 +66,14 @@ WindowPortLocal::~WindowPortLocal() {}
void WindowPortLocal::OnPreInit(Window* window) {}
void WindowPortLocal::OnDeviceScaleFactorChanged(float device_scale_factor) {
+ if (last_device_scale_factor_ != device_scale_factor &&
+ local_surface_id_.is_valid()) {
+ last_device_scale_factor_ = device_scale_factor;
+ local_surface_id_ = local_surface_id_allocator_.GenerateId();
+ if (frame_sink_)
+ frame_sink_->SetLocalSurfaceId(local_surface_id_);
+ }
+
ScopedCursorHider hider(window_);
if (window_->delegate())
window_->delegate()->OnDeviceScaleFactorChanged(device_scale_factor);
@@ -80,7 +89,14 @@ void WindowPortLocal::OnWillMoveChild(size_t current_index, size_t dest_index) {
void WindowPortLocal::OnVisibilityChanged(bool visible) {}
void WindowPortLocal::OnDidChangeBounds(const gfx::Rect& old_bounds,
- const gfx::Rect& new_bounds) {}
+ const gfx::Rect& new_bounds) {
+ if (last_size_ != new_bounds.size() && local_surface_id_.is_valid()) {
+ last_size_ = new_bounds.size();
+ local_surface_id_ = local_surface_id_allocator_.GenerateId();
+ if (frame_sink_)
+ frame_sink_->SetLocalSurfaceId(local_surface_id_);
+ }
+}
void WindowPortLocal::OnDidChangeTransform(
const gfx::Transform& old_transform,
@@ -106,6 +122,9 @@ WindowPortLocal::CreateLayerTreeFrameSink() {
frame_sink_id_, context_factory_private->GetHostFrameSinkManager());
frame_sink->SetSurfaceChangedCallback(base::Bind(
&WindowPortLocal::OnSurfaceChanged, weak_factory_.GetWeakPtr()));
+ frame_sink_ = frame_sink->GetWeakPtr();
+ local_surface_id_ = local_surface_id_allocator_.GenerateId();
+ frame_sink->SetLocalSurfaceId(local_surface_id_);
if (window_->GetRootWindow())
window_->layer()->GetCompositor()->AddFrameSink(frame_sink_id_);
return std::move(frame_sink);
@@ -115,6 +134,25 @@ viz::SurfaceId WindowPortLocal::GetSurfaceId() const {
return viz::SurfaceId(frame_sink_id_, local_surface_id_);
}
+void WindowPortLocal::AllocateLocalSurfaceId() {
+ local_surface_id_ = local_surface_id_allocator_.GenerateId();
+ if (frame_sink_)
+ frame_sink_->SetLocalSurfaceId(local_surface_id_);
+}
+
+const viz::LocalSurfaceId& WindowPortLocal::GetLocalSurfaceId() {
+ if (!local_surface_id_.is_valid()) {
+ last_device_scale_factor_ = ui::GetScaleFactorForNativeView(window_);
+ last_size_ = window_->bounds().size();
+ local_surface_id_ = local_surface_id_allocator_.GenerateId();
+ }
+ return local_surface_id_;
+}
+
+viz::FrameSinkId WindowPortLocal::GetFrameSinkId() const {
+ return frame_sink_id_;
+}
+
void WindowPortLocal::OnWindowAddedToRootWindow() {
if (frame_sink_id_.is_valid())
window_->layer()->GetCompositor()->AddFrameSink(frame_sink_id_);
@@ -125,11 +163,11 @@ void WindowPortLocal::OnWillRemoveWindowFromRootWindow() {
window_->layer()->GetCompositor()->RemoveFrameSink(frame_sink_id_);
}
-void WindowPortLocal::OnSurfaceChanged(const viz::SurfaceId& surface_id,
- const gfx::Size& surface_size) {
- DCHECK_EQ(surface_id.frame_sink_id(), frame_sink_id_);
- local_surface_id_ = surface_id.local_surface_id();
- viz::SurfaceInfo surface_info(surface_id, 1.0f, surface_size);
+void WindowPortLocal::OnEventTargetingPolicyChanged() {}
+
+void WindowPortLocal::OnSurfaceChanged(const viz::SurfaceInfo& surface_info) {
+ DCHECK_EQ(surface_info.id().frame_sink_id(), frame_sink_id_);
+ DCHECK_EQ(surface_info.id().local_surface_id(), local_surface_id_);
scoped_refptr<viz::SurfaceReferenceFactory> reference_factory =
aura::Env::GetInstance()
->context_factory_private()
diff --git a/chromium/ui/aura/local/window_port_local.h b/chromium/ui/aura/local/window_port_local.h
index 7ab9ea1f0eb..68a29a2fc4a 100644
--- a/chromium/ui/aura/local/window_port_local.h
+++ b/chromium/ui/aura/local/window_port_local.h
@@ -8,8 +8,11 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "components/viz/common/surfaces/frame_sink_id.h"
+#include "components/viz/common/surfaces/local_surface_id_allocator.h"
+#include "ui/aura/local/layer_tree_frame_sink_local.h"
#include "ui/aura/window_port.h"
#include "ui/base/property_data.h"
+#include "ui/gfx/geometry/size.h"
namespace gfx {
class Size;
@@ -43,16 +46,23 @@ class AURA_EXPORT WindowPortLocal : public WindowPort {
std::unique_ptr<ui::PropertyData> data) override;
std::unique_ptr<cc::LayerTreeFrameSink> CreateLayerTreeFrameSink() override;
viz::SurfaceId GetSurfaceId() const override;
+ void AllocateLocalSurfaceId() override;
+ const viz::LocalSurfaceId& GetLocalSurfaceId() override;
+ viz::FrameSinkId GetFrameSinkId() const override;
void OnWindowAddedToRootWindow() override;
void OnWillRemoveWindowFromRootWindow() override;
+ void OnEventTargetingPolicyChanged() override;
private:
- void OnSurfaceChanged(const viz::SurfaceId& surface_id,
- const gfx::Size& surface_size);
+ void OnSurfaceChanged(const viz::SurfaceInfo& surface_info);
Window* const window_;
viz::FrameSinkId frame_sink_id_;
+ gfx::Size last_size_;
+ float last_device_scale_factor_ = 1.0f;
viz::LocalSurfaceId local_surface_id_;
+ viz::LocalSurfaceIdAllocator local_surface_id_allocator_;
+ base::WeakPtr<aura::LayerTreeFrameSinkLocal> frame_sink_;
base::WeakPtrFactory<WindowPortLocal> weak_factory_;
diff --git a/chromium/ui/aura/mus/DEPS b/chromium/ui/aura/mus/DEPS
index 2f08e4b543d..1f379237e61 100644
--- a/chromium/ui/aura/mus/DEPS
+++ b/chromium/ui/aura/mus/DEPS
@@ -4,23 +4,15 @@ include_rules = [
"+cc/output/layer_tree_frame_sink_client.h",
"+cc/output/layer_tree_frame_sink.h",
"+cc/scheduler/begin_frame_source.h",
- "+cc/surfaces/local_surface_id.h",
- "+cc/surfaces/local_surface_id_allocator.h",
- "+cc/surfaces/surface_info.h",
- "+cc/surfaces/surface_manager.h",
- "+cc/surfaces/surface_reference_factory.h",
"+components/discardable_memory/client/client_discardable_shared_memory_manager.h",
"+components/viz/client",
- "+components/viz/common/gpu",
+ "+components/viz/common",
"+gpu/command_buffer/client/gpu_memory_buffer_manager.h",
"+gpu/ipc/client/gpu_channel_host.h",
"+mojo/public/cpp/system/buffer.h",
"+mojo/public/cpp/system/platform_handle.h",
"+services/ui/common/accelerator_util.h",
"+services/ui/common/task_runner_test_base.h",
- "+services/ui/public/cpp/gpu",
- "+services/ui/public/cpp/property_type_converters.h",
- "+services/ui/public/cpp/raster_thread_helper.h",
- "+services/ui/public/cpp/client_layer_tree_frame_sink.h",
+ "+services/ui/public",
"+ui/gl/gl_bindings.h",
]
diff --git a/chromium/ui/aura/mus/client_surface_embedder.cc b/chromium/ui/aura/mus/client_surface_embedder.cc
index cf439ce2375..e14dcd5254d 100644
--- a/chromium/ui/aura/mus/client_surface_embedder.cc
+++ b/chromium/ui/aura/mus/client_surface_embedder.cc
@@ -5,7 +5,7 @@
#include "ui/aura/mus/client_surface_embedder.h"
#include "base/memory/ptr_util.h"
-#include "cc/surfaces/stub_surface_reference_factory.h"
+#include "components/viz/common/surfaces/stub_surface_reference_factory.h"
#include "ui/aura/window.h"
#include "ui/gfx/geometry/dip_util.h"
@@ -27,7 +27,7 @@ ClientSurfaceEmbedder::ClientSurfaceEmbedder(
// this is the case with window decorations provided by Window Manager.
// This content should appear underneath the content of the embedded client.
window_->layer()->StackAtTop(surface_layer_.get());
- ref_factory_ = new cc::StubSurfaceReferenceFactory();
+ ref_factory_ = new viz::StubSurfaceReferenceFactory();
}
ClientSurfaceEmbedder::~ClientSurfaceEmbedder() = default;
diff --git a/chromium/ui/aura/mus/drag_drop_controller_mus.cc b/chromium/ui/aura/mus/drag_drop_controller_mus.cc
index 0d64f7b0258..fea4fc0554f 100644
--- a/chromium/ui/aura/mus/drag_drop_controller_mus.cc
+++ b/chromium/ui/aura/mus/drag_drop_controller_mus.cc
@@ -15,7 +15,9 @@
#include "mojo/public/cpp/bindings/map.h"
#include "services/ui/public/interfaces/window_tree.mojom.h"
#include "services/ui/public/interfaces/window_tree_constants.mojom.h"
+#include "ui/aura/client/drag_drop_client_observer.h"
#include "ui/aura/client/drag_drop_delegate.h"
+#include "ui/aura/env.h"
#include "ui/aura/mus/drag_drop_controller_host.h"
#include "ui/aura/mus/mus_types.h"
#include "ui/aura/mus/os_exchange_data_provider_mus.h"
@@ -116,8 +118,11 @@ uint32_t DragDropControllerMus::OnCompleteDrop(
void DragDropControllerMus::OnPerformDragDropCompleted(uint32_t action_taken) {
DCHECK(current_drag_state_);
+ for (client::DragDropClientObserver& observer : observers_)
+ observer.OnDragEnded();
current_drag_state_->completed_action = action_taken;
current_drag_state_->runloop_quit_closure.Run();
+ current_drag_state_ = nullptr;
}
void DragDropControllerMus::OnDragDropDone() {
@@ -140,8 +145,10 @@ int DragDropControllerMus::StartDragAndDrop(
CurrentDragState current_drag_state = {root_window_mus->server_id(),
change_id, ui::mojom::kDropEffectNone,
data, run_loop.QuitClosure()};
- base::AutoReset<CurrentDragState*> resetter(&current_drag_state_,
- &current_drag_state);
+
+ // current_drag_state_ will be reset in |OnPerformDragDropCompleted| before
+ // run_loop.Run() quits.
+ current_drag_state_ = &current_drag_state;
base::MessageLoop* loop = base::MessageLoop::current();
base::MessageLoop::ScopedNestableTaskAllower allow_nested(loop);
@@ -155,6 +162,10 @@ int DragDropControllerMus::StartDragAndDrop(
std::map<std::string, std::vector<uint8_t>> drag_data =
static_cast<const aura::OSExchangeDataProviderMus&>(data.provider())
.GetData();
+
+ for (client::DragDropClientObserver& observer : observers_)
+ observer.OnDragStarted();
+
window_tree_->PerformDragDrop(
change_id, root_window_mus->server_id(), screen_location,
mojo::MapToUnorderedMap(drag_data),
@@ -162,7 +173,6 @@ int DragDropControllerMus::StartDragAndDrop(
data.provider().GetDragImageOffset(), drag_operations, mojo_source);
run_loop.Run();
-
return current_drag_state.completed_action;
}
@@ -176,6 +186,16 @@ bool DragDropControllerMus::IsDragDropInProgress() {
return current_drag_state_ != nullptr;
}
+void DragDropControllerMus::AddObserver(
+ client::DragDropClientObserver* observer) {
+ observers_.AddObserver(observer);
+}
+
+void DragDropControllerMus::RemoveObserver(
+ client::DragDropClientObserver* observer) {
+ observers_.RemoveObserver(observer);
+}
+
uint32_t DragDropControllerMus::HandleDragEnterOrOver(
WindowMus* window,
uint32_t event_flags,
diff --git a/chromium/ui/aura/mus/drag_drop_controller_mus.h b/chromium/ui/aura/mus/drag_drop_controller_mus.h
index 92700dcb992..e161339ded1 100644
--- a/chromium/ui/aura/mus/drag_drop_controller_mus.h
+++ b/chromium/ui/aura/mus/drag_drop_controller_mus.h
@@ -11,6 +11,8 @@
#include <memory>
#include <vector>
+#include "base/observer_list.h"
+#include "ui/aura/aura_export.h"
#include "ui/aura/client/drag_drop_client.h"
#include "ui/aura/window_tracker.h"
#include "ui/base/dragdrop/drag_drop_types.h"
@@ -32,7 +34,7 @@ class WindowMus;
// DragDropControllerMus acts as the DragDropClient for aura as well as
// handling all drag operations from the server. Drag operations are forwarded
// to the client::DragDropDelegate set on the target Window.
-class DragDropControllerMus : public client::DragDropClient {
+class AURA_EXPORT DragDropControllerMus : public client::DragDropClient {
public:
DragDropControllerMus(DragDropControllerHost* drag_drop_controller_host,
ui::mojom::WindowTree* window_tree);
@@ -70,6 +72,8 @@ class DragDropControllerMus : public client::DragDropClient {
ui::DragDropTypes::DragEventSource source) override;
void DragCancel() override;
bool IsDragDropInProgress() override;
+ void AddObserver(client::DragDropClientObserver* observer) override;
+ void RemoveObserver(client::DragDropClientObserver* observer) override;
private:
struct CurrentDragState;
@@ -105,6 +109,8 @@ class DragDropControllerMus : public client::DragDropClient {
// Used to track the current drop target.
WindowTracker drop_target_window_tracker_;
+ base::ObserverList<client::DragDropClientObserver> observers_;
+
DISALLOW_COPY_AND_ASSIGN(DragDropControllerMus);
};
diff --git a/chromium/ui/aura/mus/drag_drop_controller_mus_unittest.cc b/chromium/ui/aura/mus/drag_drop_controller_mus_unittest.cc
new file mode 100644
index 00000000000..55964c70bd8
--- /dev/null
+++ b/chromium/ui/aura/mus/drag_drop_controller_mus_unittest.cc
@@ -0,0 +1,170 @@
+// 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/aura/mus/drag_drop_controller_mus.h"
+
+#include <memory>
+
+#include "base/callback_forward.h"
+#include "base/memory/ptr_util.h"
+#include "base/strings/utf_string_conversions.h"
+#include "base/task_scheduler/post_task.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "ui/aura/client/drag_drop_client_observer.h"
+#include "ui/aura/client/drag_drop_delegate.h"
+#include "ui/aura/mus/drag_drop_controller_host.h"
+#include "ui/aura/mus/window_mus.h"
+#include "ui/aura/test/aura_mus_test_base.h"
+#include "ui/aura/test/mus/test_window_tree.h"
+#include "ui/base/dragdrop/drop_target_event.h"
+#include "ui/events/event_utils.h"
+
+namespace aura {
+namespace {
+
+class DragDropControllerMusTest : public test::AuraMusWmTestBase {
+ public:
+ DragDropControllerMusTest() = default;
+
+ // test::AuraMusWmTestBase
+ void SetUp() override {
+ AuraMusWmTestBase::SetUp();
+ controller_ = base::MakeUnique<DragDropControllerMus>(&controller_host_,
+ window_tree());
+ window_ = std::unique_ptr<aura::Window>(
+ CreateNormalWindow(0, root_window(), nullptr));
+ }
+
+ void TearDown() override {
+ window_.reset();
+ controller_.reset();
+ AuraMusWmTestBase::TearDown();
+ }
+
+ protected:
+ void PostDragMoveAndDrop() {
+ // Posted task will be run when the inner loop runs in StartDragAndDrop.
+ ASSERT_TRUE(base::ThreadTaskRunnerHandle::IsSet());
+ base::ThreadTaskRunnerHandle::Get()->PostTask(
+ FROM_HERE, base::BindOnce(&DragDropControllerMusTest::DragMoveAndDrop,
+ base::Unretained(this)));
+ }
+
+ void StartDragAndDrop() {
+ controller_->StartDragAndDrop(
+ ui::OSExchangeData(), window_->GetRootWindow(), window_.get(),
+ gfx::Point(5, 5), ui::DragDropTypes::DRAG_MOVE,
+ ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
+ }
+
+ std::unique_ptr<DragDropControllerMus> controller_;
+ std::unique_ptr<aura::Window> window_;
+
+ private:
+ void DragMoveAndDrop() {
+ WindowMus* const window_mus = WindowMus::Get(window_.get());
+ controller_->OnDragEnter(window_mus, 0, gfx::Point(5, 20), 0);
+ controller_->OnDragOver(window_mus, 0, gfx::Point(5, 20), 0);
+ controller_->OnCompleteDrop(window_mus, 0, gfx::Point(5, 20), 0);
+ controller_->OnPerformDragDropCompleted(0);
+ }
+
+ class TestDragDropControllerHost : public DragDropControllerHost {
+ public:
+ TestDragDropControllerHost() : serial_(0u) {}
+
+ // DragDropControllerHost
+ uint32_t CreateChangeIdForDrag(WindowMus* window) override {
+ return serial_++;
+ }
+
+ private:
+ uint32_t serial_;
+
+ } controller_host_;
+
+ DISALLOW_COPY_AND_ASSIGN(DragDropControllerMusTest);
+};
+
+TEST_F(DragDropControllerMusTest, DragStartedAndEndedEvents) {
+ enum class State { kNotInvoked, kDragStartInvoked, kDragEndInvoked };
+
+ class TestObserver : public client::DragDropClientObserver {
+ public:
+ TestObserver() = default;
+ State state() const { return state_; }
+
+ // Overrides from client::DragDropClientObserver:
+ void OnDragStarted() override {
+ EXPECT_EQ(State::kNotInvoked, state_);
+ state_ = State::kDragStartInvoked;
+ }
+ void OnDragEnded() override {
+ EXPECT_EQ(State::kDragStartInvoked, state_);
+ state_ = State::kDragEndInvoked;
+ }
+
+ private:
+ State state_{State::kNotInvoked};
+
+ DISALLOW_COPY_AND_ASSIGN(TestObserver);
+ } observer;
+
+ controller_->AddObserver(&observer);
+ PostDragMoveAndDrop();
+ StartDragAndDrop();
+ EXPECT_EQ(State::kDragEndInvoked, observer.state());
+ controller_->RemoveObserver(&observer);
+}
+
+TEST_F(DragDropControllerMusTest, EventTarget) {
+ enum class State {
+ kNotInvoked,
+ kDragEnteredInvoked,
+ kDragUpdateInvoked,
+ kPerformDropInvoked
+ };
+
+ class TestDelegate : public client::DragDropDelegate {
+ public:
+ TestDelegate(aura::Window* window) : window_(window) {}
+ State state() const { return state_; }
+
+ // Overrides from client::DragDropClientObserver:
+ void OnDragEntered(const ui::DropTargetEvent& event) override {
+ EXPECT_EQ(State::kNotInvoked, state_);
+ EXPECT_EQ(window_, event.target());
+ state_ = State::kDragEnteredInvoked;
+ }
+ int OnDragUpdated(const ui::DropTargetEvent& event) override {
+ EXPECT_TRUE(State::kDragEnteredInvoked == state_ ||
+ State::kDragUpdateInvoked == state_);
+ EXPECT_EQ(window_, event.target());
+ state_ = State::kDragUpdateInvoked;
+ return ui::DragDropTypes::DRAG_MOVE;
+ }
+ void OnDragExited() override { ADD_FAILURE(); }
+ int OnPerformDrop(const ui::DropTargetEvent& event) override {
+ EXPECT_EQ(State::kDragUpdateInvoked, state_);
+ EXPECT_EQ(window_, event.target());
+ state_ = State::kPerformDropInvoked;
+ return ui::DragDropTypes::DRAG_MOVE;
+ }
+
+ private:
+ aura::Window* const window_;
+ State state_{State::kNotInvoked};
+
+ DISALLOW_COPY_AND_ASSIGN(TestDelegate);
+ } delegate(window_.get());
+
+ client::SetDragDropDelegate(window_.get(), &delegate);
+ PostDragMoveAndDrop();
+ StartDragAndDrop();
+ EXPECT_EQ(State::kPerformDropInvoked, delegate.state());
+ client::SetDragDropDelegate(window_.get(), nullptr);
+}
+
+} // namespace
+} // namespace aura
diff --git a/chromium/ui/aura/mus/hit_test_data_provider_aura.cc b/chromium/ui/aura/mus/hit_test_data_provider_aura.cc
new file mode 100644
index 00000000000..db915077e08
--- /dev/null
+++ b/chromium/ui/aura/mus/hit_test_data_provider_aura.cc
@@ -0,0 +1,133 @@
+// 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/aura/mus/hit_test_data_provider_aura.h"
+
+#include "base/containers/adapters.h"
+#include "services/ui/public/interfaces/window_tree_constants.mojom.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_targeter.h"
+
+namespace {
+
+viz::mojom::HitTestRegionPtr CreateHitTestRegion(const aura::Window* window,
+ uint32_t flags,
+ const gfx::Rect& rect) {
+ const ui::Layer* layer = window->layer();
+ DCHECK(layer);
+
+ auto hit_test_region = viz::mojom::HitTestRegion::New();
+ DCHECK(window->GetFrameSinkId().is_valid());
+ hit_test_region->frame_sink_id = window->GetFrameSinkId();
+ if (layer->GetPrimarySurfaceInfo()) {
+ DCHECK(window->GetFrameSinkId() ==
+ layer->GetPrimarySurfaceInfo()->id().frame_sink_id());
+ hit_test_region->local_surface_id =
+ layer->GetPrimarySurfaceInfo()->id().local_surface_id();
+ }
+ hit_test_region->flags = flags;
+ hit_test_region->rect = rect;
+ hit_test_region->transform = layer->transform();
+
+ return hit_test_region;
+}
+
+} // namespace
+
+namespace aura {
+
+HitTestDataProviderAura::HitTestDataProviderAura(aura::Window* window)
+ : window_(window) {}
+
+HitTestDataProviderAura::~HitTestDataProviderAura() {}
+
+viz::mojom::HitTestRegionListPtr HitTestDataProviderAura::GetHitTestData()
+ const {
+ const ui::mojom::EventTargetingPolicy event_targeting_policy =
+ window_->event_targeting_policy();
+ if (event_targeting_policy == ui::mojom::EventTargetingPolicy::NONE)
+ return nullptr;
+
+ auto hit_test_region_list = viz::mojom::HitTestRegionList::New();
+ hit_test_region_list->flags =
+ event_targeting_policy ==
+ ui::mojom::EventTargetingPolicy::DESCENDANTS_ONLY
+ ? viz::mojom::kHitTestIgnore
+ : viz::mojom::kHitTestMine;
+ hit_test_region_list->bounds = window_->bounds();
+
+ GetHitTestDataRecursively(window_, hit_test_region_list.get());
+ return hit_test_region_list;
+}
+
+void HitTestDataProviderAura::GetHitTestDataRecursively(
+ aura::Window* window,
+ viz::mojom::HitTestRegionList* hit_test_region_list) const {
+ WindowTargeter* targeter =
+ static_cast<WindowTargeter*>(window->GetEventTargeter());
+
+ // TODO(varkha): Figure out if we need to add hit-test regions for |window|.
+ // Walk the children in Z-order (reversed order of children()) to produce
+ // the hit-test data. Each child's hit test data is added before the hit-test
+ // data from the child's descendants because the child could clip its
+ // descendants for the purpose of event handling.
+ for (aura::Window* child : base::Reversed(window->children())) {
+ const ui::mojom::EventTargetingPolicy event_targeting_policy =
+ child->event_targeting_policy();
+ if (event_targeting_policy == ui::mojom::EventTargetingPolicy::NONE)
+ continue;
+ if (event_targeting_policy !=
+ ui::mojom::EventTargetingPolicy::DESCENDANTS_ONLY) {
+ gfx::Rect rect_mouse(child->bounds());
+ gfx::Rect rect_touch;
+ bool touch_and_mouse_are_same = true;
+ uint32_t flags = child->layer()->GetPrimarySurfaceInfo()
+ ? viz::mojom::kHitTestChildSurface
+ : viz::mojom::kHitTestMine;
+ // Use the |targeter| to query for possibly expanded hit-test area.
+ // Use the |child| bounds with mouse and touch flags when there is no
+ // |targeter|.
+ if (targeter &&
+ targeter->GetHitTestRects(child, &rect_mouse, &rect_touch)) {
+ touch_and_mouse_are_same = rect_mouse == rect_touch;
+ }
+
+ auto shape_rects =
+ targeter ? targeter->GetExtraHitTestShapeRects(child) : nullptr;
+ if (shape_rects) {
+ // The |child| has a complex shape. Clip it to |rect_mouse|.
+ const gfx::Vector2d offset = child->bounds().OffsetFromOrigin();
+ for (const gfx::Rect& shape_rect : *shape_rects) {
+ gfx::Rect rect = shape_rect;
+ rect.Offset(offset);
+ rect.Intersect(rect_mouse);
+ if (rect.IsEmpty())
+ continue;
+ hit_test_region_list->regions.push_back(CreateHitTestRegion(
+ child,
+ flags | viz::mojom::kHitTestMouse | viz::mojom::kHitTestTouch,
+ rect));
+ }
+ } else {
+ // The |child| has possibly same mouse and touch hit-test areas.
+ if (!rect_mouse.IsEmpty()) {
+ hit_test_region_list->regions.push_back(CreateHitTestRegion(
+ child,
+ flags | (touch_and_mouse_are_same ? (viz::mojom::kHitTestMouse |
+ viz::mojom::kHitTestTouch)
+ : viz::mojom::kHitTestMouse),
+ rect_mouse));
+ }
+ if (!touch_and_mouse_are_same && !rect_touch.IsEmpty()) {
+ hit_test_region_list->regions.push_back(CreateHitTestRegion(
+ child, flags | viz::mojom::kHitTestTouch, rect_touch));
+ }
+ }
+ }
+ if (event_targeting_policy != ui::mojom::EventTargetingPolicy::TARGET_ONLY)
+ GetHitTestDataRecursively(child, hit_test_region_list);
+ }
+}
+
+} // namespace aura
diff --git a/chromium/ui/aura/mus/hit_test_data_provider_aura.h b/chromium/ui/aura/mus/hit_test_data_provider_aura.h
new file mode 100644
index 00000000000..04b7748b494
--- /dev/null
+++ b/chromium/ui/aura/mus/hit_test_data_provider_aura.h
@@ -0,0 +1,41 @@
+// 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_AURA_MUS_HIT_TEST_DATA_PROVIDER_AURA_H_
+#define UI_AURA_MUS_HIT_TEST_DATA_PROVIDER_AURA_H_
+
+#include "base/macros.h"
+#include "components/viz/client/hit_test_data_provider.h"
+
+namespace aura {
+
+class Window;
+
+// A HitTestDataProvider that captures hit-test areas from a aura::Window tree
+// and packages it to be submitted to compositor frame sink. The |window| used
+// when creating the HitTestDataProviderAura should outlive the data provider.
+class HitTestDataProviderAura : public viz::HitTestDataProvider {
+ public:
+ explicit HitTestDataProviderAura(Window* window);
+ ~HitTestDataProviderAura() override;
+
+ // HitTestDataProvider:
+ viz::mojom::HitTestRegionListPtr GetHitTestData() const override;
+
+ private:
+ // Recursively walks the children of |window| and uses |window|'s
+ // EventTargeter to generate hit-test data for the |window|'s descendants.
+ // Populates |hit_test_region_list|.
+ void GetHitTestDataRecursively(
+ aura::Window* window,
+ viz::mojom::HitTestRegionList* hit_test_region_list) const;
+
+ aura::Window* const window_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(HitTestDataProviderAura);
+};
+
+} // namespace aura
+
+#endif // UI_AURA_MUS_HIT_TEST_DATA_PROVIDER_AURA_H_ \ No newline at end of file
diff --git a/chromium/ui/aura/mus/hit_test_data_provider_aura_unittest.cc b/chromium/ui/aura/mus/hit_test_data_provider_aura_unittest.cc
new file mode 100644
index 00000000000..5f8611fe1b2
--- /dev/null
+++ b/chromium/ui/aura/mus/hit_test_data_provider_aura_unittest.cc
@@ -0,0 +1,290 @@
+// 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/aura/mus/window_tree_client.h"
+
+#include "components/viz/client/hit_test_data_provider.h"
+#include "ui/aura/client/aura_constants.h"
+#include "ui/aura/mus/window_port_mus.h"
+#include "ui/aura/test/aura_mus_test_base.h"
+#include "ui/aura/window.h"
+#include "ui/aura/window_targeter.h"
+#include "ui/gfx/geometry/rect.h"
+
+namespace aura {
+
+namespace {
+
+const int kMouseInset = -5;
+const int kTouchInset = -10;
+
+// Custom WindowTargeter that expands hit-test regions of child windows.
+class TestWindowTargeter : public WindowTargeter {
+ public:
+ TestWindowTargeter() {
+ SetInsets(gfx::Insets(kMouseInset), gfx::Insets(kTouchInset));
+ }
+ ~TestWindowTargeter() override {}
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestWindowTargeter);
+};
+
+// Custom WindowTargeter that replaces hit-test area on a window with a frame
+// rectangle and a hole in the middle 1/3.
+// ----------------------
+// | hit hit |
+// | ---------- |
+// | | | |
+// | | No hit | hit |
+// | | | |
+// | hit | | |
+// | ---------- |
+// | hit hit |
+// ----------------------
+class TestHoleWindowTargeter : public aura::WindowTargeter {
+ public:
+ TestHoleWindowTargeter() = default;
+ ~TestHoleWindowTargeter() override {}
+
+ private:
+ // aura::WindowTargeter:
+ std::unique_ptr<aura::WindowTargeter::HitTestRects> GetExtraHitTestShapeRects(
+ aura::Window* target) const override {
+ gfx::Rect bounds = target->bounds();
+ int x0 = 0;
+ int x1 = bounds.width() / 3;
+ int x2 = bounds.width() - bounds.width() / 3;
+ int x3 = bounds.width();
+ int y0 = 0;
+ int y1 = bounds.height() / 3;
+ int y2 = bounds.height() - bounds.height() / 3;
+ int y3 = bounds.height();
+ auto shape_rects = base::MakeUnique<aura::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);
+ shape_rects->emplace_back(x0, y2, bounds.width(), y3 - y2);
+ return shape_rects;
+ }
+
+ DISALLOW_COPY_AND_ASSIGN(TestHoleWindowTargeter);
+};
+
+} // namespace
+
+// Creates a root window and child windows. Maintains a cc:LayerTreeFrameSink
+// to help exercise its viz::HitTestDataProvider.
+class HitTestDataProviderAuraTest : public test::AuraTestBaseMus {
+ public:
+ HitTestDataProviderAuraTest() {}
+ ~HitTestDataProviderAuraTest() override {}
+
+ void SetUp() override {
+ test::AuraTestBaseMus::SetUp();
+
+ root_ = base::MakeUnique<Window>(nullptr);
+ root_->Init(ui::LAYER_NOT_DRAWN);
+ root_->SetEventTargeter(base::MakeUnique<WindowTargeter>());
+ root_->SetBounds(gfx::Rect(0, 0, 300, 200));
+
+ window2_ = new Window(nullptr);
+ window2_->Init(ui::LAYER_TEXTURED);
+ window2_->SetBounds(gfx::Rect(20, 30, 40, 60));
+
+ window3_ = new Window(nullptr);
+ window3_->Init(ui::LAYER_TEXTURED);
+ window3_->SetEventTargeter(base::MakeUnique<WindowTargeter>());
+ window3_->SetBounds(gfx::Rect(50, 60, 100, 40));
+
+ window4_ = new Window(nullptr);
+ window4_->Init(ui::LAYER_TEXTURED);
+ window4_->SetBounds(gfx::Rect(20, 10, 60, 30));
+
+ window3_->AddChild(window4_);
+ root_->AddChild(window2_);
+ root_->AddChild(window3_);
+
+ WindowPort* port = WindowPortMus::Get(root_.get());
+ sink_ = port->CreateLayerTreeFrameSink();
+ }
+
+ protected:
+ const viz::HitTestDataProvider* hit_test_data_provider() const {
+ // TODO(varkha): Find a way to get the HitTestDataProvider without depending
+ // on WindowPortMus
+ WindowPortMus* port = WindowPortMus::Get(root_.get());
+ return port->local_layer_tree_frame_sink_->hit_test_data_provider();
+ }
+
+ Window* root() { return root_.get(); }
+ Window* window2() { return window2_; }
+ Window* window3() { return window3_; }
+ Window* window4() { return window4_; }
+
+ private:
+ std::unique_ptr<cc::LayerTreeFrameSink> sink_;
+ std::unique_ptr<Window> root_;
+ Window* window2_;
+ Window* window3_;
+ Window* window4_;
+
+ DISALLOW_COPY_AND_ASSIGN(HitTestDataProviderAuraTest);
+};
+
+// TODO(riajiang): Add test cases for kHitTestChildSurface to ensure
+// that local_surface_id is set and used correctly.
+
+// Tests that the order of reported hit-test regions matches windows Z-order.
+TEST_F(HitTestDataProviderAuraTest, Stacking) {
+ const auto hit_test_data_1 = hit_test_data_provider()->GetHitTestData();
+ ASSERT_TRUE(hit_test_data_1);
+ EXPECT_EQ(hit_test_data_1->flags, viz::mojom::kHitTestMine);
+ EXPECT_EQ(hit_test_data_1->bounds, root()->bounds());
+ Window* expected_order_1[] = {window3(), window4(), window2()};
+ EXPECT_EQ(hit_test_data_1->regions.size(), arraysize(expected_order_1));
+ int i = 0;
+ for (const auto& region : hit_test_data_1->regions) {
+ EXPECT_EQ(region->flags, viz::mojom::kHitTestMine |
+ viz::mojom::kHitTestMouse |
+ viz::mojom::kHitTestTouch);
+ EXPECT_EQ(region->frame_sink_id, expected_order_1[i]->GetFrameSinkId());
+ EXPECT_EQ(region->rect.ToString(),
+ expected_order_1[i]->bounds().ToString());
+ i++;
+ }
+
+ root()->StackChildAbove(window2(), window3());
+ const auto hit_test_data_2 = hit_test_data_provider()->GetHitTestData();
+ ASSERT_TRUE(hit_test_data_2);
+ EXPECT_EQ(hit_test_data_2->flags, viz::mojom::kHitTestMine);
+ EXPECT_EQ(hit_test_data_2->bounds, root()->bounds());
+
+ Window* expected_order_2[] = {window2(), window3(), window4()};
+ EXPECT_EQ(hit_test_data_2->regions.size(), arraysize(expected_order_2));
+ i = 0;
+ for (const auto& region : hit_test_data_2->regions) {
+ EXPECT_EQ(region->flags, viz::mojom::kHitTestMine |
+ viz::mojom::kHitTestMouse |
+ viz::mojom::kHitTestTouch);
+ EXPECT_EQ(region->frame_sink_id, expected_order_2[i]->GetFrameSinkId());
+ EXPECT_EQ(region->rect.ToString(),
+ expected_order_2[i]->bounds().ToString());
+ i++;
+ }
+}
+
+// Tests that the hit-test regions get expanded with a custom event targeter.
+TEST_F(HitTestDataProviderAuraTest, CustomTargeter) {
+ window3()->SetEventTargeter(base::MakeUnique<TestWindowTargeter>());
+ const auto hit_test_data = hit_test_data_provider()->GetHitTestData();
+ ASSERT_TRUE(hit_test_data);
+ EXPECT_EQ(hit_test_data->flags, viz::mojom::kHitTestMine);
+ EXPECT_EQ(hit_test_data->bounds, root()->bounds());
+
+ // Children of a container that has the custom targeter installed will get
+ // reported twice, once with hit-test bounds optimized for mouse events and
+ // another time with bounds expanded more for touch input.
+ Window* expected_windows[] = {window3(), window4(), window4(), window2()};
+ uint32_t expected_flags[] = {
+ viz::mojom::kHitTestMine | viz::mojom::kHitTestMouse |
+ viz::mojom::kHitTestTouch,
+ viz::mojom::kHitTestMine | viz::mojom::kHitTestMouse,
+ viz::mojom::kHitTestMine | viz::mojom::kHitTestTouch,
+ viz::mojom::kHitTestMine | viz::mojom::kHitTestMouse |
+ viz::mojom::kHitTestTouch};
+ int expected_insets[] = {0, kMouseInset, kTouchInset, 0};
+ ASSERT_EQ(hit_test_data->regions.size(), arraysize(expected_windows));
+ ASSERT_EQ(hit_test_data->regions.size(), arraysize(expected_flags));
+ ASSERT_EQ(hit_test_data->regions.size(), arraysize(expected_insets));
+ int i = 0;
+ for (const auto& region : hit_test_data->regions) {
+ EXPECT_EQ(region->frame_sink_id, expected_windows[i]->GetFrameSinkId());
+ EXPECT_EQ(region->flags, expected_flags[i]);
+ gfx::Rect expected_bounds = expected_windows[i]->bounds();
+ expected_bounds.Inset(gfx::Insets(expected_insets[i]));
+ EXPECT_EQ(region->rect.ToString(), expected_bounds.ToString());
+ i++;
+ }
+}
+
+// Tests that the complex hit-test shape can be set with a custom targeter.
+TEST_F(HitTestDataProviderAuraTest, HoleTargeter) {
+ window3()->SetEventTargeter(base::MakeUnique<TestHoleWindowTargeter>());
+ const auto hit_test_data = hit_test_data_provider()->GetHitTestData();
+ ASSERT_TRUE(hit_test_data);
+ EXPECT_EQ(hit_test_data->flags, viz::mojom::kHitTestMine);
+ EXPECT_EQ(hit_test_data->bounds, root()->bounds());
+
+ // Children of a container that has the custom targeter installed will get
+ // reported 4 times for each of the hit test regions defined by the custom
+ // targeter.
+ Window* expected_windows[] = {window3(), window4(), window4(),
+ window4(), window4(), window2()};
+ uint32_t expected_flags = viz::mojom::kHitTestMine |
+ viz::mojom::kHitTestMouse |
+ viz::mojom::kHitTestTouch;
+ std::vector<gfx::Rect> expected_bounds;
+ expected_bounds.push_back(window3()->bounds());
+
+ // original window4 is at gfx::Rect(20, 10, 60, 30).
+ expected_bounds.emplace_back(20, 10, 60, 10);
+ expected_bounds.emplace_back(20, 20, 20, 10);
+ expected_bounds.emplace_back(60, 20, 20, 10);
+ expected_bounds.emplace_back(20, 30, 60, 10);
+
+ expected_bounds.push_back(window2()->bounds());
+
+ ASSERT_EQ(hit_test_data->regions.size(), arraysize(expected_windows));
+ ASSERT_EQ(hit_test_data->regions.size(), expected_bounds.size());
+ int i = 0;
+ for (const auto& region : hit_test_data->regions) {
+ EXPECT_EQ(region->frame_sink_id, expected_windows[i]->GetFrameSinkId());
+ EXPECT_EQ(region->flags, expected_flags);
+ EXPECT_EQ(region->rect.ToString(), expected_bounds[i].ToString());
+ i++;
+ }
+}
+
+TEST_F(HitTestDataProviderAuraTest, TargetingPolicies) {
+ root()->SetEventTargetingPolicy(ui::mojom::EventTargetingPolicy::NONE);
+ auto hit_test_data = hit_test_data_provider()->GetHitTestData();
+ ASSERT_FALSE(hit_test_data);
+
+ root()->SetEventTargetingPolicy(ui::mojom::EventTargetingPolicy::TARGET_ONLY);
+ window3()->SetEventTargetingPolicy(
+ ui::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS);
+ hit_test_data = hit_test_data_provider()->GetHitTestData();
+ ASSERT_TRUE(hit_test_data);
+ EXPECT_EQ(hit_test_data->flags, viz::mojom::kHitTestMine);
+ EXPECT_EQ(hit_test_data->regions.size(), 3U);
+
+ root()->SetEventTargetingPolicy(ui::mojom::EventTargetingPolicy::TARGET_ONLY);
+ window3()->SetEventTargetingPolicy(
+ ui::mojom::EventTargetingPolicy::TARGET_ONLY);
+ hit_test_data = hit_test_data_provider()->GetHitTestData();
+ ASSERT_TRUE(hit_test_data);
+ EXPECT_EQ(hit_test_data->flags, viz::mojom::kHitTestMine);
+ EXPECT_EQ(hit_test_data->regions.size(), 2U);
+
+ root()->SetEventTargetingPolicy(
+ ui::mojom::EventTargetingPolicy::DESCENDANTS_ONLY);
+ window3()->SetEventTargetingPolicy(
+ ui::mojom::EventTargetingPolicy::DESCENDANTS_ONLY);
+ hit_test_data = hit_test_data_provider()->GetHitTestData();
+ ASSERT_TRUE(hit_test_data);
+ EXPECT_EQ(hit_test_data->flags, viz::mojom::kHitTestIgnore);
+ EXPECT_EQ(hit_test_data->regions.size(), 2U);
+
+ root()->SetEventTargetingPolicy(
+ ui::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS);
+ window3()->SetEventTargetingPolicy(
+ ui::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS);
+ hit_test_data = hit_test_data_provider()->GetHitTestData();
+ ASSERT_TRUE(hit_test_data);
+ EXPECT_EQ(hit_test_data->flags, viz::mojom::kHitTestMine);
+ EXPECT_EQ(hit_test_data->regions.size(), 3U);
+}
+
+} // namespace aura
diff --git a/chromium/ui/aura/mus/in_flight_change.h b/chromium/ui/aura/mus/in_flight_change.h
index 40b3dcbcc6c..0422d2f20be 100644
--- a/chromium/ui/aura/mus/in_flight_change.h
+++ b/chromium/ui/aura/mus/in_flight_change.h
@@ -41,6 +41,7 @@ enum class ChangeType {
ADD_TRANSIENT_WINDOW,
BOUNDS,
CAPTURE,
+ CHILD_MODAL_PARENT,
DELETE_WINDOW,
DRAG_LOOP,
FOCUS,
diff --git a/chromium/ui/aura/mus/mus_context_factory.cc b/chromium/ui/aura/mus/mus_context_factory.cc
index ed99ef60c9f..6cab93e4813 100644
--- a/chromium/ui/aura/mus/mus_context_factory.cc
+++ b/chromium/ui/aura/mus/mus_context_factory.cc
@@ -8,11 +8,11 @@
#include "base/memory/ptr_util.h"
#include "cc/base/switches.h"
#include "components/viz/common/gpu/context_provider.h"
+#include "components/viz/host/renderer_settings_creation.h"
#include "services/ui/public/cpp/gpu/gpu.h"
#include "ui/aura/mus/window_port_mus.h"
#include "ui/aura/window_tree_host.h"
#include "ui/compositor/compositor_switches.h"
-#include "ui/compositor/compositor_util.h"
#include "ui/display/display_switches.h"
#include "ui/gfx/switches.h"
#include "ui/gl/gl_bindings.h"
@@ -39,8 +39,8 @@ viz::BufferToTextureTargetMap CreateBufferToTextureTargetMap() {
MusContextFactory::MusContextFactory(ui::Gpu* gpu)
: gpu_(gpu),
- renderer_settings_(
- ui::CreateRendererSettings(CreateBufferToTextureTargetMap())),
+ resource_settings_(
+ viz::CreateResourceSettings(CreateBufferToTextureTargetMap())),
weak_ptr_factory_(this) {}
MusContextFactory::~MusContextFactory() {}
@@ -104,7 +104,7 @@ cc::TaskGraphRunner* MusContextFactory::GetTaskGraphRunner() {
}
const viz::ResourceSettings& MusContextFactory::GetResourceSettings() const {
- return renderer_settings_.resource_settings;
+ return resource_settings_;
}
} // namespace aura
diff --git a/chromium/ui/aura/mus/mus_context_factory.h b/chromium/ui/aura/mus/mus_context_factory.h
index 3634f7b4c0c..ab1b1950f62 100644
--- a/chromium/ui/aura/mus/mus_context_factory.h
+++ b/chromium/ui/aura/mus/mus_context_factory.h
@@ -10,7 +10,6 @@
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/memory/weak_ptr.h"
-#include "cc/surfaces/surface_manager.h"
#include "components/viz/common/display/renderer_settings.h"
#include "components/viz/common/gpu/context_provider.h"
#include "services/ui/public/cpp/raster_thread_helper.h"
@@ -58,7 +57,7 @@ class AURA_EXPORT MusContextFactory : public ui::ContextFactory {
ui::RasterThreadHelper raster_thread_helper_;
ui::Gpu* gpu_;
- const viz::RendererSettings renderer_settings_;
+ const viz::ResourceSettings resource_settings_;
scoped_refptr<viz::ContextProvider> shared_main_thread_context_provider_;
base::WeakPtrFactory<MusContextFactory> weak_ptr_factory_;
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 04e7539f04a..cfdf82b7ef0 100644
--- a/chromium/ui/aura/mus/os_exchange_data_provider_mus.cc
+++ b/chromium/ui/aura/mus/os_exchange_data_provider_mus.cc
@@ -251,7 +251,7 @@ bool OSExchangeDataProviderMus::HasCustomFormat(
// These methods were added in an ad-hoc way to different operating
// systems. We need to support them until they get cleaned up.
-#if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN)
+#if defined(USE_X11) || defined(OS_WIN)
void OSExchangeDataProviderMus::SetFileContents(
const base::FilePath& filename,
const std::string& file_contents) {}
diff --git a/chromium/ui/aura/mus/os_exchange_data_provider_mus.h b/chromium/ui/aura/mus/os_exchange_data_provider_mus.h
index 777da5ac293..27a541950dd 100644
--- a/chromium/ui/aura/mus/os_exchange_data_provider_mus.h
+++ b/chromium/ui/aura/mus/os_exchange_data_provider_mus.h
@@ -68,7 +68,7 @@ class AURA_EXPORT OSExchangeDataProviderMus
// per operating system. Now we have to have at least two providers per OS,
// leading to the following warts, which will remain until we clean all the
// callsites up.
-#if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN)
+#if defined(USE_X11) || defined(OS_WIN)
void SetFileContents(const base::FilePath& filename,
const std::string& file_contents) override;
#endif
diff --git a/chromium/ui/aura/mus/user_activity_forwarder.h b/chromium/ui/aura/mus/user_activity_forwarder.h
index d1890424b88..58d28529ed1 100644
--- a/chromium/ui/aura/mus/user_activity_forwarder.h
+++ b/chromium/ui/aura/mus/user_activity_forwarder.h
@@ -24,7 +24,7 @@ namespace aura {
// downstream of ui::UserActivityDetector) instead observe UserActivityMonitor
// directly: http://crbug.com/626899
class AURA_EXPORT UserActivityForwarder
- : NON_EXPORTED_BASE(public ui::mojom::UserActivityObserver) {
+ : public ui::mojom::UserActivityObserver {
public:
UserActivityForwarder(ui::mojom::UserActivityMonitorPtr monitor,
ui::UserActivityDetector* detector);
diff --git a/chromium/ui/aura/mus/user_activity_forwarder_unittest.cc b/chromium/ui/aura/mus/user_activity_forwarder_unittest.cc
index dc2fd59f428..9d011c0e723 100644
--- a/chromium/ui/aura/mus/user_activity_forwarder_unittest.cc
+++ b/chromium/ui/aura/mus/user_activity_forwarder_unittest.cc
@@ -71,7 +71,8 @@ TEST_F(UserActivityForwarderTest, ForwardActivityToDetector) {
// Run pending tasks so |monitor| receives |forwarder|'s registration.
RunUntilIdle();
- base::TimeTicks now = base::TimeTicks::FromInternalValue(1000);
+ base::TimeTicks now =
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(1000);
detector.set_now_for_test(now);
monitor.NotifyUserActivityObservers();
RunUntilIdle();
diff --git a/chromium/ui/aura/mus/window_manager_delegate.cc b/chromium/ui/aura/mus/window_manager_delegate.cc
index e2f42eb1fab..0bf4087a847 100644
--- a/chromium/ui/aura/mus/window_manager_delegate.cc
+++ b/chromium/ui/aura/mus/window_manager_delegate.cc
@@ -15,4 +15,6 @@ ui::mojom::EventResult WindowManagerDelegate::OnAccelerator(
return ui::mojom::EventResult::UNHANDLED;
}
+void WindowManagerDelegate::OnEventBlockedByModalWindow(Window* window) {}
+
} // namespace aura
diff --git a/chromium/ui/aura/mus/window_manager_delegate.h b/chromium/ui/aura/mus/window_manager_delegate.h
index d3df4610aa2..bd3332ef53e 100644
--- a/chromium/ui/aura/mus/window_manager_delegate.h
+++ b/chromium/ui/aura/mus/window_manager_delegate.h
@@ -41,6 +41,12 @@ class WindowTreeHostMus;
struct WindowTreeHostMusInitParams;
+// This mirrors ui::mojom::BlockingContainers. See it for details.
+struct BlockingContainers {
+ aura::Window* system_modal_container = nullptr;
+ aura::Window* min_container = nullptr;
+};
+
// See the mojom with the same name for details on the functions in this
// interface.
class AURA_EXPORT WindowManagerClient {
@@ -56,7 +62,6 @@ class AURA_EXPORT WindowManagerClient {
virtual void RemoveAccelerator(uint32_t id) = 0;
virtual void AddActivationParent(Window* window) = 0;
virtual void RemoveActivationParent(Window* window) = 0;
- virtual void ActivateNextWindow() = 0;
virtual void SetExtendedHitRegionForChildren(
Window* window,
const gfx::Insets& mouse_area,
@@ -80,6 +85,12 @@ class AURA_EXPORT WindowManagerClient {
virtual void SetGlobalOverrideCursor(
base::Optional<ui::CursorData> cursor) = 0;
+ // Sets whether the cursor is visible because the user touched the
+ // screen. This bit is separate from SetCursorVisible(), as it implicitly is
+ // set in the window server when a touch event occurs, and is implicitly
+ // cleared when the mouse moves.
+ virtual void SetCursorTouchVisible(bool enabled) = 0;
+
// Sets the list of keys which don't hide the cursor.
virtual void SetKeyEventsThatDontHideCursor(
std::vector<ui::mojom::EventMatcherPtr> cursor_key_list) = 0;
@@ -89,6 +100,11 @@ class AURA_EXPORT WindowManagerClient {
// this does nothing.
virtual void RequestClose(Window* window) = 0;
+ // See mojom::WindowManager::SetBlockingContainers() and
+ // mojom::BlockingContainers for details on what this does.
+ virtual void SetBlockingContainers(
+ const std::vector<BlockingContainers>& all_blocking_containers) = 0;
+
// Blocks until the initial displays have been received, or if displays are
// not automatically created until the connection to mus has been
// established.
@@ -217,6 +233,10 @@ class AURA_EXPORT WindowManagerDelegate {
const ui::Event& event,
std::unordered_map<std::string, std::vector<uint8_t>>* properties);
+ // Called when the mouse cursor is shown or hidden in response to a touch
+ // event or window manager call.
+ virtual void OnCursorTouchVisibleChanged(bool enabled) = 0;
+
virtual void OnWmPerformMoveLoop(
Window* window,
ui::mojom::MoveLoopSource source,
@@ -238,6 +258,10 @@ class AURA_EXPORT WindowManagerDelegate {
// window.
virtual void OnWmDeactivateWindow(Window* window) = 0;
+ // Called when an event is blocked by a modal window. |window| is the modal
+ // window that blocked the event.
+ virtual void OnEventBlockedByModalWindow(Window* window);
+
protected:
virtual ~WindowManagerDelegate() {}
};
diff --git a/chromium/ui/aura/mus/window_mus.h b/chromium/ui/aura/mus/window_mus.h
index acf13fd17aa..4b734983e1e 100644
--- a/chromium/ui/aura/mus/window_mus.h
+++ b/chromium/ui/aura/mus/window_mus.h
@@ -14,10 +14,6 @@
#include "ui/aura/aura_export.h"
#include "ui/aura/mus/mus_types.h"
-namespace cc {
-class SurfaceInfo;
-}
-
namespace gfx {
class Rect;
class Transform;
@@ -29,6 +25,12 @@ enum class OrderDirection;
}
}
+namespace viz {
+class FrameSinkId;
+class LocalSurfaceId;
+class SurfaceInfo;
+}
+
namespace aura {
class Window;
@@ -60,6 +62,9 @@ class AURA_EXPORT WindowMus {
virtual ~WindowMus() {}
// Returns the WindowMus associated with |window|.
+ static const WindowMus* Get(const Window* window) {
+ return const_cast<const WindowMus*>(Get(const_cast<Window*>(window)));
+ }
static WindowMus* Get(Window* window);
Id server_id() const { return server_id_; }
diff --git a/chromium/ui/aura/mus/window_port_mus.cc b/chromium/ui/aura/mus/window_port_mus.cc
index 4915a5e13db..3b937f13e8b 100644
--- a/chromium/ui/aura/mus/window_port_mus.cc
+++ b/chromium/ui/aura/mus/window_port_mus.cc
@@ -10,6 +10,7 @@
#include "ui/aura/client/transient_window_client.h"
#include "ui/aura/env.h"
#include "ui/aura/mus/client_surface_embedder.h"
+#include "ui/aura/mus/hit_test_data_provider_aura.h"
#include "ui/aura/mus/property_converter.h"
#include "ui/aura/mus/window_tree_client.h"
#include "ui/aura/mus/window_tree_client_delegate.h"
@@ -107,11 +108,11 @@ std::unique_ptr<viz::ClientLayerTreeFrameSink>
WindowPortMus::RequestLayerTreeFrameSink(
scoped_refptr<viz::ContextProvider> context_provider,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager) {
- cc::mojom::CompositorFrameSinkPtrInfo sink_info;
- cc::mojom::CompositorFrameSinkRequest sink_request =
+ viz::mojom::CompositorFrameSinkPtrInfo sink_info;
+ viz::mojom::CompositorFrameSinkRequest sink_request =
mojo::MakeRequest(&sink_info);
- cc::mojom::CompositorFrameSinkClientPtr client;
- cc::mojom::CompositorFrameSinkClientRequest client_request =
+ viz::mojom::CompositorFrameSinkClientPtr client;
+ viz::mojom::CompositorFrameSinkClientRequest client_request =
mojo::MakeRequest(&client);
constexpr bool enable_surface_synchronization = true;
auto layer_tree_frame_sink = base::MakeUnique<viz::ClientLayerTreeFrameSink>(
@@ -119,6 +120,7 @@ WindowPortMus::RequestLayerTreeFrameSink(
gpu_memory_buffer_manager, nullptr /* shared_bitmap_manager */,
nullptr /* synthetic_begin_frame_source */, std::move(sink_info),
std::move(client_request),
+ base::MakeUnique<HitTestDataProviderAura>(window_),
base::MakeUnique<viz::DefaultLocalSurfaceIdProvider>(),
enable_surface_synchronization);
window_tree_client_->AttachCompositorFrameSink(
@@ -126,6 +128,12 @@ WindowPortMus::RequestLayerTreeFrameSink(
return layer_tree_frame_sink;
}
+viz::FrameSinkId WindowPortMus::GetFrameSinkId() const {
+ if (embed_frame_sink_id_.is_valid())
+ return embed_frame_sink_id_;
+ return viz::FrameSinkId(0, server_id());
+}
+
WindowPortMus::ServerChangeIdType WindowPortMus::ScheduleChange(
const ServerChangeType type,
const ServerChangeData& data) {
@@ -293,7 +301,7 @@ void WindowPortMus::SetFrameSinkIdFromServer(
const viz::FrameSinkId& frame_sink_id) {
DCHECK(window_mus_type() == WindowMusType::TOP_LEVEL_IN_WM ||
window_mus_type() == WindowMusType::EMBED_IN_OWNER);
- frame_sink_id_ = frame_sink_id;
+ embed_frame_sink_id_ = frame_sink_id;
UpdatePrimarySurfaceInfo();
}
@@ -311,7 +319,7 @@ const viz::LocalSurfaceId& WindowPortMus::GetOrAllocateLocalSurfaceId(
// The newly generated frame by the embedder will block in the display
// compositor until the child submits a corresponding CompositorFrame or a
// deadline hits.
- if (frame_sink_id_.is_valid())
+ if (embed_frame_sink_id_.is_valid())
UpdatePrimarySurfaceInfo();
if (local_layer_tree_frame_sink_)
@@ -322,19 +330,21 @@ const viz::LocalSurfaceId& WindowPortMus::GetOrAllocateLocalSurfaceId(
void WindowPortMus::SetFallbackSurfaceInfo(
const viz::SurfaceInfo& surface_info) {
- if (!frame_sink_id_.is_valid()) {
+ if (!embed_frame_sink_id_.is_valid()) {
// |primary_surface_info_| shold not be valid, since we didn't know the
- // |frame_sink_id_|.
+ // |embed_frame_sink_id_|.
DCHECK(!primary_surface_info_.is_valid());
- frame_sink_id_ = surface_info.id().frame_sink_id();
+ embed_frame_sink_id_ = surface_info.id().frame_sink_id();
UpdatePrimarySurfaceInfo();
}
// The frame sink id should never be changed.
- DCHECK_EQ(surface_info.id().frame_sink_id(), frame_sink_id_);
+ DCHECK_EQ(surface_info.id().frame_sink_id(), embed_frame_sink_id_);
fallback_surface_info_ = surface_info;
UpdateClientSurfaceEmbedder();
+ if (window_->delegate())
+ window_->delegate()->OnFirstSurfaceActivation(fallback_surface_info_);
}
void WindowPortMus::DestroyFromServer() {
@@ -392,6 +402,10 @@ WindowPortMus::ChangeSource WindowPortMus::OnTransientChildRemoved(
: ChangeSource::LOCAL;
}
+void WindowPortMus::AllocateLocalSurfaceId() {
+ local_surface_id_ = local_surface_id_allocator_.GenerateId();
+}
+
const viz::LocalSurfaceId& WindowPortMus::GetLocalSurfaceId() {
return local_surface_id_;
}
@@ -451,6 +465,16 @@ void WindowPortMus::OnPreInit(Window* window) {
}
void WindowPortMus::OnDeviceScaleFactorChanged(float device_scale_factor) {
+ // TODO(fsamuel): If we don't have a LayerTreeFrameSinkLocal then we should
+ // let the window server know about the device scale factor change and
+ // the new LocalSurfaceId allocated.
+ if (last_device_scale_factor_ != device_scale_factor &&
+ local_surface_id_.is_valid() && local_layer_tree_frame_sink_) {
+ last_device_scale_factor_ = device_scale_factor;
+ local_surface_id_ = local_surface_id_allocator_.GenerateId();
+ local_layer_tree_frame_sink_->SetLocalSurfaceId(local_surface_id_);
+ }
+
if (window_->delegate())
window_->delegate()->OnDeviceScaleFactorChanged(device_scale_factor);
}
@@ -546,12 +570,20 @@ WindowPortMus::CreateLayerTreeFrameSink() {
nullptr,
aura::Env::GetInstance()->context_factory()->GetGpuMemoryBufferManager());
local_layer_tree_frame_sink_ = frame_sink->GetWeakPtr();
+ local_surface_id_ = local_surface_id_allocator_.GenerateId();
return std::move(frame_sink);
}
viz::SurfaceId WindowPortMus::GetSurfaceId() const {
- // This is only used by WindowPortLocal in unit tests.
- return viz::SurfaceId();
+ return viz::SurfaceId(embed_frame_sink_id_, local_surface_id_);
+}
+
+void WindowPortMus::OnWindowAddedToRootWindow() {}
+
+void WindowPortMus::OnWillRemoveWindowFromRootWindow() {}
+
+void WindowPortMus::OnEventTargetingPolicyChanged() {
+ SetEventTargetingPolicy(window_->event_targeting_policy());
}
void WindowPortMus::UpdatePrimarySurfaceInfo() {
@@ -562,15 +594,13 @@ void WindowPortMus::UpdatePrimarySurfaceInfo() {
return;
}
- if (!frame_sink_id_.is_valid() || !local_surface_id_.is_valid())
+ if (!embed_frame_sink_id_.is_valid() || !local_surface_id_.is_valid())
return;
primary_surface_info_ = viz::SurfaceInfo(
- viz::SurfaceId(frame_sink_id_, local_surface_id_),
+ viz::SurfaceId(embed_frame_sink_id_, local_surface_id_),
ScaleFactorForDisplay(window_), last_surface_size_in_pixels_);
UpdateClientSurfaceEmbedder();
- if (window_->delegate())
- window_->delegate()->OnWindowSurfaceChanged(primary_surface_info_);
}
void WindowPortMus::UpdateClientSurfaceEmbedder() {
diff --git a/chromium/ui/aura/mus/window_port_mus.h b/chromium/ui/aura/mus/window_port_mus.h
index 68936714fd1..b0d5d62cd92 100644
--- a/chromium/ui/aura/mus/window_port_mus.h
+++ b/chromium/ui/aura/mus/window_port_mus.h
@@ -93,11 +93,17 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus {
scoped_refptr<viz::ContextProvider> context_provider,
gpu::GpuMemoryBufferManager* gpu_memory_buffer_manager);
+ // WindowPort:
+ // Returns either the FrameSinkId set by window server or its server_id with
+ // the client id part 0.
+ viz::FrameSinkId GetFrameSinkId() const override;
+
private:
friend class WindowPortMusTestApi;
friend class WindowTreeClient;
friend class WindowTreeClientPrivate;
friend class WindowTreeHostMus;
+ friend class HitTestDataProviderAuraTest;
using ServerChangeIdType = uint8_t;
@@ -242,7 +248,6 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus {
void RemoveTransientChildFromServer(WindowMus* child) override;
ChangeSource OnTransientChildAdded(WindowMus* child) override;
ChangeSource OnTransientChildRemoved(WindowMus* child) override;
- const viz::LocalSurfaceId& GetLocalSurfaceId() override;
std::unique_ptr<WindowMusChangeData> PrepareForServerBoundsChange(
const gfx::Rect& bounds) override;
std::unique_ptr<WindowMusChangeData> PrepareForServerVisibilityChange(
@@ -271,8 +276,11 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus {
std::unique_ptr<ui::PropertyData> data) override;
std::unique_ptr<cc::LayerTreeFrameSink> CreateLayerTreeFrameSink() override;
viz::SurfaceId GetSurfaceId() const override;
- void OnWindowAddedToRootWindow() override {}
- void OnWillRemoveWindowFromRootWindow() override {}
+ void AllocateLocalSurfaceId() override;
+ const viz::LocalSurfaceId& GetLocalSurfaceId() override;
+ void OnWindowAddedToRootWindow() override;
+ void OnWillRemoveWindowFromRootWindow() override;
+ void OnEventTargetingPolicyChanged() override;
void UpdatePrimarySurfaceInfo();
void UpdateClientSurfaceEmbedder();
@@ -287,13 +295,15 @@ class AURA_EXPORT WindowPortMus : public WindowPort, public WindowMus {
ServerChangeIdType next_server_change_id_ = 0;
ServerChanges server_changes_;
- viz::FrameSinkId frame_sink_id_;
+ // Only set when it is embedding another client inside.
+ viz::FrameSinkId embed_frame_sink_id_;
viz::SurfaceInfo primary_surface_info_;
viz::SurfaceInfo fallback_surface_info_;
viz::LocalSurfaceId local_surface_id_;
viz::LocalSurfaceIdAllocator local_surface_id_allocator_;
+ float last_device_scale_factor_ = 1.0f;
gfx::Size last_surface_size_in_pixels_;
ui::CursorData cursor_;
diff --git a/chromium/ui/aura/mus/window_tree_client.cc b/chromium/ui/aura/mus/window_tree_client.cc
index 8d64f8deada..a06044dba27 100644
--- a/chromium/ui/aura/mus/window_tree_client.cc
+++ b/chromium/ui/aura/mus/window_tree_client.cc
@@ -72,14 +72,6 @@
namespace aura {
namespace {
-// This serves to document the places that rely on bounds changes to the
-// root window being ignored.
-constexpr bool kRootWindowBoundsChangesAreIgnored = true;
-
-Id MakeTransportId(ClientSpecificId client_id, ClientSpecificId local_id) {
- return (client_id << 16) | local_id;
-}
-
inline uint16_t HiWord(uint32_t id) {
return static_cast<uint16_t>((id >> 16) & 0xFFFF);
}
@@ -135,7 +127,7 @@ WindowTreeHostMus* GetWindowTreeHostMus(WindowMus* window) {
}
bool IsInternalProperty(const void* key) {
- return key == client::kModalKey;
+ return key == client::kModalKey || key == client::kChildModalParentKey;
}
void SetWindowTypeFromProperties(
@@ -158,21 +150,6 @@ float ScaleFactorForDisplay(Window* window) {
return ui::GetScaleFactorForNativeView(window);
}
-void ConvertEventLocationToDip(int64_t display_id, ui::LocatedEvent* event) {
- display::Screen* screen = display::Screen::GetScreen();
- display::Display display;
- if (!screen->GetDisplayWithDisplayId(display_id, &display) ||
- display.device_scale_factor() == 1.f) {
- return;
- }
- const gfx::Point host_location =
- gfx::ConvertPointToDIP(display.device_scale_factor(), event->location());
- event->set_location(host_location);
- const gfx::Point root_location = gfx::ConvertPointToDIP(
- display.device_scale_factor(), event->root_location());
- event->set_root_location(root_location);
-}
-
// 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) {
@@ -200,6 +177,10 @@ void OnAckMustSucceed(bool success) {
CHECK(success);
}
+Id GetServerIdForWindow(Window* window) {
+ return window ? WindowMus::Get(window)->server_id() : kInvalidServerId;
+}
+
} // namespace
WindowTreeClient::WindowTreeClient(
@@ -210,7 +191,6 @@ WindowTreeClient::WindowTreeClient(
scoped_refptr<base::SingleThreadTaskRunner> io_task_runner,
bool create_discardable_memory)
: connector_(connector),
- client_id_(0),
next_window_id_(1),
next_change_id_(1),
delegate_(delegate),
@@ -290,9 +270,6 @@ WindowTreeClient::~WindowTreeClient() {
}
void WindowTreeClient::ConnectViaWindowTreeFactory() {
- // The client id doesn't really matter, we use 101 purely for debugging.
- client_id_ = 101;
-
ui::mojom::WindowTreeFactoryPtr factory;
connector_->BindInterface(ui::mojom::kServiceName, &factory);
ui::mojom::WindowTreePtr window_tree;
@@ -368,8 +345,8 @@ void WindowTreeClient::Embed(
void WindowTreeClient::AttachCompositorFrameSink(
Id window_id,
- cc::mojom::CompositorFrameSinkRequest compositor_frame_sink,
- cc::mojom::CompositorFrameSinkClientPtr client) {
+ viz::mojom::CompositorFrameSinkRequest compositor_frame_sink,
+ viz::mojom::CompositorFrameSinkClientPtr client) {
DCHECK(tree_);
tree_->AttachCompositorFrameSink(window_id, std::move(compositor_frame_sink),
std::move(client));
@@ -390,6 +367,63 @@ bool WindowTreeClient::IsWindowKnown(aura::Window* window) {
return windows_.count(window_mus->server_id()) > 0;
}
+void WindowTreeClient::ConvertPointerEventLocationToDip(
+ int64_t display_id,
+ WindowMus* window,
+ ui::LocatedEvent* event) const {
+ // PointerEvents shouldn't have the target set.
+ DCHECK(!event->target());
+ if (window_manager_delegate_) {
+ ConvertPointerEventLocationToDipInWindowManager(display_id, window, event);
+ return;
+ }
+ display::Screen* screen = display::Screen::GetScreen();
+ display::Display display;
+ // TODO(sky): this needs to take into account the ui display scale.
+ // http://crbug.com/758399.
+ if (!screen->GetDisplayWithDisplayId(display_id, &display) ||
+ display.device_scale_factor() == 1.f) {
+ return;
+ }
+ const gfx::Point root_location = gfx::ConvertPointToDIP(
+ display.device_scale_factor(), event->root_location());
+ event->set_root_location(root_location);
+ if (window) {
+ const gfx::Point host_location = gfx::ConvertPointToDIP(
+ display.device_scale_factor(), event->location());
+ event->set_location(host_location);
+ } else {
+ // When there is no window force the root and location to be the same. They
+ // may differ it |window| was valid at the time of the event, but was since
+ // deleted.
+ event->set_location(root_location);
+ }
+}
+
+void WindowTreeClient::ConvertPointerEventLocationToDipInWindowManager(
+ int64_t display_id,
+ WindowMus* window,
+ ui::LocatedEvent* event) const {
+ const WindowTreeHostMus* window_tree_host =
+ GetWindowTreeHostForDisplayId(display_id);
+ if (!window_tree_host)
+ return;
+
+ ui::Event::DispatcherApi dispatcher_api(event);
+ if (window) {
+ dispatcher_api.set_target(window->GetWindow());
+ } else {
+ // UpdateForRootTransform() in the case of no target uses |location_|.
+ // |location_| may be relative to a window that wasn't found. To ensure we
+ // convert from the root, reset |location_| to |root_location_|.
+ event->set_location_f(event->root_location_f());
+ }
+ event->UpdateForRootTransform(
+ window_tree_host->GetInverseRootTransform(),
+ window_tree_host->GetInverseRootTransformForLocalEventCoordinates());
+ dispatcher_api.set_target(nullptr);
+}
+
InFlightChange* WindowTreeClient::GetOldestInFlightChangeMatching(
const InFlightChange& change) {
for (const auto& pair : in_flight_map_) {
@@ -481,6 +515,20 @@ void WindowTreeClient::SetLocalPropertiesFromServerProperties(
window->SetPropertyFromServer(pair.first, &pair.second);
}
+const WindowTreeHostMus* WindowTreeClient::GetWindowTreeHostForDisplayId(
+ int64_t display_id) const {
+ if (!window_manager_delegate_)
+ return nullptr;
+
+ for (WindowMus* window : roots_) {
+ WindowTreeHostMus* window_tree_host =
+ static_cast<WindowTreeHostMus*>(window->GetWindow()->GetHost());
+ if (window_tree_host->display_id() == display_id)
+ return window_tree_host;
+ }
+ return nullptr;
+}
+
std::unique_ptr<WindowTreeHostMus> WindowTreeClient::CreateWindowTreeHost(
WindowMusType window_mus_type,
const ui::mojom::WindowData& window_data,
@@ -567,28 +615,36 @@ void WindowTreeClient::OnConnectionLost() {
bool WindowTreeClient::HandleInternalPropertyChanged(WindowMus* window,
const void* key,
int64_t old_value) {
- if (key != client::kModalKey)
- return false;
-
- const uint32_t change_id =
- ScheduleInFlightChange(base::MakeUnique<InFlightSetModalTypeChange>(
- window, static_cast<ui::ModalType>(old_value)));
- tree_->SetModalType(change_id, window->server_id(),
- window->GetWindow()->GetProperty(client::kModalKey));
- return true;
+ if (key == client::kModalKey) {
+ const uint32_t change_id =
+ ScheduleInFlightChange(base::MakeUnique<InFlightSetModalTypeChange>(
+ window, static_cast<ui::ModalType>(old_value)));
+ tree_->SetModalType(change_id, window->server_id(),
+ window->GetWindow()->GetProperty(client::kModalKey));
+ return true;
+ }
+ if (key == client::kChildModalParentKey) {
+ const uint32_t change_id =
+ ScheduleInFlightChange(base::MakeUnique<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;
}
void WindowTreeClient::OnEmbedImpl(
ui::mojom::WindowTree* window_tree,
- ClientSpecificId client_id,
ui::mojom::WindowDataPtr root_data,
int64_t display_id,
Id focused_window_id,
bool drawn,
const base::Optional<viz::LocalSurfaceId>& local_surface_id) {
- // WARNING: this is only called if WindowTreeClient was created as the
- // result of an embedding.
- client_id_ = client_id;
WindowTreeConnectionEstablished(window_tree);
DCHECK(roots_.empty());
@@ -601,19 +657,6 @@ void WindowTreeClient::OnEmbedImpl(
delegate_->OnEmbed(std::move(window_tree_host));
}
-void WindowTreeClient::OnSetDisplayRootDone(
- Id window_id,
- const base::Optional<viz::LocalSurfaceId>& local_surface_id) {
- // The only way SetDisplayRoot() should fail is if we've done something wrong.
- CHECK(local_surface_id.has_value());
- WindowMus* window = GetWindowByServerId(window_id);
- if (!window)
- return; // Display was already deleted.
-
- ui::Compositor* compositor = window->GetWindow()->GetHost()->compositor();
- compositor->SetLocalSurfaceId(*local_surface_id);
-}
-
WindowTreeHostMus* WindowTreeClient::WmNewDisplayAddedImpl(
const display::Display& display,
ui::mojom::WindowDataPtr root_data,
@@ -713,7 +756,7 @@ void WindowTreeClient::OnWindowMusCreated(WindowMus* window) {
if (window->server_id() != kInvalidServerId)
return;
- window->set_server_id(MakeTransportId(client_id_, next_window_id_++));
+ window->set_server_id(next_window_id_++);
RegisterWindowMus(window);
DCHECK(window_manager_delegate_ || !IsRoot(window));
@@ -737,6 +780,11 @@ void WindowTreeClient::OnWindowMusCreated(WindowMus* window) {
base::MakeUnique<CrashInFlightChange>(window, ChangeType::NEW_WINDOW));
tree_->NewWindow(change_id, window->server_id(),
std::move(transport_properties));
+ if (window->GetWindow()->event_targeting_policy() !=
+ ui::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS) {
+ SetEventTargetingPolicy(window,
+ window->GetWindow()->event_targeting_policy());
+ }
if (window->window_mus_type() == WindowMusType::DISPLAY_MANUALLY_CREATED) {
WindowTreeHostMus* window_tree_host = GetWindowTreeHostMus(window);
std::unique_ptr<DisplayInitParams> display_init_params =
@@ -755,7 +803,6 @@ void WindowTreeClient::OnWindowMusCreated(WindowMus* window) {
// bounds changes are routed through OnWindowTreeHostBoundsWillChange()).
// But the display is created with an initial bounds, and we need to push
// that to the server.
- DCHECK(kRootWindowBoundsChangesAreIgnored);
ScheduleInFlightBoundsChange(
window, gfx::Rect(),
gfx::Rect(
@@ -765,8 +812,7 @@ void WindowTreeClient::OnWindowMusCreated(WindowMus* window) {
window_manager_client_->SetDisplayRoot(
display, display_init_params->viewport_metrics.Clone(),
display_init_params->is_primary_display, window->server_id(),
- base::Bind(&WindowTreeClient::OnSetDisplayRootDone,
- base::Unretained(this), window->server_id()));
+ base::Bind(&OnAckMustSucceed));
}
}
}
@@ -816,7 +862,21 @@ void WindowTreeClient::OnWindowMusBoundsChanged(WindowMus* window,
// OnWindowTreeHostBoundsWillChange(). Any bounds that happen here are a side
// effect of those and can be ignored.
if (IsRoot(window)) {
- DCHECK(kRootWindowBoundsChangesAreIgnored);
+ // NOTE: this has to happen to here as during the call to
+ // OnWindowTreeHostBoundsWillChange() the compositor hasn't been updated
+ // yet.
+ if (window->window_mus_type() == WindowMusType::DISPLAY_MANUALLY_CREATED) {
+ WindowTreeHost* window_tree_host = window->GetWindow()->GetHost();
+ // |window_tree_host| may be null if this is called during creation of
+ // the window associated with the WindowTreeHostMus.
+ if (window_tree_host) {
+ viz::LocalSurfaceId local_surface_id =
+ window->GetOrAllocateLocalSurfaceId(
+ window_tree_host->GetBoundsInPixels().size());
+ DCHECK(local_surface_id.is_valid());
+ window_tree_host->compositor()->SetLocalSurfaceId(local_surface_id);
+ }
+ }
return;
}
@@ -947,9 +1007,9 @@ std::set<Window*> WindowTreeClient::GetRoots() {
}
bool WindowTreeClient::WasCreatedByThisClient(const WindowMus* window) const {
- // Windows created via CreateTopLevelWindow() are not owned by us, but have
- // our client id. const_cast is required by set.
- return HiWord(window->server_id()) == client_id_ &&
+ // Windows created via CreateTopLevelWindow() are not owned by us, but don't
+ // have high-word set. const_cast is required by set.
+ return !HiWord(window->server_id()) &&
roots_.count(const_cast<WindowMus*>(window)) == 0;
}
@@ -1008,7 +1068,6 @@ void WindowTreeClient::SetEventTargetingPolicy(
}
void WindowTreeClient::OnEmbed(
- ClientSpecificId client_id,
ui::mojom::WindowDataPtr root_data,
ui::mojom::WindowTreePtr tree,
int64_t display_id,
@@ -1025,8 +1084,7 @@ void WindowTreeClient::OnEmbed(
MakeRequest(&window_manager_internal_client_));
window_manager_client_ = window_manager_internal_client_.get();
}
-
- OnEmbedImpl(tree_ptr_.get(), client_id, std::move(root_data), display_id,
+ OnEmbedImpl(tree_ptr_.get(), std::move(root_data), display_id,
focused_window_id, drawn, local_surface_id);
}
@@ -1334,7 +1392,8 @@ void WindowTreeClient::OnWindowInputEvent(uint32_t event_id,
if (matches_pointer_watcher && has_pointer_watcher_) {
DCHECK(event->IsPointerEvent());
std::unique_ptr<ui::Event> event_in_dip(ui::Event::Clone(*event));
- ConvertEventLocationToDip(display_id, event_in_dip->AsLocatedEvent());
+ ConvertPointerEventLocationToDip(display_id, window,
+ event_in_dip->AsLocatedEvent());
delegate_->OnPointerEventObserved(*event_in_dip->AsPointerEvent(),
window ? window->GetWindow() : nullptr);
}
@@ -1368,8 +1427,31 @@ 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());
- DispatchEventToTarget(mapped_event.get(), window);
- ack_handler.set_handled(mapped_event->handled());
+ ui::Event* event_to_dispatch = mapped_event.get();
+// Ash wants the native events in one place (see ExtendedMouseWarpController).
+// By using the constructor that takes a MouseEvent we ensure the MouseEvent
+// has a NativeEvent that can be used to extract the pixel coordinates.
+//
+// TODO: this should really be covered by |root_location|. See 608547 for
+// details.
+#if defined(USE_OZONE)
+ std::unique_ptr<ui::MouseEvent> mapped_event_with_native;
+ if (mapped_event->type() == ui::ET_MOUSE_MOVED ||
+ mapped_event->type() == ui::ET_MOUSE_DRAGGED) {
+ mapped_event_with_native = base::MakeUnique<ui::MouseEvent>(
+ static_cast<const base::NativeEvent&>(mapped_event.get()));
+ // MouseEvent(NativeEvent) sets the root_location to location.
+ mapped_event_with_native->set_root_location_f(
+ mapped_event->AsMouseEvent()->root_location_f());
+ // |mapped_event| is now the NativeEvent. It's expected the location of the
+ // NativeEvent is the same as root_location.
+ mapped_event->AsMouseEvent()->set_location_f(
+ mapped_event->AsMouseEvent()->root_location_f());
+ event_to_dispatch = mapped_event_with_native.get();
+ }
+#endif
+ DispatchEventToTarget(event_to_dispatch, window);
+ ack_handler.set_handled(event_to_dispatch->handled());
}
void WindowTreeClient::OnPointerEventObserved(std::unique_ptr<ui::Event> event,
@@ -1380,8 +1462,9 @@ void WindowTreeClient::OnPointerEventObserved(std::unique_ptr<ui::Event> event,
if (!has_pointer_watcher_)
return;
- ConvertEventLocationToDip(display_id, event->AsLocatedEvent());
WindowMus* target_window = GetWindowByServerId(window_id);
+ ConvertPointerEventLocationToDip(display_id, target_window,
+ event->AsLocatedEvent());
delegate_->OnPointerEventObserved(
*event->AsPointerEvent(),
target_window ? target_window->GetWindow() : nullptr);
@@ -1500,6 +1583,29 @@ void WindowTreeClient::OnChangeCompleted(uint32_t change_id, bool success) {
}
}
+void WindowTreeClient::SetBlockingContainers(
+ const std::vector<BlockingContainers>& all_blocking_containers) {
+ std::vector<ui::mojom::BlockingContainersPtr>
+ transport_all_blocking_containers;
+ for (const BlockingContainers& blocking_containers :
+ all_blocking_containers) {
+ ui::mojom::BlockingContainersPtr transport_blocking_containers =
+ ui::mojom::BlockingContainers::New();
+ // The |system_modal_container| must be specified, |min_container| may be
+ // null.
+ DCHECK(blocking_containers.system_modal_container);
+ transport_blocking_containers->system_modal_container_id =
+ GetServerIdForWindow(blocking_containers.system_modal_container);
+ transport_blocking_containers->min_container_id =
+ GetServerIdForWindow(blocking_containers.min_container);
+ transport_all_blocking_containers.push_back(
+ std::move(transport_blocking_containers));
+ }
+ window_manager_client_->SetBlockingContainers(
+ std::move(transport_all_blocking_containers),
+ base::Bind(&OnAckMustSucceed));
+}
+
void WindowTreeClient::GetWindowManager(
mojo::AssociatedInterfaceRequest<WindowManager> internal) {
window_manager_internal_.reset(
@@ -1537,8 +1643,7 @@ WindowTreeHostMusInitParams WindowTreeClient::CreateInitParamsForNewDisplay() {
return init_params;
}
-void WindowTreeClient::OnConnect(ClientSpecificId client_id) {
- client_id_ = client_id;
+void WindowTreeClient::OnConnect() {
got_initial_displays_ = true;
if (window_manager_delegate_)
window_manager_delegate_->OnWmConnected();
@@ -1811,6 +1916,20 @@ void WindowTreeClient::OnAccelerator(uint32_t ack_id,
window_manager_client_->OnAcceleratorAck(ack_id, result, properties);
}
+void WindowTreeClient::OnCursorTouchVisibleChanged(bool enabled) {
+ if (window_manager_client_)
+ window_manager_delegate_->OnCursorTouchVisibleChanged(enabled);
+}
+
+void WindowTreeClient::OnEventBlockedByModalWindow(Id window_id) {
+ if (!window_manager_delegate_)
+ return;
+
+ WindowMus* window = GetWindowByServerId(window_id);
+ if (window)
+ window_manager_delegate_->OnEventBlockedByModalWindow(window->GetWindow());
+}
+
void WindowTreeClient::SetFrameDecorationValues(
ui::mojom::FrameDecorationValuesPtr values) {
if (window_manager_client_) {
@@ -1855,11 +1974,6 @@ void WindowTreeClient::RemoveActivationParent(Window* window) {
}
}
-void WindowTreeClient::ActivateNextWindow() {
- if (window_manager_client_)
- window_manager_client_->ActivateNextWindow();
-}
-
void WindowTreeClient::SetExtendedHitRegionForChildren(
Window* window,
const gfx::Insets& mouse_insets,
@@ -1900,6 +2014,11 @@ void WindowTreeClient::SetGlobalOverrideCursor(
window_manager_client_->WmSetGlobalOverrideCursor(std::move(cursor));
}
+void WindowTreeClient::SetCursorTouchVisible(bool enabled) {
+ if (window_manager_client_)
+ window_manager_client_->WmSetCursorTouchVisible(enabled);
+}
+
void WindowTreeClient::SetKeyEventsThatDontHideCursor(
std::vector<ui::mojom::EventMatcherPtr> cursor_key_list) {
if (window_manager_client_) {
@@ -1943,9 +2062,10 @@ void WindowTreeClient::AddDisplayReusingWindowTreeHost(
WindowMus* display_root_window = WindowMus::Get(window_tree_host->window());
window_manager_client_->SetDisplayRoot(
display, std::move(viewport_metrics), is_primary_display,
- display_root_window->server_id(),
- base::Bind(&WindowTreeClient::OnSetDisplayRootDone,
- base::Unretained(this), display_root_window->server_id()));
+ display_root_window->server_id(), base::Bind(&OnAckMustSucceed));
+ window_tree_host->compositor()->SetLocalSurfaceId(
+ display_root_window->GetOrAllocateLocalSurfaceId(
+ window_tree_host->GetBoundsInPixels().size()));
}
}
@@ -2076,13 +2196,23 @@ void WindowTreeClient::OnWindowTreeHostMoveCursorToDisplayLocation(
}
}
+void WindowTreeClient::OnWindowTreeHostConfineCursorToBounds(
+ const gfx::Rect& bounds_in_pixels,
+ int64_t display_id) {
+ DCHECK(window_manager_client_);
+ if (window_manager_client_) {
+ window_manager_client_->WmConfineCursorToBounds(bounds_in_pixels,
+ display_id);
+ }
+}
+
std::unique_ptr<WindowPortMus> WindowTreeClient::CreateWindowPortForTopLevel(
const std::map<std::string, std::vector<uint8_t>>* properties) {
std::unique_ptr<WindowPortMus> window_port =
base::MakeUnique<WindowPortMus>(this, WindowMusType::TOP_LEVEL);
roots_.insert(window_port.get());
- window_port->set_server_id(MakeTransportId(client_id_, next_window_id_++));
+ window_port->set_server_id(next_window_id_++);
RegisterWindowMus(window_port.get());
std::unordered_map<std::string, std::vector<uint8_t>> transport_properties;
diff --git a/chromium/ui/aura/mus/window_tree_client.h b/chromium/ui/aura/mus/window_tree_client.h
index fb4c741b568..4490bdcde2e 100644
--- a/chromium/ui/aura/mus/window_tree_client.h
+++ b/chromium/ui/aura/mus/window_tree_client.h
@@ -89,8 +89,8 @@ using EventResultCallback = base::Callback<void(ui::mojom::EventResult)>;
// When WindowTreeClient is deleted all windows are deleted (and observers
// notified).
class AURA_EXPORT WindowTreeClient
- : NON_EXPORTED_BASE(public ui::mojom::WindowTreeClient),
- NON_EXPORTED_BASE(public ui::mojom::WindowManager),
+ : public ui::mojom::WindowTreeClient,
+ public ui::mojom::WindowManager,
public CaptureSynchronizerDelegate,
public FocusSynchronizerDelegate,
public DragDropControllerHost,
@@ -129,7 +129,6 @@ class AURA_EXPORT WindowTreeClient
FocusSynchronizer* focus_synchronizer() { return focus_synchronizer_.get(); }
bool connected() const { return tree_ != nullptr; }
- ClientSpecificId client_id() const { return client_id_; }
void SetCanFocus(Window* window, bool can_focus);
void SetCanAcceptDrops(WindowMus* window, bool can_accept_drops);
@@ -155,8 +154,8 @@ class AURA_EXPORT WindowTreeClient
void AttachCompositorFrameSink(
Id window_id,
- cc::mojom::CompositorFrameSinkRequest compositor_frame_sink,
- cc::mojom::CompositorFrameSinkClientPtr client);
+ viz::mojom::CompositorFrameSinkRequest compositor_frame_sink,
+ viz::mojom::CompositorFrameSinkClientPtr client);
bool IsRoot(WindowMus* window) const { return roots_.count(window) > 0; }
@@ -207,6 +206,22 @@ class AURA_EXPORT WindowTreeClient
bool IsWindowKnown(aura::Window* window);
+ // Updates the coordinates of |event| to be in DIPs. |window| is the source
+ // of the event, and may be null. A null |window| means either there is no
+ // local window the event is targeted at *or* |window| was valid at the time
+ // the event was generated at the server but was deleted locally before the
+ // event was received.
+ void ConvertPointerEventLocationToDip(int64_t display_id,
+ WindowMus* window,
+ ui::LocatedEvent* event) const;
+
+ // Variant of ConvertPointerEventLocationToDip() that is used when in
+ // the window-manager.
+ void ConvertPointerEventLocationToDipInWindowManager(
+ int64_t display_id,
+ WindowMus* window,
+ ui::LocatedEvent* event) const;
+
// Returns the oldest InFlightChange that matches |change|.
InFlightChange* GetOldestInFlightChangeMatching(const InFlightChange& change);
@@ -236,6 +251,9 @@ class AURA_EXPORT WindowTreeClient
WindowMus* window,
const ui::mojom::WindowData& window_data);
+ const WindowTreeHostMus* GetWindowTreeHostForDisplayId(
+ int64_t display_id) const;
+
// Creates a new WindowTreeHostMus.
std::unique_ptr<WindowTreeHostMus> CreateWindowTreeHost(
WindowMusType window_mus_type,
@@ -264,18 +282,12 @@ class AURA_EXPORT WindowTreeClient
// OnEmbed() calls into this. Exposed as a separate function for testing.
void OnEmbedImpl(ui::mojom::WindowTree* window_tree,
- ClientSpecificId client_id,
ui::mojom::WindowDataPtr root_data,
int64_t display_id,
Id focused_window_id,
bool drawn,
const base::Optional<viz::LocalSurfaceId>& local_surface_id);
- // Called once mus acks the call to SetDisplayRoot().
- void OnSetDisplayRootDone(
- Id window_id,
- const base::Optional<viz::LocalSurfaceId>& local_surface_id);
-
// Called by WmNewDisplayAdded().
WindowTreeHostMus* WmNewDisplayAddedImpl(
const display::Display& display,
@@ -331,7 +343,6 @@ class AURA_EXPORT WindowTreeClient
// Overridden from WindowTreeClient:
void OnEmbed(
- ClientSpecificId client_id,
ui::mojom::WindowDataPtr root,
ui::mojom::WindowTreePtr tree,
int64_t display_id,
@@ -421,11 +432,13 @@ class AURA_EXPORT WindowTreeClient
void OnDragDropDone() override;
void OnChangeCompleted(uint32_t change_id, bool success) override;
void RequestClose(uint32_t window_id) override;
+ void SetBlockingContainers(
+ const std::vector<BlockingContainers>& all_blocking_containers) override;
void GetWindowManager(
mojo::AssociatedInterfaceRequest<WindowManager> internal) override;
// Overridden from WindowManager:
- void OnConnect(ClientSpecificId client_id) override;
+ void OnConnect() override;
void WmNewDisplayAdded(
const display::Display& display,
ui::mojom::WindowDataPtr root_data,
@@ -468,6 +481,8 @@ class AURA_EXPORT WindowTreeClient
void OnAccelerator(uint32_t ack_id,
uint32_t accelerator_id,
std::unique_ptr<ui::Event> event) override;
+ void OnCursorTouchVisibleChanged(bool enabled) override;
+ void OnEventBlockedByModalWindow(Id window_id) override;
// Overridden from WindowManagerClient:
void SetFrameDecorationValues(
@@ -479,7 +494,6 @@ class AURA_EXPORT WindowTreeClient
void RemoveAccelerator(uint32_t id) override;
void AddActivationParent(Window* window) override;
void RemoveActivationParent(Window* window) override;
- void ActivateNextWindow() override;
void SetExtendedHitRegionForChildren(
Window* window,
const gfx::Insets& mouse_insets,
@@ -489,6 +503,7 @@ class AURA_EXPORT WindowTreeClient
void SetCursorVisible(bool visible) override;
void SetCursorSize(ui::CursorSize cursor_size) override;
void SetGlobalOverrideCursor(base::Optional<ui::CursorData> cursor) override;
+ void SetCursorTouchVisible(bool enabled) override;
void SetKeyEventsThatDontHideCursor(
std::vector<ui::mojom::EventMatcherPtr> cursor_key_list) override;
void RequestClose(Window* window) override;
@@ -532,6 +547,8 @@ class AURA_EXPORT WindowTreeClient
void OnWindowTreeHostMoveCursorToDisplayLocation(
const gfx::Point& location_in_pixels,
int64_t display_id) override;
+ void OnWindowTreeHostConfineCursorToBounds(const gfx::Rect& bounds_in_pixels,
+ int64_t display_id) override;
std::unique_ptr<WindowPortMus> CreateWindowPortForTopLevel(
const std::map<std::string, std::vector<uint8_t>>* properties) override;
void OnWindowTreeHostCreated(WindowTreeHostMus* window_tree_host) override;
@@ -573,10 +590,6 @@ class AURA_EXPORT WindowTreeClient
// This may be null in tests.
service_manager::Connector* connector_;
- // This is set once and only once when we get OnEmbed(). It gives the unique
- // id for this client.
- ClientSpecificId client_id_;
-
// Id assigned to the next window created.
ClientSpecificId next_window_id_;
diff --git a/chromium/ui/aura/mus/window_tree_client_unittest.cc b/chromium/ui/aura/mus/window_tree_client_unittest.cc
index f6ba1a71dfc..9fb47c75742 100644
--- a/chromium/ui/aura/mus/window_tree_client_unittest.cc
+++ b/chromium/ui/aura/mus/window_tree_client_unittest.cc
@@ -52,6 +52,7 @@
#include "ui/events/test/test_event_handler.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/transform.h"
namespace aura {
@@ -211,11 +212,35 @@ INSTANTIATE_TEST_CASE_P(/* no prefix */,
WindowTreeClientWmTestSurfaceSync,
::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(WindowTreeClientWmTestSurfaceSync,
ClientSurfaceEmbedderOnValidEmbedding) {
- Window window(nullptr);
+ 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,
@@ -245,6 +270,7 @@ TEST_P(WindowTreeClientWmTestSurfaceSync,
ClientSurfaceEmbedder* client_surface_embedder =
window_port_mus->client_surface_embedder();
ASSERT_NE(nullptr, client_surface_embedder);
+ EXPECT_FALSE(delegate.last_surface_info().is_valid());
// Until the fallback surface fills the window, we will have gutter.
{
@@ -261,6 +287,9 @@ TEST_P(WindowTreeClientWmTestSurfaceSync,
// client lib. This should cause the gutter to go away, eliminating overdraw.
window_tree_client()->OnWindowSurfaceChanged(
server_id(&window), window_port_mus->PrimarySurfaceInfoForTesting());
+ EXPECT_TRUE(delegate.last_surface_info().is_valid());
+ EXPECT_EQ(delegate.last_surface_info(),
+ window_port_mus->PrimarySurfaceInfoForTesting());
// The gutter is gone.
ASSERT_EQ(nullptr, client_surface_embedder->BottomGutterForTesting());
@@ -718,41 +747,52 @@ class InputEventBasicTestWindowDelegate : public test::TestWindowDelegate {
: test_window_tree_(test_window_tree) {}
~InputEventBasicTestWindowDelegate() override {}
- bool got_move() const { return got_move_; }
- bool got_press() const { return got_press_; }
- bool got_release() const { return got_release_; }
+ int move_count() const { return move_count_; }
+ int press_count() const { return press_count_; }
+ int release_count() const { return release_count_; }
bool was_acked() const { return was_acked_; }
const gfx::Point& last_event_location() const { return last_event_location_; }
void set_event_id(uint32_t event_id) { event_id_ = event_id; }
+ bool last_mouse_event_had_native_event() const {
+ return last_mouse_event_had_native_event_;
+ }
+ const gfx::Point& last_native_event_location() const {
+ return last_native_event_location_;
+ }
// TestWindowDelegate::
void OnMouseEvent(ui::MouseEvent* event) override {
was_acked_ = test_window_tree_->WasEventAcked(event_id_);
if (event->type() == ui::ET_MOUSE_MOVED)
- got_move_ = true;
+ ++move_count_;
else if (event->type() == ui::ET_MOUSE_PRESSED)
- got_press_ = true;
+ ++press_count_;
else if (event->type() == ui::ET_MOUSE_RELEASED)
- got_release_ = true;
+ ++release_count_;
last_event_location_ = event->location();
+ last_mouse_event_had_native_event_ = event->HasNativeEvent();
+ if (event->HasNativeEvent()) {
+ last_native_event_location_ =
+ ui::EventSystemLocationFromNative(event->native_event());
+ }
event->SetHandled();
}
void OnTouchEvent(ui::TouchEvent* event) override {
was_acked_ = test_window_tree_->WasEventAcked(event_id_);
if (event->type() == ui::ET_TOUCH_PRESSED)
- got_press_ = true;
+ ++press_count_;
else if (event->type() == ui::ET_TOUCH_RELEASED)
- got_release_ = true;
+ ++release_count_;
last_event_location_ = event->location();
event->SetHandled();
}
void reset() {
was_acked_ = false;
- got_move_ = false;
- got_press_ = false;
- got_release_ = false;
+ move_count_ = 0;
+ press_count_ = 0;
+ release_count_ = 0;
last_event_location_ = gfx::Point();
event_id_ = 0;
}
@@ -760,11 +800,13 @@ class InputEventBasicTestWindowDelegate : public test::TestWindowDelegate {
private:
TestWindowTree* test_window_tree_;
bool was_acked_ = false;
- bool got_move_ = false;
- bool got_press_ = false;
- bool got_release_ = false;
+ int move_count_ = 0;
+ int press_count_ = 0;
+ int release_count_ = false;
gfx::Point last_event_location_;
uint32_t event_id_ = 0;
+ bool last_mouse_event_had_native_event_ = false;
+ gfx::Point last_native_event_location_;
DISALLOW_COPY_AND_ASSIGN(InputEventBasicTestWindowDelegate);
};
@@ -775,7 +817,7 @@ class InputEventBasicTestEventHandler : public ui::test::TestEventHandler {
: target_window_(target_window) {}
~InputEventBasicTestEventHandler() override {}
- bool got_move() const { return got_move_; }
+ int move_count() const { return move_count_; }
const gfx::Point& last_event_location() const { return last_event_location_; }
void set_event_id(uint32_t event_id) { event_id_ = event_id; }
@@ -783,21 +825,21 @@ class InputEventBasicTestEventHandler : public ui::test::TestEventHandler {
void OnMouseEvent(ui::MouseEvent* event) override {
if (event->target() == target_window_) {
if (event->type() == ui::ET_MOUSE_MOVED)
- got_move_ = true;
+ ++move_count_;
last_event_location_ = event->location();
event->SetHandled();
}
}
void reset() {
- got_move_ = false;
+ move_count_ = 0;
last_event_location_ = gfx::Point();
event_id_ = 0;
}
private:
Window* target_window_ = nullptr;
- bool got_move_ = false;
+ int move_count_ = 0;
gfx::Point last_event_location_;
uint32_t event_id_ = 0;
@@ -822,7 +864,7 @@ TEST_F(WindowTreeClientClientTest, InputEventBasic) {
top_level->AddChild(&child);
child.SetBounds(gfx::Rect(10, 10, 100, 100));
child.Show();
- EXPECT_FALSE(window_delegate.got_move());
+ EXPECT_EQ(0, window_delegate.move_count());
EXPECT_FALSE(window_delegate.was_acked());
const gfx::Point event_location_in_child(2, 3);
const uint32_t event_id = 1;
@@ -836,7 +878,7 @@ TEST_F(WindowTreeClientClientTest, InputEventBasic) {
EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
EXPECT_EQ(ui::mojom::EventResult::HANDLED,
window_tree()->GetEventResult(event_id));
- EXPECT_TRUE(window_delegate.got_move());
+ EXPECT_EQ(1, window_delegate.move_count());
EXPECT_FALSE(window_delegate.was_acked());
EXPECT_EQ(event_location_in_child, window_delegate.last_event_location());
}
@@ -857,7 +899,7 @@ TEST_F(WindowTreeClientClientTest, InputEventPointerEvent) {
top_level->AddChild(&child);
child.SetBounds(gfx::Rect(10, 10, 100, 100));
child.Show();
- EXPECT_FALSE(window_delegate.got_move());
+ EXPECT_EQ(0, window_delegate.move_count());
const gfx::Point event_location(2, 3);
const uint32_t event_id = 1;
window_delegate.set_event_id(event_id);
@@ -871,7 +913,7 @@ TEST_F(WindowTreeClientClientTest, InputEventPointerEvent) {
EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
EXPECT_EQ(ui::mojom::EventResult::HANDLED,
window_tree()->GetEventResult(event_id));
- EXPECT_TRUE(window_delegate.got_move());
+ EXPECT_EQ(1, window_delegate.move_count());
EXPECT_EQ(event_location, window_delegate.last_event_location());
}
@@ -899,8 +941,8 @@ TEST_F(WindowTreeClientClientTest, InputEventFindTargetAndConversion) {
child2.SetBounds(gfx::Rect(20, 30, 100, 100));
child2.Show();
- EXPECT_FALSE(window_delegate1.got_move());
- EXPECT_FALSE(window_delegate2.got_move());
+ EXPECT_EQ(0, window_delegate1.move_count());
+ EXPECT_EQ(0, window_delegate2.move_count());
// child1 has a targeter set and event_location is (50, 60), child2
// should get the event even though mus-ws wants to send to child1.
@@ -917,8 +959,8 @@ TEST_F(WindowTreeClientClientTest, InputEventFindTargetAndConversion) {
EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
EXPECT_EQ(ui::mojom::EventResult::HANDLED,
window_tree()->GetEventResult(event_id));
- EXPECT_FALSE(window_delegate1.got_move());
- EXPECT_TRUE(window_delegate2.got_move());
+ EXPECT_EQ(0, window_delegate1.move_count());
+ EXPECT_EQ(1, window_delegate2.move_count());
EXPECT_EQ(gfx::Point(30, 30), window_delegate2.last_event_location());
window_delegate1.reset();
window_delegate2.reset();
@@ -938,8 +980,8 @@ TEST_F(WindowTreeClientClientTest, InputEventFindTargetAndConversion) {
EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
EXPECT_EQ(ui::mojom::EventResult::HANDLED,
window_tree()->GetEventResult(event_id));
- EXPECT_TRUE(window_delegate1.got_move());
- EXPECT_FALSE(window_delegate2.got_move());
+ EXPECT_EQ(1, window_delegate1.move_count());
+ EXPECT_EQ(0, window_delegate2.move_count());
EXPECT_EQ(gfx::Point(50, 60), window_delegate1.last_event_location());
}
@@ -967,8 +1009,8 @@ TEST_F(WindowTreeClientClientTest, InputEventCustomWindowTargeter) {
child2.SetBounds(gfx::Rect(20, 30, 100, 100));
child2.Show();
- EXPECT_FALSE(window_delegate1.got_move());
- EXPECT_FALSE(window_delegate2.got_move());
+ EXPECT_EQ(0, window_delegate1.move_count());
+ EXPECT_EQ(0, window_delegate2.move_count());
// child1 has a custom targeter set which would always return itself as the
// target window therefore event should go to child1 unlike
@@ -986,8 +1028,8 @@ TEST_F(WindowTreeClientClientTest, InputEventCustomWindowTargeter) {
EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
EXPECT_EQ(ui::mojom::EventResult::HANDLED,
window_tree()->GetEventResult(event_id));
- EXPECT_TRUE(window_delegate1.got_move());
- EXPECT_FALSE(window_delegate2.got_move());
+ EXPECT_EQ(1, window_delegate1.move_count());
+ EXPECT_EQ(0, window_delegate2.move_count());
EXPECT_EQ(gfx::Point(50, 60), window_delegate1.last_event_location());
window_delegate1.reset();
window_delegate2.reset();
@@ -1003,8 +1045,8 @@ TEST_F(WindowTreeClientClientTest, InputEventCustomWindowTargeter) {
EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
EXPECT_EQ(ui::mojom::EventResult::HANDLED,
window_tree()->GetEventResult(event_id));
- EXPECT_TRUE(window_delegate1.got_move());
- EXPECT_FALSE(window_delegate2.got_move());
+ EXPECT_EQ(1, window_delegate1.move_count());
+ EXPECT_EQ(0, window_delegate2.move_count());
EXPECT_EQ(gfx::Point(70, 90), window_delegate1.last_event_location());
}
@@ -1037,8 +1079,8 @@ TEST_F(WindowTreeClientClientTest, InputEventCaptureWindow) {
child2->SetBounds(gfx::Rect(20, 30, 100, 100));
child2->Show();
- EXPECT_FALSE(window_delegate1->got_move());
- EXPECT_FALSE(window_delegate2->got_move());
+ EXPECT_EQ(0, window_delegate1->move_count());
+ EXPECT_EQ(0, window_delegate2->move_count());
// child1 has a custom targeter set which would always return itself as the
// target window therefore event should go to child1.
@@ -1055,8 +1097,8 @@ TEST_F(WindowTreeClientClientTest, InputEventCaptureWindow) {
EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
EXPECT_EQ(ui::mojom::EventResult::HANDLED,
window_tree()->GetEventResult(event_id));
- EXPECT_TRUE(window_delegate1->got_move());
- EXPECT_FALSE(window_delegate2->got_move());
+ EXPECT_EQ(1, window_delegate1->move_count());
+ EXPECT_EQ(0, window_delegate2->move_count());
EXPECT_EQ(gfx::Point(50, 60), window_delegate1->last_event_location());
window_delegate1->reset();
window_delegate2->reset();
@@ -1076,8 +1118,8 @@ TEST_F(WindowTreeClientClientTest, InputEventCaptureWindow) {
EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
EXPECT_EQ(ui::mojom::EventResult::HANDLED,
window_tree()->GetEventResult(event_id));
- EXPECT_FALSE(window_delegate1->got_move());
- EXPECT_TRUE(window_delegate2->got_move());
+ EXPECT_EQ(0, window_delegate1->move_count());
+ EXPECT_EQ(1, window_delegate2->move_count());
EXPECT_EQ(gfx::Point(30, 30), window_delegate2->last_event_location());
child2.reset();
child1.reset();
@@ -1104,8 +1146,8 @@ TEST_F(WindowTreeClientClientTest, InputEventRootWindow) {
child.SetBounds(gfx::Rect(10, 10, 100, 100));
child.Show();
- EXPECT_FALSE(root_handler.got_move());
- EXPECT_FALSE(child_delegate.got_move());
+ EXPECT_EQ(0, root_handler.move_count());
+ EXPECT_EQ(0, child_delegate.move_count());
const gfx::Point event_location_in_child(20, 30);
const uint32_t event_id = 1;
@@ -1121,9 +1163,9 @@ TEST_F(WindowTreeClientClientTest, InputEventRootWindow) {
EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
EXPECT_EQ(ui::mojom::EventResult::HANDLED,
window_tree()->GetEventResult(event_id));
- EXPECT_TRUE(root_handler.got_move());
+ EXPECT_EQ(1, root_handler.move_count());
EXPECT_EQ(gfx::Point(20, 30), root_handler.last_event_location());
- EXPECT_FALSE(child_delegate.got_move());
+ EXPECT_EQ(0, child_delegate.move_count());
EXPECT_EQ(gfx::Point(), child_delegate.last_event_location());
}
@@ -1145,7 +1187,7 @@ TEST_F(WindowTreeClientClientTest, InputMouseEventNoWindow) {
child.SetBounds(gfx::Rect(10, 10, 100, 100));
child.Show();
- EXPECT_FALSE(window_delegate.got_press());
+ EXPECT_EQ(0, window_delegate.press_count());
EXPECT_FALSE(env->IsMouseButtonDown());
EXPECT_FALSE(env->mouse_button_flags());
EXPECT_EQ(gfx::Point(), env->last_mouse_location());
@@ -1154,7 +1196,7 @@ TEST_F(WindowTreeClientClientTest, InputMouseEventNoWindow) {
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(),
+ ui::ET_POINTER_DOWN, event_location, event_location,
ui::EF_LEFT_MOUSE_BUTTON, 0,
ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE, 0),
ui::EventTimeForNow());
@@ -1164,7 +1206,7 @@ TEST_F(WindowTreeClientClientTest, InputMouseEventNoWindow) {
EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
EXPECT_EQ(ui::mojom::EventResult::HANDLED,
window_tree()->GetEventResult(event_id));
- EXPECT_TRUE(window_delegate.got_press());
+ EXPECT_EQ(1, window_delegate.press_count());
EXPECT_TRUE(env->IsMouseButtonDown());
EXPECT_EQ(1024, env->mouse_button_flags()); // ui::EF_LEFT_MOUSE_BUTTON
EXPECT_EQ(event_location, env->last_mouse_location());
@@ -1174,7 +1216,7 @@ TEST_F(WindowTreeClientClientTest, InputMouseEventNoWindow) {
event_id = 2;
window_delegate.set_event_id(event_id);
ui::PointerEvent pointer_event_up(
- ui::ET_POINTER_UP, event_location1, gfx::Point(),
+ 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());
@@ -1187,7 +1229,7 @@ TEST_F(WindowTreeClientClientTest, InputMouseEventNoWindow) {
// aura::Env, location shouldn't be updated.
EXPECT_EQ(ui::mojom::EventResult::UNHANDLED,
window_tree()->GetEventResult(event_id));
- EXPECT_FALSE(window_delegate.got_release());
+ EXPECT_EQ(0, window_delegate.release_count());
EXPECT_FALSE(env->IsMouseButtonDown());
EXPECT_FALSE(env->mouse_button_flags());
EXPECT_EQ(event_location, env->last_mouse_location());
@@ -1211,7 +1253,7 @@ TEST_F(WindowTreeClientClientTest, InputTouchEventNoWindow) {
child.SetBounds(gfx::Rect(10, 10, 100, 100));
child.Show();
- EXPECT_FALSE(window_delegate.got_press());
+ EXPECT_EQ(0, window_delegate.press_count());
EXPECT_FALSE(env->is_touch_down());
const gfx::Point event_location(2, 3);
@@ -1227,7 +1269,7 @@ TEST_F(WindowTreeClientClientTest, InputTouchEventNoWindow) {
EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
EXPECT_EQ(ui::mojom::EventResult::HANDLED,
window_tree()->GetEventResult(event_id));
- EXPECT_TRUE(window_delegate.got_press());
+ EXPECT_EQ(1, window_delegate.press_count());
EXPECT_TRUE(env->is_touch_down());
window_delegate.reset();
@@ -1246,7 +1288,7 @@ TEST_F(WindowTreeClientClientTest, InputTouchEventNoWindow) {
// aura::Env.
EXPECT_EQ(ui::mojom::EventResult::UNHANDLED,
window_tree()->GetEventResult(event_id));
- EXPECT_FALSE(window_delegate.got_release());
+ EXPECT_EQ(0, window_delegate.release_count());
EXPECT_FALSE(env->is_touch_down());
}
@@ -1865,7 +1907,7 @@ class CloseWindowWindowTreeHostObserver : public aura::WindowTreeHostObserver {
bool root_destroyed() const { return root_destroyed_; }
// aura::WindowTreeHostObserver::
- void OnHostCloseRequested(const aura::WindowTreeHost* host) override {
+ void OnHostCloseRequested(aura::WindowTreeHost* host) override {
root_destroyed_ = true;
}
@@ -2306,6 +2348,7 @@ TEST_F(WindowTreeClientWmTest, ManuallyCreateDisplay) {
WindowTreeHostMusInitParams init_params =
WindowTreeClientPrivate(window_tree_client_impl())
.CallCreateInitParamsForNewDisplay();
+ init_params.display_id = display_params->display->id();
init_params.display_init_params = std::move(display_params);
WindowTreeHostMus window_tree_host(std::move(init_params));
window_tree_host.InitHost();
@@ -2379,7 +2422,9 @@ TEST_F(WindowTreeClientClientTestHighDPI, PointerEventsInDip) {
// Delegate received the event in Dips.
const ui::PointerEvent* last_event = last_event_observed();
ASSERT_TRUE(last_event);
- EXPECT_EQ(gfx::ConvertPointToDIP(2.0f, location_pixels),
+ // NOTE: the root and location are the same as there was no window supplied to
+ // OnPointerEventObserved().
+ EXPECT_EQ(gfx::ConvertPointToDIP(2.0f, root_location_pixels),
last_event->location());
EXPECT_EQ(gfx::ConvertPointToDIP(2.0f, root_location_pixels),
last_event->root_location());
@@ -2416,8 +2461,8 @@ TEST_F(WindowTreeClientClientTestHighDPI, InputEventsInDip) {
child2.SetBounds(gfx::Rect(20, 30, 100, 100));
child2.Show();
- EXPECT_FALSE(window_delegate1.got_move());
- EXPECT_FALSE(window_delegate2.got_move());
+ EXPECT_EQ(0, window_delegate1.move_count());
+ EXPECT_EQ(0, window_delegate2.move_count());
// child1 has a custom targeter set which would always return itself as the
// target window therefore event should go to child1 and should be in dip.
@@ -2425,19 +2470,26 @@ TEST_F(WindowTreeClientClientTestHighDPI, InputEventsInDip) {
uint32_t event_id = 1;
window_delegate1.set_event_id(event_id);
window_delegate2.set_event_id(event_id);
- std::unique_ptr<ui::Event> ui_event(
- new ui::MouseEvent(ui::ET_MOUSE_MOVED, event_location_in_pixels,
- gfx::Point(), ui::EventTimeForNow(), ui::EF_NONE, 0));
+ std::unique_ptr<ui::Event> ui_event(new ui::MouseEvent(
+ ui::ET_MOUSE_MOVED, event_location_in_pixels, event_location_in_pixels,
+ ui::EventTimeForNow(), ui::EF_NONE, 0));
window_tree_client()->OnWindowInputEvent(
event_id, server_id(&child1), window_tree_host.display_id(),
ui::Event::Clone(*ui_event.get()), 0);
EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
EXPECT_EQ(ui::mojom::EventResult::HANDLED,
window_tree()->GetEventResult(event_id));
- EXPECT_TRUE(window_delegate1.got_move());
- EXPECT_FALSE(window_delegate2.got_move());
+ EXPECT_EQ(1, window_delegate1.move_count());
+ EXPECT_EQ(0, window_delegate2.move_count());
const gfx::Point event_location_in_dip(25, 30);
EXPECT_EQ(event_location_in_dip, window_delegate1.last_event_location());
+#if defined(USE_OZONE)
+ // For ozone there should be NativeEvent.
+ EXPECT_TRUE(window_delegate1.last_mouse_event_had_native_event());
+ // And the location of the NativeEvent should be in pixels.
+ EXPECT_EQ(event_location_in_pixels,
+ window_delegate1.last_native_event_location());
+#endif
window_delegate1.reset();
window_delegate2.reset();
@@ -2451,8 +2503,8 @@ TEST_F(WindowTreeClientClientTestHighDPI, InputEventsInDip) {
EXPECT_TRUE(window_tree()->WasEventAcked(event_id));
EXPECT_EQ(ui::mojom::EventResult::HANDLED,
window_tree()->GetEventResult(event_id));
- EXPECT_TRUE(window_delegate1.got_move());
- EXPECT_FALSE(window_delegate2.got_move());
+ EXPECT_EQ(1, window_delegate1.move_count());
+ EXPECT_EQ(0, window_delegate2.move_count());
gfx::Point transformed_event_location_in_dip(event_location_in_dip.x() + 20,
event_location_in_dip.y() + 30);
EXPECT_EQ(transformed_event_location_in_dip,
@@ -2473,4 +2525,76 @@ TEST_F(WindowTreeClientDestructionTest, Shutdown) {
window2.Init(ui::LAYER_NOT_DRAWN);
}
+TEST_F(WindowTreeClientWmTest, ObservedPointerEvents) {
+ const gfx::Rect bounds(1, 2, 101, 102);
+ std::unique_ptr<DisplayInitParams> display_params =
+ base::MakeUnique<DisplayInitParams>();
+ const int64_t display_id = 201;
+ float device_scale_factor = 2.0f;
+ float ui_scale_factor = 1.5f;
+ display_params->display = base::MakeUnique<display::Display>(display_id);
+ display_params->display->set_bounds(bounds);
+ display_params->viewport_metrics.bounds_in_pixels = bounds;
+ display_params->viewport_metrics.device_scale_factor = device_scale_factor;
+ display_params->viewport_metrics.ui_scale_factor = ui_scale_factor;
+ WindowTreeHostMusInitParams init_params =
+ WindowTreeClientPrivate(window_tree_client_impl())
+ .CallCreateInitParamsForNewDisplay();
+ init_params.display_id = display_id;
+ init_params.display_init_params = std::move(display_params);
+
+ WindowTreeHostMus window_tree_host(std::move(init_params));
+ window_tree_host.InitHost();
+ gfx::Transform scale_transform;
+ scale_transform.Scale(ui_scale_factor, ui_scale_factor);
+ window_tree_host.window()->SetTransform(scale_transform);
+ window_tree_host.compositor()->SetScaleAndSize(device_scale_factor,
+ bounds.size());
+
+ // Start a pointer watcher for all events excluding move events.
+ window_tree_client_impl()->StartPointerWatcher(false /* want_moves */);
+
+ // Simulate the server sending an observed event.
+ const gfx::Point location_pixels(10, 12);
+ const gfx::Point root_location_pixels(14, 16);
+ std::unique_ptr<ui::PointerEvent> pointer_event_down(new ui::PointerEvent(
+ ui::ET_POINTER_DOWN, location_pixels, root_location_pixels,
+ ui::EF_CONTROL_DOWN, 0,
+ ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 1),
+ base::TimeTicks()));
+ std::unique_ptr<ui::PointerEvent> pointer_event_down2(
+ ui::Event::Clone(*pointer_event_down).release()->AsPointerEvent());
+ window_tree_client()->OnPointerEventObserved(std::move(pointer_event_down),
+ 0u, display_id);
+
+ ASSERT_FALSE(observed_pointer_events().empty());
+ const ui::PointerEvent* last_event = observed_pointer_events().back().get();
+ ASSERT_TRUE(last_event);
+ EXPECT_EQ(nullptr, last_event->target());
+ // NOTE: the root and location are the same as there was no window supplied to
+ // OnPointerEventObserved().
+ EXPECT_EQ(gfx::ConvertPointToDIP(device_scale_factor * ui_scale_factor,
+ root_location_pixels),
+ last_event->location());
+ EXPECT_EQ(gfx::ConvertPointToDIP(device_scale_factor * ui_scale_factor,
+ root_location_pixels),
+ last_event->root_location());
+
+ observed_pointer_events().clear();
+ window_tree_client()->OnPointerEventObserved(
+ std::move(pointer_event_down2),
+ WindowMus::Get(window_tree_host.window())->server_id(), display_id);
+ ASSERT_FALSE(observed_pointer_events().empty());
+ last_event = observed_pointer_events().back().get();
+ ASSERT_TRUE(last_event);
+ EXPECT_EQ(nullptr, last_event->target());
+ // |location| from the server has already had |ui_scale_factor| applied, so
+ // it won't be reapplied here.
+ EXPECT_EQ(gfx::ConvertPointToDIP(device_scale_factor, location_pixels),
+ last_event->location());
+ EXPECT_EQ(gfx::ConvertPointToDIP(device_scale_factor * ui_scale_factor,
+ root_location_pixels),
+ last_event->root_location());
+}
+
} // namespace aura
diff --git a/chromium/ui/aura/mus/window_tree_host_mus.cc b/chromium/ui/aura/mus/window_tree_host_mus.cc
index a529a0bcc3a..927258842c2 100644
--- a/chromium/ui/aura/mus/window_tree_host_mus.cc
+++ b/chromium/ui/aura/mus/window_tree_host_mus.cc
@@ -41,8 +41,11 @@ WindowTreeHostMus::WindowTreeHostMus(WindowTreeHostMusInitParams init_params)
delegate_(init_params.window_tree_client) {
gfx::Rect bounds_in_pixels;
display_init_params_ = std::move(init_params.display_init_params);
- if (display_init_params_)
+ if (display_init_params_) {
bounds_in_pixels = display_init_params_->viewport_metrics.bounds_in_pixels;
+ if (display_init_params_->display)
+ DCHECK_EQ(display_id_, display_init_params_->display->id());
+ }
window()->SetProperty(kWindowTreeHostMusKey, this);
// TODO(sky): find a cleaner way to set this! Better solution is to likely
// have constructor take aura::Window.
@@ -84,6 +87,12 @@ WindowTreeHostMus::WindowTreeHostMus(WindowTreeHostMusInitParams init_params)
// Mus windows are assumed hidden.
compositor()->SetVisible(false);
+
+ if (window_mus->window_mus_type() ==
+ WindowMusType::DISPLAY_MANUALLY_CREATED) {
+ compositor()->SetLocalSurfaceId(
+ window_mus->GetOrAllocateLocalSurfaceId(bounds_in_pixels.size()));
+ }
}
WindowTreeHostMus::~WindowTreeHostMus() {
@@ -151,6 +160,12 @@ void WindowTreeHostMus::CancelWindowMove() {
delegate_->OnWindowTreeHostCancelWindowMove(this);
}
+void WindowTreeHostMus::ConfineCursorToBounds(
+ const gfx::Rect& bounds_in_pixels) {
+ delegate_->OnWindowTreeHostConfineCursorToBounds(bounds_in_pixels,
+ display_id_);
+}
+
display::Display WindowTreeHostMus::GetDisplay() const {
display::Display display;
display::Screen::GetScreen()->GetDisplayWithDisplayId(display_id_, &display);
@@ -195,13 +210,23 @@ void WindowTreeHostMus::OnCloseRequest() {
void WindowTreeHostMus::MoveCursorToScreenLocationInPixels(
const gfx::Point& location_in_pixels) {
- gfx::Point screen_location_in_pixels = location_in_pixels;
- gfx::Point location = GetLocationOnScreenInPixels();
- screen_location_in_pixels.Offset(-location.x(), -location.y());
- delegate_->OnWindowTreeHostMoveCursorToDisplayLocation(
- screen_location_in_pixels, display_id_);
+ // |location_in_pixels| is relative to the display.
+ delegate_->OnWindowTreeHostMoveCursorToDisplayLocation(location_in_pixels,
+ display_id_);
+}
- Env::GetInstance()->set_last_mouse_location(location_in_pixels);
+gfx::Transform WindowTreeHostMus::GetRootTransformForLocalEventCoordinates()
+ const {
+ if (WindowMus::Get(window())->window_mus_type() !=
+ WindowMusType::DISPLAY_MANUALLY_CREATED) {
+ return WindowTreeHost::GetRootTransformForLocalEventCoordinates();
+ }
+ // Local events already have the transform set on the window applied, so
+ // don't apply it again.
+ gfx::Transform transform;
+ const float scale = window()->layer()->device_scale_factor();
+ transform.Scale(scale, scale);
+ return transform;
}
} // namespace aura
diff --git a/chromium/ui/aura/mus/window_tree_host_mus.h b/chromium/ui/aura/mus/window_tree_host_mus.h
index 764a7b0e91d..2ab21f4c626 100644
--- a/chromium/ui/aura/mus/window_tree_host_mus.h
+++ b/chromium/ui/aura/mus/window_tree_host_mus.h
@@ -80,6 +80,9 @@ class AURA_EXPORT WindowTreeHostMus : public aura::WindowTreeHostPlatform {
// PerformWindowMove().
void CancelWindowMove();
+ // Tells the window manager to confine the cursor to these specific bounds.
+ void ConfineCursorToBounds(const gfx::Rect& pixel_bounds);
+
// Used during initial setup. Returns the DisplayInitParams
// supplied to the constructor.
std::unique_ptr<DisplayInitParams> ReleaseDisplayInitParams();
@@ -98,6 +101,7 @@ class AURA_EXPORT WindowTreeHostMus : public aura::WindowTreeHostPlatform {
void OnCloseRequest() override;
void MoveCursorToScreenLocationInPixels(
const gfx::Point& location_in_pixels) override;
+ gfx::Transform GetRootTransformForLocalEventCoordinates() const override;
private:
int64_t display_id_;
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 4ea7c2bf60c..b80e3389182 100644
--- a/chromium/ui/aura/mus/window_tree_host_mus_delegate.h
+++ b/chromium/ui/aura/mus/window_tree_host_mus_delegate.h
@@ -76,6 +76,12 @@ class AURA_EXPORT WindowTreeHostMusDelegate {
const gfx::Point& location_in_pixels,
int64_t display_id) = 0;
+ // Called to confine the cursor to a set of bounds in pixels. Only available
+ // to the window manager.
+ virtual void OnWindowTreeHostConfineCursorToBounds(
+ const gfx::Rect& bounds_in_pixels,
+ int64_t display_id) = 0;
+
// Called when a WindowTreeHostMus is created without a WindowPort.
// TODO: this should take an unordered_map, see http://crbug.com/670515.
virtual std::unique_ptr<WindowPortMus> CreateWindowPortForTopLevel(
diff --git a/chromium/ui/aura/window.cc b/chromium/ui/aura/window.cc
index 5697e03d5fd..e618ea8d511 100644
--- a/chromium/ui/aura/window.cc
+++ b/chromium/ui/aura/window.cc
@@ -20,6 +20,7 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "cc/output/layer_tree_frame_sink.h"
+#include "services/ui/public/interfaces/window_tree_constants.mojom.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/capture_client.h"
#include "ui/aura/client/cursor_client.h"
@@ -64,7 +65,8 @@ Window::Window(WindowDelegate* delegate,
visible_(false),
id_(kInitialId),
transparent_(false),
- ignore_events_(false),
+ event_targeting_policy_(
+ ui::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS),
// Don't notify newly added observers during notification. This causes
// problems for code that adds an observer as part of an observer
// notification (such as the workspace code).
@@ -482,6 +484,15 @@ bool Window::HasObserver(const WindowObserver* observer) const {
return observers_.HasObserver(observer);
}
+void Window::SetEventTargetingPolicy(ui::mojom::EventTargetingPolicy policy) {
+ if (event_targeting_policy_ == policy)
+ return;
+
+ event_targeting_policy_ = policy;
+ if (port_)
+ port_->OnEventTargetingPolicyChanged();
+}
+
bool Window::ContainsPointInRoot(const gfx::Point& point_in_root) const {
const Window* root_window = GetRootWindow();
if (!root_window)
@@ -745,8 +756,10 @@ Window* Window::GetWindowForPoint(const gfx::Point& local_point,
Window* child = *it;
if (for_event_handling) {
- if (child->ignore_events_)
+ if (child->event_targeting_policy_ ==
+ ui::mojom::EventTargetingPolicy::NONE) {
continue;
+ }
// The client may not allow events to be processed by certain subtrees.
client::EventClient* client = client::GetEventClient(GetRootWindow());
@@ -764,8 +777,23 @@ Window* Window::GetWindowForPoint(const gfx::Point& local_point,
Window* match = child->GetWindowForPoint(point_in_child_coords,
return_tightest,
for_event_handling);
- if (match)
- return match;
+ if (!match)
+ continue;
+
+ switch (child->event_targeting_policy_) {
+ case ui::mojom::EventTargetingPolicy::TARGET_ONLY:
+ if (child->delegate_)
+ return child;
+ break;
+ case ui::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS:
+ return match;
+ case ui::mojom::EventTargetingPolicy::DESCENDANTS_ONLY:
+ if (match != child)
+ return match;
+ break;
+ case ui::mojom::EventTargetingPolicy::NONE:
+ NOTREACHED(); // This case is handled early on.
+ }
}
return delegate_ ? this : nullptr;
@@ -990,6 +1018,18 @@ viz::SurfaceId Window::GetSurfaceId() const {
return port_->GetSurfaceId();
}
+void Window::AllocateLocalSurfaceId() {
+ port_->AllocateLocalSurfaceId();
+}
+
+const viz::LocalSurfaceId& Window::GetLocalSurfaceId() const {
+ return port_->GetLocalSurfaceId();
+}
+
+viz::FrameSinkId Window::GetFrameSinkId() const {
+ return port_->GetFrameSinkId();
+}
+
void Window::OnPaintLayer(const ui::PaintContext& context) {
Paint(context);
}
diff --git a/chromium/ui/aura/window.h b/chromium/ui/aura/window.h
index cd6d841fc59..15009ff8b4e 100644
--- a/chromium/ui/aura/window.h
+++ b/chromium/ui/aura/window.h
@@ -45,6 +45,9 @@ class Transform;
namespace ui {
class Layer;
+namespace mojom {
+enum class EventTargetingPolicy;
+}
}
namespace aura {
@@ -241,8 +244,10 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
void RemoveObserver(WindowObserver* observer);
bool HasObserver(const WindowObserver* observer) const;
- void set_ignore_events(bool ignore_events) { ignore_events_ = ignore_events; }
- bool ignore_events() const { return ignore_events_; }
+ void SetEventTargetingPolicy(ui::mojom::EventTargetingPolicy policy);
+ ui::mojom::EventTargetingPolicy event_targeting_policy() const {
+ return event_targeting_policy_;
+ }
// Returns true if the |point_in_root| in root window's coordinate falls
// within this window's bounds. Returns false if the window is detached
@@ -312,9 +317,22 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
// Create a LayerTreeFrameSink for the aura::Window.
std::unique_ptr<cc::LayerTreeFrameSink> CreateLayerTreeFrameSink();
- // Get the current viz::SurfaceId.
+ // Gets the current viz::SurfaceId.
viz::SurfaceId GetSurfaceId() const;
+ // Forces the window to allocate a new viz::LocalSurfaceId for the next
+ // CompositorFrame submission in anticipation of a synchronization operation
+ // that does not involve a resize or a device scale factor change.
+ void AllocateLocalSurfaceId();
+
+ // Gets the current viz::LocalSurfaceId.
+ const viz::LocalSurfaceId& GetLocalSurfaceId() const;
+
+ // Returns the FrameSinkId. In LOCAL mode, this returns a valid FrameSinkId
+ // only if a LayerTreeFrameSink has been created. In MUS mode, this always
+ // return a valid FrameSinkId.
+ viz::FrameSinkId GetFrameSinkId() const;
+
protected:
// Deletes (or removes if not owned by parent) all child windows. Intended for
// use from the destructor.
@@ -327,6 +345,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
int64_t old_value,
std::unique_ptr<ui::PropertyData> data) override;
private:
+ friend class HitTestDataProviderAura;
friend class LayoutManager;
friend class PropertyConverter;
friend class WindowPort;
@@ -480,7 +499,7 @@ class AURA_EXPORT Window : public ui::LayerDelegate,
std::unique_ptr<ui::EventTargeter> targeter_;
// Makes the window pass all events through to any windows behind it.
- bool ignore_events_;
+ ui::mojom::EventTargetingPolicy event_targeting_policy_;
base::ObserverList<WindowObserver, true> observers_;
diff --git a/chromium/ui/aura/window_delegate.h b/chromium/ui/aura/window_delegate.h
index 4ef1c7cfcbd..eac0589bf44 100644
--- a/chromium/ui/aura/window_delegate.h
+++ b/chromium/ui/aura/window_delegate.h
@@ -98,7 +98,9 @@ class AURA_EXPORT WindowDelegate : public ui::EventHandler {
// above returns true.
virtual void GetHitTestMask(gfx::Path* mask) const = 0;
- virtual void OnWindowSurfaceChanged(const viz::SurfaceInfo& surface_info) {}
+ // 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) {}
protected:
~WindowDelegate() override {}
diff --git a/chromium/ui/aura/window_event_dispatcher.cc b/chromium/ui/aura/window_event_dispatcher.cc
index b6088e10469..9b3aa8fe2ba 100644
--- a/chromium/ui/aura/window_event_dispatcher.cc
+++ b/chromium/ui/aura/window_event_dispatcher.cc
@@ -11,6 +11,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
+#include "services/ui/public/interfaces/window_tree_constants.mojom.h"
#include "ui/aura/client/capture_client.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/client/event_client.h"
@@ -68,13 +69,9 @@ void ConvertEventLocationToTarget(ui::EventTarget* event_target,
return;
gfx::Point location = event->AsLocatedEvent()->location();
- gfx::Point root_location = event->AsLocatedEvent()->root_location();
Window::ConvertPointToTarget(static_cast<Window*>(event_target),
static_cast<Window*>(target), &location);
- Window::ConvertPointToTarget(static_cast<Window*>(event_target),
- static_cast<Window*>(target), &root_location);
event->AsLocatedEvent()->set_location(location);
- event->AsLocatedEvent()->set_root_location(root_location);
}
} // namespace
@@ -260,7 +257,9 @@ const Window* WindowEventDispatcher::window() const {
void WindowEventDispatcher::TransformEventForDeviceScaleFactor(
ui::LocatedEvent* event) {
- event->UpdateForRootTransform(host_->GetInverseRootTransform());
+ event->UpdateForRootTransform(
+ host_->GetInverseRootTransform(),
+ host_->GetInverseRootTransformForLocalEventCoordinates());
}
void WindowEventDispatcher::DispatchMouseExitToHidingWindow(Window* window) {
@@ -584,7 +583,9 @@ void WindowEventDispatcher::DispatchSyntheticTouchEvent(ui::TouchEvent* event) {
// the pointer, in dips. OnEventFromSource expects events with co-ordinates
// in raw pixels, so we convert back to raw pixels here.
DCHECK(event->type() == ui::ET_TOUCH_CANCELLED);
- event->UpdateForRootTransform(host_->GetRootTransform());
+ event->UpdateForRootTransform(
+ host_->GetRootTransform(),
+ host_->GetRootTransformForLocalEventCoordinates());
DispatchDetails details = OnEventFromSource(event);
if (details.dispatcher_destroyed)
return;
@@ -670,7 +671,8 @@ void WindowEventDispatcher::OnWindowBoundsChanged(Window* window,
synthesize_mouse_move_ = false;
}
- if (window->IsVisible() && !window->ignore_events()) {
+ if (window->IsVisible() && window->event_targeting_policy() !=
+ ui::mojom::EventTargetingPolicy::NONE) {
gfx::Rect old_bounds_in_root = old_bounds, new_bounds_in_root = new_bounds;
Window::ConvertRectToTarget(window->parent(), host_->window(),
&old_bounds_in_root);
@@ -772,6 +774,14 @@ ui::EventDispatchDetails WindowEventDispatcher::SynthesizeMouseMoveEvent() {
return details;
synthesize_mouse_move_ = false;
+ // No need to generate mouse event if the cursor is invisible.
+ client::CursorClient* cursor_client =
+ client::GetCursorClient(host_->window());
+ if (cursor_client && (!cursor_client->IsMouseEventsEnabled() ||
+ !cursor_client->IsCursorVisible())) {
+ return details;
+ }
+
// If one of the mouse buttons is currently down, then do not synthesize a
// mouse-move event. In such cases, aura could synthesize a DRAGGED event
// instead of a MOVED event, but in multi-display/multi-host scenarios, the
diff --git a/chromium/ui/aura/window_event_dispatcher_unittest.cc b/chromium/ui/aura/window_event_dispatcher_unittest.cc
index b02fde1b611..2f5e9f1275a 100644
--- a/chromium/ui/aura/window_event_dispatcher_unittest.cc
+++ b/chromium/ui/aura/window_event_dispatcher_unittest.cc
@@ -18,6 +18,7 @@
#include "base/test/histogram_tester.h"
#include "base/threading/thread_task_runner_handle.h"
#include "build/build_config.h"
+#include "services/ui/public/interfaces/window_tree_constants.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/capture_client.h"
#include "ui/aura/client/event_client.h"
@@ -1122,6 +1123,9 @@ TEST_P(WindowEventDispatcherTest, DoNotSynthesizeWhileButtonDown) {
// Flaky on 32-bit Windows bots. http://crbug.com/388272
TEST_P(WindowEventDispatcherTest,
MAYBE(SynthesizeMouseEventsOnWindowBoundsChanged)) {
+ test::TestCursorClient cursor_client(root_window());
+ cursor_client.ShowCursor();
+
test::TestWindowDelegate delegate;
std::unique_ptr<aura::Window> window(CreateTestWindowWithDelegate(
&delegate, 1234, gfx::Rect(5, 5, 100, 100), root_window()));
@@ -1150,7 +1154,7 @@ TEST_P(WindowEventDispatcherTest,
recorder.Reset();
// Set window to ignore events.
- window->set_ignore_events(true);
+ window->SetEventTargetingPolicy(ui::mojom::EventTargetingPolicy::NONE);
// Update the window bounds so that cursor is back inside the window.
// This should not trigger a synthetic event.
@@ -1161,7 +1165,8 @@ TEST_P(WindowEventDispatcherTest,
recorder.Reset();
// Set window to accept events but invisible.
- window->set_ignore_events(false);
+ window->SetEventTargetingPolicy(
+ ui::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS);
window->Hide();
recorder.Reset();
@@ -1170,6 +1175,31 @@ TEST_P(WindowEventDispatcherTest,
window->SetBounds(bounds1);
RunAllPendingInMessageLoop();
EXPECT_TRUE(recorder.events().empty());
+
+ // Hide the cursor. None of the following scenario should trigger
+ // a synthetic event.
+ cursor_client.HideCursor();
+
+ window->Show();
+ RunAllPendingInMessageLoop();
+ EXPECT_TRUE(recorder.events().empty());
+
+ window->SetBounds(bounds2);
+ RunAllPendingInMessageLoop();
+ EXPECT_TRUE(recorder.events().empty());
+
+ window->SetBounds(bounds1);
+ RunAllPendingInMessageLoop();
+ EXPECT_TRUE(recorder.events().empty());
+
+ cursor_client.ShowCursor();
+ window->SetBounds(bounds2);
+ RunAllPendingInMessageLoop();
+ ASSERT_FALSE(recorder.events().empty());
+ ASSERT_FALSE(recorder.mouse_event_flags().empty());
+ EXPECT_EQ(ui::ET_MOUSE_MOVED, recorder.events().back());
+ EXPECT_EQ(ui::EF_IS_SYNTHESIZED, recorder.mouse_event_flags().back());
+ recorder.Reset();
}
// Tests that a mouse exit is dispatched to the last known cursor location
@@ -2053,7 +2083,7 @@ class ExitMessageLoopOnMousePress : public ui::test::TestEventHandler {
void OnMouseEvent(ui::MouseEvent* event) override {
ui::test::TestEventHandler::OnMouseEvent(event);
if (event->type() == ui::ET_MOUSE_PRESSED)
- base::MessageLoopForUI::current()->QuitWhenIdle();
+ base::RunLoop::QuitCurrentWhenIdleDeprecated();
}
private:
@@ -2877,6 +2907,65 @@ TEST_F(WindowEventDispatcherMusTest, UseDefaultTargeterToFindTarget2) {
EXPECT_EQ(gfx::Point(), last_event_location_delegate2.last_mouse_location());
}
+namespace {
+
+class LocationRecordingEventHandler : public ui::EventHandler {
+ public:
+ LocationRecordingEventHandler() = default;
+ ~LocationRecordingEventHandler() override = default;
+
+ const gfx::Point& event_root_location() const { return event_root_location_; }
+
+ const gfx::Point& env_root_location() const { return env_root_location_; }
+
+ int mouse_event_count() const { return mouse_event_count_; }
+
+ // ui::EventHandler:
+ void OnMouseEvent(ui::MouseEvent* event) override {
+ ++mouse_event_count_;
+ event_root_location_ = event->root_location();
+ env_root_location_ = Env::GetInstance()->last_mouse_location();
+ }
+
+ private:
+ int mouse_event_count_ = 0;
+ gfx::Point event_root_location_;
+ gfx::Point env_root_location_;
+
+ DISALLOW_COPY_AND_ASSIGN(LocationRecordingEventHandler);
+};
+
+} // namespace
+
+TEST_F(WindowEventDispatcherMusTest, RootLocationDoesntChange) {
+ std::unique_ptr<Window> window(
+ test::CreateTestWindowWithBounds(gfx::Rect(0, 0, 10, 20), root_window()));
+ std::unique_ptr<Window> child_window(
+ test::CreateTestWindowWithBounds(gfx::Rect(5, 6, 10, 20), window.get()));
+
+ test::EnvTestHelper().SetAlwaysUseLastMouseLocation(false);
+
+ LocationRecordingEventHandler event_handler;
+ root_window()->AddPreTargetHandler(&event_handler);
+
+ const gfx::Point mouse_location(1, 2);
+ gfx::Point root_location(mouse_location);
+
+ ui::MouseEvent mouse(ui::ET_MOUSE_PRESSED, mouse_location, root_location,
+ ui::EventTimeForNow(), ui::EF_LEFT_MOUSE_BUTTON,
+ ui::EF_LEFT_MOUSE_BUTTON);
+ ui::Event::DispatcherApi(&mouse).set_target(child_window.get());
+ DispatchEventUsingWindowDispatcher(&mouse);
+ EXPECT_EQ(1, event_handler.mouse_event_count());
+
+ // The root location during dispatch of the event and Env should match the
+ // one that was dispatched.
+ EXPECT_EQ(root_location, event_handler.event_root_location());
+ EXPECT_EQ(root_location, event_handler.env_root_location());
+
+ root_window()->RemovePreTargetHandler(&event_handler);
+}
+
class NestedLocationDelegate : public test::TestWindowDelegate {
public:
NestedLocationDelegate() {}
diff --git a/chromium/ui/aura/window_port.h b/chromium/ui/aura/window_port.h
index 2834ff96319..47a6d22627d 100644
--- a/chromium/ui/aura/window_port.h
+++ b/chromium/ui/aura/window_port.h
@@ -87,9 +87,24 @@ class AURA_EXPORT WindowPort {
// Get the current viz::SurfaceId.
virtual viz::SurfaceId GetSurfaceId() const = 0;
+ // Forces the window to allocate a new viz::LocalSurfaceId for the next
+ // CompositorFrame submission in anticipation of a synchronization operation
+ // that does not involve a resize or a device scale factor change.
+ virtual void AllocateLocalSurfaceId() = 0;
+
+ // Gets the current viz::LocalSurfaceId. The viz::LocalSurfaceId is allocated
+ // lazily on call, and will be updated on changes to size or device scale
+ // factor.
+ virtual const viz::LocalSurfaceId& GetLocalSurfaceId() = 0;
+
+ // This can return invalid FrameSinkId.
+ virtual viz::FrameSinkId GetFrameSinkId() const = 0;
+
virtual void OnWindowAddedToRootWindow() = 0;
virtual void OnWillRemoveWindowFromRootWindow() = 0;
+ virtual void OnEventTargetingPolicyChanged() = 0;
+
protected:
// Returns the WindowPort associated with a Window.
static WindowPort* Get(Window* window);
diff --git a/chromium/ui/aura/window_port_for_shutdown.cc b/chromium/ui/aura/window_port_for_shutdown.cc
index 054342eb174..73fd7a98a80 100644
--- a/chromium/ui/aura/window_port_for_shutdown.cc
+++ b/chromium/ui/aura/window_port_for_shutdown.cc
@@ -60,8 +60,20 @@ viz::SurfaceId WindowPortForShutdown::GetSurfaceId() const {
return viz::SurfaceId();
}
+void WindowPortForShutdown::AllocateLocalSurfaceId() {}
+
+const viz::LocalSurfaceId& WindowPortForShutdown::GetLocalSurfaceId() {
+ return local_surface_id_;
+}
+
+viz::FrameSinkId WindowPortForShutdown::GetFrameSinkId() const {
+ return frame_sink_id_;
+}
+
void WindowPortForShutdown::OnWindowAddedToRootWindow() {}
void WindowPortForShutdown::OnWillRemoveWindowFromRootWindow() {}
+void WindowPortForShutdown::OnEventTargetingPolicyChanged() {}
+
} // namespace aura
diff --git a/chromium/ui/aura/window_port_for_shutdown.h b/chromium/ui/aura/window_port_for_shutdown.h
index 2d369f7a79f..0807e61aa57 100644
--- a/chromium/ui/aura/window_port_for_shutdown.h
+++ b/chromium/ui/aura/window_port_for_shutdown.h
@@ -7,6 +7,8 @@
#include "ui/aura/window_port.h"
+#include "components/viz/common/surfaces/local_surface_id.h"
+
namespace aura {
// When WindowTreeClient is destroyed any existing windows get a
@@ -37,10 +39,16 @@ class WindowPortForShutdown : public WindowPort {
std::unique_ptr<ui::PropertyData> data) override;
std::unique_ptr<cc::LayerTreeFrameSink> CreateLayerTreeFrameSink() override;
viz::SurfaceId GetSurfaceId() const override;
+ void AllocateLocalSurfaceId() override;
+ const viz::LocalSurfaceId& GetLocalSurfaceId() override;
+ viz::FrameSinkId GetFrameSinkId() const override;
void OnWindowAddedToRootWindow() override;
void OnWillRemoveWindowFromRootWindow() override;
+ void OnEventTargetingPolicyChanged() override;
private:
+ viz::LocalSurfaceId local_surface_id_;
+ viz::FrameSinkId frame_sink_id_;
DISALLOW_COPY_AND_ASSIGN(WindowPortForShutdown);
};
diff --git a/chromium/ui/aura/window_targeter.cc b/chromium/ui/aura/window_targeter.cc
index 5b3a9885cfe..8be8e145d7d 100644
--- a/chromium/ui/aura/window_targeter.cc
+++ b/chromium/ui/aura/window_targeter.cc
@@ -4,6 +4,7 @@
#include "ui/aura/window_targeter.h"
+#include "services/ui/public/interfaces/window_tree_constants.mojom.h"
#include "ui/aura/client/capture_client.h"
#include "ui/aura/client/event_client.h"
#include "ui/aura/client/focus_client.h"
@@ -26,6 +27,26 @@ bool WindowTargeter::SubtreeShouldBeExploredForEvent(
EventLocationInsideBounds(window, event);
}
+bool WindowTargeter::GetHitTestRects(Window* window,
+ gfx::Rect* hit_test_rect_mouse,
+ gfx::Rect* hit_test_rect_touch) const {
+ DCHECK(hit_test_rect_mouse);
+ DCHECK(hit_test_rect_touch);
+ *hit_test_rect_mouse = *hit_test_rect_touch = window->bounds();
+
+ if (ShouldUseExtendedBounds(window)) {
+ hit_test_rect_mouse->Inset(mouse_extend_);
+ hit_test_rect_touch->Inset(touch_extend_);
+ }
+
+ return true;
+}
+
+std::unique_ptr<WindowTargeter::HitTestRects>
+WindowTargeter::GetExtraHitTestShapeRects(Window* target) const {
+ return nullptr;
+}
+
Window* WindowTargeter::FindTargetInRootWindow(Window* root_window,
const ui::LocatedEvent& event) {
DCHECK_EQ(root_window, root_window->GetRootWindow());
@@ -83,8 +104,10 @@ ui::EventTarget* WindowTargeter::FindTargetForEvent(ui::EventTarget* root,
// applying the host's transform.
ui::LocatedEvent* located_event = static_cast<ui::LocatedEvent*>(event);
located_event->ConvertLocationToTarget(target, new_root);
+ WindowTreeHost* window_tree_host = new_root->GetHost();
located_event->UpdateForRootTransform(
- new_root->GetHost()->GetRootTransform());
+ window_tree_host->GetRootTransform(),
+ window_tree_host->GetRootTransformForLocalEventCoordinates());
}
ignore_result(new_root->GetHost()->event_sink()->OnEventFromSource(event));
@@ -116,8 +139,12 @@ bool WindowTargeter::SubtreeCanAcceptEvent(
const ui::LocatedEvent& event) const {
if (!window->IsVisible())
return false;
- if (window->ignore_events())
+ if (window->event_targeting_policy() ==
+ ui::mojom::EventTargetingPolicy::NONE ||
+ window->event_targeting_policy() ==
+ ui::mojom::EventTargetingPolicy::TARGET_ONLY) {
return false;
+ }
client::EventClient* client = client::GetEventClient(window->GetRootWindow());
if (client && !client->CanProcessEventsWithinSubtree(window))
return false;
@@ -134,10 +161,48 @@ bool WindowTargeter::SubtreeCanAcceptEvent(
bool WindowTargeter::EventLocationInsideBounds(
Window* window,
const ui::LocatedEvent& event) const {
+ gfx::Rect mouse_rect;
+ gfx::Rect touch_rect;
+ if (!GetHitTestRects(window, &mouse_rect, &touch_rect))
+ return false;
+
+ const gfx::Vector2d offset = -window->bounds().OffsetFromOrigin();
+ mouse_rect.Offset(offset);
+ touch_rect.Offset(offset);
gfx::Point point = event.location();
if (window->parent())
Window::ConvertPointToTarget(window->parent(), window, &point);
- return gfx::Rect(window->bounds().size()).Contains(point);
+
+ const bool point_in_rect = event.IsTouchEvent() || event.IsGestureEvent()
+ ? touch_rect.Contains(point)
+ : mouse_rect.Contains(point);
+ if (!point_in_rect)
+ return false;
+
+ auto shape_rects = GetExtraHitTestShapeRects(window);
+ if (!shape_rects)
+ return true;
+
+ for (const gfx::Rect& shape_rect : *shape_rects) {
+ if (shape_rect.Contains(point)) {
+ return true;
+ }
+ }
+
+ return false;
+}
+
+bool WindowTargeter::ShouldUseExtendedBounds(const aura::Window* window) const {
+ return true;
+}
+
+void WindowTargeter::OnSetInsets() {}
+
+void WindowTargeter::SetInsets(const gfx::Insets& mouse_extend,
+ const gfx::Insets& touch_extend) {
+ mouse_extend_ = mouse_extend;
+ touch_extend_ = touch_extend;
+ OnSetInsets();
}
Window* WindowTargeter::FindTargetForKeyEvent(Window* window,
diff --git a/chromium/ui/aura/window_targeter.h b/chromium/ui/aura/window_targeter.h
index 83fdcde3b80..cb07c106c62 100644
--- a/chromium/ui/aura/window_targeter.h
+++ b/chromium/ui/aura/window_targeter.h
@@ -5,9 +5,17 @@
#ifndef UI_AURA_WINDOW_TARGETER_H_
#define UI_AURA_WINDOW_TARGETER_H_
+#include <memory>
+#include <vector>
+
#include "base/macros.h"
#include "ui/aura/aura_export.h"
#include "ui/events/event_targeter.h"
+#include "ui/gfx/geometry/insets.h"
+
+namespace gfx {
+class Rect;
+}
namespace ui {
class KeyEvent;
@@ -23,6 +31,8 @@ class AURA_EXPORT WindowTargeter : public ui::EventTargeter {
WindowTargeter();
~WindowTargeter() override;
+ using HitTestRects = std::vector<gfx::Rect>;
+
// Returns true if |window| or one of its descendants can be a target of
// |event|. This requires that |window| and its descendants are not
// prohibited from accepting the event, and that the event is within an
@@ -31,6 +41,25 @@ class AURA_EXPORT WindowTargeter : public ui::EventTargeter {
virtual bool SubtreeShouldBeExploredForEvent(Window* window,
const ui::LocatedEvent& event);
+ // Returns true if the |target| is accepting LocatedEvents, false otherwise.
+ // |hit_test_rect_mouse| and |hit_test_rect_touch| must be not null and return
+ // the bounds that can be used for hit testing. The default implementation
+ // extends the |target|'s |bounds()| by insets provided with SetInsets().
+ // This can be used to extend the hit-test area for touch events and make
+ // targeting windows with imprecise input devices easier.
+ // Returned rectangles are in |target|'s parent's coordinates.
+ virtual bool GetHitTestRects(Window* target,
+ gfx::Rect* hit_test_rect_mouse,
+ gfx::Rect* hit_test_rect_touch) const;
+
+ // Returns additional hit-test areas or nullptr when there are none. Used when
+ // a window needs a complex shape hit-test area. This additional area is
+ // clipped to |hit_test_rect_mouse| returned by GetHitTestRects or the window
+ // bounds when GetHitTestRects is not overridden.
+ // Returned rectangles are in |target|'s coordinates.
+ virtual std::unique_ptr<HitTestRects> GetExtraHitTestShapeRects(
+ Window* target) const;
+
Window* FindTargetInRootWindow(Window* root_window,
const ui::LocatedEvent& event);
@@ -60,15 +89,35 @@ class AURA_EXPORT WindowTargeter : public ui::EventTargeter {
// Returns whether the location of the event is in an actionable region of the
// target. Note that the location etc. of |event| is in the |window|'s
// parent's coordinate system.
+ // Deprecated. As an alternative, override GetHitTestRects.
+ // TODO(varkha): Make this non-overridable.
virtual bool EventLocationInsideBounds(Window* target,
const ui::LocatedEvent& event) const;
+ // 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().
+ virtual void OnSetInsets();
+
+ // Sets additional mouse and touch insets that are factored into the hit-test
+ // regions returned by GetHitTestRects.
+ void SetInsets(const gfx::Insets& mouse_extend,
+ const gfx::Insets& touch_extend);
+
+ const gfx::Insets& mouse_extend() const { return mouse_extend_; }
+ const gfx::Insets& touch_extend() const { return touch_extend_; }
+
private:
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);
+ gfx::Insets mouse_extend_;
+ gfx::Insets touch_extend_;
+
DISALLOW_COPY_AND_ASSIGN(WindowTargeter);
};
diff --git a/chromium/ui/aura/window_tree_host.cc b/chromium/ui/aura/window_tree_host.cc
index b47bcc61b00..d73bbda0ec5 100644
--- a/chromium/ui/aura/window_tree_host.cc
+++ b/chromium/ui/aura/window_tree_host.cc
@@ -7,7 +7,7 @@
#include "base/command_line.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
-#include "cc/base/switches.h"
+#include "components/viz/common/switches.h"
#include "ui/aura/client/capture_client.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/env.h"
@@ -20,6 +20,7 @@
#include "ui/base/ime/input_method_factory.h"
#include "ui/base/layout.h"
#include "ui/base/view_prop.h"
+#include "ui/compositor/compositor_switches.h"
#include "ui/compositor/dip_util.h"
#include "ui/compositor/layer.h"
#include "ui/display/display.h"
@@ -96,6 +97,20 @@ gfx::Transform WindowTreeHost::GetInverseRootTransform() const {
return invert;
}
+gfx::Transform WindowTreeHost::GetRootTransformForLocalEventCoordinates()
+ const {
+ return GetRootTransform();
+}
+
+gfx::Transform WindowTreeHost::GetInverseRootTransformForLocalEventCoordinates()
+ const {
+ gfx::Transform invert;
+ gfx::Transform transform = GetRootTransformForLocalEventCoordinates();
+ if (!transform.GetInverse(&invert))
+ return transform;
+ return invert;
+}
+
void WindowTreeHost::SetOutputSurfacePaddingInPixels(
const gfx::Insets& padding_in_pixels) {
if (output_surface_padding_in_pixels_ == padding_in_pixels)
@@ -255,7 +270,8 @@ void WindowTreeHost::DestroyDispatcher() {
//window()->RemoveOrDestroyChildren();
}
-void WindowTreeHost::CreateCompositor(const viz::FrameSinkId& frame_sink_id) {
+void WindowTreeHost::CreateCompositor(const viz::FrameSinkId& frame_sink_id,
+ bool force_software_compositor) {
DCHECK(Env::GetInstance());
ui::ContextFactory* context_factory = Env::GetInstance()->context_factory();
DCHECK(context_factory);
@@ -264,13 +280,14 @@ void WindowTreeHost::CreateCompositor(const viz::FrameSinkId& frame_sink_id) {
bool enable_surface_synchronization =
aura::Env::GetInstance()->mode() == aura::Env::Mode::MUS ||
base::CommandLine::ForCurrentProcess()->HasSwitch(
- cc::switches::kEnableSurfaceSynchronization);
+ switches::kEnableSurfaceSynchronization);
compositor_.reset(new ui::Compositor(
(!context_factory_private || frame_sink_id.is_valid())
? frame_sink_id
: context_factory_private->AllocateFrameSinkId(),
context_factory, context_factory_private,
- base::ThreadTaskRunnerHandle::Get(), enable_surface_synchronization));
+ base::ThreadTaskRunnerHandle::Get(), enable_surface_synchronization,
+ ui::IsPixelCanvasRecordingEnabled(), false, force_software_compositor));
if (!dispatcher()) {
window()->Init(ui::LAYER_NOT_DRAWN);
window()->set_host(this);
@@ -280,10 +297,12 @@ void WindowTreeHost::CreateCompositor(const viz::FrameSinkId& frame_sink_id) {
}
void WindowTreeHost::InitCompositor() {
+ DCHECK(!compositor_->root_layer());
display::Display display =
display::Screen::GetScreen()->GetDisplayNearestWindow(window());
compositor_->SetScaleAndSize(display.device_scale_factor(),
- GetBoundsInPixels().size());
+ GetBoundsInPixels().size(),
+ window()->GetLocalSurfaceId());
compositor_->SetRootLayer(window()->layer());
compositor_->SetDisplayColorSpace(display.color_space());
}
@@ -308,10 +327,11 @@ void WindowTreeHost::OnHostResizedInPixels(
gfx::Size adjusted_size(new_size_in_pixels);
adjusted_size.Enlarge(output_surface_padding_in_pixels_.width(),
output_surface_padding_in_pixels_.height());
+
// The compositor should have the same size as the native root window host.
// Get the latest scale from display because it might have been changed.
compositor_->SetScaleAndSize(ui::GetScaleFactorForNativeView(window()),
- adjusted_size);
+ adjusted_size, window()->GetLocalSurfaceId());
gfx::Size layer_size = GetBoundsInPixels().size();
// The layer, and the observers should be notified of the
@@ -326,6 +346,14 @@ void WindowTreeHost::OnHostWorkspaceChanged() {
observer.OnHostWorkspaceChanged(this);
}
+void WindowTreeHost::OnHostDisplayChanged() {
+ if (!compositor_)
+ return;
+ display::Display display =
+ display::Screen::GetScreen()->GetDisplayNearestWindow(window());
+ compositor_->SetDisplayColorSpace(display.color_space());
+}
+
void WindowTreeHost::OnHostCloseRequested() {
for (WindowTreeHostObserver& observer : observers_)
observer.OnHostCloseRequested(this);
@@ -354,7 +382,7 @@ void WindowTreeHost::OnDisplayMetricsChanged(const display::Display& display,
if (metrics & DisplayObserver::DISPLAY_METRIC_COLOR_SPACE) {
display::Screen* screen = display::Screen::GetScreen();
if (compositor_ &&
- display.id() != screen->GetDisplayNearestView(window()).id()) {
+ display.id() == screen->GetDisplayNearestView(window()).id()) {
compositor_->SetDisplayColorSpace(display.color_space());
}
}
diff --git a/chromium/ui/aura/window_tree_host.h b/chromium/ui/aura/window_tree_host.h
index f0757f56ef4..a436fca5d35 100644
--- a/chromium/ui/aura/window_tree_host.h
+++ b/chromium/ui/aura/window_tree_host.h
@@ -83,6 +83,13 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate,
virtual void SetRootTransform(const gfx::Transform& transform);
virtual gfx::Transform GetInverseRootTransform() const;
+ // These functions are used in event translation for translating the local
+ // coordinates of LocatedEvents. Default implementation calls to non-event
+ // ones (e.g. GetRootTransform()).
+ virtual gfx::Transform GetRootTransformForLocalEventCoordinates() const;
+ virtual gfx::Transform GetInverseRootTransformForLocalEventCoordinates()
+ const;
+
// Sets padding applied to the output surface. The output surface is sized to
// to the size of the host plus output surface padding. |window()| is offset
// by |padding_in_pixels|, that is, |window|'s origin is set to
@@ -195,7 +202,8 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate,
// If frame_sink_id is not passed in, one will be grabbed from
// ContextFactoryPrivate.
void CreateCompositor(
- const viz::FrameSinkId& frame_sink_id = viz::FrameSinkId());
+ const viz::FrameSinkId& frame_sink_id = viz::FrameSinkId(),
+ bool force_software_compositor = false);
void InitCompositor();
void OnAcceleratedWidgetAvailable();
@@ -206,6 +214,7 @@ class AURA_EXPORT WindowTreeHost : public ui::internal::InputMethodDelegate,
void OnHostMovedInPixels(const gfx::Point& new_location_in_pixels);
void OnHostResizedInPixels(const gfx::Size& new_size_in_pixels);
void OnHostWorkspaceChanged();
+ void OnHostDisplayChanged();
void OnHostCloseRequested();
void OnHostActivated();
void OnHostLostWindowCapture();
diff --git a/chromium/ui/aura/window_tree_host_mac.h b/chromium/ui/aura/window_tree_host_mac.h
deleted file mode 100644
index 7ae5efd57c0..00000000000
--- a/chromium/ui/aura/window_tree_host_mac.h
+++ /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.
-
-#ifndef UI_AURA_WINDOW_TREE_HOST_MAC_H_
-#define UI_AURA_WINDOW_TREE_HOST_MAC_H_
-
-#include <vector>
-
-#include "base/mac/scoped_nsobject.h"
-#include "base/macros.h"
-#include "ui/aura/aura_export.h"
-#include "ui/aura/window_tree_host.h"
-#include "ui/gfx/geometry/insets.h"
-#include "ui/gfx/geometry/rect.h"
-
-namespace aura {
-
-class AURA_EXPORT WindowTreeHostMac : public WindowTreeHost {
- public:
- explicit WindowTreeHostMac(const gfx::Rect& bounds);
- ~WindowTreeHostMac() override;
-
- private:
- // WindowTreeHost Overrides.
- ui::EventSource* GetEventSource() override;
- gfx::AcceleratedWidget GetAcceleratedWidget() override;
- void Show() override;
- void Hide() override;
- void ToggleFullScreen() override;
- gfx::Rect GetBounds() const override;
- void SetBounds(const gfx::Rect& bounds) override;
- gfx::Insets GetInsets() const override;
- void SetInsets(const gfx::Insets& insets) override;
- gfx::Point GetLocationOnNativeScreen() const override;
- void SetCapture() override;
- void ReleaseCapture() override;
- bool ConfineCursorToRootWindow() override;
- void UnConfineCursor() override;
- void SetCursorNative(gfx::NativeCursor cursor_type) override;
- void MoveCursorToNative(const gfx::Point& location) override;
- void OnCursorVisibilityChangedNative(bool show) override;
- void OnDeviceScaleFactorChanged(float device_scale_factor) override;
-
- private:
- base::scoped_nsobject<NSWindow> window_;
-
- DISALLOW_COPY_AND_ASSIGN(WindowTreeHostMac);
-};
-
-} // namespace aura
-
-#endif // UI_AURA_WINDOW_TREE_HOST_MAC_H_
diff --git a/chromium/ui/aura/window_tree_host_mac.mm b/chromium/ui/aura/window_tree_host_mac.mm
deleted file mode 100644
index c6748a6076f..00000000000
--- a/chromium/ui/aura/window_tree_host_mac.mm
+++ /dev/null
@@ -1,105 +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 <Cocoa/Cocoa.h>
-
-#include "ui/aura/window_tree_host.h"
-#include "ui/aura/window_tree_host_mac.h"
-
-namespace aura {
-
-WindowTreeHostMac::WindowTreeHostMac(const gfx::Rect& bounds) {
- window_.reset(
- [[NSWindow alloc]
- initWithContentRect:NSRectFromCGRect(bounds.ToCGRect())
- styleMask:NSBorderlessWindowMask
- backing:NSBackingStoreBuffered
- defer:NO]);
- CreateCompositor();
- OnAcceleratedWidgetAvailable();
-}
-
-WindowTreeHostMac::~WindowTreeHostMac() {
- DestroyDispatcher();
-}
-
-EventSource* WindowTreeHostMac::GetEventSource() {
- NOTIMPLEMENTED();
- return nil;
-}
-
-gfx::AcceleratedWidget WindowTreeHostMac::GetAcceleratedWidget() {
- return [window_ contentView];
-}
-void WindowTreeHostMac::ShowImpl() {
- [window_ makeKeyAndOrderFront:nil];
-}
-
-void WindowTreeHostMac::HideImpl() {
- [window_ orderOut:nil];
-}
-
-void WindowTreeHostMac::ToggleFullScreen() {
-}
-
-gfx::Rect WindowTreeHostMac::GetBounds() const {
- return gfx::Rect(NSRectToCGRect([window_ frame]));
-}
-
-void WindowTreeHostMac::SetBounds(const gfx::Rect& bounds) {
- [window_ setFrame:NSRectFromCGRect(bounds.ToCGRect()) display:YES animate:NO];
-}
-
-gfx::Insets WindowTreeHostMac::GetInsets() const {
- NOTIMPLEMENTED();
- return gfx::Insets();
-}
-
-void WindowTreeHostMac::SetInsets(const gfx::Insets& insets) {
- NOTIMPLEMENTED();
-}
-
-gfx::Point WindowTreeHostMac::GetLocationOnNativeScreen() const {
- NOTIMPLEMENTED();
- return gfx::Point(0, 0);
-}
-
-void WindowTreeHostMac::SetCapture() {
- NOTIMPLEMENTED();
-}
-
-void WindowTreeHostMac::ReleaseCapture() {
- NOTIMPLEMENTED();
-}
-
-bool WindowTreeHostMac::ConfineCursorToRootWindow() {
- return false;
-}
-
-void WindowTreeHostMac::UnConfineCursor() {
- NOTIMPLEMENTED();
-}
-
-void WindowTreeHostMac::SetCursorNative(gfx::NativeCursor cursor_type) {
- NOTIMPLEMENTED();
-}
-
-void WindowTreeHostMac::MoveCursorToNative(const gfx::Point& location) {
- NOTIMPLEMENTED();
-}
-
-void WindowTreeHostMac::OnCursorVisibilityChangedNative(bool show) {
- NOTIMPLEMENTED();
-}
-
-void WindowTreeHostMac::OnDeviceScaleFactorChanged(float device_scale_factor) {
- NOTIMPLEMENTED();
-}
-
-// static
-WindowTreeHost* WindowTreeHost::Create(const gfx::Rect& bounds) {
- return new WindowTreeHostMac(bounds);
-}
-
-} // namespace aura
diff --git a/chromium/ui/aura/window_tree_host_observer.h b/chromium/ui/aura/window_tree_host_observer.h
index f5c112ad8df..e71455dc743 100644
--- a/chromium/ui/aura/window_tree_host_observer.h
+++ b/chromium/ui/aura/window_tree_host_observer.h
@@ -17,17 +17,17 @@ class WindowTreeHost;
class AURA_EXPORT WindowTreeHostObserver {
public:
// Called when the host's client size has changed.
- virtual void OnHostResized(const WindowTreeHost* host) {}
+ virtual void OnHostResized(WindowTreeHost* host) {}
// Called when the host is moved on screen.
- virtual void OnHostMovedInPixels(const WindowTreeHost* host,
+ virtual void OnHostMovedInPixels(WindowTreeHost* host,
const gfx::Point& new_origin_in_pixels) {}
// Called when the host is moved to a different workspace.
- virtual void OnHostWorkspaceChanged(const WindowTreeHost* host) {}
+ virtual void OnHostWorkspaceChanged(WindowTreeHost* host) {}
// Called when the native window system sends the host request to close.
- virtual void OnHostCloseRequested(const WindowTreeHost* host) {}
+ virtual void OnHostCloseRequested(WindowTreeHost* host) {}
protected:
virtual ~WindowTreeHostObserver() {}
diff --git a/chromium/ui/aura/window_tree_host_platform.cc b/chromium/ui/aura/window_tree_host_platform.cc
index 8cb7263bdaa..16027faaa71 100644
--- a/chromium/ui/aura/window_tree_host_platform.cc
+++ b/chromium/ui/aura/window_tree_host_platform.cc
@@ -6,6 +6,7 @@
#include <utility>
+#include "base/run_loop.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
#include "ui/aura/window_event_dispatcher.h"
@@ -23,7 +24,6 @@
#endif
#if defined(OS_WIN)
-#include "base/message_loop/message_loop.h"
#include "ui/base/cursor/cursor_loader_win.h"
#include "ui/platform_window/win/win_window.h"
#endif
@@ -158,7 +158,7 @@ void WindowTreeHostPlatform::DispatchEvent(ui::Event* event) {
void WindowTreeHostPlatform::OnCloseRequest() {
#if defined(OS_WIN)
// TODO: this obviously shouldn't be here.
- base::MessageLoopForUI::current()->QuitWhenIdle();
+ base::RunLoop::QuitCurrentWhenIdleDeprecated();
#else
OnHostCloseRequested();
#endif
diff --git a/chromium/ui/aura/window_tree_host_platform.h b/chromium/ui/aura/window_tree_host_platform.h
index 07340787579..13ef6ca1e57 100644
--- a/chromium/ui/aura/window_tree_host_platform.h
+++ b/chromium/ui/aura/window_tree_host_platform.h
@@ -21,9 +21,8 @@ class WindowPort;
// The unified WindowTreeHost implementation for platforms
// that implement PlatformWindow.
-class AURA_EXPORT WindowTreeHostPlatform
- : public WindowTreeHost,
- public NON_EXPORTED_BASE(ui::PlatformWindowDelegate) {
+class AURA_EXPORT WindowTreeHostPlatform : public WindowTreeHost,
+ public ui::PlatformWindowDelegate {
public:
explicit WindowTreeHostPlatform(const gfx::Rect& bounds);
~WindowTreeHostPlatform() override;
diff --git a/chromium/ui/aura/window_tree_host_unittest.cc b/chromium/ui/aura/window_tree_host_unittest.cc
index 735d26debfb..3c4900bd758 100644
--- a/chromium/ui/aura/window_tree_host_unittest.cc
+++ b/chromium/ui/aura/window_tree_host_unittest.cc
@@ -86,4 +86,12 @@ TEST_F(WindowTreeHostTest, NoRewritesPostIME) {
host()->RemoveEventRewriter(&event_rewriter);
}
+TEST_F(WindowTreeHostTest, ColorSpace) {
+ EXPECT_EQ(gfx::ColorSpace::CreateSRGB(),
+ host()->compositor()->output_color_space());
+ test_screen()->SetColorSpace(gfx::ColorSpace::CreateSCRGBLinear());
+ EXPECT_EQ(gfx::ColorSpace::CreateSCRGBLinear(),
+ host()->compositor()->output_color_space());
+}
+
} // namespace aura
diff --git a/chromium/ui/aura/window_tree_host_x11.cc b/chromium/ui/aura/window_tree_host_x11.cc
index d57358cf49a..cd4d4487e87 100644
--- a/chromium/ui/aura/window_tree_host_x11.cc
+++ b/chromium/ui/aura/window_tree_host_x11.cc
@@ -288,8 +288,16 @@ uint32_t WindowTreeHostX11::DispatchEvent(const ui::PlatformEvent& event) {
// It's possible that the X window may be resized by some other means
// than from within aura (e.g. the X window manager can change the
// size). Make sure the root window size is maintained properly.
- gfx::Rect bounds(xev->xconfigure.x, xev->xconfigure.y,
- xev->xconfigure.width, xev->xconfigure.height);
+ int translated_x = xev->xconfigure.x;
+ int translated_y = xev->xconfigure.y;
+ if (!xev->xconfigure.send_event && !xev->xconfigure.override_redirect) {
+ ::Window unused;
+ XTranslateCoordinates(xdisplay_, xwindow_, x_root_window_, 0, 0,
+ &translated_x, &translated_y, &unused);
+ }
+ gfx::Rect bounds(translated_x, translated_y, xev->xconfigure.width,
+ xev->xconfigure.height);
+
bool size_changed = bounds_.size() != bounds.size();
bool origin_changed = bounds_.origin() != bounds.origin();
bounds_ = bounds;
diff --git a/chromium/ui/aura/window_unittest.cc b/chromium/ui/aura/window_unittest.cc
index afe9120cbef..68fb78b987f 100644
--- a/chromium/ui/aura/window_unittest.cc
+++ b/chromium/ui/aura/window_unittest.cc
@@ -16,6 +16,8 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
+#include "cc/output/layer_tree_frame_sink.h"
+#include "services/ui/public/interfaces/window_tree_constants.mojom.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/capture_client.h"
#include "ui/aura/client/focus_change_observer.h"
@@ -1544,7 +1546,7 @@ TEST_P(WindowTest, Visibility) {
EXPECT_EQ(1, d2.shown());
}
-TEST_P(WindowTest, IgnoreEventsTest) {
+TEST_P(WindowTest, EventTargetingPolicy) {
TestWindowDelegate d11;
TestWindowDelegate d12;
TestWindowDelegate d111;
@@ -1560,18 +1562,32 @@ TEST_P(WindowTest, IgnoreEventsTest) {
std::unique_ptr<Window> w121(CreateTestWindowWithDelegate(
&d121, 121, gfx::Rect(150, 150, 50, 50), w12.get()));
+ EXPECT_EQ(w121.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
+ w12->SetEventTargetingPolicy(ui::mojom::EventTargetingPolicy::TARGET_ONLY);
+ EXPECT_EQ(w12.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
+ w12->SetEventTargetingPolicy(
+ ui::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS);
+
EXPECT_EQ(w12.get(), w1->GetEventHandlerForPoint(gfx::Point(10, 10)));
- w12->set_ignore_events(true);
+ w12->SetEventTargetingPolicy(ui::mojom::EventTargetingPolicy::NONE);
EXPECT_EQ(w11.get(), w1->GetEventHandlerForPoint(gfx::Point(10, 10)));
- w12->set_ignore_events(false);
+ w12->SetEventTargetingPolicy(
+ ui::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS);
EXPECT_EQ(w121.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
- w121->set_ignore_events(true);
+ w121->SetEventTargetingPolicy(ui::mojom::EventTargetingPolicy::NONE);
EXPECT_EQ(w12.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
- w12->set_ignore_events(true);
+ w12->SetEventTargetingPolicy(ui::mojom::EventTargetingPolicy::NONE);
EXPECT_EQ(w111.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
- w111->set_ignore_events(true);
+ w111->SetEventTargetingPolicy(ui::mojom::EventTargetingPolicy::NONE);
EXPECT_EQ(w11.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
+
+ w11->SetEventTargetingPolicy(
+ ui::mojom::EventTargetingPolicy::DESCENDANTS_ONLY);
+ EXPECT_EQ(nullptr, w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
+ w111->SetEventTargetingPolicy(
+ ui::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS);
+ EXPECT_EQ(w111.get(), w1->GetEventHandlerForPoint(gfx::Point(160, 160)));
}
// Tests transformation on the root window.
@@ -2850,6 +2866,33 @@ TEST_P(WindowTest, WindowDestroyCompletesAnimations) {
animator->RemoveObserver(&observer);
}
+TEST_P(WindowTest, LocalSurfaceIdChanges) {
+ Window window(nullptr);
+ window.Init(ui::LAYER_NOT_DRAWN);
+ std::unique_ptr<cc::LayerTreeFrameSink> frame_sink(
+ window.CreateLayerTreeFrameSink());
+ viz::LocalSurfaceId local_surface_id1 = window.GetLocalSurfaceId();
+ EXPECT_NE(nullptr, frame_sink.get());
+ EXPECT_TRUE(local_surface_id1.is_valid());
+
+ window.SetBounds(gfx::Rect(300, 300));
+ viz::LocalSurfaceId local_surface_id2 = window.GetLocalSurfaceId();
+ EXPECT_TRUE(local_surface_id2.is_valid());
+ EXPECT_NE(local_surface_id1, local_surface_id2);
+
+ window.OnDeviceScaleFactorChanged(3.0f);
+ viz::LocalSurfaceId local_surface_id3 = window.GetLocalSurfaceId();
+ EXPECT_TRUE(local_surface_id3.is_valid());
+ EXPECT_NE(local_surface_id1, local_surface_id3);
+ EXPECT_NE(local_surface_id2, local_surface_id3);
+
+ window.AllocateLocalSurfaceId();
+ viz::LocalSurfaceId local_surface_id4 = window.GetLocalSurfaceId();
+ EXPECT_NE(local_surface_id1, local_surface_id4);
+ EXPECT_NE(local_surface_id2, local_surface_id4);
+ EXPECT_NE(local_surface_id3, local_surface_id4);
+}
+
INSTANTIATE_TEST_CASE_P(/* no prefix */,
WindowTest,
::testing::Values(BackendType::CLASSIC,
diff --git a/chromium/ui/base/BUILD.gn b/chromium/ui/base/BUILD.gn
index 119d0fab47c..4210c32aa44 100644
--- a/chromium/ui/base/BUILD.gn
+++ b/chromium/ui/base/BUILD.gn
@@ -67,8 +67,6 @@ component("base") {
"accelerators/platform_accelerator.h",
"accelerators/platform_accelerator_cocoa.h",
"accelerators/platform_accelerator_cocoa.mm",
- "android/ui_base_jni_registrar.cc",
- "android/ui_base_jni_registrar.h",
"class_property.cc",
"class_property.h",
"clipboard/clipboard_android.cc",
@@ -379,8 +377,7 @@ component("base") {
if (is_fuchsia) {
sources += [
- "clipboard/clipboard_fuchsia.cc",
- "clipboard/clipboard_fuchsia.h",
+ "idle/idle_fuchsia.cc",
"resource/resource_bundle_fuchsia.cc",
]
}
@@ -584,10 +581,13 @@ component("base") {
]
deps += [
- "//ui/events/ozone:events_ozone_evdev",
"//ui/events/ozone:events_ozone_layout",
"//ui/ozone:ozone_base",
]
+
+ if (!is_fuchsia) {
+ deps += [ "//ui/events/ozone:events_ozone_evdev" ]
+ }
}
if (!toolkit_views && !use_aura) {
@@ -788,6 +788,7 @@ test("ui_base_unittests") {
"material_design/material_design_controller_unittest.cc",
"models/tree_node_iterator_unittest.cc",
"resource/data_pack_literal.cc",
+ "resource/data_pack_literal.h",
"resource/data_pack_unittest.cc",
"resource/resource_bundle_unittest.cc",
"resource/scale_factor_unittest.cc",
@@ -834,6 +835,7 @@ test("ui_base_unittests") {
"cocoa/controls/hyperlink_text_view_unittest.mm",
"cocoa/focus_tracker_unittest.mm",
"cocoa/fullscreen_window_manager_unittest.mm",
+ "cocoa/hover_button_unittest.mm",
"cocoa/hover_image_button_unittest.mm",
"cocoa/menu_controller_unittest.mm",
"cocoa/nsgraphics_context_additions_unittest.mm",
@@ -868,7 +870,7 @@ test("ui_base_unittests") {
if (use_x11) {
sources += [ "ime/composition_text_util_pango_unittest.cc" ]
}
- if (!use_x11 && is_chromeos) {
+ if (is_chromeos) {
# These were already removed in the non-chromeos case.
sources -= [ "ime/input_method_chromeos_unittest.cc" ]
}
@@ -881,6 +883,7 @@ test("ui_base_unittests") {
":ui_base_unittests_bundle_data",
"//base",
"//base/test:test_support",
+ "//mojo/edk/system",
"//net",
"//skia",
"//testing/gmock",
@@ -971,7 +974,7 @@ test("ui_base_unittests") {
]
}
- if (use_x11 && !is_chromeos) {
+ if (use_x11) {
sources += [
"dragdrop/os_exchange_data_provider_aurax11_unittest.cc",
"x/selection_requestor_unittest.cc",
diff --git a/chromium/ui/base/accelerators/accelerator_manager.cc b/chromium/ui/base/accelerators/accelerator_manager.cc
index d5c8a5bec16..b604c019ccc 100644
--- a/chromium/ui/base/accelerators/accelerator_manager.cc
+++ b/chromium/ui/base/accelerators/accelerator_manager.cc
@@ -88,22 +88,22 @@ bool AcceleratorManager::IsRegistered(const Accelerator& accelerator) const {
}
bool AcceleratorManager::Process(const Accelerator& accelerator) {
- bool result = false;
AcceleratorMap::iterator map_iter = accelerators_.find(accelerator);
- if (map_iter != accelerators_.end()) {
- // 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) {
- if ((*iter)->CanHandleAccelerators() &&
- (*iter)->AcceleratorPressed(accelerator)) {
- result = true;
- break;
- }
+ 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) {
+ if ((*iter)->CanHandleAccelerators() &&
+ (*iter)->AcceleratorPressed(accelerator)) {
+ return true;
}
}
- return result;
+
+ return false;
}
bool AcceleratorManager::HasPriorityHandler(
diff --git a/chromium/ui/base/accelerators/accelerator_manager.h b/chromium/ui/base/accelerators/accelerator_manager.h
index c792b181f91..621454eb9ed 100644
--- a/chromium/ui/base/accelerators/accelerator_manager.h
+++ b/chromium/ui/base/accelerators/accelerator_manager.h
@@ -69,7 +69,7 @@ class UI_BASE_EXPORT AcceleratorManager {
// Returns whether |accelerator| is already registered.
bool IsRegistered(const Accelerator& accelerator) const;
- // Activate the target associated with the specified accelerator.
+ // Activates the target associated with the specified accelerator.
// First, AcceleratorPressed handler of the most recently registered target
// is called, and if that handler processes the event (i.e. returns true),
// this method immediately returns. If not, we do the same thing on the next
diff --git a/chromium/ui/base/accelerators/accelerator_manager_unittest.cc b/chromium/ui/base/accelerators/accelerator_manager_unittest.cc
index 3cca7da2723..93752b37d4d 100644
--- a/chromium/ui/base/accelerators/accelerator_manager_unittest.cc
+++ b/chromium/ui/base/accelerators/accelerator_manager_unittest.cc
@@ -20,8 +20,8 @@ namespace {
class TestTarget : public AcceleratorTarget {
public:
- TestTarget() : accelerator_pressed_count_(0) {}
- ~TestTarget() override {}
+ TestTarget() = default;
+ ~TestTarget() override = default;
int accelerator_pressed_count() const {
return accelerator_pressed_count_;
@@ -36,7 +36,7 @@ class TestTarget : public AcceleratorTarget {
bool CanHandleAccelerators() const override;
private:
- int accelerator_pressed_count_;
+ int accelerator_pressed_count_ = 0;
DISALLOW_COPY_AND_ASSIGN(TestTarget);
};
diff --git a/chromium/ui/base/class_property.h b/chromium/ui/base/class_property.h
index 4df498944b0..38fdb7eb7fa 100644
--- a/chromium/ui/base/class_property.h
+++ b/chromium/ui/base/class_property.h
@@ -11,6 +11,7 @@
#include <memory>
#include <set>
+#include "base/time/time.h"
#include "ui/base/property_data.h"
#include "ui/base/ui_base_export.h"
#include "ui/base/ui_base_types.h"
@@ -45,8 +46,9 @@
// // outside all namespaces:
// DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(FOO_EXPORT, MyType)
//
-// If a property type is not exported, use DECLARE_CLASS_PROPERTY_TYPE(MyType)
-// which is a shorthand for DECLARE_EXPORTED_CLASS_PROPERTY_TYPE(, MyType).
+// If a property type is not exported, use
+// DECLARE_UI_CLASS_PROPERTY_TYPE(MyType) which is a shorthand for
+// DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(, MyType).
namespace ui {
@@ -144,6 +146,14 @@ class ClassPropertyCaster<bool> {
static int64_t ToInt64(bool x) { return static_cast<int64_t>(x); }
static bool FromInt64(int64_t x) { return x != 0; }
};
+template <>
+class ClassPropertyCaster<base::TimeDelta> {
+ public:
+ static int64_t ToInt64(base::TimeDelta x) { return x.InMicroseconds(); }
+ static base::TimeDelta FromInt64(int64_t x) {
+ return base::TimeDelta::FromMicroseconds(x);
+ }
+};
} // namespace
diff --git a/chromium/ui/base/class_property_unittest.cc b/chromium/ui/base/class_property_unittest.cc
index 31e85efb709..dcbacd021a9 100644
--- a/chromium/ui/base/class_property_unittest.cc
+++ b/chromium/ui/base/class_property_unittest.cc
@@ -86,29 +86,31 @@ TEST(PropertyTest, Property) {
}
TEST(PropertyTest, OwnedProperty) {
- std::unique_ptr<PropertyHandler> h = base::MakeUnique<PropertyHandler>();
-
- EXPECT_EQ(NULL, h->GetProperty(kOwnedKey));
- void* last_deleted = TestProperty::last_deleted();
- TestProperty* p1 = new TestProperty();
- h->SetProperty(kOwnedKey, p1);
- EXPECT_EQ(p1, h->GetProperty(kOwnedKey));
- EXPECT_EQ(last_deleted, TestProperty::last_deleted());
-
- TestProperty* p2 = new TestProperty();
- h->SetProperty(kOwnedKey, p2);
- EXPECT_EQ(p2, h->GetProperty(kOwnedKey));
- EXPECT_EQ(p1, TestProperty::last_deleted());
-
- h->ClearProperty(kOwnedKey);
- EXPECT_EQ(NULL, h->GetProperty(kOwnedKey));
- EXPECT_EQ(p2, TestProperty::last_deleted());
-
- TestProperty* p3 = new TestProperty();
- h->SetProperty(kOwnedKey, p3);
- EXPECT_EQ(p3, h->GetProperty(kOwnedKey));
- EXPECT_EQ(p2, TestProperty::last_deleted());
- h.reset();
+ TestProperty* p3;
+ {
+ PropertyHandler h;
+
+ EXPECT_EQ(NULL, h.GetProperty(kOwnedKey));
+ void* last_deleted = TestProperty::last_deleted();
+ TestProperty* p1 = new TestProperty();
+ h.SetProperty(kOwnedKey, p1);
+ EXPECT_EQ(p1, h.GetProperty(kOwnedKey));
+ EXPECT_EQ(last_deleted, TestProperty::last_deleted());
+
+ TestProperty* p2 = new TestProperty();
+ h.SetProperty(kOwnedKey, p2);
+ EXPECT_EQ(p2, h.GetProperty(kOwnedKey));
+ EXPECT_EQ(p1, TestProperty::last_deleted());
+
+ h.ClearProperty(kOwnedKey);
+ EXPECT_EQ(NULL, h.GetProperty(kOwnedKey));
+ EXPECT_EQ(p2, TestProperty::last_deleted());
+
+ p3 = new TestProperty();
+ h.SetProperty(kOwnedKey, p3);
+ EXPECT_EQ(p3, h.GetProperty(kOwnedKey));
+ EXPECT_EQ(p2, TestProperty::last_deleted());
+ }
EXPECT_EQ(p3, TestProperty::last_deleted());
}
diff --git a/chromium/ui/base/clipboard/clipboard.h b/chromium/ui/base/clipboard/clipboard.h
index 8d0cd38f4a2..94236adca28 100644
--- a/chromium/ui/base/clipboard/clipboard.h
+++ b/chromium/ui/base/clipboard/clipboard.h
@@ -8,12 +8,12 @@
#include <stddef.h>
#include <stdint.h>
-#include <map>
#include <memory>
#include <string>
#include <vector>
#include "base/compiler_specific.h"
+#include "base/containers/flat_map.h"
#include "base/lazy_instance.h"
#include "base/macros.h"
#include "base/process/process.h"
@@ -42,7 +42,7 @@ namespace ui {
class TestClipboard;
class ScopedClipboardWriter;
-class UI_BASE_EXPORT Clipboard : NON_EXPORTED_BASE(public base::ThreadChecker) {
+class UI_BASE_EXPORT Clipboard : public base::ThreadChecker {
public:
// MIME type constants.
static const char kMimeTypeText[];
@@ -292,9 +292,9 @@ class UI_BASE_EXPORT Clipboard : NON_EXPORTED_BASE(public base::ThreadChecker) {
// CBF_WEBKIT none empty vector
// CBF_DATA format char array
// data byte array
- typedef std::vector<char> ObjectMapParam;
- typedef std::vector<ObjectMapParam> ObjectMapParams;
- typedef std::map<int /* ObjectType */, ObjectMapParams> ObjectMap;
+ using ObjectMapParam = std::vector<char>;
+ using ObjectMapParams = std::vector<ObjectMapParam>;
+ using ObjectMap = base::flat_map<int /* ObjectType */, ObjectMapParams>;
// Write a bunch of objects to the system clipboard. Copies are made of the
// contents of |objects|.
@@ -337,13 +337,13 @@ class UI_BASE_EXPORT Clipboard : NON_EXPORTED_BASE(public base::ThreadChecker) {
// A list of allowed threads. By default, this is empty and no thread checking
// is done (in the unit test case), but a user (like content) can set which
// threads are allowed to call this method.
- typedef std::vector<base::PlatformThreadId> AllowedThreadsVector;
+ using AllowedThreadsVector = std::vector<base::PlatformThreadId>;
static base::LazyInstance<AllowedThreadsVector>::DestructorAtExit
allowed_threads_;
// Mapping from threads to clipboard objects.
- typedef std::map<base::PlatformThreadId, std::unique_ptr<Clipboard>>
- ClipboardMap;
+ using ClipboardMap =
+ base::flat_map<base::PlatformThreadId, std::unique_ptr<Clipboard>>;
static base::LazyInstance<ClipboardMap>::DestructorAtExit clipboard_map_;
// Mutex that controls access to |g_clipboard_map|.
diff --git a/chromium/ui/base/clipboard/clipboard_android.cc b/chromium/ui/base/clipboard/clipboard_android.cc
index 849493e10fe..a151b9930a0 100644
--- a/chromium/ui/base/clipboard/clipboard_android.cc
+++ b/chromium/ui/base/clipboard/clipboard_android.cc
@@ -550,10 +550,6 @@ void ClipboardAndroid::WriteData(const Clipboard::FormatType& format,
g_map.Get().Set(format.ToString(), std::string(data_data, data_len));
}
-bool RegisterClipboardAndroid(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
// Returns a pointer to the current ClipboardAndroid object.
static jlong Init(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj) {
diff --git a/chromium/ui/base/clipboard/clipboard_android.h b/chromium/ui/base/clipboard/clipboard_android.h
index 716cc387f74..1ef1bee944b 100644
--- a/chromium/ui/base/clipboard/clipboard_android.h
+++ b/chromium/ui/base/clipboard/clipboard_android.h
@@ -87,9 +87,6 @@ class ClipboardAndroid : public Clipboard {
DISALLOW_COPY_AND_ASSIGN(ClipboardAndroid);
};
-// Registers the ClipboardAndroid native method.
-bool RegisterClipboardAndroid(JNIEnv* env);
-
} // namespace ui
#endif // UI_BASE_CLIPBOARD_CLIPBOARD_ANDROID_H_
diff --git a/chromium/ui/base/clipboard/clipboard_fuchsia.cc b/chromium/ui/base/clipboard/clipboard_fuchsia.cc
deleted file mode 100644
index 72de3f4daf1..00000000000
--- a/chromium/ui/base/clipboard/clipboard_fuchsia.cc
+++ /dev/null
@@ -1,281 +0,0 @@
-// Copyright 2017 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/base/clipboard/clipboard_fuchsia.h"
-
-#include <algorithm>
-#include <utility>
-
-#include "base/callback.h"
-#include "base/lazy_instance.h"
-#include "base/stl_util.h"
-#include "base/strings/utf_string_conversions.h"
-#include "base/synchronization/lock.h"
-#include "base/time/time.h"
-#include "third_party/skia/include/core/SkBitmap.h"
-#include "ui/gfx/geometry/size.h"
-
-namespace ui {
-
-const char kMimeTypeBitmap[] = "image/bmp";
-
-// Clipboard::FormatType implementation.
-Clipboard::FormatType::FormatType() {}
-
-Clipboard::FormatType::FormatType(const std::string& native_format)
- : data_(native_format) {}
-
-Clipboard::FormatType::~FormatType() {}
-
-std::string Clipboard::FormatType::Serialize() const {
- return data_;
-}
-
-// static
-Clipboard::FormatType Clipboard::FormatType::Deserialize(
- const std::string& serialization) {
- return FormatType(serialization);
-}
-
-bool Clipboard::FormatType::operator<(const FormatType& other) const {
- return data_ < other.data_;
-}
-
-bool Clipboard::FormatType::Equals(const FormatType& other) const {
- return data_ == other.data_;
-}
-
-// Various predefined FormatTypes.
-// static
-Clipboard::FormatType Clipboard::GetFormatType(
- const std::string& format_string) {
- return FormatType::Deserialize(format_string);
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetUrlFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeURIList));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetUrlWFormatType() {
- return GetUrlFormatType();
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetPlainTextFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeText));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetPlainTextWFormatType() {
- return GetPlainTextFormatType();
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetWebKitSmartPasteFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebkitSmartPaste));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetHtmlFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeHTML));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetRtfFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeRTF));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetBitmapFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeBitmap));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetWebCustomDataFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypeWebCustomData));
- return type;
-}
-
-// static
-const Clipboard::FormatType& Clipboard::GetPepperCustomDataFormatType() {
- CR_DEFINE_STATIC_LOCAL(FormatType, type, (kMimeTypePepperCustomData));
- return type;
-}
-
-// Clipboard factory method.
-// static
-Clipboard* Clipboard::Create() {
- return new ClipboardFuchsia;
-}
-
-// ClipboardFuchsia implementation.
-
-ClipboardFuchsia::ClipboardFuchsia() {
- DCHECK(CalledOnValidThread());
-}
-
-ClipboardFuchsia::~ClipboardFuchsia() {
- DCHECK(CalledOnValidThread());
-}
-
-void ClipboardFuchsia::OnPreShutdown() {}
-
-uint64_t ClipboardFuchsia::GetSequenceNumber(ClipboardType type) const {
- DCHECK(CalledOnValidThread());
- NOTIMPLEMENTED();
- return 0;
-}
-
-bool ClipboardFuchsia::IsFormatAvailable(const Clipboard::FormatType& format,
- ClipboardType type) const {
- DCHECK(CalledOnValidThread());
- DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
- NOTIMPLEMENTED();
- return false;
-}
-
-void ClipboardFuchsia::Clear(ClipboardType type) {
- DCHECK(CalledOnValidThread());
- DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
- NOTIMPLEMENTED();
-}
-
-void ClipboardFuchsia::ReadAvailableTypes(ClipboardType type,
- std::vector<base::string16>* types,
- bool* contains_filenames) const {
- DCHECK(CalledOnValidThread());
- DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
- NOTIMPLEMENTED();
- types->clear();
- *contains_filenames = false;
-}
-
-void ClipboardFuchsia::ReadText(ClipboardType type,
- base::string16* result) const {
- DCHECK(CalledOnValidThread());
- DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
- NOTREACHED();
-}
-
-void ClipboardFuchsia::ReadAsciiText(ClipboardType type,
- std::string* result) const {
- DCHECK(CalledOnValidThread());
- DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
- NOTREACHED();
-}
-
-// Note: |src_url| isn't really used. It is only implemented in Windows
-void ClipboardFuchsia::ReadHTML(ClipboardType type,
- base::string16* markup,
- std::string* src_url,
- uint32_t* fragment_start,
- uint32_t* fragment_end) const {
- DCHECK(CalledOnValidThread());
- DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
- NOTREACHED();
-}
-
-void ClipboardFuchsia::ReadRTF(ClipboardType type, std::string* result) const {
- DCHECK(CalledOnValidThread());
- NOTREACHED();
-}
-
-SkBitmap ClipboardFuchsia::ReadImage(ClipboardType type) const {
- DCHECK(CalledOnValidThread());
- DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
- NOTREACHED();
- return SkBitmap();
-}
-
-void ClipboardFuchsia::ReadCustomData(ClipboardType clipboard_type,
- const base::string16& type,
- base::string16* result) const {
- DCHECK(CalledOnValidThread());
- NOTREACHED();
-}
-
-void ClipboardFuchsia::ReadBookmark(base::string16* title,
- std::string* url) const {
- DCHECK(CalledOnValidThread());
- NOTREACHED();
-}
-
-void ClipboardFuchsia::ReadData(const Clipboard::FormatType& format,
- std::string* result) const {
- DCHECK(CalledOnValidThread());
- NOTIMPLEMENTED();
- result->clear();
-}
-
-base::Time ClipboardFuchsia::GetLastModifiedTime() const {
- DCHECK(CalledOnValidThread());
- NOTIMPLEMENTED();
- return base::Time();
-}
-
-void ClipboardFuchsia::ClearLastModifiedTime() {
- DCHECK(CalledOnValidThread());
- NOTIMPLEMENTED();
-}
-
-// Main entry point used to write several values in the clipboard.
-void ClipboardFuchsia::WriteObjects(ClipboardType type,
- const ObjectMap& objects) {
- DCHECK(CalledOnValidThread());
- DCHECK_EQ(type, CLIPBOARD_TYPE_COPY_PASTE);
- NOTIMPLEMENTED();
-}
-
-void ClipboardFuchsia::WriteText(const char* text_data, size_t text_len) {
- DCHECK(CalledOnValidThread());
- NOTIMPLEMENTED();
-}
-
-void ClipboardFuchsia::WriteHTML(const char* markup_data,
- size_t markup_len,
- const char* url_data,
- size_t url_len) {
- DCHECK(CalledOnValidThread());
- NOTIMPLEMENTED();
-}
-
-void ClipboardFuchsia::WriteRTF(const char* rtf_data, size_t data_len) {
- DCHECK(CalledOnValidThread());
- NOTIMPLEMENTED();
-}
-
-void ClipboardFuchsia::WriteBookmark(const char* title_data,
- size_t title_len,
- const char* url_data,
- size_t url_len) {
- DCHECK(CalledOnValidThread());
- NOTIMPLEMENTED();
-}
-
-void ClipboardFuchsia::WriteWebSmartPaste() {
- DCHECK(CalledOnValidThread());
- NOTIMPLEMENTED();
-}
-
-void ClipboardFuchsia::WriteBitmap(const SkBitmap& bitmap) {
- DCHECK(CalledOnValidThread());
- NOTIMPLEMENTED();
-}
-
-void ClipboardFuchsia::WriteData(const Clipboard::FormatType& format,
- const char* data_data,
- size_t data_len) {
- DCHECK(CalledOnValidThread());
- NOTIMPLEMENTED();
-}
-
-} // namespace ui
diff --git a/chromium/ui/base/clipboard/clipboard_fuchsia.h b/chromium/ui/base/clipboard/clipboard_fuchsia.h
deleted file mode 100644
index ca68893aac9..00000000000
--- a/chromium/ui/base/clipboard/clipboard_fuchsia.h
+++ /dev/null
@@ -1,71 +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_CLIPBOARD_CLIPBOARD_FUCHSIA_H_
-#define UI_BASE_CLIPBOARD_CLIPBOARD_FUCHSIA_H_
-
-#include "ui/base/clipboard/clipboard.h"
-
-#include "base/macros.h"
-#include "base/time/time.h"
-
-namespace ui {
-
-// This is a stub implementation of Clipboard for Fuchsia.
-// TODO(fuchsia): Implement this class.
-class ClipboardFuchsia : public Clipboard {
- private:
- friend class Clipboard;
-
- ClipboardFuchsia();
- ~ClipboardFuchsia() override;
-
- // Clipboard overrides:
- void OnPreShutdown() override;
- uint64_t GetSequenceNumber(ClipboardType type) const override;
- bool IsFormatAvailable(const FormatType& format,
- ClipboardType type) const override;
- void Clear(ClipboardType type) override;
- void ReadAvailableTypes(ClipboardType type,
- std::vector<base::string16>* types,
- bool* contains_filenames) const override;
- void ReadText(ClipboardType type, base::string16* result) const override;
- void ReadAsciiText(ClipboardType type, std::string* result) const override;
- void ReadHTML(ClipboardType type,
- base::string16* markup,
- std::string* src_url,
- uint32_t* fragment_start,
- uint32_t* fragment_end) const override;
- void ReadRTF(ClipboardType type, std::string* result) const override;
- SkBitmap ReadImage(ClipboardType type) const override;
- void ReadCustomData(ClipboardType clipboard_type,
- const base::string16& type,
- base::string16* result) const override;
- void ReadBookmark(base::string16* title, std::string* url) const override;
- void ReadData(const FormatType& format, std::string* result) const override;
- base::Time GetLastModifiedTime() const override;
- void ClearLastModifiedTime() override;
- void WriteObjects(ClipboardType type, const ObjectMap& objects) override;
- void WriteText(const char* text_data, size_t text_len) override;
- void WriteHTML(const char* markup_data,
- size_t markup_len,
- const char* url_data,
- size_t url_len) override;
- void WriteRTF(const char* rtf_data, size_t data_len) override;
- void WriteBookmark(const char* title_data,
- size_t title_len,
- const char* url_data,
- size_t url_len) override;
- void WriteWebSmartPaste() override;
- void WriteBitmap(const SkBitmap& bitmap) override;
- void WriteData(const FormatType& format,
- const char* data_data,
- size_t data_len) override;
-
- DISALLOW_COPY_AND_ASSIGN(ClipboardFuchsia);
-};
-
-} // namespace ui
-
-#endif // UI_BASE_CLIPBOARD_CLIPBOARD_FUCHSIA_H_
diff --git a/chromium/ui/base/clipboard/clipboard_monitor.h b/chromium/ui/base/clipboard/clipboard_monitor.h
index cd6ed1e13c3..1330aaf0764 100644
--- a/chromium/ui/base/clipboard/clipboard_monitor.h
+++ b/chromium/ui/base/clipboard/clipboard_monitor.h
@@ -17,8 +17,7 @@ class ClipboardObserver;
// A singleton instance to monitor and notify ClipboardObservers for clipboard
// changes.
-class UI_BASE_EXPORT ClipboardMonitor
- : NON_EXPORTED_BASE(public base::ThreadChecker) {
+class UI_BASE_EXPORT ClipboardMonitor : public base::ThreadChecker {
public:
static ClipboardMonitor* GetInstance();
diff --git a/chromium/ui/base/cocoa/hover_button.h b/chromium/ui/base/cocoa/hover_button.h
index b25e29aa3e1..5354bf7258a 100644
--- a/chromium/ui/base/cocoa/hover_button.h
+++ b/chromium/ui/base/cocoa/hover_button.h
@@ -10,6 +10,22 @@
#import "ui/base/cocoa/tracking_area.h"
#import "ui/base/ui_base_export.h"
+@class HoverButton;
+
+// Assign an object which conforms to this protocol to a HoverButton's
+// dragDelegate property to make the button draggable.
+UI_BASE_EXPORT
+@protocol HoverButtonDragDelegate
+
+// When the user performs a drag on the HoverButton, this method will be called
+// with the button and the mouse down event. The delegate is expected to begin
+// a drag by calling -[NSView beginDraggingSessionWithItems:event:source:] with
+// the event or run a nested tracking loop. When it returns, the HoverButton
+// returns to kHoverStateNone and stops tracking the mouse.
+- (void)beginDragFromHoverButton:(HoverButton*)button event:(NSEvent*)event;
+
+@end
+
// A button that changes when you hover over it and click it.
UI_BASE_EXPORT
@interface HoverButton : NSButton {
@@ -32,6 +48,19 @@ UI_BASE_EXPORT
@property(nonatomic) HoverState hoverState;
+// Enables or disables the tracking for the button.
+@property(nonatomic) BOOL trackingEnabled;
+
+// Assign an object to make the button a drag source.
+@property(nonatomic, assign) id<HoverButtonDragDelegate> dragDelegate;
+
+// An NSRect in the view's coordinate space which is used for hover and hit
+// testing. Default value is NSZeroRect, which makes the hitbox equal to the
+// view's bounds. May be overridden by subclasses. Example: A button in the
+// corner of a fullscreen window might extend its hitbox to the edges of the
+// window so that it can be clicked more easily (Fitts's law).
+@property(readonly, nonatomic) NSRect hitbox;
+
// Common initialization called from initWithFrame: and awakeFromNib.
// Subclassers should call [super commonInit].
- (void)commonInit;
@@ -39,9 +68,6 @@ UI_BASE_EXPORT
// Text that would be announced by screen readers.
- (void)setAccessibilityTitle:(NSString*)accessibilityTitle;
-// Enables or disables the tracking for the button.
-- (void)setTrackingEnabled:(BOOL)enabled;
-
// Checks to see whether the mouse is in the button's bounds and update
// the image in case it gets out of sync. This occurs to the close button
// when you close a tab so the tab to the left of it takes its place, and
diff --git a/chromium/ui/base/cocoa/hover_button.mm b/chromium/ui/base/cocoa/hover_button.mm
index ebcd582ea64..b8e9b1547a7 100644
--- a/chromium/ui/base/cocoa/hover_button.mm
+++ b/chromium/ui/base/cocoa/hover_button.mm
@@ -4,9 +4,20 @@
#import "ui/base/cocoa/hover_button.h"
+#include <cmath>
+
+namespace {
+
+// Distance to start a drag when a dragDelegate is assigned.
+constexpr CGFloat kDragDistance = 5;
+
+} // namespace
+
@implementation HoverButton
@synthesize hoverState = hoverState_;
+@synthesize trackingEnabled = trackingEnabled_;
+@synthesize dragDelegate = dragDelegate_;
- (id)initWithFrame:(NSRect)frameRect {
if ((self = [super initWithFrame:frameRect])) {
@@ -20,16 +31,33 @@
}
- (void)commonInit {
- [self setTrackingEnabled:YES];
self.hoverState = kHoverStateNone;
- [self updateTrackingAreas];
+ self.trackingEnabled = YES;
}
- (void)dealloc {
- [self setTrackingEnabled:NO];
+ self.trackingEnabled = NO;
[super dealloc];
}
+- (NSRect)hitbox {
+ return NSZeroRect;
+}
+
+- (void)setTrackingEnabled:(BOOL)trackingEnabled {
+ if (trackingEnabled == trackingEnabled_)
+ return;
+ trackingEnabled_ = trackingEnabled;
+ [self updateTrackingAreas];
+}
+
+- (void)setEnabled:(BOOL)enabled {
+ if (enabled == self.enabled)
+ return;
+ super.enabled = enabled;
+ [self updateTrackingAreas];
+}
+
- (void)mouseEntered:(NSEvent*)theEvent {
if (trackingArea_.get())
self.hoverState = kHoverStateMouseOver;
@@ -45,6 +73,8 @@
}
- (void)mouseDown:(NSEvent*)theEvent {
+ if (!self.enabled)
+ return;
mouseDown_ = YES;
self.hoverState = kHoverStateMouseDown;
@@ -64,12 +94,21 @@
NSKeyDownMask | NSKeyUpMask);
while ((nextEvent = [window nextEventMatchingMask:eventMask])) {
+ if ([nextEvent type] == NSLeftMouseUp)
+ break;
// Update the image state, which will change if the user moves the mouse
// into or out of the button.
[self checkImageState];
-
- if ([nextEvent type] == NSLeftMouseUp) {
- break;
+ if (dragDelegate_ && [nextEvent type] == NSLeftMouseDragged) {
+ const NSPoint startPos = [theEvent locationInWindow];
+ const NSPoint pos = [nextEvent locationInWindow];
+ if (std::abs(startPos.x - pos.x) > kDragDistance ||
+ std::abs(startPos.y - pos.y) > kDragDistance) {
+ [dragDelegate_ beginDragFromHoverButton:self event:nextEvent];
+ mouseDown_ = NO;
+ self.hoverState = kHoverStateNone;
+ return;
+ }
}
}
}
@@ -77,11 +116,12 @@
// If the mouse is still over the button, it means the user clicked the
// button.
if (self.hoverState == kHoverStateMouseDown) {
- [self performClick:nil];
+ [self sendAction:self.action to:self.target];
}
// Clean up.
mouseDown_ = NO;
+ [self checkImageState];
}
- (void)setAccessibilityTitle:(NSString*)accessibilityTitle {
@@ -90,16 +130,22 @@
forAttribute:NSAccessibilityTitleAttribute];
}
-- (void)setTrackingEnabled:(BOOL)enabled {
- if (enabled) {
- trackingArea_.reset(
- [[CrTrackingArea alloc] initWithRect:NSZeroRect
- options:NSTrackingMouseEnteredAndExited |
- NSTrackingMouseMoved |
- NSTrackingActiveAlways |
- NSTrackingInVisibleRect
- owner:self
- userInfo:nil]);
+- (void)updateTrackingAreas {
+ if (trackingEnabled_ && self.enabled) {
+ NSRect hitbox = self.hitbox;
+ if (CrTrackingArea* trackingArea = trackingArea_.get()) {
+ if (NSEqualRects(trackingArea.rect, hitbox))
+ return;
+ [self removeTrackingArea:trackingArea];
+ }
+ trackingArea_.reset([[CrTrackingArea alloc]
+ initWithRect:hitbox
+ options:NSTrackingMouseEnteredAndExited |
+ NSTrackingMouseMoved |
+ NSTrackingActiveAlways |
+ (NSIsEmptyRect(hitbox) ? NSTrackingInVisibleRect : 0)
+ owner:self
+ userInfo:nil]);
[self addTrackingArea:trackingArea_.get()];
// If you have a separate window that overlaps the close button, and you
@@ -119,9 +165,6 @@
trackingArea_.reset(nil);
}
}
-}
-
-- (void)updateTrackingAreas {
[super updateTrackingAreas];
[self checkImageState];
}
@@ -130,10 +173,14 @@
if (!trackingArea_.get())
return;
+ NSEvent* currentEvent = [NSApp currentEvent];
+ if (!currentEvent || currentEvent.window != self.window)
+ return;
+
// Update the button's state if the button has moved.
- NSPoint mouseLoc = [[self window] mouseLocationOutsideOfEventStream];
- mouseLoc = [self convertPoint:mouseLoc fromView:nil];
- BOOL mouseInBounds = NSPointInRect(mouseLoc, [self bounds]);
+ const NSPoint mouseLoc =
+ [self.superview convertPoint:currentEvent.locationInWindow fromView:nil];
+ BOOL mouseInBounds = [self hitTest:mouseLoc] != nil;
if (mouseDown_ && mouseInBounds) {
self.hoverState = kHoverStateMouseDown;
} else {
@@ -141,10 +188,19 @@
}
}
-- (void)setHoverState:(HoverState)state {
- BOOL stateChanged = (hoverState_ != state);
- hoverState_ = state;
- [self setNeedsDisplay:stateChanged];
+- (void)setHoverState:(HoverState)hoverState {
+ if (hoverState == hoverState_)
+ return;
+ hoverState_ = hoverState;
+ self.needsDisplay = YES;
+}
+
+- (NSView*)hitTest:(NSPoint)point {
+ if (NSPointInRect([self.superview convertPoint:point toView:self],
+ self.hitbox)) {
+ return self;
+ }
+ return [super hitTest:point];
}
@end
diff --git a/chromium/ui/base/cocoa/hover_button_unittest.mm b/chromium/ui/base/cocoa/hover_button_unittest.mm
new file mode 100644
index 00000000000..54f15c24b67
--- /dev/null
+++ b/chromium/ui/base/cocoa/hover_button_unittest.mm
@@ -0,0 +1,199 @@
+// 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/hover_button.h"
+
+#import <Cocoa/Cocoa.h>
+
+#import "ui/events/test/cocoa_test_event_utils.h"
+#import "ui/gfx/test/ui_cocoa_test_helper.h"
+
+@interface TestHoverButton : HoverButton
+@property(readwrite, nonatomic) NSRect hitbox;
+@end
+
+@implementation TestHoverButton
+@synthesize hitbox = hitbox_;
+
+- (void)setHitbox:(NSRect)hitbox {
+ hitbox_ = hitbox;
+ [self updateTrackingAreas];
+}
+@end
+
+@interface HoverButtonTestTarget : NSObject
+@property(nonatomic, copy) void (^actionHandler)(id);
+@end
+
+@implementation HoverButtonTestTarget
+@synthesize actionHandler = actionHandler_;
+
+- (void)dealloc {
+ [actionHandler_ release];
+ [super dealloc];
+}
+
+- (IBAction)action:(id)sender {
+ actionHandler_(sender);
+}
+@end
+
+@interface HoverButtonTestDragDelegate : NSObject<HoverButtonDragDelegate>
+@property(nonatomic, copy) void (^dragHandler)(HoverButton*, NSEvent*);
+@end
+
+@implementation HoverButtonTestDragDelegate
+@synthesize dragHandler = dragHandler_;
+
+- (void)dealloc {
+ [dragHandler_ release];
+ [super dealloc];
+}
+
+- (void)beginDragFromHoverButton:(HoverButton*)button event:(NSEvent*)event {
+ dragHandler_(button, event);
+}
+@end
+
+namespace {
+
+class HoverButtonTest : public ui::CocoaTest {
+ public:
+ HoverButtonTest() {
+ NSRect frame = NSMakeRect(0, 0, 20, 20);
+ base::scoped_nsobject<TestHoverButton> button(
+ [[TestHoverButton alloc] initWithFrame:frame]);
+ button_ = button;
+ target_.reset([[HoverButtonTestTarget alloc] init]);
+ button_.target = target_;
+ button_.action = @selector(action:);
+ [[test_window() contentView] addSubview:button_];
+ }
+
+ protected:
+ void HoverAndExpect(HoverState hoverState) {
+ EXPECT_EQ(kHoverStateNone, button_.hoverState);
+ [button_ mouseEntered:cocoa_test_event_utils::EnterEvent()];
+ EXPECT_EQ(hoverState, button_.hoverState);
+ [button_ mouseExited:cocoa_test_event_utils::ExitEvent()];
+ EXPECT_EQ(kHoverStateNone, button_.hoverState);
+ }
+
+ bool HandleMouseDown(NSEvent* mouseDownEvent) {
+ __block bool action_sent = false;
+ target_.get().actionHandler = ^(id sender) {
+ action_sent = true;
+ EXPECT_EQ(kHoverStateMouseDown, button_.hoverState);
+ };
+ [NSApp sendEvent:mouseDownEvent];
+ target_.get().actionHandler = nil;
+ return action_sent;
+ }
+
+ TestHoverButton* button_; // Weak, owned by test_window().
+ base::scoped_nsobject<HoverButtonTestTarget> target_;
+};
+
+TEST_VIEW(HoverButtonTest, button_)
+
+TEST_F(HoverButtonTest, Hover) {
+ EXPECT_EQ(kHoverStateNone, button_.hoverState);
+
+ // Default
+ HoverAndExpect(kHoverStateMouseOver);
+
+ // Tracking disabled
+ button_.trackingEnabled = NO;
+ HoverAndExpect(kHoverStateNone);
+ button_.trackingEnabled = YES;
+
+ // Button disabled
+ button_.enabled = NO;
+ HoverAndExpect(kHoverStateNone);
+ button_.enabled = YES;
+
+ // Back to normal
+ HoverAndExpect(kHoverStateMouseOver);
+}
+
+TEST_F(HoverButtonTest, Click) {
+ EXPECT_EQ(kHoverStateNone, button_.hoverState);
+ const auto click = cocoa_test_event_utils::MouseClickInView(button_, 1);
+
+ [NSApp postEvent:click.second atStart:YES];
+ EXPECT_TRUE(HandleMouseDown(click.first));
+
+ button_.enabled = NO;
+ EXPECT_FALSE(HandleMouseDown(click.first));
+
+ EXPECT_EQ(kHoverStateNone, button_.hoverState);
+}
+
+TEST_F(HoverButtonTest, CustomHitbox) {
+ NSRect hitbox = button_.frame;
+ hitbox.size.width += 10;
+
+ NSPoint inside_hit_point =
+ NSMakePoint(NSMaxX(button_.frame) + 5, NSMidY(button_.frame));
+ NSPoint outside_hit_point =
+ NSMakePoint(inside_hit_point.x + 10, inside_hit_point.y);
+
+ {
+ NSRect trackingRect = button_.trackingAreas[0].rect;
+ EXPECT_FALSE(NSPointInRect(inside_hit_point, trackingRect));
+ EXPECT_FALSE(NSPointInRect(outside_hit_point, trackingRect));
+ EXPECT_NE(button_, [button_ hitTest:inside_hit_point]);
+ EXPECT_EQ(nil, [button_ hitTest:outside_hit_point]);
+ }
+
+ button_.hitbox = hitbox;
+ {
+ NSRect trackingRect = button_.trackingAreas[0].rect;
+ EXPECT_TRUE(NSPointInRect(inside_hit_point, trackingRect));
+ EXPECT_FALSE(NSPointInRect(outside_hit_point, trackingRect));
+ EXPECT_EQ(button_, [button_ hitTest:inside_hit_point]);
+ EXPECT_EQ(nil, [button_ hitTest:outside_hit_point]);
+ }
+
+ button_.hitbox = NSZeroRect;
+ {
+ NSRect trackingRect = button_.trackingAreas[0].rect;
+ EXPECT_FALSE(NSPointInRect(inside_hit_point, trackingRect));
+ EXPECT_FALSE(NSPointInRect(outside_hit_point, trackingRect));
+ EXPECT_NE(button_, [button_ hitTest:inside_hit_point]);
+ EXPECT_EQ(nil, [button_ hitTest:outside_hit_point]);
+ }
+}
+
+TEST_F(HoverButtonTest, DragDelegate) {
+ base::scoped_nsobject<HoverButtonTestDragDelegate> dragDelegate(
+ [[HoverButtonTestDragDelegate alloc] init]);
+
+ __block bool dragged = false;
+ dragDelegate.get().dragHandler = ^(HoverButton* button, NSEvent* event) {
+ dragged = true;
+ };
+ button_.dragDelegate = dragDelegate;
+
+ const auto click = cocoa_test_event_utils::MouseClickInView(button_, 1);
+ NSPoint targetPoint = click.first.locationInWindow;
+ targetPoint.x += 5; // *Not* enough to trigger a drag.
+ [NSApp postEvent:cocoa_test_event_utils::MouseEventAtPointInWindow(
+ targetPoint, NSEventTypeLeftMouseDragged,
+ [button_ window], 1)
+ atStart:NO];
+ [NSApp postEvent:click.second atStart:NO];
+ EXPECT_TRUE(HandleMouseDown(click.first));
+ EXPECT_FALSE(dragged);
+
+ targetPoint.x += 1; // Now it's enough to trigger a drag.
+ [NSApp postEvent:cocoa_test_event_utils::MouseEventAtPointInWindow(
+ targetPoint, NSEventTypeLeftMouseDragged,
+ [button_ window], 1)
+ atStart:NO];
+ [NSApp postEvent:click.second atStart:NO];
+ EXPECT_FALSE(HandleMouseDown(click.first));
+ EXPECT_TRUE(dragged);
+}
+} // namespace
diff --git a/chromium/ui/base/cocoa/menu_controller.mm b/chromium/ui/base/cocoa/menu_controller.mm
index 7e38840d22b..7f547003ba5 100644
--- a/chromium/ui/base/cocoa/menu_controller.mm
+++ b/chromium/ui/base/cocoa/menu_controller.mm
@@ -18,6 +18,33 @@
#include "ui/gfx/font_list.h"
#include "ui/gfx/image/image.h"
#include "ui/gfx/text_elider.h"
+#include "ui/strings/grit/ui_strings.h"
+
+namespace {
+
+// Called when an empty submenu is created. This inserts a menu item labeled
+// "(empty)" into the submenu. Matches Windows behavior.
+NSMenu* MakeEmptySubmenu() {
+ base::scoped_nsobject<NSMenu> submenu([[NSMenu alloc] initWithTitle:@""]);
+ NSString* empty_menu_title =
+ l10n_util::GetNSString(IDS_APP_MENU_EMPTY_SUBMENU);
+ [submenu addItemWithTitle:empty_menu_title action:NULL keyEquivalent:@""];
+ [[submenu itemAtIndex:0] setEnabled:NO];
+ return submenu.autorelease();
+}
+
+// Called when adding a submenu to the menu and checks if the submenu, via its
+// |model|, has visible child items.
+bool MenuHasVisibleItems(const ui::MenuModel* model) {
+ int count = model->GetItemCount();
+ for (int index = 0; index < count; index++) {
+ if (model->IsVisibleAt(index))
+ return true;
+ }
+ return false;
+}
+
+} // namespace
NSString* const kMenuControllerMenuWillOpenNotification =
@"MenuControllerMenuWillOpen";
@@ -144,13 +171,16 @@ NSString* const kMenuControllerMenuDidCloseNotification =
[item setImage:icon.ToNSImage()];
ui::MenuModel::ItemType type = model->GetTypeAt(index);
- if (type == ui::MenuModel::TYPE_SUBMENU) {
- // Recursively build a submenu from the sub-model at this index.
+ if (type == ui::MenuModel::TYPE_SUBMENU && model->IsVisibleAt(index)) {
+ ui::MenuModel* submenuModel = model->GetSubmenuModelAt(index);
+
+ // If there are visible items, recursively build the submenu.
+ NSMenu* submenu = MenuHasVisibleItems(submenuModel)
+ ? [self menuFromModel:submenuModel]
+ : MakeEmptySubmenu();
+
[item setTarget:nil];
[item setAction:nil];
- ui::MenuModel* submenuModel = model->GetSubmenuModelAt(index);
- NSMenu* submenu =
- [self menuFromModel:(ui::SimpleMenuModel*)submenuModel];
[item setSubmenu:submenu];
} else {
// The MenuModel works on indexes so we can't just set the command id as the
diff --git a/chromium/ui/base/cocoa/menu_controller_unittest.mm b/chromium/ui/base/cocoa/menu_controller_unittest.mm
index 9dffd0fce4b..f282e24b068 100644
--- a/chromium/ui/base/cocoa/menu_controller_unittest.mm
+++ b/chromium/ui/base/cocoa/menu_controller_unittest.mm
@@ -9,8 +9,10 @@
#include "base/run_loop.h"
#include "base/strings/sys_string_conversions.h"
#include "base/strings/utf_string_conversions.h"
+#import "testing/gtest_mac.h"
#include "third_party/skia/include/core/SkBitmap.h"
#import "ui/base/cocoa/menu_controller.h"
+#include "ui/base/l10n/l10n_util_mac.h"
#include "ui/base/models/simple_menu_model.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/events/test/cocoa_test_event_utils.h"
@@ -74,6 +76,50 @@ const int kTestLabelResourceId = IDS_APP_SCROLLBAR_CXMENU_SCROLLHERE;
class MenuControllerTest : public CocoaTest {
};
+class TestSimpleMenuModelVisibility : public SimpleMenuModel {
+ public:
+ explicit TestSimpleMenuModelVisibility(SimpleMenuModel::Delegate* delegate)
+ : SimpleMenuModel(delegate) {}
+
+ // SimpleMenuModel:
+ bool IsVisibleAt(int index) const override {
+ return items_[ValidateItemIndex(index)].visible;
+ }
+
+ void SetVisibility(int command_id, bool visible) {
+ int index = SimpleMenuModel::GetIndexOfCommandId(command_id);
+ items_[ValidateItemIndex(index)].visible = visible;
+ }
+
+ void AddItem(int command_id, const base::string16& label) {
+ SimpleMenuModel::AddItem(command_id, label);
+ items_.push_back({true, command_id});
+ }
+
+ void AddSubMenuWithStringId(int command_id, int string_id, MenuModel* model) {
+ SimpleMenuModel::AddSubMenuWithStringId(command_id, string_id, model);
+ items_.push_back({true, command_id});
+ }
+
+ private:
+ struct Item {
+ bool visible;
+ int command_id;
+ };
+
+ typedef std::vector<Item> ItemVector;
+
+ int ValidateItemIndex(int index) const {
+ CHECK_GE(index, 0);
+ CHECK_LT(static_cast<size_t>(index), items_.size());
+ return index;
+ }
+
+ ItemVector items_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestSimpleMenuModelVisibility);
+};
+
// A menu delegate that counts the number of times certain things are called
// to make sure things are hooked up properly.
class Delegate : public SimpleMenuModel::Delegate {
@@ -214,7 +260,7 @@ TEST_F(MenuControllerTest, EmptyMenu) {
SimpleMenuModel model(&delegate);
base::scoped_nsobject<MenuController> menu(
[[MenuController alloc] initWithModel:&model useWithPopUpButtonCell:NO]);
- EXPECT_EQ([[menu menu] numberOfItems], 0);
+ EXPECT_EQ(0, [[menu menu] numberOfItems]);
}
TEST_F(MenuControllerTest, BasicCreation) {
@@ -229,14 +275,14 @@ TEST_F(MenuControllerTest, BasicCreation) {
base::scoped_nsobject<MenuController> menu(
[[MenuController alloc] initWithModel:&model useWithPopUpButtonCell:NO]);
- EXPECT_EQ([[menu menu] numberOfItems], 6);
+ EXPECT_EQ(6, [[menu menu] numberOfItems]);
// Check the title, tag, and represented object are correct for a random
// element.
NSMenuItem* itemTwo = [[menu menu] itemAtIndex:2];
NSString* title = [itemTwo title];
EXPECT_EQ(ASCIIToUTF16("three"), base::SysNSStringToUTF16(title));
- EXPECT_EQ([itemTwo tag], 2);
+ EXPECT_EQ(2, [itemTwo tag]);
EXPECT_EQ([[itemTwo representedObject] pointerValue], &model);
EXPECT_TRUE([[[menu menu] itemAtIndex:3] isSeparatorItem]);
@@ -255,19 +301,19 @@ TEST_F(MenuControllerTest, Submenus) {
base::scoped_nsobject<MenuController> menu(
[[MenuController alloc] initWithModel:&model useWithPopUpButtonCell:NO]);
- EXPECT_EQ([[menu menu] numberOfItems], 3);
+ EXPECT_EQ(3, [[menu menu] numberOfItems]);
// Inspect the submenu to ensure it has correct properties.
NSMenu* submenu = [[[menu menu] itemAtIndex:1] submenu];
EXPECT_TRUE(submenu);
- EXPECT_EQ([submenu numberOfItems], 3);
+ EXPECT_EQ(3, [submenu numberOfItems]);
// Inspect one of the items to make sure it has the correct model as its
// represented object and the proper tag.
NSMenuItem* submenuItem = [submenu itemAtIndex:1];
NSString* title = [submenuItem title];
EXPECT_EQ(ASCIIToUTF16("sub-two"), base::SysNSStringToUTF16(title));
- EXPECT_EQ([submenuItem tag], 1);
+ EXPECT_EQ(1, [submenuItem tag]);
EXPECT_EQ([[submenuItem representedObject] pointerValue], &submodel);
// Make sure the item after the submenu is correct and its represented
@@ -275,7 +321,7 @@ TEST_F(MenuControllerTest, Submenus) {
NSMenuItem* item = [[menu menu] itemAtIndex:2];
title = [item title];
EXPECT_EQ(ASCIIToUTF16("three"), base::SysNSStringToUTF16(title));
- EXPECT_EQ([item tag], 2);
+ EXPECT_EQ(2, [item tag]);
EXPECT_EQ([[item representedObject] pointerValue], &model);
}
@@ -288,7 +334,88 @@ TEST_F(MenuControllerTest, EmptySubmenu) {
base::scoped_nsobject<MenuController> menu(
[[MenuController alloc] initWithModel:&model useWithPopUpButtonCell:NO]);
- EXPECT_EQ([[menu menu] numberOfItems], 2);
+ EXPECT_EQ(2, [[menu menu] numberOfItems]);
+
+ // Inspect the submenu to ensure it has one item labeled "(empty)".
+ NSMenu* submenu = [[[menu menu] itemAtIndex:1] submenu];
+ EXPECT_TRUE(submenu);
+ EXPECT_EQ(1, [submenu numberOfItems]);
+
+ EXPECT_NSEQ(@"(empty)", [[submenu itemAtIndex:0] title]);
+}
+
+// Tests that an empty menu item, "(empty)", is added to a submenu that contains
+// hidden child items.
+TEST_F(MenuControllerTest, EmptySubmenuWhenAllChildItemsAreHidden) {
+ Delegate delegate;
+ TestSimpleMenuModelVisibility model(&delegate);
+ model.AddItem(1, ASCIIToUTF16("one"));
+ TestSimpleMenuModelVisibility submodel(&delegate);
+ // Hide the two child menu items.
+ submodel.AddItem(2, ASCIIToUTF16("sub-one"));
+ submodel.SetVisibility(2, false);
+ submodel.AddItem(3, ASCIIToUTF16("sub-two"));
+ submodel.SetVisibility(3, false);
+ model.AddSubMenuWithStringId(4, kTestLabelResourceId, &submodel);
+
+ base::scoped_nsobject<MenuController> menu(
+ [[MenuController alloc] initWithModel:&model useWithPopUpButtonCell:NO]);
+ EXPECT_EQ(2, [[menu menu] numberOfItems]);
+
+ // Inspect the submenu to ensure it has one item labeled "(empty)".
+ NSMenu* submenu = [[[menu menu] itemAtIndex:1] submenu];
+ EXPECT_TRUE(submenu);
+ EXPECT_EQ(1, [submenu numberOfItems]);
+
+ EXPECT_NSEQ(@"(empty)", [[submenu itemAtIndex:0] title]);
+}
+
+// Tests hiding a submenu item. If a submenu item with children is set to
+// hidden, then the submenu should hide.
+TEST_F(MenuControllerTest, HiddenSubmenu) {
+ // SimpleMenuModel posts a task that calls Delegate::MenuClosed. Create
+ // a MessageLoop for that purpose.
+ base::MessageLoopForUI message_loop;
+
+ // Create the model.
+ Delegate delegate;
+ TestSimpleMenuModelVisibility model(&delegate);
+ model.AddItem(1, ASCIIToUTF16("one"));
+ TestSimpleMenuModelVisibility submodel(&delegate);
+ submodel.AddItem(2, ASCIIToUTF16("sub-one"));
+ submodel.AddItem(3, ASCIIToUTF16("sub-two"));
+ // Set the submenu to be hidden.
+ model.AddSubMenuWithStringId(4, kTestLabelResourceId, &submodel);
+
+ model.SetVisibility(4, false);
+
+ // Create the controller.
+ base::scoped_nsobject<MenuController> menu_controller(
+ [[MenuController alloc] initWithModel:&model useWithPopUpButtonCell:NO]);
+ EXPECT_EQ(2, [[menu_controller menu] numberOfItems]);
+ delegate.menu_to_close_ = [menu_controller menu];
+
+ // Show the menu.
+ CFRunLoopPerformBlock(CFRunLoopGetCurrent(), NSEventTrackingRunLoopMode, ^{
+ EXPECT_TRUE([menu_controller isMenuOpen]);
+ // Ensure that the submenu is hidden.
+ NSMenuItem* item = [[menu_controller menu] itemAtIndex:1];
+ EXPECT_TRUE([item isHidden]);
+ });
+
+ // Pop open the menu, which will spin an event-tracking run loop.
+ [NSMenu popUpContextMenu:[menu_controller menu]
+ withEvent:cocoa_test_event_utils::RightMouseDownAtPoint(
+ NSZeroPoint)
+ forView:[test_window() contentView]];
+
+ EXPECT_FALSE([menu_controller isMenuOpen]);
+
+ // Pump the task that notifies the delegate.
+ base::RunLoop().RunUntilIdle();
+
+ // Expect that the delegate got notified properly.
+ EXPECT_TRUE(delegate.did_close_);
}
TEST_F(MenuControllerTest, PopUpButton) {
@@ -302,13 +429,13 @@ TEST_F(MenuControllerTest, PopUpButton) {
// title.
base::scoped_nsobject<MenuController> menu(
[[MenuController alloc] initWithModel:&model useWithPopUpButtonCell:YES]);
- EXPECT_EQ([[menu menu] numberOfItems], 4);
- EXPECT_EQ(base::SysNSStringToUTF16([[[menu menu] itemAtIndex:0] title]),
- base::string16());
+ EXPECT_EQ(4, [[menu menu] numberOfItems]);
+ EXPECT_EQ(base::string16(),
+ base::SysNSStringToUTF16([[[menu menu] itemAtIndex:0] title]));
// Make sure the tags are still correct (the index no longer matches the tag).
NSMenuItem* itemTwo = [[menu menu] itemAtIndex:2];
- EXPECT_EQ([itemTwo tag], 1);
+ EXPECT_EQ(1, [itemTwo tag]);
}
TEST_F(MenuControllerTest, Execute) {
@@ -317,13 +444,13 @@ TEST_F(MenuControllerTest, Execute) {
model.AddItem(1, ASCIIToUTF16("one"));
base::scoped_nsobject<MenuController> menu(
[[MenuController alloc] initWithModel:&model useWithPopUpButtonCell:NO]);
- EXPECT_EQ([[menu menu] numberOfItems], 1);
+ EXPECT_EQ(1, [[menu menu] numberOfItems]);
// Fake selecting the menu item, we expect the delegate to be told to execute
// a command.
NSMenuItem* item = [[menu menu] itemAtIndex:0];
[[item target] performSelector:[item action] withObject:item];
- EXPECT_EQ(delegate.execute_count_, 1);
+ EXPECT_EQ(1, delegate.execute_count_);
}
void Validate(MenuController* controller, NSMenu* menu) {
@@ -346,7 +473,7 @@ TEST_F(MenuControllerTest, Validate) {
base::scoped_nsobject<MenuController> menu(
[[MenuController alloc] initWithModel:&model useWithPopUpButtonCell:NO]);
- EXPECT_EQ([[menu menu] numberOfItems], 3);
+ EXPECT_EQ(3, [[menu menu] numberOfItems]);
Validate(menu.get(), [menu menu]);
}
@@ -363,7 +490,7 @@ TEST_F(MenuControllerTest, LabelFontList) {
base::scoped_nsobject<MenuController> menu(
[[MenuController alloc] initWithModel:&model useWithPopUpButtonCell:NO]);
- EXPECT_EQ([[menu menu] numberOfItems], 2);
+ EXPECT_EQ(2, [[menu menu] numberOfItems]);
Validate(menu.get(), [menu menu]);
@@ -403,7 +530,7 @@ TEST_F(MenuControllerTest, Dynamic) {
model.AddItem(1, ASCIIToUTF16("foo"));
base::scoped_nsobject<MenuController> menu(
[[MenuController alloc] initWithModel:&model useWithPopUpButtonCell:NO]);
- EXPECT_EQ([[menu menu] numberOfItems], 1);
+ EXPECT_EQ(1, [[menu menu] numberOfItems]);
// Validate() simulates opening the menu - the item label/icon should be
// initialized after this so we can validate the menu contents.
Validate(menu.get(), [menu menu]);
diff --git a/chromium/ui/base/cocoa/touch_bar_util.h b/chromium/ui/base/cocoa/touch_bar_util.h
index 5d6d7f7705d..c97f726a2d9 100644
--- a/chromium/ui/base/cocoa/touch_bar_util.h
+++ b/chromium/ui/base/cocoa/touch_bar_util.h
@@ -41,15 +41,7 @@ UI_BASE_EXPORT Class NSGroupTouchBarItem();
// Returns a stylized blue button for the touch bar. The button performs
// |action| from the |target|.
-// The __attribute__ visibility annotation is necessary to work around a clang
-// bug: https://bugs.llvm.org/show_bug.cgi?id=33796.
-#if defined(UI_BASE_IMPLEMENTATION) && defined(COMPONENT_BUILD)
-// UI_BASE_EXPORT specifies "default" visibility.
API_AVAILABLE(macosx(10.12.2))
-#else
-API_AVAILABLE(macosx(10.12.2))
-__attribute__((visibility("hidden")))
-#endif
UI_BASE_EXPORT NSButton* GetBlueTouchBarButton(NSString* title,
id target,
SEL action);
diff --git a/chromium/ui/base/cursor/cursor_loader.h b/chromium/ui/base/cursor/cursor_loader.h
index fca5e7dce44..527b1472018 100644
--- a/chromium/ui/base/cursor/cursor_loader.h
+++ b/chromium/ui/base/cursor/cursor_loader.h
@@ -8,6 +8,7 @@
#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/string16.h"
+#include "ui/base/cursor/cursor_type.h"
#include "ui/base/ui_base_export.h"
#include "ui/display/display.h"
#include "ui/gfx/geometry/point.h"
diff --git a/chromium/ui/base/cursor/cursor_loader_ozone.cc b/chromium/ui/base/cursor/cursor_loader_ozone.cc
index b8498ef9b66..ef23518d1e4 100644
--- a/chromium/ui/base/cursor/cursor_loader_ozone.cc
+++ b/chromium/ui/base/cursor/cursor_loader_ozone.cc
@@ -16,7 +16,9 @@ CursorLoaderOzone::CursorLoaderOzone() {
factory_ = CursorFactoryOzone::GetInstance();
}
-CursorLoaderOzone::~CursorLoaderOzone() {}
+CursorLoaderOzone::~CursorLoaderOzone() {
+ UnloadAll();
+}
void CursorLoaderOzone::LoadImageCursor(CursorType id,
int resource_id,
diff --git a/chromium/ui/base/cursor/ozone/cursor_data_factory_ozone.cc b/chromium/ui/base/cursor/ozone/cursor_data_factory_ozone.cc
index e0a68d956ad..3bcaf00b7b6 100644
--- a/chromium/ui/base/cursor/ozone/cursor_data_factory_ozone.cc
+++ b/chromium/ui/base/cursor/ozone/cursor_data_factory_ozone.cc
@@ -18,7 +18,7 @@ const uint32_t kBadCookie = 0xBADBADCC;
CursorDataOzone* ToCursorDataOzone(PlatformCursor cursor) {
CursorDataOzone* ozone = static_cast<CursorDataOzone*>(cursor);
#if DCHECK_IS_ON()
- ozone->AssertIsACusrorDataOzone();
+ ozone->AssertIsACursorDataOzone();
#endif
return ozone;
}
@@ -32,7 +32,7 @@ PlatformCursor ToPlatformCursor(CursorDataOzone* cursor) {
CursorDataOzone::CursorDataOzone(const ui::CursorData& data)
: magic_cookie_(kCookie), data_(data) {}
-void CursorDataOzone::AssertIsACusrorDataOzone() {
+void CursorDataOzone::AssertIsACursorDataOzone() {
CHECK_EQ(magic_cookie_, kCookie);
}
diff --git a/chromium/ui/base/cursor/ozone/cursor_data_factory_ozone.h b/chromium/ui/base/cursor/ozone/cursor_data_factory_ozone.h
index d3ef8a137e4..c9859f23306 100644
--- a/chromium/ui/base/cursor/ozone/cursor_data_factory_ozone.h
+++ b/chromium/ui/base/cursor/ozone/cursor_data_factory_ozone.h
@@ -35,7 +35,7 @@ class UI_BASE_EXPORT CursorDataOzone
// level CursorFactoryOzone interface. Even worse, there can be multiple
// subclasses that map to this void* type. This asserts that a magic cookie
// that we put at the start of valid CursorDataOzone objects is correct.
- void AssertIsACusrorDataOzone();
+ void AssertIsACursorDataOzone();
private:
friend class base::RefCounted<CursorDataOzone>;
diff --git a/chromium/ui/base/dragdrop/os_exchange_data.h b/chromium/ui/base/dragdrop/os_exchange_data.h
index 282587d23df..3bb6feffc1b 100644
--- a/chromium/ui/base/dragdrop/os_exchange_data.h
+++ b/chromium/ui/base/dragdrop/os_exchange_data.h
@@ -113,7 +113,7 @@ class UI_BASE_EXPORT OSExchangeData {
virtual bool HasFile() const = 0;
virtual bool HasCustomFormat(const Clipboard::FormatType& format) const = 0;
-#if (!defined(OS_CHROMEOS) && defined(USE_X11)) || defined(OS_WIN)
+#if defined(USE_X11) || defined(OS_WIN)
virtual void SetFileContents(const base::FilePath& filename,
const std::string& file_contents) = 0;
#endif
diff --git a/chromium/ui/base/dragdrop/os_exchange_data_provider_factory.cc b/chromium/ui/base/dragdrop/os_exchange_data_provider_factory.cc
index 962fd2c5748..bc3ecda3a1a 100644
--- a/chromium/ui/base/dragdrop/os_exchange_data_provider_factory.cc
+++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_factory.cc
@@ -5,8 +5,9 @@
#include "ui/base/dragdrop/os_exchange_data_provider_factory.h"
#include "base/memory/ptr_util.h"
+#include "build/build_config.h"
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#if defined(USE_X11)
#include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h"
#elif defined(OS_LINUX)
#include "ui/base/dragdrop/os_exchange_data_provider_aura.h"
@@ -40,7 +41,7 @@ OSExchangeDataProviderFactory::CreateProvider() {
if (factory_)
return factory_->BuildProvider();
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#if defined(USE_X11)
return base::MakeUnique<OSExchangeDataProviderAuraX11>();
#elif defined(OS_LINUX)
return base::MakeUnique<OSExchangeDataProviderAura>();
@@ -48,6 +49,10 @@ OSExchangeDataProviderFactory::CreateProvider() {
return ui::BuildOSExchangeDataProviderMac();
#elif defined(OS_WIN)
return base::MakeUnique<OSExchangeDataProviderWin>();
+#elif defined(OS_FUCHSIA)
+ // TODO(fuchsia): Implement this when UI support is added. (crbug.com/750934)
+ NOTIMPLEMENTED();
+ return nullptr;
#else
#error "Unknown operating system"
#endif
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 9d0338b03c5..5741375f506 100644
--- a/chromium/ui/base/dragdrop/os_exchange_data_provider_win.cc
+++ b/chromium/ui/base/dragdrop/os_exchange_data_provider_win.cc
@@ -108,9 +108,9 @@ class FormatEtcEnumerator final : public IEnumFORMATETC {
private:
// We are _forced_ to use a vector as our internal data model as Windows'
- // retarded IEnumFORMATETC API assumes a deterministic ordering of elements
- // through methods like Next and Skip. This exposes the underlying data
- // structure to the user. Bah.
+ // IEnumFORMATETC API assumes a deterministic ordering of elements through
+ // methods like Next and Skip. This exposes the underlying data structure to
+ // the user. Bah.
std::vector<std::unique_ptr<FORMATETC>> contents_;
// The cursor of the active enumeration - an index into |contents_|.
diff --git a/chromium/ui/base/idle/idle_fuchsia.cc b/chromium/ui/base/idle/idle_fuchsia.cc
new file mode 100644
index 00000000000..ed21be8b78a
--- /dev/null
+++ b/chromium/ui/base/idle/idle_fuchsia.cc
@@ -0,0 +1,23 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/idle/idle.h"
+
+#include "base/logging.h"
+
+namespace ui {
+
+void CalculateIdleTime(IdleTimeCallback notify) {
+ // TODO(fuchsia): https://crbug.com/743296.
+ NOTIMPLEMENTED();
+ notify.Run(0);
+}
+
+bool CheckIdleStateIsLocked() {
+ // TODO(fuchsia): https://crbug.com/743296.
+ NOTIMPLEMENTED();
+ return false;
+}
+
+} // namespace ui
diff --git a/chromium/ui/base/ime/BUILD.gn b/chromium/ui/base/ime/BUILD.gn
index 2940cb9b6eb..f53139c8da0 100644
--- a/chromium/ui/base/ime/BUILD.gn
+++ b/chromium/ui/base/ime/BUILD.gn
@@ -31,8 +31,6 @@ component("ime") {
"chromeos/ime_candidate_window_handler_interface.h",
"chromeos/ime_keyboard.cc",
"chromeos/ime_keyboard.h",
- "chromeos/ime_keyboard_x11.cc",
- "chromeos/ime_keyboard_x11.h",
"chromeos/ime_keymap.cc",
"chromeos/ime_keymap.h",
"chromeos/input_method_delegate.h",
@@ -54,11 +52,12 @@ component("ime") {
"composition_text.h",
"composition_text_util_pango.cc",
"composition_text_util_pango.h",
- "composition_underline.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",
"input_method.h",
@@ -161,22 +160,14 @@ component("ime") {
if (is_chromeos) {
deps += [
"//chromeos",
+ "//services/ui/public/cpp/input_devices",
"//ui/chromeos/strings",
"//ui/events:dom_keycode_converter",
]
- if (use_ozone) {
- deps += [ "//services/ui/public/cpp/input_devices" ]
- sources += [
- "chromeos/ime_keyboard_mus.cc",
- "chromeos/ime_keyboard_mus.h",
- ]
- }
- if (!use_x11) {
- sources -= [
- "chromeos/ime_keyboard_x11.cc",
- "chromeos/ime_keyboard_x11.h",
- ]
- }
+ sources += [
+ "chromeos/ime_keyboard_mus.cc",
+ "chromeos/ime_keyboard_mus.h",
+ ]
}
if (use_pango) {
@@ -209,4 +200,11 @@ component("ime") {
"//ui/ozone",
]
}
+
+ if (is_fuchsia) {
+ sources -= [
+ "input_method_auralinux.cc",
+ "input_method_auralinux.h",
+ ]
+ }
}
diff --git a/chromium/ui/base/ime/composition_text.cc b/chromium/ui/base/ime/composition_text.cc
index a2e583f6221..ab2136e9d1e 100644
--- a/chromium/ui/base/ime/composition_text.cc
+++ b/chromium/ui/base/ime/composition_text.cc
@@ -14,19 +14,4 @@ CompositionText::CompositionText(const CompositionText& other) = default;
CompositionText::~CompositionText() {
}
-void CompositionText::Clear() {
- text.clear();
- underlines.clear();
- selection = gfx::Range();
-}
-
-void CompositionText::CopyFrom(const CompositionText& obj) {
- Clear();
- text = obj.text;
- for (size_t i = 0; i < obj.underlines.size(); i++) {
- underlines.push_back(obj.underlines[i]);
- }
- selection = obj.selection;
-}
-
} // namespace ui
diff --git a/chromium/ui/base/ime/composition_text.h b/chromium/ui/base/ime/composition_text.h
index ba56c627106..272535ba3e6 100644
--- a/chromium/ui/base/ime/composition_text.h
+++ b/chromium/ui/base/ime/composition_text.h
@@ -8,7 +8,7 @@
#include <stddef.h>
#include "base/strings/string16.h"
-#include "ui/base/ime/composition_underline.h"
+#include "ui/base/ime/ime_text_span.h"
#include "ui/base/ime/ui_base_ime_export.h"
#include "ui/gfx/range/range.h"
@@ -21,12 +21,11 @@ struct UI_BASE_IME_EXPORT CompositionText {
~CompositionText();
bool operator==(const CompositionText& rhs) const {
- if ((this->text != rhs.text) ||
- (this->selection != rhs.selection) ||
- (this->underlines.size() != rhs.underlines.size()))
+ if ((this->text != rhs.text) || (this->selection != rhs.selection) ||
+ (this->ime_text_spans.size() != rhs.ime_text_spans.size()))
return false;
- for (size_t i = 0; i < this->underlines.size(); ++i) {
- if (this->underlines[i] != rhs.underlines[i])
+ for (size_t i = 0; i < this->ime_text_spans.size(); ++i) {
+ if (this->ime_text_spans[i] != rhs.ime_text_spans[i])
return false;
}
return true;
@@ -36,17 +35,11 @@ struct UI_BASE_IME_EXPORT CompositionText {
return !(*this == rhs);
}
- void Clear();
-
- void CopyFrom(const CompositionText& obj);
-
// Content of the composition text.
base::string16 text;
- // Underline information of the composition text.
- // They must be sorted in ascending order by their start_offset and cannot be
- // overlapped with each other.
- CompositionUnderlines underlines;
+ // ImeTextSpan information for the composition text.
+ ImeTextSpans ime_text_spans;
// Selection range in the composition text. It represents the caret position
// if the range length is zero. Usually it's used for representing the target
diff --git a/chromium/ui/base/ime/composition_text_unittest.cc b/chromium/ui/base/ime/composition_text_unittest.cc
index c03090a5623..8431e2eb6d5 100644
--- a/chromium/ui/base/ime/composition_text_unittest.cc
+++ b/chromium/ui/base/ime/composition_text_unittest.cc
@@ -13,37 +13,39 @@ namespace ui {
TEST(CompositionTextTest, CopyTest) {
const base::string16 kSampleText = base::UTF8ToUTF16("Sample Text");
- const CompositionUnderline kSampleUnderline1(10, 20, SK_ColorBLACK, false,
- SK_ColorTRANSPARENT);
+ const ImeTextSpan kSampleUnderline1(ImeTextSpan::Type::kComposition, 10, 20,
+ SK_ColorBLACK, false,
+ SK_ColorTRANSPARENT);
- const CompositionUnderline kSampleUnderline2(11, 21, SK_ColorBLACK, true,
- SK_ColorTRANSPARENT);
+ const ImeTextSpan kSampleUnderline2(ImeTextSpan::Type::kComposition, 11, 21,
+ SK_ColorBLACK, true, SK_ColorTRANSPARENT);
- const CompositionUnderline kSampleUnderline3(12, 22, SK_ColorRED, false,
- SK_ColorTRANSPARENT);
+ const ImeTextSpan kSampleUnderline3(ImeTextSpan::Type::kComposition, 12, 22,
+ SK_ColorRED, false, SK_ColorTRANSPARENT);
// Make CompositionText
CompositionText text;
text.text = kSampleText;
- text.underlines.push_back(kSampleUnderline1);
- text.underlines.push_back(kSampleUnderline2);
- text.underlines.push_back(kSampleUnderline3);
+ text.ime_text_spans.push_back(kSampleUnderline1);
+ text.ime_text_spans.push_back(kSampleUnderline2);
+ text.ime_text_spans.push_back(kSampleUnderline3);
text.selection.set_start(30);
text.selection.set_end(40);
- CompositionText text2;
- text2.CopyFrom(text);
+ CompositionText text2 = text;
EXPECT_EQ(text.text, text2.text);
- EXPECT_EQ(text.underlines.size(), text2.underlines.size());
- for (size_t i = 0; i < text.underlines.size(); ++i) {
- EXPECT_EQ(text.underlines[i].start_offset,
- text2.underlines[i].start_offset);
- EXPECT_EQ(text.underlines[i].end_offset, text2.underlines[i].end_offset);
- EXPECT_EQ(text.underlines[i].color, text2.underlines[i].color);
- EXPECT_EQ(text.underlines[i].thick, text2.underlines[i].thick);
- EXPECT_EQ(text.underlines[i].background_color,
- text2.underlines[i].background_color);
+ EXPECT_EQ(text.ime_text_spans.size(), text2.ime_text_spans.size());
+ for (size_t i = 0; i < text.ime_text_spans.size(); ++i) {
+ EXPECT_EQ(text.ime_text_spans[i].start_offset,
+ text2.ime_text_spans[i].start_offset);
+ EXPECT_EQ(text.ime_text_spans[i].end_offset,
+ text2.ime_text_spans[i].end_offset);
+ EXPECT_EQ(text.ime_text_spans[i].underline_color,
+ text2.ime_text_spans[i].underline_color);
+ EXPECT_EQ(text.ime_text_spans[i].thick, text2.ime_text_spans[i].thick);
+ EXPECT_EQ(text.ime_text_spans[i].background_color,
+ text2.ime_text_spans[i].background_color);
}
EXPECT_EQ(text.selection.start(), text2.selection.start());
diff --git a/chromium/ui/base/ime/composition_text_util_pango.cc b/chromium/ui/base/ime/composition_text_util_pango.cc
index b8a92973992..9ef58037f7b 100644
--- a/chromium/ui/base/ime/composition_text_util_pango.cc
+++ b/chromium/ui/base/ime/composition_text_util_pango.cc
@@ -18,7 +18,7 @@ void ExtractCompositionTextFromGtkPreedit(const gchar* utf8_text,
PangoAttrList* attrs,
int cursor_position,
CompositionText* composition) {
- composition->Clear();
+ *composition = CompositionText();
composition->text = base::UTF8ToUTF16(utf8_text);
if (composition->text.empty())
@@ -75,44 +75,43 @@ void ExtractCompositionTextFromGtkPreedit(const gchar* utf8_text,
if (background_attr || underline_attr) {
// Use a black thin underline by default.
- CompositionUnderline underline(char16_offsets[start],
- char16_offsets[end],
- SK_ColorBLACK,
- false,
- SK_ColorTRANSPARENT);
+ ImeTextSpan ime_text_span(ImeTextSpan::Type::kComposition,
+ char16_offsets[start], char16_offsets[end],
+ SK_ColorBLACK, false, SK_ColorTRANSPARENT);
// Always use thick underline for a range with background color, which
// is usually the selection range.
if (background_attr) {
- underline.thick = true;
+ ime_text_span.thick = true;
// If the cursor is at start or end of this underline, then we treat
// it as the selection range as well, but make sure to set the cursor
// position to the selection end.
- if (underline.start_offset == cursor_offset) {
- composition->selection.set_start(underline.end_offset);
+ if (ime_text_span.start_offset == cursor_offset) {
+ composition->selection.set_start(ime_text_span.end_offset);
composition->selection.set_end(cursor_offset);
- } else if (underline.end_offset == cursor_offset) {
- composition->selection.set_start(underline.start_offset);
+ } else if (ime_text_span.end_offset == cursor_offset) {
+ composition->selection.set_start(ime_text_span.start_offset);
composition->selection.set_end(cursor_offset);
}
}
if (underline_attr) {
int type = reinterpret_cast<PangoAttrInt*>(underline_attr)->value;
if (type == PANGO_UNDERLINE_DOUBLE)
- underline.thick = true;
+ ime_text_span.thick = true;
else if (type == PANGO_UNDERLINE_ERROR)
- underline.color = SK_ColorRED;
+ ime_text_span.underline_color = SK_ColorRED;
}
- composition->underlines.push_back(underline);
+ composition->ime_text_spans.push_back(ime_text_span);
}
} while (pango_attr_iterator_next(iter));
pango_attr_iterator_destroy(iter);
}
// Use a black thin underline by default.
- if (composition->underlines.empty()) {
- composition->underlines.push_back(CompositionUnderline(
- 0, length, SK_ColorBLACK, false, SK_ColorTRANSPARENT));
+ if (composition->ime_text_spans.empty()) {
+ composition->ime_text_spans.push_back(
+ ImeTextSpan(ImeTextSpan::Type::kComposition, 0, length, SK_ColorBLACK,
+ false, SK_ColorTRANSPARENT));
}
}
diff --git a/chromium/ui/base/ime/composition_text_util_pango_unittest.cc b/chromium/ui/base/ime/composition_text_util_pango_unittest.cc
index c645e300da8..be674433b65 100644
--- a/chromium/ui/base/ime/composition_text_util_pango_unittest.cc
+++ b/chromium/ui/base/ime/composition_text_util_pango_unittest.cc
@@ -25,10 +25,10 @@ struct AttributeInfo {
int end_offset;
};
-struct Underline {
+struct ImeTextSpan {
unsigned start_offset;
unsigned end_offset;
- uint32_t color;
+ uint32_t underline_color;
bool thick;
uint32_t background_color;
};
@@ -36,7 +36,7 @@ struct Underline {
struct TestData {
const char* text;
const AttributeInfo attrs[10];
- const Underline underlines[10];
+ const ImeTextSpan ime_text_spans[10];
};
const TestData kTestData[] = {
@@ -95,11 +95,10 @@ const TestData kTestData[] = {
{0, 0, 0, false, SK_ColorTRANSPARENT}}},
};
-void CompareUnderline(const Underline& a,
- const ui::CompositionUnderline& b) {
+void CompareImeTextSpan(const ImeTextSpan& a, const ui::ImeTextSpan& b) {
EXPECT_EQ(a.start_offset, b.start_offset);
EXPECT_EQ(a.end_offset, b.end_offset);
- EXPECT_EQ(a.color, b.color);
+ EXPECT_EQ(a.underline_color, b.underline_color);
EXPECT_EQ(a.thick, b.thick);
EXPECT_EQ(a.background_color, b.background_color);
}
@@ -135,11 +134,12 @@ TEST(CompositionTextUtilPangoTest, ExtractCompositionText) {
ui::CompositionText result;
ui::ExtractCompositionTextFromGtkPreedit(text, pango_attrs, 0, &result);
- const Underline* underlines = kTestData[i].underlines;
- for (size_t u = 0; underlines[u].color &&
- u < result.underlines.size(); ++u) {
- SCOPED_TRACE(testing::Message() << "Underline:" << u);
- CompareUnderline(underlines[u], result.underlines[u]);
+ const ImeTextSpan* ime_text_spans = kTestData[i].ime_text_spans;
+ for (size_t u = 0;
+ ime_text_spans[u].underline_color && u < result.ime_text_spans.size();
+ ++u) {
+ SCOPED_TRACE(testing::Message() << "ImeTextSpan:" << u);
+ CompareImeTextSpan(ime_text_spans[u], result.ime_text_spans[u]);
}
pango_attr_list_unref(pango_attrs);
diff --git a/chromium/ui/base/ime/composition_underline.h b/chromium/ui/base/ime/composition_underline.h
deleted file mode 100644
index 9eb7763aa80..00000000000
--- a/chromium/ui/base/ime/composition_underline.h
+++ /dev/null
@@ -1,68 +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_BASE_IME_COMPOSITION_UNDERLINE_H_
-#define UI_BASE_IME_COMPOSITION_UNDERLINE_H_
-
-#include <stdint.h>
-
-#include <vector>
-
-#include "third_party/skia/include/core/SkColor.h"
-
-namespace ui {
-
-// Intentionally keep sync with blink::WebCompositionUnderline defined in:
-// third_party/WebKit/public/web/WebCompositionUnderline.h
-struct CompositionUnderline {
- CompositionUnderline()
- : start_offset(0),
- end_offset(0),
- color(SK_ColorTRANSPARENT),
- thick(false),
- background_color(SK_ColorTRANSPARENT) {}
-
- // TODO(huangs): remove this constructor.
- CompositionUnderline(uint32_t s, uint32_t e, SkColor c, bool t)
- : start_offset(s),
- end_offset(e),
- color(c),
- thick(t),
- background_color(SK_ColorTRANSPARENT) {}
-
- CompositionUnderline(uint32_t s, uint32_t e, SkColor c, bool t, SkColor bc)
- : start_offset(s),
- end_offset(e),
- color(c),
- thick(t),
- background_color(bc) {}
-
- bool operator<(const CompositionUnderline& rhs) const {
- return std::tie(start_offset, end_offset) <
- std::tie(rhs.start_offset, rhs.end_offset);
- }
-
- bool operator==(const CompositionUnderline& rhs) const {
- return (this->start_offset == rhs.start_offset) &&
- (this->end_offset == rhs.end_offset) && (this->color == rhs.color) &&
- (this->thick == rhs.thick) &&
- (this->background_color == rhs.background_color);
- }
-
- bool operator!=(const CompositionUnderline& rhs) const {
- return !(*this == rhs);
- }
-
- uint32_t start_offset;
- uint32_t end_offset;
- SkColor color;
- bool thick;
- SkColor background_color;
-};
-
-typedef std::vector<CompositionUnderline> CompositionUnderlines;
-
-} // namespace ui
-
-#endif // UI_BASE_IME_COMPOSITION_UNDERLINE_H_
diff --git a/chromium/ui/base/ime/ime_text_span.cc b/chromium/ui/base/ime/ime_text_span.cc
new file mode 100644
index 00000000000..1ee2876be35
--- /dev/null
+++ b/chromium/ui/base/ime/ime_text_span.cc
@@ -0,0 +1,46 @@
+// Copyright 2017 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/base/ime/ime_text_span.h"
+
+#include <string>
+#include <vector>
+
+namespace ui {
+
+ImeTextSpan::ImeTextSpan() : ImeTextSpan(0, 0, SK_ColorTRANSPARENT, false) {}
+
+ImeTextSpan::ImeTextSpan(uint32_t start_offset,
+ uint32_t end_offset,
+ SkColor underline_color,
+ bool thick)
+ : ImeTextSpan(Type::kComposition,
+ start_offset,
+ end_offset,
+ underline_color,
+ thick,
+ SK_ColorTRANSPARENT) {}
+
+ImeTextSpan::ImeTextSpan(Type type,
+ uint32_t start_offset,
+ uint32_t end_offset,
+ SkColor underline_color,
+ bool thick,
+ SkColor background_color,
+ SkColor suggestion_highlight_color,
+ const std::vector<std::string>& suggestions)
+ : type(type),
+ start_offset(start_offset),
+ end_offset(end_offset),
+ underline_color(underline_color),
+ thick(thick),
+ background_color(background_color),
+ suggestion_highlight_color(suggestion_highlight_color),
+ suggestions(suggestions) {}
+
+ImeTextSpan::ImeTextSpan(const ImeTextSpan& rhs) = default;
+
+ImeTextSpan::~ImeTextSpan() = default;
+
+} // namespace ui
diff --git a/chromium/ui/base/ime/ime_text_span.h b/chromium/ui/base/ime/ime_text_span.h
new file mode 100644
index 00000000000..36b77f755ee
--- /dev/null
+++ b/chromium/ui/base/ime/ime_text_span.h
@@ -0,0 +1,79 @@
+// 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_BASE_IME_IME_TEXT_SPAN_H_
+#define UI_BASE_IME_IME_TEXT_SPAN_H_
+
+#include <stdint.h>
+
+#include <string>
+#include <vector>
+
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/base/ime/ui_base_ime_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 {
+ enum class Type {
+ // Creates a composition marker.
+ kComposition,
+ // Creates a suggestion marker that isn't cleared after the user picks a
+ // replacement.
+ kSuggestion,
+ };
+
+ // The default constructor is used by generated Mojo code.
+ ImeTextSpan();
+ // TODO(huangs): remove this constructor.
+ ImeTextSpan(uint32_t start_offset,
+ uint32_t end_offset,
+ SkColor underline_color,
+ bool thick);
+ ImeTextSpan(
+ Type type,
+ uint32_t start_offset,
+ uint32_t end_offset,
+ SkColor underline_color,
+ bool thick,
+ SkColor background_color,
+ SkColor suggestion_highlight_color = SK_ColorTRANSPARENT,
+ const std::vector<std::string>& suggestions = std::vector<std::string>());
+
+ ImeTextSpan(const ImeTextSpan& rhs);
+
+ ~ImeTextSpan();
+
+ bool operator==(const ImeTextSpan& rhs) const {
+ return (this->type == rhs.type) &&
+ (this->start_offset == rhs.start_offset) &&
+ (this->end_offset == rhs.end_offset) &&
+ (this->underline_color == rhs.underline_color) &&
+ (this->thick == rhs.thick) &&
+ (this->background_color == rhs.background_color) &&
+ (this->suggestion_highlight_color ==
+ rhs.suggestion_highlight_color) &&
+ (this->suggestions == rhs.suggestions);
+ }
+
+ bool operator!=(const ImeTextSpan& rhs) const { return !(*this == rhs); }
+
+ Type type;
+ uint32_t start_offset;
+ uint32_t end_offset;
+ SkColor underline_color;
+ bool thick;
+ SkColor background_color;
+ SkColor suggestion_highlight_color;
+ std::vector<std::string> suggestions;
+};
+
+typedef std::vector<ImeTextSpan> ImeTextSpans;
+
+} // namespace ui
+
+#endif // UI_BASE_IME_IME_TEXT_SPAN_H_
diff --git a/chromium/ui/base/ime/input_method_auralinux.cc b/chromium/ui/base/ime/input_method_auralinux.cc
index 03833c120ac..01893d5739b 100644
--- a/chromium/ui/base/ime/input_method_auralinux.cc
+++ b/chromium/ui/base/ime/input_method_auralinux.cc
@@ -125,7 +125,7 @@ void InputMethodAuraLinux::ProcessKeyEventByEngineDone(
base::string16* result_text,
bool is_handled) {
composition_changed_ = composition_changed;
- composition_.CopyFrom(*composition);
+ composition_ = *composition;
result_text_ = *result_text;
ignore_result(ProcessKeyEventDone(event, filtered, is_handled));
}
@@ -201,7 +201,7 @@ ui::EventDispatchDetails InputMethodAuraLinux::ProcessKeyEventDone(
// Makes sure the cached composition is cleared after committing any text or
// cleared composition.
if (client && !client->HasCompositionText())
- composition_.Clear();
+ composition_ = CompositionText();
if (!filtered) {
details = DispatchKeyEventPostIME(event);
@@ -317,7 +317,7 @@ void InputMethodAuraLinux::ResetContext() {
context_->Focus();
}
- composition_.Clear();
+ composition_ = CompositionText();
result_text_.clear();
is_sync_mode_ = false;
composition_changed_ = false;
@@ -349,7 +349,7 @@ void InputMethodAuraLinux::OnCommit(const base::string16& text) {
return;
if (!event.stopped_propagation() && !details.target_destroyed)
GetTextInputClient()->InsertText(text);
- composition_.Clear();
+ composition_ = CompositionText();
}
}
@@ -379,7 +379,7 @@ void InputMethodAuraLinux::OnPreeditEnd() {
if (is_sync_mode_) {
if (!composition_.text.empty()) {
- composition_.Clear();
+ composition_ = CompositionText();
composition_changed_ = true;
}
} else {
@@ -392,7 +392,7 @@ void InputMethodAuraLinux::OnPreeditEnd() {
if (!event.stopped_propagation() && !details.target_destroyed)
client->ClearCompositionText();
}
- composition_.Clear();
+ composition_ = CompositionText();
}
}
diff --git a/chromium/ui/base/ime/input_method_base.h b/chromium/ui/base/ime/input_method_base.h
index dbf9df4ecbd..77c95ef3183 100644
--- a/chromium/ui/base/ime/input_method_base.h
+++ b/chromium/ui/base/ime/input_method_base.h
@@ -29,7 +29,7 @@ class TextInputClient;
// A helper class providing functionalities shared among ui::InputMethod
// implementations.
class UI_BASE_IME_EXPORT InputMethodBase
- : NON_EXPORTED_BASE(public InputMethod),
+ : public InputMethod,
public base::SupportsWeakPtr<InputMethodBase>,
public IMEInputContextHandlerInterface {
public:
diff --git a/chromium/ui/base/ime/input_method_chromeos.cc b/chromium/ui/base/ime/input_method_chromeos.cc
index 1312ba47d71..d5c7b01804e 100644
--- a/chromium/ui/base/ime/input_method_chromeos.cc
+++ b/chromium/ui/base/ime/input_method_chromeos.cc
@@ -289,7 +289,7 @@ void InputMethodChromeOS::ResetContext() {
if (!IsNonPasswordInputFieldFocused() || !GetTextInputClient())
return;
- composition_.Clear();
+ composition_ = CompositionText();
result_text_.clear();
composing_text_ = false;
composition_changed_ = false;
@@ -534,7 +534,7 @@ void InputMethodChromeOS::UpdateCompositionText(const CompositionText& text,
GetTextInputClient()->SetCompositionText(composition_);
SendFakeProcessKeyEvent(false);
composition_changed_ = false;
- composition_.Clear();
+ composition_ = CompositionText();
}
}
@@ -544,7 +544,7 @@ void InputMethodChromeOS::HidePreeditText() {
// Intentionally leaves |composing_text_| unchanged.
composition_changed_ = true;
- composition_.Clear();
+ composition_ = CompositionText();
if (!handling_key_event_) {
TextInputClient* client = GetTextInputClient();
@@ -588,7 +588,7 @@ void InputMethodChromeOS::ExtractCompositionText(
const CompositionText& text,
uint32_t cursor_position,
CompositionText* out_composition) const {
- out_composition->Clear();
+ *out_composition = CompositionText();
out_composition->text = text.text;
if (out_composition->text.empty())
@@ -613,17 +613,19 @@ void InputMethodChromeOS::ExtractCompositionText(
out_composition->selection = gfx::Range(cursor_offset);
- const CompositionUnderlines text_underlines = text.underlines;
- if (!text_underlines.empty()) {
- for (size_t i = 0; i < text_underlines.size(); ++i) {
- const uint32_t start = text_underlines[i].start_offset;
- const uint32_t end = text_underlines[i].end_offset;
+ const ImeTextSpans text_ime_text_spans = text.ime_text_spans;
+ if (!text_ime_text_spans.empty()) {
+ for (size_t i = 0; i < text_ime_text_spans.size(); ++i) {
+ const uint32_t start = text_ime_text_spans[i].start_offset;
+ const uint32_t end = text_ime_text_spans[i].end_offset;
if (start >= end)
continue;
- CompositionUnderline underline(
- char16_offsets[start], char16_offsets[end], text_underlines[i].color,
- text_underlines[i].thick, text_underlines[i].background_color);
- out_composition->underlines.push_back(underline);
+ ImeTextSpan ime_text_span(ui::ImeTextSpan::Type::kComposition,
+ char16_offsets[start], char16_offsets[end],
+ text_ime_text_spans[i].underline_color,
+ text_ime_text_spans[i].thick,
+ text_ime_text_spans[i].background_color);
+ out_composition->ime_text_spans.push_back(ime_text_span);
}
}
@@ -631,29 +633,29 @@ void InputMethodChromeOS::ExtractCompositionText(
if (text.selection.start() < text.selection.end()) {
const uint32_t start = text.selection.start();
const uint32_t end = text.selection.end();
- CompositionUnderline underline(char16_offsets[start],
- char16_offsets[end],
- SK_ColorBLACK,
- true /* thick */,
- SK_ColorTRANSPARENT);
- out_composition->underlines.push_back(underline);
-
- // If the cursor is at start or end of this underline, then we treat
+ ImeTextSpan ime_text_span(ui::ImeTextSpan::Type::kComposition,
+ char16_offsets[start], char16_offsets[end],
+ SK_ColorBLACK, true /* thick */,
+ SK_ColorTRANSPARENT);
+ out_composition->ime_text_spans.push_back(ime_text_span);
+
+ // If the cursor is at start or end of this ime_text_span, then we treat
// it as the selection range as well, but make sure to set the cursor
// position to the selection end.
- if (underline.start_offset == cursor_offset) {
- out_composition->selection.set_start(underline.end_offset);
+ if (ime_text_span.start_offset == cursor_offset) {
+ out_composition->selection.set_start(ime_text_span.end_offset);
out_composition->selection.set_end(cursor_offset);
- } else if (underline.end_offset == cursor_offset) {
- out_composition->selection.set_start(underline.start_offset);
+ } else if (ime_text_span.end_offset == cursor_offset) {
+ out_composition->selection.set_start(ime_text_span.start_offset);
out_composition->selection.set_end(cursor_offset);
}
}
// Use a black thin underline by default.
- if (out_composition->underlines.empty()) {
- out_composition->underlines.push_back(CompositionUnderline(
- 0, length, SK_ColorBLACK, false /* thick */, SK_ColorTRANSPARENT));
+ if (out_composition->ime_text_spans.empty()) {
+ out_composition->ime_text_spans.push_back(
+ ImeTextSpan(ui::ImeTextSpan::Type::kComposition, 0, length,
+ SK_ColorBLACK, false /* thick */, SK_ColorTRANSPARENT));
}
}
diff --git a/chromium/ui/base/ime/mock_ime_input_context_handler.cc b/chromium/ui/base/ime/mock_ime_input_context_handler.cc
index 4c6045df821..b0ef49d0ec8 100644
--- a/chromium/ui/base/ime/mock_ime_input_context_handler.cc
+++ b/chromium/ui/base/ime/mock_ime_input_context_handler.cc
@@ -26,7 +26,7 @@ void MockIMEInputContextHandler::UpdateCompositionText(
uint32_t cursor_pos,
bool visible) {
++update_preedit_text_call_count_;
- last_update_composition_arg_.composition_text.CopyFrom(text);
+ last_update_composition_arg_.composition_text = text;
last_update_composition_arg_.cursor_pos = cursor_pos;
last_update_composition_arg_.is_visible = visible;
}
diff --git a/chromium/ui/base/ime/mock_input_method.h b/chromium/ui/base/ime/mock_input_method.h
index f703e4a00a1..b841a7a1d26 100644
--- a/chromium/ui/base/ime/mock_input_method.h
+++ b/chromium/ui/base/ime/mock_input_method.h
@@ -23,8 +23,7 @@ class TextInputClient;
// of this class as the global input method with calling
// SetUpInputMethodFactoryForTesting() which is declared in
// ui/base/ime/input_method_factory.h
-class UI_BASE_IME_EXPORT MockInputMethod
- : NON_EXPORTED_BASE(public InputMethod) {
+class UI_BASE_IME_EXPORT MockInputMethod : public InputMethod {
public:
explicit MockInputMethod(internal::InputMethodDelegate* delegate);
~MockInputMethod() override;
diff --git a/chromium/ui/base/ime/win/imm32_manager.cc b/chromium/ui/base/ime/win/imm32_manager.cc
index 8b868ce51ca..b4af3c966cd 100644
--- a/chromium/ui/base/ime/win/imm32_manager.cc
+++ b/chromium/ui/base/ime/win/imm32_manager.cc
@@ -62,10 +62,10 @@ void GetCompositionTargetRange(HIMC imm_context, int* target_start,
// Helper function for IMM32Manager::GetCompositionInfo() method, to get
// underlines information of the current composition string.
-void GetCompositionUnderlines(HIMC imm_context,
- int target_start,
- int target_end,
- ui::CompositionUnderlines* underlines) {
+void GetImeTextSpans(HIMC imm_context,
+ int target_start,
+ int target_end,
+ ui::ImeTextSpans* ime_text_spans) {
int clause_size = ::ImmGetCompositionString(imm_context, GCS_COMPCLAUSE,
NULL, 0);
int clause_length = clause_size / sizeof(uint32_t);
@@ -75,19 +75,19 @@ void GetCompositionUnderlines(HIMC imm_context,
::ImmGetCompositionString(imm_context, GCS_COMPCLAUSE,
clause_data.get(), clause_size);
for (int i = 0; i < clause_length - 1; ++i) {
- ui::CompositionUnderline underline;
- underline.start_offset = clause_data[i];
- underline.end_offset = clause_data[i+1];
- underline.color = SK_ColorBLACK;
- underline.thick = false;
- underline.background_color = SK_ColorTRANSPARENT;
+ ui::ImeTextSpan ime_text_span;
+ ime_text_span.start_offset = clause_data[i];
+ ime_text_span.end_offset = clause_data[i + 1];
+ ime_text_span.underline_color = SK_ColorBLACK;
+ ime_text_span.thick = false;
+ ime_text_span.background_color = SK_ColorTRANSPARENT;
// Use thick underline for the target clause.
- if (underline.start_offset >= static_cast<uint32_t>(target_start) &&
- underline.end_offset <= static_cast<uint32_t>(target_end)) {
- underline.thick = true;
+ if (ime_text_span.start_offset >= static_cast<uint32_t>(target_start) &&
+ ime_text_span.end_offset <= static_cast<uint32_t>(target_end)) {
+ ime_text_span.thick = true;
}
- underlines->push_back(underline);
+ ime_text_spans->push_back(ime_text_span);
}
}
}
@@ -294,8 +294,8 @@ void IMM32Manager::GetCompositionInfo(HIMC imm_context,
LPARAM lparam,
CompositionText* composition) {
// We only care about GCS_COMPATTR, GCS_COMPCLAUSE and GCS_CURSORPOS, and
- // convert them into underlines and selection range respectively.
- composition->underlines.clear();
+ // convert them into composition underlines and selection range respectively.
+ composition->ime_text_spans.clear();
int length = static_cast<int>(composition->text.length());
@@ -320,36 +320,36 @@ void IMM32Manager::GetCompositionInfo(HIMC imm_context,
composition->selection = gfx::Range(0);
}
- // Retrieve the clause segmentations and convert them to underlines.
+ // Retrieve the clause segmentations and convert them to ime_text_spans.
if (lparam & GCS_COMPCLAUSE) {
- GetCompositionUnderlines(imm_context, target_start, target_end,
- &composition->underlines);
+ GetImeTextSpans(imm_context, target_start, target_end,
+ &composition->ime_text_spans);
}
- // Set default underlines in case there is no clause information.
- if (!composition->underlines.empty())
+ // Set default composition underlines in case there is no clause information.
+ if (!composition->ime_text_spans.empty())
return;
- CompositionUnderline underline;
- underline.color = SK_ColorBLACK;
- underline.background_color = SK_ColorTRANSPARENT;
+ ImeTextSpan ime_text_span;
+ ime_text_span.underline_color = SK_ColorBLACK;
+ ime_text_span.background_color = SK_ColorTRANSPARENT;
if (target_start > 0) {
- underline.start_offset = 0U;
- underline.end_offset = static_cast<uint32_t>(target_start);
- underline.thick = false;
- composition->underlines.push_back(underline);
+ ime_text_span.start_offset = 0U;
+ ime_text_span.end_offset = static_cast<uint32_t>(target_start);
+ ime_text_span.thick = false;
+ composition->ime_text_spans.push_back(ime_text_span);
}
if (target_end > target_start) {
- underline.start_offset = static_cast<uint32_t>(target_start);
- underline.end_offset = static_cast<uint32_t>(target_end);
- underline.thick = true;
- composition->underlines.push_back(underline);
+ ime_text_span.start_offset = static_cast<uint32_t>(target_start);
+ ime_text_span.end_offset = static_cast<uint32_t>(target_end);
+ ime_text_span.thick = true;
+ composition->ime_text_spans.push_back(ime_text_span);
}
if (target_end < length) {
- underline.start_offset = static_cast<uint32_t>(target_end);
- underline.end_offset = static_cast<uint32_t>(length);
- underline.thick = false;
- composition->underlines.push_back(underline);
+ ime_text_span.start_offset = static_cast<uint32_t>(target_end);
+ ime_text_span.end_offset = static_cast<uint32_t>(length);
+ ime_text_span.thick = false;
+ composition->ime_text_spans.push_back(ime_text_span);
}
}
@@ -403,7 +403,7 @@ bool IMM32Manager::GetComposition(HWND window_handle, LPARAM lparam,
composition->text[0] = 0xFF3F;
}
- // Retrieve the composition underlines and selection range information.
+ // Retrieve the IME text spans and selection range information.
GetCompositionInfo(imm_context, lparam, composition);
// Mark that there is an ongoing composition.
diff --git a/chromium/ui/base/l10n/l10n_util.cc b/chromium/ui/base/l10n/l10n_util.cc
index 5100c0ced98..c43fd7cc09e 100644
--- a/chromium/ui/base/l10n/l10n_util.cc
+++ b/chromium/ui/base/l10n/l10n_util.cc
@@ -334,7 +334,7 @@ std::string GetLanguage(const std::string& locale) {
return std::string(locale, 0, hyphen_pos);
}
-// TOOD(jshin): revamp this function completely to use a more sytematic
+// TODO(jshin): revamp this function completely to use a more sytematic
// and generic locale fallback based on ICU/CLDR.
bool CheckAndResolveLocale(const std::string& locale,
std::string* resolved_locale) {
diff --git a/chromium/ui/base/l10n/l10n_util_android.cc b/chromium/ui/base/l10n/l10n_util_android.cc
index 5c7c12d57b1..6fa1f4685b6 100644
--- a/chromium/ui/base/l10n/l10n_util_android.cc
+++ b/chromium/ui/base/l10n/l10n_util_android.cc
@@ -108,8 +108,4 @@ ScopedJavaLocalRef<jstring> GetDurationString(JNIEnv* env,
return jtime_remaining;
}
-bool RegisterLocalizationUtil(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
} // namespace l10n_util
diff --git a/chromium/ui/base/l10n/l10n_util_android.h b/chromium/ui/base/l10n/l10n_util_android.h
index 3745ed6cb2c..38592e9c58e 100644
--- a/chromium/ui/base/l10n/l10n_util_android.h
+++ b/chromium/ui/base/l10n/l10n_util_android.h
@@ -20,8 +20,6 @@ UI_BASE_EXPORT base::string16 GetDisplayNameForLocale(
UI_BASE_EXPORT bool IsLayoutRtl();
-UI_BASE_EXPORT bool RegisterLocalizationUtil(JNIEnv* env);
-
} // namespace l10n_util
#endif // UI_BASE_L10N_L10N_UTIL_ANDROID_H_
diff --git a/chromium/ui/base/material_design/material_design_controller.cc b/chromium/ui/base/material_design/material_design_controller.cc
index ee9a7d6e8b2..530b6896e0c 100644
--- a/chromium/ui/base/material_design/material_design_controller.cc
+++ b/chromium/ui/base/material_design/material_design_controller.cc
@@ -20,7 +20,7 @@
#include "base/files/file_enumerator.h"
#include "base/threading/thread_restrictions.h"
-#include "ui/events/ozone/evdev/event_device_info.h"
+#include "ui/events/ozone/evdev/event_device_info.h" // nogncheck
#endif // defined(USE_OZONE)
#endif // defined(OS_CHROMEOS)
diff --git a/chromium/ui/base/models/button_menu_item_model.h b/chromium/ui/base/models/button_menu_item_model.h
index 0b15d9c26ae..22595e64ee1 100644
--- a/chromium/ui/base/models/button_menu_item_model.h
+++ b/chromium/ui/base/models/button_menu_item_model.h
@@ -26,8 +26,7 @@ class UI_BASE_EXPORT ButtonMenuItemModel {
TYPE_BUTTON_LABEL
};
- class UI_BASE_EXPORT Delegate
- : NON_EXPORTED_BASE(public AcceleratorProvider) {
+ class UI_BASE_EXPORT Delegate : public AcceleratorProvider {
public:
// Some command ids have labels that change over time.
virtual bool IsItemForCommandIdDynamic(int command_id) const;
diff --git a/chromium/ui/base/models/simple_menu_model.h b/chromium/ui/base/models/simple_menu_model.h
index 9a9f3505095..7c54a24e12d 100644
--- a/chromium/ui/base/models/simple_menu_model.h
+++ b/chromium/ui/base/models/simple_menu_model.h
@@ -28,8 +28,7 @@ class ButtonMenuItemModel;
// The breadth of MenuModel is not exposed through this API.
class UI_BASE_EXPORT SimpleMenuModel : public MenuModel {
public:
- class UI_BASE_EXPORT Delegate
- : NON_EXPORTED_BASE(public AcceleratorProvider) {
+ class UI_BASE_EXPORT Delegate : public AcceleratorProvider {
public:
~Delegate() override {}
diff --git a/chromium/ui/base/page_transition_types.h b/chromium/ui/base/page_transition_types.h
index 1d2d420834c..b77f25acc48 100644
--- a/chromium/ui/base/page_transition_types.h
+++ b/chromium/ui/base/page_transition_types.h
@@ -25,8 +25,10 @@ namespace ui {
// A Java counterpart will be generated for this enum.
// GENERATED_JAVA_ENUM_PACKAGE: org.chromium.ui.base
enum PageTransition {
+ PAGE_TRANSITION_FIRST = 0,
+
// User got to this page by clicking a link on another page.
- PAGE_TRANSITION_LINK = 0,
+ PAGE_TRANSITION_LINK = PAGE_TRANSITION_FIRST,
// User got this page by typing the URL in the URL bar. This should not be
// used for cases where the user selected a choice that didn't look at all
diff --git a/chromium/ui/base/resource/data_pack.cc b/chromium/ui/base/resource/data_pack.cc
index 3d07d985a2a..511149d4d9f 100644
--- a/chromium/ui/base/resource/data_pack.cc
+++ b/chromium/ui/base/resource/data_pack.cc
@@ -24,31 +24,14 @@
namespace {
-static const uint32_t kFileFormatVersion = 4;
-// Length of file header: version, entry count and text encoding type.
-static const size_t kHeaderLength = 2 * sizeof(uint32_t) + sizeof(uint8_t);
-
-#pragma pack(push, 2)
-struct DataPackEntry {
- uint16_t resource_id;
- uint32_t file_offset;
-
- static int CompareById(const void* void_key, const void* void_entry) {
- uint16_t key = *reinterpret_cast<const uint16_t*>(void_key);
- const DataPackEntry* entry =
- reinterpret_cast<const DataPackEntry*>(void_entry);
- if (key < entry->resource_id) {
- return -1;
- } else if (key > entry->resource_id) {
- return 1;
- } else {
- return 0;
- }
- }
-};
-#pragma pack(pop)
-
-static_assert(sizeof(DataPackEntry) == 6, "size of entry must be six");
+static const uint32_t kFileFormatV4 = 4;
+static const uint32_t kFileFormatV5 = 5;
+// int32(version), int32(resource_count), int8(encoding)
+static const size_t kHeaderLengthV4 = 2 * sizeof(uint32_t) + sizeof(uint8_t);
+// int32(version), int8(encoding), 3 bytes padding,
+// int16(resource_count), int16(alias_count)
+static const size_t kHeaderLengthV5 =
+ sizeof(uint32_t) + sizeof(uint8_t) * 4 + sizeof(uint16_t) * 2;
// We're crashing when trying to load a pak file on Windows. Add some error
// codes for logging.
@@ -102,6 +85,30 @@ void MaybePrintResourceId(uint16_t resource_id) {
namespace ui {
+#pragma pack(push, 2)
+struct DataPack::Entry {
+ uint16_t resource_id;
+ uint32_t file_offset;
+
+ static int CompareById(const void* void_key, const void* void_entry) {
+ uint16_t key = *reinterpret_cast<const uint16_t*>(void_key);
+ const Entry* entry = reinterpret_cast<const Entry*>(void_entry);
+ return key - entry->resource_id;
+ }
+};
+
+struct DataPack::Alias {
+ uint16_t resource_id;
+ uint16_t entry_index;
+
+ static int CompareById(const void* void_key, const void* void_entry) {
+ uint16_t key = *reinterpret_cast<const uint16_t*>(void_key);
+ const Alias* entry = reinterpret_cast<const Alias*>(void_entry);
+ return key - entry->resource_id;
+ }
+};
+#pragma pack(pop)
+
// Abstraction of a data source (memory mapped file or in-memory buffer).
class DataPack::DataSource {
public:
@@ -149,9 +156,15 @@ class DataPack::BufferDataSource : public DataPack::DataSource {
};
DataPack::DataPack(ui::ScaleFactor scale_factor)
- : resource_count_(0),
+ : resource_table_(nullptr),
+ resource_count_(0),
+ alias_table_(nullptr),
+ alias_count_(0),
text_encoding_type_(BINARY),
scale_factor_(scale_factor) {
+ // Static assert must be within a DataPack member to appease visiblity rules.
+ static_assert(sizeof(Entry) == 6, "size of Entry must be 6");
+ static_assert(sizeof(Alias) == 4, "size of Alias must be 4");
}
DataPack::~DataPack() {
@@ -193,29 +206,37 @@ bool DataPack::LoadFromBuffer(base::StringPiece buffer) {
}
bool DataPack::LoadImpl(std::unique_ptr<DataPack::DataSource> data_source) {
- // Sanity check the header of the file.
- if (kHeaderLength > data_source->GetLength()) {
+ const uint8_t* data = data_source->GetData();
+ size_t data_length = data_source->GetLength();
+ // Parse the version and check for truncated header.
+ uint32_t version = 0;
+ if (data_length > sizeof(version))
+ version = reinterpret_cast<const uint32_t*>(data)[0];
+ size_t header_length =
+ version == kFileFormatV4 ? kHeaderLengthV4 : kHeaderLengthV5;
+ if (version == 0 || data_length < header_length) {
DLOG(ERROR) << "Data pack file corruption: incomplete file header.";
LogDataPackError(HEADER_TRUNCATED);
return false;
}
// Parse the header of the file.
- // First uint32_t: version; second: resource count;
- const uint32_t* ptr =
- reinterpret_cast<const uint32_t*>(data_source->GetData());
- uint32_t version = ptr[0];
- if (version != kFileFormatVersion) {
+ if (version == kFileFormatV4) {
+ resource_count_ = reinterpret_cast<const uint32_t*>(data)[1];
+ alias_count_ = 0;
+ text_encoding_type_ = static_cast<TextEncodingType>(data[8]);
+ } else if (version == kFileFormatV5) {
+ // Version 5 added the alias table and changed the header format.
+ text_encoding_type_ = static_cast<TextEncodingType>(data[4]);
+ resource_count_ = reinterpret_cast<const uint16_t*>(data)[4];
+ alias_count_ = reinterpret_cast<const uint16_t*>(data)[5];
+ } else {
LOG(ERROR) << "Bad data pack version: got " << version << ", expected "
- << kFileFormatVersion;
+ << kFileFormatV4 << " or " << kFileFormatV5;
LogDataPackError(BAD_VERSION);
return false;
}
- resource_count_ = ptr[1];
- // third: text encoding.
- const uint8_t* ptr_encoding = reinterpret_cast<const uint8_t*>(ptr + 2);
- text_encoding_type_ = static_cast<TextEncodingType>(*ptr_encoding);
if (text_encoding_type_ != UTF8 && text_encoding_type_ != UTF16 &&
text_encoding_type_ != BINARY) {
LOG(ERROR) << "Bad data pack text encoding: got " << text_encoding_type_
@@ -227,35 +248,63 @@ bool DataPack::LoadImpl(std::unique_ptr<DataPack::DataSource> data_source) {
// Sanity check the file.
// 1) Check we have enough entries. There's an extra entry after the last item
// which gives the length of the last item.
- if (kHeaderLength + (resource_count_ + 1) * sizeof(DataPackEntry) >
- data_source->GetLength()) {
- LOG(ERROR) << "Data pack file corruption: too short for number of "
- "entries specified.";
+ size_t resource_table_size = (resource_count_ + 1) * sizeof(Entry);
+ size_t alias_table_size = alias_count_ * sizeof(Alias);
+ if (header_length + resource_table_size + alias_table_size > data_length) {
+ LOG(ERROR) << "Data pack file corruption: "
+ << "too short for number of entries.";
LogDataPackError(INDEX_TRUNCATED);
return false;
}
+
+ resource_table_ = reinterpret_cast<const Entry*>(&data[header_length]);
+ alias_table_ = reinterpret_cast<const Alias*>(
+ &data[header_length + resource_table_size]);
+
// 2) Verify the entries are within the appropriate bounds. There's an extra
// entry after the last item which gives us the length of the last item.
for (size_t i = 0; i < resource_count_ + 1; ++i) {
- const DataPackEntry* entry = reinterpret_cast<const DataPackEntry*>(
- data_source->GetData() + kHeaderLength + (i * sizeof(DataPackEntry)));
- if (entry->file_offset > data_source->GetLength()) {
- LOG(ERROR) << "Entry #" << i << " in data pack points off end of file. "
- << "Was the file corrupted?";
+ if (resource_table_[i].file_offset > data_length) {
+ LOG(ERROR) << "Data pack file corruption: "
+ << "Entry #" << i << " past end.";
LogDataPackError(ENTRY_NOT_FOUND);
return false;
}
}
- data_source_ = std::move(data_source);
+ // 3) Verify the aliases are within the appropriate bounds.
+ for (size_t i = 0; i < alias_count_; ++i) {
+ if (alias_table_[i].entry_index >= resource_count_) {
+ LOG(ERROR) << "Data pack file corruption: "
+ << "Alias #" << i << " past end.";
+ LogDataPackError(ENTRY_NOT_FOUND);
+ return false;
+ }
+ }
+ data_source_ = std::move(data_source);
return true;
}
+const DataPack::Entry* DataPack::LookupEntryById(uint16_t resource_id) const {
+ // Search the resource table first as most resources will be in there.
+ const Entry* ret = reinterpret_cast<const Entry*>(
+ bsearch(&resource_id, resource_table_, resource_count_, sizeof(Entry),
+ Entry::CompareById));
+ if (ret == nullptr) {
+ // Search the alias table for the ~10% of entries which are aliases.
+ const Alias* alias = reinterpret_cast<const Alias*>(
+ bsearch(&resource_id, alias_table_, alias_count_, sizeof(Alias),
+ Alias::CompareById));
+ if (alias != nullptr) {
+ ret = &resource_table_[alias->entry_index];
+ }
+ }
+ return ret;
+}
+
bool DataPack::HasResource(uint16_t resource_id) const {
- return !!bsearch(&resource_id, data_source_->GetData() + kHeaderLength,
- resource_count_, sizeof(DataPackEntry),
- DataPackEntry::CompareById);
+ return !!LookupEntryById(resource_id);
}
bool DataPack::GetStringPiece(uint16_t resource_id,
@@ -271,20 +320,19 @@ bool DataPack::GetStringPiece(uint16_t resource_id,
#error DataPack assumes little endian
#endif
- const DataPackEntry* target = reinterpret_cast<const DataPackEntry*>(bsearch(
- &resource_id, data_source_->GetData() + kHeaderLength, resource_count_,
- sizeof(DataPackEntry), DataPackEntry::CompareById));
- if (!target) {
+ const Entry* target = LookupEntryById(resource_id);
+ if (!target)
return false;
- }
- const DataPackEntry* next_entry = target + 1;
+ const Entry* next_entry = target + 1;
// If the next entry points beyond the end of the file this data pack's entry
// table is corrupt. Log an error and return false. See
// http://crbug.com/371301.
- if (next_entry->file_offset > data_source_->GetLength()) {
- size_t entry_index = target - reinterpret_cast<const DataPackEntry*>(
- data_source_->GetData() + kHeaderLength);
+ size_t entry_offset =
+ reinterpret_cast<const uint8_t*>(next_entry) - data_source_->GetData();
+ size_t pak_size = data_source_->GetLength();
+ if (entry_offset > pak_size || next_entry->file_offset > pak_size) {
+ size_t entry_index = target - resource_table_;
LOG(ERROR) << "Entry #" << entry_index << " in data pack points off end "
<< "of file. This should have been caught when loading. Was the "
<< "file modified?";
@@ -320,9 +368,7 @@ ui::ScaleFactor DataPack::GetScaleFactor() const {
void DataPack::CheckForDuplicateResources(
const std::vector<std::unique_ptr<ResourceHandle>>& packs) {
for (size_t i = 0; i < resource_count_ + 1; ++i) {
- const DataPackEntry* entry = reinterpret_cast<const DataPackEntry*>(
- data_source_->GetData() + kHeaderLength + (i * sizeof(DataPackEntry)));
- const uint16_t resource_id = entry->resource_id;
+ const uint16_t resource_id = resource_table_[i].resource_id;
const float resource_scale = GetScaleForScaleFactor(scale_factor_);
for (const auto& handle : packs) {
if (GetScaleForScaleFactor(handle->GetScaleFactor()) != resource_scale)
@@ -339,56 +385,44 @@ void DataPack::CheckForDuplicateResources(
bool DataPack::WritePack(const base::FilePath& path,
const std::map<uint16_t, base::StringPiece>& resources,
TextEncodingType textEncodingType) {
- FILE* file = base::OpenFile(path, "wb");
- if (!file)
- return false;
-
- if (fwrite(&kFileFormatVersion, sizeof(kFileFormatVersion), 1, file) != 1) {
- LOG(ERROR) << "Failed to write file version";
- base::CloseFile(file);
- return false;
- }
-
- // Note: the python version of this function explicitly sorted keys, but
- // std::map is a sorted associative container, we shouldn't have to do that.
- uint32_t entry_count = resources.size();
- if (fwrite(&entry_count, sizeof(entry_count), 1, file) != 1) {
- LOG(ERROR) << "Failed to write entry count";
- base::CloseFile(file);
- return false;
- }
-
if (textEncodingType != UTF8 && textEncodingType != UTF16 &&
textEncodingType != BINARY) {
LOG(ERROR) << "Invalid text encoding type, got " << textEncodingType
<< ", expected between " << BINARY << " and " << UTF16;
- base::CloseFile(file);
return false;
}
- uint8_t write_buffer = static_cast<uint8_t>(textEncodingType);
- if (fwrite(&write_buffer, sizeof(uint8_t), 1, file) != 1) {
- LOG(ERROR) << "Failed to write file text resources encoding";
+ FILE* file = base::OpenFile(path, "wb");
+ if (!file)
+ return false;
+
+ uint32_t encoding = static_cast<uint32_t>(textEncodingType);
+ // Note: the python version of this function explicitly sorted keys, but
+ // std::map is a sorted associative container, we shouldn't have to do that.
+ uint16_t entry_count = resources.size();
+ // Don't bother computing aliases (revisit if it becomes worth it).
+ uint16_t alias_count = 0;
+
+ if (fwrite(&kFileFormatV5, sizeof(kFileFormatV5), 1, file) != 1 ||
+ fwrite(&encoding, sizeof(uint32_t), 1, file) != 1 ||
+ fwrite(&entry_count, sizeof(entry_count), 1, file) != 1 ||
+ fwrite(&alias_count, sizeof(alias_count), 1, file) != 1) {
+ LOG(ERROR) << "Failed to write header";
base::CloseFile(file);
return false;
}
// Each entry is a uint16_t + a uint32_t. We have an extra entry after the
// last item so we can compute the size of the list item.
- uint32_t index_length = (entry_count + 1) * sizeof(DataPackEntry);
- uint32_t data_offset = kHeaderLength + index_length;
+ uint32_t index_length = (entry_count + 1) * sizeof(Entry);
+ uint32_t data_offset = kHeaderLengthV5 + index_length;
for (std::map<uint16_t, base::StringPiece>::const_iterator it =
resources.begin();
it != resources.end(); ++it) {
uint16_t resource_id = it->first;
- if (fwrite(&resource_id, sizeof(resource_id), 1, file) != 1) {
- LOG(ERROR) << "Failed to write id for " << resource_id;
- base::CloseFile(file);
- return false;
- }
-
- if (fwrite(&data_offset, sizeof(data_offset), 1, file) != 1) {
- LOG(ERROR) << "Failed to write offset for " << resource_id;
+ if (fwrite(&resource_id, sizeof(resource_id), 1, file) != 1 ||
+ fwrite(&data_offset, sizeof(data_offset), 1, file) != 1) {
+ LOG(ERROR) << "Failed to write entry for " << resource_id;
base::CloseFile(file);
return false;
}
diff --git a/chromium/ui/base/resource/data_pack.h b/chromium/ui/base/resource/data_pack.h
index 56d30d28e39..ffd47a4ad5e 100644
--- a/chromium/ui/base/resource/data_pack.h
+++ b/chromium/ui/base/resource/data_pack.h
@@ -75,6 +75,8 @@ class UI_DATA_PACK_EXPORT DataPack : public ResourceHandle {
#endif
private:
+ struct Entry;
+ struct Alias;
class DataSource;
class BufferDataSource;
class MemoryMappedDataSource;
@@ -82,11 +84,14 @@ class UI_DATA_PACK_EXPORT DataPack : public ResourceHandle {
// Does the actual loading of a pack file.
// Called by Load and LoadFromFile and LoadFromBuffer.
bool LoadImpl(std::unique_ptr<DataSource> data_source);
+ const Entry* LookupEntryById(uint16_t resource_id) const;
std::unique_ptr<DataSource> data_source_;
- // Number of resources in the data.
+ const Entry* resource_table_;
size_t resource_count_;
+ const Alias* alias_table_;
+ size_t alias_count_;
// Type of encoding for text resources.
TextEncodingType text_encoding_type_;
diff --git a/chromium/ui/base/resource/data_pack_literal.cc b/chromium/ui/base/resource/data_pack_literal.cc
index cf490868cca..3218f848e94 100644
--- a/chromium/ui/base/resource/data_pack_literal.cc
+++ b/chromium/ui/base/resource/data_pack_literal.cc
@@ -4,57 +4,71 @@
#include <stddef.h>
+#include "ui/base/resource/data_pack_literal.h"
+
namespace ui {
-extern const char kSamplePakContents[] = {
- 0x04, 0x00, 0x00, 0x00, // header(version
- 0x04, 0x00, 0x00, 0x00, // no. entries
- 0x01, // encoding)
- 0x01, 0x00, 0x27, 0x00, 0x00, 0x00, // index entry 1
- 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, // index entry 4
- 0x06, 0x00, 0x33, 0x00, 0x00, 0x00, // index entry 6
- 0x0a, 0x00, 0x3f, 0x00, 0x00, 0x00, // index entry 10
- 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, // extra entry for the size of last
- 't', 'h', 'i', 's', ' ', 'i', 's', ' ', 'i', 'd', ' ', '4',
- 't', 'h', 'i', 's', ' ', 'i', 's', ' ', 'i', 'd', ' ', '6'
-};
+const char kSamplePakContentsV4[] = {
+ 0x04, 0x00, 0x00, 0x00, // header(version
+ 0x04, 0x00, 0x00, 0x00, // no. entries
+ 0x01, // encoding)
+ 0x01, 0x00, 0x27, 0x00, 0x00, 0x00, // index entry 1
+ 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, // index entry 4
+ 0x06, 0x00, 0x33, 0x00, 0x00, 0x00, // index entry 6
+ 0x0a, 0x00, 0x3f, 0x00, 0x00, 0x00, // index entry 10
+ 0x00, 0x00, 0x3f, 0x00, 0x00, 0x00, // extra entry for the size of last
+ 't', 'h', 'i', 's', ' ', 'i', 's', ' ', 'i', 'd', ' ', '4',
+ 't', 'h', 'i', 's', ' ', 'i', 's', ' ', 'i', 'd', ' ', '6'};
-extern const size_t kSamplePakSize = sizeof(kSamplePakContents);
-
-extern const char kSampleCorruptPakContents[] = {
- 0x04, 0x00, 0x00, 0x00, // header(version
- 0x04, 0x00, 0x00, 0x00, // no. entries
- 0x01, // encoding)
- 0x01, 0x00, 0x27, 0x00, 0x00, 0x00, // index entry 1
- 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, // index entry 4
- 0x06, 0x00, 0x33, 0x00, 0x00, 0x00, // index entry 6
- 0x0a, 0x00, 0x3f, 0x00, 0x00, 0x00, // index entry 10
- 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, // extra entry for the size of last,
- // extends past END OF FILE.
- 't', 'h', 'i', 's', ' ', 'i', 's', ' ', 'i', 'd', ' ', '4',
- 't', 'h', 'i', 's', ' ', 'i', 's', ' ', 'i', 'd', ' ', '6'
-};
+const size_t kSamplePakSizeV4 = sizeof(kSamplePakContentsV4);
-extern const size_t kSampleCorruptPakSize = sizeof(kSampleCorruptPakContents);
+const char kSamplePakContentsV5[] = {
+ 0x05, 0x00, 0x00, 0x00, // version
+ 0x01, 0x00, 0x00, 0x00, // encoding + padding
+ 0x03, 0x00, 0x01, 0x00, // num_resources, num_aliases
+ 0x01, 0x00, 0x28, 0x00, 0x00, 0x00, // index entry 1
+ 0x04, 0x00, 0x28, 0x00, 0x00, 0x00, // index entry 4
+ 0x06, 0x00, 0x34, 0x00, 0x00, 0x00, // index entry 6
+ 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, // extra entry for the size of last
+ 0x0a, 0x00, 0x01, 0x00, // alias table
+ 't', 'h', 'i', 's', ' ', 'i', 's', ' ', 'i', 'd', ' ', '4',
+ 't', 'h', 'i', 's', ' ', 'i', 's', ' ', 'i', 'd', ' ', '6'};
-extern const char kSamplePakContents2x[] = {
- 0x04, 0x00, 0x00, 0x00, // header(version
- 0x01, 0x00, 0x00, 0x00, // no. entries
- 0x01, // encoding)
- 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, // index entry 4
- 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, // extra entry for the size of last
- 't', 'h', 'i', 's', ' ', 'i', 's', ' ', 'i', 'd', ' ', '4', ' ', '2', 'x'
-};
+const size_t kSamplePakSizeV5 = sizeof(kSamplePakContentsV5);
+
+const char kSampleCorruptPakContents[] = {
+ 0x04, 0x00, 0x00, 0x00, // header(version
+ 0x04, 0x00, 0x00, 0x00, // no. entries
+ 0x01, // encoding)
+ 0x01, 0x00, 0x27, 0x00, 0x00, 0x00, // index entry 1
+ 0x04, 0x00, 0x27, 0x00, 0x00, 0x00, // index entry 4
+ 0x06, 0x00, 0x33, 0x00, 0x00, 0x00, // index entry 6
+ 0x0a, 0x00, 0x3f, 0x00, 0x00, 0x00, // index entry 10
+ 0x00, 0x00, 0x40, 0x00, 0x00, 0x00, // extra entry for the size of last,
+ // extends past END OF FILE.
+ 't', 'h', 'i', 's', ' ', 'i', 's', ' ', 'i', 'd', ' ', '4', 't', 'h', 'i',
+ 's', ' ', 'i', 's', ' ', 'i', 'd', ' ', '6'};
+
+const size_t kSampleCorruptPakSize = sizeof(kSampleCorruptPakContents);
+
+const char kSamplePakContents2x[] = {
+ 0x04, 0x00, 0x00, 0x00, // header(version
+ 0x01, 0x00, 0x00, 0x00, // no. entries
+ 0x01, // encoding)
+ 0x04, 0x00, 0x15, 0x00, 0x00, 0x00, // index entry 4
+ 0x00, 0x00, 0x24, 0x00, 0x00, 0x00, // extra entry for the size of last
+ 't', 'h', 'i', 's', ' ', 'i', 's', ' ',
+ 'i', 'd', ' ', '4', ' ', '2', 'x'};
-extern const size_t kSamplePakSize2x = sizeof(kSamplePakContents2x);
+const size_t kSamplePakSize2x = sizeof(kSamplePakContents2x);
-extern const char kEmptyPakContents[] = {
- 0x04, 0x00, 0x00, 0x00, // header(version
- 0x00, 0x00, 0x00, 0x00, // no. entries
- 0x01, // encoding)
- 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00 // extra entry for the size of last
+const char kEmptyPakContents[] = {
+ 0x04, 0x00, 0x00, 0x00, // header(version
+ 0x00, 0x00, 0x00, 0x00, // no. entries
+ 0x01, // encoding)
+ 0x00, 0x00, 0x0f, 0x00, 0x00, 0x00 // extra entry for the size of last
};
-extern const size_t kEmptyPakSize = sizeof(kEmptyPakContents);
+const size_t kEmptyPakSize = sizeof(kEmptyPakContents);
} // namespace ui
diff --git a/chromium/ui/base/resource/data_pack_literal.h b/chromium/ui/base/resource/data_pack_literal.h
new file mode 100644
index 00000000000..0e74647771d
--- /dev/null
+++ b/chromium/ui/base/resource/data_pack_literal.h
@@ -0,0 +1,23 @@
+// 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_RESOURCE_DATA_PACK_LITERAL_H_
+#define UI_BASE_RESOURCE_DATA_PACK_LITERAL_H_
+
+namespace ui {
+
+extern const char kSamplePakContentsV4[];
+extern const size_t kSamplePakSizeV4;
+extern const char kSamplePakContentsV5[];
+extern const size_t kSamplePakSizeV5;
+extern const char kSamplePakContents2x[];
+extern const size_t kSamplePakSize2x;
+extern const char kEmptyPakContents[];
+extern const size_t kEmptyPakSize;
+extern const char kSampleCorruptPakContents[];
+extern const size_t kSampleCorruptPakSize;
+
+} // namespace ui
+
+#endif // UI_BASE_RESOURCE_DATA_PACK_LITERAL_H_
diff --git a/chromium/ui/base/resource/data_pack_unittest.cc b/chromium/ui/base/resource/data_pack_unittest.cc
index 4d5319637bc..d2615b08954 100644
--- a/chromium/ui/base/resource/data_pack_unittest.cc
+++ b/chromium/ui/base/resource/data_pack_unittest.cc
@@ -17,6 +17,7 @@
#include "base/strings/string_piece.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/resource/data_pack_literal.h"
#include "ui/base/ui_base_paths.h"
namespace ui {
@@ -27,11 +28,6 @@ class DataPackTest
DataPackTest() {}
};
-extern const char kSamplePakContents[];
-extern const char kSampleCorruptPakContents[];
-extern const size_t kSamplePakSize;
-extern const size_t kSampleCorruptPakSize;
-
TEST(DataPackTest, LoadFromPath) {
base::ScopedTempDir dir;
ASSERT_TRUE(dir.CreateUniqueTempDir());
@@ -39,8 +35,8 @@ TEST(DataPackTest, LoadFromPath) {
dir.GetPath().Append(FILE_PATH_LITERAL("sample.pak"));
// Dump contents into the pak file.
- ASSERT_EQ(base::WriteFile(data_path, kSamplePakContents, kSamplePakSize),
- static_cast<int>(kSamplePakSize));
+ ASSERT_EQ(base::WriteFile(data_path, kSamplePakContentsV4, kSamplePakSizeV4),
+ static_cast<int>(kSamplePakSizeV4));
// Load the file through the data pack API.
DataPack pack(SCALE_FACTOR_100P);
@@ -72,8 +68,8 @@ TEST(DataPackTest, LoadFromFile) {
dir.GetPath().Append(FILE_PATH_LITERAL("sample.pak"));
// Dump contents into the pak file.
- ASSERT_EQ(base::WriteFile(data_path, kSamplePakContents, kSamplePakSize),
- static_cast<int>(kSamplePakSize));
+ ASSERT_EQ(base::WriteFile(data_path, kSamplePakContentsV4, kSamplePakSizeV4),
+ static_cast<int>(kSamplePakSizeV4));
base::File file(data_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
ASSERT_TRUE(file.IsValid());
@@ -112,15 +108,15 @@ TEST(DataPackTest, LoadFromFileRegion) {
const char kPadding[5678] = {0};
ASSERT_EQ(static_cast<int>(sizeof(kPadding)),
base::WriteFile(data_path, kPadding, sizeof(kPadding)));
- ASSERT_TRUE(base::AppendToFile(
- data_path, kSamplePakContents, kSamplePakSize));
+ ASSERT_TRUE(
+ base::AppendToFile(data_path, kSamplePakContentsV4, kSamplePakSizeV4));
base::File file(data_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
ASSERT_TRUE(file.IsValid());
// Load the file through the data pack API.
DataPack pack(SCALE_FACTOR_100P);
- base::MemoryMappedFile::Region region = {sizeof(kPadding), kSamplePakSize};
+ base::MemoryMappedFile::Region region = {sizeof(kPadding), kSamplePakSizeV4};
ASSERT_TRUE(pack.LoadFromFileRegion(std::move(file), region));
base::StringPiece data;
@@ -142,11 +138,11 @@ TEST(DataPackTest, LoadFromFileRegion) {
ASSERT_FALSE(pack.GetStringPiece(140, &data));
}
-TEST(DataPackTest, LoadFromBuffer) {
+TEST(DataPackTest, LoadFromBufferV4) {
DataPack pack(SCALE_FACTOR_100P);
ASSERT_TRUE(pack.LoadFromBuffer(
- base::StringPiece(kSamplePakContents, kSamplePakSize)));
+ base::StringPiece(kSamplePakContentsV4, kSamplePakSizeV4)));
base::StringPiece data;
ASSERT_TRUE(pack.HasResource(4));
@@ -167,6 +163,31 @@ TEST(DataPackTest, LoadFromBuffer) {
ASSERT_FALSE(pack.GetStringPiece(140, &data));
}
+TEST(DataPackTest, LoadFromBufferV5) {
+ DataPack pack(SCALE_FACTOR_100P);
+
+ ASSERT_TRUE(pack.LoadFromBuffer(
+ base::StringPiece(kSamplePakContentsV5, kSamplePakSizeV5)));
+
+ base::StringPiece data;
+ ASSERT_TRUE(pack.HasResource(4));
+ ASSERT_TRUE(pack.GetStringPiece(4, &data));
+ EXPECT_EQ("this is id 4", data);
+ ASSERT_TRUE(pack.HasResource(6));
+ ASSERT_TRUE(pack.GetStringPiece(6, &data));
+ EXPECT_EQ("this is id 6", data);
+
+ // Try reading zero-length data blobs, just in case.
+ ASSERT_TRUE(pack.GetStringPiece(1, &data));
+ EXPECT_EQ(0U, data.length());
+ ASSERT_TRUE(pack.GetStringPiece(10, &data));
+ EXPECT_EQ("this is id 4", data);
+
+ // Try looking up an invalid key.
+ ASSERT_FALSE(pack.HasResource(140));
+ ASSERT_FALSE(pack.GetStringPiece(140, &data));
+}
+
INSTANTIATE_TEST_CASE_P(WriteBINARY, DataPackTest, ::testing::Values(
DataPack::BINARY));
INSTANTIATE_TEST_CASE_P(WriteUTF8, DataPackTest, ::testing::Values(
@@ -228,8 +249,8 @@ TEST(DataPackTest, ModifiedWhileUsed) {
dir.GetPath().Append(FILE_PATH_LITERAL("sample.pak"));
// Dump contents into the pak file.
- ASSERT_EQ(base::WriteFile(data_path, kSamplePakContents, kSamplePakSize),
- static_cast<int>(kSamplePakSize));
+ ASSERT_EQ(base::WriteFile(data_path, kSamplePakContentsV4, kSamplePakSizeV4),
+ static_cast<int>(kSamplePakSizeV4));
base::File file(data_path, base::File::FLAG_OPEN | base::File::FLAG_READ);
ASSERT_TRUE(file.IsValid());
diff --git a/chromium/ui/base/resource/resource_bundle.cc b/chromium/ui/base/resource/resource_bundle.cc
index 372d3302e13..4f823477883 100644
--- a/chromium/ui/base/resource/resource_bundle.cc
+++ b/chromium/ui/base/resource/resource_bundle.cc
@@ -707,7 +707,7 @@ void ResourceBundle::ReloadFonts() {
}
ScaleFactor ResourceBundle::GetMaxScaleFactor() const {
-#if defined(OS_CHROMEOS) || defined(OS_WIN) || defined(OS_LINUX)
+#if defined(OS_WIN) || defined(OS_LINUX)
return max_scale_factor_;
#else
return GetSupportedScaleFactors().back();
@@ -762,8 +762,7 @@ void ResourceBundle::InitSharedInstance(Delegate* delegate) {
} else {
supported_scale_factors.push_back(SCALE_FACTOR_100P);
}
-#elif defined(OS_MACOSX) || defined(OS_CHROMEOS) || defined(OS_LINUX) || \
- defined(OS_WIN)
+#elif defined(OS_MACOSX) || defined(OS_LINUX) || defined(OS_WIN)
supported_scale_factors.push_back(SCALE_FACTOR_200P);
#endif
ui::SetSupportedScaleFactors(supported_scale_factors);
diff --git a/chromium/ui/base/resource/resource_bundle_unittest.cc b/chromium/ui/base/resource/resource_bundle_unittest.cc
index df11f1afddb..363a0e9d03d 100644
--- a/chromium/ui/base/resource/resource_bundle_unittest.cc
+++ b/chromium/ui/base/resource/resource_bundle_unittest.cc
@@ -23,6 +23,7 @@
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/base/layout.h"
#include "ui/base/resource/data_pack.h"
+#include "ui/base/resource/data_pack_literal.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/image/image_skia.h"
@@ -38,14 +39,6 @@ using ::testing::Return;
using ::testing::ReturnArg;
namespace ui {
-
-extern const char kSamplePakContents[];
-extern const size_t kSamplePakSize;
-extern const char kSamplePakContents2x[];
-extern const size_t kSamplePakSize2x;
-extern const char kEmptyPakContents[];
-extern const size_t kEmptyPakSize;
-
namespace {
const unsigned char kPngMagic[8] = { 0x89, 'P', 'N', 'G', 13, 10, 26, 10 };
@@ -416,8 +409,8 @@ TEST_F(ResourceBundleImageTest, GetRawDataResource) {
dir_path().Append(FILE_PATH_LITERAL("sample_2x.pak"));
// Dump contents into the pak files.
- ASSERT_EQ(base::WriteFile(data_path, kSamplePakContents,
- kSamplePakSize), static_cast<int>(kSamplePakSize));
+ ASSERT_EQ(base::WriteFile(data_path, kSamplePakContentsV4, kSamplePakSizeV4),
+ static_cast<int>(kSamplePakSizeV4));
ASSERT_EQ(base::WriteFile(data_2x_path, kSamplePakContents2x,
kSamplePakSize2x), static_cast<int>(kSamplePakSize2x));
diff --git a/chromium/ui/base/ui_base_switches.cc b/chromium/ui/base/ui_base_switches.cc
index ed2ef37c03f..6681787be91 100644
--- a/chromium/ui/base/ui_base_switches.cc
+++ b/chromium/ui/base/ui_base_switches.cc
@@ -5,6 +5,16 @@
#include "build/build_config.h"
#include "ui/base/ui_base_switches.h"
+namespace features {
+
+#if defined(OS_WIN)
+// Enables stylus appearing as touch when in contact with digitizer.
+const base::Feature kDirectManipulationStylus = {
+ "DirectManipulationStylus", base::FEATURE_ENABLED_BY_DEFAULT};
+#endif // defined(OS_WIN)
+
+} // namespace features
+
namespace switches {
#if defined(OS_MACOSX) && !defined(OS_IOS)
@@ -31,6 +41,9 @@ const char kDisableMergeKeyCharEvents[] = "disable-merge-key-char-events";
const char kEnableMergeKeyCharEvents[] = "enable-merge-key-char-events";
#endif
+// Disables layer-edge anti-aliasing in the compositor.
+const char kDisableCompositedAntialiasing[] = "disable-composited-antialiasing";
+
// Disables use of DWM composition for top level windows.
const char kDisableDwmComposition[] = "disable-dwm-composition";
@@ -43,6 +56,13 @@ const char kDisableTouchDragDrop[] = "disable-touch-drag-drop";
// Enables touch event based drag and drop.
const char kEnableTouchDragDrop[] = "enable-touch-drag-drop";
+// TODO(dcastagna): Draw debug quad borders only when it is actually
+// an overlay candidate.
+// Renders a border around GL composited overlay candidate quads to
+// help debug and study overlay support.
+const char kGlCompositedOverlayCandidateQuadBorder[] =
+ "gl-composited-overlay-candidate-quad-border";
+
// The language file that we want to try to open. Of the form
// language[-country] where language is the 2 letter code from ISO-639.
const char kLang[] = "lang";
@@ -79,4 +99,33 @@ const char kDisableNewVirtualKeyboardBehavior[] =
// throughout Chrome (not just top Chrome).
const char kExtendMdToSecondaryUi[] = "secondary-ui-md";
+// Disable partial swap which is needed for some OpenGL drivers / emulators.
+const char kUIDisablePartialSwap[] = "ui-disable-partial-swap";
+
+// Visualize overdraw by color-coding elements based on if they have other
+// elements drawn underneath. This is good for showing where the UI might be
+// doing more rendering work than necessary. The colors are hinting at the
+// amount of overdraw on your screen for each pixel, as follows:
+//
+// True color: No overdraw.
+// Blue: Overdrawn once.
+// Green: Overdrawn twice.
+// Pink: Overdrawn three times.
+// Red: Overdrawn four or more times.
+const char kShowOverdrawFeedback[] = "show-overdraw-feedback";
+
+// Use SkiaRenderer instead of GLRenderer for direct rendering.
+const char kUseSkiaRenderer[] = "use-skia-renderer";
+
+// Disable re-use of non-exact resources to fulfill ResourcePool requests.
+// Intended only for use in layout or pixel tests to reduce noise.
+const char kDisallowNonExactResourceReuse[] =
+ "disallow-non-exact-resource-reuse";
+
+// Re-draw everything multiple times to simulate a much slower machine.
+// Give a slow down factor to cause renderer to take that many times longer to
+// complete, such as --slow-down-compositing-scale-factor=2.
+const char kSlowDownCompositingScaleFactor[] =
+ "slow-down-compositing-scale-factor";
+
} // namespace switches
diff --git a/chromium/ui/base/ui_base_switches.h b/chromium/ui/base/ui_base_switches.h
index 69e8cc1ee17..7a7d35865d0 100644
--- a/chromium/ui/base/ui_base_switches.h
+++ b/chromium/ui/base/ui_base_switches.h
@@ -8,9 +8,18 @@
#define UI_BASE_UI_BASE_SWITCHES_H_
#include "base/compiler_specific.h"
+#include "base/feature_list.h"
#include "build/build_config.h"
#include "ui/base/ui_base_export.h"
+namespace features {
+
+#if defined(OS_WIN)
+UI_BASE_EXPORT extern const base::Feature kDirectManipulationStylus;
+#endif // defined(OS_WIN)
+
+} // namespace features
+
namespace switches {
#if defined(OS_MACOSX) && !defined(OS_IOS)
@@ -25,21 +34,29 @@ UI_BASE_EXPORT extern const char kDisableMergeKeyCharEvents[];
UI_BASE_EXPORT extern const char kEnableMergeKeyCharEvents[];
#endif
+UI_BASE_EXPORT extern const char kDisableCompositedAntialiasing[];
UI_BASE_EXPORT extern const char kDisableDwmComposition[];
UI_BASE_EXPORT extern const char kDisableNewVirtualKeyboardBehavior[];
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 kExtendMdToSecondaryUi[];
+UI_BASE_EXPORT extern const char kGlCompositedOverlayCandidateQuadBorder[];
UI_BASE_EXPORT extern const char kLang[];
UI_BASE_EXPORT extern const char kMaterialDesignInkDropAnimationSpeed[];
UI_BASE_EXPORT extern const char kMaterialDesignInkDropAnimationSpeedFast[];
UI_BASE_EXPORT extern const char kMaterialDesignInkDropAnimationSpeedSlow[];
-
+UI_BASE_EXPORT extern const char kShowOverdrawFeedback[];
+UI_BASE_EXPORT extern const char kSlowDownCompositingScaleFactor[];
UI_BASE_EXPORT extern const char kTopChromeMD[];
UI_BASE_EXPORT extern const char kTopChromeMDMaterial[];
UI_BASE_EXPORT extern const char kTopChromeMDMaterialHybrid[];
UI_BASE_EXPORT extern const char kTopChromeMDNonMaterial[];
-UI_BASE_EXPORT extern const char kExtendMdToSecondaryUi[];
+UI_BASE_EXPORT extern const char kUIDisablePartialSwap[];
+UI_BASE_EXPORT extern const char kUseSkiaRenderer[];
+
+// Test related.
+UI_BASE_EXPORT extern const char kDisallowNonExactResourceReuse[];
} // namespace switches
diff --git a/chromium/ui/base/ui_features.gni b/chromium/ui/base/ui_features.gni
index 2dca6a502ca..186dc04160d 100644
--- a/chromium/ui/base/ui_features.gni
+++ b/chromium/ui/base/ui_features.gni
@@ -13,6 +13,9 @@ declare_args() {
# Whether the platform provides a native accessibility toolkit.
has_native_accessibility = use_atk || is_win || is_mac
+
+ # Whether the message center should be included for displaying notifications.
+ enable_message_center = is_win || is_mac || is_linux || is_chromeos
}
enable_hidpi = is_mac || is_win || is_linux
diff --git a/chromium/ui/base/user_activity/user_activity_detector_unittest.cc b/chromium/ui/base/user_activity/user_activity_detector_unittest.cc
index 0b9b7608d6a..b2decd61f41 100644
--- a/chromium/ui/base/user_activity/user_activity_detector_unittest.cc
+++ b/chromium/ui/base/user_activity/user_activity_detector_unittest.cc
@@ -92,8 +92,7 @@ TEST_F(UserActivityDetectorTest, Basic) {
ui::KeyEvent key_event(ui::ET_KEY_PRESSED, ui::VKEY_A, ui::EF_NONE);
OnEvent(&key_event);
EXPECT_FALSE(key_event.handled());
- EXPECT_EQ(now_.ToInternalValue(),
- detector_->last_activity_time().ToInternalValue());
+ EXPECT_EQ(now_, detector_->last_activity_time());
EXPECT_EQ(1, observer_->num_invocations());
observer_->reset_stats();
@@ -104,8 +103,7 @@ TEST_F(UserActivityDetectorTest, Basic) {
ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
OnEvent(&mouse_event);
EXPECT_FALSE(mouse_event.handled());
- EXPECT_EQ(now_.ToInternalValue(),
- detector_->last_activity_time().ToInternalValue());
+ EXPECT_EQ(now_, detector_->last_activity_time());
EXPECT_EQ(1, observer_->num_invocations());
observer_->reset_stats();
@@ -115,8 +113,7 @@ TEST_F(UserActivityDetectorTest, Basic) {
detector_->OnDisplayPowerChanging();
OnEvent(&mouse_event);
EXPECT_FALSE(mouse_event.handled());
- EXPECT_EQ(time_before_ignore.ToInternalValue(),
- detector_->last_activity_time().ToInternalValue());
+ EXPECT_EQ(time_before_ignore, detector_->last_activity_time());
EXPECT_EQ(0, observer_->num_invocations());
observer_->reset_stats();
@@ -126,8 +123,7 @@ TEST_F(UserActivityDetectorTest, Basic) {
AdvanceTime(kIgnoreMouseTime / 2);
OnEvent(&mouse_event);
EXPECT_FALSE(mouse_event.handled());
- EXPECT_EQ(time_before_ignore.ToInternalValue(),
- detector_->last_activity_time().ToInternalValue());
+ EXPECT_EQ(time_before_ignore, detector_->last_activity_time());
EXPECT_EQ(0, observer_->num_invocations());
observer_->reset_stats();
@@ -135,8 +131,7 @@ TEST_F(UserActivityDetectorTest, Basic) {
AdvanceTime(std::max(kIgnoreMouseTime, advance_delta));
OnEvent(&mouse_event);
EXPECT_FALSE(mouse_event.handled());
- EXPECT_EQ(now_.ToInternalValue(),
- detector_->last_activity_time().ToInternalValue());
+ EXPECT_EQ(now_, detector_->last_activity_time());
EXPECT_EQ(1, observer_->num_invocations());
observer_->reset_stats();
@@ -146,8 +141,7 @@ TEST_F(UserActivityDetectorTest, Basic) {
ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, 0));
OnEvent(&touch_event);
EXPECT_FALSE(touch_event.handled());
- EXPECT_EQ(now_.ToInternalValue(),
- detector_->last_activity_time().ToInternalValue());
+ EXPECT_EQ(now_, detector_->last_activity_time());
EXPECT_EQ(1, observer_->num_invocations());
observer_->reset_stats();
@@ -156,8 +150,7 @@ TEST_F(UserActivityDetectorTest, Basic) {
ui::GestureEventDetails(ui::ET_GESTURE_TAP));
OnEvent(&gesture_event);
EXPECT_FALSE(gesture_event.handled());
- EXPECT_EQ(now_.ToInternalValue(),
- detector_->last_activity_time().ToInternalValue());
+ EXPECT_EQ(now_, detector_->last_activity_time());
EXPECT_EQ(1, observer_->num_invocations());
observer_->reset_stats();
}
@@ -204,8 +197,7 @@ TEST_F(UserActivityDetectorTest, IgnoreSyntheticMouseEvents) {
ui::EF_NONE);
OnEvent(&mouse_event);
EXPECT_FALSE(mouse_event.handled());
- EXPECT_EQ(base::TimeTicks().ToInternalValue(),
- detector_->last_activity_time().ToInternalValue());
+ EXPECT_EQ(base::TimeTicks(), detector_->last_activity_time());
EXPECT_EQ(0, observer_->num_invocations());
}
diff --git a/chromium/ui/base/webui/OWNERS b/chromium/ui/base/webui/OWNERS
index 89558c26a0f..918baa1330f 100644
--- a/chromium/ui/base/webui/OWNERS
+++ b/chromium/ui/base/webui/OWNERS
@@ -1,5 +1,3 @@
file://ui/webui/PLATFORM_OWNERS
-dschuyler@chromium.org
-
# COMPONENT: UI>Browser>WebUI
diff --git a/chromium/ui/base/win/accessibility_misc_utils.h b/chromium/ui/base/win/accessibility_misc_utils.h
index bb5befce2b3..23c9ca97302 100644
--- a/chromium/ui/base/win/accessibility_misc_utils.h
+++ b/chromium/ui/base/win/accessibility_misc_utils.h
@@ -17,7 +17,7 @@ namespace win {
// UIA Text provider implementation for edit controls.
class UI_BASE_EXPORT UIATextProvider
- : public NON_EXPORTED_BASE(CComObjectRootEx<CComMultiThreadModel>),
+ : public CComObjectRootEx<CComMultiThreadModel>,
public IValueProvider,
public ITextProvider {
public:
diff --git a/chromium/ui/base/win/shell.cc b/chromium/ui/base/win/shell.cc
index dd8459e9b2e..cd82678bd9e 100644
--- a/chromium/ui/base/win/shell.cc
+++ b/chromium/ui/base/win/shell.cc
@@ -6,8 +6,10 @@
#include <dwmapi.h>
#include <shlobj.h> // Must be before propkey.
+
#include <propkey.h>
#include <shellapi.h>
+#include <wrl/client.h>
#include "base/command_line.h"
#include "base/debug/alias.h"
@@ -17,7 +19,6 @@
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/threading/thread_restrictions.h"
-#include "base/win/scoped_comptr.h"
#include "base/win/win_util.h"
#include "ui/base/ui_base_switches.h"
@@ -98,7 +99,7 @@ bool OpenFolderViaShell(const base::FilePath& full_path) {
bool PreventWindowFromPinning(HWND hwnd) {
DCHECK(hwnd);
- base::win::ScopedComPtr<IPropertyStore> pps;
+ Microsoft::WRL::ComPtr<IPropertyStore> pps;
if (FAILED(
SHGetPropertyStoreForWindow(hwnd, IID_PPV_ARGS(pps.GetAddressOf()))))
return false;
@@ -117,7 +118,7 @@ void SetAppDetailsForWindow(const base::string16& app_id,
HWND hwnd) {
DCHECK(hwnd);
- base::win::ScopedComPtr<IPropertyStore> pps;
+ Microsoft::WRL::ComPtr<IPropertyStore> pps;
if (FAILED(
SHGetPropertyStoreForWindow(hwnd, IID_PPV_ARGS(pps.GetAddressOf()))))
return;
@@ -167,7 +168,7 @@ void SetRelaunchDetailsForWindow(const base::string16& relaunch_command,
void ClearWindowPropertyStore(HWND hwnd) {
DCHECK(hwnd);
- base::win::ScopedComPtr<IPropertyStore> pps;
+ Microsoft::WRL::ComPtr<IPropertyStore> pps;
if (FAILED(
SHGetPropertyStoreForWindow(hwnd, IID_PPV_ARGS(pps.GetAddressOf()))))
return;
@@ -177,13 +178,18 @@ void ClearWindowPropertyStore(HWND hwnd) {
return;
PROPVARIANT empty_property_variant = {};
- for (DWORD i = 0; i < property_count; i++) {
+ for (DWORD i = property_count; i > 0; i--) {
PROPERTYKEY key;
- if (SUCCEEDED(pps->GetAt(i, &key)))
+ if (SUCCEEDED(pps->GetAt(i - 1, &key))) {
+ // Removes the value from |pps|'s array.
pps->SetValue(key, empty_property_variant);
+ }
}
+ if (FAILED(pps->Commit()))
+ return;
- pps->Commit();
+ // Verify none of the keys are leaking.
+ DCHECK(FAILED(pps->GetCount(&property_count)) || property_count == 0);
}
bool IsAeroGlassEnabled() {
diff --git a/chromium/ui/base/x/x11_util.cc b/chromium/ui/base/x/x11_util.cc
index f97eca3f7e9..dbb8cc534e3 100644
--- a/chromium/ui/base/x/x11_util.cc
+++ b/chromium/ui/base/x/x11_util.cc
@@ -391,12 +391,8 @@ int CoalescePendingMotionEvents(const XEvent* xev, XEvent* last_event) {
break;
}
- if (event_type == XI_Motion && num_coalesced > 0) {
- base::TimeDelta delta = ui::EventTimeFromNative(last_event) -
- ui::EventTimeFromNative(const_cast<XEvent*>(xev));
+ if (event_type == XI_Motion && num_coalesced > 0)
UMA_HISTOGRAM_COUNTS_10000("Event.CoalescedCount.Mouse", num_coalesced);
- UMA_HISTOGRAM_TIMES("Event.CoalescedLatency.Mouse", delta);
- }
return num_coalesced;
}
diff --git a/chromium/ui/chromeos/BUILD.gn b/chromium/ui/chromeos/BUILD.gn
index e83d1d043a7..0b7d6c0cc4e 100644
--- a/chromium/ui/chromeos/BUILD.gn
+++ b/chromium/ui/chromeos/BUILD.gn
@@ -11,6 +11,8 @@ component("chromeos") {
sources = [
"accelerometer/accelerometer_util.cc",
"accelerometer/accelerometer_util.h",
+ "devicetype_utils.cc",
+ "devicetype_utils.h",
"ime/candidate_view.cc",
"ime/candidate_view.h",
"ime/candidate_window_constants.h",
diff --git a/chromium/ui/compositor/BUILD.gn b/chromium/ui/compositor/BUILD.gn
index a992c2722fe..82793dca686 100644
--- a/chromium/ui/compositor/BUILD.gn
+++ b/chromium/ui/compositor/BUILD.gn
@@ -20,21 +20,19 @@ component("compositor") {
"compositor.cc",
"compositor.h",
"compositor_animation_observer.h",
- "compositor_constants.h",
"compositor_export.h",
"compositor_lock.cc",
"compositor_lock.h",
"compositor_observer.h",
"compositor_switches.cc",
"compositor_switches.h",
- "compositor_util.cc",
- "compositor_util.h",
"compositor_vsync_manager.cc",
"compositor_vsync_manager.h",
"debug_utils.cc",
"debug_utils.h",
"dip_util.cc",
"dip_util.h",
+ "external_begin_frame_client.h",
"float_animation_curve_adapter.cc",
"float_animation_curve_adapter.h",
"layer.cc",
@@ -86,13 +84,12 @@ component("compositor") {
"//cc",
"//cc/animation",
"//cc/paint",
- "//cc/surfaces",
- "//cc/surfaces:surfaces",
"//components/viz/common",
"//components/viz/host",
"//components/viz/service",
"//gpu/command_buffer/common",
"//skia",
+ "//ui/base",
"//ui/display",
"//ui/gfx",
"//ui/gfx/animation",
@@ -156,9 +153,9 @@ static_library("test_support") {
"//base/test:test_support",
"//cc",
"//cc:test_support",
- "//cc/surfaces",
"//components/viz/host",
"//components/viz/service",
+ "//components/viz/test:test_support",
"//gpu/command_buffer/client:gles2_c_lib",
"//gpu/command_buffer/client:gles2_implementation",
"//gpu/command_buffer/common:gles2_utils",
@@ -211,8 +208,9 @@ test("compositor_unittests") {
"//base/test:test_support",
"//cc",
"//cc:test_support",
- "//cc/surfaces",
"//components/viz/common",
+ "//components/viz/service",
+ "//components/viz/test:test_support",
"//mojo/edk/system",
"//skia",
"//testing/gmock",
diff --git a/chromium/ui/compositor/DEPS b/chromium/ui/compositor/DEPS
index 75b24eca257..69f116388f5 100644
--- a/chromium/ui/compositor/DEPS
+++ b/chromium/ui/compositor/DEPS
@@ -18,5 +18,8 @@ include_rules = [
specific_include_rules = {
"run_all_unittests\.cc": [
"+mojo/edk/embedder",
- ]
+ ],
+ ".*_(unit|pixel|perf)test.*\.cc": [
+ "+components/viz/test",
+ ],
}
diff --git a/chromium/ui/compositor/canvas_painter.cc b/chromium/ui/compositor/canvas_painter.cc
index a12e85ab06e..864d8b03e84 100644
--- a/chromium/ui/compositor/canvas_painter.cc
+++ b/chromium/ui/compositor/canvas_painter.cc
@@ -11,13 +11,17 @@ namespace ui {
CanvasPainter::CanvasPainter(SkBitmap* output,
const gfx::Size& paint_size,
float raster_scale,
- SkColor clear_color)
+ SkColor clear_color,
+ bool is_pixel_canvas)
: output_(output),
paint_size_(paint_size),
raster_scale_(raster_scale),
clear_color_(clear_color),
list_(new cc::DisplayItemList),
- context_(list_.get(), raster_scale, gfx::Rect(paint_size_)) {}
+ context_(list_.get(),
+ raster_scale,
+ gfx::Rect(paint_size_),
+ is_pixel_canvas) {}
CanvasPainter::~CanvasPainter() {
gfx::Size pixel_size = gfx::ScaleToCeiledSize(paint_size_, raster_scale_);
diff --git a/chromium/ui/compositor/canvas_painter.h b/chromium/ui/compositor/canvas_painter.h
index 1db206f36b0..da44d7bb166 100644
--- a/chromium/ui/compositor/canvas_painter.h
+++ b/chromium/ui/compositor/canvas_painter.h
@@ -29,7 +29,8 @@ class COMPOSITOR_EXPORT CanvasPainter {
CanvasPainter(SkBitmap* output,
const gfx::Size& paint_size,
float raster_scale,
- SkColor clear_color);
+ SkColor clear_color,
+ bool is_pixel_canvas);
~CanvasPainter();
const PaintContext& context() const { return context_; }
diff --git a/chromium/ui/compositor/clip_recorder.cc b/chromium/ui/compositor/clip_recorder.cc
index 5f8133f2abf..77acf0f7cfc 100644
--- a/chromium/ui/compositor/clip_recorder.cc
+++ b/chromium/ui/compositor/clip_recorder.cc
@@ -21,8 +21,8 @@ ClipRecorder::~ClipRecorder() {
for (int i = 0; i < num_closers_; ++i) {
// Each restore is part of a separate visual rect, so gets its own
// StartPaint/EndPaintOfPairedEnd.
- cc::PaintOpBuffer* buffer = context_.list_->StartPaint();
- buffer->push<cc::RestoreOp>();
+ context_.list_->StartPaint();
+ context_.list_->push<cc::RestoreOp>();
context_.list_->EndPaintOfPairedEnd();
}
}
@@ -30,10 +30,10 @@ ClipRecorder::~ClipRecorder() {
void ClipRecorder::ClipRect(const gfx::Rect& clip_rect) {
bool antialias = false;
- cc::PaintOpBuffer* buffer = context_.list_->StartPaint();
- buffer->push<cc::SaveOp>();
- buffer->push<cc::ClipRectOp>(gfx::RectToSkRect(clip_rect),
- SkClipOp::kIntersect, antialias);
+ context_.list_->StartPaint();
+ context_.list_->push<cc::SaveOp>();
+ context_.list_->push<cc::ClipRectOp>(gfx::RectToSkRect(clip_rect),
+ SkClipOp::kIntersect, antialias);
context_.list_->EndPaintOfPairedBegin();
++num_closers_;
}
@@ -41,9 +41,10 @@ void ClipRecorder::ClipRect(const gfx::Rect& clip_rect) {
void ClipRecorder::ClipPath(const gfx::Path& clip_path) {
bool antialias = false;
- cc::PaintOpBuffer* buffer = context_.list_->StartPaint();
- buffer->push<cc::SaveOp>();
- buffer->push<cc::ClipPathOp>(clip_path, SkClipOp::kIntersect, antialias);
+ context_.list_->StartPaint();
+ context_.list_->push<cc::SaveOp>();
+ context_.list_->push<cc::ClipPathOp>(clip_path, SkClipOp::kIntersect,
+ antialias);
context_.list_->EndPaintOfPairedBegin();
++num_closers_;
}
@@ -51,9 +52,10 @@ void ClipRecorder::ClipPath(const gfx::Path& clip_path) {
void ClipRecorder::ClipPathWithAntiAliasing(const gfx::Path& clip_path) {
bool antialias = true;
- cc::PaintOpBuffer* buffer = context_.list_->StartPaint();
- buffer->push<cc::SaveOp>();
- buffer->push<cc::ClipPathOp>(clip_path, SkClipOp::kIntersect, antialias);
+ context_.list_->StartPaint();
+ context_.list_->push<cc::SaveOp>();
+ context_.list_->push<cc::ClipPathOp>(clip_path, SkClipOp::kIntersect,
+ antialias);
context_.list_->EndPaintOfPairedBegin();
++num_closers_;
}
diff --git a/chromium/ui/compositor/compositing_recorder.cc b/chromium/ui/compositor/compositing_recorder.cc
index 4270342a13a..ab4bf8826ab 100644
--- a/chromium/ui/compositor/compositing_recorder.cc
+++ b/chromium/ui/compositor/compositing_recorder.cc
@@ -19,9 +19,9 @@ CompositingRecorder::CompositingRecorder(const PaintContext& context,
if (!saved_)
return;
- cc::PaintOpBuffer* buffer = context_.list_->StartPaint();
- buffer->push<cc::SaveLayerAlphaOp>(nullptr, alpha,
- !lcd_text_requires_opaque_layer);
+ context_.list_->StartPaint();
+ context_.list_->push<cc::SaveLayerAlphaOp>(nullptr, alpha,
+ !lcd_text_requires_opaque_layer);
context_.list_->EndPaintOfPairedBegin();
}
@@ -29,8 +29,8 @@ CompositingRecorder::~CompositingRecorder() {
if (!saved_)
return;
- cc::PaintOpBuffer* buffer = context_.list_->StartPaint();
- buffer->push<cc::RestoreOp>();
+ context_.list_->StartPaint();
+ context_.list_->push<cc::RestoreOp>();
context_.list_->EndPaintOfPairedEnd();
}
diff --git a/chromium/ui/compositor/compositor.cc b/chromium/ui/compositor/compositor.cc
index 70eab90261e..68e7df216cd 100644
--- a/chromium/ui/compositor/compositor.cc
+++ b/chromium/ui/compositor/compositor.cc
@@ -27,21 +27,24 @@
#include "cc/base/switches.h"
#include "cc/input/input_handler.h"
#include "cc/layers/layer.h"
-#include "cc/output/begin_frame_args.h"
#include "cc/output/latency_info_swap_promise.h"
-#include "cc/scheduler/begin_frame_source.h"
#include "cc/trees/layer_tree_host.h"
#include "cc/trees/layer_tree_settings.h"
+#include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "components/viz/common/frame_sinks/begin_frame_source.h"
#include "components/viz/common/gpu/context_provider.h"
-#include "components/viz/common/quads/resource_format.h"
+#include "components/viz/common/resources/resource_format.h"
#include "components/viz/common/resources/resource_settings.h"
#include "components/viz/common/surfaces/local_surface_id_allocator.h"
+#include "components/viz/host/host_frame_sink_manager.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
#include "third_party/skia/include/core/SkBitmap.h"
+#include "ui/base/ui_base_switches.h"
#include "ui/compositor/compositor_observer.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/compositor/compositor_vsync_manager.h"
#include "ui/compositor/dip_util.h"
+#include "ui/compositor/external_begin_frame_client.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animator_collection.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
@@ -57,21 +60,27 @@ Compositor::Compositor(const viz::FrameSinkId& frame_sink_id,
ui::ContextFactory* context_factory,
ui::ContextFactoryPrivate* context_factory_private,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- bool enable_surface_synchronization)
+ bool enable_surface_synchronization,
+ bool enable_pixel_canvas,
+ bool external_begin_frames_enabled,
+ bool force_software_compositor)
: context_factory_(context_factory),
context_factory_private_(context_factory_private),
frame_sink_id_(frame_sink_id),
task_runner_(task_runner),
vsync_manager_(new CompositorVSyncManager()),
+ external_begin_frames_enabled_(external_begin_frames_enabled),
+ force_software_compositor_(force_software_compositor),
layer_animator_collection_(this),
scheduled_timeout_(base::TimeTicks()),
allow_locks_to_extend_timeout_(false),
+ is_pixel_canvas_(enable_pixel_canvas),
weak_ptr_factory_(this),
lock_timeout_weak_ptr_factory_(this) {
if (context_factory_private) {
- context_factory_private->GetFrameSinkManager()
- ->surface_manager()
- ->RegisterFrameSinkId(frame_sink_id_);
+ auto* host_frame_sink_manager =
+ context_factory_private_->GetHostFrameSinkManager();
+ host_frame_sink_manager->RegisterFrameSinkId(frame_sink_id_, this);
}
root_web_layer_ = cc::Layer::Create();
@@ -162,7 +171,10 @@ Compositor::Compositor(const viz::FrameSinkId& frame_sink_id,
gpu::MemoryAllocation::CUTOFF_ALLOW_NICE_TO_HAVE;
settings.disallow_non_exact_resource_reuse =
- command_line->HasSwitch(cc::switches::kDisallowNonExactResourceReuse);
+ command_line->HasSwitch(switches::kDisallowNonExactResourceReuse);
+
+ settings.wait_for_all_pipeline_stages_before_draw =
+ command_line->HasSwitch(cc::switches::kRunAllCompositorStagesBeforeDraw);
base::TimeTicks before_create = base::TimeTicks::Now();
@@ -213,12 +225,14 @@ Compositor::~Compositor() {
context_factory_->RemoveCompositor(this);
if (context_factory_private_) {
- auto* manager = context_factory_private_->GetFrameSinkManager();
+ auto* host_frame_sink_manager =
+ context_factory_private_->GetHostFrameSinkManager();
for (auto& client : child_frame_sinks_) {
DCHECK(client.is_valid());
- manager->UnregisterFrameSinkHierarchy(frame_sink_id_, client);
+ host_frame_sink_manager->UnregisterFrameSinkHierarchy(frame_sink_id_,
+ client);
}
- manager->surface_manager()->InvalidateFrameSinkId(frame_sink_id_);
+ host_frame_sink_manager->InvalidateFrameSinkId(frame_sink_id_);
}
}
@@ -229,8 +243,8 @@ bool Compositor::IsForSubframe() {
void Compositor::AddFrameSink(const viz::FrameSinkId& frame_sink_id) {
if (!context_factory_private_)
return;
- context_factory_private_->GetFrameSinkManager()->RegisterFrameSinkHierarchy(
- frame_sink_id_, frame_sink_id);
+ context_factory_private_->GetHostFrameSinkManager()
+ ->RegisterFrameSinkHierarchy(frame_sink_id_, frame_sink_id);
child_frame_sinks_.insert(frame_sink_id);
}
@@ -240,8 +254,8 @@ void Compositor::RemoveFrameSink(const viz::FrameSinkId& frame_sink_id) {
auto it = child_frame_sinks_.find(frame_sink_id);
DCHECK(it != child_frame_sinks_.end());
DCHECK(it->is_valid());
- context_factory_private_->GetFrameSinkManager()->UnregisterFrameSinkHierarchy(
- frame_sink_id_, *it);
+ context_factory_private_->GetHostFrameSinkManager()
+ ->UnregisterFrameSinkHierarchy(frame_sink_id_, *it);
child_frame_sinks_.erase(it);
}
@@ -312,11 +326,13 @@ void Compositor::SetLatencyInfo(const ui::LatencyInfo& latency_info) {
host_->QueueSwapPromise(std::move(swap_promise));
}
-void Compositor::SetScaleAndSize(float scale, const gfx::Size& size_in_pixel) {
+void Compositor::SetScaleAndSize(float scale,
+ const gfx::Size& size_in_pixel,
+ const viz::LocalSurfaceId& local_surface_id) {
DCHECK_GT(scale, 0);
if (!size_in_pixel.IsEmpty()) {
size_ = size_in_pixel;
- host_->SetViewportSize(size_in_pixel);
+ host_->SetViewportSize(size_in_pixel, local_surface_id);
root_web_layer_->SetBounds(size_in_pixel);
// TODO(fsamuel): Get rid of ContextFactoryPrivate.
if (context_factory_private_)
@@ -325,19 +341,17 @@ void Compositor::SetScaleAndSize(float scale, const gfx::Size& size_in_pixel) {
if (device_scale_factor_ != scale) {
device_scale_factor_ = scale;
host_->SetDeviceScaleFactor(scale);
+ if (is_pixel_canvas())
+ host_->SetRecordingScaleFactor(scale);
if (root_layer_)
root_layer_->OnDeviceScaleFactorChanged(scale);
}
}
void Compositor::SetDisplayColorSpace(const gfx::ColorSpace& color_space) {
- blending_color_space_ = color_space;
- output_color_space_ = blending_color_space_;
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableHDR)) {
- blending_color_space_ = gfx::ColorSpace::CreateExtendedSRGB();
- output_color_space_ = gfx::ColorSpace::CreateSCRGBLinear();
- }
- host_->SetRasterColorSpace(color_space.GetParametricApproximation());
+ output_color_space_ = color_space;
+ blending_color_space_ = output_color_space_.GetBlendingColorSpace();
+ host_->SetRasterColorSpace(output_color_space_.GetRasterColorSpace());
// Color space is reset when the output surface is lost, so this must also be
// updated then.
// TODO(fsamuel): Get rid of this.
@@ -392,7 +406,7 @@ void Compositor::SetDisplayVSyncParameters(base::TimeTicks timebase,
}
if (interval.is_zero()) {
// TODO(brianderson): We should not be receiving 0 intervals.
- interval = cc::BeginFrameArgs::DefaultInterval();
+ interval = viz::BeginFrameArgs::DefaultInterval();
}
DCHECK_GT(interval.InMillisecondsF(), 0);
refresh_rate_ =
@@ -433,6 +447,34 @@ scoped_refptr<CompositorVSyncManager> Compositor::vsync_manager() const {
return vsync_manager_;
}
+void Compositor::IssueExternalBeginFrame(const viz::BeginFrameArgs& args) {
+ DCHECK(external_begin_frames_enabled_);
+ if (context_factory_private_)
+ context_factory_private_->IssueExternalBeginFrame(this, args);
+}
+
+void Compositor::SetExternalBeginFrameClient(ExternalBeginFrameClient* client) {
+ DCHECK(external_begin_frames_enabled_);
+ external_begin_frame_client_ = client;
+ if (needs_external_begin_frames_)
+ external_begin_frame_client_->OnNeedsExternalBeginFrames(true);
+}
+
+void Compositor::OnDisplayDidFinishFrame(const viz::BeginFrameAck& ack) {
+ DCHECK(external_begin_frames_enabled_);
+ if (external_begin_frame_client_)
+ external_begin_frame_client_->OnDisplayDidFinishFrame(ack);
+}
+
+void Compositor::OnNeedsExternalBeginFrames(bool needs_begin_frames) {
+ DCHECK(external_begin_frames_enabled_);
+ if (external_begin_frame_client_) {
+ external_begin_frame_client_->OnNeedsExternalBeginFrames(
+ needs_begin_frames);
+ }
+ needs_external_begin_frames_ = needs_begin_frames;
+}
+
void Compositor::AddObserver(CompositorObserver* observer) {
observer_list_.AddObserver(observer);
}
@@ -460,7 +502,7 @@ bool Compositor::HasAnimationObserver(
return animation_observer_list_.HasObserver(observer);
}
-void Compositor::BeginMainFrame(const cc::BeginFrameArgs& args) {
+void Compositor::BeginMainFrame(const viz::BeginFrameArgs& args) {
DCHECK(!IsLocked());
for (auto& observer : animation_observer_list_)
observer.OnAnimationStep(args.frame_time);
@@ -517,6 +559,12 @@ void Compositor::DidSubmitCompositorFrame() {
observer.OnCompositingStarted(this, start_time);
}
+void Compositor::OnFirstSurfaceActivation(
+ const viz::SurfaceInfo& surface_info) {
+ // TODO(fsamuel): Once surface synchronization is turned on, the fallback
+ // surface should be set here.
+}
+
void Compositor::SetOutputIsSecure(bool output_is_secure) {
if (context_factory_private_)
context_factory_private_->SetOutputIsSecure(this, output_is_secure);
diff --git a/chromium/ui/compositor/compositor.h b/chromium/ui/compositor/compositor.h
index 163fbb01646..a3bc8cafc57 100644
--- a/chromium/ui/compositor/compositor.h
+++ b/chromium/ui/compositor/compositor.h
@@ -17,10 +17,12 @@
#include "base/single_thread_task_runner.h"
#include "base/time/time.h"
#include "build/build_config.h"
-#include "cc/output/begin_frame_args.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"
+#include "components/viz/common/surfaces/local_surface_id.h"
#include "components/viz/common/surfaces/surface_sequence.h"
+#include "components/viz/host/host_frame_sink_client.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/compositor/compositor_animation_observer.h"
#include "ui/compositor/compositor_export.h"
@@ -69,6 +71,7 @@ namespace ui {
class Compositor;
class CompositorVSyncManager;
+class ExternalBeginFrameClient;
class LatencyInfo;
class Layer;
class Reflector;
@@ -133,6 +136,8 @@ class COMPOSITOR_EXPORT ContextFactoryPrivate {
virtual void SetDisplayVSyncParameters(ui::Compositor* compositor,
base::TimeTicks timebase,
base::TimeDelta interval) = 0;
+ virtual void IssueExternalBeginFrame(ui::Compositor* compositor,
+ const viz::BeginFrameArgs& args) = 0;
virtual void SetOutputIsSecure(Compositor* compositor, bool secure) = 0;
};
@@ -179,16 +184,19 @@ class COMPOSITOR_EXPORT ContextFactory {
// displayable form of pixels comprising a single widget's contents. It draws an
// appropriately transformed texture for each transformed view in the widget's
// view hierarchy.
-class COMPOSITOR_EXPORT Compositor
- : NON_EXPORTED_BASE(public cc::LayerTreeHostClient),
- NON_EXPORTED_BASE(public cc::LayerTreeHostSingleThreadClient),
- NON_EXPORTED_BASE(public CompositorLockDelegate) {
+class COMPOSITOR_EXPORT Compositor : public cc::LayerTreeHostClient,
+ public cc::LayerTreeHostSingleThreadClient,
+ public CompositorLockDelegate,
+ public viz::HostFrameSinkClient {
public:
Compositor(const viz::FrameSinkId& frame_sink_id,
ui::ContextFactory* context_factory,
ui::ContextFactoryPrivate* context_factory_private,
scoped_refptr<base::SingleThreadTaskRunner> task_runner,
- bool enable_surface_synchronization);
+ bool enable_surface_synchronization,
+ bool enable_pixel_canvas,
+ bool external_begin_frames_enabled = false,
+ bool force_software_compositor = false);
~Compositor() override;
ui::ContextFactory* context_factory() { return context_factory_; }
@@ -227,6 +235,11 @@ class COMPOSITOR_EXPORT Compositor
// compositing layers on.
float device_scale_factor() const { return device_scale_factor_; }
+ // The color space of the device that this compositor is being displayed on.
+ const gfx::ColorSpace& output_color_space() const {
+ return output_color_space_;
+ }
+
// Where possible, draws are scissored to a damage region calculated from
// changes to layer properties. This bypasses that and indicates that
// the whole frame needs to be drawn.
@@ -243,7 +256,10 @@ class COMPOSITOR_EXPORT Compositor
void SetLatencyInfo(const LatencyInfo& latency_info);
// Sets the compositor's device scale factor and size.
- void SetScaleAndSize(float scale, const gfx::Size& size_in_pixel);
+ void SetScaleAndSize(
+ float scale,
+ const gfx::Size& size_in_pixel,
+ const viz::LocalSurfaceId& local_surface_id = viz::LocalSurfaceId());
// Set the output color profile into which this compositor should render.
void SetDisplayColorSpace(const gfx::ColorSpace& color_space);
@@ -291,6 +307,26 @@ class COMPOSITOR_EXPORT Compositor
// Returns the vsync manager for this compositor.
scoped_refptr<CompositorVSyncManager> vsync_manager() const;
+ bool external_begin_frames_enabled() {
+ return external_begin_frames_enabled_;
+ }
+
+ void SetExternalBeginFrameClient(ExternalBeginFrameClient* client);
+
+ // The ExternalBeginFrameClient calls this to issue a BeginFrame with the
+ // given |args|.
+ void IssueExternalBeginFrame(const viz::BeginFrameArgs& args);
+
+ // Called by the ContextFactory when a BeginFrame was completed by the Display
+ // if the enable_external_begin_frames setting is true.
+ void OnDisplayDidFinishFrame(const viz::BeginFrameAck& ack);
+
+ // Called by the ContextFactory to signal whether BeginFrames are needed by
+ // the compositor if the enable_external_begin_frames setting is true.
+ void OnNeedsExternalBeginFrames(bool needs_begin_frames);
+
+ bool force_software_compositor() { return force_software_compositor_; }
+
// Returns the main thread task runner this compositor uses. Users of the
// compositor generally shouldn't use this.
scoped_refptr<base::SingleThreadTaskRunner> task_runner() const {
@@ -330,7 +366,7 @@ class COMPOSITOR_EXPORT Compositor
// LayerTreeHostClient implementation.
void WillBeginMainFrame() override {}
void DidBeginMainFrame() override {}
- void BeginMainFrame(const cc::BeginFrameArgs& args) override;
+ void BeginMainFrame(const viz::BeginFrameArgs& args) override;
void BeginMainFrameNotExpectedSoon() override;
void BeginMainFrameNotExpectedUntil(base::TimeTicks time) override;
void UpdateLayerTreeHost() override;
@@ -356,6 +392,9 @@ class COMPOSITOR_EXPORT Compositor
void DidSubmitCompositorFrame() override;
void DidLoseLayerTreeFrameSink() override {}
+ // viz::HostFrameSinkClient implementation.
+ void OnFirstSurfaceActivation(const viz::SurfaceInfo& surface_info) override;
+
bool IsLocked() { return !active_locks_.empty(); }
void SetOutputIsSecure(bool output_is_secure);
@@ -375,6 +414,9 @@ class COMPOSITOR_EXPORT Compositor
allow_locks_to_extend_timeout_ = allowed;
}
+ // If true, all paint commands are recorded at pixel size instead of DIP.
+ bool is_pixel_canvas() const { return is_pixel_canvas_; }
+
private:
friend class base::RefCounted<Compositor>;
@@ -418,6 +460,12 @@ class COMPOSITOR_EXPORT Compositor
// The manager of vsync parameters for this compositor.
scoped_refptr<CompositorVSyncManager> vsync_manager_;
+ bool external_begin_frames_enabled_;
+ ExternalBeginFrameClient* external_begin_frame_client_ = nullptr;
+ bool needs_external_begin_frames_ = false;
+
+ const bool force_software_compositor_;
+
// The device scale factor of the monitor that this compositor is compositing
// layers on.
float device_scale_factor_ = 0.f;
@@ -435,6 +483,8 @@ class COMPOSITOR_EXPORT Compositor
base::TimeTicks scheduled_timeout_;
// If true, the |scheduled_timeout_| might be recalculated and extended.
bool allow_locks_to_extend_timeout_;
+ // If true, all paint commands are recorded at pixel size instead of DIP.
+ const bool is_pixel_canvas_;
base::WeakPtrFactory<Compositor> weak_ptr_factory_;
base::WeakPtrFactory<Compositor> lock_timeout_weak_ptr_factory_;
diff --git a/chromium/ui/compositor/compositor_constants.h b/chromium/ui/compositor/compositor_constants.h
deleted file mode 100644
index ef007b0ff7f..00000000000
--- a/chromium/ui/compositor/compositor_constants.h
+++ /dev/null
@@ -1,18 +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_COMPOSITOR_COMPOSITOR_CONSTANTS_H_
-#define UI_COMPOSITOR_COMPOSITOR_CONSTANTS_H_
-
-// This flag is used to work around a rendering bug in Windows where the
-// software surface becomes inconsistent with the hardware surface. This
-// happens in particular circumstances (Classic mode, Chrome using hardware
-// rendering, and the window on a secondary monitor) and when moving the mouse
-// over the window, Windows restores the GDI software surface underneath the
-// mouse, rather than the hardware surface we've painted. As a result, for
-// small or infrequently painting windows, we force back to the software
-// compositor to avoid this bug. See http://crbug.com/333380.
-const wchar_t kForceSoftwareCompositor[] = L"Chrome.ForceSoftwareCompositor";
-
-#endif // UI_COMPOSITOR_COMPOSITOR_CONSTANTS_H_
diff --git a/chromium/ui/compositor/compositor_switches.cc b/chromium/ui/compositor/compositor_switches.cc
index 991aba5e0ef..f8179b84a74 100644
--- a/chromium/ui/compositor/compositor_switches.cc
+++ b/chromium/ui/compositor/compositor_switches.cc
@@ -21,9 +21,6 @@ const char kEnablePixelOutputInTests[] = "enable-pixel-output-in-tests";
// maximum.
const char kLimitFps[] = "limit-fps";
-// Disable partial swap which is needed for some OpenGL drivers / emulators.
-const char kUIDisablePartialSwap[] = "ui-disable-partial-swap";
-
const char kUIEnableRGBA4444Textures[] = "ui-enable-rgba-4444-textures";
const char kUIEnableZeroCopy[] = "ui-enable-zero-copy";
@@ -32,6 +29,11 @@ const char kUIShowPaintRects[] = "ui-show-paint-rects";
const char kUISlowAnimations[] = "ui-slow-animations";
+// If enabled, all draw commands recorded on canvas are done in pixel aligned
+// measurements. This also enables scaling of all elements in views and layers
+// to be done via corner points. See https://goo.gl/Dqig5s
+const char kEnablePixelCanvasRecording[] = "enable-pixel-canvas-recording";
+
} // namespace switches
namespace ui {
@@ -42,4 +44,9 @@ bool IsUIZeroCopyEnabled() {
return command_line.HasSwitch(switches::kUIEnableZeroCopy);
}
+bool IsPixelCanvasRecordingEnabled() {
+ return base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnablePixelCanvasRecording);
+}
+
} // namespace ui
diff --git a/chromium/ui/compositor/compositor_switches.h b/chromium/ui/compositor/compositor_switches.h
index 54fc3354217..5c03be4898b 100644
--- a/chromium/ui/compositor/compositor_switches.h
+++ b/chromium/ui/compositor/compositor_switches.h
@@ -12,11 +12,11 @@ namespace switches {
COMPOSITOR_EXPORT extern const char kEnableHardwareOverlays[];
COMPOSITOR_EXPORT extern const char kEnablePixelOutputInTests[];
COMPOSITOR_EXPORT extern const char kLimitFps[];
-COMPOSITOR_EXPORT extern const char kUIDisablePartialSwap[];
COMPOSITOR_EXPORT extern const char kUIEnableRGBA4444Textures[];
COMPOSITOR_EXPORT extern const char kUIEnableZeroCopy[];
COMPOSITOR_EXPORT extern const char kUIShowPaintRects[];
COMPOSITOR_EXPORT extern const char kUISlowAnimations[];
+COMPOSITOR_EXPORT extern const char kEnablePixelCanvasRecording[];
} // namespace switches
@@ -24,6 +24,8 @@ namespace ui {
bool IsUIZeroCopyEnabled();
+bool COMPOSITOR_EXPORT IsPixelCanvasRecordingEnabled();
+
} // namespace ui
#endif // UI_COMPOSITOR_COMPOSITOR_SWITCHES_H_
diff --git a/chromium/ui/compositor/compositor_unittest.cc b/chromium/ui/compositor/compositor_unittest.cc
index 12fa0ba4974..83878b0a424 100644
--- a/chromium/ui/compositor/compositor_unittest.cc
+++ b/chromium/ui/compositor/compositor_unittest.cc
@@ -9,10 +9,10 @@
#include "base/single_thread_task_runner.h"
#include "base/test/test_mock_time_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
-#include "cc/output/begin_frame_args.h"
-#include "cc/surfaces/surface_manager.h"
-#include "cc/test/begin_frame_args_test.h"
+#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "components/viz/common/surfaces/local_surface_id_allocator.h"
+#include "components/viz/service/surfaces/surface_manager.h"
+#include "components/viz/test/begin_frame_args_test.h"
#include "testing/gmock/include/gmock/gmock.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/compositor/compositor.h"
@@ -40,7 +40,8 @@ class CompositorTest : public testing::Test {
compositor_.reset(new ui::Compositor(
context_factory_private->AllocateFrameSinkId(), context_factory,
context_factory_private, CreateTaskRunner(),
- false /* enable_surface_synchronization */));
+ false /* enable_surface_synchronization */,
+ false /* enable_pixel_canvas */));
compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
}
@@ -114,8 +115,7 @@ class CompositorObserverForLocks : public CompositorObserver {
bool locked_ = false;
};
-class MockCompositorLockClient
- : NON_EXPORTED_BASE(public ui::CompositorLockClient) {
+class MockCompositorLockClient : public ui::CompositorLockClient {
public:
MOCK_METHOD0(CompositorLockTimedOut, void());
};
diff --git a/chromium/ui/compositor/compositor_util.cc b/chromium/ui/compositor/compositor_util.cc
deleted file mode 100644
index 91b254340c0..00000000000
--- a/chromium/ui/compositor/compositor_util.cc
+++ /dev/null
@@ -1,46 +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/compositor/compositor_util.h"
-
-#include "base/command_line.h"
-#include "cc/base/switches.h"
-#include "components/viz/common/display/renderer_settings.h"
-#include "ui/compositor/compositor_switches.h"
-#include "ui/display/display_switches.h"
-#include "ui/gfx/color_space_switches.h"
-
-namespace ui {
-
-viz::RendererSettings CreateRendererSettings(
- const viz::BufferToTextureTargetMap& image_targets) {
- viz::RendererSettings renderer_settings;
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- renderer_settings.partial_swap_enabled =
- !command_line->HasSwitch(switches::kUIDisablePartialSwap);
-#if defined(OS_WIN)
- renderer_settings.finish_rendering_on_resize = true;
-#elif defined(OS_MACOSX)
- renderer_settings.release_overlay_resources_after_gpu_query = true;
-#endif
- renderer_settings.gl_composited_overlay_candidate_quad_border =
- command_line->HasSwitch(
- cc::switches::kGlCompositedOverlayCandidateQuadBorder);
- renderer_settings.show_overdraw_feedback =
- command_line->HasSwitch(cc::switches::kShowOverdrawFeedback);
- renderer_settings.enable_color_correct_rendering =
- base::FeatureList::IsEnabled(features::kColorCorrectRendering) ||
- command_line->HasSwitch(switches::kEnableHDR);
- renderer_settings.resource_settings.buffer_to_texture_target_map =
- image_targets;
-
- renderer_settings.disallow_non_exact_resource_reuse =
- command_line->HasSwitch(cc::switches::kDisallowNonExactResourceReuse);
- renderer_settings.allow_antialiasing =
- !command_line->HasSwitch(cc::switches::kDisableCompositedAntialiasing);
-
- return renderer_settings;
-}
-
-} // namespace ui
diff --git a/chromium/ui/compositor/compositor_util.h b/chromium/ui/compositor/compositor_util.h
deleted file mode 100644
index 1939514833f..00000000000
--- a/chromium/ui/compositor/compositor_util.h
+++ /dev/null
@@ -1,24 +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_COMPOSITOR_COMPOSITOR_UTIL_H_
-#define UI_COMPOSITOR_COMPOSITOR_UTIL_H_
-
-#include <stdint.h>
-
-#include "components/viz/common/resources/buffer_to_texture_target_map.h"
-#include "ui/compositor/compositor_export.h"
-
-namespace viz {
-class RendererSettings;
-}
-
-namespace ui {
-
-COMPOSITOR_EXPORT viz::RendererSettings CreateRendererSettings(
- const viz::BufferToTextureTargetMap& image_targets);
-
-} // namespace ui
-
-#endif // UI_COMPOSITOR_COMPOSITOR_UTIL_H_
diff --git a/chromium/ui/compositor/external_begin_frame_client.h b/chromium/ui/compositor/external_begin_frame_client.h
new file mode 100644
index 00000000000..764c901df30
--- /dev/null
+++ b/chromium/ui/compositor/external_begin_frame_client.h
@@ -0,0 +1,23 @@
+// Copyright (c) 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_COMPOSITOR_EXTERNAL_BEGIN_FRAME_CLIENT_H_
+#define UI_COMPOSITOR_EXTERNAL_BEGIN_FRAME_CLIENT_H_
+
+#include "components/viz/common/frame_sinks/begin_frame_args.h"
+#include "ui/compositor/compositor_export.h"
+
+namespace ui {
+
+class COMPOSITOR_EXPORT ExternalBeginFrameClient {
+ public:
+ virtual ~ExternalBeginFrameClient() {}
+
+ virtual void OnDisplayDidFinishFrame(const viz::BeginFrameAck& ack) = 0;
+ virtual void OnNeedsExternalBeginFrames(bool needs_begin_frames) = 0;
+};
+
+} // namespace ui
+
+#endif // UI_COMPOSITOR_EXTERNAL_BEGIN_FRAME_CLIENT_H_
diff --git a/chromium/ui/compositor/layer.cc b/chromium/ui/compositor/layer.cc
index d2248572c2a..72ccf5e861c 100644
--- a/chromium/ui/compositor/layer.cc
+++ b/chromium/ui/compositor/layer.cc
@@ -21,9 +21,9 @@
#include "cc/layers/solid_color_layer.h"
#include "cc/layers/surface_layer.h"
#include "cc/layers/texture_layer.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/resources/transferable_resource.h"
#include "cc/trees/layer_tree_settings.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/resources/transferable_resource.h"
#include "ui/compositor/compositor_switches.h"
#include "ui/compositor/dip_util.h"
#include "ui/compositor/layer_animator.h"
@@ -40,6 +40,10 @@
namespace {
const ui::Layer* GetRoot(const ui::Layer* layer) {
+ // Parent walk cannot be done on a layer that is being used as a mask. Get the
+ // layer to which this layer is a mask of.
+ if (layer->layer_mask_back_link())
+ layer = layer->layer_mask_back_link();
while (layer->parent())
layer = layer->parent();
return layer;
@@ -108,7 +112,8 @@ Layer::Layer()
delegate_(NULL),
owner_(NULL),
cc_layer_(NULL),
- device_scale_factor_(1.0f) {
+ device_scale_factor_(1.0f),
+ cache_render_surface_requests_(0) {
CreateCcLayer();
}
@@ -135,7 +140,8 @@ Layer::Layer(LayerType type)
delegate_(NULL),
owner_(NULL),
cc_layer_(NULL),
- device_scale_factor_(1.0f) {
+ device_scale_factor_(1.0f),
+ cache_render_surface_requests_(0) {
CreateCcLayer();
}
@@ -178,7 +184,7 @@ std::unique_ptr<Layer> Layer::Clone() const {
clone->SetLayerInverted(layer_inverted_);
clone->SetLayerBlur(layer_blur_sigma_);
if (alpha_shape_)
- clone->SetAlphaShape(base::MakeUnique<SkRegion>(*alpha_shape_));
+ clone->SetAlphaShape(base::MakeUnique<ShapeRects>(*alpha_shape_));
// cc::Layer state.
if (surface_layer_) {
@@ -315,7 +321,7 @@ void Layer::SetAnimator(LayerAnimator* animator) {
Compositor* compositor = GetCompositor();
if (animator_) {
- if (compositor)
+ if (compositor && !layer_mask_back_link())
animator_->DetachLayerAndTimeline(compositor);
animator_->SetDelegate(nullptr);
}
@@ -324,7 +330,7 @@ void Layer::SetAnimator(LayerAnimator* animator) {
if (animator_) {
animator_->SetDelegate(this);
- if (compositor)
+ if (compositor && !layer_mask_back_link())
animator_->AttachLayerAndTimeline(compositor);
}
}
@@ -445,14 +451,13 @@ void Layer::SetLayerInverted(bool inverted) {
}
void Layer::SetMaskLayer(Layer* layer_mask) {
+ if (layer_mask_ == layer_mask)
+ return;
// The provided mask should not have a layer mask itself.
DCHECK(!layer_mask ||
- (!layer_mask->layer_mask_layer() &&
- layer_mask->children().empty() &&
+ (!layer_mask->layer_mask_layer() && layer_mask->children().empty() &&
!layer_mask->layer_mask_back_link_));
DCHECK(!layer_mask_back_link_);
- if (layer_mask_ == layer_mask)
- return;
// We need to de-reference the currently linked object so that no problem
// arises if the mask layer gets deleted before this object.
if (layer_mask_)
@@ -474,8 +479,8 @@ void Layer::SetBackgroundZoom(float zoom, int inset) {
SetLayerBackgroundFilters();
}
-void Layer::SetAlphaShape(std::unique_ptr<SkRegion> region) {
- alpha_shape_ = std::move(region);
+void Layer::SetAlphaShape(std::unique_ptr<ShapeRects> shape) {
+ alpha_shape_ = std::move(shape);
SetLayerFilters();
}
@@ -661,13 +666,27 @@ void Layer::SwitchCCLayerForTest() {
// which could be a supprise. But we want to preserve it after switching to a
// new cc::Layer. There could be a whole subtree and the root changed, but does
// not mean we want to treat the cache all different.
-void Layer::SetCacheRenderSurface(bool cache_render_surface) {
- cc_layer_->SetCacheRenderSurface(cache_render_surface);
+void Layer::AddCacheRenderSurfaceRequest() {
+ ++cache_render_surface_requests_;
+ TRACE_COUNTER_ID1("ui", "CacheRenderSurfaceRequests", this,
+ cache_render_surface_requests_);
+ if (cache_render_surface_requests_ == 1)
+ cc_layer_->SetCacheRenderSurface(true);
+}
+
+void Layer::RemoveCacheRenderSurfaceRequest() {
+ DCHECK_GT(cache_render_surface_requests_, 0u);
+
+ --cache_render_surface_requests_;
+ TRACE_COUNTER_ID1("ui", "CacheRenderSurfaceRequests", this,
+ cache_render_surface_requests_);
+ if (cache_render_surface_requests_ == 0)
+ cc_layer_->SetCacheRenderSurface(false);
}
void Layer::SetTextureMailbox(
const viz::TextureMailbox& mailbox,
- std::unique_ptr<cc::SingleReleaseCallback> release_callback,
+ std::unique_ptr<viz::SingleReleaseCallback> release_callback,
gfx::Size texture_size_in_dip) {
DCHECK(type_ == LAYER_TEXTURED || type_ == LAYER_SOLID_COLOR);
DCHECK(mailbox.IsValid());
@@ -741,6 +760,12 @@ void Layer::SetFallbackSurface(const viz::SurfaceInfo& surface_info) {
mirror->dest()->SetFallbackSurface(surface_info);
}
+const viz::SurfaceInfo* Layer::GetPrimarySurfaceInfo() const {
+ if (surface_layer_)
+ return &surface_layer_->primary_surface_info();
+ return nullptr;
+}
+
const viz::SurfaceInfo* Layer::GetFallbackSurfaceInfo() const {
if (surface_layer_)
return &surface_layer_->fallback_surface_info();
@@ -896,7 +921,8 @@ void Layer::OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) {
}
void Layer::SetDidScrollCallback(
- base::Callback<void(const gfx::ScrollOffset&)> callback) {
+ base::Callback<void(const gfx::ScrollOffset&, const cc::ElementId&)>
+ callback) {
cc_layer_->set_did_scroll_callback(std::move(callback));
}
@@ -927,7 +953,7 @@ void Layer::SetScrollOffset(const gfx::ScrollOffset& offset) {
}
void Layer::RequestCopyOfOutput(
- std::unique_ptr<cc::CopyOutputRequest> request) {
+ std::unique_ptr<viz::CopyOutputRequest> request) {
cc_layer_->RequestCopyOfOutput(std::move(request));
}
@@ -944,8 +970,9 @@ scoped_refptr<cc::DisplayItemList> Layer::PaintContentsToDisplayList(
paint_region_.Clear();
auto display_list = make_scoped_refptr(new cc::DisplayItemList);
if (delegate_) {
- delegate_->OnPaintLayer(
- PaintContext(display_list.get(), device_scale_factor_, invalidation));
+ delegate_->OnPaintLayer(PaintContext(display_list.get(),
+ device_scale_factor_, invalidation,
+ GetCompositor()->is_pixel_canvas()));
}
display_list->Finalize();
// TODO(domlaskowski): Move mirror invalidation to Layer::SchedulePaint.
@@ -964,7 +991,7 @@ size_t Layer::GetApproximateUnsharedMemoryUsage() const {
bool Layer::PrepareTextureMailbox(
viz::TextureMailbox* mailbox,
- std::unique_ptr<cc::SingleReleaseCallback>* release_callback) {
+ std::unique_ptr<viz::SingleReleaseCallback>* release_callback) {
if (!mailbox_release_callback_)
return false;
*mailbox = mailbox_;
@@ -1181,6 +1208,10 @@ float Layer::GetRefreshRate() const {
return compositor ? compositor->refresh_rate() : 60.0;
}
+ui::Layer* Layer::GetLayer() {
+ return this;
+}
+
cc::Layer* Layer::GetCcLayer() const {
return cc_layer_;
}
diff --git a/chromium/ui/compositor/layer.h b/chromium/ui/compositor/layer.h
index e89acf51120..869c00c6f91 100644
--- a/chromium/ui/compositor/layer.h
+++ b/chromium/ui/compositor/layer.h
@@ -24,7 +24,6 @@
#include "components/viz/common/quads/texture_mailbox.h"
#include "components/viz/common/surfaces/sequence_surface_reference_factory.h"
#include "third_party/skia/include/core/SkColor.h"
-#include "third_party/skia/include/core/SkRegion.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/layer_animation_delegate.h"
#include "ui/compositor/layer_delegate.h"
@@ -34,7 +33,6 @@
#include "ui/gfx/transform.h"
namespace cc {
-class CopyOutputRequest;
class Layer;
class NinePatchLayer;
class SolidColorLayer;
@@ -42,6 +40,10 @@ class SurfaceLayer;
class TextureLayer;
}
+namespace viz {
+class CopyOutputRequest;
+}
+
namespace ui {
class Compositor;
@@ -60,12 +62,12 @@ class LayerThreadedAnimationDelegate;
// NOTE: Unlike Views, each Layer does *not* own its child Layers. If you
// delete a Layer and it has children, the parent of each child Layer is set to
// NULL, but the children are not deleted.
-class COMPOSITOR_EXPORT Layer
- : public LayerAnimationDelegate,
- NON_EXPORTED_BASE(public cc::ContentLayerClient),
- NON_EXPORTED_BASE(public cc::TextureLayerClient),
- NON_EXPORTED_BASE(public cc::LayerClient) {
+class COMPOSITOR_EXPORT Layer : public LayerAnimationDelegate,
+ public cc::ContentLayerClient,
+ public cc::TextureLayerClient,
+ public cc::LayerClient {
public:
+ using ShapeRects = std::vector<gfx::Rect>;
Layer();
explicit Layer(LayerType type);
~Layer() override;
@@ -233,8 +235,8 @@ class COMPOSITOR_EXPORT Layer
void SetBackgroundZoom(float zoom, int inset);
// Set the shape of this layer.
- SkRegion* alpha_shape() const { return alpha_shape_.get(); }
- void SetAlphaShape(std::unique_ptr<SkRegion> region);
+ const ShapeRects* alpha_shape() const { return alpha_shape_.get(); }
+ void SetAlphaShape(std::unique_ptr<ShapeRects> shape);
// Invert the layer.
bool layer_inverted() const { return layer_inverted_; }
@@ -299,7 +301,7 @@ class COMPOSITOR_EXPORT Layer
// shared memory resource or an actual mailbox for a texture.
void SetTextureMailbox(
const viz::TextureMailbox& mailbox,
- std::unique_ptr<cc::SingleReleaseCallback> release_callback,
+ std::unique_ptr<viz::SingleReleaseCallback> release_callback,
gfx::Size texture_size_in_dip);
void SetTextureSize(gfx::Size texture_size_in_dip);
void SetTextureFlipped(bool flipped);
@@ -314,6 +316,9 @@ class COMPOSITOR_EXPORT Layer
// display compositor, the fallback surface will be used.
void SetFallbackSurface(const viz::SurfaceInfo& surface_info);
+ // Returns the primary SurfaceInfo set by SetShowPrimarySurface.
+ const viz::SurfaceInfo* GetPrimarySurfaceInfo() const;
+
// Returns the fallback SurfaceInfo set by SetFallbackSurface.
const viz::SurfaceInfo* GetFallbackSurfaceInfo() const;
@@ -366,12 +371,15 @@ class COMPOSITOR_EXPORT Layer
void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip);
// Requets a copy of the layer's output as a texture or bitmap.
- void RequestCopyOfOutput(std::unique_ptr<cc::CopyOutputRequest> request);
+ void RequestCopyOfOutput(std::unique_ptr<viz::CopyOutputRequest> request);
// Invoked when scrolling performed by the cc::InputHandler is committed. This
// will only occur if the Layer has set scroll container bounds.
void SetDidScrollCallback(
- base::Callback<void(const gfx::ScrollOffset&)> callback);
+ base::Callback<void(const gfx::ScrollOffset&, const cc::ElementId&)>
+ callback);
+
+ cc::ElementId element_id() const { return cc_layer_->element_id(); }
// Marks this layer as scrollable inside the provided bounds. This size only
// affects scrolling so if clipping is desired, a separate clipping layer
@@ -394,7 +402,7 @@ class COMPOSITOR_EXPORT Layer
// TextureLayerClient
bool PrepareTextureMailbox(
viz::TextureMailbox* mailbox,
- std::unique_ptr<cc::SingleReleaseCallback>* release_callback) override;
+ std::unique_ptr<viz::SingleReleaseCallback>* release_callback) override;
float device_scale_factor() const { return device_scale_factor_; }
@@ -419,7 +427,13 @@ class COMPOSITOR_EXPORT Layer
// occlusion culling in favor of efficient caching. This should
// only be used when paying the cost of creating a render
// surface even if layer is invisible is not a problem.
- void SetCacheRenderSurface(bool cache_render_surface);
+ void AddCacheRenderSurfaceRequest();
+ void RemoveCacheRenderSurfaceRequest();
+
+ // The back link from the mask layer to it's associated masked layer.
+ // We keep this reference for the case that if the mask layer gets deleted
+ // while attached to the main layer before the main layer is deleted.
+ const Layer* layer_mask_back_link() const { return layer_mask_back_link_; }
private:
friend class LayerOwner;
@@ -453,6 +467,7 @@ class COMPOSITOR_EXPORT Layer
SkColor GetColorForAnimation() const override;
float GetTemperatureFromAnimation() const override;
float GetDeviceScaleFactor() const override;
+ ui::Layer* GetLayer() override;
cc::Layer* GetCcLayer() const override;
LayerThreadedAnimationDelegate* GetThreadedAnimationDelegate() override;
LayerAnimatorCollection* GetLayerAnimatorCollection() override;
@@ -546,7 +561,7 @@ class COMPOSITOR_EXPORT Layer
int zoom_inset_;
// Shape of the window.
- std::unique_ptr<SkRegion> alpha_shape_;
+ std::unique_ptr<ShapeRects> alpha_shape_;
std::string name_;
@@ -580,12 +595,17 @@ class COMPOSITOR_EXPORT Layer
// The callback to release the mailbox. This is only set after
// SetTextureMailbox is called, before we give it to the TextureLayer.
- std::unique_ptr<cc::SingleReleaseCallback> mailbox_release_callback_;
+ std::unique_ptr<viz::SingleReleaseCallback> mailbox_release_callback_;
// The size of the frame or texture in DIP, set when SetShowDelegatedContent
// or SetTextureMailbox was called.
gfx::Size frame_size_in_dip_;
+ // The counter to maintain how many cache render surface requests we have. If
+ // the value > 0, means we need to cache the render surface. If the value
+ // == 0, means we should not cache the render surface.
+ unsigned cache_render_surface_requests_;
+
DISALLOW_COPY_AND_ASSIGN(Layer);
};
diff --git a/chromium/ui/compositor/layer_animation_delegate.h b/chromium/ui/compositor/layer_animation_delegate.h
index 827647be7a4..45bf8bad926 100644
--- a/chromium/ui/compositor/layer_animation_delegate.h
+++ b/chromium/ui/compositor/layer_animation_delegate.h
@@ -16,6 +16,7 @@ class Layer;
namespace ui {
+class Layer;
class LayerAnimatorCollection;
class LayerThreadedAnimationDelegate;
@@ -40,6 +41,7 @@ class COMPOSITOR_EXPORT LayerAnimationDelegate {
virtual SkColor GetColorForAnimation() const = 0;
virtual float GetTemperatureFromAnimation() const = 0;
virtual float GetDeviceScaleFactor() const = 0;
+ virtual ui::Layer* GetLayer() = 0;
virtual cc::Layer* GetCcLayer() const = 0;
virtual LayerAnimatorCollection* GetLayerAnimatorCollection() = 0;
virtual LayerThreadedAnimationDelegate* GetThreadedAnimationDelegate() = 0;
diff --git a/chromium/ui/compositor/layer_animation_element.cc b/chromium/ui/compositor/layer_animation_element.cc
index 9f6797fa9cd..82cdb89f5d6 100644
--- a/chromium/ui/compositor/layer_animation_element.cc
+++ b/chromium/ui/compositor/layer_animation_element.cc
@@ -9,6 +9,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
+#include "base/strings/stringprintf.h"
#include "cc/animation/animation.h"
#include "cc/animation/animation_id_provider.h"
#include "ui/compositor/float_animation_curve_adapter.h"
@@ -39,6 +40,7 @@ class Pause : public LayerAnimationElement {
~Pause() override {}
private:
+ std::string DebugName() const override { return "Pause"; }
void OnStart(LayerAnimationDelegate* delegate) override {}
bool OnProgress(double t, LayerAnimationDelegate* delegate) override {
return false;
@@ -61,6 +63,9 @@ class InterpolatedTransformTransition : public LayerAnimationElement {
~InterpolatedTransformTransition() override {}
protected:
+ std::string DebugName() const override {
+ return "InterpolatedTransformTransition";
+ }
void OnStart(LayerAnimationDelegate* delegate) override {}
bool OnProgress(double t, LayerAnimationDelegate* delegate) override {
@@ -92,6 +97,7 @@ class BoundsTransition : public LayerAnimationElement {
~BoundsTransition() override {}
protected:
+ std::string DebugName() const override { return "BoundsTransition"; }
void OnStart(LayerAnimationDelegate* delegate) override {
start_ = delegate->GetBoundsForAnimation();
}
@@ -127,6 +133,7 @@ class VisibilityTransition : public LayerAnimationElement {
~VisibilityTransition() override {}
protected:
+ std::string DebugName() const override { return "VisibilityTransition"; }
void OnStart(LayerAnimationDelegate* delegate) override {
start_ = delegate->GetVisibilityForAnimation();
}
@@ -161,6 +168,7 @@ class BrightnessTransition : public LayerAnimationElement {
~BrightnessTransition() override {}
protected:
+ std::string DebugName() const override { return "BrightnessTransition"; }
void OnStart(LayerAnimationDelegate* delegate) override {
start_ = delegate->GetBrightnessForAnimation();
}
@@ -196,6 +204,7 @@ class GrayscaleTransition : public LayerAnimationElement {
~GrayscaleTransition() override {}
protected:
+ std::string DebugName() const override { return "GrayscaleTransition"; }
void OnStart(LayerAnimationDelegate* delegate) override {
start_ = delegate->GetGrayscaleForAnimation();
}
@@ -231,6 +240,7 @@ class ColorTransition : public LayerAnimationElement {
~ColorTransition() override {}
protected:
+ std::string DebugName() const override { return "ColorTransition"; }
void OnStart(LayerAnimationDelegate* delegate) override {
start_ = delegate->GetColorForAnimation();
}
@@ -265,6 +275,7 @@ class TemperatureTransition : public LayerAnimationElement {
~TemperatureTransition() override {}
protected:
+ std::string DebugName() const override { return "TemperatureTransition"; }
void OnStart(LayerAnimationDelegate* delegate) override {
start_ = delegate->GetTemperatureFromAnimation();
}
@@ -304,6 +315,9 @@ class ThreadedLayerAnimationElement : public LayerAnimationElement {
explicit ThreadedLayerAnimationElement(const LayerAnimationElement& element)
: LayerAnimationElement(element) {
}
+ std::string DebugName() const override {
+ return "ThreadedLayerAnimationElement";
+ }
bool OnProgress(double t, LayerAnimationDelegate* delegate) override {
if (t < 1.0)
@@ -365,6 +379,7 @@ class ThreadedOpacityTransition : public ThreadedLayerAnimationElement {
~ThreadedOpacityTransition() override {}
protected:
+ std::string DebugName() const override { return "ThreadedOpacityTransition"; }
void OnStart(LayerAnimationDelegate* delegate) override {
start_ = delegate->GetOpacityForAnimation();
}
@@ -416,6 +431,9 @@ class ThreadedTransformTransition : public ThreadedLayerAnimationElement {
~ThreadedTransformTransition() override {}
protected:
+ std::string DebugName() const override {
+ return "ThreadedTransformTransition";
+ }
void OnStart(LayerAnimationDelegate* delegate) override {
start_ = delegate->GetTransformForAnimation();
}
@@ -621,6 +639,21 @@ void LayerAnimationElement::RequestEffectiveStart(
effective_start_time_ = requested_start_time_;
}
+std::string LayerAnimationElement::ToString() const {
+ // TODO(wkorman): Add support for subclasses to tack on more info
+ // beyond just their name.
+ return base::StringPrintf(
+ "LayerAnimationElement{name=%s, id=%d, group=%d, "
+ "last_progressed_fraction=%0.2f, "
+ "start_frame_number=%d}",
+ DebugName().c_str(), animation_id_, animation_group_id_,
+ last_progressed_fraction_, start_frame_number_);
+}
+
+std::string LayerAnimationElement::DebugName() const {
+ return "Default";
+}
+
// static
LayerAnimationElement::AnimatableProperty
LayerAnimationElement::ToAnimatableProperty(cc::TargetProperty::Type property) {
@@ -636,6 +669,57 @@ LayerAnimationElement::ToAnimatableProperty(cc::TargetProperty::Type property) {
}
// static
+std::string LayerAnimationElement::AnimatablePropertiesToString(
+ AnimatableProperties properties) {
+ std::string str;
+ int property_count = 0;
+ for (unsigned i = FIRST_PROPERTY; i != SENTINEL; i = i << 1) {
+ if (i & properties) {
+ LayerAnimationElement::AnimatableProperty property =
+ static_cast<LayerAnimationElement::AnimatableProperty>(i);
+ if (property_count > 0)
+ str.append("|");
+ // TODO(wkorman): Consider reworking enum definition to follow
+ // #define pattern that includes easier string output.
+ switch (property) {
+ case UNKNOWN:
+ str.append("UNKNOWN");
+ break;
+ case TRANSFORM:
+ str.append("TRANSFORM");
+ break;
+ case BOUNDS:
+ str.append("BOUNDS");
+ break;
+ case OPACITY:
+ str.append("OPACITY");
+ break;
+ case VISIBILITY:
+ str.append("VISIBILITY");
+ break;
+ case BRIGHTNESS:
+ str.append("BRIGHTNESS");
+ break;
+ case GRAYSCALE:
+ str.append("GRAYSCALE");
+ break;
+ case COLOR:
+ str.append("COLOR");
+ break;
+ case TEMPERATURE:
+ str.append("TEMPERATURE");
+ break;
+ case SENTINEL:
+ NOTREACHED();
+ break;
+ }
+ property_count++;
+ }
+ }
+ return str;
+}
+
+// static
base::TimeDelta LayerAnimationElement::GetEffectiveDuration(
const base::TimeDelta& duration) {
switch (ScopedAnimationDurationScaleMode::duration_scale_mode()) {
diff --git a/chromium/ui/compositor/layer_animation_element.h b/chromium/ui/compositor/layer_animation_element.h
index d4f248dece5..9a11b97cc5e 100644
--- a/chromium/ui/compositor/layer_animation_element.h
+++ b/chromium/ui/compositor/layer_animation_element.h
@@ -14,6 +14,7 @@
#include "base/memory/weak_ptr.h"
#include "base/time/time.h"
#include "cc/animation/animation.h"
+#include "cc/trees/target_property.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/compositor/compositor_export.h"
#include "ui/gfx/animation/tween.h"
@@ -77,6 +78,9 @@ class COMPOSITOR_EXPORT LayerAnimationElement {
virtual ~LayerAnimationElement();
+ static std::string AnimatablePropertiesToString(
+ AnimatableProperties properties);
+
// Creates an element that transitions to the given transform. The caller owns
// the return value.
static std::unique_ptr<LayerAnimationElement> CreateTransformElement(
@@ -213,7 +217,11 @@ class COMPOSITOR_EXPORT LayerAnimationElement {
// call made to {Progress, ProgressToEnd}.
double last_progressed_fraction() const { return last_progressed_fraction_; }
+ std::string ToString() const;
+
protected:
+ virtual std::string DebugName() const;
+
// Called once each time the animation element is run before any call to
// OnProgress.
virtual void OnStart(LayerAnimationDelegate* delegate) = 0;
diff --git a/chromium/ui/compositor/layer_animation_element_unittest.cc b/chromium/ui/compositor/layer_animation_element_unittest.cc
index 93714e505e8..6baad140ab6 100644
--- a/chromium/ui/compositor/layer_animation_element_unittest.cc
+++ b/chromium/ui/compositor/layer_animation_element_unittest.cc
@@ -400,6 +400,20 @@ TEST(LayerAnimationElementTest, AbortTransformElement) {
delegate.GetTransformForAnimation());
}
+TEST(LayerAnimationElementTest, ToString) {
+ float target = 1.0;
+ base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
+ std::unique_ptr<LayerAnimationElement> element =
+ LayerAnimationElement::CreateOpacityElement(target, delta);
+ element->set_animation_group_id(42);
+ // TODO(wkorman): Test varying last_progressed_fraction and
+ // start_frame_number.
+ EXPECT_EQ(
+ "LayerAnimationElement{name=ThreadedOpacityTransition, id=1, group=42, "
+ "last_progressed_fraction=0.00, start_frame_number=0}",
+ element->ToString());
+}
+
} // namespace
} // namespace ui
diff --git a/chromium/ui/compositor/layer_animation_sequence.cc b/chromium/ui/compositor/layer_animation_sequence.cc
index f13db19d1d1..a7a7b1c596e 100644
--- a/chromium/ui/compositor/layer_animation_sequence.cc
+++ b/chromium/ui/compositor/layer_animation_sequence.cc
@@ -7,6 +7,7 @@
#include <algorithm>
#include <iterator>
+#include "base/strings/stringprintf.h"
#include "base/trace_event/trace_event.h"
#include "cc/animation/animation_id_provider.h"
#include "ui/compositor/layer_animation_delegate.h"
@@ -290,4 +291,23 @@ LayerAnimationElement* LayerAnimationSequence::CurrentElement() const {
return elements_[current_index].get();
}
+std::string LayerAnimationSequence::ElementsToString() const {
+ std::string str;
+ for (size_t i = 0; i < elements_.size(); i++) {
+ if (i > 0)
+ str.append(", ");
+ str.append(elements_[i]->ToString());
+ }
+ return str;
+}
+
+std::string LayerAnimationSequence::ToString() const {
+ return base::StringPrintf(
+ "LayerAnimationSequence{size=%zu, properties=%s, "
+ "elements=[%s], is_cyclic=%d, group_id=%d}",
+ size(),
+ LayerAnimationElement::AnimatablePropertiesToString(properties_).c_str(),
+ ElementsToString().c_str(), is_cyclic_, animation_group_id_);
+}
+
} // namespace ui
diff --git a/chromium/ui/compositor/layer_animation_sequence.h b/chromium/ui/compositor/layer_animation_sequence.h
index 379ff54a020..cee0500a7f0 100644
--- a/chromium/ui/compositor/layer_animation_sequence.h
+++ b/chromium/ui/compositor/layer_animation_sequence.h
@@ -138,6 +138,8 @@ class COMPOSITOR_EXPORT LayerAnimationSequence
LayerAnimationElement* FirstElement() const;
+ std::string ToString() const;
+
private:
friend class LayerAnimatorTestController;
@@ -146,6 +148,8 @@ class COMPOSITOR_EXPORT LayerAnimationSequence
FRIEND_TEST_ALL_PREFIXES(LayerAnimatorTest,
ObserverReleasedBeforeAnimationSequenceEnds);
+ std::string ElementsToString() const;
+
// Notifies the observers that this sequence has been scheduled.
void NotifyScheduled();
diff --git a/chromium/ui/compositor/layer_animation_sequence_unittest.cc b/chromium/ui/compositor/layer_animation_sequence_unittest.cc
index 9222046fb28..3ce4001408c 100644
--- a/chromium/ui/compositor/layer_animation_sequence_unittest.cc
+++ b/chromium/ui/compositor/layer_animation_sequence_unittest.cc
@@ -7,6 +7,7 @@
#include <memory>
#include "base/compiler_specific.h"
+#include "base/strings/stringprintf.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/compositor/layer_animation_delegate.h"
@@ -268,6 +269,46 @@ TEST(LayerAnimationSequenceTest, AddObserver) {
}
}
+TEST(LayerAnimationSequenceTest, ToString) {
+ base::TimeDelta delta = base::TimeDelta::FromSeconds(1);
+ LayerAnimationSequence sequence;
+ EXPECT_EQ(
+ "LayerAnimationSequence{size=0, properties=, elements=[], is_cyclic=0, "
+ "group_id=0}",
+ sequence.ToString());
+
+ std::unique_ptr<LayerAnimationElement> brightness =
+ LayerAnimationElement::CreateBrightnessElement(1.0f, delta);
+ int brightness_id = brightness->animation_id();
+ sequence.AddElement(std::move(brightness));
+ EXPECT_EQ(
+ base::StringPrintf(
+ "LayerAnimationSequence{size=1, properties=BRIGHTNESS, "
+ "elements=[LayerAnimationElement{name=BrightnessTransition, id=%d, "
+ "group=0, last_progressed_fraction=0.00, start_frame_number=0}], "
+ "is_cyclic=0, group_id=0}",
+ brightness_id),
+ sequence.ToString());
+
+ std::unique_ptr<LayerAnimationElement> opacity =
+ LayerAnimationElement::CreateOpacityElement(1.0f, delta);
+ int opacity_id = opacity->animation_id();
+ sequence.AddElement(std::move(opacity));
+ sequence.set_is_cyclic(true);
+ sequence.set_animation_group_id(1973);
+ EXPECT_EQ(
+ base::StringPrintf(
+ "LayerAnimationSequence{size=2, properties=OPACITY|BRIGHTNESS, "
+ "elements=[LayerAnimationElement{name=BrightnessTransition, id=%d, "
+ "group=0, last_progressed_fraction=0.00, start_frame_number=0}, "
+ "LayerAnimationElement{name=ThreadedOpacityTransition, id=%d, "
+ "group=0, "
+ "last_progressed_fraction=0.00, start_frame_number=0}], is_cyclic=1, "
+ "group_id=1973}",
+ brightness_id, opacity_id),
+ sequence.ToString());
+}
+
} // namespace
} // namespace ui
diff --git a/chromium/ui/compositor/layer_animator.cc b/chromium/ui/compositor/layer_animator.cc
index 09e5b17f16c..5902c14a039 100644
--- a/chromium/ui/compositor/layer_animator.cc
+++ b/chromium/ui/compositor/layer_animator.cc
@@ -15,7 +15,7 @@
#include "cc/animation/animation_player.h"
#include "cc/animation/animation_timeline.h"
#include "cc/animation/element_animations.h"
-#include "cc/output/begin_frame_args.h"
+#include "components/viz/common/frame_sinks/begin_frame_args.h"
#include "ui/compositor/compositor.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animation_delegate.h"
@@ -919,11 +919,12 @@ LayerAnimatorCollection* LayerAnimator::GetLayerAnimatorCollection() {
return delegate_ ? delegate_->GetLayerAnimatorCollection() : NULL;
}
-void LayerAnimator::NotifyAnimationStarted(
- base::TimeTicks monotonic_time,
- cc::TargetProperty::Type target_property,
- int group) {
- OnThreadedAnimationStarted(monotonic_time, target_property, group);
+void LayerAnimator::NotifyAnimationStarted(base::TimeTicks monotonic_time,
+ int target_property,
+ int group) {
+ OnThreadedAnimationStarted(
+ monotonic_time, static_cast<cc::TargetProperty::Type>(target_property),
+ group);
}
LayerAnimator::RunningAnimation::RunningAnimation(
diff --git a/chromium/ui/compositor/layer_animator.h b/chromium/ui/compositor/layer_animator.h
index 19dc61dad58..a86864cb315 100644
--- a/chromium/ui/compositor/layer_animator.h
+++ b/chromium/ui/compositor/layer_animator.h
@@ -53,10 +53,9 @@ class ScopedLayerAnimationSettings;
// ensure that it is not disposed of until it finishes executing. It does this
// by holding a reference to itself for the duration of methods for which it
// must guarantee that |this| is valid.
-class COMPOSITOR_EXPORT LayerAnimator
- : public base::RefCounted<LayerAnimator>,
- public LayerThreadedAnimationDelegate,
- NON_EXPORTED_BASE(public cc::AnimationDelegate) {
+class COMPOSITOR_EXPORT LayerAnimator : public base::RefCounted<LayerAnimator>,
+ public LayerThreadedAnimationDelegate,
+ public cc::AnimationDelegate {
public:
enum PreemptionStrategy {
IMMEDIATELY_SET_NEW_TARGET,
@@ -345,18 +344,18 @@ class COMPOSITOR_EXPORT LayerAnimator
// cc::AnimationDelegate implementation.
void NotifyAnimationStarted(base::TimeTicks monotonic_time,
- cc::TargetProperty::Type target_property,
+ int target_property,
int group_id) override;
void NotifyAnimationFinished(base::TimeTicks monotonic_time,
- cc::TargetProperty::Type target_property,
+ int target_property,
int group_id) override {}
void NotifyAnimationAborted(base::TimeTicks monotonic_time,
- cc::TargetProperty::Type target_property,
+ int target_property,
int group_id) override {}
void NotifyAnimationTakeover(
base::TimeTicks monotonic_time,
- cc::TargetProperty::Type target_property,
- double animation_start_time,
+ int target_property,
+ base::TimeTicks animation_start_time,
std::unique_ptr<cc::AnimationCurve> curve) override {}
// Implementation of LayerThreadedAnimationDelegate.
diff --git a/chromium/ui/compositor/layer_animator_unittest.cc b/chromium/ui/compositor/layer_animator_unittest.cc
index 4b9575b4ba2..3e09d10b574 100644
--- a/chromium/ui/compositor/layer_animator_unittest.cc
+++ b/chromium/ui/compositor/layer_animator_unittest.cc
@@ -1694,6 +1694,178 @@ TEST(LayerAnimatorTest, ImplicitAnimationObservers) {
EXPECT_FLOAT_EQ(0.0f, delegate.GetBrightnessForAnimation());
}
+// Tests that caching render surface added to a scoped settings object is still
+// reset when the object goes out of scope.
+TEST(LayerAnimatorTest, CacheRenderSurface) {
+ ui::Layer layer;
+ scoped_refptr<LayerAnimator> animator(layer.GetAnimator());
+ animator->set_disable_timer_for_test(true);
+ TestImplicitAnimationObserver observer(false);
+
+ EXPECT_FALSE(observer.animations_completed());
+ EXPECT_FALSE(layer.cc_layer_for_testing()->cache_render_surface());
+ animator->SetOpacity(1.0f);
+
+ {
+ ScopedLayerAnimationSettings settings(animator.get());
+ settings.CacheRenderSurface();
+ settings.AddObserver(&observer);
+ animator->SetOpacity(0.0f);
+ }
+
+ EXPECT_FALSE(observer.animations_completed());
+ EXPECT_TRUE(layer.cc_layer_for_testing()->cache_render_surface());
+ animator->StopAnimatingProperty(LayerAnimationElement::OPACITY);
+ EXPECT_TRUE(observer.animations_completed());
+ EXPECT_TRUE(observer.WasAnimationCompletedForProperty(
+ LayerAnimationElement::OPACITY));
+ EXPECT_FLOAT_EQ(0.0f, layer.opacity());
+ EXPECT_FALSE(layer.cc_layer_for_testing()->cache_render_surface());
+}
+
+// Tests that caching render surface added to a scoped settings object will not
+// crash when the layer was destroyed.
+TEST(LayerAnimatorTest, CacheRenderSurfaceOnWillBeDestroyedLayer) {
+ // Case 1: layer is a pointer.
+ ui::Layer* layer1 = new Layer();
+ scoped_refptr<LayerAnimator> animator(layer1->GetAnimator());
+ animator->set_disable_timer_for_test(true);
+ TestImplicitAnimationObserver observer1(false);
+
+ EXPECT_FALSE(observer1.animations_completed());
+ animator->SetOpacity(1.0f);
+
+ {
+ ScopedLayerAnimationSettings settings(animator.get());
+ settings.CacheRenderSurface();
+ settings.AddObserver(&observer1);
+ animator->SetOpacity(0.0f);
+ }
+
+ EXPECT_FALSE(observer1.animations_completed());
+ delete layer1;
+ layer1 = nullptr;
+ animator->StopAnimatingProperty(LayerAnimationElement::OPACITY);
+ EXPECT_TRUE(observer1.animations_completed());
+
+ // Case 2: layer is a local variable.
+ TestImplicitAnimationObserver observer2(false);
+ {
+ ui::Layer layer2;
+ animator = layer2.GetAnimator();
+
+ EXPECT_FALSE(observer2.animations_completed());
+ animator->SetBrightness(1.0f);
+
+ ScopedLayerAnimationSettings settings(animator.get());
+ settings.CacheRenderSurface();
+ settings.AddObserver(&observer2);
+ animator->SetBrightness(0.0f);
+ }
+
+ EXPECT_FALSE(observer2.animations_completed());
+ animator->StopAnimatingProperty(LayerAnimationElement::BRIGHTNESS);
+ EXPECT_TRUE(observer2.animations_completed());
+
+ // Case 3: Animation finishes before layer is destroyed.
+ ui::Layer layer3;
+ animator = layer3.GetAnimator();
+ TestImplicitAnimationObserver observer3(false);
+
+ EXPECT_FALSE(observer3.animations_completed());
+ animator->SetGrayscale(1.0f);
+
+ {
+ ScopedLayerAnimationSettings settings(animator.get());
+ settings.CacheRenderSurface();
+ settings.AddObserver(&observer3);
+ animator->SetGrayscale(0.0f);
+ }
+
+ EXPECT_FALSE(observer3.animations_completed());
+ animator->StopAnimatingProperty(LayerAnimationElement::GRAYSCALE);
+ EXPECT_TRUE(observer3.animations_completed());
+}
+
+// Tests that caching render surface added to two scoped settings objects is
+// still reset when animation finishes.
+TEST(LayerAnimatorTest, CacheRenderSurfaceInTwoAnimations) {
+ ui::Layer layer;
+ scoped_refptr<LayerAnimator> animator(layer.GetAnimator());
+ animator->set_disable_timer_for_test(true);
+
+ // Case 1: the original cache status if false.
+ EXPECT_FALSE(layer.cc_layer_for_testing()->cache_render_surface());
+ animator->SetBrightness(1.0f);
+ animator->SetOpacity(1.0f);
+
+ // Start the brightness animation.
+ {
+ ScopedLayerAnimationSettings settings(animator.get());
+ settings.CacheRenderSurface();
+ animator->SetBrightness(0.0f);
+ }
+ EXPECT_TRUE(layer.cc_layer_for_testing()->cache_render_surface());
+
+ // Start the opacity animation.
+ {
+ ScopedLayerAnimationSettings settings(animator.get());
+ settings.CacheRenderSurface();
+ animator->SetOpacity(0.0f);
+ }
+ EXPECT_TRUE(layer.cc_layer_for_testing()->cache_render_surface());
+
+ // Finish the brightness animation.
+ {
+ animator->StopAnimatingProperty(LayerAnimationElement::BRIGHTNESS);
+ EXPECT_FLOAT_EQ(0.0f, layer.layer_brightness());
+ EXPECT_TRUE(layer.cc_layer_for_testing()->cache_render_surface());
+ }
+
+ // Finish the opacity animation.
+ {
+ animator->StopAnimatingProperty(LayerAnimationElement::OPACITY);
+ EXPECT_FLOAT_EQ(0.0f, layer.opacity());
+ EXPECT_FALSE(layer.cc_layer_for_testing()->cache_render_surface());
+ }
+
+ // Case 2: the original cache status if true.
+ layer.AddCacheRenderSurfaceRequest();
+ EXPECT_TRUE(layer.cc_layer_for_testing()->cache_render_surface());
+ animator->SetBrightness(1.0f);
+ animator->SetOpacity(1.0f);
+
+ // Start the brightness animation.
+ {
+ ScopedLayerAnimationSettings settings(animator.get());
+ settings.CacheRenderSurface();
+ animator->SetBrightness(0.0f);
+ }
+ EXPECT_TRUE(layer.cc_layer_for_testing()->cache_render_surface());
+
+ // Start the opacity animation.
+ {
+ ScopedLayerAnimationSettings settings(animator.get());
+ settings.CacheRenderSurface();
+ animator->SetOpacity(0.0f);
+ }
+ EXPECT_TRUE(layer.cc_layer_for_testing()->cache_render_surface());
+
+ // Finish the brightness animation.
+ {
+ animator->StopAnimatingProperty(LayerAnimationElement::BRIGHTNESS);
+ EXPECT_FLOAT_EQ(0.0f, layer.layer_brightness());
+ EXPECT_TRUE(layer.cc_layer_for_testing()->cache_render_surface());
+ }
+
+ // Finish the opacity animation.
+ {
+ animator->StopAnimatingProperty(LayerAnimationElement::OPACITY);
+ EXPECT_FLOAT_EQ(0.0f, layer.opacity());
+ EXPECT_TRUE(layer.cc_layer_for_testing()->cache_render_surface());
+ }
+}
+
// Tests that an observer added to a scoped settings object is still notified
// when the object goes out of scope due to the animation being interrupted.
TEST(LayerAnimatorTest, InterruptedImplicitAnimationObservers) {
diff --git a/chromium/ui/compositor/layer_observer.h b/chromium/ui/compositor/layer_observer.h
index fa3480bdabf..5e59deb5dab 100644
--- a/chromium/ui/compositor/layer_observer.h
+++ b/chromium/ui/compositor/layer_observer.h
@@ -11,8 +11,6 @@ namespace ui {
class Layer;
-// TODO(domlaskowski): This is only used for layer mirroring, so it should be
-// removed and replaced by a private equivalent in the Layer class.
class COMPOSITOR_EXPORT LayerObserver {
public:
virtual void LayerDestroyed(Layer* layer) {}
diff --git a/chromium/ui/compositor/layer_owner_unittest.cc b/chromium/ui/compositor/layer_owner_unittest.cc
index 94992e09755..3c1a65d666c 100644
--- a/chromium/ui/compositor/layer_owner_unittest.cc
+++ b/chromium/ui/compositor/layer_owner_unittest.cc
@@ -81,7 +81,8 @@ void LayerOwnerTestWithCompositor::SetUp() {
compositor_.reset(
new ui::Compositor(context_factory_private->AllocateFrameSinkId(),
context_factory, context_factory_private, task_runner,
- false /* enable_surface_synchronization */));
+ false /* enable_surface_synchronization */,
+ false /* enable_pixel_canvas */));
compositor_->SetAcceleratedWidget(gfx::kNullAcceleratedWidget);
}
diff --git a/chromium/ui/compositor/layer_unittest.cc b/chromium/ui/compositor/layer_unittest.cc
index fbb15a8e4eb..dcb2cf9ee7d 100644
--- a/chromium/ui/compositor/layer_unittest.cc
+++ b/chromium/ui/compositor/layer_unittest.cc
@@ -18,15 +18,16 @@
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
+#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/trace_event.h"
#include "cc/animation/animation_player.h"
#include "cc/layers/layer.h"
-#include "cc/output/copy_output_request.h"
-#include "cc/output/copy_output_result.h"
#include "cc/test/pixel_test_utils.h"
+#include "components/viz/common/quads/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_result.h"
#include "components/viz/common/surfaces/sequence_surface_reference_factory.h"
#include "components/viz/common/surfaces/surface_id.h"
#include "components/viz/common/surfaces/surface_reference_factory.h"
@@ -197,8 +198,8 @@ class LayerWithRealCompositorTest : public testing::Test {
void ReadPixels(SkBitmap* bitmap, gfx::Rect source_rect) {
scoped_refptr<ReadbackHolder> holder(new ReadbackHolder);
- std::unique_ptr<cc::CopyOutputRequest> request =
- cc::CopyOutputRequest::CreateBitmapRequest(
+ std::unique_ptr<viz::CopyOutputRequest> request =
+ viz::CopyOutputRequest::CreateBitmapRequest(
base::BindOnce(&ReadbackHolder::OutputRequestCallback, holder));
request->set_area(source_rect);
@@ -245,7 +246,7 @@ class LayerWithRealCompositorTest : public testing::Test {
public:
ReadbackHolder() : run_loop_(new base::RunLoop) {}
- void OutputRequestCallback(std::unique_ptr<cc::CopyOutputResult> result) {
+ void OutputRequestCallback(std::unique_ptr<viz::CopyOutputResult> result) {
result_ = result->TakeBitmap();
run_loop_->Quit();
}
@@ -550,7 +551,7 @@ TEST(LayerStandaloneTest, ReleaseMailboxOnDestruction) {
bool callback_run = false;
viz::TextureMailbox mailbox(gpu::Mailbox::Generate(), gpu::SyncToken(), 0);
layer->SetTextureMailbox(mailbox,
- cc::SingleReleaseCallback::Create(
+ viz::SingleReleaseCallback::Create(
base::Bind(ReturnMailbox, &callback_run)),
gfx::Size(10, 10));
EXPECT_FALSE(callback_run);
@@ -735,7 +736,7 @@ TEST_F(LayerWithDelegateTest, Cloning) {
layer->SetLayerInverted(true);
const float temperature = 0.8f;
layer->SetLayerTemperature(temperature);
- layer->SetCacheRenderSurface(true);
+ layer->AddCacheRenderSurfaceRequest();
auto clone = layer->Clone();
@@ -944,8 +945,9 @@ TEST_F(LayerWithNullDelegateTest, SwitchLayerPreservesCCLayerState) {
bool callback1_run = false;
viz::TextureMailbox mailbox(gpu::Mailbox::Generate(), gpu::SyncToken(), 0);
- l1->SetTextureMailbox(mailbox, cc::SingleReleaseCallback::Create(
- base::Bind(ReturnMailbox, &callback1_run)),
+ l1->SetTextureMailbox(mailbox,
+ viz::SingleReleaseCallback::Create(
+ base::Bind(ReturnMailbox, &callback1_run)),
gfx::Size(10, 10));
EXPECT_NE(before_layer, l1->cc_layer_for_testing());
@@ -959,8 +961,9 @@ TEST_F(LayerWithNullDelegateTest, SwitchLayerPreservesCCLayerState) {
bool callback2_run = false;
mailbox = viz::TextureMailbox(gpu::Mailbox::Generate(), gpu::SyncToken(), 0);
- l1->SetTextureMailbox(mailbox, cc::SingleReleaseCallback::Create(
- base::Bind(ReturnMailbox, &callback2_run)),
+ l1->SetTextureMailbox(mailbox,
+ viz::SingleReleaseCallback::Create(
+ base::Bind(ReturnMailbox, &callback2_run)),
gfx::Size(10, 10));
EXPECT_TRUE(callback1_run);
EXPECT_FALSE(callback2_run);
@@ -979,8 +982,9 @@ TEST_F(LayerWithNullDelegateTest, SwitchLayerPreservesCCLayerState) {
// Back to a texture, without changing the bounds of the layer or the texture.
bool callback3_run = false;
mailbox = viz::TextureMailbox(gpu::Mailbox::Generate(), gpu::SyncToken(), 0);
- l1->SetTextureMailbox(mailbox, cc::SingleReleaseCallback::Create(
- base::Bind(ReturnMailbox, &callback3_run)),
+ l1->SetTextureMailbox(mailbox,
+ viz::SingleReleaseCallback::Create(
+ base::Bind(ReturnMailbox, &callback3_run)),
gfx::Size(10, 10));
EXPECT_NE(before_layer, l1->cc_layer_for_testing());
@@ -1126,7 +1130,7 @@ TEST_F(LayerWithNullDelegateTest, SetBoundsSchedulesPaint) {
// Checks that the damage rect for a TextureLayer is empty after a commit.
TEST_F(LayerWithNullDelegateTest, EmptyDamagedRect) {
base::RunLoop run_loop;
- cc::ReleaseCallback callback =
+ viz::ReleaseCallback callback =
base::Bind([](base::RunLoop* run_loop, const gpu::SyncToken& sync_token,
bool is_lost) { run_loop->Quit(); },
base::Unretained(&run_loop));
@@ -1134,7 +1138,7 @@ TEST_F(LayerWithNullDelegateTest, EmptyDamagedRect) {
std::unique_ptr<Layer> root(CreateLayer(LAYER_SOLID_COLOR));
viz::TextureMailbox mailbox(gpu::Mailbox::Generate(), gpu::SyncToken(),
GL_TEXTURE_2D);
- root->SetTextureMailbox(mailbox, cc::SingleReleaseCallback::Create(callback),
+ root->SetTextureMailbox(mailbox, viz::SingleReleaseCallback::Create(callback),
gfx::Size(10, 10));
compositor()->SetRootLayer(root.get());
@@ -1261,9 +1265,9 @@ TEST_F(LayerWithRealCompositorTest, DrawAlphaThresholdFilterPixels) {
CreateColorLayer(blue_with_alpha, gfx::Rect(viewport_size)));
// Add a shape to restrict the visible part of the layer.
- SkRegion shape;
- shape.setRect(0, 0, viewport_size.width(), blue_height);
- foreground_layer->SetAlphaShape(base::WrapUnique(new SkRegion(shape)));
+ auto shape = base::MakeUnique<Layer::ShapeRects>();
+ shape->emplace_back(0, 0, viewport_size.width(), blue_height);
+ foreground_layer->SetAlphaShape(std::move(shape));
foreground_layer->SetFillsBoundsOpaquely(false);
@@ -2006,7 +2010,7 @@ TEST_F(LayerWithRealCompositorTest, SwitchCCLayerCacheRenderSurface) {
GetCompositor()->SetRootLayer(root.get());
root->Add(l1.get());
- l1->SetCacheRenderSurface(true);
+ l1->AddCacheRenderSurfaceRequest();
// Change l1's cc::Layer.
l1->SwitchCCLayerForTest();
diff --git a/chromium/ui/compositor/paint_cache.cc b/chromium/ui/compositor/paint_cache.cc
index 417a1798083..71b2a0e5ed3 100644
--- a/chromium/ui/compositor/paint_cache.cc
+++ b/chromium/ui/compositor/paint_cache.cc
@@ -10,30 +10,23 @@
namespace ui {
-PaintCache::PaintCache() {}
-
-PaintCache::~PaintCache() {
-}
+PaintCache::PaintCache() = default;
+PaintCache::~PaintCache() = default;
bool PaintCache::UseCache(const PaintContext& context,
const gfx::Size& size_in_context) {
if (!paint_op_buffer_)
return false;
DCHECK(context.list_);
- cc::PaintOpBuffer* buffer = context.list_->StartPaint();
- buffer->push<cc::DrawRecordOp>(paint_op_buffer_);
+ context.list_->StartPaint();
+ context.list_->push<cc::DrawRecordOp>(paint_op_buffer_);
gfx::Rect bounds_in_layer = context.ToLayerSpaceBounds(size_in_context);
context.list_->EndPaintOfUnpaired(bounds_in_layer);
return true;
}
-cc::PaintOpBuffer* PaintCache::ResetCache() {
- paint_op_buffer_ = sk_make_sp<cc::PaintOpBuffer>();
- return paint_op_buffer_.get();
-}
-
-void PaintCache::FinalizeCache() {
- paint_op_buffer_->ShrinkToFit();
+void PaintCache::SetPaintOpBuffer(sk_sp<cc::PaintOpBuffer> paint_op_buffer) {
+ paint_op_buffer_ = std::move(paint_op_buffer);
}
} // namespace ui
diff --git a/chromium/ui/compositor/paint_cache.h b/chromium/ui/compositor/paint_cache.h
index c32e96e54dd..04ae875a64e 100644
--- a/chromium/ui/compositor/paint_cache.h
+++ b/chromium/ui/compositor/paint_cache.h
@@ -36,12 +36,7 @@ class COMPOSITOR_EXPORT PaintCache {
// Only PaintRecorder can modify these.
friend PaintRecorder;
- // Resets the cache to be empty, and returns a PaintOpBuffer that is the new
- // empty cache. Adding PaintOps to the buffer will put them in the cache.
- cc::PaintOpBuffer* ResetCache();
-
- // Call when done recording into the cache's PaintOpBuffer.
- void FinalizeCache();
+ void SetPaintOpBuffer(sk_sp<cc::PaintOpBuffer> paint_op_buffer);
// Stored in an sk_sp because PaintOpBuffer requires this to append the cached
// items into it.
diff --git a/chromium/ui/compositor/paint_context.cc b/chromium/ui/compositor/paint_context.cc
index b2b4fac54b3..48e2e9d8f68 100644
--- a/chromium/ui/compositor/paint_context.cc
+++ b/chromium/ui/compositor/paint_context.cc
@@ -10,10 +10,14 @@ namespace ui {
PaintContext::PaintContext(cc::DisplayItemList* list,
float device_scale_factor,
- const gfx::Rect& invalidation)
+ const gfx::Rect& invalidation,
+ bool is_pixel_canvas)
: list_(list),
device_scale_factor_(device_scale_factor),
- invalidation_(invalidation) {
+ invalidation_(gfx::ScaleToRoundedRect(
+ invalidation,
+ is_pixel_canvas ? device_scale_factor_ : 1.f)),
+ is_pixel_canvas_(is_pixel_canvas) {
#if DCHECK_IS_ON()
root_visited_ = nullptr;
inside_paint_recorder_ = false;
@@ -25,7 +29,8 @@ PaintContext::PaintContext(const PaintContext& other,
: list_(other.list_),
device_scale_factor_(other.device_scale_factor_),
invalidation_(other.invalidation_),
- offset_(other.offset_ + offset) {
+ offset_(other.offset_ + offset),
+ is_pixel_canvas_(other.is_pixel_canvas_) {
#if DCHECK_IS_ON()
root_visited_ = other.root_visited_;
inside_paint_recorder_ = other.inside_paint_recorder_;
@@ -37,7 +42,8 @@ PaintContext::PaintContext(const PaintContext& other,
: list_(other.list_),
device_scale_factor_(other.device_scale_factor_),
invalidation_(),
- offset_(other.offset_) {
+ offset_(other.offset_),
+ is_pixel_canvas_(other.is_pixel_canvas_) {
#if DCHECK_IS_ON()
root_visited_ = other.root_visited_;
inside_paint_recorder_ = other.inside_paint_recorder_;
diff --git a/chromium/ui/compositor/paint_context.h b/chromium/ui/compositor/paint_context.h
index bc17c50f46b..96385275c43 100644
--- a/chromium/ui/compositor/paint_context.h
+++ b/chromium/ui/compositor/paint_context.h
@@ -29,7 +29,8 @@ class COMPOSITOR_EXPORT PaintContext {
// |invalidation|.
PaintContext(cc::DisplayItemList* list,
float device_scale_factor,
- const gfx::Rect& invalidation);
+ const gfx::Rect& invalidation,
+ bool is_pixel_canvas);
// Clone a PaintContext with an additional |offset|.
PaintContext(const PaintContext& other, const gfx::Vector2d& offset);
@@ -46,6 +47,13 @@ class COMPOSITOR_EXPORT PaintContext {
// invalid.
bool CanCheckInvalid() const { return !invalidation_.IsEmpty(); }
+ // The device scale of the frame being painted.
+ float device_scale_factor() const { return device_scale_factor_; }
+
+ // Returns true if the paint commands are recorded at pixel size instead of
+ // DIP.
+ bool is_pixel_canvas() const { return is_pixel_canvas_; }
+
// When true, the |bounds| touches an invalidated area, so should be
// re-painted. When false, re-painting can be skipped. Bounds should be in
// the local space with offsets up to the painting root in the PaintContext.
@@ -94,6 +102,8 @@ class COMPOSITOR_EXPORT PaintContext {
// Offset from the PaintContext to the space of the paint root and the
// |invalidation_|.
gfx::Vector2d offset_;
+ // If enabled, the paint commands are recorded at pixel size.
+ const bool is_pixel_canvas_;
#if DCHECK_IS_ON()
// Used to verify that the |invalidation_| is only used to compare against
diff --git a/chromium/ui/compositor/paint_recorder.cc b/chromium/ui/compositor/paint_recorder.cc
index 8a8c4c28caf..f85d3cbdc76 100644
--- a/chromium/ui/compositor/paint_recorder.cc
+++ b/chromium/ui/compositor/paint_recorder.cc
@@ -21,32 +21,60 @@ namespace ui {
// to the |context|'s PaintOpBuffer.
PaintRecorder::PaintRecorder(const PaintContext& context,
const gfx::Size& recording_size,
+ float recording_scale_x,
+ float recording_scale_y,
PaintCache* cache)
: context_(context),
- record_canvas_(cache ? cache->ResetCache() : context_.list_->StartPaint(),
+ local_list_(cache ? base::MakeRefCounted<cc::DisplayItemList>(
+ cc::DisplayItemList::kToBeReleasedAsPaintOpBuffer)
+ : nullptr),
+ record_canvas_(cache ? local_list_.get() : context_.list_,
gfx::RectToSkRect(gfx::Rect(recording_size))),
canvas_(&record_canvas_, context.device_scale_factor_),
cache_(cache),
recording_size_(recording_size) {
+ if (cache) {
+ local_list_->StartPaint();
+ } else {
+ context_.list_->StartPaint();
+ }
+
#if DCHECK_IS_ON()
- DCHECK(!context.inside_paint_recorder_);
- context.inside_paint_recorder_ = true;
+ DCHECK(!context_.inside_paint_recorder_);
+ context_.inside_paint_recorder_ = true;
#endif
+ if (context_.is_pixel_canvas()) {
+ canvas()->Save();
+ canvas()->Scale(recording_scale_x, recording_scale_y);
+ }
}
+// TODO(malaykeshav): The scaling of recording size needs to be handled case
+// by case and the decision to perform the scale should be moved to the caller.
PaintRecorder::PaintRecorder(const PaintContext& context,
const gfx::Size& recording_size)
- : PaintRecorder(context, recording_size, nullptr) {}
+ : PaintRecorder(
+ context,
+ gfx::ScaleToRoundedSize(
+ recording_size,
+ context.is_pixel_canvas() ? context.device_scale_factor_ : 1.f),
+ context.device_scale_factor_,
+ context.device_scale_factor_,
+ nullptr) {}
PaintRecorder::~PaintRecorder() {
#if DCHECK_IS_ON()
context_.inside_paint_recorder_ = false;
#endif
+ if (context_.is_pixel_canvas())
+ canvas()->Restore();
// If using cache, append what we've saved there to the PaintContext.
// Otherwise, the content is already stored in the PaintContext, and we can
// just close it.
if (cache_) {
- cache_->FinalizeCache();
+ local_list_->EndPaintOfUnpaired(gfx::Rect());
+ local_list_->Finalize();
+ cache_->SetPaintOpBuffer(local_list_->ReleaseAsRecord());
cache_->UseCache(context_, recording_size_);
} else {
gfx::Rect bounds_in_layer = context_.ToLayerSpaceBounds(recording_size_);
diff --git a/chromium/ui/compositor/paint_recorder.h b/chromium/ui/compositor/paint_recorder.h
index 3785c1bbc23..609d6f0bf42 100644
--- a/chromium/ui/compositor/paint_recorder.h
+++ b/chromium/ui/compositor/paint_recorder.h
@@ -8,6 +8,7 @@
#include <memory>
#include "base/macros.h"
+#include "cc/paint/display_item_list.h"
#include "cc/paint/record_paint_canvas.h"
#include "ui/compositor/compositor_export.h"
#include "ui/gfx/canvas.h"
@@ -31,6 +32,8 @@ class COMPOSITOR_EXPORT PaintRecorder {
// PaintRecorder is in use. Canvas is bounded by |recording_size|.
PaintRecorder(const PaintContext& context,
const gfx::Size& recording_size,
+ float recording_scale_x,
+ float recording_scale_y,
PaintCache* cache);
PaintRecorder(const PaintContext& context, const gfx::Size& recording_size);
~PaintRecorder();
@@ -40,6 +43,7 @@ class COMPOSITOR_EXPORT PaintRecorder {
private:
const PaintContext& context_;
+ scoped_refptr<cc::DisplayItemList> local_list_;
cc::RecordPaintCanvas record_canvas_;
gfx::Canvas canvas_;
PaintCache* cache_;
diff --git a/chromium/ui/compositor/scoped_layer_animation_settings.cc b/chromium/ui/compositor/scoped_layer_animation_settings.cc
index 71db455afb0..2ffc1250b13 100644
--- a/chromium/ui/compositor/scoped_layer_animation_settings.cc
+++ b/chromium/ui/compositor/scoped_layer_animation_settings.cc
@@ -10,11 +10,49 @@
#include "ui/compositor/layer_animation_observer.h"
#include "ui/compositor/layer_animation_sequence.h"
#include "ui/compositor/layer_animator.h"
+#include "ui/compositor/layer_observer.h"
namespace {
const int kDefaultTransitionDurationMs = 200;
+class CacheRenderSurfaceObserver : public ui::ImplicitAnimationObserver,
+ public ui::LayerObserver {
+ public:
+ CacheRenderSurfaceObserver(ui::Layer* layer) : layer_(layer) {
+ layer_->AddObserver(this);
+ layer_->AddCacheRenderSurfaceRequest();
+ }
+ ~CacheRenderSurfaceObserver() override {
+ if (layer_)
+ layer_->RemoveObserver(this);
+ }
+
+ // ui::ImplicitAnimationObserver overrides:
+ void OnImplicitAnimationsCompleted() override {
+ // If animation finishes before |layer_| is destoyed, we will reset the
+ // cache and remove |this| from the |layer_| observer list when deleting
+ // |this|.
+ if (layer_)
+ layer_->RemoveCacheRenderSurfaceRequest();
+ delete this;
+ }
+
+ // ui::LayerObserver overrides:
+ void LayerDestroyed(ui::Layer* layer) override {
+ // If the animation is still going past layer destruction then we want the
+ // layer too keep being cached until the animation has finished. We will
+ // defer deleting |this| until the animation finishes.
+ layer_->RemoveObserver(this);
+ layer_ = nullptr;
+ }
+
+ private:
+ ui::Layer* layer_;
+
+ DISALLOW_COPY_AND_ASSIGN(CacheRenderSurfaceObserver);
+};
+
} // namespace
namespace ui {
@@ -63,6 +101,11 @@ void ScopedLayerAnimationSettings::SetTransitionDuration(
animator_->SetTransitionDuration(duration);
}
+void ScopedLayerAnimationSettings::CacheRenderSurface() {
+ AddObserver(
+ new CacheRenderSurfaceObserver(animator_->delegate()->GetLayer()));
+}
+
void ScopedLayerAnimationSettings::LockTransitionDuration() {
animator_->is_transition_duration_locked_ = true;
}
diff --git a/chromium/ui/compositor/scoped_layer_animation_settings.h b/chromium/ui/compositor/scoped_layer_animation_settings.h
index ddc6d68499b..61867126bca 100644
--- a/chromium/ui/compositor/scoped_layer_animation_settings.h
+++ b/chromium/ui/compositor/scoped_layer_animation_settings.h
@@ -31,6 +31,9 @@ class COMPOSITOR_EXPORT ScopedLayerAnimationSettings {
void SetAnimationMetricsReporter(AnimationMetricsReporter* reporter);
void SetTransitionDuration(base::TimeDelta duration);
+ // This will request render surface caching on the animating layer. The cache
+ // request will be removed at the end of the animation.
+ void CacheRenderSurface();
base::TimeDelta GetTransitionDuration() const;
// Locks transition duration in |animator_|. When transition duration
diff --git a/chromium/ui/compositor/test/test_compositor_host_ozone.cc b/chromium/ui/compositor/test/test_compositor_host_ozone.cc
index 97d33afa448..1659d9331d9 100644
--- a/chromium/ui/compositor/test/test_compositor_host_ozone.cc
+++ b/chromium/ui/compositor/test/test_compositor_host_ozone.cc
@@ -84,7 +84,8 @@ TestCompositorHostOzone::TestCompositorHostOzone(
context_factory,
context_factory_private,
base::ThreadTaskRunnerHandle::Get(),
- false /* enable_surface_synchronization */) {}
+ false /* enable_surface_synchronization */,
+ false /* enable_pixel_canvas */) {}
TestCompositorHostOzone::~TestCompositorHostOzone() {}
diff --git a/chromium/ui/compositor/transform_animation_curve_adapter_unittest.cc b/chromium/ui/compositor/transform_animation_curve_adapter_unittest.cc
index b5b44e90270..7c80133bb28 100644
--- a/chromium/ui/compositor/transform_animation_curve_adapter_unittest.cc
+++ b/chromium/ui/compositor/transform_animation_curve_adapter_unittest.cc
@@ -7,7 +7,6 @@
#include <sstream>
#include "base/time/time.h"
-#include "cc/base/time_util.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/compositor/test/test_utils.h"
@@ -39,7 +38,7 @@ TEST(InverseTransformCurveAdapterTest, InversesTransform) {
static const int kSteps = 1000;
double step = 1.0 / kSteps;
for (int i = 0; i <= kSteps; ++i) {
- base::TimeDelta time_step = cc::TimeUtil::Scale(duration, i * step);
+ base::TimeDelta time_step = duration * (i * step);
std::ostringstream message;
message << "Step " << i << " of " << kSteps;
SCOPED_TRACE(message.str());
diff --git a/chromium/ui/compositor/transform_recorder.cc b/chromium/ui/compositor/transform_recorder.cc
index 525de51cc98..4175f1e4fbc 100644
--- a/chromium/ui/compositor/transform_recorder.cc
+++ b/chromium/ui/compositor/transform_recorder.cc
@@ -17,8 +17,8 @@ TransformRecorder::~TransformRecorder() {
if (!transformed_)
return;
- cc::PaintOpBuffer* buffer = context_.list_->StartPaint();
- buffer->push<cc::RestoreOp>();
+ context_.list_->StartPaint();
+ context_.list_->push<cc::RestoreOp>();
context_.list_->EndPaintOfPairedEnd();
}
@@ -27,9 +27,9 @@ void TransformRecorder::Transform(const gfx::Transform& transform) {
if (transform.IsIdentity())
return;
- cc::PaintOpBuffer* buffer = context_.list_->StartPaint();
- buffer->push<cc::SaveOp>();
- buffer->push<cc::ConcatOp>(static_cast<SkMatrix>(transform.matrix()));
+ context_.list_->StartPaint();
+ context_.list_->push<cc::SaveOp>();
+ context_.list_->push<cc::ConcatOp>(static_cast<SkMatrix>(transform.matrix()));
context_.list_->EndPaintOfPairedBegin();
transformed_ = true;
diff --git a/chromium/ui/display/BUILD.gn b/chromium/ui/display/BUILD.gn
index 0d7b80d03ac..f4a4f5b3c94 100644
--- a/chromium/ui/display/BUILD.gn
+++ b/chromium/ui/display/BUILD.gn
@@ -145,7 +145,6 @@ test("display_unittests") {
"manager/chromeos/configure_displays_task_unittest.cc",
"manager/chromeos/display_change_observer_unittest.cc",
"manager/chromeos/display_configurator_unittest.cc",
- "manager/chromeos/mojo/touch_device_transform_struct_traits_unittest.cc",
"manager/chromeos/query_content_protection_task_unittest.cc",
"manager/chromeos/touch_transform_controller_unittest.cc",
"manager/chromeos/touchscreen_util_unittest.cc",
@@ -171,10 +170,10 @@ test("display_unittests") {
"//testing/gmock",
"//testing/gtest",
"//ui/display/manager",
- "//ui/display/manager/chromeos/mojo:interfaces",
"//ui/display/mojo:interfaces",
"//ui/display/types",
"//ui/display/util",
+ "//ui/events:test_support",
"//ui/events/devices",
"//ui/gfx:test_support",
"//ui/gfx/geometry",
@@ -185,11 +184,4 @@ test("display_unittests") {
# does not compile display_observer.cc
sources -= [ "display_change_notifier_unittest.cc" ]
}
-
- if (is_chromeos && use_x11) {
- sources += [
- "manager/chromeos/x11/display_util_x11_unittest.cc",
- "manager/chromeos/x11/native_display_event_dispatcher_x11_unittest.cc",
- ]
- }
}
diff --git a/chromium/ui/display/display.cc b/chromium/ui/display/display.cc
index e5a0414b3a9..c0901916615 100644
--- a/chromium/ui/display/display.cc
+++ b/chromium/ui/display/display.cc
@@ -61,7 +61,8 @@ int64_t internal_display_id_ = -1;
} // namespace
bool CompareDisplayIds(int64_t id1, int64_t id2) {
- DCHECK_NE(id1, id2);
+ if (id1 == id2)
+ return false;
// Output index is stored in the first 8 bits. See GetDisplayIdFromEDID
// in edid_parser.cc.
int index_1 = id1 & 0xFF;
@@ -94,6 +95,7 @@ void Display::ResetForceDeviceScaleFactorForTesting() {
// static
void Display::SetForceDeviceScaleFactor(double dsf) {
// Reset any previously set values and unset the flag.
+ g_has_forced_device_scale_factor = -1;
g_forced_device_scale_factor = -1.0;
base::CommandLine::ForCurrentProcess()->AppendSwitchASCII(
@@ -108,6 +110,12 @@ gfx::ColorSpace Display::GetForcedColorProfile() {
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);
@@ -143,14 +151,11 @@ Display::Display(int64_t id, const gfx::Rect& bounds)
bounds_(bounds),
work_area_(bounds),
device_scale_factor_(GetForcedDeviceScaleFactor()),
- color_space_(HasForceColorProfile() ? GetForcedColorProfile()
- : gfx::ColorSpace::CreateSRGB()),
+ color_space_(gfx::ColorSpace::CreateSRGB()),
color_depth_(DEFAULT_BITS_PER_PIXEL),
depth_per_component_(DEFAULT_BITS_PER_COMPONENT) {
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(switches::kEnableHDR)) {
- color_depth_ = HDR_BITS_PER_PIXEL;
- depth_per_component_ = HDR_BITS_PER_COMPONENT;
- }
+ if (HasForceColorProfile())
+ SetColorSpaceAndDepth(GetForcedColorProfile());
#if defined(USE_AURA)
SetScaleAndBounds(device_scale_factor_, bounds);
#endif
@@ -231,6 +236,17 @@ void Display::SetSize(const gfx::Size& size_in_pixel) {
SetScaleAndBounds(device_scale_factor_, gfx::Rect(origin, size_in_pixel));
}
+void Display::SetColorSpaceAndDepth(const gfx::ColorSpace& color_space) {
+ color_space_ = color_space;
+ if (color_space_.IsHDR()) {
+ color_depth_ = HDR_BITS_PER_PIXEL;
+ depth_per_component_ = HDR_BITS_PER_COMPONENT;
+ } else {
+ color_depth_ = DEFAULT_BITS_PER_PIXEL;
+ depth_per_component_ = DEFAULT_BITS_PER_COMPONENT;
+ }
+}
+
void Display::UpdateWorkAreaFromInsets(const gfx::Insets& insets) {
work_area_ = bounds_;
work_area_.Inset(insets);
diff --git a/chromium/ui/display/display.h b/chromium/ui/display/display.h
index d81227aabbb..4690594ad7c 100644
--- a/chromium/ui/display/display.h
+++ b/chromium/ui/display/display.h
@@ -192,12 +192,16 @@ class DISPLAY_EXPORT Display final {
maximum_cursor_size_ = size;
}
- // The full color space of the display.
+ // The color space of the display.
gfx::ColorSpace color_space() const { return color_space_; }
void set_color_space(const gfx::ColorSpace& color_space) {
color_space_ = color_space;
}
+ // Set the color space of the display and reset the color depth and depth per
+ // component based on whether or not the color space is HDR.
+ void SetColorSpaceAndDepth(const gfx::ColorSpace& color_space);
+
// The number of bits per pixel. Used by media query APIs.
int color_depth() const { return color_depth_; }
void set_color_depth(int color_depth) {
diff --git a/chromium/ui/display/display_switches.cc b/chromium/ui/display/display_switches.cc
index d4f897ce487..354b483ba1f 100644
--- a/chromium/ui/display/display_switches.cc
+++ b/chromium/ui/display/display_switches.cc
@@ -43,15 +43,17 @@ const char kScreenConfig[] = "screen-config";
// This is for debugging on linux desktop.
const char kUseFirstDisplayAsInternal[] = "use-first-display-as-internal";
-// Use an fp16 scRGB swap chain compatible with HDR output.
-const char kEnableHDR[] = "enable-hdr";
-
#if defined(OS_CHROMEOS)
-const char kDisableDisplayColorCalibration[] =
- "disable-display-color-calibration";
// Enables unified desktop mode.
const char kEnableUnifiedDesktop[] = "ash-enable-unified-desktop";
#endif
} // namespace switches
+
+namespace features {
+
+const base::Feature kHighDynamicRange{"HighDynamicRange",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+} // namespace features
diff --git a/chromium/ui/display/display_switches.h b/chromium/ui/display/display_switches.h
index 610ba111574..b88b99256f2 100644
--- a/chromium/ui/display/display_switches.h
+++ b/chromium/ui/display/display_switches.h
@@ -6,6 +6,7 @@
#define UI_DISPLAY_DISPLAY_SWITCHES_H_
#include "base/compiler_specific.h"
+#include "base/feature_list.h"
#include "build/build_config.h"
#include "ui/display/display_export.h"
@@ -20,13 +21,17 @@ DISPLAY_EXPORT extern const char kHostWindowBounds[];
DISPLAY_EXPORT extern const char kScreenConfig[];
DISPLAY_EXPORT extern const char kSecondaryDisplayLayout[];
DISPLAY_EXPORT extern const char kUseFirstDisplayAsInternal[];
-DISPLAY_EXPORT extern const char kEnableHDR[];
#if defined(OS_CHROMEOS)
-DISPLAY_EXPORT extern const char kDisableDisplayColorCalibration[];
DISPLAY_EXPORT extern const char kEnableUnifiedDesktop[];
#endif
} // namespace switches
+namespace features {
+
+DISPLAY_EXPORT extern const base::Feature kHighDynamicRange;
+
+} // namespace features
+
#endif // UI_DISPLAY_DISPLAY_SWITCHES_H_
diff --git a/chromium/ui/display/display_unittest.cc b/chromium/ui/display/display_unittest.cc
index aa0b55d5212..8fb0a0fdcf7 100644
--- a/chromium/ui/display/display_unittest.cc
+++ b/chromium/ui/display/display_unittest.cc
@@ -72,20 +72,17 @@ TEST(DisplayTest, ForcedDeviceScaleFactor) {
}
TEST(DisplayTest, DisplayHDRValues) {
- base::test::ScopedCommandLine scoped_command_line;
- base::CommandLine* command_line = scoped_command_line.GetProcessCommandLine();
- {
- Display display;
- EXPECT_EQ(24, display.color_depth());
- EXPECT_EQ(8, display.depth_per_component());
- }
-
- command_line->AppendSwitch(switches::kEnableHDR);
- {
- Display display;
- EXPECT_EQ(48, display.color_depth());
- EXPECT_EQ(16, display.depth_per_component());
- }
+ Display display;
+ EXPECT_EQ(24, display.color_depth());
+ EXPECT_EQ(8, display.depth_per_component());
+
+ display.SetColorSpaceAndDepth(gfx::ColorSpace::CreateSCRGBLinear());
+ EXPECT_EQ(48, display.color_depth());
+ EXPECT_EQ(16, display.depth_per_component());
+
+ display.SetColorSpaceAndDepth(gfx::ColorSpace::CreateSRGB());
+ EXPECT_EQ(24, display.color_depth());
+ EXPECT_EQ(8, display.depth_per_component());
}
} // namespace display
diff --git a/chromium/ui/display/fake_display_delegate.cc b/chromium/ui/display/fake_display_delegate.cc
index ba6ad179280..bc31a7275f4 100644
--- a/chromium/ui/display/fake_display_delegate.cc
+++ b/chromium/ui/display/fake_display_delegate.cc
@@ -108,10 +108,6 @@ void FakeDisplayDelegate::Initialize() {
initialized_ = true;
}
-void FakeDisplayDelegate::GrabServer() {}
-
-void FakeDisplayDelegate::UngrabServer() {}
-
void FakeDisplayDelegate::TakeDisplayControl(
const DisplayControlCallback& callback) {
callback.Run(false);
@@ -122,12 +118,6 @@ void FakeDisplayDelegate::RelinquishDisplayControl(
callback.Run(false);
}
-void FakeDisplayDelegate::SyncWithServer() {}
-
-void FakeDisplayDelegate::SetBackgroundColor(uint32_t color_argb) {}
-
-void FakeDisplayDelegate::ForceDPMSOn() {}
-
void FakeDisplayDelegate::GetDisplays(const GetDisplaysCallback& callback) {
std::vector<DisplaySnapshot*> displays;
for (auto& display : displays_)
@@ -135,9 +125,6 @@ void FakeDisplayDelegate::GetDisplays(const GetDisplaysCallback& callback) {
callback.Run(displays);
}
-void FakeDisplayDelegate::AddMode(const DisplaySnapshot& output,
- const DisplayMode* mode) {}
-
void FakeDisplayDelegate::Configure(const DisplaySnapshot& output,
const DisplayMode* mode,
const gfx::Point& origin,
@@ -169,8 +156,6 @@ void FakeDisplayDelegate::Configure(const DisplaySnapshot& output,
}
}
-void FakeDisplayDelegate::CreateFrameBuffer(const gfx::Size& size) {}
-
void FakeDisplayDelegate::GetHDCPState(const DisplaySnapshot& output,
const GetHDCPStateCallback& callback) {
callback.Run(false, HDCP_STATE_UNDESIRED);
@@ -182,18 +167,6 @@ void FakeDisplayDelegate::SetHDCPState(const DisplaySnapshot& output,
callback.Run(false);
}
-std::vector<ColorCalibrationProfile>
-FakeDisplayDelegate::GetAvailableColorCalibrationProfiles(
- const DisplaySnapshot& output) {
- return std::vector<ColorCalibrationProfile>();
-}
-
-bool FakeDisplayDelegate::SetColorCalibrationProfile(
- const DisplaySnapshot& output,
- ColorCalibrationProfile new_profile) {
- return false;
-}
-
bool FakeDisplayDelegate::SetColorCorrection(
const DisplaySnapshot& output,
const std::vector<GammaRampRGBEntry>& degamma_lut,
diff --git a/chromium/ui/display/fake_display_delegate.h b/chromium/ui/display/fake_display_delegate.h
index 73e5f36dc7d..17d34fefec6 100644
--- a/chromium/ui/display/fake_display_delegate.h
+++ b/chromium/ui/display/fake_display_delegate.h
@@ -81,30 +81,19 @@ class DISPLAY_EXPORT FakeDisplayDelegate : public NativeDisplayDelegate,
// NativeDisplayDelegate overrides:
void Initialize() override;
- void GrabServer() override;
- void UngrabServer() override;
void TakeDisplayControl(const DisplayControlCallback& callback) override;
void RelinquishDisplayControl(
const DisplayControlCallback& callback) override;
- void SyncWithServer() override;
- void SetBackgroundColor(uint32_t color_argb) override;
- void ForceDPMSOn() override;
void GetDisplays(const GetDisplaysCallback& callback) override;
- void AddMode(const DisplaySnapshot& output, const DisplayMode* mode) override;
void Configure(const DisplaySnapshot& output,
const DisplayMode* mode,
const gfx::Point& origin,
const ConfigureCallback& callback) override;
- void CreateFrameBuffer(const gfx::Size& size) override;
void GetHDCPState(const DisplaySnapshot& output,
const GetHDCPStateCallback& callback) override;
void SetHDCPState(const DisplaySnapshot& output,
HDCPState state,
const SetHDCPStateCallback& callback) override;
- std::vector<ColorCalibrationProfile> GetAvailableColorCalibrationProfiles(
- const DisplaySnapshot& output) override;
- bool SetColorCalibrationProfile(const DisplaySnapshot& output,
- ColorCalibrationProfile new_profile) override;
bool SetColorCorrection(const DisplaySnapshot& output,
const std::vector<GammaRampRGBEntry>& degamma_lut,
const std::vector<GammaRampRGBEntry>& gamma_lut,
diff --git a/chromium/ui/display/fake_display_snapshot.cc b/chromium/ui/display/fake_display_snapshot.cc
index c7294a56fb9..bd5951118a5 100644
--- a/chromium/ui/display/fake_display_snapshot.cc
+++ b/chromium/ui/display/fake_display_snapshot.cc
@@ -6,7 +6,6 @@
#include <inttypes.h>
-#include <sstream>
#include <utility>
#include <vector>
@@ -29,42 +28,6 @@ float PixelPitchMmFromDPI(float dpi) {
return (1.0f / dpi) * kInchInMm;
}
-std::string ModeListString(
- const std::vector<std::unique_ptr<const DisplayMode>>& modes) {
- std::stringstream stream;
- bool first = true;
- for (auto& mode : modes) {
- if (!first)
- stream << ", ";
- stream << mode->ToString();
- first = false;
- }
- return stream.str();
-}
-
-std::string DisplayConnectionTypeString(DisplayConnectionType type) {
- switch (type) {
- case DISPLAY_CONNECTION_TYPE_NONE:
- return "none";
- case DISPLAY_CONNECTION_TYPE_UNKNOWN:
- return "unknown";
- case DISPLAY_CONNECTION_TYPE_INTERNAL:
- return "internal";
- case DISPLAY_CONNECTION_TYPE_VGA:
- return "vga";
- case DISPLAY_CONNECTION_TYPE_HDMI:
- return "hdmi";
- case DISPLAY_CONNECTION_TYPE_DVI:
- return "dvi";
- case DISPLAY_CONNECTION_TYPE_DISPLAYPORT:
- return "dp";
- case DISPLAY_CONNECTION_TYPE_NETWORK:
- return "network";
- }
- NOTREACHED();
- return "";
-}
-
// Extracts text after specified delimiter. If the delimiter doesn't appear
// exactly once the result will be empty and the input string will be
// unmodified. Otherwise, the input string will contain the text before the
@@ -200,8 +163,8 @@ std::unique_ptr<FakeDisplaySnapshot> Builder::Build() {
return base::MakeUnique<FakeDisplaySnapshot>(
id_, origin_, physical_size, type_, is_aspect_preserving_scaling_,
- has_overscan_, has_color_correction_matrix_, name_, product_id_,
- std::move(modes_), current_mode_, native_mode_);
+ has_overscan_, has_color_correction_matrix_, name_, std::move(modes_),
+ current_mode_, native_mode_, product_id_, maximum_cursor_size_);
}
Builder& Builder::SetId(int64_t id) {
@@ -274,6 +237,11 @@ Builder& Builder::SetProductId(int64_t product_id) {
return *this;
}
+Builder& Builder::SetMaximumCursorSize(const gfx::Size& maximum_cursor_size) {
+ maximum_cursor_size_ = maximum_cursor_size;
+ return *this;
+}
+
Builder& Builder::SetDPI(int dpi) {
dpi_ = static_cast<float>(dpi);
return *this;
@@ -320,10 +288,11 @@ FakeDisplaySnapshot::FakeDisplaySnapshot(int64_t display_id,
bool has_overscan,
bool has_color_correction_matrix,
std::string display_name,
- int64_t product_id,
DisplayModeList modes,
const DisplayMode* current_mode,
- const DisplayMode* native_mode)
+ const DisplayMode* native_mode,
+ int64_t product_id,
+ const gfx::Size& maximum_cursor_size)
: DisplaySnapshot(display_id,
origin,
physical_size,
@@ -336,9 +305,9 @@ FakeDisplaySnapshot::FakeDisplaySnapshot(int64_t display_id,
std::move(modes),
std::vector<uint8_t>(),
current_mode,
- native_mode) {
- product_id_ = product_id;
-}
+ native_mode,
+ product_id,
+ maximum_cursor_size) {}
FakeDisplaySnapshot::~FakeDisplaySnapshot() {}
@@ -371,17 +340,4 @@ std::unique_ptr<DisplaySnapshot> FakeDisplaySnapshot::CreateFromSpec(
return builder.Build();
}
-std::string FakeDisplaySnapshot::ToString() const {
- return base::StringPrintf(
- "id=%" PRId64
- " current_mode=%s native_mode=%s origin=%s"
- " physical_size=%s, type=%s name=\"%s\" modes=(%s)",
- display_id_,
- current_mode_ ? current_mode_->ToString().c_str() : "nullptr",
- native_mode_ ? native_mode_->ToString().c_str() : "nullptr",
- origin_.ToString().c_str(), physical_size_.ToString().c_str(),
- DisplayConnectionTypeString(type_).c_str(), display_name_.c_str(),
- ModeListString(modes_).c_str());
-}
-
} // namespace display
diff --git a/chromium/ui/display/fake_display_snapshot.h b/chromium/ui/display/fake_display_snapshot.h
index 1cb0b46d0a9..c6502d9009b 100644
--- a/chromium/ui/display/fake_display_snapshot.h
+++ b/chromium/ui/display/fake_display_snapshot.h
@@ -60,6 +60,7 @@ class DISPLAY_EXPORT FakeDisplaySnapshot : public DisplaySnapshot {
Builder& SetHasColorCorrectionMatrix(bool val);
Builder& SetName(const std::string& name);
Builder& SetProductId(int64_t product_id);
+ Builder& SetMaximumCursorSize(const gfx::Size& maximum_cursor_size);
// Sets physical_size so that the screen has the specified DPI using the
// native resolution.
Builder& SetDPI(int dpi);
@@ -85,6 +86,7 @@ class DISPLAY_EXPORT FakeDisplaySnapshot : public DisplaySnapshot {
bool has_color_correction_matrix_ = false;
std::string name_;
int64_t product_id_ = DisplaySnapshot::kInvalidProductID;
+ gfx::Size maximum_cursor_size_ = gfx::Size(64, 64);
DisplayModeList modes_;
const DisplayMode* current_mode_ = nullptr;
const DisplayMode* native_mode_ = nullptr;
@@ -100,10 +102,11 @@ class DISPLAY_EXPORT FakeDisplaySnapshot : public DisplaySnapshot {
bool has_overscan,
bool has_color_correction_matrix,
std::string display_name,
- int64_t product_id,
DisplayModeList modes,
const DisplayMode* current_mode,
- const DisplayMode* native_mode);
+ const DisplayMode* native_mode,
+ int64_t product_id,
+ const gfx::Size& maximum_cursor_size);
~FakeDisplaySnapshot() override;
// Creates a display snapshot from the provided |spec| string. Returns null if
@@ -113,9 +116,6 @@ class DISPLAY_EXPORT FakeDisplaySnapshot : public DisplaySnapshot {
int64_t id,
const std::string& spec);
- // DisplaySnapshot:
- std::string ToString() const override;
-
private:
DISALLOW_COPY_AND_ASSIGN(FakeDisplaySnapshot);
};
diff --git a/chromium/ui/display/mac/screen_mac.mm b/chromium/ui/display/mac/screen_mac.mm
index 11eca13659c..da151150c5e 100644
--- a/chromium/ui/display/mac/screen_mac.mm
+++ b/chromium/ui/display/mac/screen_mac.mm
@@ -90,8 +90,10 @@ Display BuildDisplayForScreen(NSScreen* screen) {
base::FeatureList::IsEnabled(features::kColorCorrectRendering);
if (base::mac::IsAtLeastOS10_12() && !color_correct_rendering_enabled)
color_space = base::mac::GetSystemColorSpace();
- display.set_color_space(
- gfx::ICCProfile::FromCGColorSpace(color_space).GetColorSpace());
+ gfx::ICCProfile icc_profile =
+ gfx::ICCProfile::FromCGColorSpace(color_space);
+ icc_profile.HistogramDisplay(display.id());
+ display.set_color_space(icc_profile.GetColorSpace());
}
display.set_color_depth(NSBitsPerPixelFromDepth([screen depth]));
display.set_depth_per_component(NSBitsPerSampleFromDepth([screen depth]));
diff --git a/chromium/ui/display/manager/BUILD.gn b/chromium/ui/display/manager/BUILD.gn
index e646a6f0376..ba0f5911fcb 100644
--- a/chromium/ui/display/manager/BUILD.gn
+++ b/chromium/ui/display/manager/BUILD.gn
@@ -21,8 +21,6 @@ component("manager") {
"chromeos/display_util.h",
"chromeos/query_content_protection_task.cc",
"chromeos/query_content_protection_task.h",
- "chromeos/touch_device_transform.cc",
- "chromeos/touch_device_transform.h",
"chromeos/touch_transform_controller.cc",
"chromeos/touch_transform_controller.h",
"chromeos/touch_transform_setter.h",
@@ -64,32 +62,4 @@ component("manager") {
if (is_chromeos) {
deps += [ "//chromeos" ]
}
-
- if (use_x11) {
- deps += [ "//ui/gfx/x" ]
- }
-
- if (is_chromeos && use_x11) {
- sources += [
- "chromeos/x11/display_mode_x11.cc",
- "chromeos/x11/display_mode_x11.h",
- "chromeos/x11/display_snapshot_x11.cc",
- "chromeos/x11/display_snapshot_x11.h",
- "chromeos/x11/display_util_x11.cc",
- "chromeos/x11/display_util_x11.h",
- "chromeos/x11/native_display_delegate_x11.cc",
- "chromeos/x11/native_display_delegate_x11.h",
- "chromeos/x11/native_display_event_dispatcher_x11.cc",
- "chromeos/x11/native_display_event_dispatcher_x11.h",
- ]
-
- configs += [
- "//build/config/linux:x11",
- "//build/config/linux:xext",
- "//build/config/linux:xi",
- "//build/config/linux:xrandr",
- ]
-
- deps += [ "//ui/events/platform" ]
- }
}
diff --git a/chromium/ui/display/manager/chromeos/DEPS b/chromium/ui/display/manager/chromeos/DEPS
index 5943a4fe475..5663dc26aa0 100644
--- a/chromium/ui/display/manager/chromeos/DEPS
+++ b/chromium/ui/display/manager/chromeos/DEPS
@@ -15,5 +15,6 @@ specific_include_rules = {
],
"touch_transform_controller_unittest.cc": [
"+ui/events/devices/device_data_manager.h",
+ "+ui/events/test/device_data_manager_test_api.h",
],
}
diff --git a/chromium/ui/display/manager/chromeos/default_touch_transform_setter.cc b/chromium/ui/display/manager/chromeos/default_touch_transform_setter.cc
index cd94a89c24a..1e9f12c9a84 100644
--- a/chromium/ui/display/manager/chromeos/default_touch_transform_setter.cc
+++ b/chromium/ui/display/manager/chromeos/default_touch_transform_setter.cc
@@ -4,8 +4,8 @@
#include "ui/display/manager/chromeos/default_touch_transform_setter.h"
-#include "ui/display/manager/chromeos/touch_device_transform.h"
#include "ui/events/devices/device_data_manager.h"
+#include "ui/events/devices/touch_device_transform.h"
namespace display {
@@ -14,18 +14,8 @@ DefaultTouchTransformSetter::DefaultTouchTransformSetter() = default;
DefaultTouchTransformSetter::~DefaultTouchTransformSetter() = default;
void DefaultTouchTransformSetter::ConfigureTouchDevices(
- const std::map<int32_t, double>& scales,
- const std::vector<TouchDeviceTransform>& transforms) {
- ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance();
- device_manager->ClearTouchDeviceAssociations();
- for (auto& device_scale_pair : scales) {
- device_manager->UpdateTouchRadiusScale(device_scale_pair.first,
- device_scale_pair.second);
- }
- for (const TouchDeviceTransform& transform : transforms) {
- device_manager->UpdateTouchInfoForDisplay(
- transform.display_id, transform.device_id, transform.transform);
- }
+ const std::vector<ui::TouchDeviceTransform>& transforms) {
+ ui::DeviceDataManager::GetInstance()->ConfigureTouchDevices(transforms);
}
} // namespace display
diff --git a/chromium/ui/display/manager/chromeos/default_touch_transform_setter.h b/chromium/ui/display/manager/chromeos/default_touch_transform_setter.h
index aa451f750ae..7f64f27c10e 100644
--- a/chromium/ui/display/manager/chromeos/default_touch_transform_setter.h
+++ b/chromium/ui/display/manager/chromeos/default_touch_transform_setter.h
@@ -18,8 +18,7 @@ class DISPLAY_MANAGER_EXPORT DefaultTouchTransformSetter
// TouchTransformSetter:
void ConfigureTouchDevices(
- const std::map<int32_t, double>& scales,
- const std::vector<TouchDeviceTransform>& transforms) override;
+ const std::vector<ui::TouchDeviceTransform>& transforms) override;
private:
DISALLOW_COPY_AND_ASSIGN(DefaultTouchTransformSetter);
diff --git a/chromium/ui/display/manager/chromeos/display_change_observer.cc b/chromium/ui/display/manager/chromeos/display_change_observer.cc
index 392598069bb..de95a0090c4 100644
--- a/chromium/ui/display/manager/chromeos/display_change_observer.cc
+++ b/chromium/ui/display/manager/chromeos/display_change_observer.cc
@@ -54,17 +54,6 @@ const int kMinimumWidthFor4K = 3840;
// available in external large monitors.
const float kAdditionalDeviceScaleFactorsFor4k[] = {1.25f, 2.0f};
-void UpdateInternalDisplayId(
- const DisplayConfigurator::DisplayStateList& display_states) {
- for (auto* state : display_states) {
- if (state->type() == DISPLAY_CONNECTION_TYPE_INTERNAL) {
- if (Display::HasInternalDisplay())
- DCHECK_EQ(Display::InternalDisplayId(), state->display_id());
- Display::SetInternalDisplayId(state->display_id());
- }
- }
-}
-
} // namespace
// static
@@ -152,8 +141,8 @@ DisplayChangeObserver::~DisplayChangeObserver() {
}
MultipleDisplayState DisplayChangeObserver::GetStateForDisplayIds(
- const DisplayConfigurator::DisplayStateList& display_states) const {
- UpdateInternalDisplayId(display_states);
+ const DisplayConfigurator::DisplayStateList& display_states) {
+ UpdateInternalDisplay(display_states);
if (display_states.size() == 1)
return MULTIPLE_DISPLAY_STATE_SINGLE;
DisplayIdList list =
@@ -180,78 +169,15 @@ bool DisplayChangeObserver::GetResolutionForDisplayId(int64_t display_id,
void DisplayChangeObserver::OnDisplayModeChanged(
const DisplayConfigurator::DisplayStateList& display_states) {
- UpdateInternalDisplayId(display_states);
+ UpdateInternalDisplay(display_states);
std::vector<ManagedDisplayInfo> displays;
- std::set<int64_t> ids;
for (const DisplaySnapshot* state : display_states) {
const DisplayMode* mode_info = state->current_mode();
if (!mode_info)
continue;
- float device_scale_factor = 1.0f;
- // Sets dpi only if the screen size is not blacklisted.
- float dpi = IsDisplaySizeBlackListed(state->physical_size())
- ? 0
- : kInchInMm * mode_info->size().width() /
- state->physical_size().width();
- if (state->type() == DISPLAY_CONNECTION_TYPE_INTERNAL) {
- if (dpi)
- device_scale_factor = FindDeviceScaleFactor(dpi);
- } else {
- scoped_refptr<ManagedDisplayMode> mode =
- display_manager_->GetSelectedModeForDisplayId(state->display_id());
- if (mode) {
- device_scale_factor = mode->device_scale_factor();
- } else {
- // For monitors that are 40 inches and 4K or above, set
- // |device_scale_factor| to 2x. For margin purposes, 100 is subtracted
- // from the value of |k2xThreshouldSizeSquaredFor4KInMm|
- const int k2xThreshouldSizeSquaredFor4KInMm =
- (40 * 40 * kInchInMm * kInchInMm) - 100;
- gfx::Vector2d size_in_vec(state->physical_size().width(),
- state->physical_size().height());
- if (size_in_vec.LengthSquared() > k2xThreshouldSizeSquaredFor4KInMm &&
- mode_info->size().width() >= kMinimumWidthFor4K) {
- // Make sure that additional device scale factors table has 2x.
- DCHECK_EQ(2.0f, kAdditionalDeviceScaleFactorsFor4k[1]);
- device_scale_factor = 2.0f;
- }
- }
- }
- gfx::Rect display_bounds(state->origin(), mode_info->size());
-
- std::string name = (state->type() == DISPLAY_CONNECTION_TYPE_INTERNAL)
- ? l10n_util::GetStringUTF8(IDS_DISPLAY_NAME_INTERNAL)
- : state->display_name();
-
- if (name.empty())
- name = l10n_util::GetStringUTF8(IDS_DISPLAY_NAME_UNKNOWN);
-
- bool has_overscan = state->has_overscan();
- int64_t id = state->display_id();
- ids.insert(id);
-
- displays.push_back(ManagedDisplayInfo(id, name, has_overscan));
- ManagedDisplayInfo& new_info = displays.back();
- new_info.set_sys_path(state->sys_path());
- new_info.set_device_scale_factor(device_scale_factor);
- new_info.SetBounds(display_bounds);
- new_info.set_native(true);
- new_info.set_is_aspect_preserving_scaling(
- state->is_aspect_preserving_scaling());
- if (dpi)
- new_info.set_device_dpi(dpi);
-
- ManagedDisplayInfo::ManagedDisplayModeList display_modes =
- (state->type() == DISPLAY_CONNECTION_TYPE_INTERNAL)
- ? GetInternalManagedDisplayModeList(new_info, *state)
- : GetExternalManagedDisplayModeList(*state);
- new_info.SetManagedDisplayModes(display_modes);
-
- new_info.set_available_color_profiles(
- display_configurator_->GetAvailableColorCalibrationProfiles(id));
- new_info.set_maximum_cursor_size(state->maximum_cursor_size());
+ displays.emplace_back(CreateManagedDisplayInfo(state, mode_info));
}
AssociateTouchscreens(
@@ -288,6 +214,97 @@ void DisplayChangeObserver::OnTouchscreenDeviceConfigurationChanged() {
OnDisplayModeChanged(cached_displays);
}
+void DisplayChangeObserver::UpdateInternalDisplay(
+ const DisplayConfigurator::DisplayStateList& display_states) {
+ for (auto* state : display_states) {
+ if (state->type() == DISPLAY_CONNECTION_TYPE_INTERNAL) {
+ if (Display::HasInternalDisplay())
+ DCHECK_EQ(Display::InternalDisplayId(), state->display_id());
+ Display::SetInternalDisplayId(state->display_id());
+
+ if (state->native_mode() &&
+ (!display_manager_->IsDisplayIdValid(state->display_id()) ||
+ !state->current_mode())) {
+ // Register the internal display info if
+ // 1) If it's not already registered. It'll be treated as
+ // new display in |UpdateDisplaysWith()|.
+ // 2) If it's not connected, because the display info will not
+ // be updated in |UpdateDisplaysWith()|, which will skips the
+ // disconnected displays.
+ ManagedDisplayInfo new_info =
+ CreateManagedDisplayInfo(state, state->native_mode());
+ display_manager_->UpdateInternalDisplay(new_info);
+ }
+ }
+ }
+}
+
+ManagedDisplayInfo DisplayChangeObserver::CreateManagedDisplayInfo(
+ const DisplaySnapshot* state,
+ const DisplayMode* mode_info) {
+ float device_scale_factor = 1.0f;
+ // Sets dpi only if the screen size is not blacklisted.
+ float dpi = IsDisplaySizeBlackListed(state->physical_size())
+ ? 0
+ : kInchInMm * mode_info->size().width() /
+ state->physical_size().width();
+
+ if (state->type() == DISPLAY_CONNECTION_TYPE_INTERNAL) {
+ if (dpi)
+ device_scale_factor = FindDeviceScaleFactor(dpi);
+ } else {
+ scoped_refptr<ManagedDisplayMode> mode =
+ display_manager_->GetSelectedModeForDisplayId(state->display_id());
+ if (mode) {
+ device_scale_factor = mode->device_scale_factor();
+ } else {
+ // For monitors that are 40 inches and 4K or above, set
+ // |device_scale_factor| to 2x. For margin purposes, 100 is subtracted
+ // from the value of |k2xThreshouldSizeSquaredFor4KInMm|
+ const int k2xThreshouldSizeSquaredFor4KInMm =
+ (40 * 40 * kInchInMm * kInchInMm) - 100;
+ gfx::Vector2d size_in_vec(state->physical_size().width(),
+ state->physical_size().height());
+ if (size_in_vec.LengthSquared() > k2xThreshouldSizeSquaredFor4KInMm &&
+ mode_info->size().width() >= kMinimumWidthFor4K) {
+ // Make sure that additional device scale factors table has 2x.
+ DCHECK_EQ(2.0f, kAdditionalDeviceScaleFactorsFor4k[1]);
+ device_scale_factor = 2.0f;
+ }
+ }
+ }
+
+ std::string name = (state->type() == DISPLAY_CONNECTION_TYPE_INTERNAL)
+ ? l10n_util::GetStringUTF8(IDS_DISPLAY_NAME_INTERNAL)
+ : state->display_name();
+
+ if (name.empty())
+ name = l10n_util::GetStringUTF8(IDS_DISPLAY_NAME_UNKNOWN);
+
+ const bool has_overscan = state->has_overscan();
+ const int64_t id = state->display_id();
+
+ ManagedDisplayInfo new_info = ManagedDisplayInfo(id, name, has_overscan);
+ new_info.set_sys_path(state->sys_path());
+ new_info.set_device_scale_factor(device_scale_factor);
+ const gfx::Rect display_bounds(state->origin(), mode_info->size());
+ new_info.SetBounds(display_bounds);
+ new_info.set_native(true);
+ new_info.set_is_aspect_preserving_scaling(
+ state->is_aspect_preserving_scaling());
+ if (dpi)
+ new_info.set_device_dpi(dpi);
+
+ ManagedDisplayInfo::ManagedDisplayModeList display_modes =
+ (state->type() == DISPLAY_CONNECTION_TYPE_INTERNAL)
+ ? GetInternalManagedDisplayModeList(new_info, *state)
+ : GetExternalManagedDisplayModeList(*state);
+ new_info.SetManagedDisplayModes(display_modes);
+
+ new_info.set_maximum_cursor_size(state->maximum_cursor_size());
+ return new_info;
+}
+
// static
float DisplayChangeObserver::FindDeviceScaleFactor(float dpi) {
for (size_t i = 0; i < arraysize(kThresholdTableForInternal); ++i) {
diff --git a/chromium/ui/display/manager/chromeos/display_change_observer.h b/chromium/ui/display/manager/chromeos/display_change_observer.h
index d9468f9973b..8ad853d4e40 100644
--- a/chromium/ui/display/manager/chromeos/display_change_observer.h
+++ b/chromium/ui/display/manager/chromeos/display_change_observer.h
@@ -43,7 +43,7 @@ class DISPLAY_MANAGER_EXPORT DisplayChangeObserver
// DisplayConfigurator::StateController overrides:
MultipleDisplayState GetStateForDisplayIds(
- const DisplayConfigurator::DisplayStateList& outputs) const override;
+ const DisplayConfigurator::DisplayStateList& outputs) override;
bool GetResolutionForDisplayId(int64_t display_id,
gfx::Size* size) const override;
@@ -61,6 +61,12 @@ class DISPLAY_MANAGER_EXPORT DisplayChangeObserver
DISPLAY_EXPORT static float FindDeviceScaleFactor(float dpi);
private:
+ void UpdateInternalDisplay(
+ const DisplayConfigurator::DisplayStateList& display_states);
+
+ ManagedDisplayInfo CreateManagedDisplayInfo(const DisplaySnapshot* state,
+ const DisplayMode* mode_info);
+
// Both |display_configurator_| and |display_manager_| are not owned and must
// outlive DisplayChangeObserver.
DisplayConfigurator* display_configurator_;
diff --git a/chromium/ui/display/manager/chromeos/display_change_observer_unittest.cc b/chromium/ui/display/manager/chromeos/display_change_observer_unittest.cc
index cf74f786ea9..dbf22a33ab4 100644
--- a/chromium/ui/display/manager/chromeos/display_change_observer_unittest.cc
+++ b/chromium/ui/display/manager/chromeos/display_change_observer_unittest.cc
@@ -93,8 +93,7 @@ TEST(DisplayChangeObserverTest, GetExternalManagedDisplayModeList) {
TEST(DisplayChangeObserverTest, GetEmptyExternalManagedDisplayModeList) {
FakeDisplaySnapshot display_snapshot(
123, gfx::Point(), gfx::Size(), DISPLAY_CONNECTION_TYPE_UNKNOWN, false,
- false, false, std::string(), 0,
- std::vector<std::unique_ptr<const DisplayMode>>(), nullptr, nullptr);
+ false, false, std::string(), {}, nullptr, nullptr, 0, gfx::Size());
ManagedDisplayInfo::ManagedDisplayModeList display_modes =
DisplayChangeObserver::GetExternalManagedDisplayModeList(
diff --git a/chromium/ui/display/manager/chromeos/display_configurator.cc b/chromium/ui/display/manager/chromeos/display_configurator.cc
index 163ecac3067..088cc973d0b 100644
--- a/chromium/ui/display/manager/chromeos/display_configurator.cc
+++ b/chromium/ui/display/manager/chromeos/display_configurator.cc
@@ -72,19 +72,19 @@ base::TimeDelta DisplayConfigurator::TestApi::GetConfigureDelay() const {
class DisplayConfigurator::DisplayLayoutManagerImpl
: public DisplayLayoutManager {
public:
- DisplayLayoutManagerImpl(DisplayConfigurator* configurator);
+ explicit DisplayLayoutManagerImpl(DisplayConfigurator* configurator);
~DisplayLayoutManagerImpl() override;
- // DisplayConfigurator::DisplayLayoutManager:
+ // DisplayLayoutManager:
SoftwareMirroringController* GetSoftwareMirroringController() const override;
StateController* GetStateController() const override;
MultipleDisplayState GetDisplayState() const override;
chromeos::DisplayPowerState GetPowerState() const override;
- bool GetDisplayLayout(const std::vector<DisplaySnapshot*>& displays,
- MultipleDisplayState new_display_state,
- chromeos::DisplayPowerState new_power_state,
- std::vector<DisplayConfigureRequest>* requests,
- gfx::Size* framebuffer_size) const override;
+ bool GetDisplayLayout(
+ const std::vector<DisplaySnapshot*>& displays,
+ MultipleDisplayState new_display_state,
+ chromeos::DisplayPowerState new_power_state,
+ std::vector<DisplayConfigureRequest>* requests) const override;
DisplayStateList GetDisplayStates() const override;
bool IsMirroring() const override;
@@ -204,8 +204,7 @@ bool DisplayConfigurator::DisplayLayoutManagerImpl::GetDisplayLayout(
const std::vector<DisplaySnapshot*>& displays,
MultipleDisplayState new_display_state,
chromeos::DisplayPowerState new_power_state,
- std::vector<DisplayConfigureRequest>* requests,
- gfx::Size* framebuffer_size) const {
+ std::vector<DisplayConfigureRequest>* requests) const {
std::vector<DisplayState> states = ParseDisplays(displays);
std::vector<bool> display_power;
int num_on_displays =
@@ -328,7 +327,6 @@ bool DisplayConfigurator::DisplayLayoutManagerImpl::GetDisplayLayout(
}
DCHECK(new_display_state == MULTIPLE_DISPLAY_STATE_HEADLESS ||
!size.IsEmpty());
- *framebuffer_size = size;
return true;
}
@@ -410,8 +408,6 @@ bool DisplayConfigurator::DisplayLayoutManagerImpl::FindMirrorMode(
external_mode->size().height() &&
!external_mode->is_interlaced();
if (can_fit) {
- configurator_->native_display_delegate_->AddMode(
- *internal_display->display, external_mode.get());
internal_display->display->add_mode(external_mode.get());
internal_display->mirror_mode =
internal_display->display->modes().back().get();
@@ -622,8 +618,7 @@ void DisplayConfigurator::OnDisplayControlRelinquished(
std::move(callback).Run(success);
}
-void DisplayConfigurator::ForceInitialConfigure(
- uint32_t background_color_argb) {
+void DisplayConfigurator::ForceInitialConfigure() {
if (!configure_display_ || display_externally_controlled_)
return;
@@ -637,7 +632,7 @@ void DisplayConfigurator::ForceInitialConfigure(
configuration_task_.reset(new UpdateDisplayConfigurationTask(
native_display_delegate_.get(), layout_manager_.get(),
requested_display_state_, requested_power_state_,
- kSetDisplayPowerForceProbe, background_color_argb, true,
+ kSetDisplayPowerForceProbe, true,
base::Bind(&DisplayConfigurator::OnConfigured,
weak_ptr_factory_.GetWeakPtr())));
configuration_task_->Run();
@@ -812,36 +807,6 @@ void DisplayConfigurator::OnSetContentProtectionCompleted(
content_protection_tasks_.front().Run();
}
-std::vector<ColorCalibrationProfile>
-DisplayConfigurator::GetAvailableColorCalibrationProfiles(int64_t display_id) {
- if (!base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableDisplayColorCalibration)) {
- for (const DisplaySnapshot* display : cached_displays_) {
- if (display->display_id() == display_id &&
- IsPhysicalDisplayType(display->type())) {
- return native_display_delegate_->GetAvailableColorCalibrationProfiles(
- *display);
- }
- }
- }
-
- return std::vector<ColorCalibrationProfile>();
-}
-
-bool DisplayConfigurator::SetColorCalibrationProfile(
- int64_t display_id,
- ColorCalibrationProfile new_profile) {
- for (const DisplaySnapshot* display : cached_displays_) {
- if (display->display_id() == display_id &&
- IsPhysicalDisplayType(display->type())) {
- return native_display_delegate_->SetColorCalibrationProfile(*display,
- new_profile);
- }
- }
-
- return false;
-}
-
bool DisplayConfigurator::SetColorCorrection(
int64_t display_id,
const std::vector<GammaRampRGBEntry>& degamma_lut,
@@ -980,10 +945,6 @@ void DisplayConfigurator::SuspendDisplays(
// SetDisplayPowerInternal so requested_power_state_ is maintained.
SetDisplayPowerInternal(chromeos::DISPLAY_POWER_ALL_OFF,
kSetDisplayPowerNoFlags, callback);
-
- // We need to make sure that the monitor configuration we just did actually
- // completes before we return.
- native_display_delegate_->SyncWithServer();
}
void DisplayConfigurator::ResumeDisplays() {
@@ -1035,9 +996,10 @@ void DisplayConfigurator::RunPendingConfiguration() {
configuration_task_.reset(new UpdateDisplayConfigurationTask(
native_display_delegate_.get(), layout_manager_.get(),
- requested_display_state_, pending_power_state_, pending_power_flags_, 0,
- force_configure_, base::Bind(&DisplayConfigurator::OnConfigured,
- weak_ptr_factory_.GetWeakPtr())));
+ requested_display_state_, pending_power_state_, pending_power_flags_,
+ force_configure_,
+ base::Bind(&DisplayConfigurator::OnConfigured,
+ weak_ptr_factory_.GetWeakPtr())));
// Reset the flags before running the task; otherwise it may end up scheduling
// another configuration.
@@ -1055,7 +1017,6 @@ void DisplayConfigurator::RunPendingConfiguration() {
void DisplayConfigurator::OnConfigured(
bool success,
const std::vector<DisplaySnapshot*>& displays,
- const gfx::Size& framebuffer_size,
MultipleDisplayState new_display_state,
chromeos::DisplayPowerState new_power_state) {
VLOG(1) << "OnConfigured: success=" << success << " new_display_state="
@@ -1068,17 +1029,6 @@ void DisplayConfigurator::OnConfigured(
current_display_state_ = new_display_state;
current_power_state_ = new_power_state;
- // |framebuffer_size| is empty in software mirroring mode, headless mode,
- // or all displays are off.
- DCHECK(!framebuffer_size.IsEmpty() ||
- (mirroring_controller_ &&
- mirroring_controller_->SoftwareMirroringEnabled()) ||
- new_display_state == MULTIPLE_DISPLAY_STATE_HEADLESS ||
- new_power_state == chromeos::DISPLAY_POWER_ALL_OFF);
-
- if (!framebuffer_size.IsEmpty())
- framebuffer_size_ = framebuffer_size;
-
// If the pending power state hasn't changed then make sure that value
// gets updated as well since the last requested value may have been
// dependent on certain conditions (ie: if only the internal monitor was
diff --git a/chromium/ui/display/manager/chromeos/display_configurator.h b/chromium/ui/display/manager/chromeos/display_configurator.h
index 3a7bd2394a9..822dfbc5668 100644
--- a/chromium/ui/display/manager/chromeos/display_configurator.h
+++ b/chromium/ui/display/manager/chromeos/display_configurator.h
@@ -95,7 +95,7 @@ class DISPLAY_MANAGER_EXPORT DisplayConfigurator
// Called when displays are detected.
virtual MultipleDisplayState GetStateForDisplayIds(
- const DisplayConfigurator::DisplayStateList& outputs) const = 0;
+ const DisplayConfigurator::DisplayStateList& outputs) = 0;
// Queries the resolution (|size|) in pixels to select display mode for the
// given display id.
@@ -116,7 +116,8 @@ class DISPLAY_MANAGER_EXPORT DisplayConfigurator
// Helper class used by tests.
class TestApi {
public:
- TestApi(DisplayConfigurator* configurator) : configurator_(configurator) {}
+ explicit TestApi(DisplayConfigurator* configurator)
+ : configurator_(configurator) {}
~TestApi() {}
// If |configure_timer_| is started, stops the timer, runs
@@ -173,7 +174,6 @@ class DISPLAY_MANAGER_EXPORT DisplayConfigurator
chromeos::DisplayPowerState requested_power_state() const {
return requested_power_state_;
}
- const gfx::Size framebuffer_size() const { return framebuffer_size_; }
const std::vector<DisplaySnapshot*>& cached_displays() const {
return cached_displays_;
}
@@ -212,10 +212,7 @@ class DISPLAY_MANAGER_EXPORT DisplayConfigurator
bool is_panel_fitting_enabled);
// Does initial configuration of displays during startup.
- // If |background_color_argb| is non zero and there are multiple displays,
- // DisplayConfigurator sets the background color of X's RootWindow to this
- // color.
- void ForceInitialConfigure(uint32_t background_color_argb);
+ void ForceInitialConfigure();
// Stop handling display configuration events/requests.
void PrepareForExit();
@@ -274,15 +271,6 @@ class DISPLAY_MANAGER_EXPORT DisplayConfigurator
uint32_t protection_mask,
const SetProtectionCallback& callback);
- // Checks the available color profiles for |display_id| and fills the result
- // into |profiles|.
- std::vector<ColorCalibrationProfile> GetAvailableColorCalibrationProfiles(
- int64_t display_id);
-
- // Updates the color calibration to |new_profile|.
- bool SetColorCalibrationProfile(int64_t display_id,
- ColorCalibrationProfile new_profile);
-
// Returns true if there is at least one display on.
bool IsDisplayOn() const;
@@ -331,7 +319,6 @@ class DISPLAY_MANAGER_EXPORT DisplayConfigurator
// this is called with the result (|success|) and the updated display state.
void OnConfigured(bool success,
const std::vector<DisplaySnapshot*>& displays,
- const gfx::Size& framebuffer_size,
MultipleDisplayState new_display_state,
chromeos::DisplayPowerState new_power_state);
@@ -381,11 +368,8 @@ class DISPLAY_MANAGER_EXPORT DisplayConfigurator
bool is_panel_fitting_enabled_;
// This is detected by the constructor to determine whether or not we should
- // be enabled. If we aren't running on Chrome OS, we can't assume that the
- // Xrandr X11 extension or the Ozone underlying display hotplug system are
- // supported.
- // If this flag is set to false, any attempts to change the display
- // configuration to immediately fail without changing the state.
+ // be enabled. If this flag is set to false, any attempts to change the
+ // display configuration will immediately fail without changing the state.
bool configure_display_;
// Current configuration state.
@@ -431,14 +415,10 @@ class DISPLAY_MANAGER_EXPORT DisplayConfigurator
// configuration changes asynchronously.
DisplayStateList cached_displays_;
- // Most-recently-used framebuffer size.
- gfx::Size framebuffer_size_;
-
base::ObserverList<Observer> observers_;
// The timer to delay configuring displays. This is used to aggregate multiple
// display configuration events when they are reported in short time spans.
- // See comment for NativeDisplayEventDispatcherX11 for more details.
base::OneShotTimer configure_timer_;
// Id for next display protection client.
diff --git a/chromium/ui/display/manager/chromeos/display_configurator_unittest.cc b/chromium/ui/display/manager/chromeos/display_configurator_unittest.cc
index a366630ab85..fd18131ca47 100644
--- a/chromium/ui/display/manager/chromeos/display_configurator_unittest.cc
+++ b/chromium/ui/display/manager/chromeos/display_configurator_unittest.cc
@@ -22,7 +22,7 @@ namespace test {
namespace {
-int64_t kDisplayIds[3] = {123, 456, 789};
+constexpr int64_t kDisplayIds[3] = {123, 456, 789};
std::unique_ptr<DisplayMode> MakeDisplayMode(int width,
int height,
@@ -108,7 +108,7 @@ class TestStateController : public DisplayConfigurator::StateController {
// DisplayConfigurator::StateController overrides:
MultipleDisplayState GetStateForDisplayIds(
- const DisplayConfigurator::DisplayStateList& outputs) const override {
+ const DisplayConfigurator::DisplayStateList& outputs) override {
return state_;
}
bool GetResolutionForDisplayId(int64_t display_id,
@@ -146,7 +146,7 @@ class TestMirroringController
// the time it took to complete.
class ConfigurationWaiter {
public:
- ConfigurationWaiter(DisplayConfigurator::TestApi* test_api)
+ explicit ConfigurationWaiter(DisplayConfigurator::TestApi* test_api)
: on_configured_callback_(base::Bind(&ConfigurationWaiter::OnConfigured,
base::Unretained(this))),
test_api_(test_api),
@@ -303,14 +303,12 @@ class DisplayConfiguratorTest : public testing::Test {
configurator_.Init(nullptr, false);
EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
- configurator_.ForceInitialConfigure(0);
+ configurator_.ForceInitialConfigure();
EXPECT_EQ(
JoinActions(
- kInitXRandR, kGrab,
- GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
- .c_str(),
+ kInit,
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
- kForceDPMS, kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
}
@@ -420,21 +418,15 @@ TEST_F(DisplayConfiguratorTest, ConnectSecondOutput) {
observer_.Reset();
state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
UpdateOutputs(2, true);
- const int kDualHeight = small_mode_.size().height() +
- DisplayConfigurator::kVerticalGap +
- big_mode_.size().height();
+
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
- outputs_[0].get(), outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &big_mode_,
gfx::Point(0, small_mode_.size().height() +
DisplayConfigurator::kVerticalGap))
.c_str(),
- kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
EXPECT_EQ(1, observer_.num_changes());
@@ -443,12 +435,9 @@ TEST_F(DisplayConfiguratorTest, ConnectSecondOutput) {
configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
EXPECT_EQ(
JoinActions(
- kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
- outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
- kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
EXPECT_EQ(1, observer_.num_changes());
@@ -458,11 +447,8 @@ TEST_F(DisplayConfiguratorTest, ConnectSecondOutput) {
UpdateOutputs(1, true);
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
- kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
EXPECT_EQ(1, observer_.num_changes());
@@ -480,43 +466,35 @@ TEST_F(DisplayConfiguratorTest, ConnectSecondOutput) {
UpdateOutputs(2, true);
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
- outputs_[0].get(), outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &big_mode_,
gfx::Point(0, small_mode_.size().height() +
DisplayConfigurator::kVerticalGap))
.c_str(),
- kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
- const gfx::Size framebuffer_size = configurator_.framebuffer_size();
- DCHECK(!framebuffer_size.IsEmpty());
observer_.Reset();
configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
- EXPECT_EQ(JoinActions(kGrab, kUngrab, nullptr), log_->GetActionsAndClear());
+ EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
configurator_.display_state());
EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled());
- EXPECT_EQ(framebuffer_size.ToString(),
- configurator_.framebuffer_size().ToString());
EXPECT_EQ(1, observer_.num_changes());
// Setting MULTIPLE_DISPLAY_STATE_DUAL_MIRROR should try to reconfigure.
observer_.Reset();
configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
- EXPECT_EQ(JoinActions(nullptr), log_->GetActionsAndClear());
+ EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
EXPECT_EQ(1, observer_.num_changes());
// Set back to software mirror mode.
observer_.Reset();
configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
- EXPECT_EQ(JoinActions(kGrab, kUngrab, nullptr), log_->GetActionsAndClear());
+ EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
configurator_.display_state());
EXPECT_TRUE(mirroring_controller_.SoftwareMirroringEnabled());
@@ -527,11 +505,8 @@ TEST_F(DisplayConfiguratorTest, ConnectSecondOutput) {
UpdateOutputs(1, true);
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
- kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
EXPECT_EQ(1, observer_.num_changes());
@@ -545,12 +520,9 @@ TEST_F(DisplayConfiguratorTest, SetDisplayPower) {
UpdateOutputs(2, true);
EXPECT_EQ(
JoinActions(
- kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
- outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
- kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
EXPECT_EQ(1, observer_.num_changes());
@@ -567,12 +539,9 @@ TEST_F(DisplayConfiguratorTest, SetDisplayPower) {
EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
EXPECT_EQ(
JoinActions(
- kGrab, GetFramebufferAction(big_mode_.size(), outputs_[0].get(),
- outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &big_mode_, gfx::Point(0, 0)).c_str(),
- kForceDPMS, kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state());
EXPECT_EQ(1, observer_.num_changes());
@@ -586,15 +555,11 @@ TEST_F(DisplayConfiguratorTest, SetDisplayPower) {
config_waiter_.on_configuration_callback());
EXPECT_EQ(kNoDelay, config_waiter_.Wait());
EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
- EXPECT_EQ(
- JoinActions(
- kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
- outputs_[1].get())
- .c_str(),
- GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
- GetCrtcAction(*outputs_[1], nullptr, gfx::Point(0, 0)).c_str(),
- kUngrab, nullptr),
- log_->GetActionsAndClear());
+ EXPECT_EQ(JoinActions(
+ GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
+ GetCrtcAction(*outputs_[1], nullptr, gfx::Point(0, 0)).c_str(),
+ nullptr),
+ log_->GetActionsAndClear());
EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
EXPECT_EQ(1, observer_.num_changes());
@@ -609,12 +574,9 @@ TEST_F(DisplayConfiguratorTest, SetDisplayPower) {
EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
EXPECT_EQ(
JoinActions(
- kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
- outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
- kForceDPMS, kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
@@ -632,21 +594,15 @@ TEST_F(DisplayConfiguratorTest, SetDisplayPower) {
state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
observer_.Reset();
UpdateOutputs(2, true);
- const int kDualHeight = small_mode_.size().height() +
- DisplayConfigurator::kVerticalGap +
- big_mode_.size().height();
+
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
- outputs_[0].get(), outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &big_mode_,
gfx::Point(0, small_mode_.size().height() +
DisplayConfigurator::kVerticalGap))
.c_str(),
- kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
configurator_.display_state());
@@ -665,12 +621,9 @@ TEST_F(DisplayConfiguratorTest, SetDisplayPower) {
EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
EXPECT_EQ(
JoinActions(
- kGrab, GetFramebufferAction(big_mode_.size(), outputs_[0].get(),
- outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &big_mode_, gfx::Point(0, 0)).c_str(),
- kForceDPMS, kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state());
EXPECT_FALSE(mirroring_controller_.SoftwareMirroringEnabled());
@@ -687,16 +640,12 @@ TEST_F(DisplayConfiguratorTest, SetDisplayPower) {
EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
- outputs_[0].get(), outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], nullptr,
gfx::Point(0, small_mode_.size().height() +
DisplayConfigurator::kVerticalGap))
.c_str(),
- kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
configurator_.display_state());
@@ -713,16 +662,12 @@ TEST_F(DisplayConfiguratorTest, SetDisplayPower) {
EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
- outputs_[0].get(), outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &big_mode_,
gfx::Point(0, small_mode_.size().height() +
DisplayConfigurator::kVerticalGap))
.c_str(),
- kForceDPMS, kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
configurator_.display_state());
@@ -736,21 +681,15 @@ TEST_F(DisplayConfiguratorTest, SuspendAndResume) {
// No preparation is needed before suspending when the display is already
// on. The configurator should still reprobe on resume in case a display
// was connected while suspended.
- const gfx::Size framebuffer_size = configurator_.framebuffer_size();
- DCHECK(!framebuffer_size.IsEmpty());
config_waiter_.Reset();
configurator_.SuspendDisplays(config_waiter_.on_configuration_callback());
EXPECT_EQ(kNoDelay, config_waiter_.Wait());
EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
- EXPECT_EQ(framebuffer_size.ToString(),
- configurator_.framebuffer_size().ToString());
- EXPECT_EQ(JoinActions(
- kGrab, GetFramebufferAction(small_mode_.size(),
- outputs_[0].get(), nullptr)
- .c_str(),
- GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
- kUngrab, kSync, nullptr),
- log_->GetActionsAndClear());
+ EXPECT_EQ(
+ JoinActions(
+ GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
+ nullptr),
+ log_->GetActionsAndClear());
// No resume delay in single display mode.
config_waiter_.Reset();
@@ -759,11 +698,8 @@ TEST_F(DisplayConfiguratorTest, SuspendAndResume) {
EXPECT_EQ(base::TimeDelta::Max(), config_waiter_.Wait());
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
- kForceDPMS, kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
// Now turn the display off before suspending and check that the
@@ -774,19 +710,17 @@ TEST_F(DisplayConfiguratorTest, SuspendAndResume) {
config_waiter_.on_configuration_callback());
EXPECT_EQ(kNoDelay, config_waiter_.Wait());
EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
- EXPECT_EQ(JoinActions(
- kGrab, GetFramebufferAction(small_mode_.size(),
- outputs_[0].get(), nullptr)
- .c_str(),
- GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
- kUngrab, nullptr),
- log_->GetActionsAndClear());
+ EXPECT_EQ(
+ JoinActions(
+ GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
+ nullptr),
+ log_->GetActionsAndClear());
config_waiter_.Reset();
configurator_.SuspendDisplays(config_waiter_.on_configuration_callback());
EXPECT_EQ(kNoDelay, config_waiter_.Wait());
EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
- EXPECT_EQ(kSync, log_->GetActionsAndClear());
+ EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
config_waiter_.Reset();
configurator_.ResumeDisplays();
@@ -802,23 +736,17 @@ TEST_F(DisplayConfiguratorTest, SuspendAndResume) {
EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
- kForceDPMS, kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
UpdateOutputs(2, true);
EXPECT_EQ(
JoinActions(
- kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
- outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
- kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
config_waiter_.Reset();
@@ -828,15 +756,11 @@ TEST_F(DisplayConfiguratorTest, SuspendAndResume) {
EXPECT_EQ(kNoDelay, config_waiter_.Wait());
EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
- EXPECT_EQ(
- JoinActions(
- kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
- outputs_[1].get())
- .c_str(),
- GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
- GetCrtcAction(*outputs_[1], nullptr, gfx::Point(0, 0)).c_str(),
- kUngrab, nullptr),
- log_->GetActionsAndClear());
+ EXPECT_EQ(JoinActions(
+ GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
+ GetCrtcAction(*outputs_[1], nullptr, gfx::Point(0, 0)).c_str(),
+ nullptr),
+ log_->GetActionsAndClear());
// No delay in suspend.
config_waiter_.Reset();
@@ -846,7 +770,7 @@ TEST_F(DisplayConfiguratorTest, SuspendAndResume) {
EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_OFF,
configurator_.current_power_state());
EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
- EXPECT_EQ(kSync, log_->GetActionsAndClear());
+ EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
// If a display is disconnected while suspended, the configurator should
// pick up the change and only turn on the internal display. The should be
@@ -867,11 +791,8 @@ TEST_F(DisplayConfiguratorTest, SuspendAndResume) {
EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
- kForceDPMS, kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
}
@@ -880,9 +801,8 @@ TEST_F(DisplayConfiguratorTest, Headless) {
EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
Init(false);
EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
- configurator_.ForceInitialConfigure(0);
- EXPECT_EQ(JoinActions(kInitXRandR, kGrab, kForceDPMS, kUngrab, nullptr),
- log_->GetActionsAndClear());
+ configurator_.ForceInitialConfigure();
+ EXPECT_EQ(JoinActions(kInit, nullptr), log_->GetActionsAndClear());
// Not much should happen when the display power state is changed while
// no displays are connected.
@@ -892,15 +812,14 @@ TEST_F(DisplayConfiguratorTest, Headless) {
config_waiter_.on_configuration_callback());
EXPECT_EQ(kNoDelay, config_waiter_.Wait());
EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
- EXPECT_EQ(JoinActions(kGrab, kUngrab, nullptr), log_->GetActionsAndClear());
+ EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
config_waiter_.Reset();
configurator_.SetDisplayPower(chromeos::DISPLAY_POWER_ALL_ON,
DisplayConfigurator::kSetDisplayPowerNoFlags,
config_waiter_.on_configuration_callback());
EXPECT_EQ(kNoDelay, config_waiter_.Wait());
EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
- EXPECT_EQ(JoinActions(kGrab, kForceDPMS, kUngrab, nullptr),
- log_->GetActionsAndClear());
+ EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
// Connect an external display and check that it's configured correctly.
outputs_[0] = FakeDisplaySnapshot::Builder()
@@ -915,19 +834,12 @@ TEST_F(DisplayConfiguratorTest, Headless) {
UpdateOutputs(1, true);
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(big_mode_.size(), outputs_[0].get(), nullptr)
- .c_str(),
GetCrtcAction(*outputs_[0], &big_mode_, gfx::Point(0, 0)).c_str(),
- kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
- const gfx::Size framebuffer_size = configurator_.framebuffer_size();
- DCHECK(!framebuffer_size.IsEmpty());
UpdateOutputs(0, true);
- EXPECT_EQ(JoinActions(kGrab, kUngrab, nullptr), log_->GetActionsAndClear());
- EXPECT_EQ(framebuffer_size.ToString(),
- configurator_.framebuffer_size().ToString());
+ EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
}
TEST_F(DisplayConfiguratorTest, StartWithTwoOutputs) {
@@ -937,16 +849,13 @@ TEST_F(DisplayConfiguratorTest, StartWithTwoOutputs) {
EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
- configurator_.ForceInitialConfigure(0);
+ configurator_.ForceInitialConfigure();
EXPECT_EQ(
JoinActions(
- kInitXRandR, kGrab,
- GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
- outputs_[1].get())
- .c_str(),
+ kInit,
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
- kForceDPMS, kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
}
@@ -954,7 +863,7 @@ TEST_F(DisplayConfiguratorTest, InvalidMultipleDisplayStates) {
UpdateOutputs(0, false);
EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
Init(false);
- configurator_.ForceInitialConfigure(0);
+ configurator_.ForceInitialConfigure();
observer_.Reset();
configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_HEADLESS);
EXPECT_EQ(1, observer_.num_changes());
@@ -995,7 +904,7 @@ TEST_F(DisplayConfiguratorTest, GetMultipleDisplayStateForMirroredDisplays) {
UpdateOutputs(2, false);
Init(false);
state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
- configurator_.ForceInitialConfigure(0);
+ configurator_.ForceInitialConfigure();
EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
}
@@ -1039,18 +948,14 @@ TEST_F(DisplayConfiguratorTest, PanelFitting) {
UpdateOutputs(2, false);
state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
Init(true /* is_panel_fitting_enabled */);
- configurator_.ForceInitialConfigure(0);
+ configurator_.ForceInitialConfigure();
EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR, configurator_.display_state());
EXPECT_EQ(
JoinActions(
- kInitXRandR, kGrab,
- GetAddOutputModeAction(*outputs_[0], &small_mode_).c_str(),
- GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
- outputs_[1].get())
- .c_str(),
+ kInit,
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
- kForceDPMS, kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
// Both outputs should be using the small mode.
@@ -1069,7 +974,7 @@ TEST_F(DisplayConfiguratorTest, PanelFitting) {
TEST_F(DisplayConfiguratorTest, ContentProtection) {
Init(false);
- configurator_.ForceInitialConfigure(0);
+ configurator_.ForceInitialConfigure();
EXPECT_NE(kNoActions, log_->GetActionsAndClear());
uint64_t id = configurator_.RegisterContentProtectionClient();
@@ -1145,13 +1050,11 @@ TEST_F(DisplayConfiguratorTest, DoNotConfigureWithSuspendedDisplays) {
configurator_.SuspendDisplays(config_waiter_.on_configuration_callback());
EXPECT_EQ(kNoDelay, config_waiter_.Wait());
EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
- EXPECT_EQ(JoinActions(
- kGrab, GetFramebufferAction(small_mode_.size(),
- outputs_[0].get(), nullptr)
- .c_str(),
- GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
- kUngrab, kSync, nullptr),
- log_->GetActionsAndClear());
+ EXPECT_EQ(
+ JoinActions(
+ GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
+ nullptr),
+ log_->GetActionsAndClear());
// The configuration timer should not be started when the displays
// are suspended.
@@ -1176,23 +1079,17 @@ TEST_F(DisplayConfiguratorTest, DoNotConfigureWithSuspendedDisplays) {
EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
- kForceDPMS, kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
UpdateOutputs(2, false);
configurator_.SetDisplayMode(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
EXPECT_EQ(
JoinActions(
- kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
- outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
- kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
// The DisplayConfigurator should do nothing at resume time if there is no
@@ -1210,13 +1107,11 @@ TEST_F(DisplayConfiguratorTest, DoNotConfigureWithSuspendedDisplays) {
configurator_.SuspendDisplays(config_waiter_.on_configuration_callback());
EXPECT_EQ(kNoDelay, config_waiter_.Wait());
EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
- EXPECT_EQ(JoinActions(
- kGrab, GetFramebufferAction(small_mode_.size(),
- outputs_[0].get(), nullptr)
- .c_str(),
- GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
- kUngrab, kSync, nullptr),
- log_->GetActionsAndClear());
+ EXPECT_EQ(
+ JoinActions(
+ GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
+ nullptr),
+ log_->GetActionsAndClear());
EXPECT_FALSE(test_api_.TriggerConfigureTimeout());
EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
@@ -1226,11 +1121,8 @@ TEST_F(DisplayConfiguratorTest, DoNotConfigureWithSuspendedDisplays) {
EXPECT_EQ(base::TimeDelta::Max(), config_waiter_.Wait());
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
- kForceDPMS, kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
}
@@ -1240,7 +1132,7 @@ TEST_F(DisplayConfiguratorTest, ContentProtectionTwoClients) {
EXPECT_NE(client1, client2);
Init(false);
- configurator_.ForceInitialConfigure(0);
+ configurator_.ForceInitialConfigure();
UpdateOutputs(2, true);
EXPECT_NE(kNoActions, log_->GetActionsAndClear());
@@ -1302,7 +1194,7 @@ TEST_F(DisplayConfiguratorTest, ContentProtectionTwoClientsEnable) {
EXPECT_NE(client1, client2);
Init(false);
- configurator_.ForceInitialConfigure(0);
+ configurator_.ForceInitialConfigure();
UpdateOutputs(2, true);
log_->GetActionsAndClear();
@@ -1375,13 +1267,10 @@ TEST_F(DisplayConfiguratorTest, HandleConfigureCrtcFailure) {
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(big_mode_.size(), outputs_[0].get(), nullptr)
- .c_str(),
GetCrtcAction(*outputs_[0], modes[0].get(), gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[0], modes[3].get(), gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[0], modes[2].get(), gfx::Point(0, 0)).c_str(),
- kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
outputs_[1] = FakeDisplaySnapshot::Builder()
@@ -1405,9 +1294,6 @@ TEST_F(DisplayConfiguratorTest, HandleConfigureCrtcFailure) {
EXPECT_EQ(
JoinActions(
- kGrab, GetFramebufferAction(modes[0]->size(), outputs_[0].get(),
- outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], modes[0].get(), gfx::Point(0, 0)).c_str(),
// Then attempt to configure crtc1 with the first mode.
GetCrtcAction(*outputs_[1], modes[0].get(), gfx::Point(0, 0)).c_str(),
@@ -1419,12 +1305,6 @@ TEST_F(DisplayConfiguratorTest, HandleConfigureCrtcFailure) {
// and the configured modes were different, it
// should now try and setup a valid configurable
// extended mode.
- GetFramebufferAction(
- gfx::Size(modes[0]->size().width(),
- modes[0]->size().height() + modes[0]->size().height() +
- DisplayConfigurator::kVerticalGap),
- outputs_[0].get(), outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], modes[0].get(), gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], modes[0].get(),
gfx::Point(0, modes[0]->size().height() +
@@ -1435,7 +1315,7 @@ TEST_F(DisplayConfiguratorTest, HandleConfigureCrtcFailure) {
gfx::Point(0, modes[0]->size().height() +
DisplayConfigurator::kVerticalGap))
.c_str(),
- kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
}
@@ -1445,7 +1325,7 @@ TEST_F(DisplayConfiguratorTest, SaveDisplayPowerStateOnConfigFailure) {
// Start out with two displays in extended mode.
state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
Init(false);
- configurator_.ForceInitialConfigure(0);
+ configurator_.ForceInitialConfigure();
log_->GetActionsAndClear();
observer_.Reset();
@@ -1481,11 +1361,8 @@ TEST_F(DisplayConfiguratorTest, SaveDisplayPowerStateOnConfigFailure) {
UpdateOutputs(1, true);
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
- kForceDPMS, kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
}
@@ -1496,7 +1373,7 @@ TEST_F(DisplayConfiguratorTest, DontRestoreStalePowerStateAfterResume) {
// Start out with two displays in mirrored mode.
state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_MIRROR);
Init(false);
- configurator_.ForceInitialConfigure(0);
+ configurator_.ForceInitialConfigure();
log_->GetActionsAndClear();
observer_.Reset();
@@ -1511,12 +1388,9 @@ TEST_F(DisplayConfiguratorTest, DontRestoreStalePowerStateAfterResume) {
EXPECT_EQ(0, observer_.num_failures());
EXPECT_EQ(
JoinActions(
- kGrab, GetFramebufferAction(big_mode_.size(), outputs_[0].get(),
- outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &big_mode_, gfx::Point(0, 0)).c_str(),
- kForceDPMS, kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
// Suspend and resume the system. Resuming should restore the previous power
@@ -1527,15 +1401,11 @@ TEST_F(DisplayConfiguratorTest, DontRestoreStalePowerStateAfterResume) {
EXPECT_EQ(kNoDelay, config_waiter_.Wait());
EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
EXPECT_EQ(2, observer_.num_changes());
- EXPECT_EQ(
- JoinActions(
- kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
- outputs_[1].get())
- .c_str(),
- GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
- GetCrtcAction(*outputs_[1], nullptr, gfx::Point(0, 0)).c_str(),
- kUngrab, kSync, nullptr),
- log_->GetActionsAndClear());
+ EXPECT_EQ(JoinActions(
+ GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
+ GetCrtcAction(*outputs_[1], nullptr, gfx::Point(0, 0)).c_str(),
+ nullptr),
+ log_->GetActionsAndClear());
// Before the task runs, exit docked mode.
config_waiter_.Reset();
@@ -1548,12 +1418,9 @@ TEST_F(DisplayConfiguratorTest, DontRestoreStalePowerStateAfterResume) {
EXPECT_EQ(0, observer_.num_failures());
EXPECT_EQ(
JoinActions(
- kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
- outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
- kForceDPMS, kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
// Check that the display states are not changed after resuming.
@@ -1569,12 +1436,9 @@ TEST_F(DisplayConfiguratorTest, DontRestoreStalePowerStateAfterResume) {
EXPECT_EQ(kLongDelay, config_waiter_.Wait());
EXPECT_EQ(
JoinActions(
- kGrab, GetFramebufferAction(small_mode_.size(), outputs_[0].get(),
- outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &small_mode_, gfx::Point(0, 0)).c_str(),
- kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
}
@@ -1585,24 +1449,20 @@ TEST_F(DisplayConfiguratorTest, ExternalControl) {
base::Bind(&DisplayConfiguratorTest::OnDisplayControlUpdated,
base::Unretained(this)));
EXPECT_EQ(CALLBACK_SUCCESS, PopDisplayControlResult());
- EXPECT_EQ(JoinActions(
- kGrab, GetFramebufferAction(small_mode_.size(),
- outputs_[0].get(), nullptr)
- .c_str(),
- GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
- kUngrab, kRelinquishDisplayControl, nullptr),
- log_->GetActionsAndClear());
+ EXPECT_EQ(
+ JoinActions(
+ GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
+ kRelinquishDisplayControl, nullptr),
+ log_->GetActionsAndClear());
configurator_.TakeControl(
base::Bind(&DisplayConfiguratorTest::OnDisplayControlUpdated,
base::Unretained(this)));
EXPECT_EQ(CALLBACK_SUCCESS, PopDisplayControlResult());
EXPECT_EQ(
JoinActions(
- kTakeDisplayControl, kGrab,
- GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
- .c_str(),
+ kTakeDisplayControl,
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
- kForceDPMS, kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
}
@@ -1611,7 +1471,7 @@ TEST_F(DisplayConfiguratorTest,
// Start out with two displays in extended mode.
state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
Init(false);
- configurator_.ForceInitialConfigure(0);
+ configurator_.ForceInitialConfigure();
log_->GetActionsAndClear();
observer_.Reset();
@@ -1633,21 +1493,14 @@ TEST_F(DisplayConfiguratorTest,
EXPECT_EQ(1, observer_.num_changes());
EXPECT_EQ(0, observer_.num_failures());
- const int kDualHeight = small_mode_.size().height() +
- DisplayConfigurator::kVerticalGap +
- big_mode_.size().height();
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
- outputs_[0].get(), outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], nullptr,
gfx::Point(0, small_mode_.size().height() +
DisplayConfigurator::kVerticalGap))
.c_str(),
- kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
config_waiter_.Reset();
@@ -1662,16 +1515,12 @@ TEST_F(DisplayConfiguratorTest,
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
- outputs_[0].get(), outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &big_mode_,
gfx::Point(0, small_mode_.size().height() +
DisplayConfigurator::kVerticalGap))
.c_str(),
- kForceDPMS, kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
}
@@ -1680,7 +1529,7 @@ TEST_F(DisplayConfiguratorTest,
// Start out with two displays in extended mode.
state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
Init(false);
- configurator_.ForceInitialConfigure(0);
+ configurator_.ForceInitialConfigure();
log_->GetActionsAndClear();
observer_.Reset();
@@ -1696,22 +1545,14 @@ TEST_F(DisplayConfiguratorTest,
EXPECT_EQ(0, observer_.num_changes());
EXPECT_EQ(1, observer_.num_failures());
- const int kDualHeight = small_mode_.size().height() +
- DisplayConfigurator::kVerticalGap +
- big_mode_.size().height();
-
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
- outputs_[0].get(), outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], nullptr,
gfx::Point(0, small_mode_.size().height() +
DisplayConfigurator::kVerticalGap))
.c_str(),
- kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
// This configuration should trigger a display configuration since the
@@ -1726,10 +1567,6 @@ TEST_F(DisplayConfiguratorTest,
EXPECT_EQ(2, observer_.num_failures());
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
- outputs_[0].get(), outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &big_mode_,
gfx::Point(0, small_mode_.size().height() +
@@ -1739,7 +1576,7 @@ TEST_F(DisplayConfiguratorTest,
gfx::Point(0, small_mode_.size().height() +
DisplayConfigurator::kVerticalGap))
.c_str(),
- kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
// Allow configuration to succeed.
@@ -1755,16 +1592,12 @@ TEST_F(DisplayConfiguratorTest,
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
- outputs_[0].get(), outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &big_mode_,
gfx::Point(0, small_mode_.size().height() +
DisplayConfigurator::kVerticalGap))
.c_str(),
- kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
}
@@ -1772,25 +1605,15 @@ TEST_F(DisplayConfiguratorTest, TestWithThreeDisplays) {
// Start out with two displays in extended mode.
state_controller_.set_state(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED);
Init(false);
- configurator_.ForceInitialConfigure(0);
+ configurator_.ForceInitialConfigure();
log_->GetActionsAndClear();
observer_.Reset();
UpdateOutputs(3, true);
state_controller_.set_state(MULTIPLE_DISPLAY_STATE_MULTI_EXTENDED);
- const int kDualHeight = small_mode_.size().height() +
- DisplayConfigurator::kVerticalGap +
- big_mode_.size().height();
- const int kTripleHeight = 2 * small_mode_.size().height() +
- 2 * DisplayConfigurator::kVerticalGap +
- big_mode_.size().height();
EXPECT_EQ(
JoinActions(
- kGrab, GetFramebufferAction(
- gfx::Size(big_mode_.size().width(), kTripleHeight),
- outputs_[0].get(), outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &big_mode_,
gfx::Point(0, small_mode_.size().height() +
@@ -1802,7 +1625,7 @@ TEST_F(DisplayConfiguratorTest, TestWithThreeDisplays) {
big_mode_.size().height() +
2 * DisplayConfigurator::kVerticalGap))
.c_str(),
- kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
// Verify that turning the power off works.
@@ -1814,10 +1637,6 @@ TEST_F(DisplayConfiguratorTest, TestWithThreeDisplays) {
EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
EXPECT_EQ(
JoinActions(
- kGrab, GetFramebufferAction(
- gfx::Size(big_mode_.size().width(), kTripleHeight),
- outputs_[0].get(), outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], nullptr,
gfx::Point(0, small_mode_.size().height() +
@@ -1829,7 +1648,7 @@ TEST_F(DisplayConfiguratorTest, TestWithThreeDisplays) {
big_mode_.size().height() +
2 * DisplayConfigurator::kVerticalGap))
.c_str(),
- kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
config_waiter_.Reset();
@@ -1840,10 +1659,6 @@ TEST_F(DisplayConfiguratorTest, TestWithThreeDisplays) {
EXPECT_EQ(CALLBACK_SUCCESS, config_waiter_.callback_result());
EXPECT_EQ(
JoinActions(
- kGrab, GetFramebufferAction(
- gfx::Size(big_mode_.size().width(), kTripleHeight),
- outputs_[0].get(), outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &big_mode_,
gfx::Point(0, small_mode_.size().height() +
@@ -1855,7 +1670,7 @@ TEST_F(DisplayConfiguratorTest, TestWithThreeDisplays) {
big_mode_.size().height() +
2 * DisplayConfigurator::kVerticalGap))
.c_str(),
- kForceDPMS, kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
// Disconnect the third output.
@@ -1864,16 +1679,12 @@ TEST_F(DisplayConfiguratorTest, TestWithThreeDisplays) {
UpdateOutputs(2, true);
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
- outputs_[0].get(), outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &big_mode_,
gfx::Point(0, small_mode_.size().height() +
DisplayConfigurator::kVerticalGap))
.c_str(),
- kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
}
@@ -1889,21 +1700,15 @@ TEST_F(DisplayConfiguratorTest, SuspendResumeWithMultipleDisplays) {
EXPECT_EQ(1, observer_.num_changes());
EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON,
configurator_.current_power_state());
- const int kDualHeight = small_mode_.size().height() +
- DisplayConfigurator::kVerticalGap +
- big_mode_.size().height();
+
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
- outputs_[0].get(), outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &big_mode_,
gfx::Point(0, small_mode_.size().height() +
DisplayConfigurator::kVerticalGap))
.c_str(),
- kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
// Suspending displays should result in an immediate configuration without
@@ -1918,16 +1723,12 @@ TEST_F(DisplayConfiguratorTest, SuspendResumeWithMultipleDisplays) {
configurator_.display_state());
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
- outputs_[0].get(), outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], nullptr,
gfx::Point(0, small_mode_.size().height() +
DisplayConfigurator::kVerticalGap))
.c_str(),
- kUngrab, kSync, nullptr),
+ nullptr),
log_->GetActionsAndClear());
// Resuming from suspend with dual displays. Configuration should be done
@@ -1942,16 +1743,12 @@ TEST_F(DisplayConfiguratorTest, SuspendResumeWithMultipleDisplays) {
configurator_.display_state());
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
- outputs_[0].get(), outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], &big_mode_,
gfx::Point(0, small_mode_.size().height() +
DisplayConfigurator::kVerticalGap))
.c_str(),
- kForceDPMS, kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
// Suspend displays and disconnect one of them while in suspend.
@@ -1965,16 +1762,12 @@ TEST_F(DisplayConfiguratorTest, SuspendResumeWithMultipleDisplays) {
configurator_.current_power_state());
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(gfx::Size(big_mode_.size().width(), kDualHeight),
- outputs_[0].get(), outputs_[1].get())
- .c_str(),
GetCrtcAction(*outputs_[0], nullptr, gfx::Point(0, 0)).c_str(),
GetCrtcAction(*outputs_[1], nullptr,
gfx::Point(0, small_mode_.size().height() +
DisplayConfigurator::kVerticalGap))
.c_str(),
- kUngrab, kSync, nullptr),
+ nullptr),
log_->GetActionsAndClear());
UpdateOutputs(1, false);
EXPECT_EQ(kNoActions, log_->GetActionsAndClear());
@@ -1990,11 +1783,8 @@ TEST_F(DisplayConfiguratorTest, SuspendResumeWithMultipleDisplays) {
EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, configurator_.display_state());
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(small_mode_.size(), outputs_[0].get(), nullptr)
- .c_str(),
GetCrtcAction(*outputs_[0], &small_mode_, gfx::Point(0, 0)).c_str(),
- kForceDPMS, kUngrab, nullptr),
+ nullptr),
log_->GetActionsAndClear());
// Verify that the above is the exact same behavior for 3+ displays.
diff --git a/chromium/ui/display/manager/chromeos/display_layout_manager.h b/chromium/ui/display/manager/chromeos/display_layout_manager.h
index f6cb591007c..c43f2bbb00e 100644
--- a/chromium/ui/display/manager/chromeos/display_layout_manager.h
+++ b/chromium/ui/display/manager/chromeos/display_layout_manager.h
@@ -34,12 +34,12 @@ class DisplayLayoutManager {
// Based on the given |displays|, display state and power state, it will
// create display configuration requests which will then be used to
// configure the hardware. The requested configuration is stored in
- // |requests| and |framebuffer_size|.
- virtual bool GetDisplayLayout(const std::vector<DisplaySnapshot*>& displays,
- MultipleDisplayState new_display_state,
- chromeos::DisplayPowerState new_power_state,
- std::vector<DisplayConfigureRequest>* requests,
- gfx::Size* framebuffer_size) const = 0;
+ // |requests|.
+ virtual bool GetDisplayLayout(
+ const std::vector<DisplaySnapshot*>& displays,
+ MultipleDisplayState new_display_state,
+ chromeos::DisplayPowerState new_power_state,
+ std::vector<DisplayConfigureRequest>* requests) const = 0;
virtual std::vector<DisplaySnapshot*> GetDisplayStates() const = 0;
diff --git a/chromium/ui/display/manager/chromeos/mojo/BUILD.gn b/chromium/ui/display/manager/chromeos/mojo/BUILD.gn
deleted file mode 100644
index e29b518ebcc..00000000000
--- a/chromium/ui/display/manager/chromeos/mojo/BUILD.gn
+++ /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("//mojo/public/tools/bindings/mojom.gni")
-
-mojom("interfaces") {
- sources = [
- "touch_device_transform.mojom",
- ]
-
- public_deps = [
- "//ui/gfx/mojo",
- ]
-}
diff --git a/chromium/ui/display/manager/chromeos/mojo/OWNERS b/chromium/ui/display/manager/chromeos/mojo/OWNERS
deleted file mode 100644
index e75daf744a0..00000000000
--- a/chromium/ui/display/manager/chromeos/mojo/OWNERS
+++ /dev/null
@@ -1,8 +0,0 @@
-per-file *_struct_traits*.*=set noparent
-per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
-
-per-file *.mojom=set noparent
-per-file *.mojom=file://ipc/SECURITY_OWNERS
-
-per-file *.typemap=set noparent
-per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/chromium/ui/display/manager/chromeos/mojo/touch_device_transform.typemap b/chromium/ui/display/manager/chromeos/mojo/touch_device_transform.typemap
deleted file mode 100644
index 3a0a96276af..00000000000
--- a/chromium/ui/display/manager/chromeos/mojo/touch_device_transform.typemap
+++ /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.
-
-mojom = "//ui/display/manager/chromeos/mojo/touch_device_transform.mojom"
-public_headers = [ "//ui/display/manager/chromeos/touch_device_transform.h" ]
-traits_headers = [ "//ui/display/manager/chromeos/mojo/touch_device_transform_struct_traits.h" ]
-deps = [
- "//ui/gfx/mojo:struct_traits",
-]
-public_deps = [
- "//ui/display/manager",
-]
-type_mappings =
- [ "display.mojom.TouchDeviceTransform=display::TouchDeviceTransform" ]
diff --git a/chromium/ui/display/manager/chromeos/mojo/typemaps.gni b/chromium/ui/display/manager/chromeos/mojo/typemaps.gni
deleted file mode 100644
index 21a671bb583..00000000000
--- a/chromium/ui/display/manager/chromeos/mojo/typemaps.gni
+++ /dev/null
@@ -1,6 +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.
-
-typemaps =
- [ "//ui/display/manager/chromeos/mojo/touch_device_transform.typemap" ]
diff --git a/chromium/ui/display/manager/chromeos/touch_device_transform.h b/chromium/ui/display/manager/chromeos/touch_device_transform.h
deleted file mode 100644
index c9eee51c9b0..00000000000
--- a/chromium/ui/display/manager/chromeos/touch_device_transform.h
+++ /dev/null
@@ -1,26 +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_DISPLAY_MANAGER_CHROMEOS_TOUCH_DEVICE_TRANSFORM_H_
-#define UI_DISPLAY_MANAGER_CHROMEOS_TOUCH_DEVICE_TRANSFORM_H_
-
-#include <stdint.h>
-
-#include "ui/display/manager/display_manager_export.h"
-#include "ui/gfx/transform.h"
-
-namespace display {
-
-struct DISPLAY_MANAGER_EXPORT TouchDeviceTransform {
- TouchDeviceTransform();
- ~TouchDeviceTransform();
-
- int64_t display_id;
- int32_t device_id;
- gfx::Transform transform;
-};
-
-} // namespace display
-
-#endif // UI_DISPLAY_MANAGER_CHROMEOS_TOUCH_DEVICE_TRANSFORM_H_
diff --git a/chromium/ui/display/manager/chromeos/touch_transform_controller.cc b/chromium/ui/display/manager/chromeos/touch_transform_controller.cc
index a297d628ef9..3ed5de8929e 100644
--- a/chromium/ui/display/manager/chromeos/touch_transform_controller.cc
+++ b/chromium/ui/display/manager/chromeos/touch_transform_controller.cc
@@ -10,7 +10,6 @@
#include "third_party/skia/include/core/SkMatrix44.h"
#include "ui/display/display_layout.h"
#include "ui/display/manager/chromeos/display_configurator.h"
-#include "ui/display/manager/chromeos/touch_device_transform.h"
#include "ui/display/manager/chromeos/touch_transform_setter.h"
#include "ui/display/manager/display_manager.h"
#include "ui/display/manager/managed_display_info.h"
@@ -18,6 +17,7 @@
#include "ui/display/types/display_constants.h"
#include "ui/display/types/display_snapshot.h"
#include "ui/events/devices/input_device_manager.h"
+#include "ui/events/devices/touch_device_transform.h"
namespace display {
@@ -197,16 +197,10 @@ double TouchTransformController::GetTouchResolutionScale(
gfx::Transform TouchTransformController::GetTouchTransform(
const ManagedDisplayInfo& display,
const ManagedDisplayInfo& touch_display,
- const ui::TouchscreenDevice& touchscreen,
- const gfx::Size& framebuffer_size) const {
+ const ui::TouchscreenDevice& touchscreen) const {
auto current_size = gfx::SizeF(display.bounds_in_native().size());
auto touch_native_size = gfx::SizeF(touch_display.GetNativeModeSize());
-#if defined(USE_OZONE)
auto touch_area = gfx::SizeF(touchscreen.size);
-#elif defined(USE_X11)
- // On X11 touches are reported in the framebuffer coordinate space.
- auto touch_area = gfx::SizeF(framebuffer_size);
-#endif
gfx::Transform ctm;
@@ -214,14 +208,12 @@ gfx::Transform TouchTransformController::GetTouchTransform(
touch_area.IsEmpty() || touchscreen.id == ui::InputDevice::kInvalidId)
return ctm;
-#if defined(USE_OZONE)
// Translate the touch so that it falls within the display bounds. This
// should not be performed if the displays are mirrored.
if (display.id() == touch_display.id()) {
ctm.Translate(display.bounds_in_native().x(),
display.bounds_in_native().y());
}
-#endif
// If the device is currently under calibration, then do not return any
// transform as we want to use the raw native touch input data for calibration
@@ -300,8 +292,7 @@ TouchTransformController::~TouchTransformController() {}
void TouchTransformController::UpdateTouchTransforms() const {
UpdateData update_data;
UpdateTouchTransforms(&update_data);
- setter_->ConfigureTouchDevices(update_data.device_to_scale,
- update_data.touch_device_transforms);
+ setter_->ConfigureTouchDevices(update_data.touch_device_transforms);
}
void TouchTransformController::UpdateTouchRadius(
@@ -319,13 +310,15 @@ void TouchTransformController::UpdateTouchTransform(
const ManagedDisplayInfo& touch_display,
const ManagedDisplayInfo& target_display,
UpdateData* update_data) const {
- TouchDeviceTransform touch_device_transform;
+ ui::TouchDeviceTransform touch_device_transform;
touch_device_transform.display_id = target_display_id;
- gfx::Size fb_size = display_configurator_->framebuffer_size();
for (const auto& device_id : touch_display.input_devices()) {
touch_device_transform.device_id = device_id;
touch_device_transform.transform = GetTouchTransform(
- target_display, touch_display, FindTouchscreenById(device_id), fb_size);
+ target_display, touch_display, FindTouchscreenById(device_id));
+ auto device_to_scale_iter = update_data->device_to_scale.find(device_id);
+ if (device_to_scale_iter != update_data->device_to_scale.end())
+ touch_device_transform.radius_scale = device_to_scale_iter->second;
update_data->touch_device_transforms.push_back(touch_device_transform);
}
}
diff --git a/chromium/ui/display/manager/chromeos/touch_transform_controller.h b/chromium/ui/display/manager/chromeos/touch_transform_controller.h
index 69239bc5301..1d089e4e83b 100644
--- a/chromium/ui/display/manager/chromeos/touch_transform_controller.h
+++ b/chromium/ui/display/manager/chromeos/touch_transform_controller.h
@@ -17,6 +17,7 @@
namespace ui {
struct TouchscreenDevice;
+struct TouchDeviceTransform;
}
namespace display {
@@ -26,8 +27,6 @@ class DisplayManager;
class ManagedDisplayInfo;
class TouchTransformSetter;
-struct TouchDeviceTransform;
-
namespace test {
class TouchTransformControllerTest;
}
@@ -59,7 +58,7 @@ class DISPLAY_MANAGER_EXPORT TouchTransformController {
~UpdateData();
std::map<int32_t, double> device_to_scale;
- std::vector<TouchDeviceTransform> touch_device_transforms;
+ std::vector<ui::TouchDeviceTransform> touch_device_transforms;
};
void UpdateTouchTransforms(UpdateData* data) const;
@@ -69,14 +68,12 @@ class DISPLAY_MANAGER_EXPORT TouchTransformController {
// The transform is also responsible for properly scaling the display if the
// display supports panel fitting.
//
- // On X11 events are reported in framebuffer coordinate space, so the
- // |framebuffer_size| is used for scaling.
// On Ozone events are reported in the touchscreen's resolution, so
// |touch_display| is used to determine the size and scale the event.
- gfx::Transform GetTouchTransform(const ManagedDisplayInfo& display,
- const ManagedDisplayInfo& touch_display,
- const ui::TouchscreenDevice& touchscreen,
- const gfx::Size& framebuffer_size) const;
+ gfx::Transform GetTouchTransform(
+ const ManagedDisplayInfo& display,
+ const ManagedDisplayInfo& touch_display,
+ const ui::TouchscreenDevice& touchscreen) const;
// Returns the scaling factor for the touch radius such that it scales the
// radius from |touch_device|'s coordinate system to the |touch_display|'s
diff --git a/chromium/ui/display/manager/chromeos/touch_transform_controller_unittest.cc b/chromium/ui/display/manager/chromeos/touch_transform_controller_unittest.cc
index 473b847b753..2860c085541 100644
--- a/chromium/ui/display/manager/chromeos/touch_transform_controller_unittest.cc
+++ b/chromium/ui/display/manager/chromeos/touch_transform_controller_unittest.cc
@@ -21,7 +21,9 @@ namespace test {
namespace {
constexpr int kDisplayId1 = 1;
+constexpr int kDisplayId2 = 2;
constexpr int kTouchId1 = 5;
+constexpr int kTouchId2 = 6;
ManagedDisplayInfo CreateDisplayInfo(int64_t id,
unsigned int touch_device_id,
@@ -39,6 +41,19 @@ ManagedDisplayInfo CreateDisplayInfo(int64_t id,
return info;
}
+ui::TouchDeviceTransform CreateTouchDeviceTransform(
+ int64_t display_id,
+ int32_t device_id,
+ const gfx::Transform& transform,
+ double radius_scale = 1.0) {
+ ui::TouchDeviceTransform touch_device_transform;
+ touch_device_transform.display_id = display_id;
+ touch_device_transform.device_id = device_id;
+ touch_device_transform.transform = transform;
+ touch_device_transform.radius_scale = radius_scale;
+ return touch_device_transform;
+}
+
ui::TouchscreenDevice CreateTouchscreenDevice(unsigned int id,
const gfx::Size& size) {
return ui::TouchscreenDevice(id, ui::InputDeviceType::INPUT_DEVICE_EXTERNAL,
@@ -101,12 +116,12 @@ class TouchTransformControllerTest : public testing::Test {
TouchTransformControllerTest() {}
~TouchTransformControllerTest() override {}
- gfx::Transform GetTouchTransform(const ManagedDisplayInfo& display,
- const ManagedDisplayInfo& touch_display,
- const ui::TouchscreenDevice& touchscreen,
- const gfx::Size& framebuffer_size) const {
+ gfx::Transform GetTouchTransform(
+ const ManagedDisplayInfo& display,
+ const ManagedDisplayInfo& touch_display,
+ const ui::TouchscreenDevice& touchscreen) const {
return touch_transform_controller_->GetTouchTransform(
- display, touch_display, touchscreen, framebuffer_size);
+ display, touch_display, touchscreen);
}
double GetTouchResolutionScale(
@@ -160,8 +175,7 @@ TEST_F(TouchTransformControllerTest, MirrorModeLetterboxing) {
gfx::Size fb_size(1920, 1200);
- // Create the touchscreens with the same size as the framebuffer so we can
- // share the tests between Ozone & X11.
+ // TODO(kylechar): Check the TouchscreenDevice size makes sense for Ozone.
ui::TouchscreenDevice internal_touchscreen =
CreateTouchscreenDevice(10, fb_size);
ui::TouchscreenDevice external_touchscreen =
@@ -169,15 +183,16 @@ TEST_F(TouchTransformControllerTest, MirrorModeLetterboxing) {
ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance();
- device_manager->UpdateTouchInfoForDisplay(
+ std::vector<ui::TouchDeviceTransform> transforms;
+ transforms.push_back(CreateTouchDeviceTransform(
internal_display_info.id(), internal_touchscreen.id,
GetTouchTransform(internal_display_info, internal_display_info,
- internal_touchscreen, fb_size));
-
- device_manager->UpdateTouchInfoForDisplay(
+ internal_touchscreen)));
+ transforms.push_back(CreateTouchDeviceTransform(
internal_display_info.id(), external_touchscreen.id,
GetTouchTransform(external_display_info, external_display_info,
- external_touchscreen, fb_size));
+ external_touchscreen)));
+ device_manager->ConfigureTouchDevices(transforms);
EXPECT_EQ(1, device_manager->GetTargetDisplayForTouchDevice(10));
EXPECT_EQ(1, device_manager->GetTargetDisplayForTouchDevice(11));
@@ -227,24 +242,25 @@ TEST_F(TouchTransformControllerTest, MirrorModePillarboxing) {
gfx::Size fb_size(1024, 768);
- // Create the touchscreens with the same size as the framebuffer so we can
- // share the tests between Ozone & X11.
+ // TODO(kylechar): Check the TouchscreenDevice size makes sense for Ozone.
ui::TouchscreenDevice internal_touchscreen =
CreateTouchscreenDevice(10, fb_size);
ui::TouchscreenDevice external_touchscreen =
CreateTouchscreenDevice(11, fb_size);
ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance();
+ std::vector<ui::TouchDeviceTransform> transforms;
- device_manager->UpdateTouchInfoForDisplay(
+ transforms.push_back(CreateTouchDeviceTransform(
internal_display_info.id(), internal_touchscreen.id,
GetTouchTransform(internal_display_info, internal_display_info,
- internal_touchscreen, fb_size));
+ internal_touchscreen)));
- device_manager->UpdateTouchInfoForDisplay(
+ transforms.push_back(CreateTouchDeviceTransform(
internal_display_info.id(), external_touchscreen.id,
GetTouchTransform(external_display_info, external_display_info,
- external_touchscreen, fb_size));
+ external_touchscreen)));
+ device_manager->ConfigureTouchDevices(transforms);
EXPECT_EQ(1, device_manager->GetTargetDisplayForTouchDevice(10));
EXPECT_EQ(1, device_manager->GetTargetDisplayForTouchDevice(11));
@@ -299,24 +315,24 @@ TEST_F(TouchTransformControllerTest, SoftwareMirrorMode) {
gfx::Size fb_size(1920, 1990);
- // Create the touchscreens with the same size as the framebuffer so we can
- // share the tests between Ozone & X11.
+ // TODO(kylechar): Check the TouchscreenDevice size makes sense for Ozone.
ui::TouchscreenDevice display1_touchscreen =
CreateTouchscreenDevice(10, fb_size);
ui::TouchscreenDevice display2_touchscreen =
CreateTouchscreenDevice(11, fb_size);
ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance();
+ std::vector<ui::TouchDeviceTransform> transforms;
- device_manager->UpdateTouchInfoForDisplay(
+ transforms.push_back(CreateTouchDeviceTransform(
display1_info.id(), display1_touchscreen.id,
- GetTouchTransform(display1_info, display1_info, display1_touchscreen,
- fb_size));
+ GetTouchTransform(display1_info, display1_info, display1_touchscreen)));
- device_manager->UpdateTouchInfoForDisplay(
+ transforms.push_back(CreateTouchDeviceTransform(
display1_info.id(), display2_touchscreen.id,
- GetTouchTransform(display1_info, display2_info, display2_touchscreen,
- fb_size));
+ GetTouchTransform(display1_info, display2_info, display2_touchscreen)));
+
+ device_manager->ConfigureTouchDevices(transforms);
EXPECT_EQ(1, device_manager->GetTargetDisplayForTouchDevice(10));
EXPECT_EQ(1, device_manager->GetTargetDisplayForTouchDevice(11));
@@ -370,20 +386,20 @@ TEST_F(TouchTransformControllerTest, ExtendedMode) {
CreateDisplayInfo(2, 6u, gfx::Rect(0, 828, 2560, 1600));
gfx::Size fb_size(2560, 2428);
- // Create the touchscreens with the same size as the framebuffer so we can
- // share the tests between Ozone & X11.
+ // TODO(kylechar): Check the TouchscreenDevice size makes sense for Ozone.
ui::TouchscreenDevice touchscreen1 = CreateTouchscreenDevice(5, fb_size);
ui::TouchscreenDevice touchscreen2 = CreateTouchscreenDevice(6, fb_size);
ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance();
-
- device_manager->UpdateTouchInfoForDisplay(
+ std::vector<ui::TouchDeviceTransform> transforms;
+ transforms.push_back(CreateTouchDeviceTransform(
display1.id(), touchscreen1.id,
- GetTouchTransform(display1, display1, touchscreen1, fb_size));
+ GetTouchTransform(display1, display1, touchscreen1)));
- device_manager->UpdateTouchInfoForDisplay(
+ transforms.push_back(CreateTouchDeviceTransform(
display2.id(), touchscreen2.id,
- GetTouchTransform(display2, display2, touchscreen2, fb_size));
+ GetTouchTransform(display2, display2, touchscreen2)));
+ device_manager->ConfigureTouchDevices(transforms);
EXPECT_EQ(1, device_manager->GetTargetDisplayForTouchDevice(5));
EXPECT_EQ(2, device_manager->GetTargetDisplayForTouchDevice(6));
@@ -407,26 +423,16 @@ TEST_F(TouchTransformControllerTest, ExtendedMode) {
x = 0.0;
y = 0.0;
device_manager->ApplyTouchTransformer(6, &x, &y);
-#if defined(USE_OZONE)
// On ozone we expect screen coordinates so add display origin.
EXPECT_NEAR(0 + 0, x, 0.5);
EXPECT_NEAR(0 + 828, y, 0.5);
-#else
- EXPECT_NEAR(0, x, 0.5);
- EXPECT_NEAR(0, y, 0.5);
-#endif
x = 2559.0;
y = 2427.0;
device_manager->ApplyTouchTransformer(6, &x, &y);
-#if defined(USE_OZONE)
// On ozone we expect screen coordinates so add display origin.
EXPECT_NEAR(2559 + 0, x, 0.5);
EXPECT_NEAR(1599 + 828, y, 0.5);
-#else
- EXPECT_NEAR(2559, x, 0.5);
- EXPECT_NEAR(1599, y, 0.5);
-#endif
}
TEST_F(TouchTransformControllerTest, TouchRadiusScale) {
@@ -441,16 +447,12 @@ TEST_F(TouchTransformControllerTest, TouchRadiusScale) {
}
TEST_F(TouchTransformControllerTest, OzoneTranslation) {
-#if defined(USE_OZONE)
// The internal display has size 1920 x 1200. The external display has
// size 1920x1200. The total frame buffer is 1920x2450,
// where 2458 = 1200 + 50 (hidden gap) + 1200
// and the second monitor is translated to Point (0, 1250) in the
// framebuffer.
- const int kDisplayId2 = 2;
- const int kTouchId2 = 6;
const gfx::Size kDisplaySize(1920, 1200);
- const gfx::Size kTouchSize(1920, 1200);
const int kHiddenGap = 50;
ManagedDisplayInfo display1 = CreateDisplayInfo(
@@ -461,23 +463,23 @@ TEST_F(TouchTransformControllerTest, OzoneTranslation) {
gfx::Rect(0, kDisplaySize.height() + kHiddenGap,
kDisplaySize.width(), kDisplaySize.height()));
- gfx::Size fb_size(1920, 2450);
-
ui::TouchscreenDevice touchscreen1 =
CreateTouchscreenDevice(kTouchId1, kDisplaySize);
ui::TouchscreenDevice touchscreen2 =
CreateTouchscreenDevice(kTouchId2, kDisplaySize);
ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance();
+ std::vector<ui::TouchDeviceTransform> transforms;
// Mirror displays. Touch screen 2 is associated to display 1.
- device_manager->UpdateTouchInfoForDisplay(
+ transforms.push_back(CreateTouchDeviceTransform(
display1.id(), touchscreen1.id,
- GetTouchTransform(display1, display1, touchscreen1, kTouchSize));
+ GetTouchTransform(display1, display1, touchscreen1)));
- device_manager->UpdateTouchInfoForDisplay(
+ transforms.push_back(CreateTouchDeviceTransform(
display1.id(), touchscreen2.id,
- GetTouchTransform(display1, display2, touchscreen2, kTouchSize));
+ GetTouchTransform(display1, display2, touchscreen2)));
+ device_manager->ConfigureTouchDevices(transforms);
EXPECT_EQ(kDisplayId1,
device_manager->GetTargetDisplayForTouchDevice(kTouchId1));
@@ -509,9 +511,10 @@ TEST_F(TouchTransformControllerTest, OzoneTranslation) {
EXPECT_NEAR(1200, y, 0.5);
// Remove mirroring of displays.
- device_manager->UpdateTouchInfoForDisplay(
+ transforms.push_back(CreateTouchDeviceTransform(
display2.id(), touchscreen2.id,
- GetTouchTransform(display2, display2, touchscreen2, kTouchSize));
+ GetTouchTransform(display2, display2, touchscreen2)));
+ device_manager->ConfigureTouchDevices(transforms);
x = 1920.0;
y = 1200.0;
@@ -524,7 +527,6 @@ TEST_F(TouchTransformControllerTest, OzoneTranslation) {
device_manager->ApplyTouchTransformer(kTouchId2, &x, &y);
EXPECT_NEAR(1920, x, 0.5);
EXPECT_NEAR(1200 + kDisplaySize.height() + kHiddenGap, y, 0.5);
-#endif // USE_OZONE
}
TEST_F(TouchTransformControllerTest, AccurateUserTouchCalibration) {
@@ -549,16 +551,15 @@ TEST_F(TouchTransformControllerTest, AccurateUserTouchCalibration) {
const std::string msg = GetTouchPointString(user_input);
- gfx::Size fb_size(1920, 1200);
-
ui::TouchscreenDevice touchscreen =
CreateTouchscreenDevice(kTouchId1, kTouchSize);
ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance();
-
- device_manager->UpdateTouchInfoForDisplay(
+ std::vector<ui::TouchDeviceTransform> transforms;
+ transforms.push_back(CreateTouchDeviceTransform(
display.id(), touchscreen.id,
- GetTouchTransform(display, display, touchscreen, kTouchSize));
+ GetTouchTransform(display, display, touchscreen)));
+ device_manager->ConfigureTouchDevices(transforms);
EXPECT_EQ(kDisplayId1,
device_manager->GetTargetDisplayForTouchDevice(kTouchId1));
@@ -598,10 +599,11 @@ TEST_F(TouchTransformControllerTest, ErrorProneUserTouchCalibration) {
CreateTouchscreenDevice(kTouchId1, kTouchSize);
ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance();
-
- device_manager->UpdateTouchInfoForDisplay(
+ std::vector<ui::TouchDeviceTransform> transforms;
+ transforms.push_back(CreateTouchDeviceTransform(
display.id(), touchscreen.id,
- GetTouchTransform(display, display, touchscreen, kTouchSize));
+ GetTouchTransform(display, display, touchscreen)));
+ device_manager->ConfigureTouchDevices(transforms);
EXPECT_EQ(kDisplayId1,
device_manager->GetTargetDisplayForTouchDevice(kTouchId1));
@@ -643,10 +645,11 @@ TEST_F(TouchTransformControllerTest, ResolutionChangeUserTouchCalibration) {
CreateTouchscreenDevice(kTouchId1, kTouchSize);
ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance();
-
- device_manager->UpdateTouchInfoForDisplay(
+ std::vector<ui::TouchDeviceTransform> transforms;
+ transforms.push_back(CreateTouchDeviceTransform(
display.id(), touchscreen.id,
- GetTouchTransform(display, display, touchscreen, kTouchSize));
+ GetTouchTransform(display, display, touchscreen)));
+ device_manager->ConfigureTouchDevices(transforms);
EXPECT_EQ(kDisplayId1,
device_manager->GetTargetDisplayForTouchDevice(kTouchId1));
@@ -684,9 +687,11 @@ TEST_F(TouchTransformControllerTest, DifferentBoundsUserTouchCalibration) {
ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance();
- device_manager->UpdateTouchInfoForDisplay(
+ std::vector<ui::TouchDeviceTransform> transforms;
+ transforms.push_back(CreateTouchDeviceTransform(
display.id(), touchscreen.id,
- GetTouchTransform(display, display, touchscreen, kTouchSize));
+ GetTouchTransform(display, display, touchscreen)));
+ device_manager->ConfigureTouchDevices(transforms);
EXPECT_EQ(kDisplayId1,
device_manager->GetTargetDisplayForTouchDevice(kTouchId1));
@@ -718,12 +723,8 @@ TEST_F(TouchTransformControllerTest, LetterboxingUserTouchCalibration) {
false)));
internal_display_info.SetManagedDisplayModes(internal_modes);
- gfx::Size fb_size(kDisplaySize);
-
- // Create the touchscreens with the same size as the framebuffer so we can
- // share the tests between Ozone & X11.
ui::TouchscreenDevice internal_touchscreen =
- CreateTouchscreenDevice(kTouchId1, fb_size);
+ CreateTouchscreenDevice(kTouchId1, kTouchSize);
ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance();
@@ -742,10 +743,12 @@ TEST_F(TouchTransformControllerTest, LetterboxingUserTouchCalibration) {
internal_display_info.SetTouchCalibrationData(touch_data);
EXPECT_TRUE(internal_display_info.has_touch_calibration_data());
- device_manager->UpdateTouchInfoForDisplay(
+ std::vector<ui::TouchDeviceTransform> transforms;
+ transforms.push_back(CreateTouchDeviceTransform(
internal_display_info.id(), internal_touchscreen.id,
GetTouchTransform(internal_display_info, internal_display_info,
- internal_touchscreen, fb_size));
+ internal_touchscreen)));
+ device_manager->ConfigureTouchDevices(transforms);
EXPECT_EQ(kDisplayId1,
device_manager->GetTargetDisplayForTouchDevice(kTouchId1));
@@ -793,12 +796,8 @@ TEST_F(TouchTransformControllerTest, PillarBoxingUserTouchCalibration) {
false)));
internal_display_info.SetManagedDisplayModes(internal_modes);
- gfx::Size fb_size(kDisplaySize);
-
- // Create the touchscreens with the same size as the framebuffer so we can
- // share the tests between Ozone & X11.
ui::TouchscreenDevice internal_touchscreen =
- CreateTouchscreenDevice(kTouchId1, fb_size);
+ CreateTouchscreenDevice(kTouchId1, kDisplaySize);
ui::DeviceDataManager* device_manager = ui::DeviceDataManager::GetInstance();
@@ -817,10 +816,12 @@ TEST_F(TouchTransformControllerTest, PillarBoxingUserTouchCalibration) {
internal_display_info.SetTouchCalibrationData(touch_data);
EXPECT_TRUE(internal_display_info.has_touch_calibration_data());
- device_manager->UpdateTouchInfoForDisplay(
+ std::vector<ui::TouchDeviceTransform> transforms;
+ transforms.push_back(CreateTouchDeviceTransform(
internal_display_info.id(), internal_touchscreen.id,
GetTouchTransform(internal_display_info, internal_display_info,
- internal_touchscreen, fb_size));
+ internal_touchscreen)));
+ device_manager->ConfigureTouchDevices(transforms);
EXPECT_EQ(kDisplayId1,
device_manager->GetTargetDisplayForTouchDevice(kTouchId1));
diff --git a/chromium/ui/display/manager/chromeos/touch_transform_setter.h b/chromium/ui/display/manager/chromeos/touch_transform_setter.h
index 4e87b079c4c..efbb8e12a6f 100644
--- a/chromium/ui/display/manager/chromeos/touch_transform_setter.h
+++ b/chromium/ui/display/manager/chromeos/touch_transform_setter.h
@@ -5,15 +5,16 @@
#ifndef UI_DISPLAY_MANAGER_CHROMEOS_TOUCH_TRANSFORM_SETTER_H_
#define UI_DISPLAY_MANAGER_CHROMEOS_TOUCH_TRANSFORM_SETTER_H_
-#include <map>
#include <vector>
#include "base/macros.h"
#include "ui/display/manager/display_manager_export.h"
-namespace display {
-
+namespace ui {
struct TouchDeviceTransform;
+}
+
+namespace display {
// TouchTransformSetter is used by TouchTransformController to apply the actual
// settings.
@@ -21,11 +22,9 @@ class DISPLAY_MANAGER_EXPORT TouchTransformSetter {
public:
virtual ~TouchTransformSetter() {}
- // |scales| maps from the touch device id to the touch radius scale and
// |transforms| contains the transform for each device and display pair.
virtual void ConfigureTouchDevices(
- const std::map<int32_t, double>& scales,
- const std::vector<TouchDeviceTransform>& transforms) = 0;
+ const std::vector<ui::TouchDeviceTransform>& transforms) = 0;
};
} // namespace display
diff --git a/chromium/ui/display/manager/chromeos/update_display_configuration_task.cc b/chromium/ui/display/manager/chromeos/update_display_configuration_task.cc
index 581c7c624a8..1e533f9b097 100644
--- a/chromium/ui/display/manager/chromeos/update_display_configuration_task.cc
+++ b/chromium/ui/display/manager/chromeos/update_display_configuration_task.cc
@@ -18,7 +18,6 @@ UpdateDisplayConfigurationTask::UpdateDisplayConfigurationTask(
MultipleDisplayState new_display_state,
chromeos::DisplayPowerState new_power_state,
int power_flags,
- uint32_t background_color_argb,
bool force_configure,
const ResponseCallback& callback)
: delegate_(delegate),
@@ -26,19 +25,16 @@ UpdateDisplayConfigurationTask::UpdateDisplayConfigurationTask(
new_display_state_(new_display_state),
new_power_state_(new_power_state),
power_flags_(power_flags),
- background_color_argb_(background_color_argb),
force_configure_(force_configure),
callback_(callback),
force_dpms_(false),
requesting_displays_(false),
weak_ptr_factory_(this) {
- delegate_->GrabServer();
delegate_->AddObserver(this);
}
UpdateDisplayConfigurationTask::~UpdateDisplayConfigurationTask() {
delegate_->RemoveObserver(this);
- delegate_->UngrabServer();
}
void UpdateDisplayConfigurationTask::Run() {
@@ -65,9 +61,6 @@ void UpdateDisplayConfigurationTask::OnDisplaysUpdated(
cached_displays_ = displays;
requesting_displays_ = false;
- if (cached_displays_.size() > 1 && background_color_argb_)
- delegate_->SetBackgroundColor(background_color_argb_);
-
// If the user hasn't requested a display state, update it using the requested
// power state.
if (new_display_state_ == MULTIPLE_DISPLAY_STATE_INVALID)
@@ -99,14 +92,11 @@ void UpdateDisplayConfigurationTask::EnterState(
VLOG(2) << "EnterState";
std::vector<DisplayConfigureRequest> requests;
if (!layout_manager_->GetDisplayLayout(cached_displays_, new_display_state_,
- new_power_state_, &requests,
- &framebuffer_size_)) {
+ new_power_state_, &requests)) {
callback.Run(ConfigureDisplaysTask::ERROR);
return;
}
if (!requests.empty()) {
- DCHECK(!framebuffer_size_.IsEmpty());
- delegate_->CreateFrameBuffer(framebuffer_size_);
configure_task_.reset(
new ConfigureDisplaysTask(delegate_, requests, callback));
configure_task_->Run();
@@ -160,11 +150,8 @@ void UpdateDisplayConfigurationTask::OnEnableSoftwareMirroring(
}
void UpdateDisplayConfigurationTask::FinishConfiguration(bool success) {
- if (success && force_dpms_)
- delegate_->ForceDPMSOn();
-
- callback_.Run(success, cached_displays_, framebuffer_size_,
- new_display_state_, new_power_state_);
+ callback_.Run(success, cached_displays_, new_display_state_,
+ new_power_state_);
}
bool UpdateDisplayConfigurationTask::ShouldForceDpms() const {
diff --git a/chromium/ui/display/manager/chromeos/update_display_configuration_task.h b/chromium/ui/display/manager/chromeos/update_display_configuration_task.h
index e76ba8cdf79..1538fd0f2e3 100644
--- a/chromium/ui/display/manager/chromeos/update_display_configuration_task.h
+++ b/chromium/ui/display/manager/chromeos/update_display_configuration_task.h
@@ -24,20 +24,17 @@ class NativeDisplayDelegate;
class DISPLAY_MANAGER_EXPORT UpdateDisplayConfigurationTask
: public NativeDisplayObserver {
public:
- typedef base::Callback<void(
- bool /* success */,
- const std::vector<DisplaySnapshot*>& /* displays */,
- const gfx::Size& /* framebuffer_size */,
- MultipleDisplayState /* new_display_state */,
- chromeos::DisplayPowerState /* new_power_state */)>
- ResponseCallback;
+ using ResponseCallback =
+ base::Callback<void(bool /* success */,
+ const std::vector<DisplaySnapshot*>& /* displays */,
+ MultipleDisplayState /* new_display_state */,
+ chromeos::DisplayPowerState /* new_power_state */)>;
UpdateDisplayConfigurationTask(NativeDisplayDelegate* delegate,
DisplayLayoutManager* layout_manager,
MultipleDisplayState new_display_state,
chromeos::DisplayPowerState new_power_state,
int power_flags,
- uint32_t background_color_argb,
bool force_configure,
const ResponseCallback& callback);
~UpdateDisplayConfigurationTask() override;
@@ -91,8 +88,6 @@ class DISPLAY_MANAGER_EXPORT UpdateDisplayConfigurationTask
// DisplayConfigurator.
int power_flags_;
- uint32_t background_color_argb_;
-
bool force_configure_;
// Used to signal that the task has finished.
@@ -105,8 +100,6 @@ class DISPLAY_MANAGER_EXPORT UpdateDisplayConfigurationTask
// List of updated displays.
std::vector<DisplaySnapshot*> cached_displays_;
- gfx::Size framebuffer_size_;
-
std::unique_ptr<ConfigureDisplaysTask> configure_task_;
base::WeakPtrFactory<UpdateDisplayConfigurationTask> weak_ptr_factory_;
diff --git a/chromium/ui/display/manager/chromeos/update_display_configuration_task_unittest.cc b/chromium/ui/display/manager/chromeos/update_display_configuration_task_unittest.cc
index 72989ca0d73..4115036836e 100644
--- a/chromium/ui/display/manager/chromeos/update_display_configuration_task_unittest.cc
+++ b/chromium/ui/display/manager/chromeos/update_display_configuration_task_unittest.cc
@@ -80,11 +80,11 @@ class TestDisplayLayoutManager : public DisplayLayoutManager {
return power_state_;
}
- bool GetDisplayLayout(const std::vector<DisplaySnapshot*>& displays,
- MultipleDisplayState new_display_state,
- chromeos::DisplayPowerState new_power_state,
- std::vector<DisplayConfigureRequest>* requests,
- gfx::Size* framebuffer_size) const override {
+ bool GetDisplayLayout(
+ const std::vector<DisplaySnapshot*>& displays,
+ MultipleDisplayState new_display_state,
+ chromeos::DisplayPowerState new_power_state,
+ std::vector<DisplayConfigureRequest>* requests) const override {
gfx::Point origin;
for (DisplaySnapshot* display : displays) {
const DisplayMode* mode = display->native_mode();
@@ -100,12 +100,8 @@ class TestDisplayLayoutManager : public DisplayLayoutManager {
requests->push_back(DisplayConfigureRequest(display, nullptr, origin));
}
- if (new_display_state != MULTIPLE_DISPLAY_STATE_DUAL_MIRROR) {
+ if (new_display_state != MULTIPLE_DISPLAY_STATE_DUAL_MIRROR)
origin.Offset(0, mode->size().height());
- framebuffer_size->SetToMax(gfx::Size(mode->size().width(), origin.y()));
- } else {
- *framebuffer_size = mode->size();
- }
}
return true;
@@ -179,7 +175,6 @@ class UpdateDisplayConfigurationTaskTest : public testing::Test {
void ResponseCallback(bool success,
const std::vector<DisplaySnapshot*>& displays,
- const gfx::Size& framebuffer_size,
MultipleDisplayState new_display_state,
chromeos::DisplayPowerState new_power_state) {
configured_ = true;
@@ -220,7 +215,7 @@ TEST_F(UpdateDisplayConfigurationTaskTest, HeadlessConfiguration) {
{
UpdateDisplayConfigurationTask task(
&delegate_, &layout_manager_, MULTIPLE_DISPLAY_STATE_HEADLESS,
- chromeos::DISPLAY_POWER_ALL_ON, 0, 0, false,
+ chromeos::DISPLAY_POWER_ALL_ON, 0, false,
base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback,
base::Unretained(this)));
task.Run();
@@ -230,7 +225,7 @@ TEST_F(UpdateDisplayConfigurationTaskTest, HeadlessConfiguration) {
EXPECT_TRUE(configuration_status_);
EXPECT_EQ(MULTIPLE_DISPLAY_STATE_HEADLESS, display_state_);
EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, power_state_);
- EXPECT_EQ(JoinActions(kGrab, kUngrab, nullptr), log_.GetActionsAndClear());
+ EXPECT_EQ(kNoActions, log_.GetActionsAndClear());
}
TEST_F(UpdateDisplayConfigurationTaskTest, SingleConfiguration) {
@@ -239,7 +234,7 @@ TEST_F(UpdateDisplayConfigurationTaskTest, SingleConfiguration) {
{
UpdateDisplayConfigurationTask task(
&delegate_, &layout_manager_, MULTIPLE_DISPLAY_STATE_SINGLE,
- chromeos::DISPLAY_POWER_ALL_ON, 0, 0, false,
+ chromeos::DISPLAY_POWER_ALL_ON, 0, false,
base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback,
base::Unretained(this)));
task.Run();
@@ -251,11 +246,8 @@ TEST_F(UpdateDisplayConfigurationTaskTest, SingleConfiguration) {
EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, power_state_);
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(small_mode_.size(), displays_[0].get(), nullptr)
- .c_str(),
GetCrtcAction(*displays_[0], &small_mode_, gfx::Point()).c_str(),
- kUngrab, nullptr),
+ nullptr),
log_.GetActionsAndClear());
}
@@ -265,7 +257,7 @@ TEST_F(UpdateDisplayConfigurationTaskTest, ExtendedConfiguration) {
{
UpdateDisplayConfigurationTask task(
&delegate_, &layout_manager_, MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
- chromeos::DISPLAY_POWER_ALL_ON, 0, 0, false,
+ chromeos::DISPLAY_POWER_ALL_ON, 0, false,
base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback,
base::Unretained(this)));
task.Run();
@@ -277,16 +269,11 @@ TEST_F(UpdateDisplayConfigurationTaskTest, ExtendedConfiguration) {
EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, power_state_);
EXPECT_EQ(
JoinActions(
- kGrab, GetFramebufferAction(gfx::Size(big_mode_.size().width(),
- small_mode_.size().height() +
- big_mode_.size().height()),
- displays_[0].get(), displays_[1].get())
- .c_str(),
GetCrtcAction(*displays_[0], &small_mode_, gfx::Point()).c_str(),
GetCrtcAction(*displays_[1], &big_mode_,
gfx::Point(0, small_mode_.size().height()))
.c_str(),
- kUngrab, nullptr),
+ nullptr),
log_.GetActionsAndClear());
}
@@ -296,7 +283,7 @@ TEST_F(UpdateDisplayConfigurationTaskTest, MirrorConfiguration) {
{
UpdateDisplayConfigurationTask task(
&delegate_, &layout_manager_, MULTIPLE_DISPLAY_STATE_DUAL_MIRROR,
- chromeos::DISPLAY_POWER_ALL_ON, 0, 0, false,
+ chromeos::DISPLAY_POWER_ALL_ON, 0, false,
base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback,
base::Unretained(this)));
task.Run();
@@ -308,12 +295,9 @@ TEST_F(UpdateDisplayConfigurationTaskTest, MirrorConfiguration) {
EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, power_state_);
EXPECT_EQ(
JoinActions(
- kGrab, GetFramebufferAction(small_mode_.size(), displays_[0].get(),
- displays_[1].get())
- .c_str(),
GetCrtcAction(*displays_[0], &small_mode_, gfx::Point()).c_str(),
GetCrtcAction(*displays_[1], &small_mode_, gfx::Point()).c_str(),
- kUngrab, nullptr),
+ nullptr),
log_.GetActionsAndClear());
}
@@ -324,7 +308,7 @@ TEST_F(UpdateDisplayConfigurationTaskTest, FailMirrorConfiguration) {
{
UpdateDisplayConfigurationTask task(
&delegate_, &layout_manager_, MULTIPLE_DISPLAY_STATE_DUAL_MIRROR,
- chromeos::DISPLAY_POWER_ALL_ON, 0, 0, false,
+ chromeos::DISPLAY_POWER_ALL_ON, 0, false,
base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback,
base::Unretained(this)));
task.Run();
@@ -332,7 +316,7 @@ TEST_F(UpdateDisplayConfigurationTaskTest, FailMirrorConfiguration) {
EXPECT_TRUE(configured_);
EXPECT_FALSE(configuration_status_);
- EXPECT_EQ(JoinActions(kGrab, kUngrab, nullptr), log_.GetActionsAndClear());
+ EXPECT_EQ(kNoActions, log_.GetActionsAndClear());
}
TEST_F(UpdateDisplayConfigurationTaskTest, FailExtendedConfiguration) {
@@ -342,7 +326,7 @@ TEST_F(UpdateDisplayConfigurationTaskTest, FailExtendedConfiguration) {
{
UpdateDisplayConfigurationTask task(
&delegate_, &layout_manager_, MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
- chromeos::DISPLAY_POWER_ALL_ON, 0, 0, false,
+ chromeos::DISPLAY_POWER_ALL_ON, 0, false,
base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback,
base::Unretained(this)));
task.Run();
@@ -352,11 +336,6 @@ TEST_F(UpdateDisplayConfigurationTaskTest, FailExtendedConfiguration) {
EXPECT_FALSE(configuration_status_);
EXPECT_EQ(
JoinActions(
- kGrab, GetFramebufferAction(gfx::Size(big_mode_.size().width(),
- small_mode_.size().height() +
- big_mode_.size().height()),
- displays_[0].get(), displays_[1].get())
- .c_str(),
GetCrtcAction(*displays_[0], &small_mode_, gfx::Point()).c_str(),
GetCrtcAction(*displays_[1], &big_mode_,
gfx::Point(0, small_mode_.size().height()))
@@ -364,7 +343,7 @@ TEST_F(UpdateDisplayConfigurationTaskTest, FailExtendedConfiguration) {
GetCrtcAction(*displays_[1], &small_mode_,
gfx::Point(0, small_mode_.size().height()))
.c_str(),
- kUngrab, nullptr),
+ nullptr),
log_.GetActionsAndClear());
}
@@ -374,7 +353,7 @@ TEST_F(UpdateDisplayConfigurationTaskTest, SingleChangePowerConfiguration) {
{
UpdateDisplayConfigurationTask task(
&delegate_, &layout_manager_, MULTIPLE_DISPLAY_STATE_SINGLE,
- chromeos::DISPLAY_POWER_ALL_ON, 0, 0, false,
+ chromeos::DISPLAY_POWER_ALL_ON, 0, false,
base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback,
base::Unretained(this)));
task.Run();
@@ -386,18 +365,15 @@ TEST_F(UpdateDisplayConfigurationTaskTest, SingleChangePowerConfiguration) {
EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_ON, power_state_);
EXPECT_EQ(
JoinActions(
- kGrab,
- GetFramebufferAction(small_mode_.size(), displays_[0].get(), nullptr)
- .c_str(),
GetCrtcAction(*displays_[0], &small_mode_, gfx::Point()).c_str(),
- kUngrab, nullptr),
+ nullptr),
log_.GetActionsAndClear());
// Turn power off
{
UpdateDisplayConfigurationTask task(
&delegate_, &layout_manager_, MULTIPLE_DISPLAY_STATE_SINGLE,
- chromeos::DISPLAY_POWER_ALL_OFF, 0, 0, false,
+ chromeos::DISPLAY_POWER_ALL_OFF, 0, false,
base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback,
base::Unretained(this)));
task.Run();
@@ -407,11 +383,8 @@ TEST_F(UpdateDisplayConfigurationTaskTest, SingleChangePowerConfiguration) {
EXPECT_EQ(MULTIPLE_DISPLAY_STATE_SINGLE, display_state_);
EXPECT_EQ(chromeos::DISPLAY_POWER_ALL_OFF, power_state_);
EXPECT_EQ(
- JoinActions(kGrab, GetFramebufferAction(small_mode_.size(),
- displays_[0].get(), nullptr)
- .c_str(),
- GetCrtcAction(*displays_[0], nullptr, gfx::Point()).c_str(),
- kUngrab, nullptr),
+ JoinActions(
+ GetCrtcAction(*displays_[0], nullptr, gfx::Point()).c_str(), nullptr),
log_.GetActionsAndClear());
}
@@ -424,7 +397,7 @@ TEST_F(UpdateDisplayConfigurationTaskTest, NoopSoftwareMirrorConfiguration) {
{
UpdateDisplayConfigurationTask task(
&delegate_, &layout_manager_, MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
- chromeos::DISPLAY_POWER_ALL_ON, 0, 0, false,
+ chromeos::DISPLAY_POWER_ALL_ON, 0, false,
base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback,
base::Unretained(this)));
task.Run();
@@ -435,7 +408,7 @@ TEST_F(UpdateDisplayConfigurationTaskTest, NoopSoftwareMirrorConfiguration) {
{
UpdateDisplayConfigurationTask task(
&delegate_, &layout_manager_, MULTIPLE_DISPLAY_STATE_DUAL_MIRROR,
- chromeos::DISPLAY_POWER_ALL_ON, 0, 0, false,
+ chromeos::DISPLAY_POWER_ALL_ON, 0, false,
base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback,
base::Unretained(this)));
task.Run();
@@ -445,7 +418,7 @@ TEST_F(UpdateDisplayConfigurationTaskTest, NoopSoftwareMirrorConfiguration) {
EXPECT_EQ(MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED, display_state_);
EXPECT_TRUE(layout_manager_.GetSoftwareMirroringController()
->SoftwareMirroringEnabled());
- EXPECT_EQ(JoinActions(kGrab, kUngrab, nullptr), log_.GetActionsAndClear());
+ EXPECT_EQ(kNoActions, log_.GetActionsAndClear());
}
TEST_F(UpdateDisplayConfigurationTaskTest,
@@ -458,7 +431,7 @@ TEST_F(UpdateDisplayConfigurationTaskTest,
{
UpdateDisplayConfigurationTask task(
&delegate_, &layout_manager_, MULTIPLE_DISPLAY_STATE_DUAL_EXTENDED,
- chromeos::DISPLAY_POWER_ALL_ON, 0, 0, false,
+ chromeos::DISPLAY_POWER_ALL_ON, 0, false,
base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback,
base::Unretained(this)));
task.Run();
@@ -469,7 +442,7 @@ TEST_F(UpdateDisplayConfigurationTaskTest,
{
UpdateDisplayConfigurationTask task(
&delegate_, &layout_manager_, MULTIPLE_DISPLAY_STATE_DUAL_MIRROR,
- chromeos::DISPLAY_POWER_ALL_ON, 0, 0, true /* force_configure */,
+ chromeos::DISPLAY_POWER_ALL_ON, 0, true /* force_configure */,
base::Bind(&UpdateDisplayConfigurationTaskTest::ResponseCallback,
base::Unretained(this)));
task.Run();
@@ -481,16 +454,11 @@ TEST_F(UpdateDisplayConfigurationTaskTest,
->SoftwareMirroringEnabled());
EXPECT_EQ(
JoinActions(
- kGrab, GetFramebufferAction(gfx::Size(big_mode_.size().width(),
- small_mode_.size().height() +
- big_mode_.size().height()),
- displays_[0].get(), displays_[1].get())
- .c_str(),
GetCrtcAction(*displays_[0], &small_mode_, gfx::Point()).c_str(),
GetCrtcAction(*displays_[1], &big_mode_,
gfx::Point(0, small_mode_.size().height()))
.c_str(),
- kUngrab, nullptr),
+ nullptr),
log_.GetActionsAndClear());
}
diff --git a/chromium/ui/display/manager/chromeos/x11/DEPS b/chromium/ui/display/manager/chromeos/x11/DEPS
deleted file mode 100644
index 4c156b26039..00000000000
--- a/chromium/ui/display/manager/chromeos/x11/DEPS
+++ /dev/null
@@ -1,4 +0,0 @@
-include_rules = [
- "+ui/events/platform",
- "+ui/gfx/x",
-]
diff --git a/chromium/ui/display/manager/chromeos/x11/display_mode_x11.cc b/chromium/ui/display/manager/chromeos/x11/display_mode_x11.cc
deleted file mode 100644
index 5c6722042d4..00000000000
--- a/chromium/ui/display/manager/chromeos/x11/display_mode_x11.cc
+++ /dev/null
@@ -1,24 +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 "base/memory/ptr_util.h"
-
-#include "ui/display/manager/chromeos/x11/display_mode_x11.h"
-
-namespace display {
-
-DisplayModeX11::DisplayModeX11(const gfx::Size& size,
- bool interlaced,
- float refresh_rate,
- RRMode mode_id)
- : DisplayMode(size, interlaced, refresh_rate), mode_id_(mode_id) {}
-
-DisplayModeX11::~DisplayModeX11() {}
-
-std::unique_ptr<DisplayMode> DisplayModeX11::Clone() const {
- return base::WrapUnique(
- new DisplayModeX11(size(), is_interlaced(), refresh_rate(), mode_id()));
-}
-
-} // namespace display
diff --git a/chromium/ui/display/manager/chromeos/x11/display_mode_x11.h b/chromium/ui/display/manager/chromeos/x11/display_mode_x11.h
deleted file mode 100644
index 7c8b63002f1..00000000000
--- a/chromium/ui/display/manager/chromeos/x11/display_mode_x11.h
+++ /dev/null
@@ -1,37 +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_DISPLAY_MANAGER_CHROMEOS_X11_DISPLAY_MODE_X11_H_
-#define UI_DISPLAY_MANAGER_CHROMEOS_X11_DISPLAY_MODE_X11_H_
-
-#include "base/macros.h"
-#include "ui/display/manager/display_manager_export.h"
-#include "ui/display/types/display_mode.h"
-
-// Forward declare from Xlib and Xrandr.
-typedef unsigned long XID;
-typedef XID RRMode;
-
-namespace display {
-
-class DISPLAY_MANAGER_EXPORT DisplayModeX11 : public DisplayMode {
- public:
- DisplayModeX11(const gfx::Size& size,
- bool interlaced,
- float refresh_rate,
- RRMode mode_id);
- ~DisplayModeX11() override;
- std::unique_ptr<DisplayMode> Clone() const override;
-
- RRMode mode_id() const { return mode_id_; }
-
- private:
- RRMode mode_id_;
-
- DISALLOW_COPY_AND_ASSIGN(DisplayModeX11);
-};
-
-} // namespace display
-
-#endif // UI_DISPLAY_MANAGER_CHROMEOS_X11_DISPLAY_MODE_X11_H_
diff --git a/chromium/ui/display/manager/chromeos/x11/display_snapshot_x11.cc b/chromium/ui/display/manager/chromeos/x11/display_snapshot_x11.cc
deleted file mode 100644
index c58593c3bd7..00000000000
--- a/chromium/ui/display/manager/chromeos/x11/display_snapshot_x11.cc
+++ /dev/null
@@ -1,61 +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/display/manager/chromeos/x11/display_snapshot_x11.h"
-
-#include "base/strings/stringprintf.h"
-#include "ui/display/manager/chromeos/x11/display_mode_x11.h"
-
-namespace display {
-
-DisplaySnapshotX11::DisplaySnapshotX11(
- int64_t display_id,
- const gfx::Point& origin,
- const gfx::Size& physical_size,
- DisplayConnectionType type,
- bool is_aspect_preserving_scaling,
- bool has_overscan,
- std::string display_name,
- std::vector<std::unique_ptr<const DisplayMode>> modes,
- const std::vector<uint8_t>& edid,
- const DisplayMode* current_mode,
- const DisplayMode* native_mode,
- RROutput output,
- RRCrtc crtc,
- int index)
- : DisplaySnapshot(display_id,
- origin,
- physical_size,
- type,
- is_aspect_preserving_scaling,
- has_overscan,
- false,
- display_name,
- // TODO(jdufault): Figure out if we can get the file
- // descriptor that maps to the device.
- base::FilePath(),
- std::move(modes),
- edid,
- current_mode,
- native_mode),
- output_(output),
- crtc_(crtc),
- index_(index) {}
-
-DisplaySnapshotX11::~DisplaySnapshotX11() {}
-
-std::string DisplaySnapshotX11::ToString() const {
- return base::StringPrintf(
- "[type=%d, output=%ld, crtc=%ld, mode=%ld, dim=%dx%d]",
- type_,
- output_,
- crtc_,
- current_mode_
- ? static_cast<const DisplayModeX11*>(current_mode_)->mode_id()
- : 0,
- physical_size_.width(),
- physical_size_.height());
-}
-
-} // namespace display
diff --git a/chromium/ui/display/manager/chromeos/x11/display_snapshot_x11.h b/chromium/ui/display/manager/chromeos/x11/display_snapshot_x11.h
deleted file mode 100644
index 58d464405c7..00000000000
--- a/chromium/ui/display/manager/chromeos/x11/display_snapshot_x11.h
+++ /dev/null
@@ -1,62 +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_DISPLAY_MANAGER_CHROMEOS_X11_DISPLAY_SNAPSHOT_X11_H_
-#define UI_DISPLAY_MANAGER_CHROMEOS_X11_DISPLAY_SNAPSHOT_X11_H_
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "ui/display/manager/display_manager_export.h"
-#include "ui/display/types/display_snapshot.h"
-
-// Forward declare from Xlib and Xrandr.
-typedef unsigned long XID;
-typedef XID RROutput;
-typedef XID RRCrtc;
-
-namespace display {
-
-class DISPLAY_MANAGER_EXPORT DisplaySnapshotX11 : public DisplaySnapshot {
- public:
- DisplaySnapshotX11(int64_t display_id,
- const gfx::Point& origin,
- const gfx::Size& physical_size,
- DisplayConnectionType type,
- bool is_aspect_preserving_scaling,
- bool has_overscan,
- std::string display_name,
- std::vector<std::unique_ptr<const DisplayMode>> modes,
- const std::vector<uint8_t>& edid,
- const DisplayMode* current_mode,
- const DisplayMode* native_mode,
- RROutput output,
- RRCrtc crtc,
- int index);
- ~DisplaySnapshotX11() override;
-
- RROutput output() const { return output_; }
- RRCrtc crtc() const { return crtc_; }
- int index() const { return index_; }
-
- // DisplaySnapshot overrides:
- std::string ToString() const override;
-
- private:
- RROutput output_;
-
- // CRTC that should be used for this output. Not necessarily the CRTC
- // that XRandR reports is currently being used.
- RRCrtc crtc_;
-
- // This output's index in the array returned by XRandR. Stable even as
- // outputs are connected or disconnected.
- int index_;
-
- DISALLOW_COPY_AND_ASSIGN(DisplaySnapshotX11);
-};
-
-} // namespace display
-
-#endif // UI_DISPLAY_MANAGER_CHROMEOS_X11_DISPLAY_SNAPSHOT_X11_H_
diff --git a/chromium/ui/display/manager/chromeos/x11/display_util_x11.cc b/chromium/ui/display/manager/chromeos/x11/display_util_x11.cc
deleted file mode 100644
index b658d2038f2..00000000000
--- a/chromium/ui/display/manager/chromeos/x11/display_util_x11.cc
+++ /dev/null
@@ -1,43 +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/display/manager/chromeos/x11/display_util_x11.h"
-
-#include "base/macros.h"
-#include "base/strings/string_util.h"
-
-namespace display {
-
-namespace {
-
-struct DisplayConnectionTypeMapping {
- // Prefix of output name.
- const char* name;
- DisplayConnectionType type;
-};
-
-const DisplayConnectionTypeMapping kDisplayConnectionTypeMapping[] = {
- {"LVDS", DISPLAY_CONNECTION_TYPE_INTERNAL},
- {"eDP", DISPLAY_CONNECTION_TYPE_INTERNAL},
- {"DSI", DISPLAY_CONNECTION_TYPE_INTERNAL},
- {"VGA", DISPLAY_CONNECTION_TYPE_VGA},
- {"HDMI", DISPLAY_CONNECTION_TYPE_HDMI},
- {"DVI", DISPLAY_CONNECTION_TYPE_DVI},
- {"DP", DISPLAY_CONNECTION_TYPE_DISPLAYPORT}};
-
-} // namespace
-
-DisplayConnectionType GetDisplayConnectionTypeFromName(
- const std::string& name) {
- for (unsigned int i = 0; i < arraysize(kDisplayConnectionTypeMapping); ++i) {
- if (base::StartsWith(name, kDisplayConnectionTypeMapping[i].name,
- base::CompareCase::SENSITIVE)) {
- return kDisplayConnectionTypeMapping[i].type;
- }
- }
-
- return DISPLAY_CONNECTION_TYPE_UNKNOWN;
-}
-
-} // namespace display
diff --git a/chromium/ui/display/manager/chromeos/x11/display_util_x11.h b/chromium/ui/display/manager/chromeos/x11/display_util_x11.h
deleted file mode 100644
index 69327708f0a..00000000000
--- a/chromium/ui/display/manager/chromeos/x11/display_util_x11.h
+++ /dev/null
@@ -1,25 +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_DISPLAY_MANAGER_CHROMEOS_X11_DISPLAY_UTIL_X11_H_
-#define UI_DISPLAY_MANAGER_CHROMEOS_X11_DISPLAY_UTIL_X11_H_
-
-#include <string>
-
-#include "ui/display/manager/display_manager_export.h"
-#include "ui/display/types/display_constants.h"
-
-typedef unsigned long XID;
-typedef XID RROutput;
-
-namespace display {
-
-// Returns the DisplayConnectionType by matching known type prefixes to |name|.
-// Returns DISPLAY_TYPE_UNKNOWN if no valid match.
-DISPLAY_MANAGER_EXPORT DisplayConnectionType
-GetDisplayConnectionTypeFromName(const std::string& name);
-
-} // namespace display
-
-#endif // UI_DISPLAY_MANAGER_CHROMEOS_X11_DISPLAY_UTIL_X11_H_
diff --git a/chromium/ui/display/manager/chromeos/x11/display_util_x11_unittest.cc b/chromium/ui/display/manager/chromeos/x11/display_util_x11_unittest.cc
deleted file mode 100644
index c7ddd655fb0..00000000000
--- a/chromium/ui/display/manager/chromeos/x11/display_util_x11_unittest.cc
+++ /dev/null
@@ -1,68 +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/display/manager/chromeos/x11/display_util_x11.h"
-
-#include <memory>
-
-#include "testing/gtest/include/gtest/gtest.h"
-
-namespace display {
-
-TEST(DisplayUtilX11Test, GetDisplayConnectionTypeFromName) {
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_INTERNAL,
- GetDisplayConnectionTypeFromName("LVDS"));
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_INTERNAL,
- GetDisplayConnectionTypeFromName("eDP"));
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_INTERNAL,
- GetDisplayConnectionTypeFromName("DSI"));
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_INTERNAL,
- GetDisplayConnectionTypeFromName("LVDSxx"));
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_INTERNAL,
- GetDisplayConnectionTypeFromName("eDPzz"));
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_INTERNAL,
- GetDisplayConnectionTypeFromName("DSIyy"));
-
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_VGA,
- GetDisplayConnectionTypeFromName("VGA"));
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_VGA,
- GetDisplayConnectionTypeFromName("VGAxx"));
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_HDMI,
- GetDisplayConnectionTypeFromName("HDMI"));
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_HDMI,
- GetDisplayConnectionTypeFromName("HDMIyy"));
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_DVI,
- GetDisplayConnectionTypeFromName("DVI"));
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_DVI,
- GetDisplayConnectionTypeFromName("DVIzz"));
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_DISPLAYPORT,
- GetDisplayConnectionTypeFromName("DP"));
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_DISPLAYPORT,
- GetDisplayConnectionTypeFromName("DPww"));
-
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_UNKNOWN,
- GetDisplayConnectionTypeFromName("xyz"));
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_UNKNOWN,
- GetDisplayConnectionTypeFromName("abcLVDS"));
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_UNKNOWN,
- GetDisplayConnectionTypeFromName("cdeeDP"));
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_UNKNOWN,
- GetDisplayConnectionTypeFromName("abcDSI"));
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_UNKNOWN,
- GetDisplayConnectionTypeFromName("LVD"));
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_UNKNOWN,
- GetDisplayConnectionTypeFromName("eD"));
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_UNKNOWN,
- GetDisplayConnectionTypeFromName("DS"));
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_UNKNOWN,
- GetDisplayConnectionTypeFromName("VG"));
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_UNKNOWN,
- GetDisplayConnectionTypeFromName("HDM"));
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_UNKNOWN,
- GetDisplayConnectionTypeFromName("DV"));
- EXPECT_EQ(DISPLAY_CONNECTION_TYPE_UNKNOWN,
- GetDisplayConnectionTypeFromName("D"));
-}
-
-} // namespace display
diff --git a/chromium/ui/display/manager/chromeos/x11/native_display_delegate_x11.cc b/chromium/ui/display/manager/chromeos/x11/native_display_delegate_x11.cc
deleted file mode 100644
index df9af546fa4..00000000000
--- a/chromium/ui/display/manager/chromeos/x11/native_display_delegate_x11.cc
+++ /dev/null
@@ -1,656 +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/display/manager/chromeos/x11/native_display_delegate_x11.h"
-
-#include <X11/Xatom.h>
-#include <X11/Xlib.h>
-#include <X11/extensions/dpms.h>
-#include <X11/extensions/XInput2.h>
-#include <X11/extensions/Xrandr.h>
-
-#include <algorithm>
-#include <utility>
-
-#include "base/logging.h"
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "ui/display/manager/chromeos/x11/display_mode_x11.h"
-#include "ui/display/manager/chromeos/x11/display_snapshot_x11.h"
-#include "ui/display/manager/chromeos/x11/display_util_x11.h"
-#include "ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11.h"
-#include "ui/display/types/native_display_observer.h"
-#include "ui/display/util/x11/edid_parser_x11.h"
-#include "ui/events/platform/platform_event_source.h"
-#include "ui/gfx/geometry/rect.h"
-#include "ui/gfx/x/x11_atom_cache.h"
-#include "ui/gfx/x/x11_error_tracker.h"
-#include "ui/gfx/x/x11_types.h"
-
-namespace display {
-
-namespace {
-
-// DPI measurements.
-const float kMmInInch = 25.4;
-const float kDpi96 = 96.0;
-const float kPixelsToMmScale = kMmInInch / kDpi96;
-
-const char kContentProtectionAtomName[] = "Content Protection";
-const char kProtectionUndesiredAtomName[] = "Undesired";
-const char kProtectionDesiredAtomName[] = "Desired";
-const char kProtectionEnabledAtomName[] = "Enabled";
-
-RRMode GetOutputNativeMode(const XRROutputInfo* output_info) {
- return output_info->nmode > 0 ? output_info->modes[0] : None;
-}
-
-XRRCrtcGamma* ResampleGammaRamp(XRRCrtcGamma* gamma_ramp, int gamma_ramp_size) {
- if (gamma_ramp->size == gamma_ramp_size)
- return gamma_ramp;
-
-#define RESAMPLE(array, i, r) \
- array[i] + (array[i + 1] - array[i]) * r / gamma_ramp_size
-
- XRRCrtcGamma* resampled = XRRAllocGamma(gamma_ramp_size);
- for (int i = 0; i < gamma_ramp_size; ++i) {
- int base_index = gamma_ramp->size * i / gamma_ramp_size;
- int remaining = gamma_ramp->size * i % gamma_ramp_size;
- if (base_index < gamma_ramp->size - 1) {
- resampled->red[i] = RESAMPLE(gamma_ramp->red, base_index, remaining);
- resampled->green[i] = RESAMPLE(gamma_ramp->green, base_index, remaining);
- resampled->blue[i] = RESAMPLE(gamma_ramp->blue, base_index, remaining);
- } else {
- resampled->red[i] = gamma_ramp->red[gamma_ramp->size - 1];
- resampled->green[i] = gamma_ramp->green[gamma_ramp->size - 1];
- resampled->blue[i] = gamma_ramp->blue[gamma_ramp->size - 1];
- }
- }
-
-#undef RESAMPLE
- XRRFreeGamma(gamma_ramp);
- return resampled;
-}
-
-} // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeDisplayDelegateX11::HelperDelegateX11
-
-class NativeDisplayDelegateX11::HelperDelegateX11
- : public NativeDisplayDelegateX11::HelperDelegate {
- public:
- HelperDelegateX11(NativeDisplayDelegateX11* delegate) : delegate_(delegate) {}
- ~HelperDelegateX11() override {}
-
- // NativeDisplayDelegateX11::HelperDelegate overrides:
- void UpdateXRandRConfiguration(const base::NativeEvent& event) override {
- XRRUpdateConfiguration(event);
- }
- std::vector<DisplaySnapshot*> GetCachedDisplays() const override {
- return delegate_->GetCachedDisplays();
- }
- void NotifyDisplayObservers() override {
- for (NativeDisplayObserver& observer : delegate_->observers_)
- observer.OnConfigurationChanged();
- }
-
- private:
- NativeDisplayDelegateX11* delegate_;
-
- DISALLOW_COPY_AND_ASSIGN(HelperDelegateX11);
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeDisplayDelegateX11 implementation:
-
-NativeDisplayDelegateX11::NativeDisplayDelegateX11()
- : display_(gfx::GetXDisplay()),
- window_(DefaultRootWindow(display_)),
- background_color_argb_(0) {}
-
-NativeDisplayDelegateX11::~NativeDisplayDelegateX11() {
- if (ui::PlatformEventSource::GetInstance() &&
- platform_event_dispatcher_.get()) {
- ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(
- platform_event_dispatcher_.get());
- }
-}
-
-void NativeDisplayDelegateX11::Initialize() {
- int error_base_ignored = 0;
- int xrandr_event_base = 0;
- XRRQueryExtension(display_, &xrandr_event_base, &error_base_ignored);
-
- helper_delegate_.reset(new HelperDelegateX11(this));
- platform_event_dispatcher_.reset(new NativeDisplayEventDispatcherX11(
- helper_delegate_.get(), xrandr_event_base));
-
- if (ui::PlatformEventSource::GetInstance()) {
- ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(
- platform_event_dispatcher_.get());
- }
-}
-
-void NativeDisplayDelegateX11::GrabServer() {
- CHECK(!screen_) << "Server already grabbed";
- XGrabServer(display_);
- screen_.reset(XRRGetScreenResources(display_, window_));
- CHECK(screen_);
-}
-
-void NativeDisplayDelegateX11::UngrabServer() {
- CHECK(screen_) << "Server not grabbed";
- screen_.reset();
- XUngrabServer(display_);
- // crbug.com/366125
- XFlush(display_);
-}
-
-void NativeDisplayDelegateX11::TakeDisplayControl(
- const DisplayControlCallback& callback) {
- NOTIMPLEMENTED();
-}
-
-void NativeDisplayDelegateX11::RelinquishDisplayControl(
- const DisplayControlCallback& callback) {
- NOTIMPLEMENTED();
-}
-
-void NativeDisplayDelegateX11::SyncWithServer() {
- XSync(display_, 0);
-}
-
-void NativeDisplayDelegateX11::SetBackgroundColor(uint32_t color_argb) {
- background_color_argb_ = color_argb;
-}
-
-void NativeDisplayDelegateX11::ForceDPMSOn() {
- CHECK(DPMSEnable(display_));
- CHECK(DPMSForceLevel(display_, DPMSModeOn));
-}
-
-void NativeDisplayDelegateX11::GetDisplays(
- const GetDisplaysCallback& callback) {
- CHECK(screen_) << "Server not grabbed";
-
- cached_outputs_.clear();
- std::set<RRCrtc> last_used_crtcs;
-
- InitModes();
- for (int i = 0; i < screen_->noutput; ++i) {
- RROutput output_id = screen_->outputs[i];
- XRROutputInfo* output_info =
- XRRGetOutputInfo(display_, screen_.get(), output_id);
- if (output_info->connection == RR_Connected) {
- cached_outputs_.push_back(
- InitDisplaySnapshot(output_id, output_info, &last_used_crtcs, i));
- }
- XRRFreeOutputInfo(output_info);
- }
-
- callback.Run(GetCachedDisplays());
-}
-
-void NativeDisplayDelegateX11::AddMode(const DisplaySnapshot& output,
- const DisplayMode* mode) {
- CHECK(screen_) << "Server not grabbed";
- CHECK(mode) << "Must add valid mode";
-
- const DisplaySnapshotX11& x11_output =
- static_cast<const DisplaySnapshotX11&>(output);
- RRMode mode_id = static_cast<const DisplayModeX11*>(mode)->mode_id();
-
- VLOG(1) << "AddDisplayMode: output=" << x11_output.output()
- << " mode=" << mode_id;
- XRRAddOutputMode(display_, x11_output.output(), mode_id);
-}
-
-void NativeDisplayDelegateX11::Configure(const DisplaySnapshot& output,
- const DisplayMode* mode,
- const gfx::Point& origin,
- const ConfigureCallback& callback) {
- const DisplaySnapshotX11& x11_output =
- static_cast<const DisplaySnapshotX11&>(output);
- RRMode mode_id = None;
- if (mode)
- mode_id = static_cast<const DisplayModeX11*>(mode)->mode_id();
-
- callback.Run(ConfigureCrtc(x11_output.crtc(), mode_id, x11_output.output(),
- origin.x(), origin.y()));
-}
-
-bool NativeDisplayDelegateX11::ConfigureCrtc(RRCrtc crtc,
- RRMode mode,
- RROutput output,
- int x,
- int y) {
- CHECK(screen_) << "Server not grabbed";
- VLOG(1) << "ConfigureCrtc: crtc=" << crtc << " mode=" << mode
- << " output=" << output << " x=" << x << " y=" << y;
- // Xrandr.h is full of lies. XRRSetCrtcConfig() is defined as returning a
- // Status, which is typically 0 for failure and 1 for success. In
- // actuality it returns a RRCONFIGSTATUS, which uses 0 for success.
- if (XRRSetCrtcConfig(display_, screen_.get(), crtc, CurrentTime, x, y, mode,
- RR_Rotate_0, (output && mode) ? &output : NULL,
- (output && mode) ? 1 : 0) != RRSetConfigSuccess) {
- LOG(WARNING) << "Unable to configure CRTC " << crtc << ":"
- << " mode=" << mode << " output=" << output << " x=" << x
- << " y=" << y;
- return false;
- }
-
- return true;
-}
-
-void NativeDisplayDelegateX11::CreateFrameBuffer(const gfx::Size& size) {
- CHECK(screen_) << "Server not grabbed";
- gfx::Size current_screen_size(
- DisplayWidth(display_, DefaultScreen(display_)),
- DisplayHeight(display_, DefaultScreen(display_)));
-
- VLOG(1) << "CreateFrameBuffer: new=" << size.ToString()
- << " current=" << current_screen_size.ToString();
-
- DestroyUnusedCrtcs();
-
- if (size == current_screen_size)
- return;
-
- gfx::Size min_screen_size(current_screen_size);
- min_screen_size.SetToMin(size);
- UpdateCrtcsForNewFramebuffer(min_screen_size);
-
- int mm_width = size.width() * kPixelsToMmScale;
- int mm_height = size.height() * kPixelsToMmScale;
- XRRSetScreenSize(
- display_, window_, size.width(), size.height(), mm_width, mm_height);
- // We don't wait for root window resize, therefore this end up with drawing
- // in the old window size, which we care during the boot.
- DrawBackground();
-
- // Don't redraw the background upon framebuffer change again. This should
- // happen only once after boot.
- background_color_argb_ = 0;
-}
-
-void NativeDisplayDelegateX11::AddObserver(NativeDisplayObserver* observer) {
- observers_.AddObserver(observer);
-}
-
-void NativeDisplayDelegateX11::RemoveObserver(NativeDisplayObserver* observer) {
- observers_.RemoveObserver(observer);
-}
-
-FakeDisplayController* NativeDisplayDelegateX11::GetFakeDisplayController() {
- return nullptr;
-}
-
-std::vector<DisplaySnapshot*> NativeDisplayDelegateX11::GetCachedDisplays()
- const {
- std::vector<DisplaySnapshot*> snapshots(cached_outputs_.size());
- std::transform(
- cached_outputs_.cbegin(), cached_outputs_.cend(), snapshots.begin(),
- [](const std::unique_ptr<DisplaySnapshot>& item) { return item.get(); });
- return snapshots;
-}
-
-void NativeDisplayDelegateX11::InitModes() {
- CHECK(screen_) << "Server not grabbed";
-
- modes_.clear();
-
- for (int i = 0; i < screen_->nmode; ++i) {
- const XRRModeInfo& info = screen_->modes[i];
- float refresh_rate = 0.0f;
- if (info.hTotal && info.vTotal) {
- refresh_rate =
- static_cast<float>(info.dotClock) /
- (static_cast<float>(info.hTotal) * static_cast<float>(info.vTotal));
- }
-
- modes_.insert(std::make_pair(
- info.id, base::MakeUnique<DisplayModeX11>(
- gfx::Size(info.width, info.height),
- info.modeFlags & RR_Interlace, refresh_rate, info.id)));
- }
-}
-
-std::unique_ptr<DisplaySnapshotX11>
-NativeDisplayDelegateX11::InitDisplaySnapshot(RROutput output,
- XRROutputInfo* info,
- std::set<RRCrtc>* last_used_crtcs,
- int index) {
- int64_t display_id = 0;
- EDIDParserX11 edid_parser(output);
- if (!edid_parser.GetDisplayId(static_cast<uint8_t>(index), &display_id))
- display_id = index;
-
- bool has_overscan = false;
- edid_parser.GetOutputOverscanFlag(&has_overscan);
-
- DisplayConnectionType type = GetDisplayConnectionTypeFromName(info->name);
- if (type == DISPLAY_CONNECTION_TYPE_UNKNOWN)
- LOG(ERROR) << "Unknown link type: " << info->name;
-
- RRMode native_mode_id = GetOutputNativeMode(info);
- RRMode current_mode_id = None;
- gfx::Point origin;
- if (info->crtc) {
- XRRCrtcInfo* crtc_info =
- XRRGetCrtcInfo(display_, screen_.get(), info->crtc);
- current_mode_id = crtc_info->mode;
- origin.SetPoint(crtc_info->x, crtc_info->y);
- XRRFreeCrtcInfo(crtc_info);
- }
-
- RRCrtc crtc = None;
- // Assign a CRTC that isn't already in use.
- for (int i = 0; i < info->ncrtc; ++i) {
- if (last_used_crtcs->find(info->crtcs[i]) == last_used_crtcs->end()) {
- crtc = info->crtcs[i];
- last_used_crtcs->insert(crtc);
- break;
- }
- }
-
- const DisplayMode* current_mode = NULL;
- const DisplayMode* native_mode = NULL;
- std::vector<std::unique_ptr<const DisplayMode>> display_modes;
-
- for (int i = 0; i < info->nmode; ++i) {
- const RRMode mode = info->modes[i];
- if (modes_.find(mode) != modes_.end()) {
- display_modes.push_back(modes_.at(mode)->Clone());
-
- if (mode == current_mode_id)
- current_mode = display_modes.back().get();
- if (mode == native_mode_id)
- native_mode = display_modes.back().get();
- } else {
- LOG(WARNING) << "Unable to find XRRModeInfo for mode " << mode;
- }
- }
-
- auto display_snapshot = base::MakeUnique<DisplaySnapshotX11>(
- display_id, origin, gfx::Size(info->mm_width, info->mm_height), type,
- IsOutputAspectPreservingScaling(output), has_overscan,
- edid_parser.GetDisplayName(), std::move(display_modes),
- edid_parser.edid(), current_mode, native_mode, output, crtc, index);
-
- VLOG(1) << "Found display " << cached_outputs_.size() << ":"
- << " output=" << output << " crtc=" << crtc
- << " current_mode=" << current_mode_id;
-
- return display_snapshot;
-}
-
-void NativeDisplayDelegateX11::GetHDCPState(
- const DisplaySnapshot& output,
- const GetHDCPStateCallback& callback) {
- HDCPState state = HDCP_STATE_UNDESIRED;
- bool success = GetHDCPState(output, &state);
- callback.Run(success, state);
-}
-
-bool NativeDisplayDelegateX11::GetHDCPState(const DisplaySnapshot& output,
- HDCPState* state) {
- unsigned char* values = NULL;
- int actual_format = 0;
- unsigned long nitems = 0;
- unsigned long bytes_after = 0;
- Atom actual_type = None;
- int success = 0;
- RROutput output_id = static_cast<const DisplaySnapshotX11&>(output).output();
- Atom prop = gfx::GetAtom(kContentProtectionAtomName);
-
- // TODO(kcwu): Move this to x11_util (similar method calls in this file and
- // output_util.cc)
- success = XRRGetOutputProperty(display_,
- output_id,
- prop,
- 0,
- 100,
- False,
- False,
- AnyPropertyType,
- &actual_type,
- &actual_format,
- &nitems,
- &bytes_after,
- &values);
- gfx::XScopedPtr<unsigned char> scoped_values(values);
- if (actual_type == None) {
- LOG(ERROR) << "Property '" << kContentProtectionAtomName
- << "' does not exist";
- return false;
- }
-
- if (success == Success && actual_type == XA_ATOM && actual_format == 32 &&
- nitems == 1) {
- Atom value = reinterpret_cast<Atom*>(values)[0];
- if (value == gfx::GetAtom(kProtectionUndesiredAtomName)) {
- *state = HDCP_STATE_UNDESIRED;
- } else if (value == gfx::GetAtom(kProtectionDesiredAtomName)) {
- *state = HDCP_STATE_DESIRED;
- } else if (value == gfx::GetAtom(kProtectionEnabledAtomName)) {
- *state = HDCP_STATE_ENABLED;
- } else {
- LOG(ERROR) << "Unknown " << kContentProtectionAtomName
- << " value: " << value;
- return false;
- }
- } else {
- LOG(ERROR) << "XRRGetOutputProperty failed";
- return false;
- }
-
- VLOG(3) << "HDCP state: success," << *state;
- return true;
-}
-
-void NativeDisplayDelegateX11::SetHDCPState(
- const DisplaySnapshot& output,
- HDCPState state,
- const SetHDCPStateCallback& callback) {
- callback.Run(SetHDCPState(output, state));
-}
-
-bool NativeDisplayDelegateX11::SetHDCPState(const DisplaySnapshot& output,
- HDCPState state) {
- Atom name = gfx::GetAtom(kContentProtectionAtomName);
- Atom value = None;
- switch (state) {
- case HDCP_STATE_UNDESIRED:
- value = gfx::GetAtom(kProtectionUndesiredAtomName);
- break;
- case HDCP_STATE_DESIRED:
- value = gfx::GetAtom(kProtectionDesiredAtomName);
- break;
- default:
- NOTREACHED() << "Invalid HDCP state: " << state;
- return false;
- }
- gfx::X11ErrorTracker err_tracker;
- unsigned char* data = reinterpret_cast<unsigned char*>(&value);
- RROutput output_id = static_cast<const DisplaySnapshotX11&>(output).output();
- XRRChangeOutputProperty(
- display_, output_id, name, XA_ATOM, 32, PropModeReplace, data, 1);
- if (err_tracker.FoundNewError()) {
- LOG(ERROR) << "XRRChangeOutputProperty failed";
- return false;
- } else {
- return true;
- }
-}
-
-void NativeDisplayDelegateX11::DestroyUnusedCrtcs() {
- CHECK(screen_) << "Server not grabbed";
-
- for (int i = 0; i < screen_->ncrtc; ++i) {
- bool in_use = false;
- for (const auto& snapshot : cached_outputs_) {
- DisplaySnapshotX11* x11_output =
- static_cast<DisplaySnapshotX11*>(snapshot.get());
- if (screen_->crtcs[i] == x11_output->crtc()) {
- in_use = true;
- break;
- }
- }
-
- if (!in_use)
- ConfigureCrtc(screen_->crtcs[i], None, None, 0, 0);
- }
-}
-
-void NativeDisplayDelegateX11::UpdateCrtcsForNewFramebuffer(
- const gfx::Size& min_screen_size) {
- CHECK(screen_) << "Server not grabbed";
- // Setting the screen size will fail if any CRTC doesn't fit afterwards.
- // At the same time, turning CRTCs off and back on uses up a lot of time.
- // This function tries to be smart to avoid too many off/on cycles:
- // - We set the new modes on CRTCs, if they fit in both the old and new
- // FBs, and park them at (0,0)
- // - We disable the CRTCs we will need but don't fit in the old FB. Those
- // will be reenabled after the resize.
- // We don't worry about the cached state of the outputs here since we are
- // not interested in the state we are setting - we just try to get the CRTCs
- // out of the way so we can rebuild the frame buffer.
- gfx::Rect fb_rect(min_screen_size);
- for (const auto& snapshot : cached_outputs_) {
- DisplaySnapshotX11* x11_output =
- static_cast<DisplaySnapshotX11*>(snapshot.get());
- const DisplayMode* mode_info = x11_output->current_mode();
- RROutput output = x11_output->output();
- RRMode mode = None;
-
- if (mode_info) {
- mode = static_cast<const DisplayModeX11*>(mode_info)->mode_id();
-
- if (!fb_rect.Contains(gfx::Rect(mode_info->size()))) {
- // In case our CRTC doesn't fit in common area of our current and about
- // to be resized framebuffer, disable it.
- // It'll get reenabled after we resize the framebuffer.
- mode = None;
- output = None;
- mode_info = NULL;
- }
- }
-
- ConfigureCrtc(x11_output->crtc(), mode, output, 0, 0);
- }
-}
-
-bool NativeDisplayDelegateX11::IsOutputAspectPreservingScaling(RROutput id) {
- Atom scaling_prop = gfx::GetAtom("scaling mode");
- Atom full_aspect_atom = gfx::GetAtom("Full aspect");
- if (scaling_prop == None || full_aspect_atom == None)
- return false;
-
- int nprop = 0;
- gfx::XScopedPtr<Atom[]> props(XRRListOutputProperties(display_, id, &nprop));
- for (int j = 0; j < nprop; j++) {
- Atom prop = props[j];
- if (scaling_prop == prop) {
- unsigned char* values = NULL;
- int actual_format;
- unsigned long nitems;
- unsigned long bytes_after;
- Atom actual_type;
- int success;
-
- success = XRRGetOutputProperty(display_,
- id,
- prop,
- 0,
- 100,
- False,
- False,
- AnyPropertyType,
- &actual_type,
- &actual_format,
- &nitems,
- &bytes_after,
- &values);
- gfx::XScopedPtr<unsigned char> scoped_value(values);
- if (success == Success && actual_type == XA_ATOM && actual_format == 32 &&
- nitems == 1) {
- Atom value = reinterpret_cast<Atom*>(values)[0];
- if (full_aspect_atom == value)
- return true;
- }
- }
- }
- return false;
-}
-
-std::vector<ColorCalibrationProfile>
-NativeDisplayDelegateX11::GetAvailableColorCalibrationProfiles(
- const DisplaySnapshot& output) {
- // TODO(mukai|marcheu): Checks the system data and fills the result.
- // Note that the order would be Dynamic -> Standard -> Movie -> Reading.
- return std::vector<ColorCalibrationProfile>();
-}
-
-bool NativeDisplayDelegateX11::SetColorCalibrationProfile(
- const DisplaySnapshot& output,
- ColorCalibrationProfile new_profile) {
- const DisplaySnapshotX11& x11_output =
- static_cast<const DisplaySnapshotX11&>(output);
-
- XRRCrtcGamma* gamma_ramp = CreateGammaRampForProfile(x11_output, new_profile);
-
- if (!gamma_ramp)
- return false;
-
- int gamma_ramp_size = XRRGetCrtcGammaSize(display_, x11_output.crtc());
- XRRSetCrtcGamma(display_, x11_output.crtc(),
- ResampleGammaRamp(gamma_ramp, gamma_ramp_size));
- XRRFreeGamma(gamma_ramp);
- return true;
-}
-
-XRRCrtcGamma* NativeDisplayDelegateX11::CreateGammaRampForProfile(
- const DisplaySnapshotX11& x11_output,
- ColorCalibrationProfile new_profile) {
- // TODO(mukai|marcheu): Creates the appropriate gamma ramp data from the
- // profile enum. It would be served by the vendor.
- return NULL;
-}
-
-bool NativeDisplayDelegateX11::SetColorCorrection(
- const DisplaySnapshot& output,
- const std::vector<GammaRampRGBEntry>& degamma_lut,
- const std::vector<GammaRampRGBEntry>& gamma_lut,
- const std::vector<float>& correction_matrix) {
- NOTIMPLEMENTED();
- return false;
-}
-
-void NativeDisplayDelegateX11::DrawBackground() {
- if (!background_color_argb_)
- return;
- // Configuring CRTCs/Framebuffer clears the boot screen image. Paint the
- // same background color after updating framebuffer to minimize the
- // duration of black screen at boot time.
- XColor color;
- Colormap colormap = DefaultColormap(display_, 0);
- // XColor uses 16 bits per color.
- color.red = (background_color_argb_ & 0x00FF0000) >> 8;
- color.green = (background_color_argb_ & 0x0000FF00);
- color.blue = (background_color_argb_ & 0x000000FF) << 8;
- color.flags = DoRed | DoGreen | DoBlue;
- XAllocColor(display_, colormap, &color);
-
- GC gc = XCreateGC(display_, window_, 0, 0);
- XSetForeground(display_, gc, color.pixel);
- XSetFillStyle(display_, gc, FillSolid);
- int width = DisplayWidth(display_, DefaultScreen(display_));
- int height = DisplayHeight(display_, DefaultScreen(display_));
- XFillRectangle(display_, window_, gc, 0, 0, width, height);
- XFreeGC(display_, gc);
- XFreeColors(display_, colormap, &color.pixel, 1, 0);
-}
-
-} // namespace display
diff --git a/chromium/ui/display/manager/chromeos/x11/native_display_delegate_x11.h b/chromium/ui/display/manager/chromeos/x11/native_display_delegate_x11.h
deleted file mode 100644
index 3b326fcb243..00000000000
--- a/chromium/ui/display/manager/chromeos/x11/native_display_delegate_x11.h
+++ /dev/null
@@ -1,182 +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_DISPLAY_MANAGER_CHROMEOS_X11_NATIVE_DISPLAY_DELEGATE_X11_H_
-#define UI_DISPLAY_MANAGER_CHROMEOS_X11_NATIVE_DISPLAY_DELEGATE_X11_H_
-
-#include <stdint.h>
-
-#include <map>
-#include <memory>
-#include <set>
-#include <vector>
-
-#include "base/compiler_specific.h"
-#include "base/event_types.h"
-#include "base/macros.h"
-#include "base/observer_list.h"
-#include "ui/display/manager/display_manager_export.h"
-#include "ui/display/types/native_display_delegate.h"
-#include "ui/gfx/geometry/point.h"
-#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/x/x11_types.h"
-
-// Forward declarations for Xlib and Xrandr.
-// This is so unused X definitions don't pollute the namespace.
-typedef XID RROutput;
-typedef XID RRCrtc;
-typedef XID RRMode;
-typedef XID _Window;
-
-struct _XRROutputInfo;
-typedef _XRROutputInfo XRROutputInfo;
-struct _XRRScreenResources;
-typedef _XRRScreenResources XRRScreenResources;
-struct _XRRCrtcGamma;
-typedef _XRRCrtcGamma XRRCrtcGamma;
-
-extern "C" {
-void XRRFreeScreenResources(XRRScreenResources* resources);
-}
-
-namespace display {
-
-class DisplayModeX11;
-class DisplaySnapshotX11;
-class NativeDisplayEventDispatcherX11;
-
-class DISPLAY_MANAGER_EXPORT NativeDisplayDelegateX11
- : public NativeDisplayDelegate {
- public:
- // Helper class that allows NativeDisplayEventDispatcherX11 and
- // NativeDisplayDelegateX11::PlatformEventObserverX11 to interact with this
- // class or with mocks in tests.
- class HelperDelegate {
- public:
- virtual ~HelperDelegate() {}
-
- // Tells XRandR to update its configuration in response to |event|, an
- // RRScreenChangeNotify event.
- virtual void UpdateXRandRConfiguration(const base::NativeEvent& event) = 0;
-
- // Returns the list of current outputs. This is used to discard duplicate
- // events.
- virtual std::vector<DisplaySnapshot*> GetCachedDisplays() const = 0;
-
- // Notify |observers_| that a change in configuration has occurred.
- virtual void NotifyDisplayObservers() = 0;
- };
-
- NativeDisplayDelegateX11();
- ~NativeDisplayDelegateX11() override;
-
- // NativeDisplayDelegate overrides:
- void Initialize() override;
- void GrabServer() override;
- void UngrabServer() override;
- void TakeDisplayControl(const DisplayControlCallback& callback) override;
- void RelinquishDisplayControl(
- const DisplayControlCallback& callback) override;
- void SyncWithServer() override;
- void SetBackgroundColor(uint32_t color_argb) override;
- void ForceDPMSOn() override;
- void GetDisplays(const GetDisplaysCallback& callback) override;
- void AddMode(const DisplaySnapshot& output, const DisplayMode* mode) override;
- void Configure(const DisplaySnapshot& output,
- const DisplayMode* mode,
- const gfx::Point& origin,
- const ConfigureCallback& callback) override;
- void CreateFrameBuffer(const gfx::Size& size) override;
- void GetHDCPState(const DisplaySnapshot& output,
- const GetHDCPStateCallback& callback) override;
- void SetHDCPState(const DisplaySnapshot& output,
- HDCPState state,
- const SetHDCPStateCallback& callback) override;
- std::vector<ColorCalibrationProfile> GetAvailableColorCalibrationProfiles(
- const DisplaySnapshot& output) override;
- bool SetColorCalibrationProfile(const DisplaySnapshot& output,
- ColorCalibrationProfile new_profile) override;
- bool SetColorCorrection(const DisplaySnapshot& output,
- const std::vector<GammaRampRGBEntry>& degamma_lut,
- const std::vector<GammaRampRGBEntry>& gamma_lut,
- const std::vector<float>& correction_matrix) override;
- void AddObserver(NativeDisplayObserver* observer) override;
- void RemoveObserver(NativeDisplayObserver* observer) override;
- FakeDisplayController* GetFakeDisplayController() override;
-
- std::vector<DisplaySnapshot*> GetCachedDisplays() const;
-
- private:
- class HelperDelegateX11;
-
- // Parses all the modes made available by |screen_|.
- void InitModes();
-
- // Helper method for GetOutputs() that returns an OutputSnapshot struct based
- // on the passed-in information.
- std::unique_ptr<DisplaySnapshotX11> InitDisplaySnapshot(
- RROutput id,
- XRROutputInfo* info,
- std::set<RRCrtc>* last_used_crtcs,
- int index);
-
- // Destroys unused CRTCs.
- void DestroyUnusedCrtcs();
-
- // Parks used CRTCs in a way which allows a framebuffer resize. This is faster
- // than turning them off, resizing, then turning them back on.
- // |min_screen_size| represent the smallest size between the current
- // framebuffer size and the requested framebuffer size.
- void UpdateCrtcsForNewFramebuffer(const gfx::Size& min_screen_size);
-
- bool ConfigureCrtc(RRCrtc crtc, RRMode mode, RROutput output, int x, int y);
-
- // Helper functions that perform the actual HDCP requests.
- bool GetHDCPState(const DisplaySnapshot& output, HDCPState* state);
- bool SetHDCPState(const DisplaySnapshot& output, HDCPState state);
-
- // Returns whether |id| is configured to preserve aspect when scaling.
- bool IsOutputAspectPreservingScaling(RROutput id);
-
- // Creates the gamma ramp for |new_profile|, or NULL if it doesn't exist.
- // The caller should take the ownership.
- XRRCrtcGamma* CreateGammaRampForProfile(const DisplaySnapshotX11& x11_output,
- ColorCalibrationProfile new_profile);
-
- void DrawBackground();
-
- XDisplay* display_;
- _Window window_;
-
- // Initialized when the server is grabbed and freed when it's ungrabbed.
- gfx::XScopedPtr<
- XRRScreenResources,
- gfx::XObjectDeleter<XRRScreenResources, void, XRRFreeScreenResources>>
- screen_;
-
- std::map<RRMode, std::unique_ptr<DisplayModeX11>> modes_;
-
- // Every time GetOutputs() is called we cache the updated list of outputs in
- // |cached_outputs_| so that we can check for duplicate events rather than
- // propagate them.
- std::vector<std::unique_ptr<DisplaySnapshot>> cached_outputs_;
-
- std::unique_ptr<HelperDelegate> helper_delegate_;
-
- // Processes X11 display events associated with the root window and notifies
- // |observers_| when a display change has occurred.
- std::unique_ptr<NativeDisplayEventDispatcherX11> platform_event_dispatcher_;
-
- // List of observers waiting for display configuration change events.
- base::ObserverList<NativeDisplayObserver> observers_;
-
- // A background color used during boot time + multi displays.
- uint32_t background_color_argb_;
-
- DISALLOW_COPY_AND_ASSIGN(NativeDisplayDelegateX11);
-};
-
-} // namespace display
-
-#endif // UI_DISPLAY_MANAGER_CHROMEOS_X11_NATIVE_DISPLAY_DELEGATE_X11_H_
diff --git a/chromium/ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11.cc b/chromium/ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11.cc
deleted file mode 100644
index a54a1cbbc46..00000000000
--- a/chromium/ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11.cc
+++ /dev/null
@@ -1,117 +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/display/manager/chromeos/x11/native_display_event_dispatcher_x11.h"
-
-#include <X11/extensions/Xrandr.h>
-#include <utility>
-
-#include "base/time/default_tick_clock.h"
-#include "ui/display/manager/chromeos/x11/display_mode_x11.h"
-#include "ui/display/manager/chromeos/x11/display_snapshot_x11.h"
-#include "ui/events/platform/platform_event_source.h"
-
-namespace display {
-
-// static
-const int NativeDisplayEventDispatcherX11::kUseCacheAfterStartupMs = 7000;
-
-NativeDisplayEventDispatcherX11::NativeDisplayEventDispatcherX11(
- NativeDisplayDelegateX11::HelperDelegate* delegate,
- int xrandr_event_base)
- : delegate_(delegate),
- xrandr_event_base_(xrandr_event_base),
- tick_clock_(new base::DefaultTickClock) {
- startup_time_ = tick_clock_->NowTicks();
-}
-
-NativeDisplayEventDispatcherX11::~NativeDisplayEventDispatcherX11() {}
-
-bool NativeDisplayEventDispatcherX11::CanDispatchEvent(
- const ui::PlatformEvent& event) {
- return (event->type - xrandr_event_base_ == RRScreenChangeNotify) ||
- (event->type - xrandr_event_base_ == RRNotify);
-}
-
-uint32_t NativeDisplayEventDispatcherX11::DispatchEvent(
- const ui::PlatformEvent& event) {
- if (event->type - xrandr_event_base_ == RRScreenChangeNotify) {
- VLOG(1) << "Received RRScreenChangeNotify event";
- delegate_->UpdateXRandRConfiguration(event);
- return ui::POST_DISPATCH_PERFORM_DEFAULT;
- }
-
- // Bail out early for everything except RRNotify_OutputChange events
- // about an output getting connected or disconnected.
- if (event->type - xrandr_event_base_ != RRNotify)
- return ui::POST_DISPATCH_PERFORM_DEFAULT;
- const XRRNotifyEvent* notify_event = reinterpret_cast<XRRNotifyEvent*>(event);
- if (notify_event->subtype != RRNotify_OutputChange)
- return ui::POST_DISPATCH_PERFORM_DEFAULT;
- const XRROutputChangeNotifyEvent* output_change_event =
- reinterpret_cast<XRROutputChangeNotifyEvent*>(event);
- const int action = output_change_event->connection;
- if (action != RR_Connected && action != RR_Disconnected)
- return ui::POST_DISPATCH_PERFORM_DEFAULT;
-
- const bool connected = (action == RR_Connected);
- VLOG(1) << "Received RRNotify_OutputChange event:"
- << " output=" << output_change_event->output
- << " crtc=" << output_change_event->crtc
- << " mode=" << output_change_event->mode
- << " action=" << (connected ? "connected" : "disconnected");
-
- bool check_cache = (tick_clock_->NowTicks() - startup_time_)
- .InMilliseconds() <= kUseCacheAfterStartupMs;
-
- if (check_cache) {
- bool found_changed_output = false;
- std::vector<DisplaySnapshot*> cached_outputs =
- delegate_->GetCachedDisplays();
- for (std::vector<DisplaySnapshot*>::const_iterator it =
- cached_outputs.begin();
- it != cached_outputs.end();
- ++it) {
- const DisplaySnapshotX11* x11_output =
- static_cast<const DisplaySnapshotX11*>(*it);
- const DisplayModeX11* x11_mode =
- static_cast<const DisplayModeX11*>(x11_output->current_mode());
- RRMode mode_id = x11_mode ? x11_mode->mode_id() : None;
-
- // Update if we failed to fetch the external display's ID before.
- // Internal display's EDID should always be available.
- bool display_id_needs_update =
- x11_output->type() != DISPLAY_CONNECTION_TYPE_INTERNAL &&
- !x11_output->display_id();
-
- if (x11_output->output() == output_change_event->output) {
- if (connected && x11_output->crtc() == output_change_event->crtc &&
- mode_id == output_change_event->mode &&
- !display_id_needs_update) {
- VLOG(1) << "Ignoring event describing already-cached state";
- return ui::POST_DISPATCH_PERFORM_DEFAULT;
- }
- found_changed_output = true;
- break;
- }
- }
-
- if (!connected && !found_changed_output) {
- VLOG(1) << "Ignoring event describing already-disconnected output";
- return ui::POST_DISPATCH_PERFORM_DEFAULT;
- }
- }
-
- delegate_->NotifyDisplayObservers();
-
- return ui::POST_DISPATCH_PERFORM_DEFAULT;
-}
-
-void NativeDisplayEventDispatcherX11::SetTickClockForTest(
- std::unique_ptr<base::TickClock> tick_clock) {
- tick_clock_ = std::move(tick_clock);
- startup_time_ = tick_clock_->NowTicks();
-}
-
-} // namespace display
diff --git a/chromium/ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11.h b/chromium/ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11.h
deleted file mode 100644
index a25bfea1286..00000000000
--- a/chromium/ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11.h
+++ /dev/null
@@ -1,55 +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_DISPLAY_MANAGER_CHROMEOS_X11_NATIVE_DISPLAY_EVENT_DISPATCHER_X11_H_
-#define UI_DISPLAY_MANAGER_CHROMEOS_X11_NATIVE_DISPLAY_EVENT_DISPATCHER_X11_H_
-
-#include <stdint.h>
-
-#include "base/macros.h"
-#include "base/time/tick_clock.h"
-#include "base/time/time.h"
-#include "ui/display/manager/chromeos/x11/native_display_delegate_x11.h"
-#include "ui/events/platform/platform_event_dispatcher.h"
-
-namespace display {
-
-// The implementation is interested in the cases of RRNotify events which
-// correspond to output add/remove events. Note that Output add/remove events
-// are sent in response to our own reconfiguration operations so spurious events
-// are common. Spurious events will have no effect.
-class DISPLAY_MANAGER_EXPORT NativeDisplayEventDispatcherX11
- : public ui::PlatformEventDispatcher {
- public:
- NativeDisplayEventDispatcherX11(
- NativeDisplayDelegateX11::HelperDelegate* delegate,
- int xrandr_event_base);
- ~NativeDisplayEventDispatcherX11() override;
-
- // ui::PlatformEventDispatcher:
- bool CanDispatchEvent(const ui::PlatformEvent& event) override;
- uint32_t DispatchEvent(const ui::PlatformEvent& event) override;
-
- void SetTickClockForTest(std::unique_ptr<base::TickClock> tick_clock);
-
- // How long the cached output is valid after startup.
- static const int kUseCacheAfterStartupMs;
-
- private:
- NativeDisplayDelegateX11::HelperDelegate* delegate_; // Not owned.
-
- // The base of the event numbers used to represent XRandr events used in
- // decoding events regarding output add/remove.
- int xrandr_event_base_;
-
- base::TimeTicks startup_time_;
-
- std::unique_ptr<base::TickClock> tick_clock_;
-
- DISALLOW_COPY_AND_ASSIGN(NativeDisplayEventDispatcherX11);
-};
-
-} // namespace display
-
-#endif // UI_DISPLAY_MANAGER_CHROMEOS_X11_NATIVE_DISPLAY_EVENT_DISPATCHER_X11_H_
diff --git a/chromium/ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11_unittest.cc b/chromium/ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11_unittest.cc
deleted file mode 100644
index 9168ef67534..00000000000
--- a/chromium/ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11_unittest.cc
+++ /dev/null
@@ -1,325 +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 <stdint.h>
-#include <X11/extensions/Xrandr.h>
-
-#undef Bool
-#undef None
-
-#include <algorithm>
-#include <memory>
-#include <vector>
-
-#include "base/macros.h"
-#include "base/memory/ptr_util.h"
-#include "base/test/simple_test_tick_clock.h"
-#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/display/manager/chromeos/x11/display_mode_x11.h"
-#include "ui/display/manager/chromeos/x11/display_snapshot_x11.h"
-#include "ui/display/manager/chromeos/x11/native_display_delegate_x11.h"
-#include "ui/display/manager/chromeos/x11/native_display_event_dispatcher_x11.h"
-
-namespace display {
-
-namespace {
-
-std::unique_ptr<DisplaySnapshotX11> CreateOutput(int64_t id,
- DisplayConnectionType type,
- RROutput output,
- RRCrtc crtc) {
- static const DisplayModeX11 kDefaultDisplayMode(gfx::Size(1, 1), false, 60.0f,
- 20);
- std::vector<std::unique_ptr<const DisplayMode>> modes;
- const DisplayMode* mode;
-
- modes.push_back(kDefaultDisplayMode.Clone());
- mode = modes.front().get();
-
- return base::MakeUnique<DisplaySnapshotX11>(
- id, gfx::Point(0, 0), gfx::Size(0, 0), type, false, false, std::string(),
- std::move(modes), std::vector<uint8_t>(), mode, nullptr, output, crtc, 0);
-}
-
-std::unique_ptr<DisplaySnapshotX11> CreateExternalOutput(RROutput output,
- RRCrtc crtc) {
- return CreateOutput(static_cast<int64_t>(output),
- DISPLAY_CONNECTION_TYPE_UNKNOWN, output, crtc);
-}
-
-std::unique_ptr<DisplaySnapshotX11> CreateInternalOutput(RROutput output,
- RRCrtc crtc) {
- return CreateOutput(0, DISPLAY_CONNECTION_TYPE_INTERNAL, output, crtc);
-}
-
-class TestHelperDelegate : public NativeDisplayDelegateX11::HelperDelegate {
- public:
- TestHelperDelegate();
- ~TestHelperDelegate() override;
-
- int num_calls_update_xrandr_config() const {
- return num_calls_update_xrandr_config_;
- }
-
- int num_calls_notify_observers() const { return num_calls_notify_observers_; }
-
- void SetCachedOutputs(
- const std::vector<std::unique_ptr<DisplaySnapshot>>& outputs) {
- cached_outputs_.resize(outputs.size());
- std::transform(outputs.cbegin(), outputs.cend(), cached_outputs_.begin(),
- [](const std::unique_ptr<DisplaySnapshot>& item) {
- return item.get();
- });
- }
-
- // NativeDisplayDelegateX11::HelperDelegate overrides:
- void UpdateXRandRConfiguration(const base::NativeEvent& event) override;
- std::vector<DisplaySnapshot*> GetCachedDisplays() const override;
- void NotifyDisplayObservers() override;
-
- private:
- int num_calls_update_xrandr_config_;
- int num_calls_notify_observers_;
-
- std::vector<DisplaySnapshot*> cached_outputs_;
-
- DISALLOW_COPY_AND_ASSIGN(TestHelperDelegate);
-};
-
-TestHelperDelegate::TestHelperDelegate()
- : num_calls_update_xrandr_config_(0), num_calls_notify_observers_(0) {}
-
-TestHelperDelegate::~TestHelperDelegate() {}
-
-void TestHelperDelegate::UpdateXRandRConfiguration(
- const base::NativeEvent& event) {
- ++num_calls_update_xrandr_config_;
-}
-
-std::vector<DisplaySnapshot*> TestHelperDelegate::GetCachedDisplays() const {
- return cached_outputs_;
-}
-
-void TestHelperDelegate::NotifyDisplayObservers() {
- ++num_calls_notify_observers_;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// NativeDisplayEventDispatcherX11Test
-
-class NativeDisplayEventDispatcherX11Test : public testing::Test {
- public:
- NativeDisplayEventDispatcherX11Test();
- ~NativeDisplayEventDispatcherX11Test() override;
-
- protected:
- void DispatchScreenChangeEvent();
- void DispatchOutputChangeEvent(RROutput output,
- RRCrtc crtc,
- RRMode mode,
- bool connected);
-
- int xrandr_event_base_;
- std::unique_ptr<TestHelperDelegate> helper_delegate_;
- std::unique_ptr<NativeDisplayEventDispatcherX11> dispatcher_;
- base::SimpleTestTickClock* test_tick_clock_; // Owned by |dispatcher_|.
-
- private:
- DISALLOW_COPY_AND_ASSIGN(NativeDisplayEventDispatcherX11Test);
-};
-
-NativeDisplayEventDispatcherX11Test::NativeDisplayEventDispatcherX11Test()
- : xrandr_event_base_(10),
- helper_delegate_(new TestHelperDelegate()),
- dispatcher_(new NativeDisplayEventDispatcherX11(helper_delegate_.get(),
- xrandr_event_base_)),
- test_tick_clock_(new base::SimpleTestTickClock) {
- test_tick_clock_->Advance(base::TimeDelta::FromMilliseconds(1));
- dispatcher_->SetTickClockForTest(
- std::unique_ptr<base::TickClock>(test_tick_clock_));
-}
-
-NativeDisplayEventDispatcherX11Test::~NativeDisplayEventDispatcherX11Test() {}
-
-void NativeDisplayEventDispatcherX11Test::DispatchScreenChangeEvent() {
- XRRScreenChangeNotifyEvent event = {0};
- event.type = xrandr_event_base_ + RRScreenChangeNotify;
-
- dispatcher_->DispatchEvent(reinterpret_cast<const ui::PlatformEvent>(&event));
-}
-
-void NativeDisplayEventDispatcherX11Test::DispatchOutputChangeEvent(
- RROutput output,
- RRCrtc crtc,
- RRMode mode,
- bool connected) {
- XRROutputChangeNotifyEvent event = {0};
- event.type = xrandr_event_base_ + RRNotify;
- event.subtype = RRNotify_OutputChange;
- event.output = output;
- event.crtc = crtc;
- event.mode = mode;
- event.connection = connected ? RR_Connected : RR_Disconnected;
-
- dispatcher_->DispatchEvent(reinterpret_cast<const ui::PlatformEvent>(&event));
-}
-
-} // namespace
-
-TEST_F(NativeDisplayEventDispatcherX11Test, OnScreenChangedEvent) {
- DispatchScreenChangeEvent();
- EXPECT_EQ(1, helper_delegate_->num_calls_update_xrandr_config());
- EXPECT_EQ(0, helper_delegate_->num_calls_notify_observers());
-}
-
-TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationOnFirstEvent) {
- DispatchOutputChangeEvent(1, 10, 20, true);
- EXPECT_EQ(0, helper_delegate_->num_calls_update_xrandr_config());
- EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
-}
-
-TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationAfterSecondEvent) {
- DispatchOutputChangeEvent(1, 10, 20, true);
-
- // Simulate addition of the first output to the cached output list.
- std::vector<std::unique_ptr<DisplaySnapshot>> outputs;
- outputs.push_back(CreateExternalOutput(1, 10));
- helper_delegate_->SetCachedOutputs(outputs);
-
- DispatchOutputChangeEvent(2, 11, 20, true);
- EXPECT_EQ(2, helper_delegate_->num_calls_notify_observers());
-}
-
-TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationOnDisconnect) {
- std::vector<std::unique_ptr<DisplaySnapshot>> outputs;
- outputs.push_back(CreateExternalOutput(1, 10));
- helper_delegate_->SetCachedOutputs(outputs);
-
- DispatchOutputChangeEvent(1, 10, 20, false);
- EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
-}
-
-TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationOnModeChange) {
- std::vector<std::unique_ptr<DisplaySnapshot>> outputs;
- outputs.push_back(CreateExternalOutput(1, 10));
- helper_delegate_->SetCachedOutputs(outputs);
-
- DispatchOutputChangeEvent(1, 10, 21, true);
- EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
-}
-
-TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationOnSecondOutput) {
- std::vector<std::unique_ptr<DisplaySnapshot>> outputs;
- outputs.push_back(CreateExternalOutput(1, 10));
- helper_delegate_->SetCachedOutputs(outputs);
-
- DispatchOutputChangeEvent(2, 11, 20, true);
- EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
-}
-
-TEST_F(NativeDisplayEventDispatcherX11Test, CheckNotificationOnDifferentCrtc) {
- std::vector<std::unique_ptr<DisplaySnapshot>> outputs;
- outputs.push_back(CreateExternalOutput(1, 10));
- helper_delegate_->SetCachedOutputs(outputs);
-
- DispatchOutputChangeEvent(1, 11, 20, true);
- EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
-}
-
-TEST_F(NativeDisplayEventDispatcherX11Test,
- CheckNotificationOnSecondOutputDisconnect) {
- std::vector<std::unique_ptr<DisplaySnapshot>> outputs;
- outputs.push_back(CreateExternalOutput(1, 10));
- outputs.push_back(CreateExternalOutput(2, 11));
- helper_delegate_->SetCachedOutputs(outputs);
-
- DispatchOutputChangeEvent(2, 11, 20, false);
- EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
-}
-
-TEST_F(NativeDisplayEventDispatcherX11Test,
- AvoidDuplicateNotificationOnSecondOutputDisconnect) {
- std::vector<std::unique_ptr<DisplaySnapshot>> outputs;
- outputs.push_back(CreateExternalOutput(1, 10));
- outputs.push_back(CreateExternalOutput(2, 11));
- helper_delegate_->SetCachedOutputs(outputs);
-
- DispatchOutputChangeEvent(2, 11, 20, false);
- EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
-
- // Simulate removal of second output from cached output list.
- outputs.erase(outputs.begin() + 1);
- helper_delegate_->SetCachedOutputs(outputs);
-
- DispatchOutputChangeEvent(2, 11, 20, false);
- EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
-}
-
-TEST_F(NativeDisplayEventDispatcherX11Test, ForceUpdateAfterCacheExpiration) {
- // +1 to compenstate a possible rounding error.
- const int kHalfOfExpirationMs =
- NativeDisplayEventDispatcherX11::kUseCacheAfterStartupMs / 2 + 1;
-
- std::vector<std::unique_ptr<DisplaySnapshot>> outputs;
- outputs.push_back(CreateExternalOutput(1, 10));
- outputs.push_back(CreateExternalOutput(2, 11));
- helper_delegate_->SetCachedOutputs(outputs);
-
- EXPECT_EQ(0, helper_delegate_->num_calls_notify_observers());
-
- // Duplicated event will be ignored during the startup.
- DispatchOutputChangeEvent(2, 11, 20, true);
- EXPECT_EQ(0, helper_delegate_->num_calls_notify_observers());
-
- test_tick_clock_->Advance(
- base::TimeDelta::FromMilliseconds(kHalfOfExpirationMs));
-
- // Duplicated event will still be ignored.
- DispatchOutputChangeEvent(2, 11, 20, true);
- EXPECT_EQ(0, helper_delegate_->num_calls_notify_observers());
-
- // The startup timeout has been elapsed. Duplicated event
- // should not be ignored.
- test_tick_clock_->Advance(
- base::TimeDelta::FromMilliseconds(kHalfOfExpirationMs));
- DispatchOutputChangeEvent(2, 11, 20, true);
- EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
-
- // Sending the same event immediately shoudldn't be ignored.
- DispatchOutputChangeEvent(2, 11, 20, true);
- EXPECT_EQ(2, helper_delegate_->num_calls_notify_observers());
-
- // Advancing time further should not change the behavior.
- test_tick_clock_->Advance(
- base::TimeDelta::FromMilliseconds(kHalfOfExpirationMs));
- DispatchOutputChangeEvent(2, 11, 20, true);
- EXPECT_EQ(3, helper_delegate_->num_calls_notify_observers());
-
- test_tick_clock_->Advance(
- base::TimeDelta::FromMilliseconds(kHalfOfExpirationMs));
- DispatchOutputChangeEvent(2, 11, 20, true);
- EXPECT_EQ(4, helper_delegate_->num_calls_notify_observers());
-}
-
-TEST_F(NativeDisplayEventDispatcherX11Test, UpdateMissingExternalDisplayId) {
- std::vector<std::unique_ptr<DisplaySnapshot>> outputs;
- outputs.push_back(CreateInternalOutput(1, 10));
- helper_delegate_->SetCachedOutputs(outputs);
-
- ASSERT_EQ(0, helper_delegate_->num_calls_notify_observers());
-
- // Internal display's ID can be zero and not updated.
- DispatchOutputChangeEvent(1, 10, 20, true);
- EXPECT_EQ(0, helper_delegate_->num_calls_notify_observers());
-
- outputs.clear();
- outputs.push_back(CreateOutput(0, DISPLAY_CONNECTION_TYPE_UNKNOWN, 2, 11));
- helper_delegate_->SetCachedOutputs(outputs);
-
- // External display should be updated if the id is zero.
- DispatchOutputChangeEvent(2, 11, 20, true);
- EXPECT_EQ(1, helper_delegate_->num_calls_notify_observers());
-}
-
-} // namespace display
diff --git a/chromium/ui/display/manager/display_layout_store.cc b/chromium/ui/display/manager/display_layout_store.cc
index 7e94b343fee..08721f48798 100644
--- a/chromium/ui/display/manager/display_layout_store.cc
+++ b/chromium/ui/display/manager/display_layout_store.cc
@@ -88,7 +88,7 @@ void DisplayLayoutStore::RegisterLayoutForDisplayIdList(
const DisplayLayout& DisplayLayoutStore::GetRegisteredDisplayLayout(
const DisplayIdList& list) {
- DCHECK_NE(1u, list.size());
+ DCHECK_GT(list.size(), 1u);
const auto iter = layouts_.find(list);
const DisplayLayout* layout = iter != layouts_.end()
? iter->second.get()
diff --git a/chromium/ui/display/manager/display_manager.cc b/chromium/ui/display/manager/display_manager.cc
index e5e3951608b..7a4b06c669f 100644
--- a/chromium/ui/display/manager/display_manager.cc
+++ b/chromium/ui/display/manager/display_manager.cc
@@ -207,6 +207,12 @@ void DisplayManager::InitDefaultDisplay() {
OnNativeDisplaysChanged(info_list);
}
+void DisplayManager::UpdateInternalDisplay(
+ const ManagedDisplayInfo& display_info) {
+ DCHECK(Display::HasInternalDisplay());
+ InsertAndUpdateDisplayInfo(display_info);
+}
+
void DisplayManager::RefreshFontParams() {
#if defined(OS_CHROMEOS)
// Use the largest device scale factor among currently active displays. Non
@@ -290,7 +296,7 @@ void DisplayManager::SetLayoutForCurrentDisplays(
}
if (delegate_)
- delegate_->PostDisplayConfigurationChange(false);
+ delegate_->PostDisplayConfigurationChange();
}
const Display& DisplayManager::GetDisplayForId(int64_t display_id) const {
@@ -446,7 +452,6 @@ void DisplayManager::RegisterDisplayProperty(
const gfx::Insets* overscan_insets,
const gfx::Size& resolution_in_pixels,
float device_scale_factor,
- ColorCalibrationProfile color_profile,
const TouchCalibrationData* touch_calibration_data) {
if (display_info_.find(display_id) == display_info_.end())
display_info_[display_id] =
@@ -460,7 +465,6 @@ void DisplayManager::RegisterDisplayProperty(
Display::ROTATION_SOURCE_USER);
display_info_[display_id].SetRotation(rotation,
Display::ROTATION_SOURCE_ACTIVE);
- display_info_[display_id].SetColorProfile(color_profile);
// Just in case the preference file was corrupted.
// TODO(mukai): register |display_modes_| here as well, so the lookup for the
// default mode in GetActiveModeForDisplayId() gets much simpler.
@@ -513,7 +517,7 @@ void DisplayManager::RegisterDisplayRotationProperties(
registered_internal_display_rotation_lock_ = rotation_lock;
registered_internal_display_rotation_ = rotation;
if (delegate_)
- delegate_->PostDisplayConfigurationChange(false);
+ delegate_->PostDisplayConfigurationChange();
}
scoped_refptr<ManagedDisplayMode> DisplayManager::GetSelectedModeForDisplayId(
@@ -551,28 +555,6 @@ gfx::Insets DisplayManager::GetOverscanInsets(int64_t display_id) const {
: gfx::Insets();
}
-void DisplayManager::SetColorCalibrationProfile(
- int64_t display_id,
- ColorCalibrationProfile profile) {
-#if defined(OS_CHROMEOS)
- if (!display_info_[display_id].IsColorProfileAvailable(profile))
- return;
-
- if (delegate_)
- delegate_->PreDisplayConfigurationChange(false);
- // Just sets color profile if it's not running on ChromeOS (like tests).
- if (!configure_displays_ ||
- delegate_->display_configurator()->SetColorCalibrationProfile(display_id,
- profile)) {
- display_info_[display_id].SetColorProfile(profile);
- UMA_HISTOGRAM_ENUMERATION("ChromeOS.Display.ColorProfile", profile,
- NUM_COLOR_PROFILES);
- }
- if (delegate_)
- delegate_->PostDisplayConfigurationChange(false);
-#endif
-}
-
void DisplayManager::OnNativeDisplaysChanged(
const DisplayInfoList& updated_displays) {
if (updated_displays.empty()) {
@@ -902,14 +884,8 @@ void DisplayManager::UpdateDisplaysWith(
if (delegate_ && primary_metrics)
NotifyMetricsChanged(screen_->GetPrimaryDisplay(), primary_metrics);
- bool must_clear_window = false;
-#if defined(USE_X11) && defined(OS_CHROMEOS)
- must_clear_window =
- !display_changes.empty() && base::SysInfo::IsRunningOnChromeOS();
-#endif
-
if (delegate_)
- delegate_->PostDisplayConfigurationChange(must_clear_window);
+ delegate_->PostDisplayConfigurationChange();
// Create the mirroring window asynchronously after all displays
// are added so that it can mirror the display newly added. This can
@@ -1400,18 +1376,6 @@ void DisplayManager::InsertAndUpdateDisplayInfo(
}
}
display_info_[new_info.id()].UpdateDisplaySize();
- OnDisplayInfoUpdated(display_info_[new_info.id()]);
-}
-
-void DisplayManager::OnDisplayInfoUpdated(
- const ManagedDisplayInfo& display_info) {
-#if defined(OS_CHROMEOS)
- ColorCalibrationProfile color_profile = display_info.color_profile();
- if (color_profile != COLOR_PROFILE_STANDARD) {
- delegate_->display_configurator()->SetColorCalibrationProfile(
- display_info.id(), color_profile);
- }
-#endif
}
Display DisplayManager::CreateDisplayFromDisplayInfoById(int64_t id) {
diff --git a/chromium/ui/display/manager/display_manager.h b/chromium/ui/display/manager/display_manager.h
index 71d3cc69aba..676558dc08e 100644
--- a/chromium/ui/display/manager/display_manager.h
+++ b/chromium/ui/display/manager/display_manager.h
@@ -70,7 +70,7 @@ class DISPLAY_MANAGER_EXPORT DisplayManager
// |clear_focus| is true, the implementation should deactivate the active
// window and set the focus window to NULL.
virtual void PreDisplayConfigurationChange(bool clear_focus) = 0;
- virtual void PostDisplayConfigurationChange(bool must_clear_window) = 0;
+ virtual void PostDisplayConfigurationChange() = 0;
#if defined(OS_CHROMEOS)
// Get the DisplayConfigurator.
@@ -127,6 +127,9 @@ class DISPLAY_MANAGER_EXPORT DisplayManager
// Initialize default display.
void InitDefaultDisplay();
+ // Update the internal display's display info.
+ void UpdateInternalDisplay(const ManagedDisplayInfo& display_info);
+
// Initializes font related params that depends on display configuration.
void RefreshFontParams();
@@ -190,7 +193,6 @@ class DISPLAY_MANAGER_EXPORT DisplayManager
const gfx::Insets* overscan_insets,
const gfx::Size& resolution_in_pixels,
float device_scale_factor,
- ColorCalibrationProfile color_profile,
const TouchCalibrationData* touch_calibration_data);
// Register stored rotation properties for the internal display.
@@ -233,10 +235,6 @@ class DISPLAY_MANAGER_EXPORT DisplayManager
// display.
gfx::Insets GetOverscanInsets(int64_t display_id) const;
- // Sets the color calibration of the display to |profile|.
- void SetColorCalibrationProfile(int64_t display_id,
- ColorCalibrationProfile profile);
-
// Called when display configuration has changed. The new display
// configurations is passed as a vector of Display object, which contains each
// display's new infomration.
@@ -413,9 +411,6 @@ class DISPLAY_MANAGER_EXPORT DisplayManager
// |GetDisplayInfo| to get the correct ManagedDisplayInfo for a display.
void InsertAndUpdateDisplayInfo(const ManagedDisplayInfo& new_info);
- // Called when the display info is updated through InsertAndUpdateDisplayInfo.
- void OnDisplayInfoUpdated(const ManagedDisplayInfo& display_info);
-
// Creates a display object from the ManagedDisplayInfo for
// |display_id|.
Display CreateDisplayFromDisplayInfoById(int64_t display_id);
diff --git a/chromium/ui/display/manager/forwarding_display_delegate.cc b/chromium/ui/display/manager/forwarding_display_delegate.cc
index c95a83cefb3..5f3a7d9fae0 100644
--- a/chromium/ui/display/manager/forwarding_display_delegate.cc
+++ b/chromium/ui/display/manager/forwarding_display_delegate.cc
@@ -8,7 +8,7 @@
#include "base/bind.h"
#include "mojo/public/cpp/bindings/sync_call_restrictions.h"
-#include "ui/display/types/display_snapshot_mojo.h"
+#include "ui/display/types/display_snapshot.h"
namespace display {
@@ -31,10 +31,6 @@ void ForwardingDisplayDelegate::Initialize() {
delegate_->Initialize(std::move(observer), &snapshots_);
}
-void ForwardingDisplayDelegate::GrabServer() {}
-
-void ForwardingDisplayDelegate::UngrabServer() {}
-
void ForwardingDisplayDelegate::TakeDisplayControl(
const DisplayControlCallback& callback) {
delegate_->TakeDisplayControl(callback);
@@ -45,12 +41,6 @@ void ForwardingDisplayDelegate::RelinquishDisplayControl(
delegate_->TakeDisplayControl(callback);
}
-void ForwardingDisplayDelegate::SyncWithServer() {}
-
-void ForwardingDisplayDelegate::SetBackgroundColor(uint32_t color_argb) {}
-
-void ForwardingDisplayDelegate::ForceDPMSOn() {}
-
void ForwardingDisplayDelegate::GetDisplays(
const GetDisplaysCallback& callback) {
if (!use_delegate_) {
@@ -63,9 +53,6 @@ void ForwardingDisplayDelegate::GetDisplays(
base::Unretained(this), callback));
}
-void ForwardingDisplayDelegate::AddMode(const DisplaySnapshot& snapshot,
- const DisplayMode* mode) {}
-
void ForwardingDisplayDelegate::Configure(const DisplaySnapshot& snapshot,
const DisplayMode* mode,
const gfx::Point& origin,
@@ -84,8 +71,6 @@ void ForwardingDisplayDelegate::Configure(const DisplaySnapshot& snapshot,
callback);
}
-void ForwardingDisplayDelegate::CreateFrameBuffer(const gfx::Size& size) {}
-
void ForwardingDisplayDelegate::GetHDCPState(
const DisplaySnapshot& snapshot,
const GetHDCPStateCallback& callback) {
@@ -99,18 +84,6 @@ void ForwardingDisplayDelegate::SetHDCPState(
delegate_->SetHDCPState(snapshot.display_id(), state, callback);
}
-std::vector<ColorCalibrationProfile>
-ForwardingDisplayDelegate::GetAvailableColorCalibrationProfiles(
- const DisplaySnapshot& output) {
- return std::vector<ColorCalibrationProfile>();
-}
-
-bool ForwardingDisplayDelegate::SetColorCalibrationProfile(
- const DisplaySnapshot& output,
- ColorCalibrationProfile new_profile) {
- return false;
-}
-
bool ForwardingDisplayDelegate::SetColorCorrection(
const DisplaySnapshot& output,
const std::vector<GammaRampRGBEntry>& degamma_lut,
@@ -148,7 +121,7 @@ void ForwardingDisplayDelegate::OnConfigurationChanged() {
void ForwardingDisplayDelegate::StoreAndForwardDisplays(
const GetDisplaysCallback& callback,
- std::vector<std::unique_ptr<DisplaySnapshotMojo>> snapshots) {
+ std::vector<std::unique_ptr<DisplaySnapshot>> snapshots) {
for (auto& observer : observers_)
observer.OnDisplaySnapshotsInvalidated();
snapshots_ = std::move(snapshots);
diff --git a/chromium/ui/display/manager/forwarding_display_delegate.h b/chromium/ui/display/manager/forwarding_display_delegate.h
index 17cded9103b..5e0eb3f352e 100644
--- a/chromium/ui/display/manager/forwarding_display_delegate.h
+++ b/chromium/ui/display/manager/forwarding_display_delegate.h
@@ -19,44 +19,33 @@
namespace display {
-class DisplaySnapshotMojo;
+class DisplaySnapshot;
// NativeDisplayDelegate implementation that forwards calls to a real
// NativeDisplayDelegate in another process. Only forwards the methods
// implemented by Ozone DRM, other method won't do anything.
class DISPLAY_MANAGER_EXPORT ForwardingDisplayDelegate
: public NativeDisplayDelegate,
- public NON_EXPORTED_BASE(mojom::NativeDisplayObserver) {
+ public mojom::NativeDisplayObserver {
public:
explicit ForwardingDisplayDelegate(mojom::NativeDisplayDelegatePtr delegate);
~ForwardingDisplayDelegate() override;
// display::NativeDisplayDelegate:
void Initialize() override;
- void GrabServer() override;
- void UngrabServer() override;
void TakeDisplayControl(const DisplayControlCallback& callback) override;
void RelinquishDisplayControl(
const DisplayControlCallback& callback) override;
- void SyncWithServer() override;
- void SetBackgroundColor(uint32_t color_argb) override;
- void ForceDPMSOn() override;
void GetDisplays(const GetDisplaysCallback& callback) override;
- void AddMode(const DisplaySnapshot& output, const DisplayMode* mode) override;
void Configure(const DisplaySnapshot& output,
const DisplayMode* mode,
const gfx::Point& origin,
const ConfigureCallback& callback) override;
- void CreateFrameBuffer(const gfx::Size& size) override;
void GetHDCPState(const DisplaySnapshot& output,
const GetHDCPStateCallback& callback) override;
void SetHDCPState(const DisplaySnapshot& output,
HDCPState state,
const SetHDCPStateCallback& callback) override;
- std::vector<ColorCalibrationProfile> GetAvailableColorCalibrationProfiles(
- const DisplaySnapshot& output) override;
- bool SetColorCalibrationProfile(const DisplaySnapshot& output,
- ColorCalibrationProfile new_profile) override;
bool SetColorCorrection(const DisplaySnapshot& output,
const std::vector<GammaRampRGBEntry>& degamma_lut,
const std::vector<GammaRampRGBEntry>& gamma_lut,
@@ -72,7 +61,7 @@ class DISPLAY_MANAGER_EXPORT ForwardingDisplayDelegate
// Stores display snapshots and forwards pointers to |callback|.
void StoreAndForwardDisplays(
const GetDisplaysCallback& callback,
- std::vector<std::unique_ptr<DisplaySnapshotMojo>> snapshots);
+ std::vector<std::unique_ptr<DisplaySnapshot>> snapshots);
// Forwards display snapshot pointers to |callback|.
void ForwardDisplays(const GetDisplaysCallback& callback);
@@ -86,7 +75,7 @@ class DISPLAY_MANAGER_EXPORT ForwardingDisplayDelegate
// Display snapshots are owned here but accessed via raw pointers elsewhere.
// Call OnDisplaySnapshotsInvalidated() on observers before invalidating them.
- std::vector<std::unique_ptr<DisplaySnapshotMojo>> snapshots_;
+ std::vector<std::unique_ptr<DisplaySnapshot>> snapshots_;
base::ObserverList<display::NativeDisplayObserver> observers_;
diff --git a/chromium/ui/display/manager/managed_display_info.cc b/chromium/ui/display/manager/managed_display_info.cc
index 850aa5468a7..82b1ea3cc21 100644
--- a/chromium/ui/display/manager/managed_display_info.cc
+++ b/chromium/ui/display/manager/managed_display_info.cc
@@ -304,8 +304,7 @@ ManagedDisplayInfo::ManagedDisplayInfo()
configured_ui_scale_(1.0f),
native_(false),
is_aspect_preserving_scaling_(false),
- clear_overscan_insets_(false),
- color_profile_(COLOR_PROFILE_STANDARD) {}
+ clear_overscan_insets_(false) {}
ManagedDisplayInfo::ManagedDisplayInfo(int64_t id,
const std::string& name,
@@ -322,8 +321,7 @@ ManagedDisplayInfo::ManagedDisplayInfo(int64_t id,
configured_ui_scale_(1.0f),
native_(false),
is_aspect_preserving_scaling_(false),
- clear_overscan_insets_(false),
- color_profile_(COLOR_PROFILE_STANDARD) {}
+ clear_overscan_insets_(false) {}
ManagedDisplayInfo::ManagedDisplayInfo(const ManagedDisplayInfo& other) =
default;
@@ -363,7 +361,6 @@ void ManagedDisplayInfo::Copy(const ManagedDisplayInfo& native_info) {
size_in_pixel_ = native_info.size_in_pixel_;
is_aspect_preserving_scaling_ = native_info.is_aspect_preserving_scaling_;
display_modes_ = native_info.display_modes_;
- available_color_profiles_ = native_info.available_color_profiles_;
maximum_cursor_size_ = native_info.maximum_cursor_size_;
// Rotation, ui_scale, color_profile and overscan are given by preference,
@@ -383,7 +380,6 @@ void ManagedDisplayInfo::Copy(const ManagedDisplayInfo& native_info) {
rotations_ = native_info.rotations_;
configured_ui_scale_ = native_info.configured_ui_scale_;
- color_profile_ = native_info.color_profile();
}
}
@@ -499,16 +495,6 @@ std::string ManagedDisplayInfo::ToFullString() const {
return ToString() + ", display_modes==" + display_modes_str;
}
-void ManagedDisplayInfo::SetColorProfile(ColorCalibrationProfile profile) {
- if (IsColorProfileAvailable(profile))
- color_profile_ = profile;
-}
-
-bool ManagedDisplayInfo::IsColorProfileAvailable(
- ColorCalibrationProfile profile) const {
- return base::ContainsValue(available_color_profiles_, profile);
-}
-
bool ManagedDisplayInfo::Use125DSFForUIScaling() const {
return Display::IsInternalDisplayId(id_);
}
diff --git a/chromium/ui/display/manager/managed_display_info.h b/chromium/ui/display/manager/managed_display_info.h
index e52e05e248c..38c2aab2b36 100644
--- a/chromium/ui/display/manager/managed_display_info.h
+++ b/chromium/ui/display/manager/managed_display_info.h
@@ -285,24 +285,6 @@ class DISPLAY_MANAGER_EXPORT ManagedDisplayInfo {
// empty size.
gfx::Size GetNativeModeSize() const;
- ColorCalibrationProfile color_profile() const { return color_profile_; }
-
- // Sets the color profile. It will ignore if the specified |profile| is not in
- // |available_color_profiles_|.
- void SetColorProfile(ColorCalibrationProfile profile);
-
- // Returns true if |profile| is in |available_color_profiles_|.
- bool IsColorProfileAvailable(ColorCalibrationProfile profile) const;
-
- const std::vector<ColorCalibrationProfile>& available_color_profiles() const {
- return available_color_profiles_;
- }
-
- void set_available_color_profiles(
- const std::vector<ColorCalibrationProfile>& profiles) {
- available_color_profiles_ = profiles;
- }
-
bool is_aspect_preserving_scaling() const {
return is_aspect_preserving_scaling_;
}
@@ -383,12 +365,6 @@ class DISPLAY_MANAGER_EXPORT ManagedDisplayInfo {
// The list of modes supported by this display.
ManagedDisplayModeList display_modes_;
- // The current profile of the color calibration.
- ColorCalibrationProfile color_profile_;
-
- // The list of available variations for the color calibration.
- std::vector<ColorCalibrationProfile> available_color_profiles_;
-
// Maximum cursor size.
gfx::Size maximum_cursor_size_;
diff --git a/chromium/ui/display/mojo/BUILD.gn b/chromium/ui/display/mojo/BUILD.gn
index 7b213c1950c..92baf0cdefb 100644
--- a/chromium/ui/display/mojo/BUILD.gn
+++ b/chromium/ui/display/mojo/BUILD.gn
@@ -10,7 +10,7 @@ mojom("interfaces") {
"display_constants.mojom",
"display_layout.mojom",
"display_mode.mojom",
- "display_snapshot_mojo.mojom",
+ "display_snapshot.mojom",
"gamma_ramp_rgb_entry.mojom",
"native_display_delegate.mojom",
]
diff --git a/chromium/ui/display/mojo/display_snapshot_mojo.mojom b/chromium/ui/display/mojo/display_snapshot.mojom
index 8b7ce1c5075..839a9c07c9c 100644
--- a/chromium/ui/display/mojo/display_snapshot_mojo.mojom
+++ b/chromium/ui/display/mojo/display_snapshot.mojom
@@ -9,8 +9,8 @@ import "ui/display/mojo/display_constants.mojom";
import "ui/display/mojo/display_mode.mojom";
import "ui/gfx/geometry/mojo/geometry.mojom";
-// Corresponds to display::DisplaySnapshotMojo.
-struct DisplaySnapshotMojo {
+// Corresponds to display::DisplaySnapshot.
+struct DisplaySnapshot {
int64 display_id;
gfx.mojom.Point origin;
gfx.mojom.Size physical_size;
diff --git a/chromium/ui/display/mojo/display_snapshot.typemap b/chromium/ui/display/mojo/display_snapshot.typemap
new file mode 100644
index 00000000000..4668070524a
--- /dev/null
+++ b/chromium/ui/display/mojo/display_snapshot.typemap
@@ -0,0 +1,17 @@
+# 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.
+
+mojom = "//ui/display/mojo/display_snapshot.mojom"
+public_headers = [ "//ui/display/types/display_snapshot.h" ]
+traits_headers = [ "//ui/display/mojo/display_snapshot_struct_traits.h" ]
+sources = [
+ "//ui/display/mojo/display_snapshot_struct_traits.cc",
+]
+public_deps = [
+ "//ui/display",
+]
+deps = [
+ "//ui/gfx/geometry",
+]
+type_mappings = [ "display.mojom.DisplaySnapshot=std::unique_ptr<display::DisplaySnapshot>[move_only]" ]
diff --git a/chromium/ui/display/mojo/display_snapshot_mojo.typemap b/chromium/ui/display/mojo/display_snapshot_mojo.typemap
deleted file mode 100644
index bd06b0fb742..00000000000
--- a/chromium/ui/display/mojo/display_snapshot_mojo.typemap
+++ /dev/null
@@ -1,17 +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.
-
-mojom = "//ui/display/mojo/display_snapshot_mojo.mojom"
-public_headers = [ "//ui/display/types/display_snapshot_mojo.h" ]
-traits_headers = [ "//ui/display/mojo/display_snapshot_mojo_struct_traits.h" ]
-sources = [
- "//ui/display/mojo/display_snapshot_mojo_struct_traits.cc",
-]
-public_deps = [
- "//ui/display",
-]
-deps = [
- "//ui/gfx/geometry",
-]
-type_mappings = [ "display.mojom.DisplaySnapshotMojo=std::unique_ptr<display::DisplaySnapshotMojo>[move_only]" ]
diff --git a/chromium/ui/display/mojo/display_snapshot_mojo_struct_traits.cc b/chromium/ui/display/mojo/display_snapshot_struct_traits.cc
index 1a370dc87ab..325f52be2d7 100644
--- a/chromium/ui/display/mojo/display_snapshot_mojo_struct_traits.cc
+++ b/chromium/ui/display/mojo/display_snapshot_struct_traits.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/display/mojo/display_snapshot_mojo_struct_traits.h"
+#include "ui/display/mojo/display_snapshot_struct_traits.h"
#include "ui/display/types/display_constants.h"
#include "ui/gfx/geometry/size.h"
@@ -32,10 +32,9 @@ static uint64_t GetModeIndex(
// static
std::vector<std::unique_ptr<display::DisplayMode>>
-StructTraits<display::mojom::DisplaySnapshotMojoDataView,
- std::unique_ptr<display::DisplaySnapshotMojo>>::
- modes(
- const std::unique_ptr<display::DisplaySnapshotMojo>& display_snapshot) {
+StructTraits<display::mojom::DisplaySnapshotDataView,
+ std::unique_ptr<display::DisplaySnapshot>>::
+ modes(const std::unique_ptr<display::DisplaySnapshot>& display_snapshot) {
std::vector<std::unique_ptr<display::DisplayMode>> display_mode_list;
for (const auto& display_mode : display_snapshot->modes())
@@ -45,28 +44,28 @@ StructTraits<display::mojom::DisplaySnapshotMojoDataView,
}
// static
-uint64_t StructTraits<display::mojom::DisplaySnapshotMojoDataView,
- std::unique_ptr<display::DisplaySnapshotMojo>>::
+uint64_t StructTraits<display::mojom::DisplaySnapshotDataView,
+ std::unique_ptr<display::DisplaySnapshot>>::
current_mode_index(
- const std::unique_ptr<display::DisplaySnapshotMojo>& display_snapshot) {
+ const std::unique_ptr<display::DisplaySnapshot>& display_snapshot) {
return GetModeIndex(display_snapshot->modes(),
display_snapshot->current_mode());
}
// static
-uint64_t StructTraits<display::mojom::DisplaySnapshotMojoDataView,
- std::unique_ptr<display::DisplaySnapshotMojo>>::
+uint64_t StructTraits<display::mojom::DisplaySnapshotDataView,
+ std::unique_ptr<display::DisplaySnapshot>>::
native_mode_index(
- const std::unique_ptr<display::DisplaySnapshotMojo>& display_snapshot) {
+ const std::unique_ptr<display::DisplaySnapshot>& display_snapshot) {
return GetModeIndex(display_snapshot->modes(),
display_snapshot->native_mode());
}
// static
-bool StructTraits<display::mojom::DisplaySnapshotMojoDataView,
- std::unique_ptr<display::DisplaySnapshotMojo>>::
- Read(display::mojom::DisplaySnapshotMojoDataView data,
- std::unique_ptr<display::DisplaySnapshotMojo>* out) {
+bool StructTraits<display::mojom::DisplaySnapshotDataView,
+ std::unique_ptr<display::DisplaySnapshot>>::
+ Read(display::mojom::DisplaySnapshotDataView data,
+ std::unique_ptr<display::DisplaySnapshot>* out) {
gfx::Point origin;
if (!data.ReadOrigin(&origin))
return false;
@@ -123,12 +122,12 @@ bool StructTraits<display::mojom::DisplaySnapshotMojoDataView,
if (!data.ReadMaximumCursorSize(&maximum_cursor_size))
return false;
- *out = base::MakeUnique<display::DisplaySnapshotMojo>(
+ *out = base::MakeUnique<display::DisplaySnapshot>(
data.display_id(), origin, physical_size, type,
data.is_aspect_preserving_scaling(), data.has_overscan(),
data.has_color_correction_matrix(), display_name, file_path,
- data.product_id(), std::move(modes), std::move(edid), current_mode,
- native_mode, maximum_cursor_size);
+ std::move(modes), std::move(edid), current_mode, native_mode,
+ data.product_id(), maximum_cursor_size);
return true;
}
diff --git a/chromium/ui/display/mojo/display_snapshot_mojo_struct_traits.h b/chromium/ui/display/mojo/display_snapshot_struct_traits.h
index 3c66e1768cf..cffec53f77e 100644
--- a/chromium/ui/display/mojo/display_snapshot_mojo_struct_traits.h
+++ b/chromium/ui/display/mojo/display_snapshot_struct_traits.h
@@ -8,97 +8,97 @@
#include "ipc/ipc_message_utils.h"
#include "ui/display/mojo/display_constants_struct_traits.h"
#include "ui/display/mojo/display_mode_struct_traits.h"
-#include "ui/display/mojo/display_snapshot_mojo.mojom.h"
+#include "ui/display/mojo/display_snapshot.mojom.h"
#include "ui/display/types/display_mode.h"
-#include "ui/display/types/display_snapshot_mojo.h"
+#include "ui/display/types/display_snapshot.h"
#include "ui/gfx/geometry/mojo/geometry_struct_traits.h"
namespace mojo {
template <>
-struct StructTraits<display::mojom::DisplaySnapshotMojoDataView,
- std::unique_ptr<display::DisplaySnapshotMojo>> {
+struct StructTraits<display::mojom::DisplaySnapshotDataView,
+ std::unique_ptr<display::DisplaySnapshot>> {
static int64_t display_id(
- const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) {
+ const std::unique_ptr<display::DisplaySnapshot>& snapshot) {
return snapshot->display_id();
}
static const gfx::Point& origin(
- const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) {
+ const std::unique_ptr<display::DisplaySnapshot>& snapshot) {
return snapshot->origin();
}
static const gfx::Size& physical_size(
- const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) {
+ const std::unique_ptr<display::DisplaySnapshot>& snapshot) {
return snapshot->physical_size();
}
static display::DisplayConnectionType type(
- const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) {
+ const std::unique_ptr<display::DisplaySnapshot>& snapshot) {
return snapshot->type();
}
static bool is_aspect_preserving_scaling(
- const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) {
+ const std::unique_ptr<display::DisplaySnapshot>& snapshot) {
return snapshot->is_aspect_preserving_scaling();
}
static bool has_overscan(
- const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) {
+ const std::unique_ptr<display::DisplaySnapshot>& snapshot) {
return snapshot->has_overscan();
}
static bool has_color_correction_matrix(
- const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) {
+ const std::unique_ptr<display::DisplaySnapshot>& snapshot) {
return snapshot->has_color_correction_matrix();
}
static std::string display_name(
- const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) {
+ const std::unique_ptr<display::DisplaySnapshot>& snapshot) {
return snapshot->display_name();
}
static const base::FilePath& sys_path(
- const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) {
+ const std::unique_ptr<display::DisplaySnapshot>& snapshot) {
return snapshot->sys_path();
}
static std::vector<uint8_t> edid(
- const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) {
+ const std::unique_ptr<display::DisplaySnapshot>& snapshot) {
return snapshot->edid();
}
static std::vector<std::unique_ptr<display::DisplayMode>> modes(
- const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot);
+ const std::unique_ptr<display::DisplaySnapshot>& snapshot);
static uint64_t current_mode_index(
- const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot);
+ const std::unique_ptr<display::DisplaySnapshot>& snapshot);
static bool has_current_mode(
- const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) {
+ const std::unique_ptr<display::DisplaySnapshot>& snapshot) {
return snapshot->current_mode() != nullptr;
}
static uint64_t native_mode_index(
- const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot);
+ const std::unique_ptr<display::DisplaySnapshot>& snapshot);
static bool has_native_mode(
- const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) {
+ const std::unique_ptr<display::DisplaySnapshot>& snapshot) {
return snapshot->native_mode() != nullptr;
}
static int64_t product_id(
- const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) {
+ const std::unique_ptr<display::DisplaySnapshot>& snapshot) {
return snapshot->product_id();
}
static const gfx::Size& maximum_cursor_size(
- const std::unique_ptr<display::DisplaySnapshotMojo>& snapshot) {
+ const std::unique_ptr<display::DisplaySnapshot>& snapshot) {
return snapshot->maximum_cursor_size();
}
- static bool Read(display::mojom::DisplaySnapshotMojoDataView data,
- std::unique_ptr<display::DisplaySnapshotMojo>* out);
+ static bool Read(display::mojom::DisplaySnapshotDataView data,
+ std::unique_ptr<display::DisplaySnapshot>* out);
};
} // namespace mojo
diff --git a/chromium/ui/display/mojo/display_struct_traits_unittest.cc b/chromium/ui/display/mojo/display_struct_traits_unittest.cc
index 42ae82788ec..cf740387f55 100644
--- a/chromium/ui/display/mojo/display_struct_traits_unittest.cc
+++ b/chromium/ui/display/mojo/display_struct_traits_unittest.cc
@@ -13,12 +13,12 @@
#include "ui/display/display_layout.h"
#include "ui/display/mojo/display_layout_struct_traits.h"
#include "ui/display/mojo/display_mode_struct_traits.h"
-#include "ui/display/mojo/display_snapshot_mojo_struct_traits.h"
+#include "ui/display/mojo/display_snapshot_struct_traits.h"
#include "ui/display/mojo/display_struct_traits.h"
#include "ui/display/mojo/gamma_ramp_rgb_entry_struct_traits.h"
#include "ui/display/types/display_constants.h"
#include "ui/display/types/display_mode.h"
-#include "ui/display/types/display_snapshot_mojo.h"
+#include "ui/display/types/display_snapshot.h"
#include "ui/display/types/gamma_ramp_rgb_entry.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
@@ -68,8 +68,8 @@ void CheckDisplayModesEqual(const DisplayMode* input,
EXPECT_EQ(input->refresh_rate(), output->refresh_rate());
}
-void CheckDisplaySnapShotMojoEqual(const DisplaySnapshotMojo& input,
- const DisplaySnapshotMojo& output) {
+void CheckDisplaySnapShotMojoEqual(const DisplaySnapshot& input,
+ const DisplaySnapshot& output) {
// We want to test each component individually to make sure each data member
// was correctly serialized and deserialized.
EXPECT_NE(&input, &output); // Make sure they aren't the same object.
@@ -285,16 +285,14 @@ TEST(DisplayStructTraitsTest, DisplaySnapshotCurrentAndNativeModesNull) {
const DisplayMode* native_mode = nullptr;
const std::vector<uint8_t> edid = {1};
- std::unique_ptr<DisplaySnapshotMojo> input =
- base::MakeUnique<DisplaySnapshotMojo>(
- display_id, origin, physical_size, type, is_aspect_preserving_scaling,
- has_overscan, has_color_correction_matrix, display_name, sys_path,
- product_id, std::move(modes), edid, current_mode, native_mode,
- maximum_cursor_size);
+ std::unique_ptr<DisplaySnapshot> input = base::MakeUnique<DisplaySnapshot>(
+ display_id, origin, physical_size, type, is_aspect_preserving_scaling,
+ has_overscan, has_color_correction_matrix, display_name, sys_path,
+ std::move(modes), edid, current_mode, native_mode, product_id,
+ maximum_cursor_size);
- std::unique_ptr<DisplaySnapshotMojo> output;
- SerializeAndDeserialize<mojom::DisplaySnapshotMojo>(
- DisplaySnapshotMojo::CreateFrom(*input), &output);
+ std::unique_ptr<DisplaySnapshot> output;
+ SerializeAndDeserialize<mojom::DisplaySnapshot>(input->Clone(), &output);
CheckDisplaySnapShotMojoEqual(*input, *output);
}
@@ -323,16 +321,14 @@ TEST(DisplayStructTraitsTest, DisplaySnapshotCurrentModeNull) {
const DisplayMode* native_mode = modes[0].get();
const std::vector<uint8_t> edid = {1};
- std::unique_ptr<DisplaySnapshotMojo> input =
- base::MakeUnique<DisplaySnapshotMojo>(
- display_id, origin, physical_size, type, is_aspect_preserving_scaling,
- has_overscan, has_color_correction_matrix, display_name, sys_path,
- product_id, std::move(modes), edid, current_mode, native_mode,
- maximum_cursor_size);
+ std::unique_ptr<DisplaySnapshot> input = base::MakeUnique<DisplaySnapshot>(
+ display_id, origin, physical_size, type, is_aspect_preserving_scaling,
+ has_overscan, has_color_correction_matrix, display_name, sys_path,
+ std::move(modes), edid, current_mode, native_mode, product_id,
+ maximum_cursor_size);
- std::unique_ptr<DisplaySnapshotMojo> output;
- SerializeAndDeserialize<mojom::DisplaySnapshotMojo>(
- DisplaySnapshotMojo::CreateFrom(*input), &output);
+ std::unique_ptr<DisplaySnapshot> output;
+ SerializeAndDeserialize<mojom::DisplaySnapshot>(input->Clone(), &output);
CheckDisplaySnapShotMojoEqual(*input, *output);
}
@@ -365,16 +361,14 @@ TEST(DisplayStructTraitsTest, DisplaySnapshotExternal) {
const DisplayMode* native_mode = modes[2].get();
const std::vector<uint8_t> edid = {2, 3, 4, 5};
- std::unique_ptr<DisplaySnapshotMojo> input =
- base::MakeUnique<DisplaySnapshotMojo>(
- display_id, origin, physical_size, type, is_aspect_preserving_scaling,
- has_overscan, has_color_correction_matrix, display_name, sys_path,
- product_id, std::move(modes), edid, current_mode, native_mode,
- maximum_cursor_size);
+ std::unique_ptr<DisplaySnapshot> input = base::MakeUnique<DisplaySnapshot>(
+ display_id, origin, physical_size, type, is_aspect_preserving_scaling,
+ has_overscan, has_color_correction_matrix, display_name, sys_path,
+ std::move(modes), edid, current_mode, native_mode, product_id,
+ maximum_cursor_size);
- std::unique_ptr<DisplaySnapshotMojo> output;
- SerializeAndDeserialize<mojom::DisplaySnapshotMojo>(
- DisplaySnapshotMojo::CreateFrom(*input), &output);
+ std::unique_ptr<DisplaySnapshot> output;
+ SerializeAndDeserialize<mojom::DisplaySnapshot>(input->Clone(), &output);
CheckDisplaySnapShotMojoEqual(*input, *output);
}
@@ -402,16 +396,14 @@ TEST(DisplayStructTraitsTest, DisplaySnapshotInternal) {
const DisplayMode* native_mode = modes[0].get();
const std::vector<uint8_t> edid = {2, 3};
- std::unique_ptr<DisplaySnapshotMojo> input =
- base::MakeUnique<DisplaySnapshotMojo>(
- display_id, origin, physical_size, type, is_aspect_preserving_scaling,
- has_overscan, has_color_correction_matrix, display_name, sys_path,
- product_id, std::move(modes), edid, current_mode, native_mode,
- maximum_cursor_size);
+ std::unique_ptr<DisplaySnapshot> input = base::MakeUnique<DisplaySnapshot>(
+ display_id, origin, physical_size, type, is_aspect_preserving_scaling,
+ has_overscan, has_color_correction_matrix, display_name, sys_path,
+ std::move(modes), edid, current_mode, native_mode, product_id,
+ maximum_cursor_size);
- std::unique_ptr<DisplaySnapshotMojo> output;
- SerializeAndDeserialize<mojom::DisplaySnapshotMojo>(
- DisplaySnapshotMojo::CreateFrom(*input), &output);
+ std::unique_ptr<DisplaySnapshot> output;
+ SerializeAndDeserialize<mojom::DisplaySnapshot>(input->Clone(), &output);
CheckDisplaySnapShotMojoEqual(*input, *output);
}
diff --git a/chromium/ui/display/mojo/native_display_delegate.mojom b/chromium/ui/display/mojo/native_display_delegate.mojom
index 9ba1f028888..d0d47a80630 100644
--- a/chromium/ui/display/mojo/native_display_delegate.mojom
+++ b/chromium/ui/display/mojo/native_display_delegate.mojom
@@ -6,7 +6,7 @@ module display.mojom;
import "ui/display/mojo/display_constants.mojom";
import "ui/display/mojo/display_mode.mojom";
-import "ui/display/mojo/display_snapshot_mojo.mojom";
+import "ui/display/mojo/display_snapshot.mojom";
import "ui/display/mojo/gamma_ramp_rgb_entry.mojom";
import "ui/gfx/geometry/mojo/geometry.mojom";
@@ -21,7 +21,8 @@ interface NativeDisplayDelegate {
// Initializes and registers the observer. This is synchronous so that ash
// initialization has an initial set of displays to use.
[Sync]
- Initialize(NativeDisplayObserver observer) => (array<DisplaySnapshotMojo> snapshots);
+ Initialize(NativeDisplayObserver observer) =>
+ (array<DisplaySnapshot> snapshots);
// Take control of the displays from any other controlling process.
TakeDisplayControl() => (bool result);
@@ -30,7 +31,7 @@ interface NativeDisplayDelegate {
RelinquishDisplayControl() => (bool result);
// Queries for a list of fresh displays.
- GetDisplays() => (array<DisplaySnapshotMojo> snapshots);
+ GetDisplays() => (array<DisplaySnapshot> snapshots);
// Configures the display represented by |display_id| to use |mode| and
// positions the display to |origin| in the framebuffer. |mode| can be null,
diff --git a/chromium/ui/display/mojo/typemaps.gni b/chromium/ui/display/mojo/typemaps.gni
index 268ff25d0c4..e352a04421f 100644
--- a/chromium/ui/display/mojo/typemaps.gni
+++ b/chromium/ui/display/mojo/typemaps.gni
@@ -7,6 +7,6 @@ typemaps = [
"//ui/display/mojo/display_constants.typemap",
"//ui/display/mojo/display_layout.typemap",
"//ui/display/mojo/display_mode.typemap",
- "//ui/display/mojo/display_snapshot_mojo.typemap",
+ "//ui/display/mojo/display_snapshot.typemap",
"//ui/display/mojo/gamma_ramp_rgb_entry.typemap",
]
diff --git a/chromium/ui/display/types/BUILD.gn b/chromium/ui/display/types/BUILD.gn
index 9cef99b8f21..b4053c4b031 100644
--- a/chromium/ui/display/types/BUILD.gn
+++ b/chromium/ui/display/types/BUILD.gn
@@ -10,8 +10,6 @@ component("types") {
"display_mode.h",
"display_snapshot.cc",
"display_snapshot.h",
- "display_snapshot_mojo.cc",
- "display_snapshot_mojo.h",
"display_types_export.h",
"fake_display_controller.h",
"gamma_ramp_rgb_entry.h",
diff --git a/chromium/ui/display/types/display_constants.h b/chromium/ui/display/types/display_constants.h
index ff524dd3dda..97cf6214f35 100644
--- a/chromium/ui/display/types/display_constants.h
+++ b/chromium/ui/display/types/display_constants.h
@@ -55,16 +55,6 @@ enum HDCPState {
HDCP_STATE_LAST = HDCP_STATE_ENABLED
};
-// Color calibration profiles. Don't change the order, and edit
-// tools/metrics/histograms/histograms.xml when a new item is added.
-enum ColorCalibrationProfile {
- COLOR_PROFILE_STANDARD,
- COLOR_PROFILE_DYNAMIC,
- COLOR_PROFILE_MOVIE,
- COLOR_PROFILE_READING,
- NUM_COLOR_PROFILES,
-};
-
} // namespace display
#endif // UI_DISPLAY_TYPES_DISPLAY_CONSTANTS_H_
diff --git a/chromium/ui/display/types/display_snapshot.cc b/chromium/ui/display/types/display_snapshot.cc
index e3ecd4b21bc..8e59a1664df 100644
--- a/chromium/ui/display/types/display_snapshot.cc
+++ b/chromium/ui/display/types/display_snapshot.cc
@@ -4,7 +4,13 @@
#include "ui/display/types/display_snapshot.h"
+#include <inttypes.h>
+
#include <algorithm>
+#include <sstream>
+#include <utility>
+
+#include "base/strings/stringprintf.h"
namespace display {
@@ -13,8 +19,44 @@ namespace {
// The display serial number beginning byte position and its length in the
// EDID number as defined in the spec.
// https://en.wikipedia.org/wiki/Extended_Display_Identification_Data
-const size_t kSerialNumberBeginingByte = 12U;
-const size_t kSerialNumberLengthInBytes = 4U;
+constexpr size_t kSerialNumberBeginingByte = 12U;
+constexpr size_t kSerialNumberLengthInBytes = 4U;
+
+std::string ModeListString(
+ const std::vector<std::unique_ptr<const DisplayMode>>& modes) {
+ std::stringstream stream;
+ bool first = true;
+ for (auto& mode : modes) {
+ if (!first)
+ stream << ", ";
+ stream << mode->ToString();
+ first = false;
+ }
+ return stream.str();
+}
+
+std::string DisplayConnectionTypeString(DisplayConnectionType type) {
+ switch (type) {
+ case DISPLAY_CONNECTION_TYPE_NONE:
+ return "none";
+ case DISPLAY_CONNECTION_TYPE_UNKNOWN:
+ return "unknown";
+ case DISPLAY_CONNECTION_TYPE_INTERNAL:
+ return "internal";
+ case DISPLAY_CONNECTION_TYPE_VGA:
+ return "vga";
+ case DISPLAY_CONNECTION_TYPE_HDMI:
+ return "hdmi";
+ case DISPLAY_CONNECTION_TYPE_DVI:
+ return "dvi";
+ case DISPLAY_CONNECTION_TYPE_DISPLAYPORT:
+ return "dp";
+ case DISPLAY_CONNECTION_TYPE_NETWORK:
+ return "network";
+ }
+ NOTREACHED();
+ return "";
+}
} // namespace
@@ -30,7 +72,9 @@ DisplaySnapshot::DisplaySnapshot(int64_t display_id,
DisplayModeList modes,
const std::vector<uint8_t>& edid,
const DisplayMode* current_mode,
- const DisplayMode* native_mode)
+ const DisplayMode* native_mode,
+ int64_t product_id,
+ const gfx::Size& maximum_cursor_size)
: display_id_(display_id),
origin_(origin),
physical_size_(physical_size),
@@ -44,7 +88,8 @@ DisplaySnapshot::DisplaySnapshot(int64_t display_id,
edid_(edid),
current_mode_(current_mode),
native_mode_(native_mode),
- product_id_(kInvalidProductID) {
+ product_id_(product_id),
+ maximum_cursor_size_(maximum_cursor_size) {
// We must explicitly clear out the bytes that represent the serial number.
const size_t end =
std::min(kSerialNumberBeginingByte + kSerialNumberLengthInBytes,
@@ -55,6 +100,42 @@ DisplaySnapshot::DisplaySnapshot(int64_t display_id,
DisplaySnapshot::~DisplaySnapshot() {}
+std::unique_ptr<DisplaySnapshot> DisplaySnapshot::Clone() {
+ DisplayModeList clone_modes;
+ const DisplayMode* cloned_current_mode = nullptr;
+ const DisplayMode* cloned_native_mode = nullptr;
+
+ // Clone the display modes and find equivalent pointers to the native and
+ // current mode.
+ for (auto& mode : modes_) {
+ clone_modes.push_back(mode->Clone());
+ if (mode.get() == current_mode_)
+ cloned_current_mode = clone_modes.back().get();
+ if (mode.get() == native_mode_)
+ cloned_native_mode = clone_modes.back().get();
+ }
+
+ return std::make_unique<DisplaySnapshot>(
+ display_id_, origin_, physical_size_, type_,
+ is_aspect_preserving_scaling_, has_overscan_,
+ has_color_correction_matrix_, display_name_, sys_path_,
+ std::move(clone_modes), edid_, cloned_current_mode, cloned_native_mode,
+ product_id_, maximum_cursor_size_);
+}
+
+std::string DisplaySnapshot::ToString() const {
+ return base::StringPrintf(
+ "id=%" PRId64
+ " current_mode=%s native_mode=%s origin=%s"
+ " physical_size=%s, type=%s name=\"%s\" modes=(%s)",
+ display_id_,
+ current_mode_ ? current_mode_->ToString().c_str() : "nullptr",
+ native_mode_ ? native_mode_->ToString().c_str() : "nullptr",
+ origin_.ToString().c_str(), physical_size_.ToString().c_str(),
+ DisplayConnectionTypeString(type_).c_str(), display_name_.c_str(),
+ ModeListString(modes_).c_str());
+}
+
// static
gfx::BufferFormat DisplaySnapshot::PrimaryFormat() {
return gfx::BufferFormat::BGRX_8888;
diff --git a/chromium/ui/display/types/display_snapshot.h b/chromium/ui/display/types/display_snapshot.h
index 3bf0c838857..db0ccbbd7ec 100644
--- a/chromium/ui/display/types/display_snapshot.h
+++ b/chromium/ui/display/types/display_snapshot.h
@@ -7,6 +7,8 @@
#include <stdint.h>
+#include <memory>
+#include <string>
#include <vector>
#include "base/files/file_path.h"
@@ -38,7 +40,9 @@ class DISPLAY_TYPES_EXPORT DisplaySnapshot {
DisplayModeList modes,
const std::vector<uint8_t>& edid,
const DisplayMode* current_mode,
- const DisplayMode* native_mode);
+ const DisplayMode* native_mode,
+ int64_t product_id,
+ const gfx::Size& maximum_cursor_size);
virtual ~DisplaySnapshot();
const gfx::Point& origin() const { return origin_; }
@@ -72,8 +76,11 @@ class DISPLAY_TYPES_EXPORT DisplaySnapshot {
return has_color_correction_matrix_;
}
+ // Clones display state.
+ virtual std::unique_ptr<DisplaySnapshot> Clone();
+
// Returns a textual representation of this display state.
- virtual std::string ToString() const = 0;
+ virtual std::string ToString() const;
// Used when no product id known.
static const int64_t kInvalidProductID = -1;
diff --git a/chromium/ui/display/types/display_snapshot_mojo.cc b/chromium/ui/display/types/display_snapshot_mojo.cc
deleted file mode 100644
index 09482de3c97..00000000000
--- a/chromium/ui/display/types/display_snapshot_mojo.cc
+++ /dev/null
@@ -1,104 +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/display/types/display_snapshot_mojo.h"
-
-#include "base/memory/ptr_util.h"
-#include "ui/display/types/display_constants.h"
-
-namespace display {
-
-// static
-std::unique_ptr<DisplaySnapshotMojo> DisplaySnapshotMojo::CreateFrom(
- const DisplaySnapshot& other) {
- DisplayModeList clone_modes;
- const DisplayMode* current_mode = nullptr;
- const DisplayMode* native_mode = nullptr;
-
- // Clone the display modes and find equivalent pointers to the native and
- // current mode.
- for (auto& mode : other.modes()) {
- clone_modes.push_back(mode->Clone());
- if (mode.get() == other.current_mode())
- current_mode = mode.get();
- if (mode.get() == other.native_mode())
- native_mode = mode.get();
- }
-
- return base::MakeUnique<DisplaySnapshotMojo>(
- other.display_id(), other.origin(), other.physical_size(), other.type(),
- other.is_aspect_preserving_scaling(), other.has_overscan(),
- other.has_color_correction_matrix(), other.display_name(),
- other.sys_path(), other.product_id(), std::move(clone_modes),
- other.edid(), current_mode, native_mode, other.maximum_cursor_size());
-}
-
-DisplaySnapshotMojo::DisplaySnapshotMojo(int64_t display_id,
- const gfx::Point& origin,
- const gfx::Size& physical_size,
- DisplayConnectionType type,
- bool is_aspect_preserving_scaling,
- bool has_overscan,
- bool has_color_correction_matrix,
- std::string display_name,
- const base::FilePath& sys_path,
- int64_t product_id,
- DisplayModeList modes,
- const std::vector<uint8_t>& edid,
- const DisplayMode* current_mode,
- const DisplayMode* native_mode,
- const gfx::Size& maximum_cursor_size)
- : DisplaySnapshot(display_id,
- origin,
- physical_size,
- type,
- is_aspect_preserving_scaling,
- has_overscan,
- has_color_correction_matrix,
- display_name,
- sys_path,
- std::move(modes),
- edid,
- current_mode,
- native_mode) {
- product_id_ = product_id;
- maximum_cursor_size_ = maximum_cursor_size;
-}
-
-DisplaySnapshotMojo::DisplaySnapshotMojo(int64_t display_id,
- const gfx::Point& origin,
- const gfx::Size& physical_size,
- DisplayConnectionType type,
- bool is_aspect_preserving_scaling,
- bool has_overscan,
- bool has_color_correction_matrix,
- std::string display_name,
- const base::FilePath& sys_path,
- DisplayModeList modes,
- const std::vector<uint8_t>& edid,
- const DisplayMode* current_mode,
- const DisplayMode* native_mode,
- std::string string_representation)
- : DisplaySnapshot(display_id,
- origin,
- physical_size,
- type,
- is_aspect_preserving_scaling,
- has_overscan,
- has_color_correction_matrix,
- display_name,
- sys_path,
- std::move(modes),
- edid,
- current_mode,
- native_mode),
- string_representation_(string_representation) {}
-
-DisplaySnapshotMojo::~DisplaySnapshotMojo() = default;
-
-std::string DisplaySnapshotMojo::ToString() const {
- return string_representation_;
-}
-
-} // namespace display
diff --git a/chromium/ui/display/types/display_snapshot_mojo.h b/chromium/ui/display/types/display_snapshot_mojo.h
deleted file mode 100644
index d68f93b6c18..00000000000
--- a/chromium/ui/display/types/display_snapshot_mojo.h
+++ /dev/null
@@ -1,67 +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_DISPLAY_TYPES_DISPLAY_SNAPSHOT_MOJO_H_
-#define UI_DISPLAY_TYPES_DISPLAY_SNAPSHOT_MOJO_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "ui/display/types/display_snapshot.h"
-#include "ui/display/types/display_types_export.h"
-
-namespace display {
-
-// DisplaySnapshot implementation that can be used with Mojo IPC.
-class DISPLAY_TYPES_EXPORT DisplaySnapshotMojo : public DisplaySnapshot {
- public:
- // Create a new DisplaySnapshotMojo by copying |other|.
- static std::unique_ptr<DisplaySnapshotMojo> CreateFrom(
- const DisplaySnapshot& other);
-
- DisplaySnapshotMojo(int64_t display_id,
- const gfx::Point& origin,
- const gfx::Size& physical_size,
- DisplayConnectionType type,
- bool is_aspect_preserving_scaling,
- bool has_overscan,
- bool has_color_correction_matrix,
- std::string display_name,
- const base::FilePath& sys_path,
- int64_t product_id,
- DisplayModeList modes,
- const std::vector<uint8_t>& edid,
- const DisplayMode* current_mode,
- const DisplayMode* native_mode,
- const gfx::Size& maximum_cursor_size);
-
- DisplaySnapshotMojo(int64_t display_id,
- const gfx::Point& origin,
- const gfx::Size& physical_size,
- DisplayConnectionType type,
- bool is_aspect_preserving_scaling,
- bool has_overscan,
- bool has_color_correction_matrix,
- std::string display_name,
- const base::FilePath& sys_path,
- DisplayModeList modes,
- const std::vector<uint8_t>& edid,
- const DisplayMode* current_mode,
- const DisplayMode* native_mode,
- std::string string_representation);
-
- ~DisplaySnapshotMojo() override;
-
- // display::DisplaySnapshot override:
- std::string ToString() const override;
-
- private:
- std::string string_representation_;
-
- DISALLOW_COPY_AND_ASSIGN(DisplaySnapshotMojo);
-};
-
-} // namespace display
-
-#endif // UI_DISPLAY_TYPES_DISPLAY_SNAPSHOT_MOJO_H_
diff --git a/chromium/ui/display/types/native_display_delegate.h b/chromium/ui/display/types/native_display_delegate.h
index 4cf7e1333e5..0e226b14302 100644
--- a/chromium/ui/display/types/native_display_delegate.h
+++ b/chromium/ui/display/types/native_display_delegate.h
@@ -16,7 +16,6 @@
namespace gfx {
class Point;
-class Size;
}
namespace display {
@@ -45,13 +44,6 @@ class DISPLAY_TYPES_EXPORT NativeDisplayDelegate {
virtual void Initialize() = 0;
- // Grabs and refreshes any display server related resources. Must be balanced
- // by a call to UngrabServer().
- virtual void GrabServer() = 0;
-
- // Released the display server and any resources allocated by GrabServer().
- virtual void UngrabServer() = 0;
-
// Take control of the display from any other controlling process.
virtual void TakeDisplayControl(const DisplayControlCallback& callback) = 0;
@@ -59,23 +51,10 @@ class DISPLAY_TYPES_EXPORT NativeDisplayDelegate {
virtual void RelinquishDisplayControl(
const DisplayControlCallback& callback) = 0;
- // Flushes all pending requests and waits for replies.
- virtual void SyncWithServer() = 0;
-
- // Sets the window's background color to |color_argb|.
- virtual void SetBackgroundColor(uint32_t color_argb) = 0;
-
- // Enables DPMS and forces it to the "on" state.
- virtual void ForceDPMSOn() = 0;
-
// Queries for a list of fresh displays and returns them via |callback|.
// Note the query operation may be expensive and take over 60 milliseconds.
virtual void GetDisplays(const GetDisplaysCallback& callback) = 0;
- // Adds |mode| to |output|. |mode| must be a valid display mode pointer.
- virtual void AddMode(const DisplaySnapshot& output,
- const DisplayMode* mode) = 0;
-
// Configures the display represented by |output| to use |mode| and positions
// the display to |origin| in the framebuffer. |mode| can be NULL, which
// represents disabling the display. The callback will return the status of
@@ -85,9 +64,6 @@ class DISPLAY_TYPES_EXPORT NativeDisplayDelegate {
const gfx::Point& origin,
const ConfigureCallback& callback) = 0;
- // Called to set the frame buffer (underlying XRR "screen") size.
- virtual void CreateFrameBuffer(const gfx::Size& size) = 0;
-
// Gets HDCP state of output.
virtual void GetHDCPState(const DisplaySnapshot& output,
const GetHDCPStateCallback& callback) = 0;
@@ -97,15 +73,6 @@ class DISPLAY_TYPES_EXPORT NativeDisplayDelegate {
HDCPState state,
const SetHDCPStateCallback& callback) = 0;
- // Gets the available list of color calibrations.
- virtual std::vector<ColorCalibrationProfile>
- GetAvailableColorCalibrationProfiles(const DisplaySnapshot& output) = 0;
-
- // Sets the color calibration of |output| to |new_profile|.
- virtual bool SetColorCalibrationProfile(
- const DisplaySnapshot& output,
- ColorCalibrationProfile new_profile) = 0;
-
// Set the gamma tables and corection matrix for the display.
virtual bool SetColorCorrection(
const DisplaySnapshot& output,
diff --git a/chromium/ui/display/win/color_profile_reader.cc b/chromium/ui/display/win/color_profile_reader.cc
index d1220cfd4a9..2a615919f8b 100644
--- a/chromium/ui/display/win/color_profile_reader.cc
+++ b/chromium/ui/display/win/color_profile_reader.cc
@@ -110,9 +110,10 @@ void ColorProfileReader::ReadProfilesCompleted(
if (profile_data.empty()) {
display_id_to_color_space_map_[display_id] = default_color_space_;
} else {
- display_id_to_color_space_map_[display_id] =
- gfx::ICCProfile::FromData(profile_data.data(), profile_data.size())
- .GetColorSpace();
+ gfx::ICCProfile icc_profile =
+ gfx::ICCProfile::FromData(profile_data.data(), profile_data.size());
+ icc_profile.HistogramDisplay(display_id);
+ display_id_to_color_space_map_[display_id] = icc_profile.GetColorSpace();
}
}
diff --git a/chromium/ui/display/win/screen_win.cc b/chromium/ui/display/win/screen_win.cc
index f4e89f29062..df4e5cb17ed 100644
--- a/chromium/ui/display/win/screen_win.cc
+++ b/chromium/ui/display/win/screen_win.cc
@@ -17,6 +17,7 @@
#include "ui/display/display.h"
#include "ui/display/display_layout.h"
#include "ui/display/display_layout_builder.h"
+#include "ui/display/display_switches.h"
#include "ui/display/win/display_info.h"
#include "ui/display/win/dpi.h"
#include "ui/display/win/scaling_util.h"
@@ -81,7 +82,8 @@ std::vector<DisplayInfo> FindAndRemoveTouchingDisplayInfos(
}
Display CreateDisplayFromDisplayInfo(const DisplayInfo& display_info,
- ColorProfileReader* color_profile_reader) {
+ ColorProfileReader* color_profile_reader,
+ bool hdr_enabled) {
Display display(display_info.id());
float scale_factor = display_info.device_scale_factor();
display.set_device_scale_factor(scale_factor);
@@ -92,8 +94,12 @@ Display CreateDisplayFromDisplayInfo(const DisplayInfo& display_info,
1.0f / scale_factor));
display.set_rotation(display_info.rotation());
if (!Display::HasForceColorProfile()) {
- display.set_color_space(
- color_profile_reader->GetDisplayColorSpace(display_info.id()));
+ if (hdr_enabled) {
+ display.SetColorSpaceAndDepth(gfx::ColorSpace::CreateSCRGBLinear());
+ } else {
+ display.SetColorSpaceAndDepth(
+ color_profile_reader->GetDisplayColorSpace(display_info.id()));
+ }
}
return display;
}
@@ -117,7 +123,8 @@ Display CreateDisplayFromDisplayInfo(const DisplayInfo& display_info,
// will take precedence.
std::vector<ScreenWinDisplay> DisplayInfosToScreenWinDisplays(
const std::vector<DisplayInfo>& display_infos,
- ColorProfileReader* color_profile_reader) {
+ ColorProfileReader* color_profile_reader,
+ bool hdr_enabled) {
// Find and extract the primary display.
std::vector<DisplayInfo> display_infos_remaining = display_infos;
auto primary_display_iter = std::find_if(
@@ -145,9 +152,10 @@ std::vector<ScreenWinDisplay> DisplayInfosToScreenWinDisplays(
// Layout and create the ScreenWinDisplays.
std::vector<Display> displays;
- for (const auto& display_info : display_infos)
- displays.push_back(
- CreateDisplayFromDisplayInfo(display_info, color_profile_reader));
+ for (const auto& display_info : display_infos) {
+ displays.push_back(CreateDisplayFromDisplayInfo(
+ display_info, color_profile_reader, hdr_enabled));
+ }
std::unique_ptr<DisplayLayout> layout(builder.Build());
layout->ApplyToDisplayList(&displays, nullptr, 0);
@@ -215,7 +223,8 @@ gfx::Point ScalePointRelative(const gfx::Point& from_origin,
ScreenWin::ScreenWin() : ScreenWin(true) {}
ScreenWin::ScreenWin(bool initialize)
- : color_profile_reader_(new ColorProfileReader(this)) {
+ : color_profile_reader_(new ColorProfileReader(this)),
+ hdr_enabled_(base::FeatureList::IsEnabled(features::kHighDynamicRange)) {
DCHECK(!g_screen_win_instance);
g_screen_win_instance = this;
if (initialize)
@@ -406,6 +415,8 @@ const std::vector<Display>& ScreenWin::GetAllDisplays() const {
}
Display ScreenWin::GetDisplayNearestWindow(gfx::NativeWindow window) const {
+ if (!window)
+ return GetPrimaryDisplay();
HWND window_hwnd = GetHWNDFromNativeView(window);
if (!window_hwnd) {
// When |window| isn't rooted to a display, we should just return the
@@ -458,7 +469,7 @@ gfx::Rect ScreenWin::DIPToScreenRectInWindow(gfx::NativeView view,
void ScreenWin::UpdateFromDisplayInfos(
const std::vector<DisplayInfo>& display_infos) {
screen_win_displays_ = DisplayInfosToScreenWinDisplays(
- display_infos, color_profile_reader_.get());
+ display_infos, color_profile_reader_.get(), hdr_enabled_);
displays_ = ScreenWinDisplaysToDisplays(screen_win_displays_);
}
diff --git a/chromium/ui/display/win/screen_win.h b/chromium/ui/display/win/screen_win.h
index d6a3497177b..988b7c8a099 100644
--- a/chromium/ui/display/win/screen_win.h
+++ b/chromium/ui/display/win/screen_win.h
@@ -203,6 +203,11 @@ class DISPLAY_EXPORT ScreenWin : public Screen,
// A helper to read color profiles from the filesystem.
std::unique_ptr<ColorProfileReader> color_profile_reader_;
+ // Whether or not HDR mode is enabled.
+ // TODO(ccameron): Set this via the GPU process when the system "HDR and
+ // advanced color" setting is enabled.
+ bool hdr_enabled_ = false;
+
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 58f1b602c50..6c44428fa91 100644
--- a/chromium/ui/display/win/screen_win_unittest.cc
+++ b/chromium/ui/display/win/screen_win_unittest.cc
@@ -143,7 +143,7 @@ class TestScreenWinInitializer {
virtual HWND CreateFakeHwnd(const gfx::Rect& bounds) = 0;
};
-class TestScreenWinManager : public TestScreenWinInitializer {
+class TestScreenWinManager final : public TestScreenWinInitializer {
public:
TestScreenWinManager() = default;
diff --git a/chromium/ui/events/BUILD.gn b/chromium/ui/events/BUILD.gn
index ca2f3a9cc3b..570f4e01dfd 100644
--- a/chromium/ui/events/BUILD.gn
+++ b/chromium/ui/events/BUILD.gn
@@ -361,7 +361,14 @@ if (!is_ios) {
test("events_unittests") {
sources = [
"android/scroller_unittest.cc",
+ "blink/blink_event_util_unittest.cc",
+ "blink/input_handler_proxy_unittest.cc",
+ "blink/input_scroll_elasticity_controller_unittest.cc",
+ "blink/web_input_event_traits_unittest.cc",
+ "blink/web_input_event_unittest.cc",
"cocoa/events_mac_unittest.mm",
+ "devices/mojo/device_struct_traits_unittest.cc",
+ "devices/mojo/touch_device_transform_struct_traits_unittest.cc",
"event_dispatcher_unittest.cc",
"event_processor_unittest.cc",
"event_rewriter_unittest.cc",
@@ -376,10 +383,12 @@ if (!is_ios) {
"gesture_detection/snap_scroll_controller_unittest.cc",
"gesture_detection/touch_disposition_gesture_filter_unittest.cc",
"gesture_detection/velocity_tracker_unittest.cc",
+ "gestures/blink/web_gesture_curve_impl_unittest.cc",
"gestures/fling_curve_unittest.cc",
"keycodes/dom/keycode_converter_unittest.cc",
"keycodes/keyboard_code_conversion_unittest.cc",
"keycodes/platform_key_map_win_unittest.cc",
+ "mojo/struct_traits_unittest.cc",
"platform/platform_event_source_unittest.cc",
"scoped_target_handler_unittest.cc",
"win/event_utils_win_unittest.cc",
@@ -393,41 +402,28 @@ if (!is_ios) {
":test_support",
"//base",
"//base/test:test_support",
+ "//cc",
+ "//ipc:test_support",
"//mojo/edk/test:run_all_unittests",
+ "//mojo/public/cpp/bindings",
"//skia",
"//testing/gmock",
"//testing/gtest",
+ "//third_party/WebKit/public:blink_headers",
+ "//ui/display",
+ "//ui/events/blink",
"//ui/events/devices",
+ "//ui/events/devices/mojo:test_interfaces",
+ "//ui/events/gestures/blink",
+ "//ui/events/mojo:test_interfaces",
"//ui/events/platform",
"//ui/gfx:test_support",
+ "//ui/gfx/ipc/geometry",
]
- if (!is_ios) {
- sources += [
- "blink/blink_event_util_unittest.cc",
- "blink/input_handler_proxy_unittest.cc",
- "blink/input_scroll_elasticity_controller_unittest.cc",
- "blink/web_input_event_traits_unittest.cc",
- "blink/web_input_event_unittest.cc",
- "devices/mojo/device_struct_traits_unittest.cc",
- "gestures/blink/web_gesture_curve_impl_unittest.cc",
- "mojo/struct_traits_unittest.cc",
- ]
- deps += [
- "//cc",
- "//ipc:test_support",
- "//mojo/public/cpp/bindings",
- "//third_party/WebKit/public:blink_headers",
- "//ui/display",
- "//ui/events/blink",
- "//ui/events/devices/mojo:test_interfaces",
- "//ui/events/gestures/blink",
- "//ui/events/mojo:test_interfaces",
- "//ui/gfx/ipc/geometry",
- ]
- }
-
- if (!is_android && !is_ios) {
+ if (is_android) {
+ sources += [ "android/motion_event_android_unittest.cc" ]
+ } else {
data_deps = [
"//third_party/mesa:osmesa",
]
@@ -446,6 +442,10 @@ if (!is_ios) {
]
}
+ if (use_x11 || use_ozone) {
+ sources += [ "devices/device_data_manager_unittest.cc" ]
+ }
+
if (use_ozone) {
sources += [
"ozone/chromeos/cursor_controller_unittest.cc",
@@ -484,14 +484,6 @@ if (!is_ios) {
]
}
- if (is_android) {
- sources += [ "android/motion_event_android_unittest.cc" ]
- }
-
- if (is_ios) {
- assert_no_deps = ios_assert_no_deps
- }
-
if (is_win) {
sources += [ "blink/web_input_event_builders_win_unittest.cc" ]
}
diff --git a/chromium/ui/events/android/motion_event_android.cc b/chromium/ui/events/android/motion_event_android.cc
index 4d458420196..09f030db9be 100644
--- a/chromium/ui/events/android/motion_event_android.cc
+++ b/chromium/ui/events/android/motion_event_android.cc
@@ -209,6 +209,7 @@ MotionEventAndroid::MotionEventAndroid(JNIEnv* env,
jint android_meta_state,
jfloat raw_offset_x_pixels,
jfloat raw_offset_y_pixels,
+ jboolean for_touch_handle,
const Pointer* const pointer0,
const Pointer* const pointer1)
: pix_to_dip_(pix_to_dip),
@@ -216,6 +217,7 @@ MotionEventAndroid::MotionEventAndroid(JNIEnv* env,
ticks_y_(ticks_y),
tick_multiplier_(tick_multiplier),
time_sec_(time_ms / 1000),
+ for_touch_handle_(for_touch_handle),
cached_time_(FromAndroidTime(time_ms)),
cached_action_(FromAndroidAction(android_action)),
cached_pointer_count_(pointer_count),
@@ -246,6 +248,7 @@ MotionEventAndroid::MotionEventAndroid(const MotionEventAndroid& e)
ticks_y_(e.ticks_y_),
tick_multiplier_(e.tick_multiplier_),
time_sec_(e.time_sec_),
+ for_touch_handle_(e.for_touch_handle_),
cached_time_(e.cached_time_),
cached_action_(e.cached_action_),
cached_pointer_count_(e.cached_pointer_count_),
@@ -261,6 +264,22 @@ MotionEventAndroid::MotionEventAndroid(const MotionEventAndroid& e)
cached_pointers_[1] = e.cached_pointers_[1];
}
+// static
+int MotionEventAndroid::GetAndroidActionForTesting(int action) {
+ int android_action = JNI_MotionEvent::ACTION_CANCEL;
+ switch (action) {
+ case ui::MotionEvent::ACTION_DOWN:
+ android_action = JNI_MotionEvent::ACTION_DOWN;
+ break;
+ case ui::MotionEvent::ACTION_UP:
+ android_action = JNI_MotionEvent::ACTION_UP;
+ break;
+ default:
+ NOTIMPLEMENTED() << "Conversion not supported: " << action;
+ }
+ return android_action;
+}
+
std::unique_ptr<MotionEventAndroid> MotionEventAndroid::CreateFor(
const gfx::PointF& point) const {
std::unique_ptr<MotionEventAndroid> event(new MotionEventAndroid(*this));
diff --git a/chromium/ui/events/android/motion_event_android.h b/chromium/ui/events/android/motion_event_android.h
index a208366a6b5..e23d0e5c0af 100644
--- a/chromium/ui/events/android/motion_event_android.h
+++ b/chromium/ui/events/android/motion_event_android.h
@@ -25,6 +25,10 @@ namespace ui {
// while all *output* coordinates are in DIPs (as with WebTouchEvent).
class EVENTS_EXPORT MotionEventAndroid : public MotionEvent {
public:
+ // Returns the motion event action defined in Java layer for a given
+ // MotionEvent::Action.
+ static int GetAndroidActionForTesting(int action);
+
struct Pointer {
Pointer(jint id,
jfloat pos_x_pixels,
@@ -64,6 +68,7 @@ class EVENTS_EXPORT MotionEventAndroid : public MotionEvent {
jint meta_state,
jfloat raw_offset_x_pixels,
jfloat raw_offset_y_pixels,
+ jboolean for_touch_handle,
const Pointer* const pointer0,
const Pointer* const pointer1);
~MotionEventAndroid() override;
@@ -110,6 +115,7 @@ class EVENTS_EXPORT MotionEventAndroid : public MotionEvent {
float ticks_y() const { return ticks_y_; }
float time_sec() const { return time_sec_; }
float GetTickMultiplier() const;
+ bool for_touch_handle() const { return for_touch_handle_; }
base::android::ScopedJavaLocalRef<jobject> GetJavaObject() const;
@@ -139,6 +145,8 @@ class EVENTS_EXPORT MotionEventAndroid : public MotionEvent {
const float tick_multiplier_;
const uint64_t time_sec_;
+ const bool for_touch_handle_;
+
const base::TimeTicks cached_time_;
const Action cached_action_;
const size_t cached_pointer_count_;
diff --git a/chromium/ui/events/android/motion_event_android_unittest.cc b/chromium/ui/events/android/motion_event_android_unittest.cc
index 8c67a9d8674..e71b5790746 100644
--- a/chromium/ui/events/android/motion_event_android_unittest.cc
+++ b/chromium/ui/events/android/motion_event_android_unittest.cc
@@ -66,7 +66,7 @@ TEST(MotionEventAndroidTest, Constructor) {
base::android::AttachCurrentThread(), nullptr, kPixToDip, 0.f, 0.f, 0.f,
event_time_ms, kAndroidActionDown, pointer_count, history_size,
action_index, kAndroidActionButton, kAndroidButtonPrimary,
- kAndroidAltKeyDown, raw_offset, -raw_offset, &p0, &p1);
+ kAndroidAltKeyDown, raw_offset, -raw_offset, false, &p0, &p1);
EXPECT_EQ(MotionEvent::ACTION_DOWN, event.GetAction());
EXPECT_EQ(event_time, event.GetEventTime());
@@ -106,7 +106,8 @@ TEST(MotionEventAndroidTest, Clone) {
1, 13.7f, -7.13f, 5.3f, 1.2f, 0.1f, 0.2f, kAndroidToolTypeFinger);
MotionEventAndroid event(base::android::AttachCurrentThread(), nullptr,
kPixToDip, 0, 0, 0, 0, kAndroidActionDown,
- pointer_count, 0, 0, 0, 0, 0, 0, 0, &p0, nullptr);
+ pointer_count, 0, 0, 0, 0, 0, 0, 0, false, &p0,
+ nullptr);
std::unique_ptr<MotionEvent> clone = event.Clone();
EXPECT_EQ(ui::test::ToString(event), ui::test::ToString(*clone));
@@ -120,7 +121,7 @@ TEST(MotionEventAndroidTest, Cancel) {
MotionEventAndroid event(base::android::AttachCurrentThread(), nullptr,
kPixToDip, 0, 0, 0, event_time_ms,
kAndroidActionDown, pointer_count, 0, 0, 0, 0, 0, 0,
- 0, &p0, nullptr);
+ 0, false, &p0, nullptr);
std::unique_ptr<MotionEvent> cancel_event = event.Cancel();
EXPECT_EQ(MotionEvent::ACTION_CANCEL, cancel_event->GetAction());
@@ -142,7 +143,7 @@ TEST(MotionEventAndroidTest, InvalidOrientationsSanitized) {
MotionEventAndroid::Pointer p1(1, 0, 0, 0, 0, orientation1, 0, 0);
MotionEventAndroid event(base::android::AttachCurrentThread(), nullptr,
kPixToDip, 0, 0, 0, 0, kAndroidActionDown,
- pointer_count, 0, 0, 0, 0, 0, 0, 0, &p0, &p1);
+ pointer_count, 0, 0, 0, 0, 0, 0, 0, false, &p0, &p1);
EXPECT_EQ(0.f, event.GetOrientation(0));
EXPECT_EQ(0.f, event.GetOrientation(1));
@@ -154,8 +155,8 @@ TEST(MotionEventAndroidTest, NonEmptyHistoryForNonMoveEventsSanitized) {
MotionEventAndroid::Pointer p0(0, 0, 0, 0, 0, 0, 0, 0);
MotionEventAndroid event(base::android::AttachCurrentThread(), nullptr,
kPixToDip, 0, 0, 0, 0, kAndroidActionDown,
- pointer_count, history_size, 0, 0, 0, 0, 0, 0, &p0,
- nullptr);
+ pointer_count, history_size, 0, 0, 0, 0, 0, 0, false,
+ &p0, nullptr);
EXPECT_EQ(0U, event.GetHistorySize());
}
@@ -171,7 +172,7 @@ TEST(MotionEventAndroidTest, ActionIndexForPointerDown) {
MotionEventAndroid event(base::android::AttachCurrentThread(), nullptr,
kPixToDip, 0, 0, 0, 0, kAndroidActionPointerDown,
pointer_count, history_size, action_index, 0, 0, 0,
- 0, 0, &p0, &p1);
+ 0, 0, false, &p0, &p1);
EXPECT_EQ(MotionEvent::ACTION_POINTER_DOWN, event.GetAction());
EXPECT_EQ(action_index, event.GetActionIndex());
diff --git a/chromium/ui/events/android/scroller.cc b/chromium/ui/events/android/scroller.cc
index 1375f3f02f5..32835f140a1 100644
--- a/chromium/ui/events/android/scroller.cc
+++ b/chromium/ui/events/android/scroller.cc
@@ -227,7 +227,7 @@ void Scroller::StartScroll(float start_x,
float dy,
base::TimeTicks start_time,
base::TimeDelta duration) {
- DCHECK_GT(duration.ToInternalValue(), 0);
+ DCHECK_GT(duration, base::TimeDelta());
mode_ = SCROLL_MODE;
finished_ = false;
duration_ = duration;
@@ -270,7 +270,7 @@ void Scroller::Fling(float start_x,
velocity_ = velocity;
duration_ = GetSplineFlingDuration(velocity);
- DCHECK_GT(duration_.ToInternalValue(), 0);
+ DCHECK_GT(duration_, base::TimeDelta());
duration_seconds_reciprocal_ = 1.0 / duration_.InSecondsF();
start_time_ = start_time;
curr_time_ = start_time_;
diff --git a/chromium/ui/events/blink/DEPS b/chromium/ui/events/blink/DEPS
index 38bfc42275f..1c63c5bab93 100644
--- a/chromium/ui/events/blink/DEPS
+++ b/chromium/ui/events/blink/DEPS
@@ -1,6 +1,7 @@
include_rules = [
"+cc/input/input_handler.h",
"+cc/input/main_thread_scrolling_reason.h",
+ "+cc/input/scroll_boundary_behavior.h",
"+cc/input/scroll_elasticity_helper.h",
"+cc/trees/swap_promise_monitor.h",
diff --git a/chromium/ui/events/blink/did_overscroll_params.h b/chromium/ui/events/blink/did_overscroll_params.h
index 46eeb15d1a5..9c3ea4b186d 100644
--- a/chromium/ui/events/blink/did_overscroll_params.h
+++ b/chromium/ui/events/blink/did_overscroll_params.h
@@ -5,6 +5,7 @@
#ifndef UI_EVENTS_BLINK_DID_OVERSCROLL_PARAMS_H_
#define UI_EVENTS_BLINK_DID_OVERSCROLL_PARAMS_H_
+#include "cc/input/scroll_boundary_behavior.h"
#include "ui/gfx/geometry/point_f.h"
#include "ui/gfx/geometry/vector2d_f.h"
@@ -17,6 +18,7 @@ struct DidOverscrollParams {
gfx::Vector2dF latest_overscroll_delta;
gfx::Vector2dF current_fling_velocity;
gfx::PointF causal_event_viewport_point;
+ cc::ScrollBoundaryBehavior scroll_boundary_behavior;
};
} // namespace ui
diff --git a/chromium/ui/events/blink/event_with_callback.cc b/chromium/ui/events/blink/event_with_callback.cc
index 39793f4e67e..132e0819b0f 100644
--- a/chromium/ui/events/blink/event_with_callback.cc
+++ b/chromium/ui/events/blink/event_with_callback.cc
@@ -72,15 +72,28 @@ void EventWithCallback::RunCallbacks(
InputHandlerProxy::EventDisposition disposition,
const LatencyInfo& latency,
std::unique_ptr<DidOverscrollParams> did_overscroll_params) {
- for (auto& original_event : original_events_) {
- std::unique_ptr<DidOverscrollParams> did_overscroll_params_copy;
- if (did_overscroll_params) {
- did_overscroll_params_copy =
- base::MakeUnique<DidOverscrollParams>(*did_overscroll_params);
- }
- std::move(original_event.callback_)
- .Run(disposition, std::move(original_event.event_), latency,
- std::move(did_overscroll_params));
+ // |original_events_| could be empty if this is the scroll event extracted
+ // from the matrix multiplication.
+ if (original_events_.size() == 0)
+ return;
+
+ // Ack the oldest event with original latency.
+ std::move(original_events_.front().callback_)
+ .Run(disposition, std::move(original_events_.front().event_), latency,
+ did_overscroll_params
+ ? base::MakeUnique<DidOverscrollParams>(*did_overscroll_params)
+ : nullptr);
+ original_events_.pop_front();
+
+ // Ack other events with coalesced latency to avoid redundant tracking.
+ LatencyInfo coalesced_latency = latency;
+ coalesced_latency.set_coalesced();
+ for (auto& coalesced_event : original_events_) {
+ std::move(coalesced_event.callback_)
+ .Run(disposition, std::move(coalesced_event.event_), coalesced_latency,
+ did_overscroll_params
+ ? base::MakeUnique<DidOverscrollParams>(*did_overscroll_params)
+ : nullptr);
}
}
diff --git a/chromium/ui/events/blink/input_handler_proxy.cc b/chromium/ui/events/blink/input_handler_proxy.cc
index d5c3e54b49a..e79247fd1c2 100644
--- a/chromium/ui/events/blink/input_handler_proxy.cc
+++ b/chromium/ui/events/blink/input_handler_proxy.cc
@@ -175,59 +175,6 @@ cc::ScrollState CreateScrollStateForGesture(const WebGestureEvent& event) {
return cc::ScrollState(scroll_state_data);
}
-void ReportInputEventLatencyUma(const WebInputEvent& event,
- const ui::LatencyInfo& latency_info) {
- if (!(event.GetType() == WebInputEvent::kGestureScrollBegin ||
- event.GetType() == WebInputEvent::kGestureScrollUpdate ||
- event.GetType() == WebInputEvent::kGesturePinchBegin ||
- event.GetType() == WebInputEvent::kGesturePinchUpdate ||
- event.GetType() == WebInputEvent::kGestureFlingStart)) {
- return;
- }
-
- ui::LatencyInfo::LatencyMap::const_iterator it =
- latency_info.latency_components().find(std::make_pair(
- ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0));
-
- if (it == latency_info.latency_components().end())
- return;
-
- base::TimeDelta delta = base::TimeTicks::Now() - it->second.event_time;
- for (size_t i = 0; i < it->second.event_count; ++i) {
- switch (event.GetType()) {
- case blink::WebInputEvent::kGestureScrollBegin:
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Event.Latency.RendererImpl.GestureScrollBegin",
- delta.InMicroseconds(), 1, 1000000, 100);
- break;
- case blink::WebInputEvent::kGestureScrollUpdate:
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- // So named for historical reasons.
- "Event.Latency.RendererImpl.GestureScroll2",
- delta.InMicroseconds(), 1, 1000000, 100);
- break;
- case blink::WebInputEvent::kGesturePinchBegin:
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Event.Latency.RendererImpl.GesturePinchBegin",
- delta.InMicroseconds(), 1, 1000000, 100);
- break;
- case blink::WebInputEvent::kGesturePinchUpdate:
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Event.Latency.RendererImpl.GesturePinchUpdate",
- delta.InMicroseconds(), 1, 1000000, 100);
- break;
- case blink::WebInputEvent::kGestureFlingStart:
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Event.Latency.RendererImpl.GestureFlingStart",
- delta.InMicroseconds(), 1, 1000000, 100);
- break;
- default:
- NOTREACHED();
- break;
- }
- }
-}
-
cc::InputHandler::ScrollInputType GestureScrollInputType(
blink::WebGestureDevice device) {
return device == blink::kWebGestureDeviceTouchpad
@@ -266,7 +213,6 @@ InputHandlerProxy::InputHandlerProxy(
disallow_vertical_fling_scroll_(false),
has_fling_animation_started_(false),
smooth_scroll_enabled_(false),
- uma_latency_reporting_enabled_(base::TimeTicks::IsHighResolution()),
touchpad_and_wheel_scroll_latching_enabled_(
touchpad_and_wheel_scroll_latching_enabled),
touch_result_(kEventDispositionUndefined),
@@ -303,9 +249,6 @@ void InputHandlerProxy::HandleInputEventWithLatencyInfo(
EventDispositionCallback callback) {
DCHECK(input_handler_);
- if (uma_latency_reporting_enabled_)
- ReportInputEventLatencyUma(*event, latency_info);
-
TRACE_EVENT_WITH_FLOW1("input,benchmark", "LatencyInfo.Flow",
TRACE_ID_DONT_MANGLE(latency_info.trace_id()),
TRACE_EVENT_FLAG_FLOW_IN | TRACE_EVENT_FLAG_FLOW_OUT,
@@ -889,7 +832,10 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureScrollBegin(
"InputHandlerProxy::handle_input gesture scroll",
TRACE_EVENT_SCOPE_THREAD);
gesture_scroll_on_impl_thread_ = true;
- result = DID_HANDLE;
+ if (scroll_status.bubble)
+ result = DID_HANDLE_SHOULD_BUBBLE;
+ else
+ result = DID_HANDLE;
break;
case cc::InputHandler::SCROLL_UNKNOWN:
case cc::InputHandler::SCROLL_ON_MAIN_THREAD:
@@ -1043,7 +989,6 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleGestureFlingStart(
const float vx = gesture_event.data.fling_start.velocity_x;
const float vy = gesture_event.data.fling_start.velocity_y;
current_fling_velocity_ = gfx::Vector2dF(vx, vy);
- DCHECK(!current_fling_velocity_.IsZero());
fling_curve_ = client_->CreateFlingAnimationCurve(
gesture_event.source_device, WebFloatPoint(vx, vy), blink::WebSize());
disallow_horizontal_fling_scroll_ = !vx;
@@ -1171,7 +1116,6 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleTouchStart(
cc::TouchAction white_listed_touch_action = cc::kTouchActionAuto;
EventDisposition result = HitTestTouchEvent(
touch_event, &is_touching_scrolling_layer, &white_listed_touch_action);
- client_->SetWhiteListedTouchAction(white_listed_touch_action);
// If |result| is still DROP_EVENT look at the touch end handler as
// we may not want to discard the entire touch sequence. Note this
@@ -1189,6 +1133,9 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleTouchStart(
if (is_flinging_on_impl && is_touching_scrolling_layer)
result = DID_NOT_HANDLE_NON_BLOCKING_DUE_TO_FLING;
+ client_->SetWhiteListedTouchAction(white_listed_touch_action,
+ touch_event.unique_touch_event_id, result);
+
return result;
}
@@ -1202,7 +1149,8 @@ InputHandlerProxy::EventDisposition InputHandlerProxy::HandleTouchMove(
cc::TouchAction white_listed_touch_action = cc::kTouchActionAuto;
EventDisposition result = HitTestTouchEvent(
touch_event, &is_touching_scrolling_layer, &white_listed_touch_action);
- client_->SetWhiteListedTouchAction(white_listed_touch_action);
+ client_->SetWhiteListedTouchAction(
+ white_listed_touch_action, touch_event.unique_touch_event_id, result);
return result;
}
return static_cast<EventDisposition>(touch_result_);
@@ -1513,13 +1461,16 @@ void InputHandlerProxy::HandleOverscroll(
ToClientScrollIncrement(current_fling_velocity_);
current_overscroll_params_->causal_event_viewport_point =
gfx::PointF(causal_event_viewport_point);
+ current_overscroll_params_->scroll_boundary_behavior =
+ scroll_result.scroll_boundary_behavior;
return;
}
client_->DidOverscroll(scroll_result.accumulated_root_overscroll,
scroll_result.unused_scroll_delta,
ToClientScrollIncrement(current_fling_velocity_),
- gfx::PointF(causal_event_viewport_point));
+ gfx::PointF(causal_event_viewport_point),
+ scroll_result.scroll_boundary_behavior);
}
bool InputHandlerProxy::CancelCurrentFling() {
@@ -1645,6 +1596,7 @@ bool InputHandlerProxy::TouchpadFlingScroll(
CancelCurrentFlingWithoutNotifyingClient();
break;
case DID_NOT_HANDLE_NON_BLOCKING_DUE_TO_FLING:
+ case DID_HANDLE_SHOULD_BUBBLE:
NOTREACHED();
return false;
}
diff --git a/chromium/ui/events/blink/input_handler_proxy.h b/chromium/ui/events/blink/input_handler_proxy.h
index 2d3a93fea35..c8a0f0972d0 100644
--- a/chromium/ui/events/blink/input_handler_proxy.h
+++ b/chromium/ui/events/blink/input_handler_proxy.h
@@ -48,10 +48,9 @@ struct DidOverscrollParams;
// the compositor's input handling logic. InputHandlerProxy instances live
// entirely on the compositor thread. Each InputHandler instance handles input
// events intended for a specific WebWidget.
-class InputHandlerProxy
- : public cc::InputHandlerClient,
- public SynchronousInputHandlerProxy,
- public NON_EXPORTED_BASE(blink::WebGestureCurveTarget) {
+class InputHandlerProxy : public cc::InputHandlerClient,
+ public SynchronousInputHandlerProxy,
+ public blink::WebGestureCurveTarget {
public:
InputHandlerProxy(cc::InputHandler* input_handler,
InputHandlerProxyClient* client,
@@ -69,7 +68,12 @@ class InputHandlerProxy
DID_NOT_HANDLE,
DID_NOT_HANDLE_NON_BLOCKING_DUE_TO_FLING,
DID_HANDLE_NON_BLOCKING,
- DROP_EVENT
+ DROP_EVENT,
+ // The compositor did handle the scroll event (so it wouldn't forward the
+ // event to the main thread.) but it didn't consume the scroll so it should
+ // pass it to the next consumer (either overscrolling or bubbling the event
+ // to the next renderer).
+ DID_HANDLE_SHOULD_BUBBLE,
};
using EventDispositionCallback =
base::OnceCallback<void(EventDisposition,
@@ -247,7 +251,6 @@ class InputHandlerProxy
scroll_elasticity_controller_;
bool smooth_scroll_enabled_;
- bool uma_latency_reporting_enabled_;
const bool touchpad_and_wheel_scroll_latching_enabled_;
// The merged result of the last touch event with previous touch events.
diff --git a/chromium/ui/events/blink/input_handler_proxy_client.h b/chromium/ui/events/blink/input_handler_proxy_client.h
index ee17a9f546e..6cefb93c4ce 100644
--- a/chromium/ui/events/blink/input_handler_proxy_client.h
+++ b/chromium/ui/events/blink/input_handler_proxy_client.h
@@ -49,7 +49,8 @@ class InputHandlerProxyClient {
const gfx::Vector2dF& accumulated_overscroll,
const gfx::Vector2dF& latest_overscroll_delta,
const gfx::Vector2dF& current_fling_velocity,
- const gfx::PointF& causal_event_viewport_point) = 0;
+ const gfx::PointF& causal_event_viewport_point,
+ const cc::ScrollBoundaryBehavior& scroll_boundary_behavior) = 0;
virtual void DidStopFlinging() = 0;
@@ -60,7 +61,10 @@ class InputHandlerProxyClient {
virtual void GenerateScrollBeginAndSendToMainThread(
const blink::WebGestureEvent& update_event) = 0;
- virtual void SetWhiteListedTouchAction(cc::TouchAction touch_action) = 0;
+ virtual void SetWhiteListedTouchAction(
+ cc::TouchAction touch_action,
+ uint32_t unique_touch_event_id,
+ InputHandlerProxy::EventDisposition event_disposition) = 0;
protected:
virtual ~InputHandlerProxyClient() {}
diff --git a/chromium/ui/events/blink/input_handler_proxy_unittest.cc b/chromium/ui/events/blink/input_handler_proxy_unittest.cc
index 7de08a08f45..8ccb5e56461 100644
--- a/chromium/ui/events/blink/input_handler_proxy_unittest.cc
+++ b/chromium/ui/events/blink/input_handler_proxy_unittest.cc
@@ -312,14 +312,19 @@ class MockInputHandlerProxyClient
blink::WebFloatSize(cumulative_scroll.width, cumulative_scroll.height));
}
- MOCK_METHOD4(DidOverscroll,
- void(const gfx::Vector2dF& accumulated_overscroll,
- const gfx::Vector2dF& latest_overscroll_delta,
- const gfx::Vector2dF& current_fling_velocity,
- const gfx::PointF& causal_event_viewport_point));
+ MOCK_METHOD5(
+ DidOverscroll,
+ void(const gfx::Vector2dF& accumulated_overscroll,
+ const gfx::Vector2dF& latest_overscroll_delta,
+ const gfx::Vector2dF& current_fling_velocity,
+ const gfx::PointF& causal_event_viewport_point,
+ const cc::ScrollBoundaryBehavior& scroll_boundary_behavior));
void DidStopFlinging() override {}
void DidAnimateForInput() override {}
- MOCK_METHOD1(SetWhiteListedTouchAction, void(cc::TouchAction touch_action));
+ MOCK_METHOD3(SetWhiteListedTouchAction,
+ void(cc::TouchAction touch_action,
+ uint32_t unique_touch_event_id,
+ InputHandlerProxy::EventDisposition event_disposition));
private:
DISALLOW_COPY_AND_ASSIGN(MockInputHandlerProxyClient);
@@ -538,6 +543,7 @@ class InputHandlerProxyEventQueueTest : public testing::TestWithParam<bool> {
void SetUp() override {
bool wheel_scroll_latching_enabled = GetParam();
event_disposition_recorder_.clear();
+ latency_info_recorder_.clear();
input_handler_proxy_ = base::MakeUnique<TestInputHandlerProxy>(
&mock_input_handler_, &mock_client_, wheel_scroll_latching_enabled);
if (input_handler_proxy_->compositor_event_queue_)
@@ -600,6 +606,7 @@ class InputHandlerProxyEventQueueTest : public testing::TestWithParam<bool> {
const ui::LatencyInfo& latency_info,
std::unique_ptr<ui::DidOverscrollParams> overscroll_params) {
event_disposition_recorder_.push_back(event_disposition);
+ latency_info_recorder_.push_back(latency_info);
}
std::deque<std::unique_ptr<EventWithCallback>>& event_queue() {
@@ -617,6 +624,7 @@ class InputHandlerProxyEventQueueTest : public testing::TestWithParam<bool> {
std::unique_ptr<TestInputHandlerProxy> input_handler_proxy_;
testing::StrictMock<MockInputHandlerProxyClient> mock_client_;
std::vector<InputHandlerProxy::EventDisposition> event_disposition_recorder_;
+ std::vector<ui::LatencyInfo> latency_info_recorder_;
base::MessageLoop loop_;
base::WeakPtrFactory<InputHandlerProxyEventQueueTest> weak_ptr_factory_;
@@ -773,6 +781,8 @@ TEST_P(InputHandlerProxyTest, GestureScrollIgnored) {
gesture_.SetType(WebInputEvent::kGestureScrollBegin);
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+ VERIFY_AND_RESET_MOCKS();
+
// GSB is dropped and not sent to the main thread, GSE shouldn't get sent to
// the main thread, either.
expected_disposition_ = InputHandlerProxy::DROP_EVENT;
@@ -782,6 +792,12 @@ TEST_P(InputHandlerProxyTest, GestureScrollIgnored) {
EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
VERIFY_AND_RESET_MOCKS();
+
+ expected_disposition_ = InputHandlerProxy::DROP_EVENT;
+ gesture_.SetType(WebInputEvent::kGestureFlingStart);
+ EXPECT_EQ(expected_disposition_, input_handler_->HandleInputEvent(gesture_));
+
+ VERIFY_AND_RESET_MOCKS();
}
TEST_P(InputHandlerProxyTest, GestureScrollByPage) {
@@ -2225,11 +2241,10 @@ void InputHandlerProxyTest::GestureFlingStopsAtContentEdge() {
.WillOnce(testing::Return(overscroll));
EXPECT_CALL(
mock_client_,
- DidOverscroll(
- overscroll.accumulated_root_overscroll,
- overscroll.unused_scroll_delta,
- testing::Property(&gfx::Vector2dF::y, testing::Lt(0)),
- testing::_));
+ DidOverscroll(overscroll.accumulated_root_overscroll,
+ overscroll.unused_scroll_delta,
+ testing::Property(&gfx::Vector2dF::y, testing::Lt(0)),
+ testing::_, overscroll.scroll_boundary_behavior));
if (!touchpad_and_wheel_scroll_latching_enabled_)
EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_));
EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
@@ -2390,11 +2405,10 @@ TEST_P(InputHandlerProxyTest, GestureFlingCancelledAfterBothAxesStopScrolling) {
.WillOnce(testing::Return(overscroll));
EXPECT_CALL(
mock_client_,
- DidOverscroll(
- overscroll.accumulated_root_overscroll,
- overscroll.unused_scroll_delta,
- testing::Property(&gfx::Vector2dF::y, testing::Lt(0)),
- testing::_));
+ DidOverscroll(overscroll.accumulated_root_overscroll,
+ overscroll.unused_scroll_delta,
+ testing::Property(&gfx::Vector2dF::y, testing::Lt(0)),
+ testing::_, overscroll.scroll_boundary_behavior));
EXPECT_SET_NEEDS_ANIMATE_INPUT(1);
time += base::TimeDelta::FromMilliseconds(10);
Animate(time);
@@ -2419,11 +2433,10 @@ TEST_P(InputHandlerProxyTest, GestureFlingCancelledAfterBothAxesStopScrolling) {
.WillOnce(testing::Return(overscroll));
EXPECT_CALL(
mock_client_,
- DidOverscroll(
- overscroll.accumulated_root_overscroll,
- overscroll.unused_scroll_delta,
- testing::Property(&gfx::Vector2dF::x, testing::Lt(0)),
- testing::_));
+ DidOverscroll(overscroll.accumulated_root_overscroll,
+ overscroll.unused_scroll_delta,
+ testing::Property(&gfx::Vector2dF::x, testing::Lt(0)),
+ testing::_, overscroll.scroll_boundary_behavior));
EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_));
time += base::TimeDelta::FromMilliseconds(10);
Animate(time);
@@ -2550,12 +2563,15 @@ TEST_P(InputHandlerProxyTest, MultiTouchPointHitTestNegative) {
*touch_action = cc::kTouchActionPanUp;
return cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER;
}));
- EXPECT_CALL(mock_client_, SetWhiteListedTouchAction(cc::kTouchActionPanUp))
+ EXPECT_CALL(mock_client_,
+ SetWhiteListedTouchAction(cc::kTouchActionPanUp, 1,
+ InputHandlerProxy::DROP_EVENT))
.WillOnce(testing::Return());
WebTouchEvent touch(WebInputEvent::kTouchStart, WebInputEvent::kNoModifiers,
WebInputEvent::kTimeStampForTesting);
+ touch.unique_touch_event_id = 1;
touch.touches_length = 3;
touch.touch_start_or_first_touch_move = true;
touch.touches[0] = CreateWebTouchPoint(WebTouchPoint::kStateStationary, 0, 0);
@@ -2591,7 +2607,9 @@ TEST_P(InputHandlerProxyTest, MultiTouchPointHitTestPositive) {
return cc::InputHandler::TouchStartOrMoveEventListenerType::
HANDLER_ON_SCROLLING_LAYER;
}));
- EXPECT_CALL(mock_client_, SetWhiteListedTouchAction(cc::kTouchActionPanY))
+ EXPECT_CALL(mock_client_,
+ SetWhiteListedTouchAction(cc::kTouchActionPanY, 1,
+ InputHandlerProxy::DID_NOT_HANDLE))
.WillOnce(testing::Return());
// Since the second touch point hits a touch-region, there should be no
// hit-testing for the third touch point.
@@ -2599,6 +2617,7 @@ TEST_P(InputHandlerProxyTest, MultiTouchPointHitTestPositive) {
WebTouchEvent touch(WebInputEvent::kTouchStart, WebInputEvent::kNoModifiers,
WebInputEvent::kTimeStampForTesting);
+ touch.unique_touch_event_id = 1;
touch.touches_length = 3;
touch.touch_start_or_first_touch_move = true;
touch.touches[0] = CreateWebTouchPoint(WebTouchPoint::kStatePressed, 0, 0);
@@ -2632,12 +2651,15 @@ TEST_P(InputHandlerProxyTest, MultiTouchPointHitTestPassivePositive) {
*touch_action = cc::kTouchActionPanX;
return cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER;
}));
- EXPECT_CALL(mock_client_, SetWhiteListedTouchAction(cc::kTouchActionPanRight))
+ EXPECT_CALL(mock_client_, SetWhiteListedTouchAction(
+ cc::kTouchActionPanRight, 1,
+ InputHandlerProxy::DID_HANDLE_NON_BLOCKING))
.WillOnce(testing::Return());
WebTouchEvent touch(WebInputEvent::kTouchStart, WebInputEvent::kNoModifiers,
WebInputEvent::kTimeStampForTesting);
+ touch.unique_touch_event_id = 1;
touch.touches_length = 3;
touch.touch_start_or_first_touch_move = true;
touch.touches[0] = CreateWebTouchPoint(WebTouchPoint::kStatePressed, 0, 0);
@@ -2670,11 +2692,14 @@ TEST_P(InputHandlerProxyTest, TouchStartPassiveAndTouchEndBlocking) {
*touch_action = cc::kTouchActionNone;
return cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER;
}));
- EXPECT_CALL(mock_client_, SetWhiteListedTouchAction(cc::kTouchActionNone))
+ EXPECT_CALL(mock_client_, SetWhiteListedTouchAction(
+ cc::kTouchActionNone, 1,
+ InputHandlerProxy::DID_HANDLE_NON_BLOCKING))
.WillOnce(testing::Return());
WebTouchEvent touch(WebInputEvent::kTouchStart, WebInputEvent::kNoModifiers,
WebInputEvent::kTimeStampForTesting);
+ touch.unique_touch_event_id = 1;
touch.touches_length = 1;
touch.touches[0] = CreateWebTouchPoint(WebTouchPoint::kStatePressed, 0, 0);
touch.touch_start_or_first_touch_move = true;
@@ -2703,7 +2728,8 @@ TEST_P(InputHandlerProxyTest, TouchMoveBlockingAddedAfterPassiveTouchStart) {
EventListenerTypeForTouchStartOrMoveAt(testing::_, testing::_))
.WillOnce(testing::Return(
cc::InputHandler::TouchStartOrMoveEventListenerType::NO_HANDLER));
- EXPECT_CALL(mock_client_, SetWhiteListedTouchAction(testing::_))
+ EXPECT_CALL(mock_client_,
+ SetWhiteListedTouchAction(testing::_, testing::_, testing::_))
.WillOnce(testing::Return());
WebTouchEvent touch(WebInputEvent::kTouchStart, WebInputEvent::kNoModifiers,
@@ -2718,7 +2744,8 @@ TEST_P(InputHandlerProxyTest, TouchMoveBlockingAddedAfterPassiveTouchStart) {
EventListenerTypeForTouchStartOrMoveAt(testing::_, testing::_))
.WillOnce(testing::Return(
cc::InputHandler::TouchStartOrMoveEventListenerType::HANDLER));
- EXPECT_CALL(mock_client_, SetWhiteListedTouchAction(testing::_))
+ EXPECT_CALL(mock_client_,
+ SetWhiteListedTouchAction(testing::_, testing::_, testing::_))
.WillOnce(testing::Return());
touch.SetType(WebInputEvent::kTouchMove);
@@ -3518,7 +3545,8 @@ TEST_P(InputHandlerProxyTest, GestureScrollingThreadStatusHistogram) {
mock_input_handler_,
GetEventListenerProperties(cc::EventListenerClass::kTouchStartOrMove))
.WillOnce(testing::Return(cc::EventListenerProperties::kPassive));
- EXPECT_CALL(mock_client_, SetWhiteListedTouchAction(testing::_))
+ EXPECT_CALL(mock_client_,
+ SetWhiteListedTouchAction(testing::_, testing::_, testing::_))
.WillOnce(testing::Return());
expected_disposition_ = InputHandlerProxy::DID_HANDLE_NON_BLOCKING;
@@ -3550,7 +3578,8 @@ TEST_P(InputHandlerProxyTest, GestureScrollingThreadStatusHistogram) {
.WillOnce(
testing::Return(cc::InputHandler::TouchStartOrMoveEventListenerType::
HANDLER_ON_SCROLLING_LAYER));
- EXPECT_CALL(mock_client_, SetWhiteListedTouchAction(testing::_))
+ EXPECT_CALL(mock_client_,
+ SetWhiteListedTouchAction(testing::_, testing::_, testing::_))
.WillOnce(testing::Return());
expected_disposition_ = InputHandlerProxy::DID_NOT_HANDLE;
@@ -4103,6 +4132,38 @@ TEST_P(InputHandlerProxyEventQueueTest, TouchpadGestureScrollEndFlushQueue) {
input_handler_proxy_->gesture_scroll_on_impl_thread_for_testing());
}
+TEST_P(InputHandlerProxyEventQueueTest, CoalescedLatencyInfo) {
+ // Handle scroll on compositor.
+ cc::InputHandlerScrollResult scroll_result_did_scroll_;
+ scroll_result_did_scroll_.did_scroll = true;
+
+ EXPECT_CALL(mock_input_handler_, ScrollBegin(testing::_, testing::_))
+ .WillOnce(testing::Return(kImplThreadScrollState));
+ EXPECT_CALL(mock_input_handler_, SetNeedsAnimateInput()).Times(1);
+ EXPECT_CALL(
+ mock_input_handler_,
+ ScrollBy(testing::Property(&cc::ScrollState::delta_y, testing::Gt(0))))
+ .WillOnce(testing::Return(scroll_result_did_scroll_));
+ EXPECT_CALL(mock_input_handler_, ScrollEnd(testing::_));
+
+ HandleGestureEvent(WebInputEvent::kGestureScrollBegin);
+ HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -20);
+ HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -40);
+ HandleGestureEvent(WebInputEvent::kGestureScrollUpdate, -30);
+ HandleGestureEvent(WebInputEvent::kGestureScrollEnd);
+ input_handler_proxy_->DeliverInputForBeginFrame();
+
+ EXPECT_EQ(0ul, event_queue().size());
+ // Should run callbacks for every original events.
+ EXPECT_EQ(5ul, event_disposition_recorder_.size());
+ EXPECT_EQ(5ul, latency_info_recorder_.size());
+ EXPECT_EQ(false, latency_info_recorder_[1].coalesced());
+ // Coalesced events should have latency set to coalesced.
+ EXPECT_EQ(true, latency_info_recorder_[2].coalesced());
+ EXPECT_EQ(true, latency_info_recorder_[3].coalesced());
+ testing::Mock::VerifyAndClearExpectations(&mock_input_handler_);
+}
+
INSTANTIATE_TEST_CASE_P(AnimateInput,
InputHandlerProxyTest,
testing::ValuesIn(test_types));
diff --git a/chromium/ui/events/blink/input_scroll_elasticity_controller_unittest.cc b/chromium/ui/events/blink/input_scroll_elasticity_controller_unittest.cc
index 6f239d2790f..df552c39d22 100644
--- a/chromium/ui/events/blink/input_scroll_elasticity_controller_unittest.cc
+++ b/chromium/ui/events/blink/input_scroll_elasticity_controller_unittest.cc
@@ -83,7 +83,8 @@ class ScrollElasticityControllerTest : public testing::Test {
ScrollElasticityControllerTest()
: controller_(&helper_),
input_event_count_(0),
- current_time_(base::TimeTicks::FromInternalValue(100000000ull)) {}
+ current_time_(base::TimeTicks() +
+ base::TimeDelta::FromMicroseconds(INT64_C(100000000))) {}
~ScrollElasticityControllerTest() override {}
diff --git a/chromium/ui/events/devices/BUILD.gn b/chromium/ui/events/devices/BUILD.gn
index ca8c4e80cb2..5913ef1acb0 100644
--- a/chromium/ui/events/devices/BUILD.gn
+++ b/chromium/ui/events/devices/BUILD.gn
@@ -25,6 +25,8 @@ component("devices") {
"input_device_observer_win.cc",
"input_device_observer_win.h",
"stylus_state.h",
+ "touch_device_transform.cc",
+ "touch_device_transform.h",
"touchscreen_device.cc",
"touchscreen_device.h",
]
@@ -32,6 +34,7 @@ component("devices") {
defines = [ "EVENTS_DEVICES_IMPLEMENTATION" ]
public_deps = [
+ "//ui/display/types",
"//ui/gfx",
]
@@ -39,7 +42,7 @@ component("devices") {
"//base",
"//base/third_party/dynamic_annotations",
"//skia",
- "//ui/display/types",
+ "//ui/gfx:geometry_skia",
"//ui/gfx/geometry",
]
diff --git a/chromium/ui/events/devices/device_data_manager.cc b/chromium/ui/events/devices/device_data_manager.cc
index d66744f3b13..86b8ebd0dad 100644
--- a/chromium/ui/events/devices/device_data_manager.cc
+++ b/chromium/ui/events/devices/device_data_manager.cc
@@ -9,6 +9,7 @@
#include "base/logging.h"
#include "ui/display/types/display_constants.h"
#include "ui/events/devices/input_device_event_observer.h"
+#include "ui/events/devices/touch_device_transform.h"
#include "ui/gfx/geometry/point3_f.h"
// This macro provides the implementation for the observer notification methods.
@@ -28,16 +29,6 @@ bool InputDeviceEquals(const ui::InputDevice& a, const ui::InputDevice& b) {
} // namespace
-DeviceDataManager::TouchscreenInfo::TouchscreenInfo() {
- Reset();
-}
-
-void DeviceDataManager::TouchscreenInfo::Reset() {
- radius_scale = 1.0;
- target_display = display::kInvalidDisplayId;
- device_transform = gfx::Transform();
-}
-
// static
DeviceDataManager* DeviceDataManager::instance_ = nullptr;
@@ -50,9 +41,6 @@ DeviceDataManager::~DeviceDataManager() {
}
// static
-DeviceDataManager* DeviceDataManager::instance() { return instance_; }
-
-// static
void DeviceDataManager::set_instance(DeviceDataManager* instance) {
DCHECK(instance)
<< "Must reset the DeviceDataManager using DeleteInstance().";
@@ -62,7 +50,7 @@ void DeviceDataManager::set_instance(DeviceDataManager* instance) {
// static
void DeviceDataManager::CreateInstance() {
- if (instance())
+ if (instance_)
return;
set_instance(new DeviceDataManager());
@@ -90,30 +78,40 @@ bool DeviceDataManager::HasInstance() {
return instance_ != nullptr;
}
-void DeviceDataManager::ClearTouchDeviceAssociations() {
- for (auto& touch_info : touch_map_)
- touch_info.Reset();
+void DeviceDataManager::ConfigureTouchDevices(
+ const std::vector<ui::TouchDeviceTransform>& transforms) {
+ ClearTouchDeviceAssociations();
+ for (const TouchDeviceTransform& transform : transforms)
+ UpdateTouchInfoFromTransform(transform);
+ are_touchscreen_target_displays_valid_ = true;
+ for (InputDeviceEventObserver& observer : observers_)
+ observer.OnTouchDeviceAssociationChanged();
}
-bool DeviceDataManager::IsTouchDeviceIdValid(
- int touch_device_id) const {
- return (touch_device_id > 0 && touch_device_id < kMaxDeviceNum);
+void DeviceDataManager::ClearTouchDeviceAssociations() {
+ for (size_t i = 0; i < touch_map_.size(); ++i)
+ touch_map_[i] = TouchDeviceTransform();
+ for (TouchscreenDevice& touchscreen_device : touchscreen_devices_)
+ touchscreen_device.target_display_id = display::kInvalidDisplayId;
}
-void DeviceDataManager::UpdateTouchInfoForDisplay(
- int64_t target_display_id,
- int touch_device_id,
- const gfx::Transform& touch_transformer) {
- if (IsTouchDeviceIdValid(touch_device_id)) {
- touch_map_[touch_device_id].target_display = target_display_id;
- touch_map_[touch_device_id].device_transform = touch_transformer;
+void DeviceDataManager::UpdateTouchInfoFromTransform(
+ const ui::TouchDeviceTransform& touch_device_transform) {
+ if (!IsTouchDeviceIdValid(touch_device_transform.device_id))
+ return;
+
+ touch_map_[touch_device_transform.device_id] = touch_device_transform;
+
+ for (TouchscreenDevice& touchscreen_device : touchscreen_devices_) {
+ if (touchscreen_device.id == touch_device_transform.device_id) {
+ touchscreen_device.target_display_id = touch_device_transform.display_id;
+ return;
+ }
}
}
-void DeviceDataManager::UpdateTouchRadiusScale(int touch_device_id,
- double scale) {
- if (IsTouchDeviceIdValid(touch_device_id))
- touch_map_[touch_device_id].radius_scale = scale;
+bool DeviceDataManager::IsTouchDeviceIdValid(int touch_device_id) const {
+ return (touch_device_id > 0 && touch_device_id < kMaxDeviceNum);
}
void DeviceDataManager::ApplyTouchRadiusScale(int touch_device_id,
@@ -127,7 +125,7 @@ void DeviceDataManager::ApplyTouchTransformer(int touch_device_id,
float* y) {
if (IsTouchDeviceIdValid(touch_device_id)) {
gfx::Point3F point(*x, *y, 0.0);
- const gfx::Transform& trans = touch_map_[touch_device_id].device_transform;
+ const gfx::Transform& trans = touch_map_[touch_device_id].transform;
trans.TransformPoint(&point);
*x = point.x();
*y = point.y();
@@ -158,7 +156,7 @@ bool DeviceDataManager::AreDeviceListsComplete() const {
int64_t DeviceDataManager::GetTargetDisplayForTouchDevice(
int touch_device_id) const {
if (IsTouchDeviceIdValid(touch_device_id))
- return touch_map_[touch_device_id].target_display;
+ return touch_map_[touch_device_id].display_id;
return display::kInvalidDisplayId;
}
@@ -171,7 +169,12 @@ void DeviceDataManager::OnTouchscreenDevicesUpdated(
InputDeviceEquals)) {
return;
}
+ are_touchscreen_target_displays_valid_ = false;
touchscreen_devices_ = devices;
+ for (TouchscreenDevice& touchscreen_device : touchscreen_devices_) {
+ touchscreen_device.target_display_id =
+ GetTargetDisplayForTouchDevice(touchscreen_device.id);
+ }
NotifyObserversTouchscreenDeviceConfigurationChanged();
}
@@ -258,4 +261,8 @@ bool DeviceDataManager::AreTouchscreensEnabled() const {
return touch_screens_enabled_;
}
+bool DeviceDataManager::AreTouchscreenTargetDisplaysValid() const {
+ return are_touchscreen_target_displays_valid_;
+}
+
} // namespace ui
diff --git a/chromium/ui/events/devices/device_data_manager.h b/chromium/ui/events/devices/device_data_manager.h
index 01e62aa98a7..7409c225002 100644
--- a/chromium/ui/events/devices/device_data_manager.h
+++ b/chromium/ui/events/devices/device_data_manager.h
@@ -16,8 +16,8 @@
#include "ui/events/devices/device_hotplug_event_observer.h"
#include "ui/events/devices/events_devices_export.h"
#include "ui/events/devices/input_device_manager.h"
+#include "ui/events/devices/touch_device_transform.h"
#include "ui/events/devices/touchscreen_device.h"
-#include "ui/gfx/transform.h"
namespace ui {
@@ -40,16 +40,16 @@ class EVENTS_DEVICES_EXPORT DeviceDataManager
static DeviceDataManager* GetInstance();
static bool HasInstance();
- void ClearTouchDeviceAssociations();
- void UpdateTouchInfoForDisplay(int64_t target_display_id,
- int touch_device_id,
- const gfx::Transform& touch_transformer);
+ // Configures the touch devices. |transforms| contains the transform for each
+ // device and display pair.
+ void ConfigureTouchDevices(
+ const std::vector<ui::TouchDeviceTransform>& transforms);
+
void ApplyTouchTransformer(int touch_device_id, float* x, float* y);
// Gets the display that touches from |touch_device_id| should be sent to.
int64_t GetTargetDisplayForTouchDevice(int touch_device_id) const;
- void UpdateTouchRadiusScale(int touch_device_id, double scale);
void ApplyTouchRadiusScale(int touch_device_id, double* radius);
void SetTouchscreensEnabled(bool enabled);
@@ -61,6 +61,7 @@ class EVENTS_DEVICES_EXPORT DeviceDataManager
const std::vector<InputDevice>& GetTouchpadDevices() const override;
bool AreDeviceListsComplete() const override;
bool AreTouchscreensEnabled() const override;
+ bool AreTouchscreenTargetDisplaysValid() const override;
void AddObserver(InputDeviceEventObserver* observer) override;
void RemoveObserver(InputDeviceEventObserver* observer) override;
@@ -68,8 +69,6 @@ class EVENTS_DEVICES_EXPORT DeviceDataManager
protected:
DeviceDataManager();
- static DeviceDataManager* instance();
-
static void set_instance(DeviceDataManager* instance);
// DeviceHotplugEventObserver:
@@ -85,20 +84,11 @@ class EVENTS_DEVICES_EXPORT DeviceDataManager
void OnStylusStateChanged(StylusState state) override;
private:
- // Information related to a touchscreen device.
- struct TouchscreenInfo {
- TouchscreenInfo();
- void Reset();
-
- double radius_scale;
- int64_t target_display;
- gfx::Transform device_transform;
- };
-
friend class test::DeviceDataManagerTestAPI;
- static DeviceDataManager* instance_;
-
+ void ClearTouchDeviceAssociations();
+ void UpdateTouchInfoFromTransform(
+ const ui::TouchDeviceTransform& touch_device_transform);
bool IsTouchDeviceIdValid(int touch_device_id) const;
void NotifyObserversTouchscreenDeviceConfigurationChanged();
@@ -108,6 +98,8 @@ class EVENTS_DEVICES_EXPORT DeviceDataManager
void NotifyObserversDeviceListsComplete();
void NotifyObserversStylusStateChanged(StylusState stylus_state);
+ static DeviceDataManager* instance_;
+
std::vector<TouchscreenDevice> touchscreen_devices_;
std::vector<InputDevice> keyboard_devices_;
std::vector<InputDevice> mouse_devices_;
@@ -118,10 +110,13 @@ class EVENTS_DEVICES_EXPORT DeviceDataManager
bool touch_screens_enabled_ = true;
+ // Set to true when ConfigureTouchDevices() is called.
+ bool are_touchscreen_target_displays_valid_ = false;
+
// Contains touchscreen device info for each device mapped by device ID. Will
// have default values if the device with corresponding ID isn't a touchscreen
// or doesn't exist.
- std::array<TouchscreenInfo, kMaxDeviceNum> touch_map_;
+ std::array<TouchDeviceTransform, kMaxDeviceNum> touch_map_;
DISALLOW_COPY_AND_ASSIGN(DeviceDataManager);
};
diff --git a/chromium/ui/events/devices/device_data_manager_unittest.cc b/chromium/ui/events/devices/device_data_manager_unittest.cc
new file mode 100644
index 00000000000..8a17653a7ca
--- /dev/null
+++ b/chromium/ui/events/devices/device_data_manager_unittest.cc
@@ -0,0 +1,109 @@
+// 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/events/devices/device_data_manager.h"
+
+#include "base/scoped_observer.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/display/types/display_constants.h"
+#include "ui/events/devices/device_hotplug_event_observer.h"
+#include "ui/events/devices/input_device.h"
+#include "ui/events/devices/input_device_event_observer.h"
+#include "ui/events/devices/touch_device_transform.h"
+#include "ui/events/devices/touchscreen_device.h"
+#include "ui/events/test/device_data_manager_test_api.h"
+#include "ui/gfx/transform.h"
+
+namespace ui {
+namespace {
+
+class DeviceDataManagerTest : public testing::Test {
+ public:
+ DeviceDataManagerTest() {}
+ ~DeviceDataManagerTest() override {}
+
+ // testing::Test:
+ void SetUp() override { DeviceDataManager::CreateInstance(); }
+ void TearDown() override { DeviceDataManager::DeleteInstance(); }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(DeviceDataManagerTest);
+};
+
+} // namespace
+
+TEST_F(DeviceDataManagerTest, DisplayIdUpdated) {
+ DeviceDataManager* device_data_manager = DeviceDataManager::GetInstance();
+ std::vector<TouchscreenDevice> touchscreen_devices(1);
+ // Default id is invalid, need something other than 0 (0 is invalid).
+ constexpr int kTouchId = 1;
+ touchscreen_devices[0].id = kTouchId;
+ static_cast<DeviceHotplugEventObserver*>(device_data_manager)
+ ->OnTouchscreenDevicesUpdated(touchscreen_devices);
+ ASSERT_EQ(1u, device_data_manager->GetTouchscreenDevices().size());
+ EXPECT_EQ(display::kInvalidDisplayId,
+ device_data_manager->GetTouchscreenDevices()[0].target_display_id);
+
+ constexpr int64_t kDisplayId = 2;
+ std::vector<TouchDeviceTransform> touch_device_transforms(1);
+ touch_device_transforms[0].display_id = kDisplayId;
+ touch_device_transforms[0].device_id = kTouchId;
+ device_data_manager->ConfigureTouchDevices(touch_device_transforms);
+ ASSERT_EQ(1u, device_data_manager->GetTouchscreenDevices().size());
+ EXPECT_EQ(kDisplayId,
+ device_data_manager->GetTouchscreenDevices()[0].target_display_id);
+}
+
+namespace {
+
+class TestInputDeviceEventObserver : public InputDeviceEventObserver {
+ public:
+ TestInputDeviceEventObserver() = default;
+
+ int on_touch_device_associations_changed_call_count() const {
+ return on_touch_device_associations_changed_call_count_;
+ }
+
+ // InputDeviceEventObserver:
+ void OnTouchDeviceAssociationChanged() override {
+ on_touch_device_associations_changed_call_count_++;
+ }
+
+ private:
+ int on_touch_device_associations_changed_call_count_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(TestInputDeviceEventObserver);
+};
+
+} // namespace
+
+TEST_F(DeviceDataManagerTest, AreTouchscreenTargetDisplaysValid) {
+ DeviceDataManager* device_data_manager = DeviceDataManager::GetInstance();
+ EXPECT_FALSE(device_data_manager->AreTouchscreenTargetDisplaysValid());
+ TestInputDeviceEventObserver observer;
+ ScopedObserver<DeviceDataManager, InputDeviceEventObserver> scoped_observer(
+ &observer);
+ scoped_observer.Add(device_data_manager);
+ test::DeviceDataManagerTestAPI().OnDeviceListsComplete();
+ EXPECT_FALSE(device_data_manager->AreTouchscreenTargetDisplaysValid());
+ EXPECT_EQ(0, observer.on_touch_device_associations_changed_call_count());
+
+ device_data_manager->ConfigureTouchDevices({});
+ EXPECT_EQ(1, observer.on_touch_device_associations_changed_call_count());
+ EXPECT_TRUE(device_data_manager->AreTouchscreenTargetDisplaysValid());
+
+ std::vector<TouchscreenDevice> touchscreen_devices(1);
+ // Default id is invalid, need something other than 0 (0 is invalid).
+ constexpr int kTouchId = 1;
+ touchscreen_devices[0].id = kTouchId;
+ static_cast<DeviceHotplugEventObserver*>(device_data_manager)
+ ->OnTouchscreenDevicesUpdated(touchscreen_devices);
+ EXPECT_EQ(1, observer.on_touch_device_associations_changed_call_count());
+ EXPECT_FALSE(device_data_manager->AreTouchscreenTargetDisplaysValid());
+ device_data_manager->ConfigureTouchDevices({});
+ EXPECT_EQ(2, observer.on_touch_device_associations_changed_call_count());
+ EXPECT_TRUE(device_data_manager->AreTouchscreenTargetDisplaysValid());
+}
+
+} // namespace ui
diff --git a/chromium/ui/events/devices/input_device_event_observer.h b/chromium/ui/events/devices/input_device_event_observer.h
index 4ea7d46e040..c2507b93999 100644
--- a/chromium/ui/events/devices/input_device_event_observer.h
+++ b/chromium/ui/events/devices/input_device_event_observer.h
@@ -23,6 +23,10 @@ class EVENTS_DEVICES_EXPORT InputDeviceEventObserver {
virtual void OnDeviceListsComplete() {}
virtual void OnStylusStateChanged(StylusState state) {}
+ // Called when ConfigureTouchDevices() is called. This indicates the
+ // transform, scale and/or device<->display mapping has changed.
+ virtual void OnTouchDeviceAssociationChanged() {}
+
protected:
InputDeviceEventObserver() {}
};
diff --git a/chromium/ui/events/devices/input_device_manager.h b/chromium/ui/events/devices/input_device_manager.h
index 59526ea357d..dcbd3167b80 100644
--- a/chromium/ui/events/devices/input_device_manager.h
+++ b/chromium/ui/events/devices/input_device_manager.h
@@ -35,6 +35,10 @@ class EVENTS_DEVICES_EXPORT InputDeviceManager {
virtual bool AreDeviceListsComplete() const = 0;
virtual bool AreTouchscreensEnabled() const = 0;
+ // Returns true if the |target_display_id| of the TouchscreenDevices returned
+ // from GetTouchscreenDevices() is valid.
+ virtual bool AreTouchscreenTargetDisplaysValid() const = 0;
+
virtual void AddObserver(InputDeviceEventObserver* observer) = 0;
virtual void RemoveObserver(InputDeviceEventObserver* observer) = 0;
diff --git a/chromium/ui/events/devices/input_device_observer_android.cc b/chromium/ui/events/devices/input_device_observer_android.cc
index 3313b7fea43..509234ebed5 100644
--- a/chromium/ui/events/devices/input_device_observer_android.cc
+++ b/chromium/ui/events/devices/input_device_observer_android.cc
@@ -19,10 +19,6 @@ using base::android::JavaParamRef;
namespace ui {
-bool InputDeviceObserverAndroid::RegisterInputDeviceObserver(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
InputDeviceObserverAndroid::InputDeviceObserverAndroid() {}
InputDeviceObserverAndroid::~InputDeviceObserverAndroid() {}
@@ -64,4 +60,4 @@ NOTIFY_OBSERVERS(NotifyObserversTouchpadDeviceConfigurationChanged(),
NOTIFY_OBSERVERS(NotifyObserversKeyboardDeviceConfigurationChanged(),
OnKeyboardDeviceConfigurationChanged());
-} // namespace ui \ No newline at end of file
+} // namespace ui
diff --git a/chromium/ui/events/devices/input_device_observer_android.h b/chromium/ui/events/devices/input_device_observer_android.h
index 311dfa821d0..b4d1be637b5 100644
--- a/chromium/ui/events/devices/input_device_observer_android.h
+++ b/chromium/ui/events/devices/input_device_observer_android.h
@@ -25,8 +25,6 @@ class EVENTS_DEVICES_EXPORT InputDeviceObserverAndroid {
static InputDeviceObserverAndroid* GetInstance();
~InputDeviceObserverAndroid();
- static bool RegisterInputDeviceObserver(JNIEnv* env);
-
void AddObserver(ui::InputDeviceEventObserver* observer);
void RemoveObserver(ui::InputDeviceEventObserver* observer);
diff --git a/chromium/ui/events/devices/mojo/BUILD.gn b/chromium/ui/events/devices/mojo/BUILD.gn
index fe65d7d1973..ee7bc482818 100644
--- a/chromium/ui/events/devices/mojo/BUILD.gn
+++ b/chromium/ui/events/devices/mojo/BUILD.gn
@@ -7,10 +7,12 @@ import("//mojo/public/tools/bindings/mojom.gni")
mojom("mojo") {
sources = [
"input_devices.mojom",
+ "touch_device_transform.mojom",
]
public_deps = [
"//ui/gfx/geometry/mojo",
+ "//ui/gfx/mojo",
]
}
diff --git a/chromium/ui/events/devices/mojo/OWNERS b/chromium/ui/events/devices/mojo/OWNERS
index 1841ff6198d..e75daf744a0 100644
--- a/chromium/ui/events/devices/mojo/OWNERS
+++ b/chromium/ui/events/devices/mojo/OWNERS
@@ -3,3 +3,6 @@ per-file *_struct_traits*.*=file://ipc/SECURITY_OWNERS
per-file *.mojom=set noparent
per-file *.mojom=file://ipc/SECURITY_OWNERS
+
+per-file *.typemap=set noparent
+per-file *.typemap=file://ipc/SECURITY_OWNERS
diff --git a/chromium/ui/display/manager/chromeos/mojo/touch_device_transform.mojom b/chromium/ui/events/devices/mojo/touch_device_transform.mojom
index 3daa9913337..5b8e9c23f5d 100644
--- a/chromium/ui/display/manager/chromeos/mojo/touch_device_transform.mojom
+++ b/chromium/ui/events/devices/mojo/touch_device_transform.mojom
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-module display.mojom;
+module ui.mojom;
import "ui/gfx/mojo/transform.mojom";
@@ -10,4 +10,5 @@ struct TouchDeviceTransform {
int64 display_id;
int32 device_id;
gfx.mojom.Transform transform;
+ double radius_scale;
};
diff --git a/chromium/ui/events/devices/mojo/touch_device_transform.typemap b/chromium/ui/events/devices/mojo/touch_device_transform.typemap
new file mode 100644
index 00000000000..689eb3b1e3b
--- /dev/null
+++ b/chromium/ui/events/devices/mojo/touch_device_transform.typemap
@@ -0,0 +1,14 @@
+# 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.
+
+mojom = "//ui/events/devices/mojo/touch_device_transform.mojom"
+public_headers = [ "//ui/events/devices/touch_device_transform.h" ]
+traits_headers =
+ [ "//ui/events/devices/mojo/touch_device_transform_struct_traits.h" ]
+deps = []
+public_deps = [
+ "//ui/gfx",
+ "//ui/gfx/mojo",
+]
+type_mappings = [ "ui.mojom.TouchDeviceTransform=ui::TouchDeviceTransform" ]
diff --git a/chromium/ui/display/manager/chromeos/mojo/touch_device_transform_struct_traits.h b/chromium/ui/events/devices/mojo/touch_device_transform_struct_traits.h
index 296ed5092b4..b9dd4506cbf 100644
--- a/chromium/ui/display/manager/chromeos/mojo/touch_device_transform_struct_traits.h
+++ b/chromium/ui/events/devices/mojo/touch_device_transform_struct_traits.h
@@ -7,33 +7,36 @@
#include <stdint.h>
-#include "ui/display/manager/chromeos/mojo/touch_device_transform.mojom.h"
-#include "ui/display/manager/chromeos/touch_device_transform.h"
+#include "ui/events/devices/mojo/touch_device_transform.mojom.h"
+#include "ui/events/devices/touch_device_transform.h"
#include "ui/gfx/mojo/transform_struct_traits.h"
namespace mojo {
template <>
-struct StructTraits<display::mojom::TouchDeviceTransformDataView,
- display::TouchDeviceTransform> {
+struct StructTraits<ui::mojom::TouchDeviceTransformDataView,
+ ui::TouchDeviceTransform> {
public:
- static int64_t display_id(const display::TouchDeviceTransform& r) {
+ static int64_t display_id(const ui::TouchDeviceTransform& r) {
return r.display_id;
}
- static int32_t device_id(const display::TouchDeviceTransform& r) {
+ static int32_t device_id(const ui::TouchDeviceTransform& r) {
return r.device_id;
}
- static const gfx::Transform& transform(
- const display::TouchDeviceTransform& r) {
+ static const gfx::Transform& transform(const ui::TouchDeviceTransform& r) {
return r.transform;
}
+ static double radius_scale(const ui::TouchDeviceTransform& r) {
+ return r.radius_scale;
+ }
- static bool Read(display::mojom::TouchDeviceTransformDataView data,
- display::TouchDeviceTransform* out) {
+ static bool Read(ui::mojom::TouchDeviceTransformDataView data,
+ ui::TouchDeviceTransform* out) {
out->display_id = data.display_id();
out->device_id = data.device_id();
if (!data.ReadTransform(&(out->transform)))
return false;
+ out->radius_scale = data.radius_scale();
return true;
}
};
diff --git a/chromium/ui/display/manager/chromeos/mojo/touch_device_transform_struct_traits_unittest.cc b/chromium/ui/events/devices/mojo/touch_device_transform_struct_traits_unittest.cc
index 42d18dafca9..c9453d5cd83 100644
--- a/chromium/ui/display/manager/chromeos/mojo/touch_device_transform_struct_traits_unittest.cc
+++ b/chromium/ui/events/devices/mojo/touch_device_transform_struct_traits_unittest.cc
@@ -2,13 +2,13 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/display/manager/chromeos/mojo/touch_device_transform_struct_traits.h"
+#include "ui/events/devices/mojo/touch_device_transform_struct_traits.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/display/manager/chromeos/mojo/touch_device_transform.mojom.h"
-#include "ui/display/manager/chromeos/touch_device_transform.h"
+#include "ui/events/devices/mojo/touch_device_transform.mojom.h"
+#include "ui/events/devices/touch_device_transform.h"
-namespace display {
+namespace ui {
TEST(TouchDeviceTransformStructTraitsTest, SerializeAndDeserialize) {
TouchDeviceTransform touch_device_transform;
@@ -16,6 +16,7 @@ TEST(TouchDeviceTransformStructTraitsTest, SerializeAndDeserialize) {
touch_device_transform.device_id = 202;
touch_device_transform.transform =
gfx::Transform(1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16);
+ touch_device_transform.radius_scale = 4;
TouchDeviceTransform deserialized;
ASSERT_TRUE(mojom::TouchDeviceTransform::Deserialize(
mojom::TouchDeviceTransform::Serialize(&touch_device_transform),
@@ -23,6 +24,7 @@ TEST(TouchDeviceTransformStructTraitsTest, SerializeAndDeserialize) {
EXPECT_EQ(touch_device_transform.display_id, deserialized.display_id);
EXPECT_EQ(touch_device_transform.device_id, deserialized.device_id);
EXPECT_EQ(touch_device_transform.transform, deserialized.transform);
+ EXPECT_EQ(touch_device_transform.radius_scale, deserialized.radius_scale);
}
-} // namespace display
+} // namespace ui
diff --git a/chromium/ui/events/devices/mojo/typemaps.gni b/chromium/ui/events/devices/mojo/typemaps.gni
index 7ce719ad827..727e53fcf73 100644
--- a/chromium/ui/events/devices/mojo/typemaps.gni
+++ b/chromium/ui/events/devices/mojo/typemaps.gni
@@ -2,4 +2,7 @@
# Use of this source code is governed by a BSD-style license that can be
# found in the LICENSE file.
-typemaps = [ "//ui/events/devices/mojo/input_device.typemap" ]
+typemaps = [
+ "//ui/events/devices/mojo/input_device.typemap",
+ "//ui/events/devices/mojo/touch_device_transform.typemap",
+]
diff --git a/chromium/ui/display/manager/chromeos/touch_device_transform.cc b/chromium/ui/events/devices/touch_device_transform.cc
index 50e8c20e920..dd8c410215d 100644
--- a/chromium/ui/display/manager/chromeos/touch_device_transform.cc
+++ b/chromium/ui/events/devices/touch_device_transform.cc
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/display/manager/chromeos/touch_device_transform.h"
+#include "ui/events/devices/touch_device_transform.h"
-namespace display {
+namespace ui {
TouchDeviceTransform::TouchDeviceTransform() = default;
TouchDeviceTransform::~TouchDeviceTransform() = default;
-} // namespace display
+} // namespace ui
diff --git a/chromium/ui/events/devices/touch_device_transform.h b/chromium/ui/events/devices/touch_device_transform.h
new file mode 100644
index 00000000000..767fe50b110
--- /dev/null
+++ b/chromium/ui/events/devices/touch_device_transform.h
@@ -0,0 +1,30 @@
+// 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_EVENTS_DEVICES_TOUCH_DEVICE_TRANSFORM_H_
+#define UI_EVENTS_DEVICES_TOUCH_DEVICE_TRANSFORM_H_
+
+#include <stdint.h>
+
+#include "ui/display/types/display_constants.h"
+#include "ui/events/devices/events_devices_export.h"
+#include "ui/events/devices/input_device.h"
+#include "ui/gfx/transform.h"
+
+namespace ui {
+
+struct EVENTS_DEVICES_EXPORT TouchDeviceTransform {
+ TouchDeviceTransform();
+ ~TouchDeviceTransform();
+
+ int64_t display_id = display::kInvalidDisplayId;
+ int32_t device_id = InputDevice::kInvalidId;
+ gfx::Transform transform;
+ // Amount to scale the touch radius by.
+ double radius_scale = 1;
+};
+
+} // namespace ui
+
+#endif // UI_EVENTS_DEVICES_TOUCH_DEVICE_TRANSFORM_H_
diff --git a/chromium/ui/events/devices/touchscreen_device.cc b/chromium/ui/events/devices/touchscreen_device.cc
index b840b9681d1..3c2a4a646fa 100644
--- a/chromium/ui/events/devices/touchscreen_device.cc
+++ b/chromium/ui/events/devices/touchscreen_device.cc
@@ -10,27 +10,19 @@
namespace ui {
-TouchscreenDevice::TouchscreenDevice() : touch_points(0), is_stylus(false) {}
+TouchscreenDevice::TouchscreenDevice() : touch_points(0) {}
TouchscreenDevice::TouchscreenDevice(int id,
InputDeviceType type,
const std::string& name,
const gfx::Size& size,
int touch_points)
- : InputDevice(id, type, name),
- size(size),
- touch_points(touch_points),
- is_stylus(false) {
-}
+ : InputDevice(id, type, name), size(size), touch_points(touch_points) {}
TouchscreenDevice::TouchscreenDevice(const InputDevice& input_device,
const gfx::Size& size,
int touch_points)
- : InputDevice(input_device),
- size(size),
- touch_points(touch_points),
- is_stylus(false) {
-}
+ : InputDevice(input_device), size(size), touch_points(touch_points) {}
TouchscreenDevice::~TouchscreenDevice() {}
diff --git a/chromium/ui/events/devices/touchscreen_device.h b/chromium/ui/events/devices/touchscreen_device.h
index ee024a0f860..958151a4487 100644
--- a/chromium/ui/events/devices/touchscreen_device.h
+++ b/chromium/ui/events/devices/touchscreen_device.h
@@ -5,8 +5,11 @@
#ifndef UI_EVENTS_DEVICES_TOUCHSCREEN_DEVICE_H_
#define UI_EVENTS_DEVICES_TOUCHSCREEN_DEVICE_H_
+#include <stdint.h>
+
#include <string>
+#include "ui/display/types/display_constants.h"
#include "ui/events/devices/events_devices_export.h"
#include "ui/events/devices/input_device.h"
#include "ui/gfx/geometry/size.h"
@@ -33,8 +36,13 @@ struct EVENTS_DEVICES_EXPORT TouchscreenDevice : public InputDevice {
gfx::Size size; // Size of the touch screen area.
int touch_points; // The number of touch points this device supports (0 if
// unknown).
- bool is_stylus; // True if the specified touchscreen device is stylus
- // capable.
+ // True if the specified touchscreen device is stylus capable.
+ bool is_stylus = false;
+ // Id of the display the touch device targets.
+ // NOTE: when obtaining TouchscreenDevice from InputDeviceManager this value
+ // may not have been updated. See
+ // InputDeviceManager::AreTouchscreenTargetDisplaysValid() for details.
+ int64_t target_display_id = display::kInvalidDisplayId;
};
} // namespace ui
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 f2182752b36..45ae658eb67 100644
--- a/chromium/ui/events/devices/x11/device_data_manager_x11.cc
+++ b/chromium/ui/events/devices/x11/device_data_manager_x11.cc
@@ -146,7 +146,7 @@ bool DeviceDataManagerX11::IsTouchDataType(const int type) {
// static
void DeviceDataManagerX11::CreateInstance() {
- if (instance())
+ if (HasInstance())
return;
DeviceDataManagerX11* device_data_manager = new DeviceDataManagerX11();
diff --git a/chromium/ui/events/devices/x11/touch_factory_x11.cc b/chromium/ui/events/devices/x11/touch_factory_x11.cc
index 7df258655ee..ab63a07ae36 100644
--- a/chromium/ui/events/devices/x11/touch_factory_x11.cc
+++ b/chromium/ui/events/devices/x11/touch_factory_x11.cc
@@ -272,7 +272,7 @@ int TouchFactory::GetSlotForTrackingID(uint32_t tracking_id) {
}
void TouchFactory::ReleaseSlotForTrackingID(uint32_t tracking_id) {
- id_generator_.ReleaseNumber(tracking_id);
+ id_generator_.MaybeReleaseNumber(tracking_id);
}
bool TouchFactory::IsTouchDevicePresent() {
diff --git a/chromium/ui/events/event.cc b/chromium/ui/events/event.cc
index 7cb7a32d90f..c487f8f1f3c 100644
--- a/chromium/ui/events/event.cc
+++ b/chromium/ui/events/event.cc
@@ -409,25 +409,10 @@ Event::Event(const base::NativeEvent& native_event,
phase_(EP_PREDISPATCH),
result_(ER_UNHANDLED),
source_device_id_(ED_UNKNOWN_DEVICE) {
- base::TimeDelta delta = EventTimeForNow() - time_stamp_;
if (type_ < ET_LAST)
latency()->set_source_event_type(EventTypeToLatencySourceEventType(type));
- base::HistogramBase::Sample delta_sample =
- static_cast<base::HistogramBase::Sample>(delta.InMicroseconds());
- UMA_HISTOGRAM_CUSTOM_COUNTS("Event.Latency.Browser", delta_sample, 1, 1000000,
- 100);
ComputeEventLatencyOS(native_event);
- // Though it seems inefficient to generate the string twice, the first
- // instance will be used only for DCHECK builds and the second won't be
- // executed at all if the histogram was previously accessed here.
- STATIC_HISTOGRAM_POINTER_GROUP(
- base::StringPrintf("Event.Latency.Browser.%s", GetName()), type_, ET_LAST,
- Add(delta_sample),
- base::Histogram::FactoryGet(
- base::StringPrintf("Event.Latency.Browser.%s", GetName()), 1, 1000000,
- 100, base::HistogramBase::kUmaTargetedHistogramFlag));
-
#if defined(USE_X11)
if (native_event->type == GenericEvent) {
XIDeviceEvent* xiev =
@@ -495,12 +480,22 @@ LocatedEvent::LocatedEvent(EventType type,
root_location_(root_location) {}
void LocatedEvent::UpdateForRootTransform(
- const gfx::Transform& reversed_root_transform) {
- // Transform has to be done at root level.
- gfx::Point3F p(location_);
- reversed_root_transform.TransformPoint(&p);
- location_ = p.AsPointF();
- root_location_ = location_;
+ const gfx::Transform& reversed_root_transform,
+ const gfx::Transform& reversed_local_transform) {
+ if (target()) {
+ gfx::Point3F transformed_location(location_);
+ reversed_local_transform.TransformPoint(&transformed_location);
+ location_ = transformed_location.AsPointF();
+
+ gfx::Point3F transformed_root_location(root_location_);
+ reversed_root_transform.TransformPoint(&transformed_root_location);
+ root_location_ = transformed_root_location.AsPointF();
+ } else {
+ // This mirrors what the code previously did.
+ gfx::Point3F transformed_location(location_);
+ reversed_root_transform.TransformPoint(&transformed_location);
+ root_location_ = location_ = transformed_location.AsPointF();
+ }
}
////////////////////////////////////////////////////////////////////////////////
@@ -572,8 +567,7 @@ MouseEvent::MouseEvent(const base::NativeEvent& native_event)
changed_button_flags_(GetChangedMouseButtonFlagsFromNative(native_event)),
pointer_details_(GetMousePointerDetailsFromNative(native_event)) {
latency()->AddLatencyNumberWithTimestamp(
- INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0,
- base::TimeTicks::FromInternalValue(time_stamp().ToInternalValue()), 1);
+ INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0, time_stamp(), 1);
latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
if (type() == ET_MOUSE_PRESSED || type() == ET_MOUSE_RELEASED)
SetClickCount(GetRepeatCount(*this));
@@ -840,8 +834,7 @@ TouchEvent::TouchEvent(const base::NativeEvent& native_event)
should_remove_native_touch_id_mapping_(false),
pointer_details_(GetTouchPointerDetailsFromNative(native_event)) {
latency()->AddLatencyNumberWithTimestamp(
- INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0,
- base::TimeTicks::FromInternalValue(time_stamp().ToInternalValue()), 1);
+ INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0, time_stamp(), 1);
latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
FixRotationAngle();
@@ -923,8 +916,10 @@ TouchEvent::~TouchEvent() {
}
void TouchEvent::UpdateForRootTransform(
- const gfx::Transform& inverted_root_transform) {
- LocatedEvent::UpdateForRootTransform(inverted_root_transform);
+ const gfx::Transform& inverted_root_transform,
+ const gfx::Transform& inverted_local_transform) {
+ LocatedEvent::UpdateForRootTransform(inverted_root_transform,
+ inverted_local_transform);
gfx::DecomposedTransform decomp;
bool success = gfx::DecomposeTransform(&decomp, inverted_root_transform);
DCHECK(success);
@@ -1149,8 +1144,7 @@ KeyEvent::KeyEvent(const base::NativeEvent& native_event, int event_flags)
code_(CodeFromNative(native_event)),
is_char_(IsCharFromNative(native_event)) {
latency()->AddLatencyNumberWithTimestamp(
- INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0,
- base::TimeTicks::FromInternalValue(time_stamp().ToInternalValue()), 1);
+ INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0, time_stamp(), 1);
latency()->AddLatencyNumber(INPUT_EVENT_LATENCY_UI_COMPONENT, 0, 0);
if (IsRepeated(*this))
diff --git a/chromium/ui/events/event.h b/chromium/ui/events/event.h
index 48b652ed0f0..6b5ccbd3096 100644
--- a/chromium/ui/events/event.h
+++ b/chromium/ui/events/event.h
@@ -114,6 +114,8 @@ class EVENTS_EXPORT Event {
bool IsAltGrDown() const { return (flags_ & EF_ALTGR_DOWN) != 0; }
bool IsCapsLockOn() const { return (flags_ & EF_CAPS_LOCK_ON) != 0; }
+ bool IsSynthesized() const { return (flags_ & EF_IS_SYNTHESIZED) != 0; }
+
bool IsCancelModeEvent() const {
return type_ == ET_CANCEL_MODE;
}
@@ -363,10 +365,12 @@ class EVENTS_EXPORT LocatedEvent : public Event {
return root_location_;
}
- // Transform the locations using |inverted_root_transform|.
- // This is applied to both |location_| and |root_location_|.
+ // Transform the locations using |inverted_root_transform| and
+ // |inverted_local_transform|. |inverted_local_transform| is only used if
+ // the event has a target.
virtual void UpdateForRootTransform(
- const gfx::Transform& inverted_root_transform);
+ const gfx::Transform& inverted_root_transform,
+ const gfx::Transform& inverted_local_transform);
template <class T> void ConvertLocationToTarget(T* source, T* target) {
if (!target || target == source)
@@ -698,7 +702,8 @@ class EVENTS_EXPORT TouchEvent : public LocatedEvent {
// Overridden from LocatedEvent.
void UpdateForRootTransform(
- const gfx::Transform& inverted_root_transform) override;
+ const gfx::Transform& inverted_root_transform,
+ const gfx::Transform& inverted_local_transform) override;
// Marks the event as not participating in synchronous gesture recognition.
void DisableSynchronousHandling();
diff --git a/chromium/ui/events/event_constants.h b/chromium/ui/events/event_constants.h
index 063058912fc..79ca132182b 100644
--- a/chromium/ui/events/event_constants.h
+++ b/chromium/ui/events/event_constants.h
@@ -136,9 +136,7 @@ enum MouseEventFlags {
// from an unconsumed touch/gesture event.
EF_TOUCH_ACCESSIBILITY = 1 << 19, // Indicates this event was generated from
// touch accessibility mode.
- EF_DIRECT_INPUT = 1 << 20, // Mouse event coming from direct,
- // on-screen input.
- EF_CURSOR_HIDE = 1 << 21, // Indicates this mouse event is generated
+ EF_CURSOR_HIDE = 1 << 20, // Indicates this mouse event is generated
// because the cursor was just hidden. This
// can be used to update hover state.
};
diff --git a/chromium/ui/events/event_unittest.cc b/chromium/ui/events/event_unittest.cc
index 29e5048a0e4..d72bb325be3 100644
--- a/chromium/ui/events/event_unittest.cc
+++ b/chromium/ui/events/event_unittest.cc
@@ -17,6 +17,8 @@
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/events/test/events_test_utils.h"
+#include "ui/events/test/test_event_target.h"
+#include "ui/gfx/transform.h"
#if defined(USE_X11)
#include <X11/Xlib.h>
@@ -1098,4 +1100,47 @@ TEST(EventTest, EventLatencyOSMouseWheelHistogram) {
#endif
}
+TEST(EventTest, UpdateForRootTransformation) {
+ gfx::Transform identity_transform;
+ const gfx::Point location(10, 10);
+ const gfx::Point root_location(20, 20);
+
+ // A mouse event that is untargeted should reset the root location when
+ // transformed. Though the events start out with different locations and
+ // root_locations, they should be equal afterwards.
+ ui::MouseEvent untargeted(ET_MOUSE_PRESSED, location, root_location,
+ EventTimeForNow(), 0, 0);
+ untargeted.UpdateForRootTransform(identity_transform, identity_transform);
+ EXPECT_EQ(location, untargeted.location());
+ EXPECT_EQ(location, untargeted.root_location());
+
+ ui::test::TestEventTarget target;
+
+ // A mouse event that is targeted should not set the root location to the
+ // local location. They start with different locations and should stay
+ // unequal after a transform is applied.
+ {
+ ui::MouseEvent targeted(ET_MOUSE_PRESSED, location, root_location,
+ EventTimeForNow(), 0, 0);
+ Event::DispatcherApi(&targeted).set_target(&target);
+ targeted.UpdateForRootTransform(identity_transform, identity_transform);
+ EXPECT_EQ(location, targeted.location());
+ EXPECT_EQ(root_location, targeted.root_location());
+ }
+
+ {
+ // Targeted event with 2x and 3x scales.
+ gfx::Transform transform2x;
+ transform2x.Scale(2, 2);
+ gfx::Transform transform3x;
+ transform3x.Scale(3, 3);
+ ui::MouseEvent targeted(ET_MOUSE_PRESSED, location, root_location,
+ EventTimeForNow(), 0, 0);
+ Event::DispatcherApi(&targeted).set_target(&target);
+ targeted.UpdateForRootTransform(transform2x, transform3x);
+ EXPECT_EQ(gfx::Point(30, 30), targeted.location());
+ EXPECT_EQ(gfx::Point(40, 40), targeted.root_location());
+ }
+}
+
} // namespace ui
diff --git a/chromium/ui/events/gesture_detection/gesture_detector.cc b/chromium/ui/events/gesture_detection/gesture_detector.cc
index a3f73861fe4..b7453add2d4 100644
--- a/chromium/ui/events/gesture_detection/gesture_detector.cc
+++ b/chromium/ui/events/gesture_detection/gesture_detector.cc
@@ -13,6 +13,7 @@
#include <cmath>
#include "base/timer/timer.h"
+#include "build/build_config.h"
#include "ui/events/gesture_detection/gesture_listeners.h"
#include "ui/events/gesture_detection/motion_event.h"
@@ -59,7 +60,8 @@ GestureDetector::Config::Config()
two_finger_tap_max_separation(300),
two_finger_tap_timeout(base::TimeDelta::FromMilliseconds(700)),
single_tap_repeat_interval(1),
- velocity_tracker_strategy(VelocityTracker::Strategy::STRATEGY_DEFAULT) {}
+ velocity_tracker_strategy(VelocityTracker::Strategy::STRATEGY_DEFAULT) {
+}
GestureDetector::Config::Config(const Config& other) = default;
@@ -291,8 +293,8 @@ bool GestureDetector::OnTouchEvent(const MotionEvent& ev) {
two_finger_tap_allowed_for_gesture_ = two_finger_tap_enabled_;
maximum_pointer_count_ = 1;
- // Always start the SHOW_PRESS timer before the LONG_PRESS timer to ensure
- // proper timeout ordering.
+ // Always start the SHOW_PRESS timer before the LONG_PRESS timer to
+ // ensure proper timeout ordering.
if (showpress_enabled_)
timeout_handler_->StartTimeout(SHOW_PRESS);
if (longpress_enabled_)
diff --git a/chromium/ui/events/gesture_detection/gesture_provider.cc b/chromium/ui/events/gesture_detection/gesture_provider.cc
index 2c0c9bf5dc7..39b8a2d1504 100644
--- a/chromium/ui/events/gesture_detection/gesture_provider.cc
+++ b/chromium/ui/events/gesture_detection/gesture_provider.cc
@@ -323,8 +323,8 @@ class GestureProvider::GestureListenerImpl : public ScaleGestureListener,
if (!scroll_event_sent_) {
// Note that scroll start hints are in distance traveled, where
// scroll deltas are in the opposite direction.
- GestureEventDetails scroll_details(
- ET_GESTURE_SCROLL_BEGIN, -raw_distance_x, -raw_distance_y);
+ GestureEventDetails scroll_details(ET_GESTURE_SCROLL_BEGIN, -distance_x,
+ -distance_y);
scroll_details.set_device_type(GestureDeviceType::DEVICE_TOUCHSCREEN);
// Scroll focus point always starts with the first touch down point.
diff --git a/chromium/ui/events/gesture_detection/gesture_provider_unittest.cc b/chromium/ui/events/gesture_detection/gesture_provider_unittest.cc
index ad6d1c9863e..50390db57e1 100644
--- a/chromium/ui/events/gesture_detection/gesture_provider_unittest.cc
+++ b/chromium/ui/events/gesture_detection/gesture_provider_unittest.cc
@@ -917,8 +917,11 @@ TEST_F(GestureProviderTest, FractionalScroll) {
// Generate a scroll gesture and verify that the resulting scroll begin event
// has the expected hint values.
TEST_F(GestureProviderTest, ScrollBeginValues) {
- const float delta_x = 13;
- const float delta_y = 89;
+ const float delta_x = 14;
+ const float delta_y = 48;
+ // These are the deltas after subtracting slop region and railing.
+ const float delta_x_hint = 0;
+ const float delta_y_hint = 40.32f;
const base::TimeTicks event_time = TimeTicks::Now();
@@ -944,8 +947,8 @@ TEST_F(GestureProviderTest, ScrollBeginValues) {
const GestureEventData* scroll_begin_gesture = GetActiveScrollBeginEvent();
ASSERT_TRUE(scroll_begin_gesture);
- EXPECT_EQ(delta_x, scroll_begin_gesture->details.scroll_x_hint());
- EXPECT_EQ(delta_y, scroll_begin_gesture->details.scroll_y_hint());
+ EXPECT_EQ(delta_x_hint, scroll_begin_gesture->details.scroll_x_hint());
+ EXPECT_EQ(delta_y_hint, scroll_begin_gesture->details.scroll_y_hint());
}
// The following three tests verify that slop regions are checked for
diff --git a/chromium/ui/events/gesture_detection/motion_event_buffer_unittest.cc b/chromium/ui/events/gesture_detection/motion_event_buffer_unittest.cc
index 5d997692ad0..b8090b2a82c 100644
--- a/chromium/ui/events/gesture_detection/motion_event_buffer_unittest.cc
+++ b/chromium/ui/events/gesture_detection/motion_event_buffer_unittest.cc
@@ -202,7 +202,7 @@ class MotionEventBufferTest : public testing::Test,
base::TimeDelta dt = current_flushed_event->GetEventTime() -
last_flushed_event->GetEventTime();
- EXPECT_GE(dt.ToInternalValue(), 0);
+ EXPECT_GE(dt, base::TimeDelta());
// A time delta of 0 is possible if the flush rate is greater than the
// event rate, in which case we can simply skip forward.
if (dt.is_zero())
diff --git a/chromium/ui/events/gesture_detection/motion_event_generic.cc b/chromium/ui/events/gesture_detection/motion_event_generic.cc
index ad4d7286d36..35a5b885585 100644
--- a/chromium/ui/events/gesture_detection/motion_event_generic.cc
+++ b/chromium/ui/events/gesture_detection/motion_event_generic.cc
@@ -268,8 +268,7 @@ void MotionEventGeneric::PushHistoricalEvent(
DCHECK_EQ(event->GetAction(), ACTION_MOVE);
DCHECK_EQ(event->GetPointerCount(), GetPointerCount());
DCHECK_EQ(event->GetAction(), GetAction());
- DCHECK_LE(event->GetEventTime().ToInternalValue(),
- GetEventTime().ToInternalValue());
+ DCHECK_LE(event->GetEventTime(), GetEventTime());
historical_events_.push_back(std::move(event));
}
diff --git a/chromium/ui/events/gestures/blink/web_gesture_curve_impl.cc b/chromium/ui/events/gestures/blink/web_gesture_curve_impl.cc
index 2f2997e8e47..a9901956a9e 100644
--- a/chromium/ui/events/gestures/blink/web_gesture_curve_impl.cc
+++ b/chromium/ui/events/gestures/blink/web_gesture_curve_impl.cc
@@ -32,7 +32,6 @@ namespace {
std::unique_ptr<GestureCurve> CreateDefaultPlatformCurve(
blink::WebGestureDevice device_source,
const gfx::Vector2dF& initial_velocity) {
- DCHECK(!initial_velocity.IsZero());
if (device_source == blink::kWebGestureDeviceSyntheticAutoscroll) {
return base::MakeUnique<FixedVelocityCurve>(initial_velocity,
base::TimeTicks());
@@ -83,37 +82,11 @@ WebGestureCurveImpl::WebGestureCurveImpl(std::unique_ptr<GestureCurve> curve,
ThreadType animating_thread_type)
: curve_(std::move(curve)),
last_offset_(initial_offset),
- animating_thread_type_(animating_thread_type),
ticks_since_first_animate_(0),
first_animate_time_(0),
last_animate_time_(0) {}
-WebGestureCurveImpl::~WebGestureCurveImpl() {
- if (ticks_since_first_animate_ <= 1)
- return;
-
- if (last_animate_time_ <= first_animate_time_)
- return;
-
- switch (animating_thread_type_) {
- case ThreadType::MAIN:
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Event.Frequency.Renderer.FlingAnimate",
- gfx::ToRoundedInt(ticks_since_first_animate_ /
- (last_animate_time_ - first_animate_time_)),
- 1, 240, 120);
- break;
- case ThreadType::IMPL:
- UMA_HISTOGRAM_CUSTOM_COUNTS(
- "Event.Frequency.RendererImpl.FlingAnimate",
- gfx::ToRoundedInt(ticks_since_first_animate_ /
- (last_animate_time_ - first_animate_time_)),
- 1, 240, 120);
- break;
- case ThreadType::TEST:
- break;
- }
-}
+WebGestureCurveImpl::~WebGestureCurveImpl() {}
bool WebGestureCurveImpl::Apply(double time,
blink::WebGestureCurveTarget* target) {
diff --git a/chromium/ui/events/gestures/blink/web_gesture_curve_impl.h b/chromium/ui/events/gestures/blink/web_gesture_curve_impl.h
index 076f0169d53..ecadeeb2e5f 100644
--- a/chromium/ui/events/gestures/blink/web_gesture_curve_impl.h
+++ b/chromium/ui/events/gestures/blink/web_gesture_curve_impl.h
@@ -22,7 +22,7 @@ class WebGestureCurveTarget;
namespace ui {
class GestureCurve;
-class WebGestureCurveImpl : public NON_EXPORTED_BASE(blink::WebGestureCurve) {
+class WebGestureCurveImpl : public blink::WebGestureCurve {
public:
static std::unique_ptr<blink::WebGestureCurve> CreateFromDefaultPlatformCurve(
blink::WebGestureDevice device_source,
@@ -53,7 +53,6 @@ class WebGestureCurveImpl : public NON_EXPORTED_BASE(blink::WebGestureCurve) {
gfx::Vector2dF last_offset_;
- ThreadType animating_thread_type_;
int64_t ticks_since_first_animate_;
double first_animate_time_;
double last_animate_time_;
diff --git a/chromium/ui/events/gestures/gesture_recognizer_impl.h b/chromium/ui/events/gestures/gesture_recognizer_impl.h
index f06cf6dc613..52901ce251c 100644
--- a/chromium/ui/events/gestures/gesture_recognizer_impl.h
+++ b/chromium/ui/events/gestures/gesture_recognizer_impl.h
@@ -59,6 +59,10 @@ class EVENTS_EXPORT GestureRecognizerImpl : public GestureRecognizer,
virtual GestureProviderAura* GetGestureProviderForConsumer(
GestureConsumer* c);
+ // Overridden from GestureRecognizer
+ bool ProcessTouchEventPreDispatch(TouchEvent* event,
+ GestureConsumer* consumer) override;
+
private:
// Sets up the target consumer for gestures based on the touch-event.
void SetupTargets(const TouchEvent& event, GestureConsumer* consumer);
@@ -66,10 +70,6 @@ class EVENTS_EXPORT GestureRecognizerImpl : public GestureRecognizer,
void DispatchGestureEvent(GestureConsumer* raw_input_consumer,
GestureEvent* event);
- // Overridden from GestureRecognizer
- bool ProcessTouchEventPreDispatch(TouchEvent* event,
- GestureConsumer* consumer) override;
-
Gestures AckTouchEvent(uint32_t unique_event_id,
ui::EventResult result,
bool is_source_touch_event_set_non_blocking,
diff --git a/chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm b/chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm
index 143f9b1f831..d6427700c41 100644
--- a/chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm
+++ b/chromium/ui/events/keycodes/keyboard_code_conversion_mac.mm
@@ -18,6 +18,12 @@ namespace ui {
namespace {
+bool IsUnicodeControl(unichar c) {
+ // C0 control characters: http://unicode.org/charts/PDF/U0000.pdf
+ // C1 control characters: http://unicode.org/charts/PDF/U0080.pdf
+ return c <= 0x1F || (c >= 0x7F && c <= 0x9F);
+}
+
// This value is not defined but shows up as 0x36.
const int kVK_RightCommand = 0x36;
// Context menu is not defined but shows up as 0x6E.
@@ -850,18 +856,10 @@ DomKey DomKeyFromNSEvent(NSEvent* event) {
// e.g. On French keyboard [+a will produce "^q", DomKey should be 'q'.
unichar dom_key_char =
[characters characterAtIndex:[characters length] - 1];
- const bool is_ctrl_down = ([event modifierFlags] & NSControlKeyMask) &&
- !([event modifierFlags] & NSAlternateKeyMask);
- const bool is_command_down = [event modifierFlags] & NSCommandKeyMask;
- // On Mac Blink won't insert ASCII character if either Ctrl or Command, or
- // both, are down.
- // See EditingBehavior::shouldInsertCharacter()
- if (std::iscntrl(dom_key_char) ||
- (dom_key_char < 0x80 && (is_ctrl_down || is_command_down))) {
- // According to spec if the key combination produces a non-printable
- // character, the key value should be the character without modifiers
- // except Shift and AltGr.
- // See https://w3c.github.io/uievents/#keys-guidelines
+ if (IsUnicodeControl(dom_key_char)) {
+ // Filter non-glyph modifiers if the generated characters are part of
+ // Unicode 'Other, Control' General Category.
+ // https://w3c.github.io/uievents-key/#selecting-key-attribute-values
bool unused_is_dead_key;
const int kAllowedModifiersMask =
NSShiftKeyMask | NSAlphaShiftKeyMask | NSAlternateKeyMask;
@@ -870,7 +868,10 @@ DomKey DomKeyFromNSEvent(NSEvent* event) {
[event keyCode], [event modifierFlags] & kAllowedModifiersMask,
&unused_is_dead_key);
}
- if (!std::iscntrl(dom_key_char))
+
+ // We need to check again because keys like ESC will produce control
+ // characters even without any modifiers.
+ if (!IsUnicodeControl(dom_key_char))
return DomKeyFromCharCode(dom_key_char);
}
}
diff --git a/chromium/ui/events/mojo/BUILD.gn b/chromium/ui/events/mojo/BUILD.gn
index 34b89eb6643..49165b33496 100644
--- a/chromium/ui/events/mojo/BUILD.gn
+++ b/chromium/ui/events/mojo/BUILD.gn
@@ -12,6 +12,7 @@ mojom("interfaces") {
]
public_deps = [
+ "//mojo/common:common_custom_types",
"//ui/gfx/mojo",
"//ui/latency/mojo:interfaces",
]
diff --git a/chromium/ui/events/mojo/event.mojom b/chromium/ui/events/mojo/event.mojom
index 48c7cd55c5e..04312539cca 100644
--- a/chromium/ui/events/mojo/event.mojom
+++ b/chromium/ui/events/mojo/event.mojom
@@ -4,6 +4,7 @@
module ui.mojom;
+import "mojo/common/time.mojom";
import "ui/events/mojo/event_constants.mojom";
import "ui/events/mojo/keyboard_codes.mojom";
import "ui/latency/mojo/latency_info.mojom";
@@ -115,10 +116,10 @@ struct Event {
//
// TODO(sky): parts of this should move to PointerData.
int32 flags;
- // Time in microseconds from when the platform was started.
- // This value accurately orders events w.r.t. to each other but
- // does not position them at an absolute time.
- int64 time_stamp;
+ // This value accurately orders events w.r.t. to each other but does not
+ // position them at an absolute time since the TimeTicks origin is only
+ // guaranteed to be fixed during one instance of the application.
+ mojo.common.mojom.TimeTicks time_stamp;
LatencyInfo latency;
KeyData? key_data;
PointerData? pointer_data;
diff --git a/chromium/ui/events/mojo/event_struct_traits.cc b/chromium/ui/events/mojo/event_struct_traits.cc
index d2a66cb7837..0b4e196f3a3 100644
--- a/chromium/ui/events/mojo/event_struct_traits.cc
+++ b/chromium/ui/events/mojo/event_struct_traits.cc
@@ -5,7 +5,6 @@
#include "ui/events/mojo/event_struct_traits.h"
#include "ui/events/event.h"
-#include "ui/events/event_utils.h"
#include "ui/events/keycodes/dom/keycode_converter.h"
#include "ui/events/mojo/event_constants.mojom.h"
#include "ui/latency/mojo/latency_info_struct_traits.h"
@@ -133,9 +132,10 @@ int32_t StructTraits<ui::mojom::EventDataView, EventUniquePtr>::flags(
return event->flags();
}
-int64_t StructTraits<ui::mojom::EventDataView, EventUniquePtr>::time_stamp(
+base::TimeTicks
+StructTraits<ui::mojom::EventDataView, EventUniquePtr>::time_stamp(
const EventUniquePtr& event) {
- return event->time_stamp().ToInternalValue();
+ return event->time_stamp();
}
const ui::LatencyInfo&
@@ -242,6 +242,10 @@ bool StructTraits<ui::mojom::EventDataView, EventUniquePtr>::Read(
EventUniquePtr* out) {
DCHECK(!out->get());
+ base::TimeTicks time_stamp;
+ if (!event.ReadTimeStamp(&time_stamp))
+ return false;
+
switch (event.action()) {
case ui::mojom::EventType::KEY_PRESSED:
case ui::mojom::EventType::KEY_RELEASED: {
@@ -250,18 +254,17 @@ bool StructTraits<ui::mojom::EventDataView, EventUniquePtr>::Read(
return false;
if (key_data->is_char) {
- out->reset(new ui::KeyEvent(
- static_cast<base::char16>(key_data->character),
- static_cast<ui::KeyboardCode>(key_data->key_code), event.flags(),
- base::TimeTicks::FromInternalValue(event.time_stamp())));
-
+ out->reset(
+ new ui::KeyEvent(static_cast<base::char16>(key_data->character),
+ static_cast<ui::KeyboardCode>(key_data->key_code),
+ event.flags(), time_stamp));
} else {
- out->reset(new ui::KeyEvent(
- event.action() == ui::mojom::EventType::KEY_PRESSED
- ? ui::ET_KEY_PRESSED
- : ui::ET_KEY_RELEASED,
- static_cast<ui::KeyboardCode>(key_data->key_code), event.flags(),
- base::TimeTicks::FromInternalValue(event.time_stamp())));
+ out->reset(
+ new ui::KeyEvent(event.action() == ui::mojom::EventType::KEY_PRESSED
+ ? ui::ET_KEY_PRESSED
+ : ui::ET_KEY_RELEASED,
+ static_cast<ui::KeyboardCode>(key_data->key_code),
+ event.flags(), time_stamp));
}
if (key_data->properties)
(*out)->AsKeyEvent()->SetProperties(*key_data->properties);
@@ -298,7 +301,7 @@ bool StructTraits<ui::mojom::EventDataView, EventUniquePtr>::Read(
ui::MouseEvent::kMousePointerId)
: ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_MOUSE,
ui::MouseEvent::kMousePointerId),
- ui::EventTimeForNow()));
+ time_stamp));
break;
}
case ui::mojom::PointerKind::TOUCH: {
@@ -313,7 +316,7 @@ bool StructTraits<ui::mojom::EventDataView, EventUniquePtr>::Read(
pointer_data->brush_data->pressure,
pointer_data->brush_data->tilt_x,
pointer_data->brush_data->tilt_y),
- ui::EventTimeForNow()));
+ time_stamp));
break;
}
case ui::mojom::PointerKind::PEN:
diff --git a/chromium/ui/events/mojo/event_struct_traits.h b/chromium/ui/events/mojo/event_struct_traits.h
index f8d0e0ebafd..247d4753143 100644
--- a/chromium/ui/events/mojo/event_struct_traits.h
+++ b/chromium/ui/events/mojo/event_struct_traits.h
@@ -20,7 +20,7 @@ template <>
struct StructTraits<ui::mojom::EventDataView, EventUniquePtr> {
static ui::mojom::EventType action(const EventUniquePtr& event);
static int32_t flags(const EventUniquePtr& event);
- static int64_t time_stamp(const EventUniquePtr& event);
+ static base::TimeTicks time_stamp(const EventUniquePtr& event);
static const ui::LatencyInfo& latency(const EventUniquePtr& event);
static ui::mojom::KeyDataPtr key_data(const EventUniquePtr& event);
static ui::mojom::PointerDataPtr pointer_data(const EventUniquePtr& event);
diff --git a/chromium/ui/events/mojo/struct_traits_unittest.cc b/chromium/ui/events/mojo/struct_traits_unittest.cc
index 4f7c4a90a1d..154f603ec58 100644
--- a/chromium/ui/events/mojo/struct_traits_unittest.cc
+++ b/chromium/ui/events/mojo/struct_traits_unittest.cc
@@ -56,8 +56,9 @@ TEST_F(StructTraitsTest, KeyEvent) {
{'Z', VKEY_Z, EF_CAPS_LOCK_ON},
{'z', VKEY_Z, EF_NONE},
{ET_KEY_PRESSED, VKEY_Z, EF_NONE,
- base::TimeTicks::FromInternalValue(101)},
- {'Z', VKEY_Z, EF_NONE, base::TimeTicks::FromInternalValue(102)},
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(101)},
+ {'Z', VKEY_Z, EF_NONE,
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(102)},
};
mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy();
@@ -88,22 +89,22 @@ TEST_F(StructTraitsTest, PointerEvent) {
{ET_POINTER_DOWN, gfx::Point(10, 10), gfx::Point(20, 30), EF_NONE, 0,
PointerDetails(EventPointerType::POINTER_TYPE_MOUSE,
MouseEvent::kMousePointerId),
- base::TimeTicks()},
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(201)},
{ET_POINTER_MOVED, gfx::Point(1, 5), gfx::Point(5, 1),
EF_LEFT_MOUSE_BUTTON, EF_LEFT_MOUSE_BUTTON,
PointerDetails(EventPointerType::POINTER_TYPE_MOUSE,
MouseEvent::kMousePointerId),
- base::TimeTicks()},
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(202)},
{ET_POINTER_UP, gfx::Point(411, 130), gfx::Point(20, 30),
EF_MIDDLE_MOUSE_BUTTON | EF_RIGHT_MOUSE_BUTTON, EF_RIGHT_MOUSE_BUTTON,
PointerDetails(EventPointerType::POINTER_TYPE_MOUSE,
MouseEvent::kMousePointerId),
- base::TimeTicks()},
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(203)},
{ET_POINTER_EXITED, gfx::Point(10, 10), gfx::Point(20, 30),
EF_BACK_MOUSE_BUTTON, 0,
PointerDetails(EventPointerType::POINTER_TYPE_MOUSE,
MouseEvent::kMousePointerId),
- base::TimeTicks()},
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(204)},
// Touch pointer events:
{ET_POINTER_DOWN, gfx::Point(10, 10), gfx::Point(20, 30), EF_NONE, 0,
@@ -114,7 +115,7 @@ TEST_F(StructTraitsTest, PointerEvent) {
/* force */ 3.0f,
/* tilt_x */ 4.0f,
/* tilt_y */ 5.0f),
- base::TimeTicks()},
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(205)},
{ET_POINTER_CANCELLED, gfx::Point(120, 120), gfx::Point(2, 3), EF_NONE, 0,
PointerDetails(EventPointerType::POINTER_TYPE_TOUCH,
/* pointer_id*/ 2,
@@ -123,7 +124,7 @@ TEST_F(StructTraitsTest, PointerEvent) {
/* force */ 3.5f,
/* tilt_x */ 2.5f,
/* tilt_y */ 0.5f),
- base::TimeTicks()},
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(206)},
};
mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy();
@@ -143,18 +144,22 @@ TEST_F(StructTraitsTest, PointerEvent) {
output_ptr_event->changed_button_flags());
EXPECT_EQ(kTestData[i].pointer_details(),
output_ptr_event->pointer_details());
+ EXPECT_EQ(kTestData[i].time_stamp(), output_ptr_event->time_stamp());
}
}
TEST_F(StructTraitsTest, PointerWheelEvent) {
MouseWheelEvent kTestData[] = {
{gfx::Vector2d(11, 15), gfx::Point(3, 4), gfx::Point(40, 30),
- base::TimeTicks(), EF_LEFT_MOUSE_BUTTON, EF_LEFT_MOUSE_BUTTON},
+ 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(), EF_MIDDLE_MOUSE_BUTTON | EF_RIGHT_MOUSE_BUTTON,
+ 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(), EF_NONE, EF_NONE},
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(303), EF_NONE,
+ EF_NONE},
};
mojom::TraitsTestServicePtr proxy = GetTraitsTestProxy();
@@ -171,6 +176,7 @@ TEST_F(StructTraitsTest, PointerWheelEvent) {
output_pointer_event->root_location());
EXPECT_EQ(kTestData[i].offset(),
output_pointer_event->pointer_details().offset);
+ EXPECT_EQ(kTestData[i].time_stamp(), output_pointer_event->time_stamp());
}
}
diff --git a/chromium/ui/events/ozone/evdev/event_factory_evdev.cc b/chromium/ui/events/ozone/evdev/event_factory_evdev.cc
index 6d5aeb6c90c..9aa24612043 100644
--- a/chromium/ui/events/ozone/evdev/event_factory_evdev.cc
+++ b/chromium/ui/events/ozone/evdev/event_factory_evdev.cc
@@ -224,12 +224,6 @@ void EventFactoryEvdev::DispatchMouseMoveEvent(
gfx::PointF location = params.location;
PointerDetails details = params.pointer_details;
- if (params.flags & EF_DIRECT_INPUT) {
- details = GetTransformedEventPointerDetails(params);
- cursor_->MoveCursorTo(GetTransformedEventLocation(params));
- location = cursor_->GetLocation();
- }
-
MouseEvent event(ui::ET_MOUSE_MOVED, gfx::Point(), gfx::Point(),
params.timestamp,
modifiers_.GetModifierFlags() | params.flags,
@@ -248,12 +242,6 @@ void EventFactoryEvdev::DispatchMouseButtonEvent(
gfx::PointF location = params.location;
PointerDetails details = params.pointer_details;
- if (params.flags & EF_DIRECT_INPUT) {
- details = GetTransformedEventPointerDetails(params);
- cursor_->MoveCursorTo(GetTransformedEventLocation(params));
- location = cursor_->GetLocation();
- }
-
// Mouse buttons can be remapped, touchpad taps & clicks cannot.
unsigned int button = params.button;
if (params.allow_remap)
diff --git a/chromium/ui/events/ozone/evdev/input_controller_evdev.cc b/chromium/ui/events/ozone/evdev/input_controller_evdev.cc
index aac3e2a02a5..d31d107e45d 100644
--- a/chromium/ui/events/ozone/evdev/input_controller_evdev.cc
+++ b/chromium/ui/events/ozone/evdev/input_controller_evdev.cc
@@ -154,6 +154,11 @@ void InputControllerEvdev::SetPrimaryButtonRight(bool right) {
button_map_->UpdateButtonMap(BTN_RIGHT, right ? BTN_LEFT : BTN_RIGHT);
}
+void InputControllerEvdev::SetMouseReverseScroll(bool enabled) {
+ input_device_settings_.mouse_reverse_scroll_enabled = enabled;
+ ScheduleUpdateDeviceSettings();
+}
+
void InputControllerEvdev::SetTapToClickPaused(bool state) {
input_device_settings_.tap_to_click_paused = state;
ScheduleUpdateDeviceSettings();
diff --git a/chromium/ui/events/ozone/evdev/input_controller_evdev.h b/chromium/ui/events/ozone/evdev/input_controller_evdev.h
index 6d1adcf6282..947e84cbed0 100644
--- a/chromium/ui/events/ozone/evdev/input_controller_evdev.h
+++ b/chromium/ui/events/ozone/evdev/input_controller_evdev.h
@@ -57,6 +57,7 @@ class EVENTS_OZONE_EVDEV_EXPORT InputControllerEvdev : public InputController {
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;
void GetTouchEventLog(const base::FilePath& out_dir,
diff --git a/chromium/ui/events/ozone/evdev/input_device_factory_evdev.cc b/chromium/ui/events/ozone/evdev/input_device_factory_evdev.cc
index ab3ec281a36..895c76615c7 100644
--- a/chromium/ui/events/ozone/evdev/input_device_factory_evdev.cc
+++ b/chromium/ui/events/ozone/evdev/input_device_factory_evdev.cc
@@ -312,6 +312,9 @@ void InputDeviceFactoryEvdev::ApplyInputDeviceSettings() {
input_device_settings_.mouse_sensitivity);
SetIntPropertyForOneType(DT_MOUSE, "Scroll Sensitivity",
input_device_settings_.mouse_sensitivity);
+ SetBoolPropertyForOneType(
+ DT_MOUSE, "Mouse Reverse Scrolling",
+ input_device_settings_.mouse_reverse_scroll_enabled);
SetBoolPropertyForOneType(DT_TOUCHPAD, "Tap Paused",
input_device_settings_.tap_to_click_paused);
diff --git a/chromium/ui/events/ozone/evdev/input_device_settings_evdev.h b/chromium/ui/events/ozone/evdev/input_device_settings_evdev.h
index 1be7637e799..8b3c9a07c60 100644
--- a/chromium/ui/events/ozone/evdev/input_device_settings_evdev.h
+++ b/chromium/ui/events/ozone/evdev/input_device_settings_evdev.h
@@ -26,6 +26,7 @@ struct InputDeviceSettingsEvdev {
bool natural_scroll_enabled = false;
bool tap_to_click_paused = false;
bool touch_event_logging_enabled = true;
+ bool mouse_reverse_scroll_enabled = false;
int touchpad_sensitivity = kDefaultSensitivity;
int mouse_sensitivity = kDefaultSensitivity;
diff --git a/chromium/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc b/chromium/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
index 7b4e229e785..4deb82017c5 100644
--- a/chromium/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
+++ b/chromium/ui/events/ozone/evdev/touch_event_converter_evdev_unittest.cc
@@ -37,6 +37,11 @@ namespace {
const char kTestDevicePath[] = "/dev/input/test-device";
+// Returns a fake TimeTicks based on the given microsecond offset.
+base::TimeTicks ToTestTimeTicks(int64_t micros) {
+ return base::TimeTicks() + base::TimeDelta::FromMicroseconds(micros);
+}
+
void InitPixelTouchscreen(TouchEventConverterEvdev* device) {
EventDeviceInfo devinfo;
EXPECT_TRUE(CapabilitiesToDeviceInfo(kLinkTouchscreen, &devinfo));
@@ -330,8 +335,7 @@ TEST_F(TouchEventConverterEvdevTest, TouchMove) {
EXPECT_EQ(1u, size());
ui::TouchEventParams event = dispatched_touch_event(0);
EXPECT_EQ(ui::ET_TOUCH_PRESSED, event.type);
- EXPECT_EQ(base::TimeTicks::FromInternalValue(1427323282019203),
- event.timestamp);
+ EXPECT_EQ(ToTestTimeTicks(1427323282019203), event.timestamp);
EXPECT_EQ(295, event.location.x());
EXPECT_EQ(421, event.location.y());
EXPECT_EQ(0, event.slot);
@@ -347,8 +351,7 @@ TEST_F(TouchEventConverterEvdevTest, TouchMove) {
EXPECT_EQ(2u, size());
event = dispatched_touch_event(1);
EXPECT_EQ(ui::ET_TOUCH_MOVED, event.type);
- EXPECT_EQ(base::TimeTicks::FromInternalValue(1427323282034693),
- event.timestamp);
+ EXPECT_EQ(ToTestTimeTicks(1427323282034693), event.timestamp);
EXPECT_EQ(312, event.location.x());
EXPECT_EQ(432, event.location.y());
EXPECT_EQ(0, event.slot);
@@ -364,8 +367,7 @@ TEST_F(TouchEventConverterEvdevTest, TouchMove) {
EXPECT_EQ(3u, size());
event = dispatched_touch_event(2);
EXPECT_EQ(ui::ET_TOUCH_RELEASED, event.type);
- EXPECT_EQ(base::TimeTicks::FromInternalValue(1427323282144540),
- event.timestamp);
+ EXPECT_EQ(ToTestTimeTicks(1427323282144540), event.timestamp);
EXPECT_EQ(312, event.location.x());
EXPECT_EQ(432, event.location.y());
EXPECT_EQ(0, event.slot);
@@ -417,7 +419,7 @@ TEST_F(TouchEventConverterEvdevTest, TwoFingerGesture) {
// Move
EXPECT_EQ(ui::ET_TOUCH_MOVED, ev0.type);
- EXPECT_EQ(base::TimeTicks::FromInternalValue(0), ev0.timestamp);
+ EXPECT_EQ(ToTestTimeTicks(0), ev0.timestamp);
EXPECT_EQ(40, ev0.location.x());
EXPECT_EQ(51, ev0.location.y());
EXPECT_EQ(0, ev0.slot);
@@ -425,7 +427,7 @@ TEST_F(TouchEventConverterEvdevTest, TwoFingerGesture) {
// Press
EXPECT_EQ(ui::ET_TOUCH_PRESSED, ev1.type);
- EXPECT_EQ(base::TimeTicks::FromInternalValue(0), ev1.timestamp);
+ EXPECT_EQ(ToTestTimeTicks(0), ev1.timestamp);
EXPECT_EQ(101, ev1.location.x());
EXPECT_EQ(102, ev1.location.y());
EXPECT_EQ(1, ev1.slot);
@@ -441,7 +443,7 @@ TEST_F(TouchEventConverterEvdevTest, TwoFingerGesture) {
ev1 = dispatched_touch_event(4);
EXPECT_EQ(ui::ET_TOUCH_MOVED, ev1.type);
- EXPECT_EQ(base::TimeTicks::FromInternalValue(0), ev1.timestamp);
+ EXPECT_EQ(ToTestTimeTicks(0), ev1.timestamp);
EXPECT_EQ(40, ev1.location.x());
EXPECT_EQ(102, ev1.location.y());
EXPECT_EQ(1, ev1.slot);
@@ -458,7 +460,7 @@ TEST_F(TouchEventConverterEvdevTest, TwoFingerGesture) {
ev0 = dispatched_touch_event(5);
EXPECT_EQ(ui::ET_TOUCH_MOVED, ev0.type);
- EXPECT_EQ(base::TimeTicks::FromInternalValue(0), ev0.timestamp);
+ EXPECT_EQ(ToTestTimeTicks(0), ev0.timestamp);
EXPECT_EQ(39, ev0.location.x());
EXPECT_EQ(51, ev0.location.y());
EXPECT_EQ(0, ev0.slot);
@@ -476,14 +478,14 @@ TEST_F(TouchEventConverterEvdevTest, TwoFingerGesture) {
ev1 = dispatched_touch_event(7);
EXPECT_EQ(ui::ET_TOUCH_RELEASED, ev0.type);
- EXPECT_EQ(base::TimeTicks::FromInternalValue(0), ev0.timestamp);
+ EXPECT_EQ(ToTestTimeTicks(0), ev0.timestamp);
EXPECT_EQ(39, ev0.location.x());
EXPECT_EQ(51, ev0.location.y());
EXPECT_EQ(0, ev0.slot);
EXPECT_FLOAT_EQ(0.17647059f, ev0.pointer_details.force);
EXPECT_EQ(ui::ET_TOUCH_MOVED, ev1.type);
- EXPECT_EQ(base::TimeTicks::FromInternalValue(0), ev1.timestamp);
+ EXPECT_EQ(ToTestTimeTicks(0), ev1.timestamp);
EXPECT_EQ(38, ev1.location.x());
EXPECT_EQ(102, ev1.location.y());
EXPECT_EQ(1, ev1.slot);
@@ -499,7 +501,7 @@ TEST_F(TouchEventConverterEvdevTest, TwoFingerGesture) {
ev1 = dispatched_touch_event(8);
EXPECT_EQ(ui::ET_TOUCH_RELEASED, ev1.type);
- EXPECT_EQ(base::TimeTicks::FromInternalValue(0), ev1.timestamp);
+ EXPECT_EQ(ToTestTimeTicks(0), ev1.timestamp);
EXPECT_EQ(38, ev1.location.x());
EXPECT_EQ(102, ev1.location.y());
EXPECT_EQ(1, ev1.slot);
@@ -844,8 +846,7 @@ TEST_F(TouchEventConverterEvdevTest, ShouldUseLeftButtonIfNoTouchButton) {
EXPECT_EQ(1u, size());
ui::TouchEventParams event = dispatched_touch_event(0);
EXPECT_EQ(ui::ET_TOUCH_PRESSED, event.type);
- EXPECT_EQ(base::TimeTicks::FromInternalValue(1433965490837958),
- event.timestamp);
+ EXPECT_EQ(ToTestTimeTicks(1433965490837958), event.timestamp);
EXPECT_EQ(3654, event.location.x());
EXPECT_EQ(1055, event.location.y());
EXPECT_EQ(0, event.slot);
@@ -859,8 +860,7 @@ TEST_F(TouchEventConverterEvdevTest, ShouldUseLeftButtonIfNoTouchButton) {
EXPECT_EQ(2u, size());
event = dispatched_touch_event(1);
EXPECT_EQ(ui::ET_TOUCH_MOVED, event.type);
- EXPECT_EQ(base::TimeTicks::FromInternalValue(1433965491001953),
- event.timestamp);
+ EXPECT_EQ(ToTestTimeTicks(1433965491001953), event.timestamp);
EXPECT_EQ(3644, event.location.x());
EXPECT_EQ(1059, event.location.y());
EXPECT_EQ(0, event.slot);
@@ -874,8 +874,7 @@ TEST_F(TouchEventConverterEvdevTest, ShouldUseLeftButtonIfNoTouchButton) {
EXPECT_EQ(3u, size());
event = dispatched_touch_event(2);
EXPECT_EQ(ui::ET_TOUCH_RELEASED, event.type);
- EXPECT_EQ(base::TimeTicks::FromInternalValue(1433965491225959),
- event.timestamp);
+ EXPECT_EQ(ToTestTimeTicks(1433965491225959), event.timestamp);
EXPECT_EQ(3644, event.location.x());
EXPECT_EQ(1059, event.location.y());
EXPECT_EQ(0, event.slot);
diff --git a/chromium/ui/events/ozone/evdev/touch_filter/horizontally_aligned_touch_noise_filter.cc b/chromium/ui/events/ozone/evdev/touch_filter/horizontally_aligned_touch_noise_filter.cc
index 446bc08a208..29dd7a8ed31 100644
--- a/chromium/ui/events/ozone/evdev/touch_filter/horizontally_aligned_touch_noise_filter.cc
+++ b/chromium/ui/events/ozone/evdev/touch_filter/horizontally_aligned_touch_noise_filter.cc
@@ -41,12 +41,12 @@ void HorizontallyAlignedTouchNoiseFilter::Filter(
"Ozone.TouchNoiseFilter.HorizontallyAlignedDistance", distance);
if (distance <= kMaxDistance) {
- VLOG(2) << base::StringPrintf("Cancel tracking id %d, down at %" PRId64
- " at %f,%f near touch %d at "
- "%f,%f",
- touch.tracking_id, time.ToInternalValue(),
- touch.x, touch.y, other_touch.tracking_id,
- other_touch.x, other_touch.y);
+ VLOG(2) << base::StringPrintf(
+ "Cancel tracking id %d, down at %" PRId64
+ " at %f,%f near touch %d at "
+ "%f,%f",
+ touch.tracking_id, time.since_origin().InMicroseconds(), touch.x,
+ touch.y, other_touch.tracking_id, other_touch.x, other_touch.y);
slots_with_noise->set(touch.slot);
}
}
diff --git a/chromium/ui/events/x/events_x_unittest.cc b/chromium/ui/events/x/events_x_unittest.cc
index a7082e60259..fdd4fc2899f 100644
--- a/chromium/ui/events/x/events_x_unittest.cc
+++ b/chromium/ui/events/x/events_x_unittest.cc
@@ -211,7 +211,7 @@ TEST_F(EventsXTest, ClickCount) {
XEvent event;
gfx::Point location(5, 10);
- base::TimeDelta time_stamp = base::TimeTicks::Now() - base::TimeTicks() -
+ base::TimeDelta time_stamp = base::TimeTicks::Now().since_origin() -
base::TimeDelta::FromMilliseconds(10);
for (int i = 1; i <= 3; ++i) {
InitButtonEvent(&event, true, location, 1, 0);
@@ -540,15 +540,22 @@ TEST_F(EventsXTest, IgnoresMotionEventForMouseWheelScroll) {
}
namespace {
+
+// Returns a fake TimeTicks based on the given millisecond offset.
+base::TimeTicks TimeTicksFromMillis(int64_t millis) {
+ return base::TimeTicks() + base::TimeDelta::FromMilliseconds(millis);
+}
+
class MockTickClock : public base::TickClock {
public:
- explicit MockTickClock(uint64_t milliseconds)
- : ticks_(base::TimeTicks::FromInternalValue(milliseconds * 1000)) {}
+ explicit MockTickClock(int64_t milliseconds)
+ : ticks_(TimeTicksFromMillis(milliseconds)) {}
base::TimeTicks NowTicks() override { return ticks_; }
private:
base::TimeTicks ticks_;
};
+
} // namespace
TEST_F(EventsXTest, TimestampRolloverAndAdjustWhenDecreasing) {
@@ -556,19 +563,17 @@ TEST_F(EventsXTest, TimestampRolloverAndAdjustWhenDecreasing) {
InitButtonEvent(&event, true, gfx::Point(5, 10), 1, 0);
ResetTimestampRolloverCountersForTesting(
- base::MakeUnique<MockTickClock>(0x100000001LL));
+ base::MakeUnique<MockTickClock>(0x100000001));
event.xbutton.time = 0xFFFFFFFF;
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(0xFFFFFFFF).ToInternalValue(),
- ui::EventTimeFromNative(&event).ToInternalValue());
+ EXPECT_EQ(TimeTicksFromMillis(0xFFFFFFFF), ui::EventTimeFromNative(&event));
ResetTimestampRolloverCountersForTesting(
- base::MakeUnique<MockTickClock>(0x100000007LL));
+ base::MakeUnique<MockTickClock>(0x100000007));
event.xbutton.time = 3;
- EXPECT_EQ(
- base::TimeDelta::FromMilliseconds(0x100000000LL + 3).ToInternalValue(),
- ui::EventTimeFromNative(&event).ToInternalValue());
+ EXPECT_EQ(TimeTicksFromMillis(0x100000000 + 3),
+ ui::EventTimeFromNative(&event));
}
TEST_F(EventsXTest, NoTimestampRolloverWhenMonotonicIncreasing) {
@@ -578,18 +583,15 @@ TEST_F(EventsXTest, NoTimestampRolloverWhenMonotonicIncreasing) {
ResetTimestampRolloverCountersForTesting(base::MakeUnique<MockTickClock>(10));
event.xbutton.time = 6;
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(6).ToInternalValue(),
- ui::EventTimeFromNative(&event).ToInternalValue());
+ EXPECT_EQ(TimeTicksFromMillis(6), ui::EventTimeFromNative(&event));
event.xbutton.time = 7;
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(7).ToInternalValue(),
- ui::EventTimeFromNative(&event).ToInternalValue());
+ EXPECT_EQ(TimeTicksFromMillis(7), ui::EventTimeFromNative(&event));
ResetTimestampRolloverCountersForTesting(
base::MakeUnique<MockTickClock>(0x100000005));
event.xbutton.time = 0xFFFFFFFF;
- EXPECT_EQ(base::TimeDelta::FromMilliseconds(0xFFFFFFFF).ToInternalValue(),
- ui::EventTimeFromNative(&event).ToInternalValue());
+ EXPECT_EQ(TimeTicksFromMillis(0xFFFFFFFF), ui::EventTimeFromNative(&event));
}
} // namespace ui
diff --git a/chromium/ui/gfx/BUILD.gn b/chromium/ui/gfx/BUILD.gn
index e579efd759a..141803adf75 100644
--- a/chromium/ui/gfx/BUILD.gn
+++ b/chromium/ui/gfx/BUILD.gn
@@ -44,8 +44,6 @@ component("geometry_skia") {
component("gfx") {
sources = [
- "android/gfx_jni_registrar.cc",
- "android/gfx_jni_registrar.h",
"android/java_bitmap.cc",
"android/java_bitmap.h",
"android/view_configuration.cc",
@@ -94,6 +92,7 @@ component("gfx") {
"image/image_family.h",
"image/image_ios.mm",
"image/image_mac.mm",
+ "image/image_platform.h",
"image/image_png_rep.cc",
"image/image_png_rep.h",
"image/image_skia.cc",
@@ -206,6 +205,7 @@ component("gfx") {
"canvas_skia_paint.h",
"image/canvas_image_source.cc",
"image/canvas_image_source.h",
+ "image/image_generic.cc",
"image/image_skia_operations.cc",
"image/image_skia_operations.h",
"paint_throbber.cc",
@@ -256,7 +256,7 @@ component("gfx") {
]
# Text rendering conditions (complicated so separated out).
- if (use_aura || is_mac || (is_android && enable_vr)) {
+ if (use_aura || is_mac || (is_android && enable_vr) || is_fuchsia) {
# Mac doesn't use RenderTextHarfBuzz by default yet.
sources += [
"harfbuzz_font_skia.cc",
@@ -330,8 +330,7 @@ component("gfx") {
sources -= [ "canvas_notimplemented.cc" ]
}
- # Desktop and Android+VR only.
- if (use_aura || (!is_ios && !is_android) || (is_android && enable_vr)) {
+ if (!is_ios) {
sources += [
"paint_vector_icon.cc",
"paint_vector_icon.h",
@@ -388,6 +387,14 @@ component("gfx") {
if (use_cairo) {
configs += [ "//build/config/linux/pangocairo" ]
}
+
+ if (is_fuchsia) {
+ sources += [
+ "font_fallback_fuchsia.cc",
+ "font_render_params_fuchsia.cc",
+ "platform_font_fuchsia.cc",
+ ]
+ }
}
component("color_space") {
@@ -483,6 +490,13 @@ source_set("selection_bound_sources") {
]
}
+# Depend on this to use buffer_types.h without pulling in all of gfx.
+source_set("buffer_types") {
+ sources = [
+ "buffer_types.h",
+ ]
+}
+
# The GPU memory buffer stuff is separate from "gfx" to allow GPU-related
# things to use these files without pulling in all of gfx, which includes large
# things like Skia.
@@ -510,7 +524,6 @@ source_set("memory_buffer_sources") {
sources = [
"buffer_format_util.cc",
"buffer_format_util.h",
- "buffer_types.h",
"client_native_pixmap.h",
"client_native_pixmap_factory.cc",
"client_native_pixmap_factory.h",
@@ -529,13 +542,15 @@ source_set("memory_buffer_sources") {
sources += [
"gpu_memory_buffer.cc",
"gpu_memory_buffer.h",
- "gpu_memory_buffer_tracing.cc",
- "gpu_memory_buffer_tracing.h",
]
}
defines = [ "GFX_IMPLEMENTATION" ]
+ public_deps = [
+ ":buffer_types",
+ ]
+
deps = [
":gfx_switches",
":native_widget_types",
@@ -702,11 +717,12 @@ test("gfx_unittests") {
]
}
+ if (!is_ios) {
+ sources += [ "paint_vector_icon_unittest.cc" ]
+ }
+
if (!is_android && !is_ios) {
- sources += [
- "paint_vector_icon_unittest.cc",
- "render_text_unittest.cc",
- ]
+ sources += [ "render_text_unittest.cc" ]
}
# TODO(jschuh): crbug.com/167187 fix size_t to int truncations.
diff --git a/chromium/ui/gfx/DEPS b/chromium/ui/gfx/DEPS
index a6891ad405f..808d12b3ae0 100644
--- a/chromium/ui/gfx/DEPS
+++ b/chromium/ui/gfx/DEPS
@@ -1,5 +1,6 @@
include_rules = [
"+base",
+ "+cc/base",
"+cc/paint",
"+device/vr/features/features.h",
"+skia/ext",
diff --git a/chromium/ui/gfx/android/view_configuration.cc b/chromium/ui/gfx/android/view_configuration.cc
index a79f0f92aa3..11fe458ccab 100644
--- a/chromium/ui/gfx/android/view_configuration.cc
+++ b/chromium/ui/gfx/android/view_configuration.cc
@@ -175,8 +175,4 @@ int ViewConfiguration::GetMinScalingSpanInDips() {
return g_view_configuration.Get().min_scaling_span_in_dips();
}
-bool ViewConfiguration::RegisterViewConfiguration(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
} // namespace gfx
diff --git a/chromium/ui/gfx/android/view_configuration.h b/chromium/ui/gfx/android/view_configuration.h
index 4495a5eccc6..e7353de3d07 100644
--- a/chromium/ui/gfx/android/view_configuration.h
+++ b/chromium/ui/gfx/android/view_configuration.h
@@ -26,9 +26,6 @@ class GFX_EXPORT ViewConfiguration {
static int GetDoubleTapSlopInDips();
static int GetMinScalingSpanInDips();
-
- // Registers methods with JNI and returns true if succeeded.
- static bool RegisterViewConfiguration(JNIEnv* env);
};
} // namespace gfx
diff --git a/chromium/ui/gfx/animation/animation_container.cc b/chromium/ui/gfx/animation/animation_container.cc
index e06803d06e1..ef15c8f64c2 100644
--- a/chromium/ui/gfx/animation/animation_container.cc
+++ b/chromium/ui/gfx/animation/animation_container.cc
@@ -13,8 +13,9 @@ using base::TimeTicks;
namespace gfx {
AnimationContainer::AnimationContainer()
- : last_tick_time_(base::TimeTicks::Now()), observer_(NULL) {
-}
+ : last_tick_time_(base::TimeTicks::Now()),
+ min_timer_interval_count_(0),
+ observer_(NULL) {}
AnimationContainer::~AnimationContainer() {
// The animations own us and stop themselves before being deleted. If
@@ -29,8 +30,12 @@ void AnimationContainer::Start(AnimationContainerElement* element) {
if (elements_.empty()) {
last_tick_time_ = base::TimeTicks::Now();
SetMinTimerInterval(element->GetTimerInterval());
+ min_timer_interval_count_ = 1;
} else if (element->GetTimerInterval() < min_timer_interval_) {
SetMinTimerInterval(element->GetTimerInterval());
+ min_timer_interval_count_ = 1;
+ } else if (element->GetTimerInterval() == min_timer_interval_) {
+ min_timer_interval_count_++;
}
element->SetStartTime(last_tick_time_);
@@ -40,16 +45,27 @@ void AnimationContainer::Start(AnimationContainerElement* element) {
void AnimationContainer::Stop(AnimationContainerElement* element) {
DCHECK(elements_.count(element) > 0); // The element must be running.
+ base::TimeDelta interval = element->GetTimerInterval();
elements_.erase(element);
if (elements_.empty()) {
timer_.Stop();
+ min_timer_interval_count_ = 0;
if (observer_)
observer_->AnimationContainerEmpty(this);
- } else {
- TimeDelta min_timer_interval = GetMinInterval();
- if (min_timer_interval > min_timer_interval_)
- SetMinTimerInterval(min_timer_interval);
+ } else if (interval == min_timer_interval_) {
+ min_timer_interval_count_--;
+
+ // If the last element at the current (minimum) timer interval has been
+ // removed then go find the new minimum and the number of elements at that
+ // same minimum.
+ if (min_timer_interval_count_ == 0) {
+ std::pair<base::TimeDelta, size_t> interval_count =
+ GetMinIntervalAndCount();
+ DCHECK(interval_count.first > min_timer_interval_);
+ SetMinTimerInterval(interval_count.first);
+ min_timer_interval_count_ = interval_count.second;
+ }
}
}
@@ -87,17 +103,30 @@ void AnimationContainer::SetMinTimerInterval(base::TimeDelta delta) {
timer_.Start(FROM_HERE, min_timer_interval_, this, &AnimationContainer::Run);
}
-TimeDelta AnimationContainer::GetMinInterval() {
+std::pair<TimeDelta, size_t> AnimationContainer::GetMinIntervalAndCount()
+ const {
DCHECK(!elements_.empty());
+ // Find the minimum interval and the number of elements sharing that same
+ // interval. It is tempting to create a map of intervals -> counts in order to
+ // make this O(log n) instead of O(n). However, profiling shows that this
+ // offers no practical performance gain (the most common case is that all
+ // elements in the set share the same interval).
TimeDelta min;
+ size_t count = 1;
Elements::const_iterator i = elements_.begin();
min = (*i)->GetTimerInterval();
for (++i; i != elements_.end(); ++i) {
- if ((*i)->GetTimerInterval() < min)
- min = (*i)->GetTimerInterval();
+ auto interval = (*i)->GetTimerInterval();
+ if (interval < min) {
+ min = interval;
+ count = 1;
+ } else if (interval == min) {
+ count++;
+ }
}
- return min;
+
+ return std::make_pair(min, count);
}
} // namespace gfx
diff --git a/chromium/ui/gfx/animation/animation_container.h b/chromium/ui/gfx/animation/animation_container.h
index a19c0539d2f..58ad1ea1d01 100644
--- a/chromium/ui/gfx/animation/animation_container.h
+++ b/chromium/ui/gfx/animation/animation_container.h
@@ -5,8 +5,9 @@
#ifndef UI_GFX_ANIMATION_ANIMATION_CONTAINER_H_
#define UI_GFX_ANIMATION_ANIMATION_CONTAINER_H_
-#include <set>
+#include <utility>
+#include "base/containers/flat_set.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/time/time.h"
@@ -55,7 +56,13 @@ class ANIMATION_EXPORT AnimationContainer
private:
friend class base::RefCounted<AnimationContainer>;
- typedef std::set<AnimationContainerElement*> Elements;
+ // This set is usually quite small so a flat_set is the most obvious choice.
+ // However, in extreme cases this can grow to 100s or even 1000s of elements.
+ // Since this set is duplicated on every call to 'Run' and indexed very
+ // frequently the cache locality of the vector is more important than the
+ // costlier (but rarer) insertion. Profiling shows that flat_set continues to
+ // perform best in these cases (up to 12x faster than std::set).
+ typedef base::flat_set<AnimationContainerElement*> Elements;
~AnimationContainer();
@@ -65,8 +72,9 @@ class ANIMATION_EXPORT AnimationContainer
// Sets min_timer_interval_ and restarts the timer.
void SetMinTimerInterval(base::TimeDelta delta);
- // Returns the min timer interval of all the timers.
- base::TimeDelta GetMinInterval();
+ // Returns the min timer interval of all the timers, and the count of timers
+ // at that interval.
+ std::pair<base::TimeDelta, size_t> GetMinIntervalAndCount() const;
// Represents one of two possible values:
// . If only a single animation has been started and the timer hasn't yet
@@ -77,8 +85,14 @@ class ANIMATION_EXPORT AnimationContainer
// Set of elements (animations) being managed.
Elements elements_;
- // Minimum interval the timers run at.
+ // Minimum interval the timers run at, plus the number of timers that have
+ // been seen at that interval. The most common case is for all of the
+ // animations to run at 60Hz, in which case all of the intervals are the same.
+ // This acts as a cache of size 1, and when an animation stops and is removed
+ // it means that the linear scan for the new minimum timer can almost always
+ // be avoided.
base::TimeDelta min_timer_interval_;
+ size_t min_timer_interval_count_;
base::RepeatingTimer timer_;
diff --git a/chromium/ui/gfx/animation/animation_unittest.cc b/chromium/ui/gfx/animation/animation_unittest.cc
index 66e9d98e085..bf1cf0138f1 100644
--- a/chromium/ui/gfx/animation/animation_unittest.cc
+++ b/chromium/ui/gfx/animation/animation_unittest.cc
@@ -2,7 +2,6 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
#include "build/build_config.h"
@@ -79,7 +78,7 @@ class DeletingAnimationDelegate : public AnimationDelegate {
public:
void AnimationEnded(const Animation* animation) override {
delete animation;
- base::MessageLoop::current()->QuitWhenIdle();
+ base::RunLoop::QuitCurrentWhenIdleDeprecated();
}
};
diff --git a/chromium/ui/gfx/animation/linear_animation.cc b/chromium/ui/gfx/animation/linear_animation.cc
index 2886a87aad5..7181214d0fe 100644
--- a/chromium/ui/gfx/animation/linear_animation.cc
+++ b/chromium/ui/gfx/animation/linear_animation.cc
@@ -21,6 +21,8 @@ static base::TimeDelta CalculateInterval(int frame_rate) {
return base::TimeDelta::FromMicroseconds(timer_interval);
}
+const int LinearAnimation::kDefaultFrameRate = 60;
+
LinearAnimation::LinearAnimation(AnimationDelegate* delegate, int frame_rate)
: LinearAnimation({}, frame_rate, delegate) {}
diff --git a/chromium/ui/gfx/animation/linear_animation.h b/chromium/ui/gfx/animation/linear_animation.h
index 9f3654d442a..d1393da0fd0 100644
--- a/chromium/ui/gfx/animation/linear_animation.h
+++ b/chromium/ui/gfx/animation/linear_animation.h
@@ -18,7 +18,7 @@ class AnimationDelegate;
class ANIMATION_EXPORT LinearAnimation : public Animation {
public:
// Default frame rate (hz).
- static const int kDefaultFrameRate = 60;
+ static const int kDefaultFrameRate;
// Initializes everything except the duration.
//
diff --git a/chromium/ui/gfx/animation/test_animation_delegate.h b/chromium/ui/gfx/animation/test_animation_delegate.h
index 6cc65afbc7e..3c40a8993e3 100644
--- a/chromium/ui/gfx/animation/test_animation_delegate.h
+++ b/chromium/ui/gfx/animation/test_animation_delegate.h
@@ -6,7 +6,7 @@
#define UI_GFX_ANIMATION_TEST_ANIMATION_DELEGATE_H_
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "ui/gfx/animation/animation_delegate.h"
namespace gfx {
@@ -20,13 +20,13 @@ class TestAnimationDelegate : public AnimationDelegate {
virtual void AnimationEnded(const Animation* animation) {
finished_ = true;
- base::MessageLoop::current()->QuitWhenIdle();
+ base::RunLoop::QuitCurrentWhenIdleDeprecated();
}
virtual void AnimationCanceled(const Animation* animation) {
finished_ = true;
canceled_ = true;
- base::MessageLoop::current()->QuitWhenIdle();
+ base::RunLoop::QuitCurrentWhenIdleDeprecated();
}
bool finished() const {
diff --git a/chromium/ui/gfx/animation/tween.cc b/chromium/ui/gfx/animation/tween.cc
index 1cebe30c4ae..1fced2c368a 100644
--- a/chromium/ui/gfx/animation/tween.cc
+++ b/chromium/ui/gfx/animation/tween.cc
@@ -98,8 +98,8 @@ uint8_t BlendColorComponents(uint8_t start,
}
double TimeDeltaDivide(base::TimeDelta dividend, base::TimeDelta divisor) {
- return static_cast<double>(dividend.ToInternalValue()) /
- static_cast<double>(divisor.ToInternalValue());
+ return static_cast<double>(dividend.InMicroseconds()) /
+ static_cast<double>(divisor.InMicroseconds());
}
} // namespace
diff --git a/chromium/ui/gfx/buffer_types.h b/chromium/ui/gfx/buffer_types.h
index 9cb5b7b6ee5..b35f587576f 100644
--- a/chromium/ui/gfx/buffer_types.h
+++ b/chromium/ui/gfx/buffer_types.h
@@ -37,12 +37,18 @@ enum class BufferFormat {
// by the CPU. *_CPU_READ_WRITE_PERSISTENT adds the additional condition that
// successive Map() calls (with Unmap() calls between) will return a pointer to
// the same memory contents. SCANOUT implies GPU_READ_WRITE.
+// *_VDA_WRITE is for cases where a video decode accellerator writes into
+// the buffers.
+
// TODO(reveman): Add GPU_READ_WRITE for use-cases where SCANOUT is not
// required.
enum class BufferUsage {
GPU_READ,
SCANOUT,
+ // SCANOUT_CAMERA_READ_WRITE implies CPU_READ_WRITE.
+ SCANOUT_CAMERA_READ_WRITE,
SCANOUT_CPU_READ_WRITE,
+ SCANOUT_VDA_WRITE,
GPU_READ_CPU_READ_WRITE,
// TODO(reveman): Merge this with GPU_READ_CPU_READ_WRITE when SurfaceTexture
// backed buffers are single buffered and support it.
diff --git a/chromium/ui/gfx/canvas.cc b/chromium/ui/gfx/canvas.cc
index 414c2c90e8d..ff5f8a8373c 100644
--- a/chromium/ui/gfx/canvas.cc
+++ b/chromium/ui/gfx/canvas.cc
@@ -287,15 +287,19 @@ void Canvas::Draw1pxLine(PointF p1, PointF p2, SkColor color) {
void Canvas::DrawCircle(const Point& center_point,
int radius,
const cc::PaintFlags& flags) {
- DrawCircle(PointF(center_point), radius, flags);
+ canvas_->drawOval(
+ SkRect::MakeLTRB(center_point.x() - radius, center_point.y() - radius,
+ center_point.x() + radius, center_point.y() + radius),
+ flags);
}
void Canvas::DrawCircle(const PointF& center_point,
float radius,
const cc::PaintFlags& flags) {
- canvas_->drawCircle(SkFloatToScalar(center_point.x()),
- SkFloatToScalar(center_point.y()),
- SkFloatToScalar(radius), flags);
+ canvas_->drawOval(
+ SkRect::MakeLTRB(center_point.x() - radius, center_point.y() - radius,
+ center_point.x() + radius, center_point.y() + radius),
+ flags);
}
void Canvas::DrawRoundRect(const Rect& rect,
diff --git a/chromium/ui/gfx/color_space.cc b/chromium/ui/gfx/color_space.cc
index 96b9306e739..f6352710c37 100644
--- a/chromium/ui/gfx/color_space.cc
+++ b/chromium/ui/gfx/color_space.cc
@@ -35,6 +35,14 @@ ColorSpace::ColorSpace(PrimaryID primaries,
matrix_(matrix),
range_(range) {}
+ColorSpace::ColorSpace(PrimaryID primaries,
+ const SkColorSpaceTransferFn& fn,
+ MatrixID matrix,
+ RangeID range)
+ : primaries_(primaries), matrix_(matrix), range_(range) {
+ SetCustomTransferFunction(fn);
+}
+
ColorSpace::ColorSpace(const ColorSpace& other)
: primaries_(other.primaries_),
transfer_(other.transfer_),
@@ -92,17 +100,22 @@ ColorSpace ColorSpace::CreateCustom(const SkMatrix44& to_XYZD50,
result.custom_primary_matrix_[3 * row + col] = to_XYZD50.get(row, col);
}
}
- result.custom_transfer_params_[0] = fn.fA;
- result.custom_transfer_params_[1] = fn.fB;
- result.custom_transfer_params_[2] = fn.fC;
- result.custom_transfer_params_[3] = fn.fD;
- result.custom_transfer_params_[4] = fn.fE;
- result.custom_transfer_params_[5] = fn.fF;
- result.custom_transfer_params_[6] = fn.fG;
- // TODO(ccameron): Use enums for near matches to know color spaces.
+ result.SetCustomTransferFunction(fn);
return result;
}
+void ColorSpace::SetCustomTransferFunction(const SkColorSpaceTransferFn& fn) {
+ custom_transfer_params_[0] = fn.fA;
+ custom_transfer_params_[1] = fn.fB;
+ custom_transfer_params_[2] = fn.fC;
+ custom_transfer_params_[3] = fn.fD;
+ custom_transfer_params_[4] = fn.fE;
+ custom_transfer_params_[5] = fn.fF;
+ custom_transfer_params_[6] = fn.fG;
+ // TODO(ccameron): Use enums for near matches to know color spaces.
+ transfer_ = TransferID::CUSTOM;
+}
+
// static
ColorSpace ColorSpace::CreateCustom(const SkMatrix44& to_XYZD50,
ColorSpace::TransferID transfer_id) {
@@ -154,14 +167,23 @@ bool ColorSpace::operator==(const ColorSpace& other) const {
if (primaries_ != other.primaries_ || transfer_ != other.transfer_ ||
matrix_ != other.matrix_ || range_ != other.range_)
return false;
- if (primaries_ == PrimaryID::CUSTOM &&
- memcmp(custom_primary_matrix_, other.custom_primary_matrix_,
- sizeof(custom_primary_matrix_)))
- return false;
- if (transfer_ == TransferID::CUSTOM &&
- memcmp(custom_transfer_params_, other.custom_transfer_params_,
- sizeof(custom_transfer_params_)))
- return false;
+ if (primaries_ == PrimaryID::CUSTOM) {
+ if (memcmp(custom_primary_matrix_, other.custom_primary_matrix_,
+ sizeof(custom_primary_matrix_))) {
+ return false;
+ }
+ }
+ if (transfer_ == TransferID::CUSTOM) {
+ if (memcmp(custom_transfer_params_, other.custom_transfer_params_,
+ sizeof(custom_transfer_params_))) {
+ return false;
+ }
+ }
+ if (primaries_ == PrimaryID::ICC_BASED ||
+ transfer_ == TransferID::ICC_BASED) {
+ if (icc_profile_id_ != other.icc_profile_id_)
+ return false;
+ }
return true;
}
@@ -191,8 +213,12 @@ ColorSpace ColorSpace::GetParametricApproximation() const {
// Query the ICC profile, if available, for the parametric approximation.
ICCProfile icc_profile;
- if (GetICCProfile(&icc_profile))
+ if (icc_profile_id_ && GetICCProfile(&icc_profile)) {
return icc_profile.GetParametricColorSpace();
+ } else {
+ DLOG(ERROR)
+ << "Unable to acquire ICC profile for parametric approximation.";
+ }
// Fall back to sRGB if the ICC profile is no longer cached.
return CreateSRGB();
@@ -281,8 +307,10 @@ std::string ColorSpace::ToString() const {
ss << ", transfer:";
if (transfer_ == TransferID::CUSTOM) {
ss << "[";
- for (size_t i = 0; i < 7; ++i)
+ for (size_t i = 0; i < 7; ++i) {
ss << custom_transfer_params_[i];
+ ss << ",";
+ }
ss << "]";
} else {
ss << static_cast<int>(transfer_);
@@ -303,6 +331,26 @@ ColorSpace ColorSpace::GetAsFullRangeRGB() const {
return result;
}
+ColorSpace ColorSpace::GetRasterColorSpace() const {
+ // Rasterization can only be done into parametric color spaces.
+ if (!IsParametric())
+ return GetParametricApproximation();
+ // Rasterization doesn't support more than 8 bit unorm values. If the output
+ // space has an extended range, use Display P3 for the rasterization space,
+ // to get a somewhat wider color gamut.
+ if (HasExtendedSkTransferFn())
+ return CreateDisplayP3D65();
+ return *this;
+}
+
+ColorSpace ColorSpace::GetBlendingColorSpace() const {
+ // HDR output on windows requires output have a linear transfer function.
+ // Linear blending breaks the web, so use extended-sRGB for blending.
+ if (transfer_ == TransferID::LINEAR_HDR)
+ return CreateExtendedSRGB();
+ return *this;
+}
+
sk_sp<SkColorSpace> ColorSpace::ToSkColorSpace() const {
// If we got a specific SkColorSpace from the ICCProfile that this color space
// was created from, use that.
@@ -423,6 +471,47 @@ bool ColorSpace::GetICCProfile(ICCProfile* icc_profile) const {
return true;
}
+bool ColorSpace::GetICCProfileData(std::vector<char>* output_data) const {
+ if (!IsValid()) {
+ DLOG(ERROR) << "Cannot fetch ICCProfile for invalid space.";
+ return false;
+ }
+ if (matrix_ != MatrixID::RGB) {
+ DLOG(ERROR) << "Not creating non-RGB ICCProfile";
+ return false;
+ }
+ if (range_ != RangeID::FULL) {
+ DLOG(ERROR) << "Not creating non-full-range ICCProfile";
+ return false;
+ }
+
+ // If this was created from an ICC profile, retrieve that exact profile.
+ ICCProfile icc_profile;
+ if (ICCProfile::FromId(icc_profile_id_, &icc_profile)) {
+ *output_data = icc_profile.data_;
+ return true;
+ }
+
+ // Otherwise, construct an ICC profile based on the best approximated
+ // primaries and matrix.
+ SkMatrix44 to_XYZD50_matrix;
+ GetPrimaryMatrix(&to_XYZD50_matrix);
+ SkColorSpaceTransferFn fn;
+ if (!GetTransferFunction(&fn)) {
+ DLOG(ERROR) << "Failed to get ColorSpace transfer function for ICCProfile.";
+ return false;
+ }
+ sk_sp<SkData> data = SkICC::WriteToICC(fn, to_XYZD50_matrix);
+ if (!data || !data->size()) {
+ DLOG(ERROR) << "Failed to create SkICC.";
+ return false;
+ }
+ const char* data_as_char = reinterpret_cast<const char*>(data->data());
+ output_data->insert(output_data->begin(), data_as_char,
+ data_as_char + data->size());
+ return true;
+}
+
void ColorSpace::GetPrimaryMatrix(SkMatrix44* to_XYZD50) const {
SkColorSpacePrimaries primaries = {0};
switch (primaries_) {
@@ -621,16 +710,6 @@ bool ColorSpace::GetTransferFunction(SkColorSpaceTransferFn* fn) const {
case ColorSpace::TransferID::GAMMA28:
fn->fG = 2.8f;
return true;
- case ColorSpace::TransferID::BT709:
- case ColorSpace::TransferID::SMPTE170M:
- case ColorSpace::TransferID::BT2020_10:
- case ColorSpace::TransferID::BT2020_12:
- fn->fA = 0.909672431050f;
- fn->fB = 0.090327568950f;
- fn->fC = 0.222222222222f;
- fn->fD = 0.081242862158f;
- fn->fG = 2.222222222222f;
- return true;
case ColorSpace::TransferID::SMPTE240M:
fn->fA = 0.899626676224f;
fn->fB = 0.100373323776f;
@@ -638,6 +717,19 @@ bool ColorSpace::GetTransferFunction(SkColorSpaceTransferFn* fn) const {
fn->fD = 0.091286342118f;
fn->fG = 2.222222222222f;
return true;
+ case ColorSpace::TransferID::BT709:
+ case ColorSpace::TransferID::SMPTE170M:
+ case ColorSpace::TransferID::BT2020_10:
+ case ColorSpace::TransferID::BT2020_12:
+ // With respect to rendering BT709
+ // * SMPTE 1886 suggests that we should be using gamma 2.4.
+ // * Most displays actually use a gamma of 2.2, and most media playing
+ // software uses the sRGB transfer function.
+ // * User studies shows that users don't really care.
+ // * Apple's CoreVideo uses gamma=1.961.
+ // Bearing all of that in mind, use the same transfer funciton as sRGB,
+ // which will allow more optimization, and will more closely match other
+ // media players.
case ColorSpace::TransferID::IEC61966_2_1:
case ColorSpace::TransferID::IEC61966_2_1_HDR:
fn->fA = 0.947867345704f;
diff --git a/chromium/ui/gfx/color_space.h b/chromium/ui/gfx/color_space.h
index 61574a5fcb8..8a514de26be 100644
--- a/chromium/ui/gfx/color_space.h
+++ b/chromium/ui/gfx/color_space.h
@@ -7,6 +7,7 @@
#include <stdint.h>
#include <ostream>
+#include <vector>
#include "base/gtest_prod_util.h"
#include "base/macros.h"
@@ -22,6 +23,7 @@ struct ParamTraits;
namespace gfx {
class ICCProfile;
+class ICCProfileCache;
// Used to represet a color space for the purpose of color conversion.
// This is designed to be safe and compact enough to send over IPC
@@ -124,6 +126,10 @@ class COLOR_SPACE_EXPORT ColorSpace {
TransferID transfer,
MatrixID matrix,
RangeID full_range);
+ ColorSpace(PrimaryID primaries,
+ const SkColorSpaceTransferFn& fn,
+ MatrixID matrix,
+ RangeID full_range);
ColorSpace(const ColorSpace& other);
ColorSpace(ColorSpace&& other);
ColorSpace& operator=(const ColorSpace& other);
@@ -143,6 +149,7 @@ class COLOR_SPACE_EXPORT ColorSpace {
// Extended sRGB matches sRGB for values in [0, 1], and extends the transfer
// function to all real values.
static ColorSpace CreateExtendedSRGB();
+
// scRGB uses the same primaries as sRGB but has a linear transfer function
// for all real values.
static ColorSpace CreateSCRGBLinear();
@@ -160,18 +167,28 @@ class COLOR_SPACE_EXPORT ColorSpace {
// Returns true if the decoded values can be outside of the 0.0-1.0 range.
bool IsHDR() const;
+
// Returns true if the encoded values can be outside of the 0.0-1.0 range.
bool FullRangeEncodedValues() const;
// Returns true if this color space can be represented parametrically.
bool IsParametric() const;
+
// Return a parametric approximation of this color space (if it is not already
// parametric).
- gfx::ColorSpace GetParametricApproximation() const;
+ ColorSpace GetParametricApproximation() const;
// Return this color space with any range adjust or YUV to RGB conversion
// stripped off.
- gfx::ColorSpace GetAsFullRangeRGB() const;
+ ColorSpace GetAsFullRangeRGB() const;
+
+ // If |this| is the final output color space, return the color space that
+ // would be appropriate for rasterization.
+ ColorSpace GetRasterColorSpace() const;
+
+ // If |this| is the final output color space, return the color space that
+ // would be appropriate for blending.
+ ColorSpace GetBlendingColorSpace() const;
// This will return nullptr for non-RGB spaces, spaces with non-FULL
// range, and unspecified spaces.
@@ -180,6 +197,7 @@ class COLOR_SPACE_EXPORT ColorSpace {
// Populate |icc_profile| with an ICC profile that represents this color
// space. Returns false if this space is not representable.
bool GetICCProfile(ICCProfile* icc_profile) const;
+ bool GetICCProfileData(std::vector<char>* data) const;
void GetPrimaryMatrix(SkMatrix44* to_XYZD50) const;
bool GetTransferFunction(SkColorSpaceTransferFn* fn) const;
@@ -190,6 +208,8 @@ class COLOR_SPACE_EXPORT ColorSpace {
void GetRangeAdjustMatrix(SkMatrix44* matrix) const;
private:
+ void SetCustomTransferFunction(const SkColorSpaceTransferFn& fn);
+
// Returns true if the transfer function is defined by an
// SkColorSpaceTransferFn which is extended to all real values.
bool HasExtendedSkTransferFn() const;
@@ -213,10 +233,11 @@ class COLOR_SPACE_EXPORT ColorSpace {
sk_sp<SkColorSpace> icc_profile_sk_color_space_;
friend class ICCProfile;
+ friend class ICCProfileCache;
friend class ColorTransform;
friend class ColorTransformInternal;
friend class ColorSpaceWin;
- friend struct IPC::ParamTraits<gfx::ColorSpace>;
+ friend struct IPC::ParamTraits<ColorSpace>;
FRIEND_TEST_ALL_PREFIXES(SimpleColorSpace, GetColorSpace);
};
diff --git a/chromium/ui/gfx/color_space_unittest.cc b/chromium/ui/gfx/color_space_unittest.cc
index 211604c14fb..bef60b8f80c 100644
--- a/chromium/ui/gfx/color_space_unittest.cc
+++ b/chromium/ui/gfx/color_space_unittest.cc
@@ -239,6 +239,23 @@ TEST(ColorSpace, ApproximateTransferFnBadMatch) {
}
}
+TEST(ColorSpace, RasterAndBlend) {
+ ColorSpace display_color_space;
+
+ // A linear transfer function being used for HDR should be blended using an
+ // sRGB-like transfer function.
+ display_color_space = ColorSpace::CreateSCRGBLinear();
+ EXPECT_EQ(ColorSpace::CreateExtendedSRGB(),
+ display_color_space.GetBlendingColorSpace());
+ EXPECT_EQ(ColorSpace::CreateDisplayP3D65(),
+ display_color_space.GetRasterColorSpace());
+
+ // If not used for HDR, a linear transfer function should be left unchanged.
+ display_color_space = ColorSpace::CreateXYZD50();
+ EXPECT_EQ(display_color_space, display_color_space.GetBlendingColorSpace());
+ EXPECT_EQ(display_color_space, display_color_space.GetRasterColorSpace());
+}
+
TEST(ColorSpace, ToSkColorSpace) {
const size_t kNumTests = 4;
ColorSpace color_spaces[kNumTests] = {
diff --git a/chromium/ui/gfx/color_transform.cc b/chromium/ui/gfx/color_transform.cc
index f3c3041fde6..3c31fb3f9f5 100644
--- a/chromium/ui/gfx/color_transform.cc
+++ b/chromium/ui/gfx/color_transform.cc
@@ -811,16 +811,6 @@ void ColorTransformInternal::AppendColorSpaceToColorSpaceTransform(
ColorTransform::Intent intent) {
if (intent == ColorTransform::Intent::INTENT_PERCEPTUAL) {
switch (src.transfer_) {
- case ColorSpace::TransferID::BT709:
- case ColorSpace::TransferID::SMPTE170M:
- // SMPTE 1886 suggests that we should be using gamma 2.4 for BT709
- // content. However, most displays actually use a gamma of 2.2, and
- // user studies shows that users don't really care. Using the same
- // gamma as the display will let us optimize a lot more, so lets stick
- // with using the SRGB transfer function.
- src.transfer_ = ColorSpace::TransferID::IEC61966_2_1;
- break;
-
case ColorSpace::TransferID::SMPTEST2084:
if (!dst.IsHDR()) {
// We don't have an HDR display, so replace SMPTE 2084 with
diff --git a/chromium/ui/gfx/color_transform_unittest.cc b/chromium/ui/gfx/color_transform_unittest.cc
index d5217a77012..906adedceb8 100644
--- a/chromium/ui/gfx/color_transform_unittest.cc
+++ b/chromium/ui/gfx/color_transform_unittest.cc
@@ -133,6 +133,14 @@ TEST(SimpleColorSpace, TransferFnCancel) {
ColorTransform::NewColorTransform(
bt709, gamma24, ColorTransform::Intent::INTENT_PERCEPTUAL));
EXPECT_EQ(bt709_to_gamma24->NumberOfStepsForTesting(), 2u);
+
+ // Rec 601 YUV to RGB conversion should have a single step.
+ gfx::ColorSpace rec601 = gfx::ColorSpace::CreateREC601();
+ std::unique_ptr<ColorTransform> rec601_yuv_to_rgb(
+ ColorTransform::NewColorTransform(
+ rec601, rec601.GetAsFullRangeRGB(),
+ ColorTransform::Intent::INTENT_PERCEPTUAL));
+ EXPECT_EQ(rec601_yuv_to_rgb->NumberOfStepsForTesting(), 1u);
}
TEST(SimpleColorSpace, SRGBFromICCAndNotICC) {
diff --git a/chromium/ui/gfx/font_fallback_fuchsia.cc b/chromium/ui/gfx/font_fallback_fuchsia.cc
new file mode 100644
index 00000000000..bfdc7aa2ce9
--- /dev/null
+++ b/chromium/ui/gfx/font_fallback_fuchsia.cc
@@ -0,0 +1,18 @@
+// 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/gfx/font_fallback.h"
+
+#include <string>
+#include <vector>
+
+namespace gfx {
+
+std::vector<Font> GetFallbackFonts(const Font& font) {
+ // TODO(fuchsia): Stubbed while bringing up headless build, see
+ // https://crbug.com/743296.
+ return std::vector<Font>();
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/font_render_params.h b/chromium/ui/gfx/font_render_params.h
index ade3672f493..39d72e35203 100644
--- a/chromium/ui/gfx/font_render_params.h
+++ b/chromium/ui/gfx/font_render_params.h
@@ -113,8 +113,7 @@ GFX_EXPORT FontRenderParams GetFontRenderParams(
GFX_EXPORT void ClearFontRenderParamsCacheForTest();
#endif
-#if defined(OS_CHROMEOS) || defined(OS_LINUX) || \
- (defined(OS_ANDROID) && BUILDFLAG(ENABLE_VR))
+#if defined(OS_LINUX) || (defined(OS_ANDROID) && BUILDFLAG(ENABLE_VR))
// Gets the device scale factor to query the FontRenderParams.
GFX_EXPORT float GetFontRenderParamsDeviceScaleFactor();
diff --git a/chromium/ui/gfx/font_render_params_fuchsia.cc b/chromium/ui/gfx/font_render_params_fuchsia.cc
new file mode 100644
index 00000000000..f693f926c22
--- /dev/null
+++ b/chromium/ui/gfx/font_render_params_fuchsia.cc
@@ -0,0 +1,38 @@
+// 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/gfx/font_render_params.h"
+
+#include "base/logging.h"
+#include "base/macros.h"
+
+namespace gfx {
+
+namespace {
+
+// Returns the system's default settings.
+FontRenderParams LoadDefaults() {
+ FontRenderParams params;
+ params.antialiasing = true;
+ params.autohinter = true;
+ params.use_bitmaps = true;
+ params.subpixel_rendering = FontRenderParams::SUBPIXEL_RENDERING_NONE;
+ params.subpixel_positioning = true;
+ params.hinting = FontRenderParams::HINTING_SLIGHT;
+
+ return params;
+}
+
+} // namespace
+
+FontRenderParams GetFontRenderParams(const FontRenderParamsQuery& query,
+ std::string* family_out) {
+ if (family_out)
+ NOTIMPLEMENTED();
+ // Customized font rendering settings are not supported, only defaults.
+ CR_DEFINE_STATIC_LOCAL(const gfx::FontRenderParams, params, (LoadDefaults()));
+ return params;
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/geometry/point.h b/chromium/ui/gfx/geometry/point.h
index bb248d5432b..b1ba5065de4 100644
--- a/chromium/ui/gfx/geometry/point.h
+++ b/chromium/ui/gfx/geometry/point.h
@@ -9,7 +9,7 @@
#include <string>
#include <tuple>
-#include "base/numerics/saturated_arithmetic.h"
+#include "base/numerics/clamped_math.h"
#include "build/build_config.h"
#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/gfx_export.h"
@@ -56,18 +56,18 @@ class GFX_EXPORT Point {
}
void Offset(int delta_x, int delta_y) {
- x_ = base::SaturatedAddition(x_, delta_x);
- y_ = base::SaturatedAddition(y_, delta_y);
+ x_ = base::ClampAdd(x_, delta_x);
+ y_ = base::ClampAdd(y_, delta_y);
}
void operator+=(const Vector2d& vector) {
- x_ = base::SaturatedAddition(x_, vector.x());
- y_ = base::SaturatedAddition(y_, vector.y());
+ x_ = base::ClampAdd(x_, vector.x());
+ y_ = base::ClampAdd(y_, vector.y());
}
void operator-=(const Vector2d& vector) {
- x_ = base::SaturatedSubtraction(x_, vector.x());
- y_ = base::SaturatedSubtraction(y_, vector.y());
+ x_ = base::ClampSub(x_, vector.x());
+ y_ = base::ClampSub(y_, vector.y());
}
void SetToMin(const Point& other);
@@ -116,8 +116,8 @@ inline Point operator-(const Point& lhs, const Vector2d& rhs) {
}
inline Vector2d operator-(const Point& lhs, const Point& rhs) {
- return Vector2d(base::SaturatedSubtraction(lhs.x(), rhs.x()),
- base::SaturatedSubtraction(lhs.y(), rhs.y()));
+ return Vector2d(base::ClampSub(lhs.x(), rhs.x()),
+ base::ClampSub(lhs.y(), rhs.y()));
}
inline Point PointAtOffsetFromOrigin(const Vector2d& offset_from_origin) {
diff --git a/chromium/ui/gfx/geometry/rect.cc b/chromium/ui/gfx/geometry/rect.cc
index b5ceda58291..63c0bbf04f0 100644
--- a/chromium/ui/gfx/geometry/rect.cc
+++ b/chromium/ui/gfx/geometry/rect.cc
@@ -15,7 +15,7 @@
#endif
#include "base/logging.h"
-#include "base/numerics/saturated_arithmetic.h"
+#include "base/numerics/clamped_math.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "ui/gfx/geometry/insets.h"
@@ -69,8 +69,8 @@ static void SaturatedClampRange(int min, int max, int* origin, int* span) {
return;
}
- int effective_span = base::SaturatedSubtraction(max, min);
- int span_loss = base::SaturatedSubtraction(max, min + effective_span);
+ int effective_span = base::ClampSub(max, min);
+ int span_loss = base::ClampSub(max, min + effective_span);
// If the desired width is within the limits of ints, we can just
// use the simple computations to represent the range precisely.
@@ -83,12 +83,12 @@ static void SaturatedClampRange(int min, int max, int* origin, int* span) {
// Now we have to approximate. If one of min or max is close enough
// to zero we choose to represent that one precisely. The other side is
// probably practically "infinite", so we move it.
- if (base::SaturatedAbsolute(max) < std::numeric_limits<int>::max() / 2) {
+ constexpr unsigned kMaxDimension = std::numeric_limits<int>::max() / 2;
+ if (base::SafeUnsignedAbs(max) < kMaxDimension) {
// Maintain origin + span == max.
*span = effective_span;
*origin = max - effective_span;
- } else if (base::SaturatedAbsolute(min) <
- std::numeric_limits<int>::max() / 2) {
+ } else if (base::SafeUnsignedAbs(min) < kMaxDimension) {
// Maintain origin == min.
*span = effective_span;
*origin = min;
@@ -116,10 +116,8 @@ void Rect::Inset(int left, int top, int right, int bottom) {
origin_ += Vector2d(left, top);
// left+right might overflow/underflow, but width() - (left+right) might
// overflow as well.
- set_width(base::SaturatedSubtraction(width(),
- base::SaturatedAddition(left, right)));
- set_height(base::SaturatedSubtraction(height(),
- base::SaturatedAddition(top, bottom)));
+ set_width(base::ClampSub(width(), base::ClampAdd(left, right)));
+ set_height(base::ClampSub(height(), base::ClampAdd(top, bottom)));
}
void Rect::Offset(int horizontal, int vertical) {
diff --git a/chromium/ui/gfx/geometry/rect.h b/chromium/ui/gfx/geometry/rect.h
index 1858d44d2c7..c33d4a7bae6 100644
--- a/chromium/ui/gfx/geometry/rect.h
+++ b/chromium/ui/gfx/geometry/rect.h
@@ -227,7 +227,7 @@ class GFX_EXPORT Rect {
// Clamp the size to avoid integer overflow in bottom() and right().
// This returns the width given an origin and a width.
- // TODO(enne): this should probably use base::SaturatedAddition, but that
+ // TODO(enne): this should probably use base::ClampAdd, but that
// function is not a constexpr.
static constexpr int GetClampedValue(int origin, int size) {
return AddWouldOverflow(origin, size)
@@ -340,6 +340,41 @@ inline Rect ScaleToEnclosedRect(const Rect& rect, float scale) {
return ScaleToEnclosedRect(rect, scale, scale);
}
+// Scales |rect| by scaling its four corner points. If the corner points lie on
+// non-integral coordinate after scaling, their values are rounded to the
+// nearest integer.
+// This is helpful during layout when relative positions of multiple gfx::Rect
+// in a given coordinate space needs to be same after scaling as it was before
+// scaling. ie. this gives a lossless relative positioning of rects.
+inline Rect ScaleToRoundedRect(const Rect& rect, float x_scale, float y_scale) {
+ if (x_scale == 1.f && y_scale == 1.f)
+ return rect;
+
+ DCHECK(
+ base::IsValueInRangeForNumericType<int>(std::round(rect.x() * x_scale)));
+ DCHECK(
+ base::IsValueInRangeForNumericType<int>(std::round(rect.y() * y_scale)));
+ DCHECK(base::IsValueInRangeForNumericType<int>(
+ std::round(rect.right() * x_scale)));
+ DCHECK(base::IsValueInRangeForNumericType<int>(
+ std::round(rect.bottom() * y_scale)));
+
+ int x = static_cast<int>(std::round(rect.x() * x_scale));
+ int y = static_cast<int>(std::round(rect.y() * y_scale));
+ int r = rect.width() == 0
+ ? x
+ : static_cast<int>(std::round(rect.right() * x_scale));
+ int b = rect.height() == 0
+ ? y
+ : static_cast<int>(std::round(rect.bottom() * y_scale));
+
+ return Rect(x, y, r - x, b - y);
+}
+
+inline Rect ScaleToRoundedRect(const Rect& rect, float scale) {
+ return ScaleToRoundedRect(rect, scale, scale);
+}
+
// 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
// test. This should not be used in production code - call ToString() instead.
diff --git a/chromium/ui/gfx/geometry/size.cc b/chromium/ui/gfx/geometry/size.cc
index 69486723a1d..781b84d7f51 100644
--- a/chromium/ui/gfx/geometry/size.cc
+++ b/chromium/ui/gfx/geometry/size.cc
@@ -12,8 +12,8 @@
#include <ApplicationServices/ApplicationServices.h>
#endif
+#include "base/numerics/clamped_math.h"
#include "base/numerics/safe_math.h"
-#include "base/numerics/saturated_arithmetic.h"
#include "base/strings/stringprintf.h"
#include "build/build_config.h"
#include "ui/gfx/geometry/safe_integer_conversions.h"
@@ -58,8 +58,8 @@ base::CheckedNumeric<int> Size::GetCheckedArea() const {
}
void Size::Enlarge(int grow_width, int grow_height) {
- SetSize(base::SaturatedAddition(width(), grow_width),
- base::SaturatedAddition(height(), grow_height));
+ SetSize(base::ClampAdd(width(), grow_width),
+ base::ClampAdd(height(), grow_height));
}
void Size::SetToMin(const Size& other) {
diff --git a/chromium/ui/gfx/geometry/vector2d.cc b/chromium/ui/gfx/geometry/vector2d.cc
index 2b4875c39cb..0ce3b20baa5 100644
--- a/chromium/ui/gfx/geometry/vector2d.cc
+++ b/chromium/ui/gfx/geometry/vector2d.cc
@@ -6,7 +6,7 @@
#include <cmath>
-#include "base/numerics/saturated_arithmetic.h"
+#include "base/numerics/clamped_math.h"
#include "base/strings/stringprintf.h"
namespace gfx {
@@ -16,13 +16,13 @@ bool Vector2d::IsZero() const {
}
void Vector2d::Add(const Vector2d& other) {
- x_ = base::SaturatedAddition(other.x_, x_);
- y_ = base::SaturatedAddition(other.y_, y_);
+ x_ = base::ClampAdd(other.x_, x_);
+ y_ = base::ClampAdd(other.y_, y_);
}
void Vector2d::Subtract(const Vector2d& other) {
- x_ = base::SaturatedSubtraction(x_, other.x_);
- y_ = base::SaturatedSubtraction(y_, other.y_);
+ x_ = base::ClampSub(x_, other.x_);
+ y_ = base::ClampSub(y_, other.y_);
}
int64_t Vector2d::LengthSquared() const {
diff --git a/chromium/ui/gfx/gpu_memory_buffer_tracing.cc b/chromium/ui/gfx/gpu_memory_buffer_tracing.cc
deleted file mode 100644
index 5f587074862..00000000000
--- a/chromium/ui/gfx/gpu_memory_buffer_tracing.cc
+++ /dev/null
@@ -1,21 +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/gfx/gpu_memory_buffer_tracing.h"
-
-#include "base/format_macros.h"
-#include "base/strings/stringprintf.h"
-
-namespace gfx {
-
-base::trace_event::MemoryAllocatorDumpGuid GetSharedMemoryGUIDForTracing(
- uint64_t tracing_process_id,
- GpuMemoryBufferId buffer_id) {
- // TODO(hajimehoshi): This should be unified to shared memory GUIDs in
- // base/memory/shared_memory_tracker.cc
- return base::trace_event::MemoryAllocatorDumpGuid(base::StringPrintf(
- "shared_memory_gpu/%" PRIx64 "/%d", tracing_process_id, buffer_id.id));
-}
-
-} // namespace gfx
diff --git a/chromium/ui/gfx/gpu_memory_buffer_tracing.h b/chromium/ui/gfx/gpu_memory_buffer_tracing.h
deleted file mode 100644
index 0b66a91abd8..00000000000
--- a/chromium/ui/gfx/gpu_memory_buffer_tracing.h
+++ /dev/null
@@ -1,15 +0,0 @@
-// Copyright 2013 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "base/trace_event/memory_allocator_dump_guid.h"
-#include "ui/gfx/gfx_export.h"
-#include "ui/gfx/gpu_memory_buffer.h"
-
-namespace gfx {
-
-base::trace_event::MemoryAllocatorDumpGuid GFX_EXPORT
-GetSharedMemoryGUIDForTracing(uint64_t tracing_process_id,
- GpuMemoryBufferId buffer_id);
-
-} // namespace gfx
diff --git a/chromium/ui/gfx/icc_profile.cc b/chromium/ui/gfx/icc_profile.cc
index a982db54eff..0a9517ac7bd 100644
--- a/chromium/ui/gfx/icc_profile.cc
+++ b/chromium/ui/gfx/icc_profile.cc
@@ -5,10 +5,12 @@
#include "ui/gfx/icc_profile.h"
#include <list>
+#include <set>
#include "base/command_line.h"
#include "base/containers/mru_cache.h"
#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/SkICC.h"
@@ -21,36 +23,194 @@ const uint64_t ICCProfile::test_id_adobe_rgb_ = 1;
const uint64_t ICCProfile::test_id_color_spin_ = 2;
const uint64_t ICCProfile::test_id_generic_rgb_ = 3;
const uint64_t ICCProfile::test_id_srgb_ = 4;
-const uint64_t ICCProfile::test_id_no_analytic_tr_fn_ = 5;
-const uint64_t ICCProfile::test_id_a2b_only_ = 6;
-const uint64_t ICCProfile::test_id_overshoot_ = 7;
-namespace {
+// A MRU cache of ICC profiles. The cache key is a uin64_t which a
+// gfx::ColorSpace may use to refer back to an ICC profile in the cache. The
+// data cached for each profile is the gfx::ICCProfile structure (which includes
+// the associated gfx::ColorSpace approximations and SkColorSpace structures)
+// and whether or not the ICC profile has been histogrammed.
+class ICCProfileCache {
+ public:
+ // Allow keeping around a maximum of 16 cached ICC profiles. Beware that
+ // we will do a linear search thorugh currently-cached ICC profiles,
+ // when creating a new ICC profile.
+ static const size_t kMaxCachedICCProfiles = 16;
+
+ ICCProfileCache() : id_to_icc_profile_mru_(kMaxCachedICCProfiles) {}
+ ~ICCProfileCache() {}
+
+ // Add |icc_profile| to the cache. If |icc_profile| does not have an id set
+ // yet, assign an id to it.
+ void InsertAndSetIdIfNeeded(ICCProfile* icc_profile) {
+ base::AutoLock lock(lock_);
+
+ if (FindByIdUnderLock(icc_profile->id_, icc_profile))
+ return;
+
+ if (FindByDataUnderLock(icc_profile->data_.data(),
+ icc_profile->data_.size(), icc_profile)) {
+ return;
+ }
+
+ if (!icc_profile->id_)
+ icc_profile->id_ = next_unused_id_++;
+
+ // Ensure that GetColorSpace() point back to this ICCProfile.
+ gfx::ColorSpace& color_space = icc_profile->color_space_;
+ color_space.icc_profile_id_ = icc_profile->id_;
+
+ // Ensure that the GetParametricColorSpace() point back to this ICCProfile
+ // only if the parametric version is accurate.
+ if (color_space.primaries_ != ColorSpace::PrimaryID::ICC_BASED &&
+ color_space.transfer_ != ColorSpace::TransferID::ICC_BASED) {
+ icc_profile->parametric_color_space_.icc_profile_id_ = icc_profile->id_;
+ }
+
+ Entry entry;
+ entry.icc_profile = *icc_profile;
+ id_to_icc_profile_mru_.Put(icc_profile->id_, entry);
+ }
+
+ // We maintain UMA histograms of display ICC profiles. Only histogram a
+ // display once for each |display_id| (because we will re-read the same
+ // ICC profile repeatedly when reading other display profiles, which will
+ // skew samples). Return true if we need to histogram this profile for
+ // |display_id|, and ensure that all future calls will return false for
+ // |display_id|.
+ bool GetAndSetNeedsHistogram(uint64_t display_id,
+ const ICCProfile& icc_profile) {
+ base::AutoLock lock(lock_);
+
+ // If we don't find the profile in the cache, don't histogram it.
+ auto found = id_to_icc_profile_mru_.Get(icc_profile.id_);
+ if (found == id_to_icc_profile_mru_.end())
+ return false;
+
+ // If we have already histogrammed this display, don't histogram it.
+ std::set<int64_t>& histogrammed_display_ids =
+ found->second.histogrammed_display_ids;
+ if (histogrammed_display_ids.count(display_id))
+ return false;
+
+ // Histogram this display, and mark that we have done so.
+ histogrammed_display_ids.insert(display_id);
+ return true;
+ }
+
+ // Move this ICC profile to the most recently used end of the cache,
+ // re-inserting if needed.
+ void TouchEntry(const ICCProfile& icc_profile) {
+ base::AutoLock lock(lock_);
+
+ if (!icc_profile.id_)
+ return;
+
+ // Look up the profile by id to move it to the front of the MRU.
+ auto found = id_to_icc_profile_mru_.Get(icc_profile.id_);
+ if (found != id_to_icc_profile_mru_.end())
+ return;
+
+ // Look up the profile by its data. If there is a new entry for the same
+ // data, don't add a duplicate.
+ if (FindByDataUnderLock(icc_profile.data_.data(), icc_profile.data_.size(),
+ nullptr)) {
+ return;
+ }
-// Allow keeping around a maximum of 8 cached ICC profiles. Beware that
-// we will do a linear search thorugh currently-cached ICC profiles,
-// when creating a new ICC profile.
-const size_t kMaxCachedICCProfiles = 8;
+ // If the entry was not found, insert it.
+ Entry entry;
+ entry.icc_profile = icc_profile;
+ id_to_icc_profile_mru_.Put(icc_profile.id_, entry);
+ }
-struct Cache {
- Cache() : id_to_icc_profile_mru(kMaxCachedICCProfiles) {}
- ~Cache() {}
+ // Look up an ICC profile in the cache by its data (to ensure that the same
+ // data gets the same id every time). On success, return true and populate
+ // |icc_profile| with the associated profile.
+ bool FindByData(const void* data, size_t size, ICCProfile* icc_profile) {
+ base::AutoLock lock(lock_);
+ return FindByDataUnderLock(data, size, icc_profile);
+ }
+
+ // Look up an ICC profile in the cache by its id. On success, return true and
+ // populate |icc_profile| with the associated profile.
+ bool FindById(uint64_t id, ICCProfile* icc_profile) {
+ base::AutoLock lock(lock_);
+ return FindByIdUnderLock(id, icc_profile);
+ }
+
+ private:
+ struct Entry {
+ ICCProfile icc_profile;
+
+ // The set of display ids which have have caused this ICC profile to be
+ // recorded in UMA histograms. Only record an ICC profile once per display
+ // id (since the same profile will be re-read repeatedly, e.g, when displays
+ // are resized).
+ std::set<int64_t> histogrammed_display_ids;
+ };
+
+ // Body for FindById, executed when the cache lock is already held.
+ bool FindByIdUnderLock(uint64_t id, ICCProfile* icc_profile) {
+ lock_.AssertAcquired();
+ if (!id)
+ return false;
+
+ auto found = id_to_icc_profile_mru_.Get(id);
+ if (found == id_to_icc_profile_mru_.end())
+ return false;
+
+ *icc_profile = found->second.icc_profile;
+ return true;
+ }
+
+ // Body for FindByData, executed when the cache lock is already held.
+ bool FindByDataUnderLock(const void* data,
+ size_t size,
+ ICCProfile* icc_profile) {
+ lock_.AssertAcquired();
+ if (size == 0)
+ return false;
+
+ for (const auto& id_entry_pair : id_to_icc_profile_mru_) {
+ const ICCProfile& cached_profile = id_entry_pair.second.icc_profile;
+ const std::vector<char>& iter_data = cached_profile.data_;
+ if (iter_data.size() != size || memcmp(data, iter_data.data(), size))
+ continue;
+
+ if (icc_profile) {
+ *icc_profile = cached_profile;
+ id_to_icc_profile_mru_.Get(cached_profile.id_);
+ }
+ return true;
+ }
+ return false;
+ }
// Start from-ICC-data IDs at the end of the hard-coded test id list above.
- uint64_t next_unused_id = 10;
- base::MRUCache<uint64_t, ICCProfile> id_to_icc_profile_mru;
- base::Lock lock;
+ uint64_t next_unused_id_ = 10;
+ base::MRUCache<uint64_t, Entry> id_to_icc_profile_mru_;
+
+ // Lock that must be held to access |id_to_icc_profile_mru_| and
+ // |next_unused_id_|.
+ base::Lock lock_;
};
-static base::LazyInstance<Cache>::DestructorAtExit g_cache =
+
+namespace {
+
+static base::LazyInstance<ICCProfileCache>::DestructorAtExit g_cache =
LAZY_INSTANCE_INITIALIZER;
-void ExtractColorSpaces(const std::vector<char>& data,
- gfx::ColorSpace* parametric_color_space,
- bool* parametric_color_space_is_accurate,
- sk_sp<SkColorSpace>* useable_sk_color_space) {
+} // namespace
+
+// static
+ICCProfile::AnalyzeResult ICCProfile::ExtractColorSpaces(
+ const std::vector<char>& data,
+ gfx::ColorSpace* parametric_color_space,
+ float* parametric_tr_fn_max_error,
+ sk_sp<SkColorSpace>* useable_sk_color_space) {
// Initialize the output parameters as invalid.
*parametric_color_space = gfx::ColorSpace();
- *parametric_color_space_is_accurate = false;
+ *parametric_tr_fn_max_error = 0;
*useable_sk_color_space = nullptr;
// Parse the profile and attempt to create a SkColorSpaceXform out of it.
@@ -58,20 +218,20 @@ void ExtractColorSpaces(const std::vector<char>& data,
sk_sp<SkICC> sk_icc = SkICC::Make(data.data(), data.size());
if (!sk_icc) {
DLOG(ERROR) << "Failed to parse ICC profile to SkICC.";
- return;
+ return kICCFailedToParse;
}
sk_sp<SkColorSpace> sk_icc_color_space =
SkColorSpace::MakeICC(data.data(), data.size());
if (!sk_icc_color_space) {
DLOG(ERROR) << "Failed to parse ICC profile to SkColorSpace.";
- return;
+ return kICCFailedToExtractSkColorSpace;
}
std::unique_ptr<SkColorSpaceXform> sk_color_space_xform =
SkColorSpaceXform::New(sk_srgb_color_space.get(),
sk_icc_color_space.get());
if (!sk_color_space_xform) {
DLOG(ERROR) << "Parsed ICC profile but can't create SkColorSpaceXform.";
- return;
+ return kICCFailedToCreateXform;
}
// Because this SkColorSpace can be used to construct a transform, mark it
@@ -82,15 +242,14 @@ void ExtractColorSpaces(const std::vector<char>& data,
// If our SkColorSpace representation is sRGB then return that.
if (SkColorSpace::Equals(sk_srgb_color_space.get(),
sk_icc_color_space.get())) {
- *parametric_color_space_is_accurate = true;
- return;
+ return kICCExtractedSRGBColorSpace;
}
// A primary matrix is required for our parametric approximation.
SkMatrix44 to_XYZD50_matrix;
if (!sk_icc->toXYZD50(&to_XYZD50_matrix)) {
DLOG(ERROR) << "Failed to extract ICC profile primary matrix.";
- return;
+ return kICCFailedToExtractMatrix;
}
// Try to directly extract a numerical transfer function.
@@ -98,27 +257,7 @@ void ExtractColorSpaces(const std::vector<char>& data,
if (sk_icc->isNumericalTransferFn(&exact_tr_fn)) {
*parametric_color_space =
gfx::ColorSpace::CreateCustom(to_XYZD50_matrix, exact_tr_fn);
- *parametric_color_space_is_accurate = true;
- return;
- }
-
- // If that fails, try to numerically approximate the transfer function.
- SkColorSpaceTransferFn approx_tr_fn;
- float approx_tr_fn_max_error = 0;
- if (SkApproximateTransferFn(sk_icc, &approx_tr_fn_max_error, &approx_tr_fn)) {
- const float kMaxError = 2.f / 256.f;
- if (approx_tr_fn_max_error < kMaxError) {
- *parametric_color_space =
- gfx::ColorSpace::CreateCustom(to_XYZD50_matrix, approx_tr_fn);
- *parametric_color_space_is_accurate = true;
- return;
- } else {
- DLOG(ERROR)
- << "Failed to accurately approximate transfer function, error: "
- << 256.f * approx_tr_fn_max_error << "/256";
- }
- } else {
- DLOG(ERROR) << "Failed approximate transfer function.";
+ return kICCExtractedMatrixAndAnalyticTrFn;
}
// If we fail to get a transfer function, use the sRGB transfer function,
@@ -127,9 +266,31 @@ void ExtractColorSpaces(const std::vector<char>& data,
// SkColorSpace.
*parametric_color_space = gfx::ColorSpace::CreateCustom(
to_XYZD50_matrix, ColorSpace::TransferID::IEC61966_2_1);
-}
-} // namespace
+ // Attempt to fit a parametric transfer function to the table data in the
+ // profile.
+ SkColorSpaceTransferFn approx_tr_fn;
+ if (!SkApproximateTransferFn(sk_icc, parametric_tr_fn_max_error,
+ &approx_tr_fn)) {
+ DLOG(ERROR) << "Failed approximate transfer function.";
+ return kICCFailedToConvergeToApproximateTrFn;
+ }
+
+ // If this converged, but has too high error, use the sRGB transfer function
+ // from above.
+ const float kMaxError = 2.f / 256.f;
+ if (*parametric_tr_fn_max_error >= kMaxError) {
+ DLOG(ERROR) << "Failed to accurately approximate transfer function, error: "
+ << 256.f * (*parametric_tr_fn_max_error) << "/256";
+ return kICCFailedToApproximateTrFnAccurately;
+ };
+
+ // If the error is sufficiently low, declare that the approximation is
+ // accurate.
+ *parametric_color_space =
+ gfx::ColorSpace::CreateCustom(to_XYZD50_matrix, approx_tr_fn);
+ return kICCExtractedMatrixAndApproximatedTrFn;
+}
ICCProfile::ICCProfile() = default;
ICCProfile::ICCProfile(ICCProfile&& other) = default;
@@ -147,7 +308,15 @@ bool ICCProfile::operator!=(const ICCProfile& other) const {
}
bool ICCProfile::IsValid() const {
- return successfully_parsed_by_sk_icc_;
+ switch (analyze_result_) {
+ case kICCFailedToParse:
+ case kICCFailedToExtractSkColorSpace:
+ case kICCFailedToCreateXform:
+ return false;
+ default:
+ break;
+ }
+ return true;
}
// static
@@ -159,30 +328,14 @@ ICCProfile ICCProfile::FromData(const void* data, size_t size) {
ICCProfile ICCProfile::FromDataWithId(const void* data,
size_t size,
uint64_t new_profile_id) {
- if (!size)
- return ICCProfile();
+ ICCProfile icc_profile;
- const char* data_as_char = reinterpret_cast<const char*>(data);
- {
- // Linearly search the cached ICC profiles to find one with the same data.
- // If it exists, re-use its id and touch it in the cache.
- Cache& cache = g_cache.Get();
- base::AutoLock lock(cache.lock);
- for (auto iter = cache.id_to_icc_profile_mru.begin();
- iter != cache.id_to_icc_profile_mru.end(); ++iter) {
- const std::vector<char>& iter_data = iter->second.data_;
- if (iter_data.size() != size || memcmp(data, iter_data.data(), size))
- continue;
- auto found = cache.id_to_icc_profile_mru.Get(iter->second.id_);
- return found->second;
- }
- if (!new_profile_id)
- new_profile_id = cache.next_unused_id++;
- }
+ if (!size)
+ return icc_profile;
// Create a new cached id and add it to the cache.
- ICCProfile icc_profile;
icc_profile.id_ = new_profile_id;
+ const char* data_as_char = reinterpret_cast<const char*>(data);
icc_profile.data_.insert(icc_profile.data_.begin(), data_as_char,
data_as_char + size);
icc_profile.ComputeColorSpaceAndCache();
@@ -203,93 +356,89 @@ const std::vector<char>& ICCProfile::GetData() const {
}
const ColorSpace& ICCProfile::GetColorSpace() const {
- // Move this ICC profile to the most recently used end of the cache,
- // inserting if needed.
- if (id_) {
- Cache& cache = g_cache.Get();
- base::AutoLock lock(cache.lock);
- auto found = cache.id_to_icc_profile_mru.Get(id_);
- if (found == cache.id_to_icc_profile_mru.end())
- found = cache.id_to_icc_profile_mru.Put(id_, *this);
- }
+ g_cache.Get().TouchEntry(*this);
return color_space_;
}
const ColorSpace& ICCProfile::GetParametricColorSpace() const {
- // Move this ICC profile to the most recently used end of the cache,
- // inserting if needed.
- if (id_) {
- Cache& cache = g_cache.Get();
- base::AutoLock lock(cache.lock);
- auto found = cache.id_to_icc_profile_mru.Get(id_);
- if (found == cache.id_to_icc_profile_mru.end())
- found = cache.id_to_icc_profile_mru.Put(id_, *this);
- }
+ g_cache.Get().TouchEntry(*this);
return parametric_color_space_;
}
// static
bool ICCProfile::FromId(uint64_t id,
ICCProfile* icc_profile) {
- if (!id)
- return false;
-
- Cache& cache = g_cache.Get();
- base::AutoLock lock(cache.lock);
-
- auto found = cache.id_to_icc_profile_mru.Get(id);
- if (found == cache.id_to_icc_profile_mru.end())
- return false;
-
- *icc_profile = found->second;
- return true;
+ return g_cache.Get().FindById(id, icc_profile);
}
void ICCProfile::ComputeColorSpaceAndCache() {
- if (!id_)
+ // Early out for empty entries.
+ if (data_.empty())
return;
- // If this already exists in the cache, just update its |color_space_|.
- {
- Cache& cache = g_cache.Get();
- base::AutoLock lock(cache.lock);
- auto found = cache.id_to_icc_profile_mru.Get(id_);
- if (found != cache.id_to_icc_profile_mru.end()) {
- color_space_ = found->second.color_space_;
- parametric_color_space_ = found->second.parametric_color_space_;
- successfully_parsed_by_sk_icc_ =
- found->second.successfully_parsed_by_sk_icc_;
- return;
- }
- }
+ // If this id already exists in the cache, copy |this| from the cache entry.
+ if (g_cache.Get().FindById(id_, this))
+ return;
+
+ // If this data already exists in the cache, copy |this| from the cache entry.
+ if (g_cache.Get().FindByData(data_.data(), data_.size(), this))
+ return;
// Parse the ICC profile
sk_sp<SkColorSpace> useable_sk_color_space;
- bool parametric_color_space_is_accurate = false;
- ExtractColorSpaces(data_, &parametric_color_space_,
- &parametric_color_space_is_accurate,
- &useable_sk_color_space);
- if (parametric_color_space_is_accurate) {
- successfully_parsed_by_sk_icc_ = true;
- parametric_color_space_.icc_profile_id_ = id_;
- color_space_ = parametric_color_space_;
- } else if (useable_sk_color_space) {
- successfully_parsed_by_sk_icc_ = true;
- color_space_ = ColorSpace(ColorSpace::PrimaryID::ICC_BASED,
- ColorSpace::TransferID::ICC_BASED);
- color_space_.icc_profile_id_ = id_;
- color_space_.icc_profile_sk_color_space_ = useable_sk_color_space;
- } else {
- successfully_parsed_by_sk_icc_ = false;
- DCHECK(!color_space_.IsValid());
- color_space_ = parametric_color_space_;
+ analyze_result_ =
+ ExtractColorSpaces(data_, &parametric_color_space_,
+ &parametric_tr_fn_error_, &useable_sk_color_space);
+ switch (analyze_result_) {
+ case kICCExtractedSRGBColorSpace:
+ case kICCExtractedMatrixAndAnalyticTrFn:
+ case kICCExtractedMatrixAndApproximatedTrFn:
+ // Successfully and accurately extracted color space.
+ color_space_ = parametric_color_space_;
+ break;
+ case kICCFailedToExtractRawTrFn:
+ case kICCFailedToExtractMatrix:
+ case kICCFailedToConvergeToApproximateTrFn:
+ case kICCFailedToApproximateTrFnAccurately:
+ // Successfully but extracted a color space, but it isn't accurate enough.
+ color_space_ = ColorSpace(ColorSpace::PrimaryID::ICC_BASED,
+ ColorSpace::TransferID::ICC_BASED);
+ color_space_.icc_profile_sk_color_space_ = useable_sk_color_space;
+ break;
+ case kICCFailedToParse:
+ case kICCFailedToExtractSkColorSpace:
+ case kICCFailedToCreateXform:
+ // Can't even use this color space as a LUT.
+ DCHECK(!parametric_color_space_.IsValid());
+ color_space_ = parametric_color_space_;
+ break;
}
// Add to the cache.
- {
- Cache& cache = g_cache.Get();
- base::AutoLock lock(cache.lock);
- cache.id_to_icc_profile_mru.Put(id_, *this);
+ g_cache.Get().InsertAndSetIdIfNeeded(this);
+}
+
+void ICCProfile::HistogramDisplay(int64_t display_id) const {
+ if (!g_cache.Get().GetAndSetNeedsHistogram(display_id, *this))
+ return;
+
+ UMA_HISTOGRAM_ENUMERATION("Blink.ColorSpace.Destination.ICCResult",
+ analyze_result_, kICCProfileAnalyzeLast);
+
+ // Add histograms for numerical approximation.
+ bool nonlinear_fit_converged =
+ analyze_result_ == kICCExtractedMatrixAndApproximatedTrFn ||
+ analyze_result_ == kICCFailedToApproximateTrFnAccurately;
+ bool nonlinear_fit_did_not_converge =
+ analyze_result_ == kICCFailedToConvergeToApproximateTrFn;
+ if (nonlinear_fit_converged || nonlinear_fit_did_not_converge) {
+ UMA_HISTOGRAM_BOOLEAN("Blink.ColorSpace.Destination.NonlinearFitConverged",
+ nonlinear_fit_converged);
+ }
+ if (nonlinear_fit_converged) {
+ UMA_HISTOGRAM_CUSTOM_COUNTS(
+ "Blink.ColorSpace.Destination.NonlinearFitError",
+ static_cast<int>(parametric_tr_fn_error_ * 255), 0, 127, 16);
}
}
diff --git a/chromium/ui/gfx/icc_profile.h b/chromium/ui/gfx/icc_profile.h
index 03170adfbda..257b536dba3 100644
--- a/chromium/ui/gfx/icc_profile.h
+++ b/chromium/ui/gfx/icc_profile.h
@@ -23,6 +23,8 @@ template <typename, typename> struct StructTraits;
namespace gfx {
+class ICCProfileCache;
+
// Used to represent a full ICC profile, usually retrieved from a monitor. It
// can be lossily compressed into a ColorSpace object. This structure should
// only be sent from higher-privilege processes to lower-privilege processes,
@@ -49,11 +51,6 @@ class COLOR_SPACE_EXPORT ICCProfile {
static ICCProfile FromCGColorSpace(CGColorSpaceRef cg_color_space);
#endif
- // This will recover a ICCProfile from a compact ColorSpace representation.
- // Internally, this will make an effort to create an identical ICCProfile
- // to the one that created |color_space|, but this is not guaranteed.
- static ICCProfile FromColorSpace(const gfx::ColorSpace& color_space);
-
// Create directly from profile data.
static ICCProfile FromData(const void* icc_profile, size_t size);
@@ -68,6 +65,10 @@ class COLOR_SPACE_EXPORT ICCProfile {
const std::vector<char>& GetData() const;
+ // Histogram how we this was approximated by a gfx::ColorSpace. Only
+ // histogram a given profile once per display.
+ void HistogramDisplay(int64_t display_id) const;
+
#if defined(OS_WIN)
// This will read monitor ICC profiles from disk and cache the results for the
// other functions to read. This should not be called on the UI or IO thread.
@@ -76,33 +77,49 @@ class COLOR_SPACE_EXPORT ICCProfile {
#endif
private:
+ // This must match ICCProfileAnalyzeResult enum in histograms.xml.
+ enum AnalyzeResult {
+ kICCExtractedMatrixAndAnalyticTrFn = 0,
+ kICCExtractedMatrixAndApproximatedTrFn = 1,
+ kICCFailedToConvergeToApproximateTrFn = 2,
+ kICCFailedToExtractRawTrFn = 3,
+ kICCFailedToExtractMatrix = 4,
+ kICCFailedToParse = 5,
+ kICCFailedToExtractSkColorSpace = 6,
+ kICCFailedToCreateXform = 7,
+ kICCFailedToApproximateTrFnAccurately = 8,
+ kICCExtractedSRGBColorSpace = 9,
+ kICCProfileAnalyzeLast = kICCExtractedSRGBColorSpace,
+ };
+
+ friend class ICCProfileCache;
friend ICCProfile ICCProfileForTestingAdobeRGB();
friend ICCProfile ICCProfileForTestingColorSpin();
friend ICCProfile ICCProfileForTestingGenericRGB();
friend ICCProfile ICCProfileForTestingSRGB();
- friend ICCProfile ICCProfileForTestingNoAnalyticTrFn();
- friend ICCProfile ICCProfileForTestingA2BOnly();
- friend ICCProfile ICCProfileForTestingOvershoot();
friend ICCProfile ICCProfileForLayoutTests();
static const uint64_t test_id_adobe_rgb_;
static const uint64_t test_id_color_spin_;
static const uint64_t test_id_generic_rgb_;
static const uint64_t test_id_srgb_;
- static const uint64_t test_id_no_analytic_tr_fn_;
- static const uint64_t test_id_a2b_only_;
- static const uint64_t test_id_overshoot_;
// Populate |icc_profile| with the ICCProfile corresponding to id |id|. Return
// false if |id| is not in the cache.
static bool FromId(uint64_t id, ICCProfile* icc_profile);
// This method is used to hard-code the |id_| to a specific value, and is
- // used by test methods to ensure that they don't conflict with the values
- // generated in the browser.
+ // used by layout test methods to ensure that they don't conflict with the
+ // values generated in the browser.
static ICCProfile FromDataWithId(const void* icc_profile,
size_t size,
uint64_t id);
+ static AnalyzeResult ExtractColorSpaces(
+ const std::vector<char>& data,
+ gfx::ColorSpace* parametric_color_space,
+ float* parametric_tr_fn_max_error,
+ sk_sp<SkColorSpace>* useable_sk_color_space);
+
void ComputeColorSpaceAndCache();
// This globally identifies this ICC profile. It is used to look up this ICC
@@ -111,6 +128,9 @@ class COLOR_SPACE_EXPORT ICCProfile {
uint64_t id_ = 0;
std::vector<char> data_;
+ // The result of attepting to extract a color space from the color profile.
+ AnalyzeResult analyze_result_ = kICCFailedToParse;
+
// |color_space| always links back to this ICC profile, and its SkColorSpace
// is always equal to the SkColorSpace created from this ICCProfile.
gfx::ColorSpace color_space_;
@@ -119,8 +139,10 @@ class COLOR_SPACE_EXPORT ICCProfile {
// is accurate, and its SkColorSpace will always be parametrically created.
gfx::ColorSpace parametric_color_space_;
- // This is set to true if SkICC successfully parsed this profile.
- bool successfully_parsed_by_sk_icc_ = false;
+ // The L-infinity error of the parametric color space fit. This is undefined
+ // unless |analyze_result_| is kICCFailedToApproximateTrFnAccurately or
+ // kICCExtractedMatrixAndApproximatedTrFn.
+ float parametric_tr_fn_error_ = -1;
FRIEND_TEST_ALL_PREFIXES(SimpleColorSpace, BT709toSRGBICC);
FRIEND_TEST_ALL_PREFIXES(SimpleColorSpace, GetColorSpace);
diff --git a/chromium/ui/gfx/icc_profile_unittest.cc b/chromium/ui/gfx/icc_profile_unittest.cc
index e1222d5a3af..d9a008d71cd 100644
--- a/chromium/ui/gfx/icc_profile_unittest.cc
+++ b/chromium/ui/gfx/icc_profile_unittest.cc
@@ -122,6 +122,9 @@ TEST(ICCProfile, ParametricVersusExact) {
// as invalid.
ICCProfile a2b = ICCProfileForTestingA2BOnly();
EXPECT_FALSE(a2b.GetColorSpace().IsValid());
+
+ // Even though it is invalid, it should not be equal to the empty constructor.
+ EXPECT_NE(a2b, gfx::ICCProfile());
}
TEST(ICCProfile, GarbageData) {
@@ -158,4 +161,97 @@ TEST(ICCProfile, GenericRGB) {
EXPECT_TRUE(SkMatrixIsApproximatelyIdentity(eye));
}
+// This tests the ICCProfile MRU cache. This cache is sloppy and should be
+// rewritten, now that some of the original design constraints have been lifted.
+// This test exists only to ensure that we are aware of behavior changes, not to
+// enforce that behavior does not change.
+// https://crbug.com/766736
+TEST(ICCProfile, ExhaustCache) {
+ // Get an ICCProfile that can't be parametrically approximated.
+ ICCProfile original = ICCProfileForTestingNoAnalyticTrFn();
+ ColorSpace original_color_space_0 = original.GetColorSpace();
+
+ // Recover the ICCProfile from its GetColorSpace. Recovery should succeed, and
+ // the ICCProfiles should be equal.
+ ICCProfile recovered_0;
+ EXPECT_TRUE(original_color_space_0.GetICCProfile(&recovered_0));
+ EXPECT_EQ(original, recovered_0);
+
+ // The GetColorSpace of the recovered version should match the original.
+ ColorSpace recovered_0_color_space = recovered_0.GetColorSpace();
+ EXPECT_EQ(recovered_0_color_space, original_color_space_0);
+
+ // Create an identical ICCProfile to the original. It should equal the
+ // original, and its GetColorSpace should equal the original.
+ ICCProfile identical_0 = ICCProfileForTestingNoAnalyticTrFn();
+ EXPECT_EQ(original, identical_0);
+ ColorSpace identical_color_space_0 = identical_0.GetColorSpace();
+ EXPECT_EQ(identical_color_space_0, original_color_space_0);
+
+ // Create 128 distinct ICC profiles. This will destroy the cached
+ // ICCProfile<->ColorSpace mapping.
+ for (size_t i = 0; i < 128; ++i) {
+ SkMatrix44 toXYZD50;
+ ColorSpace::CreateSRGB().GetPrimaryMatrix(&toXYZD50);
+ SkColorSpaceTransferFn fn;
+ fn.fA = 1;
+ fn.fB = 0;
+ fn.fC = 1;
+ fn.fD = 0;
+ fn.fE = 0;
+ fn.fF = 0;
+ fn.fG = 1.5f + i / 128.f;
+ ColorSpace color_space = ColorSpace::CreateCustom(toXYZD50, fn);
+ ICCProfile icc_profile;
+ color_space.GetICCProfile(&icc_profile);
+ }
+
+ // Recover the original ICCProfile from its GetColorSpace. Recovery should
+ // fail, because it has been pushed out of the cache.
+ ICCProfile recovered_1;
+ EXPECT_FALSE(original_color_space_0.GetICCProfile(&recovered_1));
+ EXPECT_NE(original, recovered_1);
+
+ // Create an identical ICCProfile to the original. It should equal the
+ // original, because the comparison is based on data.
+ ICCProfile identical_1 = ICCProfileForTestingNoAnalyticTrFn();
+ EXPECT_EQ(original, identical_1);
+
+ // The identical ICCProfile's GetColorSpace will not match, because the
+ // original points to the now-uncached version.
+ ColorSpace identical_1_color_space = identical_1.GetColorSpace();
+ EXPECT_NE(identical_1_color_space, original_color_space_0);
+
+ // The original ICCProfile is now orphaned because there exists a new entry
+ // with the same data.
+ ColorSpace original_color_space_2 = original.GetColorSpace();
+ ICCProfile recovered_2;
+ EXPECT_FALSE(original_color_space_2.GetICCProfile(&recovered_2));
+ EXPECT_NE(original, recovered_2);
+
+ // Blow away the cache one more time.
+ for (size_t i = 0; i < 128; ++i) {
+ SkMatrix44 toXYZD50;
+ ColorSpace::CreateSRGB().GetPrimaryMatrix(&toXYZD50);
+ SkColorSpaceTransferFn fn;
+ fn.fA = 1;
+ fn.fB = 0;
+ fn.fC = 1;
+ fn.fD = 0;
+ fn.fE = 0;
+ fn.fF = 0;
+ fn.fG = 1.5f + i / 128.f;
+ ColorSpace color_space = ColorSpace::CreateCustom(toXYZD50, fn);
+ ICCProfile icc_profile;
+ color_space.GetICCProfile(&icc_profile);
+ }
+
+ // Now the original ICCProfile can re-insert itself into the cache, with its
+ // original id.
+ ColorSpace original_color_space_3 = original.GetColorSpace();
+ ICCProfile recovered_3;
+ EXPECT_TRUE(original_color_space_3.GetICCProfile(&recovered_3));
+ EXPECT_EQ(original, recovered_3);
+}
+
} // namespace gfx
diff --git a/chromium/ui/gfx/image/canvas_image_source.h b/chromium/ui/gfx/image/canvas_image_source.h
index 1108f0d7c6d..1b1846635c9 100644
--- a/chromium/ui/gfx/image/canvas_image_source.h
+++ b/chromium/ui/gfx/image/canvas_image_source.h
@@ -5,6 +5,8 @@
#ifndef UI_GFX_IMAGE_CANVAS_IMAGE_SOURCE_H_
#define UI_GFX_IMAGE_CANVAS_IMAGE_SOURCE_H_
+#include <utility>
+
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
@@ -30,7 +32,7 @@ class GFX_EXPORT CanvasImageSource : public gfx::ImageSkiaSource {
static ImageSkia MakeImageSkia(Args&&... args) {
auto source = base::MakeUnique<T>(std::forward<Args>(args)...);
gfx::Size size = source->size();
- return gfx::ImageSkia(source.release(), size);
+ return gfx::ImageSkia(std::move(source), size);
}
CanvasImageSource(const gfx::Size& size, bool is_opaque);
diff --git a/chromium/ui/gfx/image/image.cc b/chromium/ui/gfx/image/image.cc
index b2984fb0f3d..7b49776f9ed 100644
--- a/chromium/ui/gfx/image/image.cc
+++ b/chromium/ui/gfx/image/image.cc
@@ -5,8 +5,8 @@
#include "ui/gfx/image/image.h"
#include <algorithm>
-#include <set>
#include <utility>
+#include <vector>
#include "base/logging.h"
#include "base/macros.h"
@@ -14,13 +14,9 @@
#include "build/build_config.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/image/image_platform.h"
#include "ui/gfx/image/image_png_rep.h"
#include "ui/gfx/image/image_skia.h"
-#include "ui/gfx/image/image_skia_source.h"
-
-#if !defined(OS_IOS)
-#include "ui/gfx/codec/png_codec.h"
-#endif
#if defined(OS_IOS)
#include "base/mac/foundation_util.h"
@@ -33,136 +29,14 @@
namespace gfx {
-namespace internal {
-
-#if defined(OS_IOS)
-scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromUIImage(
- UIImage* uiimage);
-// Caller takes ownership of the returned UIImage.
-UIImage* CreateUIImageFromPNG(
- const std::vector<ImagePNGRep>& image_png_reps);
-gfx::Size UIImageSize(UIImage* image);
-#elif defined(OS_MACOSX)
-scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromNSImage(
- NSImage* nsimage);
-// Caller takes ownership of the returned NSImage.
-NSImage* NSImageFromPNG(const std::vector<ImagePNGRep>& image_png_reps,
- CGColorSpaceRef color_space);
-gfx::Size NSImageSize(NSImage* image);
-#endif // defined(OS_MACOSX)
-
-#if defined(OS_IOS)
-ImageSkia* ImageSkiaFromPNG(
- const std::vector<ImagePNGRep>& image_png_reps);
-scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia(
- const ImageSkia* skia);
-#else
-// Returns a 16x16 red image to visually show error in decoding PNG.
-// Caller takes ownership of returned ImageSkia.
-ImageSkia* GetErrorImageSkia() {
- SkBitmap bitmap;
- bitmap.allocN32Pixels(16, 16);
- bitmap.eraseARGB(0xff, 0xff, 0, 0);
- return new ImageSkia(ImageSkiaRep(bitmap, 1.0f));
-}
-
-class PNGImageSource : public ImageSkiaSource {
- public:
- PNGImageSource() {}
- ~PNGImageSource() override {}
-
- ImageSkiaRep GetImageForScale(float scale) override {
- if (image_skia_reps_.empty())
- return ImageSkiaRep();
-
- const ImageSkiaRep* rep = NULL;
- // gfx::ImageSkia passes one of the resource scale factors. The source
- // should return:
- // 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) {
- if ((*iter).scale() == scale)
- return (*iter);
- if (!rep || rep->scale() < (*iter).scale())
- rep = &(*iter);
- if (rep->scale() >= scale)
- break;
- }
- return rep ? *rep : ImageSkiaRep();
- }
-
- const gfx::Size size() const {
- return size_;
- }
-
- bool AddPNGData(const ImagePNGRep& png_rep) {
- const gfx::ImageSkiaRep rep = ToImageSkiaRep(png_rep);
- if (rep.is_null())
- return false;
- if (size_.IsEmpty())
- size_ = gfx::Size(rep.GetWidth(), rep.GetHeight());
- image_skia_reps_.insert(rep);
- return true;
- }
+namespace {
- static ImageSkiaRep ToImageSkiaRep(const ImagePNGRep& png_rep) {
- scoped_refptr<base::RefCountedMemory> raw_data = png_rep.raw_data;
- CHECK(raw_data.get());
- SkBitmap bitmap;
- if (!PNGCodec::Decode(raw_data->front(), raw_data->size(),
- &bitmap)) {
- LOG(ERROR) << "Unable to decode PNG for " << png_rep.scale << ".";
- return ImageSkiaRep();
- }
- return ImageSkiaRep(bitmap, png_rep.scale);
- }
+using RepresentationMap =
+ std::map<Image::RepresentationType, std::unique_ptr<internal::ImageRep>>;
- private:
- struct Compare {
- bool operator()(const ImageSkiaRep& rep1, const ImageSkiaRep& rep2) {
- return rep1.scale() < rep2.scale();
- }
- };
+} // namespace
- typedef std::set<ImageSkiaRep, Compare> ImageSkiaRepSet;
- ImageSkiaRepSet image_skia_reps_;
- gfx::Size size_;
-
- DISALLOW_COPY_AND_ASSIGN(PNGImageSource);
-};
-
-ImageSkia* ImageSkiaFromPNG(
- const std::vector<ImagePNGRep>& image_png_reps) {
- if (image_png_reps.empty())
- return GetErrorImageSkia();
- std::unique_ptr<PNGImageSource> image_source(new PNGImageSource);
-
- for (size_t i = 0; i < image_png_reps.size(); ++i) {
- if (!image_source->AddPNGData(image_png_reps[i]))
- return GetErrorImageSkia();
- }
- const gfx::Size& size = image_source->size();
- DCHECK(!size.IsEmpty());
- if (size.IsEmpty())
- return GetErrorImageSkia();
- return new ImageSkia(image_source.release(), size);
-}
-
-scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia(
- const ImageSkia* image_skia) {
- ImageSkiaRep image_skia_rep = image_skia->GetRepresentation(1.0f);
-
- scoped_refptr<base::RefCountedBytes> png_bytes(new base::RefCountedBytes());
- if (image_skia_rep.scale() != 1.0f ||
- !PNGCodec::EncodeBGRASkBitmap(image_skia_rep.sk_bitmap(), false,
- &png_bytes->data())) {
- return NULL;
- }
- return png_bytes;
-}
-#endif
+namespace internal {
class ImageRepPNG;
class ImageRepSkia;
@@ -182,25 +56,41 @@ class ImageRep {
virtual ~ImageRep() {}
// Cast helpers ("fake RTTI").
- ImageRepPNG* AsImageRepPNG() {
+ const ImageRepPNG* AsImageRepPNG() const {
CHECK_EQ(type_, Image::kImageRepPNG);
- return reinterpret_cast<ImageRepPNG*>(this);
+ return reinterpret_cast<const ImageRepPNG*>(this);
+ }
+ ImageRepPNG* AsImageRepPNG() {
+ return const_cast<ImageRepPNG*>(
+ static_cast<const ImageRep*>(this)->AsImageRepPNG());
}
- ImageRepSkia* AsImageRepSkia() {
+ const ImageRepSkia* AsImageRepSkia() const {
CHECK_EQ(type_, Image::kImageRepSkia);
- return reinterpret_cast<ImageRepSkia*>(this);
+ return reinterpret_cast<const ImageRepSkia*>(this);
+ }
+ ImageRepSkia* AsImageRepSkia() {
+ return const_cast<ImageRepSkia*>(
+ static_cast<const ImageRep*>(this)->AsImageRepSkia());
}
#if defined(OS_IOS)
- ImageRepCocoaTouch* AsImageRepCocoaTouch() {
+ const ImageRepCocoaTouch* AsImageRepCocoaTouch() const {
CHECK_EQ(type_, Image::kImageRepCocoaTouch);
- return reinterpret_cast<ImageRepCocoaTouch*>(this);
+ return reinterpret_cast<const ImageRepCocoaTouch*>(this);
+ }
+ ImageRepCocoaTouch* AsImageRepCocoaTouch() {
+ return const_cast<ImageRepCocoaTouch*>(
+ static_cast<const ImageRep*>(this)->AsImageRepCocoaTouch());
}
#elif defined(OS_MACOSX)
- ImageRepCocoa* AsImageRepCocoa() {
+ const ImageRepCocoa* AsImageRepCocoa() const {
CHECK_EQ(type_, Image::kImageRepCocoa);
- return reinterpret_cast<ImageRepCocoa*>(this);
+ return reinterpret_cast<const ImageRepCocoa*>(this);
+ }
+ ImageRepCocoa* AsImageRepCocoa() {
+ return const_cast<ImageRepCocoa*>(
+ static_cast<const ImageRep*>(this)->AsImageRepCocoa());
}
#endif
@@ -273,6 +163,7 @@ class ImageRepSkia : public ImageRep {
gfx::Size Size() const override { return image_->size(); }
+ const ImageSkia* image() const { return image_.get(); }
ImageSkia* image() { return image_.get(); }
private:
@@ -356,16 +247,51 @@ class ImageStorage : public base::RefCounted<ImageStorage> {
{
}
- Image::RepresentationType default_representation_type() {
+ Image::RepresentationType default_representation_type() const {
+ DCHECK(IsOnValidSequence());
return default_representation_type_;
}
- Image::RepresentationMap& representations() { return representations_; }
+
+ bool HasRepresentation(Image::RepresentationType type) const {
+ DCHECK(IsOnValidSequence());
+ return representations_.count(type) != 0;
+ }
+
+ size_t RepresentationCount() const {
+ DCHECK(IsOnValidSequence());
+ return representations_.size();
+ }
+
+ const ImageRep* GetRepresentation(Image::RepresentationType rep_type,
+ bool must_exist) const {
+ DCHECK(IsOnValidSequence());
+ RepresentationMap::const_iterator it = representations_.find(rep_type);
+ if (it == representations_.end()) {
+ CHECK(!must_exist);
+ return NULL;
+ }
+ return it->second.get();
+ }
+
+ const ImageRep* AddRepresentation(std::unique_ptr<ImageRep> rep) const {
+ DCHECK(IsOnValidSequence());
+ Image::RepresentationType type = rep->type();
+ auto result = representations_.insert(std::make_pair(type, std::move(rep)));
+
+ // insert should not fail (implies that there was already a representation
+ // of that type in the map).
+ CHECK(result.second) << "type was already in map.";
+
+ return result.first->second.get();
+ }
#if defined(OS_MACOSX) && !defined(OS_IOS)
void set_default_representation_color_space(CGColorSpaceRef color_space) {
+ DCHECK(IsOnValidSequence());
default_representation_color_space_ = color_space;
}
- CGColorSpaceRef default_representation_color_space() {
+ CGColorSpaceRef default_representation_color_space() const {
+ DCHECK(IsOnValidSequence());
return default_representation_color_space_;
}
#endif // defined(OS_MACOSX) && !defined(OS_IOS)
@@ -389,7 +315,7 @@ class ImageStorage : public base::RefCounted<ImageStorage> {
// All the representations of an Image. Size will always be at least one, with
// more for any converted representations.
- Image::RepresentationMap representations_;
+ mutable RepresentationMap representations_;
DISALLOW_COPY_AND_ASSIGN(ImageStorage);
};
@@ -443,16 +369,15 @@ Image::Image(NSImage* image) {
}
#endif
-Image::Image(const Image& other) : storage_(other.storage_) {
-}
+Image::Image(const Image& other) = default;
-Image& Image::operator=(const Image& other) {
- storage_ = other.storage_;
- return *this;
-}
+Image::Image(Image&& other) = default;
-Image::~Image() {
-}
+Image& Image::operator=(const Image& other) = default;
+
+Image& Image::operator=(Image&& other) = default;
+
+Image::~Image() {}
// static
Image Image::CreateFrom1xBitmap(const SkBitmap& bitmap) {
@@ -487,12 +412,12 @@ const SkBitmap* Image::ToSkBitmap() const {
}
const ImageSkia* Image::ToImageSkia() const {
- internal::ImageRep* rep = GetRepresentation(kImageRepSkia, false);
+ const internal::ImageRep* rep = GetRepresentation(kImageRepSkia, false);
if (!rep) {
std::unique_ptr<internal::ImageRep> scoped_rep;
switch (DefaultRepresentationType()) {
case kImageRepPNG: {
- internal::ImageRepPNG* png_rep =
+ const internal::ImageRepPNG* png_rep =
GetRepresentation(kImageRepPNG, true)->AsImageRepPNG();
scoped_rep.reset(new internal::ImageRepSkia(
internal::ImageSkiaFromPNG(png_rep->image_reps())));
@@ -500,7 +425,7 @@ const ImageSkia* Image::ToImageSkia() const {
}
#if defined(OS_IOS)
case kImageRepCocoaTouch: {
- internal::ImageRepCocoaTouch* native_rep =
+ const internal::ImageRepCocoaTouch* native_rep =
GetRepresentation(kImageRepCocoaTouch, true)
->AsImageRepCocoaTouch();
scoped_rep.reset(new internal::ImageRepSkia(
@@ -509,7 +434,7 @@ const ImageSkia* Image::ToImageSkia() const {
}
#elif defined(OS_MACOSX)
case kImageRepCocoa: {
- internal::ImageRepCocoa* native_rep =
+ const internal::ImageRepCocoa* native_rep =
GetRepresentation(kImageRepCocoa, true)->AsImageRepCocoa();
scoped_rep.reset(new internal::ImageRepSkia(
new ImageSkia(ImageSkiaFromNSImage(native_rep->image()))));
@@ -527,19 +452,19 @@ const ImageSkia* Image::ToImageSkia() const {
#if defined(OS_IOS)
UIImage* Image::ToUIImage() const {
- internal::ImageRep* rep = GetRepresentation(kImageRepCocoaTouch, false);
+ const internal::ImageRep* rep = GetRepresentation(kImageRepCocoaTouch, false);
if (!rep) {
std::unique_ptr<internal::ImageRep> scoped_rep;
switch (DefaultRepresentationType()) {
case kImageRepPNG: {
- internal::ImageRepPNG* png_rep =
+ const internal::ImageRepPNG* png_rep =
GetRepresentation(kImageRepPNG, true)->AsImageRepPNG();
scoped_rep.reset(new internal::ImageRepCocoaTouch(
internal::CreateUIImageFromPNG(png_rep->image_reps())));
break;
}
case kImageRepSkia: {
- internal::ImageRepSkia* skia_rep =
+ const internal::ImageRepSkia* skia_rep =
GetRepresentation(kImageRepSkia, true)->AsImageRepSkia();
UIImage* image = UIImageFromImageSkia(*skia_rep->image());
base::mac::NSObjectRetain(image);
@@ -556,22 +481,22 @@ UIImage* Image::ToUIImage() const {
}
#elif defined(OS_MACOSX)
NSImage* Image::ToNSImage() const {
- internal::ImageRep* rep = GetRepresentation(kImageRepCocoa, false);
+ const internal::ImageRep* rep = GetRepresentation(kImageRepCocoa, false);
if (!rep) {
std::unique_ptr<internal::ImageRep> scoped_rep;
CGColorSpaceRef default_representation_color_space =
- storage_->default_representation_color_space();
+ storage()->default_representation_color_space();
switch (DefaultRepresentationType()) {
case kImageRepPNG: {
- internal::ImageRepPNG* png_rep =
+ const internal::ImageRepPNG* png_rep =
GetRepresentation(kImageRepPNG, true)->AsImageRepPNG();
scoped_rep.reset(new internal::ImageRepCocoa(internal::NSImageFromPNG(
png_rep->image_reps(), default_representation_color_space)));
break;
}
case kImageRepSkia: {
- internal::ImageRepSkia* skia_rep =
+ const internal::ImageRepSkia* skia_rep =
GetRepresentation(kImageRepSkia, true)->AsImageRepSkia();
NSImage* image = NSImageFromImageSkiaWithColorSpace(*skia_rep->image(),
default_representation_color_space);
@@ -593,7 +518,7 @@ scoped_refptr<base::RefCountedMemory> Image::As1xPNGBytes() const {
if (IsEmpty())
return new base::RefCountedBytes();
- internal::ImageRep* rep = GetRepresentation(kImageRepPNG, false);
+ const internal::ImageRep* rep = GetRepresentation(kImageRepPNG, false);
if (rep) {
const std::vector<ImagePNGRep>& image_png_reps =
@@ -609,23 +534,22 @@ scoped_refptr<base::RefCountedMemory> Image::As1xPNGBytes() const {
switch (DefaultRepresentationType()) {
#if defined(OS_IOS)
case kImageRepCocoaTouch: {
- internal::ImageRepCocoaTouch* cocoa_touch_rep =
- GetRepresentation(kImageRepCocoaTouch, true)
- ->AsImageRepCocoaTouch();
+ const internal::ImageRepCocoaTouch* cocoa_touch_rep =
+ GetRepresentation(kImageRepCocoaTouch, true)->AsImageRepCocoaTouch();
png_bytes = internal::Get1xPNGBytesFromUIImage(
cocoa_touch_rep->image());
break;
}
#elif defined(OS_MACOSX)
case kImageRepCocoa: {
- internal::ImageRepCocoa* cocoa_rep =
+ const internal::ImageRepCocoa* cocoa_rep =
GetRepresentation(kImageRepCocoa, true)->AsImageRepCocoa();
png_bytes = internal::Get1xPNGBytesFromNSImage(cocoa_rep->image());
break;
}
#endif
case kImageRepSkia: {
- internal::ImageRepSkia* skia_rep =
+ const internal::ImageRepSkia* skia_rep =
GetRepresentation(kImageRepSkia, true)->AsImageRepSkia();
png_bytes = internal::Get1xPNGBytesFromImageSkia(skia_rep->image());
break;
@@ -697,14 +621,11 @@ NSImage* Image::CopyNSImage() const {
#endif
bool Image::HasRepresentation(RepresentationType type) const {
- return storage_.get() && storage_->representations().count(type) != 0;
+ return storage() && storage()->HasRepresentation(type);
}
size_t Image::RepresentationCount() const {
- if (!storage_.get())
- return 0;
-
- return storage_->representations().size();
+ return storage() ? storage()->RepresentationCount() : 0;
}
bool Image::IsEmpty() const {
@@ -729,46 +650,28 @@ gfx::Size Image::Size() const {
return GetRepresentation(DefaultRepresentationType(), true)->Size();
}
-void Image::SwapRepresentations(Image* other) {
- storage_.swap(other->storage_);
-}
-
#if defined(OS_MACOSX) && !defined(OS_IOS)
void Image::SetSourceColorSpace(CGColorSpaceRef color_space) {
- if (storage_.get())
- storage_->set_default_representation_color_space(color_space);
+ if (storage())
+ storage()->set_default_representation_color_space(color_space);
}
#endif // defined(OS_MACOSX) && !defined(OS_IOS)
Image::RepresentationType Image::DefaultRepresentationType() const {
- CHECK(storage_.get());
- return storage_->default_representation_type();
+ CHECK(storage());
+ return storage()->default_representation_type();
}
-internal::ImageRep* Image::GetRepresentation(
- RepresentationType rep_type, bool must_exist) const {
- CHECK(storage_.get());
- RepresentationMap::const_iterator it =
- storage_->representations().find(rep_type);
- if (it == storage_->representations().end()) {
- CHECK(!must_exist);
- return NULL;
- }
- return it->second.get();
+const internal::ImageRep* Image::GetRepresentation(RepresentationType rep_type,
+ bool must_exist) const {
+ CHECK(storage());
+ return storage()->GetRepresentation(rep_type, must_exist);
}
-internal::ImageRep* Image::AddRepresentation(
+const internal::ImageRep* Image::AddRepresentation(
std::unique_ptr<internal::ImageRep> rep) const {
- CHECK(storage_.get());
- RepresentationType type = rep->type();
- auto result =
- storage_->representations().insert(std::make_pair(type, std::move(rep)));
-
- // insert should not fail (implies that there was already a representation of
- // that type in the map).
- CHECK(result.second) << "type was already in map.";
-
- return result.first->second.get();
+ CHECK(storage());
+ return storage()->AddRepresentation(std::move(rep));
}
} // namespace gfx
diff --git a/chromium/ui/gfx/image/image.h b/chromium/ui/gfx/image/image.h
index 01344242d93..f0d6cbb0b2f 100644
--- a/chromium/ui/gfx/image/image.h
+++ b/chromium/ui/gfx/image/image.h
@@ -56,9 +56,6 @@ class GFX_EXPORT Image {
kImageRepPNG,
};
- using RepresentationMap =
- std::map<RepresentationType, std::unique_ptr<internal::ImageRep>>;
-
// Creates an empty image with no representations.
Image();
@@ -87,9 +84,17 @@ class GFX_EXPORT Image {
// Initializes a new Image by AddRef()ing |other|'s internal storage.
Image(const Image& other);
+ // Moves a reference from |other| to the new image without changing the
+ // reference count.
+ Image(Image&& other);
+
// Copies a reference to |other|'s storage.
Image& operator=(const Image& other);
+ // Moves a reference from |other|'s storage without changing the reference
+ // count.
+ Image& operator=(Image&& other);
+
// Deletes the image and, if the only owner of the storage, all of its cached
// representations.
~Image();
@@ -169,9 +174,6 @@ class GFX_EXPORT Image {
int Height() const;
gfx::Size Size() const;
- // Swaps this image's internal representations with |other|.
- void SwapRepresentations(gfx::Image* other);
-
#if defined(OS_MACOSX) && !defined(OS_IOS)
// Set the default representation's color space. This is used for converting
// to NSImage. This is used to compensate for PNGCodec not writing or reading
@@ -185,15 +187,21 @@ class GFX_EXPORT Image {
// Returns the ImageRep of the appropriate type or NULL if there is no
// representation of that type (and must_exist is false).
- internal::ImageRep* GetRepresentation(
- RepresentationType rep_type, bool must_exist) const;
+ const internal::ImageRep* GetRepresentation(RepresentationType rep_type,
+ bool must_exist) const;
// Stores a representation into the map. A representation of that type must
// not already be in the map. Returns a pointer to the representation stored
// inside the map.
- internal::ImageRep* AddRepresentation(
+ const internal::ImageRep* AddRepresentation(
std::unique_ptr<internal::ImageRep> rep) const;
+ // Getter should be used internally (unless a handle to the scoped_refptr is
+ // needed) instead of directly accessing |storage_|, to ensure logical
+ // constness is upheld.
+ const internal::ImageStorage* storage() const { return storage_.get(); }
+ internal::ImageStorage* storage() { return storage_.get(); }
+
// Internal class that holds all the representations. This allows the Image to
// be cheaply copied.
scoped_refptr<internal::ImageStorage> storage_;
diff --git a/chromium/ui/gfx/image/image_family.cc b/chromium/ui/gfx/image/image_family.cc
index b9d28bddd9d..0adc6692336 100644
--- a/chromium/ui/gfx/image/image_family.cc
+++ b/chromium/ui/gfx/image/image_family.cc
@@ -25,8 +25,17 @@ ImageFamily::const_iterator::const_iterator(
ImageFamily::const_iterator::~const_iterator() {}
ImageFamily::ImageFamily() {}
+ImageFamily::ImageFamily(ImageFamily&& other) = default;
ImageFamily::~ImageFamily() {}
+ImageFamily& ImageFamily::operator=(ImageFamily&& other) = default;
+
+ImageFamily ImageFamily::Clone() const {
+ ImageFamily clone;
+ clone.map_ = map_;
+ return clone;
+}
+
void ImageFamily::Add(const gfx::Image& image) {
gfx::Size size = image.Size();
if (size.IsEmpty()) {
diff --git a/chromium/ui/gfx/image/image_family.h b/chromium/ui/gfx/image/image_family.h
index e8920b9a88f..3d0890a425d 100644
--- a/chromium/ui/gfx/image/image_family.h
+++ b/chromium/ui/gfx/image/image_family.h
@@ -98,8 +98,11 @@ class GFX_EXPORT ImageFamily {
};
ImageFamily();
+ ImageFamily(ImageFamily&& other);
~ImageFamily();
+ ImageFamily& operator=(ImageFamily&& other);
+
// Gets an iterator to the first image.
const_iterator begin() const { return const_iterator(map_.begin()); }
// Gets an iterator to one after the last image.
@@ -111,6 +114,10 @@ class GFX_EXPORT ImageFamily {
// Removes all images from the family.
void clear() { return map_.clear(); }
+ // Creates a shallow copy of the family. The Images inside share their backing
+ // store with the original Images.
+ ImageFamily Clone() const;
+
// Adds an image to the family. If another image is already present at the
// same size, it will be overwritten.
void Add(const gfx::Image& image);
@@ -162,6 +169,12 @@ class GFX_EXPORT ImageFamily {
// Map from (aspect ratio, width) to image.
std::map<MapKey, gfx::Image> map_;
+
+ // Even though the Images in the family are copyable (reference-counted), the
+ // family itself should not be implicitly copied, as it would result in a
+ // shallow clone of the entire map and updates to many reference counts.
+ // ImageFamily can be explicitly Clone()d, but std::move is preferred.
+ DISALLOW_COPY_AND_ASSIGN(ImageFamily);
};
} // namespace gfx
diff --git a/chromium/ui/gfx/image/image_family_unittest.cc b/chromium/ui/gfx/image/image_family_unittest.cc
index 88d52981400..e3973d037ac 100644
--- a/chromium/ui/gfx/image/image_family_unittest.cc
+++ b/chromium/ui/gfx/image/image_family_unittest.cc
@@ -69,6 +69,26 @@ TEST_F(ImageFamilyTest, Clear) {
EXPECT_TRUE(image_family_.empty());
}
+TEST_F(ImageFamilyTest, MoveConstructor) {
+ gfx::ImageFamily family(std::move(image_family_));
+ EXPECT_TRUE(image_family_.empty());
+ EXPECT_FALSE(family.empty());
+}
+
+TEST_F(ImageFamilyTest, MoveAssignment) {
+ gfx::ImageFamily family;
+ EXPECT_TRUE(family.empty());
+ family = std::move(image_family_);
+ EXPECT_TRUE(image_family_.empty());
+ EXPECT_FALSE(family.empty());
+}
+
+TEST_F(ImageFamilyTest, Clone) {
+ gfx::ImageFamily family = image_family_.Clone();
+ EXPECT_FALSE(image_family_.empty());
+ EXPECT_FALSE(family.empty());
+}
+
// Tests iteration over an ImageFamily.
TEST_F(ImageFamilyTest, Iteration) {
gfx::ImageFamily::const_iterator it = image_family_.begin();
diff --git a/chromium/ui/gfx/image/image_generic.cc b/chromium/ui/gfx/image/image_generic.cc
new file mode 100644
index 00000000000..3f424915dc9
--- /dev/null
+++ b/chromium/ui/gfx/image/image_generic.cc
@@ -0,0 +1,123 @@
+// 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/gfx/image/image_platform.h"
+
+#include <set>
+#include <utility>
+
+#include "ui/gfx/codec/png_codec.h"
+#include "ui/gfx/image/image_skia_source.h"
+
+namespace gfx {
+namespace internal {
+
+namespace {
+
+// Returns a 16x16 red image to visually show error in decoding PNG.
+// Caller takes ownership of returned ImageSkia.
+ImageSkia* GetErrorImageSkia() {
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(16, 16);
+ bitmap.eraseARGB(0xff, 0xff, 0, 0);
+ return new ImageSkia(ImageSkiaRep(bitmap, 1.0f));
+}
+
+class PNGImageSource : public ImageSkiaSource {
+ public:
+ PNGImageSource() {}
+ ~PNGImageSource() override {}
+
+ ImageSkiaRep GetImageForScale(float scale) override {
+ if (image_skia_reps_.empty())
+ return ImageSkiaRep();
+
+ const ImageSkiaRep* rep = NULL;
+ // gfx::ImageSkia passes one of the resource scale factors. The source
+ // should return:
+ // 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) {
+ if ((*iter).scale() == scale)
+ return (*iter);
+ if (!rep || rep->scale() < (*iter).scale())
+ rep = &(*iter);
+ if (rep->scale() >= scale)
+ break;
+ }
+ return rep ? *rep : ImageSkiaRep();
+ }
+
+ const gfx::Size size() const { return size_; }
+
+ bool AddPNGData(const ImagePNGRep& png_rep) {
+ const gfx::ImageSkiaRep rep = ToImageSkiaRep(png_rep);
+ if (rep.is_null())
+ return false;
+ if (size_.IsEmpty())
+ size_ = gfx::Size(rep.GetWidth(), rep.GetHeight());
+ image_skia_reps_.insert(rep);
+ return true;
+ }
+
+ static ImageSkiaRep ToImageSkiaRep(const ImagePNGRep& png_rep) {
+ scoped_refptr<base::RefCountedMemory> raw_data = png_rep.raw_data;
+ CHECK(raw_data.get());
+ SkBitmap bitmap;
+ if (!PNGCodec::Decode(raw_data->front(), raw_data->size(), &bitmap)) {
+ LOG(ERROR) << "Unable to decode PNG for " << png_rep.scale << ".";
+ return ImageSkiaRep();
+ }
+ return ImageSkiaRep(bitmap, png_rep.scale);
+ }
+
+ private:
+ struct Compare {
+ bool operator()(const ImageSkiaRep& rep1, const ImageSkiaRep& rep2) {
+ return rep1.scale() < rep2.scale();
+ }
+ };
+
+ typedef std::set<ImageSkiaRep, Compare> ImageSkiaRepSet;
+ ImageSkiaRepSet image_skia_reps_;
+ gfx::Size size_;
+
+ DISALLOW_COPY_AND_ASSIGN(PNGImageSource);
+};
+
+} // namespace
+
+ImageSkia* ImageSkiaFromPNG(const std::vector<ImagePNGRep>& image_png_reps) {
+ if (image_png_reps.empty())
+ return GetErrorImageSkia();
+ std::unique_ptr<PNGImageSource> image_source(new PNGImageSource);
+
+ for (size_t i = 0; i < image_png_reps.size(); ++i) {
+ if (!image_source->AddPNGData(image_png_reps[i]))
+ return GetErrorImageSkia();
+ }
+ const gfx::Size& size = image_source->size();
+ DCHECK(!size.IsEmpty());
+ if (size.IsEmpty())
+ return GetErrorImageSkia();
+ return new ImageSkia(std::move(image_source), size);
+}
+
+scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia(
+ const ImageSkia* image_skia) {
+ ImageSkiaRep image_skia_rep = image_skia->GetRepresentation(1.0f);
+
+ scoped_refptr<base::RefCountedBytes> png_bytes(new base::RefCountedBytes());
+ if (image_skia_rep.scale() != 1.0f ||
+ !PNGCodec::EncodeBGRASkBitmap(image_skia_rep.sk_bitmap(), false,
+ &png_bytes->data())) {
+ return NULL;
+ }
+ return png_bytes;
+}
+
+} // namespace internal
+} // namespace gfx
diff --git a/chromium/ui/gfx/image/image_ios.mm b/chromium/ui/gfx/image/image_ios.mm
index 9520f32082b..e1c644d1b5f 100644
--- a/chromium/ui/gfx/image/image_ios.mm
+++ b/chromium/ui/gfx/image/image_ios.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.
-#include "ui/gfx/image/image.h"
+#include "ui/gfx/image/image_platform.h"
#include <stddef.h>
#import <UIKit/UIKit.h>
diff --git a/chromium/ui/gfx/image/image_mac.mm b/chromium/ui/gfx/image/image_mac.mm
index 6358a36dc2d..bce798620b3 100644
--- a/chromium/ui/gfx/image/image_mac.mm
+++ b/chromium/ui/gfx/image/image_mac.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.
-#include "ui/gfx/image/image.h"
+#include "ui/gfx/image/image_platform.h"
#import <AppKit/AppKit.h>
#include <stddef.h>
diff --git a/chromium/ui/gfx/image/image_platform.h b/chromium/ui/gfx/image/image_platform.h
new file mode 100644
index 00000000000..ca49cbebb13
--- /dev/null
+++ b/chromium/ui/gfx/image/image_platform.h
@@ -0,0 +1,57 @@
+// 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.
+
+// This file declares platform-specific helper functions in gfx::internal for
+// use by image.cc.
+//
+// The functions are implemented in image_generic.cc (all platforms other than
+// iOS), image_ios.mm and image_mac.mm.
+
+#ifndef UI_GFX_IMAGE_IMAGE_PLATFORM_H_
+#define UI_GFX_IMAGE_IMAGE_PLATFORM_H_
+
+#include <vector>
+
+#include "base/memory/ref_counted.h"
+#include "base/memory/ref_counted_memory.h"
+#include "build/build_config.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/image/image_png_rep.h"
+#include "ui/gfx/image/image_skia.h"
+
+#if defined(OS_IOS)
+#include "base/mac/foundation_util.h"
+#include "ui/gfx/image/image_skia_util_ios.h"
+#elif defined(OS_MACOSX)
+#include "base/mac/foundation_util.h"
+#include "base/mac/mac_util.h"
+#include "ui/gfx/image/image_skia_util_mac.h"
+#endif
+
+namespace gfx {
+namespace internal {
+
+#if defined(OS_IOS)
+scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromUIImage(
+ UIImage* uiimage);
+// Caller takes ownership of the returned UIImage.
+UIImage* CreateUIImageFromPNG(const std::vector<ImagePNGRep>& image_png_reps);
+gfx::Size UIImageSize(UIImage* image);
+#elif defined(OS_MACOSX)
+scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromNSImage(
+ NSImage* nsimage);
+// Caller takes ownership of the returned NSImage.
+NSImage* NSImageFromPNG(const std::vector<ImagePNGRep>& image_png_reps,
+ CGColorSpaceRef color_space);
+gfx::Size NSImageSize(NSImage* image);
+#endif // defined(OS_MACOSX)
+
+ImageSkia* ImageSkiaFromPNG(const std::vector<ImagePNGRep>& image_png_reps);
+scoped_refptr<base::RefCountedMemory> Get1xPNGBytesFromImageSkia(
+ const ImageSkia* image_skia);
+
+} // namespace internal
+} // namespace gfx
+
+#endif // UI_GFX_IMAGE_IMAGE_PLATFORM_H_
diff --git a/chromium/ui/gfx/image/image_skia.cc b/chromium/ui/gfx/image/image_skia.cc
index bfcd9bb04a8..1ceeaf9916e 100644
--- a/chromium/ui/gfx/image/image_skia.cc
+++ b/chromium/ui/gfx/image/image_skia.cc
@@ -299,9 +299,6 @@ ImageSkia::ImageSkia(std::unique_ptr<ImageSkiaSource> source, float scale)
DetachStorageFromSequence();
}
-ImageSkia::ImageSkia(ImageSkiaSource* source, const gfx::Size& size)
- : ImageSkia(base::WrapUnique(source), size) {}
-
ImageSkia::ImageSkia(const ImageSkiaRep& image_rep) {
Init(image_rep);
// No other thread has reference to this, so it's safe to detach the sequence.
diff --git a/chromium/ui/gfx/image/image_skia.h b/chromium/ui/gfx/image/image_skia.h
index 02f1ae21bcf..aa04e584336 100644
--- a/chromium/ui/gfx/image/image_skia.h
+++ b/chromium/ui/gfx/image/image_skia.h
@@ -53,10 +53,6 @@ class GFX_EXPORT ImageSkia {
// at |scale| and uses its dimensions to calculate the size in DIP.
ImageSkia(std::unique_ptr<ImageSkiaSource> source, float scale);
- // Deprecated versions of the above constructors. ImageSkia takes ownership of
- // |source|.
- ImageSkia(ImageSkiaSource* source, const gfx::Size& size);
-
explicit ImageSkia(const gfx::ImageSkiaRep& image_rep);
// Copies a reference to |other|'s storage.
diff --git a/chromium/ui/gfx/image/image_skia_operations.cc b/chromium/ui/gfx/image/image_skia_operations.cc
index f48d2e1b9c9..df5186a8a79 100644
--- a/chromium/ui/gfx/image/image_skia_operations.cc
+++ b/chromium/ui/gfx/image/image_skia_operations.cc
@@ -9,6 +9,7 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "skia/ext/image_operations.h"
#include "third_party/skia/include/core/SkClipOp.h"
#include "third_party/skia/include/core/SkDrawLooper.h"
@@ -489,7 +490,8 @@ ImageSkia ImageSkiaOperations::CreateBlendedImage(const ImageSkia& first,
if (first.isNull() || second.isNull())
return ImageSkia();
- return ImageSkia(new BlendingImageSource(first, second, alpha), first.size());
+ return ImageSkia(base::MakeUnique<BlendingImageSource>(first, second, alpha),
+ first.size());
}
// static
@@ -499,7 +501,8 @@ ImageSkia ImageSkiaOperations::CreateSuperimposedImage(
if (first.isNull() || second.isNull())
return ImageSkia();
- return ImageSkia(new SuperimposedImageSource(first, second), first.size());
+ return ImageSkia(base::MakeUnique<SuperimposedImageSource>(first, second),
+ first.size());
}
// static
@@ -508,7 +511,8 @@ ImageSkia ImageSkiaOperations::CreateTransparentImage(const ImageSkia& image,
if (image.isNull())
return ImageSkia();
- return ImageSkia(new TransparentImageSource(image, alpha), image.size());
+ return ImageSkia(base::MakeUnique<TransparentImageSource>(image, alpha),
+ image.size());
}
// static
@@ -517,7 +521,7 @@ ImageSkia ImageSkiaOperations::CreateMaskedImage(const ImageSkia& rgb,
if (rgb.isNull() || alpha.isNull())
return ImageSkia();
- return ImageSkia(new MaskedImageSource(rgb, alpha), rgb.size());
+ return ImageSkia(base::MakeUnique<MaskedImageSource>(rgb, alpha), rgb.size());
}
// static
@@ -527,8 +531,9 @@ ImageSkia ImageSkiaOperations::CreateTiledImage(const ImageSkia& source,
if (source.isNull())
return ImageSkia();
- return ImageSkia(new TiledImageSource(source, src_x, src_y, dst_w, dst_h),
- gfx::Size(dst_w, dst_h));
+ return ImageSkia(
+ base::MakeUnique<TiledImageSource>(source, src_x, src_y, dst_w, dst_h),
+ gfx::Size(dst_w, dst_h));
}
// static
@@ -538,7 +543,8 @@ ImageSkia ImageSkiaOperations::CreateHSLShiftedImage(
if (image.isNull())
return ImageSkia();
- return ImageSkia(new HSLImageSource(image, hsl_shift), image.size());
+ return ImageSkia(base::MakeUnique<HSLImageSource>(image, hsl_shift),
+ image.size());
}
// static
@@ -548,7 +554,8 @@ ImageSkia ImageSkiaOperations::CreateButtonBackground(SkColor color,
if (image.isNull() || mask.isNull())
return ImageSkia();
- return ImageSkia(new ButtonImageSource(color, image, mask), mask.size());
+ return ImageSkia(base::MakeUnique<ButtonImageSource>(color, image, mask),
+ mask.size());
}
// static
@@ -560,8 +567,9 @@ ImageSkia ImageSkiaOperations::ExtractSubset(const ImageSkia& image,
return ImageSkia();
}
- return ImageSkia(new ExtractSubsetImageSource(image, clipped_bounds),
- clipped_bounds.size());
+ return ImageSkia(
+ base::MakeUnique<ExtractSubsetImageSource>(image, clipped_bounds),
+ clipped_bounds.size());
}
// static
@@ -572,8 +580,9 @@ ImageSkia ImageSkiaOperations::CreateResizedImage(
if (source.isNull())
return ImageSkia();
- return ImageSkia(new ResizeSource(source, method, target_dip_size),
- target_dip_size);
+ return ImageSkia(
+ base::MakeUnique<ResizeSource>(source, method, target_dip_size),
+ target_dip_size);
}
// static
@@ -587,7 +596,8 @@ ImageSkia ImageSkiaOperations::CreateImageWithDropShadow(
gfx::Size shadow_image_size = source.size();
shadow_image_size.Enlarge(shadow_padding.width(),
shadow_padding.height());
- return ImageSkia(new DropShadowSource(source, shadows), shadow_image_size);
+ return ImageSkia(base::MakeUnique<DropShadowSource>(source, shadows),
+ shadow_image_size);
}
// static
@@ -595,7 +605,7 @@ ImageSkia ImageSkiaOperations::CreateHorizontalShadow(
const std::vector<ShadowValue>& shadows,
bool fades_down) {
auto* source = new HorizontalShadowSource(shadows, fades_down);
- return ImageSkia(source, source->size());
+ return ImageSkia(base::WrapUnique(source), source->size());
}
// static
@@ -605,11 +615,10 @@ ImageSkia ImageSkiaOperations::CreateRotatedImage(
if (source.isNull())
return ImageSkia();
- return ImageSkia(new RotatedSource(source, rotation),
- SkBitmapOperations::ROTATION_180_CW == rotation ?
- source.size() :
- gfx::Size(source.height(), source.width()));
-
+ return ImageSkia(base::MakeUnique<RotatedSource>(source, rotation),
+ SkBitmapOperations::ROTATION_180_CW == rotation
+ ? source.size()
+ : gfx::Size(source.height(), source.width()));
}
// static
@@ -621,7 +630,8 @@ ImageSkia ImageSkiaOperations::CreateIconWithBadge(const ImageSkia& icon,
if (badge.isNull())
return icon;
- return ImageSkia(new IconWithBadgeSource(icon, badge), icon.size());
+ return ImageSkia(base::MakeUnique<IconWithBadgeSource>(icon, badge),
+ icon.size());
}
} // namespace gfx
diff --git a/chromium/ui/gfx/image/image_skia_unittest.cc b/chromium/ui/gfx/image/image_skia_unittest.cc
index df9b42dbed3..971325e1ad7 100644
--- a/chromium/ui/gfx/image/image_skia_unittest.cc
+++ b/chromium/ui/gfx/image/image_skia_unittest.cc
@@ -9,6 +9,7 @@
#include "base/command_line.h"
#include "base/logging.h"
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/threading/simple_thread.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
@@ -154,7 +155,7 @@ class ImageSkiaTest : public testing::Test {
TEST_F(ImageSkiaTest, FixedSource) {
ImageSkiaRep image(Size(100, 200), 0.0f);
- ImageSkia image_skia(new FixedSource(image), Size(100, 200));
+ ImageSkia image_skia(base::MakeUnique<FixedSource>(image), Size(100, 200));
EXPECT_EQ(0U, image_skia.image_reps().size());
const ImageSkiaRep& result_100p = image_skia.GetRepresentation(1.0f);
@@ -191,7 +192,8 @@ TEST_F(ImageSkiaTest, FixedSource) {
TEST_F(ImageSkiaTest, FixedScaledSource) {
ImageSkiaRep image(Size(100, 200), 1.0f);
- ImageSkia image_skia(new FixedScaleSource(image), Size(100, 200));
+ ImageSkia image_skia(base::MakeUnique<FixedScaleSource>(image),
+ Size(100, 200));
EXPECT_EQ(0U, image_skia.image_reps().size());
const ImageSkiaRep& result_100p = image_skia.GetRepresentation(1.0f);
@@ -219,7 +221,8 @@ TEST_F(ImageSkiaTest, FixedScaledSource) {
TEST_F(ImageSkiaTest, FixedUnscaledSource) {
ImageSkiaRep image(Size(100, 200), 0.0f);
- ImageSkia image_skia(new FixedScaleSource(image), Size(100, 200));
+ ImageSkia image_skia(base::MakeUnique<FixedScaleSource>(image),
+ Size(100, 200));
EXPECT_EQ(0U, image_skia.image_reps().size());
const ImageSkiaRep& result_100p = image_skia.GetRepresentation(1.0f);
@@ -244,7 +247,8 @@ TEST_F(ImageSkiaTest, FixedUnscaledSource) {
}
TEST_F(ImageSkiaTest, DynamicSource) {
- ImageSkia image_skia(new DynamicSource(Size(100, 200)), Size(100, 200));
+ ImageSkia image_skia(base::MakeUnique<DynamicSource>(Size(100, 200)),
+ Size(100, 200));
EXPECT_EQ(0U, image_skia.image_reps().size());
const ImageSkiaRep& result_100p = image_skia.GetRepresentation(1.0f);
EXPECT_EQ(100, result_100p.GetWidth());
@@ -277,7 +281,8 @@ TEST_F(ImageSkiaTest, ManyRepsPerScaleFactor) {
const int kSmallIcon2x = 32;
const int kLargeIcon1x = 32;
- ImageSkia image(new NullSource(), gfx::Size(kSmallIcon1x, kSmallIcon1x));
+ ImageSkia image(base::MakeUnique<NullSource>(),
+ gfx::Size(kSmallIcon1x, kSmallIcon1x));
// Simulate a source which loads images on a delay. Upon
// GetImageForScaleFactor, it immediately returns null and starts loading
// image reps slowly.
@@ -308,7 +313,8 @@ TEST_F(ImageSkiaTest, ManyRepsPerScaleFactor) {
}
TEST_F(ImageSkiaTest, GetBitmap) {
- ImageSkia image_skia(new DynamicSource(Size(100, 200)), Size(100, 200));
+ ImageSkia image_skia(base::MakeUnique<DynamicSource>(Size(100, 200)),
+ Size(100, 200));
const SkBitmap* bitmap = image_skia.bitmap();
EXPECT_NE(static_cast<SkBitmap*>(NULL), bitmap);
EXPECT_FALSE(bitmap->isNull());
@@ -427,7 +433,8 @@ TEST_F(ImageSkiaTest, StaticOnThreadTest) {
}
TEST_F(ImageSkiaTest, SourceOnThreadTest) {
- ImageSkia image(new DynamicSource(Size(100, 200)), Size(100, 200));
+ ImageSkia image(base::MakeUnique<DynamicSource>(Size(100, 200)),
+ Size(100, 200));
EXPECT_FALSE(image.IsThreadSafe());
test::TestOnThread image_on_thread(&image);
@@ -507,7 +514,7 @@ std::vector<float> GetSortedScaleFactors(const gfx::ImageSkia& image) {
TEST_F(ImageSkiaTest, ArbitraryScaleFactor) {
// source is owned by |image|
DynamicSource* source = new DynamicSource(Size(100, 200));
- ImageSkia image(source, gfx::Size(100, 200));
+ ImageSkia image(base::WrapUnique(source), gfx::Size(100, 200));
image.GetRepresentation(1.5f);
EXPECT_EQ(2.0f, source->GetLastRequestedScaleAndReset());
@@ -579,8 +586,9 @@ TEST_F(ImageSkiaTest, ArbitraryScaleFactor) {
}
TEST_F(ImageSkiaTest, ArbitraryScaleFactorWithMissingResource) {
- ImageSkia image(new FixedScaleSource(
- ImageSkiaRep(Size(100, 200), 1.0f)), Size(100, 200));
+ ImageSkia image(
+ base::MakeUnique<FixedScaleSource>(ImageSkiaRep(Size(100, 200), 1.0f)),
+ Size(100, 200));
// Requesting 1.5f -- falls back to 2.0f, but couldn't find. It should
// look up 1.0f and then rescale it. Note that the rescaled ImageSkiaRep will
@@ -594,8 +602,9 @@ TEST_F(ImageSkiaTest, ArbitraryScaleFactorWithMissingResource) {
TEST_F(ImageSkiaTest, UnscaledImageForArbitraryScaleFactor) {
// 0.0f means unscaled.
- ImageSkia image(new FixedScaleSource(
- ImageSkiaRep(Size(100, 200), 0.0f)), Size(100, 200));
+ ImageSkia image(
+ base::MakeUnique<FixedScaleSource>(ImageSkiaRep(Size(100, 200), 0.0f)),
+ Size(100, 200));
// Requesting 2.0f, which should return 1.0f unscaled image.
const ImageSkiaRep& rep = image.GetRepresentation(2.0f);
diff --git a/chromium/ui/gfx/image/image_unittest.cc b/chromium/ui/gfx/image/image_unittest.cc
index 317e59830fd..1e0ccd3ac93 100644
--- a/chromium/ui/gfx/image/image_unittest.cc
+++ b/chromium/ui/gfx/image/image_unittest.cc
@@ -50,26 +50,6 @@ TEST_F(ImageTest, EmptyImage) {
EXPECT_TRUE(image.IsEmpty());
EXPECT_EQ(0, image.Width());
EXPECT_EQ(0, image.Height());
-
- // Test the copy constructor.
- gfx::Image imageCopy(image);
- EXPECT_TRUE(imageCopy.IsEmpty());
- EXPECT_EQ(0, imageCopy.Width());
- EXPECT_EQ(0, imageCopy.Height());
-
- // Test calling SwapRepresentations() with an empty image.
- gfx::Image image2(gt::CreateImageSkia(25, 25));
- EXPECT_FALSE(image2.IsEmpty());
- EXPECT_EQ(25, image2.Width());
- EXPECT_EQ(25, image2.Height());
-
- image.SwapRepresentations(&image2);
- EXPECT_FALSE(image.IsEmpty());
- EXPECT_EQ(25, image.Width());
- EXPECT_EQ(25, image.Height());
- EXPECT_TRUE(image2.IsEmpty());
- EXPECT_EQ(0, image2.Width());
- EXPECT_EQ(0, image2.Height());
}
// Test constructing a gfx::Image from an empty PlatformImage.
@@ -590,61 +570,72 @@ TEST_F(ImageTest, SkBitmapConversionPreservesTransparency) {
}
}
-TEST_F(ImageTest, SwapRepresentations) {
+TEST_F(ImageTest, Copy) {
const size_t kRepCount = kUsesSkiaNatively ? 1U : 2U;
gfx::Image image1(gt::CreateImageSkia(25, 25));
- const gfx::ImageSkia* image_skia1 = image1.ToImageSkia();
+ EXPECT_EQ(25, image1.Width());
+ EXPECT_EQ(25, image1.Height());
+ gfx::Image image2(image1);
+ EXPECT_EQ(25, image2.Width());
+ EXPECT_EQ(25, image2.Height());
+
EXPECT_EQ(1U, image1.RepresentationCount());
+ EXPECT_EQ(1U, image2.RepresentationCount());
+ EXPECT_EQ(image1.ToImageSkia(), image2.ToImageSkia());
- gfx::Image image2(gt::CreatePlatformImage());
- const gfx::ImageSkia* image_skia2 = image2.ToImageSkia();
- gt::PlatformImage platform_image = gt::ToPlatformType(image2);
+ EXPECT_TRUE(gt::IsPlatformImageValid(gt::ToPlatformType(image2)));
EXPECT_EQ(kRepCount, image2.RepresentationCount());
+ EXPECT_EQ(kRepCount, image1.RepresentationCount());
+}
- image1.SwapRepresentations(&image2);
+TEST_F(ImageTest, Assign) {
+ gfx::Image image1(gt::CreatePlatformImage());
+ EXPECT_EQ(25, image1.Width());
+ EXPECT_EQ(25, image1.Height());
+ // Assignment must be on a separate line to the declaration in order to test
+ // assignment operator (instead of copy constructor).
+ gfx::Image image2;
+ image2 = image1;
+ EXPECT_EQ(25, image2.Width());
+ EXPECT_EQ(25, image2.Height());
- EXPECT_EQ(image_skia2, image1.ToImageSkia());
- EXPECT_TRUE(gt::PlatformImagesEqual(platform_image,
- gt::ToPlatformType(image1)));
- EXPECT_EQ(image_skia1, image2.ToImageSkia());
- EXPECT_EQ(kRepCount, image1.RepresentationCount());
+ EXPECT_EQ(1U, image1.RepresentationCount());
EXPECT_EQ(1U, image2.RepresentationCount());
+ EXPECT_EQ(image1.ToSkBitmap(), image2.ToSkBitmap());
}
-TEST_F(ImageTest, Copy) {
+TEST_F(ImageTest, Move) {
const size_t kRepCount = kUsesSkiaNatively ? 1U : 2U;
gfx::Image image1(gt::CreateImageSkia(25, 25));
EXPECT_EQ(25, image1.Width());
EXPECT_EQ(25, image1.Height());
- gfx::Image image2(image1);
+ gfx::Image image2(std::move(image1));
EXPECT_EQ(25, image2.Width());
EXPECT_EQ(25, image2.Height());
- EXPECT_EQ(1U, image1.RepresentationCount());
+ EXPECT_EQ(0U, image1.RepresentationCount());
EXPECT_EQ(1U, image2.RepresentationCount());
- EXPECT_EQ(image1.ToImageSkia(), image2.ToImageSkia());
EXPECT_TRUE(gt::IsPlatformImageValid(gt::ToPlatformType(image2)));
+ EXPECT_EQ(0U, image1.RepresentationCount());
EXPECT_EQ(kRepCount, image2.RepresentationCount());
- EXPECT_EQ(kRepCount, image1.RepresentationCount());
}
-TEST_F(ImageTest, Assign) {
+TEST_F(ImageTest, MoveAssign) {
gfx::Image image1(gt::CreatePlatformImage());
EXPECT_EQ(25, image1.Width());
EXPECT_EQ(25, image1.Height());
// Assignment must be on a separate line to the declaration in order to test
- // assignment operator (instead of copy constructor).
+ // move assignment operator (instead of move constructor).
gfx::Image image2;
- image2 = image1;
+ image2 = std::move(image1);
EXPECT_EQ(25, image2.Width());
EXPECT_EQ(25, image2.Height());
- EXPECT_EQ(1U, image1.RepresentationCount());
+ EXPECT_EQ(0U, image1.RepresentationCount());
EXPECT_EQ(1U, image2.RepresentationCount());
- EXPECT_EQ(image1.ToSkBitmap(), image2.ToSkBitmap());
}
TEST_F(ImageTest, MultiResolutionImageSkia) {
diff --git a/chromium/ui/gfx/image/mojo/image_skia_struct_traits.cc b/chromium/ui/gfx/image/mojo/image_skia_struct_traits.cc
index 98ef823b972..cb9487fee78 100644
--- a/chromium/ui/gfx/image/mojo/image_skia_struct_traits.cc
+++ b/chromium/ui/gfx/image/mojo/image_skia_struct_traits.cc
@@ -107,32 +107,12 @@ bool StructTraits<gfx::mojom::ImageSkiaRepDataView, gfx::ImageSkiaRep>::Read(
}
// static
-void* StructTraits<gfx::mojom::ImageSkiaDataView, gfx::ImageSkia>::SetUpContext(
+std::vector<gfx::ImageSkiaRep>
+StructTraits<gfx::mojom::ImageSkiaDataView, gfx::ImageSkia>::image_reps(
const gfx::ImageSkia& input) {
// Trigger the image to load everything.
input.EnsureRepsForSupportedScales();
-
- // Use a context to return a stable list of ImageSkiaRep objects. That is,
- // multiple calls of image_reps() should return exactly the same list of
- // ImageSkiaRep objects. So that ImageSkiaRep with the same backing pixel
- // buffer is properly serialized and only once.
- return new std::vector<gfx::ImageSkiaRep>(input.image_reps());
-}
-
-// static
-void StructTraits<gfx::mojom::ImageSkiaDataView,
- gfx::ImageSkia>::TearDownContext(const gfx::ImageSkia& input,
- void* context) {
- delete static_cast<std::vector<gfx::ImageSkiaRep>*>(context);
-}
-
-// static
-const std::vector<gfx::ImageSkiaRep>&
-StructTraits<gfx::mojom::ImageSkiaDataView, gfx::ImageSkia>::image_reps(
- const gfx::ImageSkia& input,
- void* context) {
- // See the comment in SetUpContext regarding context usage.
- return *(static_cast<std::vector<gfx::ImageSkiaRep>*>(context));
+ return input.image_reps();
}
// static
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 974ec9cf1d7..401b282789e 100644
--- a/chromium/ui/gfx/image/mojo/image_skia_struct_traits.h
+++ b/chromium/ui/gfx/image/mojo/image_skia_struct_traits.h
@@ -56,15 +56,9 @@ struct StructTraits<gfx::mojom::ImageSkiaRepDataView, gfx::ImageSkiaRep> {
template <>
struct StructTraits<gfx::mojom::ImageSkiaDataView, gfx::ImageSkia> {
- static void* SetUpContext(const gfx::ImageSkia& input);
- static void TearDownContext(const gfx::ImageSkia& input, void* context);
- static const std::vector<gfx::ImageSkiaRep>& image_reps(
- const gfx::ImageSkia& input,
- void* context);
+ static std::vector<gfx::ImageSkiaRep> image_reps(const gfx::ImageSkia& input);
- static bool IsNull(const gfx::ImageSkia& input) {
- return input.image_reps().empty();
- }
+ static bool IsNull(const gfx::ImageSkia& input) { return input.isNull(); }
static void SetToNull(gfx::ImageSkia* out) { *out = gfx::ImageSkia(); }
static bool Read(gfx::mojom::ImageSkiaDataView data, gfx::ImageSkia* out);
diff --git a/chromium/ui/gfx/image/mojo/image_traits_unittest.cc b/chromium/ui/gfx/image/mojo/image_traits_unittest.cc
index 6f35c10289e..086790a35cf 100644
--- a/chromium/ui/gfx/image/mojo/image_traits_unittest.cc
+++ b/chromium/ui/gfx/image/mojo/image_traits_unittest.cc
@@ -6,6 +6,7 @@
#include <vector>
#include "base/macros.h"
+#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "mojo/public/cpp/bindings/binding_set.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -130,20 +131,22 @@ TEST_F(ImageTraitsTest, NullImageSkia) {
EXPECT_TRUE(output.isNull());
}
-TEST_F(ImageTraitsTest, ImageSkiaWithNoRepsTreatedAsNull) {
+TEST_F(ImageTraitsTest, ImageSkiaRepsAreCreatedAsNeeded) {
const gfx::Size kSize(1, 2);
- ImageSkia image(new TestImageSkiaSource(kSize), kSize);
- ASSERT_FALSE(image.isNull());
+ ImageSkia image(base::MakeUnique<TestImageSkiaSource>(kSize), kSize);
+ EXPECT_FALSE(image.isNull());
+ EXPECT_TRUE(image.image_reps().empty());
- ImageSkia output(ImageSkiaRep(gfx::Size(1, 1), 1.0f));
- ASSERT_FALSE(output.isNull());
- service()->EchoImageSkia(image, &output);
+ ImageSkia output;
EXPECT_TRUE(output.isNull());
+ service()->EchoImageSkia(image, &output);
+ EXPECT_FALSE(image.image_reps().empty());
+ EXPECT_FALSE(output.isNull());
}
TEST_F(ImageTraitsTest, ImageSkia) {
const gfx::Size kSize(1, 2);
- ImageSkia image(new TestImageSkiaSource(kSize), kSize);
+ ImageSkia image(base::MakeUnique<TestImageSkiaSource>(kSize), kSize);
image.GetRepresentation(1.0f);
image.GetRepresentation(2.0f);
@@ -155,7 +158,7 @@ TEST_F(ImageTraitsTest, ImageSkia) {
TEST_F(ImageTraitsTest, EmptyRepPreserved) {
const gfx::Size kSize(1, 2);
- ImageSkia image(new TestImageSkiaSource(kSize), kSize);
+ ImageSkia image(base::MakeUnique<TestImageSkiaSource>(kSize), kSize);
image.GetRepresentation(1.0f);
SkBitmap empty_bitmap;
@@ -170,7 +173,7 @@ TEST_F(ImageTraitsTest, EmptyRepPreserved) {
TEST_F(ImageTraitsTest, ImageSkiaWithOperations) {
const gfx::Size kSize(32, 32);
- ImageSkia image(new TestImageSkiaSource(kSize), kSize);
+ ImageSkia image(base::MakeUnique<TestImageSkiaSource>(kSize), kSize);
const gfx::Size kNewSize(16, 16);
ImageSkia resized = ImageSkiaOperations::CreateResizedImage(
diff --git a/chromium/ui/gfx/linux/client_native_pixmap_factory_dmabuf.cc b/chromium/ui/gfx/linux/client_native_pixmap_factory_dmabuf.cc
index a91e50645fe..e5d11bb830b 100644
--- a/chromium/ui/gfx/linux/client_native_pixmap_factory_dmabuf.cc
+++ b/chromium/ui/gfx/linux/client_native_pixmap_factory_dmabuf.cc
@@ -68,6 +68,8 @@ class ClientNativePixmapFactoryDmabuf : public ClientNativePixmapFactory {
format == gfx::BufferFormat::BGRA_8888 ||
format == gfx::BufferFormat::RGBX_8888 ||
format == gfx::BufferFormat::RGBA_8888;
+ case gfx::BufferUsage::SCANOUT_VDA_WRITE:
+ return false;
case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE:
case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE_PERSISTENT: {
#if defined(OS_CHROMEOS)
@@ -83,6 +85,18 @@ class ClientNativePixmapFactoryDmabuf : public ClientNativePixmapFactory {
return false;
#endif
}
+ case gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE: {
+#if defined(OS_CHROMEOS)
+ // Each platform only supports one camera buffer type. We list the
+ // supported buffer formats on all platforms here. When allocating a
+ // camera buffer the caller is responsible for making sure a buffer is
+ // successfully allocated. For example, allocating YUV420_BIPLANAR
+ // for SCANOUT_CAMERA_READ_WRITE may only work on Intel boards.
+ return format == gfx::BufferFormat::YUV_420_BIPLANAR;
+#else
+ return false;
+#endif
+ }
}
NOTREACHED();
return false;
@@ -96,6 +110,7 @@ class ClientNativePixmapFactoryDmabuf : public ClientNativePixmapFactory {
case gfx::BufferUsage::SCANOUT_CPU_READ_WRITE:
case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE:
case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE_PERSISTENT:
+ case gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE:
#if defined(OS_CHROMEOS)
return ClientNativePixmapDmaBuf::ImportFromDmabuf(handle, size);
#else
@@ -104,6 +119,7 @@ class ClientNativePixmapFactoryDmabuf : public ClientNativePixmapFactory {
#endif
case gfx::BufferUsage::GPU_READ:
case gfx::BufferUsage::SCANOUT:
+ case gfx::BufferUsage::SCANOUT_VDA_WRITE:
// Close all the fds.
for (const auto& fd : handle.fds)
base::ScopedFD scoped_fd(fd.fd);
diff --git a/chromium/ui/gfx/mojo/BUILD.gn b/chromium/ui/gfx/mojo/BUILD.gn
index 9722968cbd9..b71ee2532d3 100644
--- a/chromium/ui/gfx/mojo/BUILD.gn
+++ b/chromium/ui/gfx/mojo/BUILD.gn
@@ -29,15 +29,3 @@ mojom("test_interfaces") {
":mojo",
]
}
-
-source_set("struct_traits") {
- sources = [
- "selection_bound_struct_traits.h",
- "transform_struct_traits.h",
- ]
- public_deps = [
- ":mojo_shared_cpp_sources",
- "//mojo/public/cpp/bindings",
- "//ui/gfx",
- ]
-}
diff --git a/chromium/ui/gfx/mojo/buffer_types.mojom b/chromium/ui/gfx/mojo/buffer_types.mojom
index 29c50d54179..79b22417a02 100644
--- a/chromium/ui/gfx/mojo/buffer_types.mojom
+++ b/chromium/ui/gfx/mojo/buffer_types.mojom
@@ -32,7 +32,9 @@ enum BufferFormat {
enum BufferUsage {
GPU_READ,
SCANOUT,
+ SCANOUT_CAMERA_READ_WRITE,
SCANOUT_CPU_READ_WRITE,
+ SCANOUT_VDA_WRITE,
GPU_READ_CPU_READ_WRITE,
GPU_READ_CPU_READ_WRITE_PERSISTENT,
diff --git a/chromium/ui/gfx/mojo/buffer_types_struct_traits.cc b/chromium/ui/gfx/mojo/buffer_types_struct_traits.cc
index 186e2eb5502..e9aea16a63c 100644
--- a/chromium/ui/gfx/mojo/buffer_types_struct_traits.cc
+++ b/chromium/ui/gfx/mojo/buffer_types_struct_traits.cc
@@ -8,30 +8,17 @@
namespace mojo {
-void* StructTraits<gfx::mojom::NativePixmapHandleDataView,
- gfx::NativePixmapHandle>::
- SetUpContext(const gfx::NativePixmapHandle& pixmap_handle) {
- auto* handles = new std::vector<mojo::ScopedHandle>();
+std::vector<mojo::ScopedHandle>
+StructTraits<gfx::mojom::NativePixmapHandleDataView, gfx::NativePixmapHandle>::
+ fds(const gfx::NativePixmapHandle& pixmap_handle) {
+ std::vector<mojo::ScopedHandle> handles;
#if defined(OS_LINUX)
for (const base::FileDescriptor& fd : pixmap_handle.fds)
- handles->emplace_back(mojo::WrapPlatformFile(fd.fd));
+ handles.emplace_back(mojo::WrapPlatformFile(fd.fd));
#endif // defined(OS_LINUX)
return handles;
}
-void StructTraits<gfx::mojom::NativePixmapHandleDataView,
- gfx::NativePixmapHandle>::
- TearDownContext(const gfx::NativePixmapHandle& handle, void* context) {
- delete static_cast<std::vector<mojo::ScopedHandle>*>(context);
-}
-
-std::vector<mojo::ScopedHandle>& StructTraits<
- gfx::mojom::NativePixmapHandleDataView,
- gfx::NativePixmapHandle>::fds(const gfx::NativePixmapHandle& pixmap_handle,
- void* context) {
- return *static_cast<std::vector<mojo::ScopedHandle>*>(context);
-}
-
bool StructTraits<
gfx::mojom::NativePixmapHandleDataView,
gfx::NativePixmapHandle>::Read(gfx::mojom::NativePixmapHandleDataView data,
diff --git a/chromium/ui/gfx/mojo/buffer_types_struct_traits.h b/chromium/ui/gfx/mojo/buffer_types_struct_traits.h
index 0fdf909f5fc..368d499c43d 100644
--- a/chromium/ui/gfx/mojo/buffer_types_struct_traits.h
+++ b/chromium/ui/gfx/mojo/buffer_types_struct_traits.h
@@ -126,8 +126,12 @@ struct EnumTraits<gfx::mojom::BufferUsage, gfx::BufferUsage> {
return gfx::mojom::BufferUsage::GPU_READ;
case gfx::BufferUsage::SCANOUT:
return gfx::mojom::BufferUsage::SCANOUT;
+ case gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE:
+ return gfx::mojom::BufferUsage::SCANOUT_CAMERA_READ_WRITE;
case gfx::BufferUsage::SCANOUT_CPU_READ_WRITE:
return gfx::mojom::BufferUsage::SCANOUT_CPU_READ_WRITE;
+ case gfx::BufferUsage::SCANOUT_VDA_WRITE:
+ return gfx::mojom::BufferUsage::SCANOUT_VDA_WRITE;
case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE:
return gfx::mojom::BufferUsage::GPU_READ_CPU_READ_WRITE;
case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE_PERSISTENT:
@@ -145,9 +149,15 @@ struct EnumTraits<gfx::mojom::BufferUsage, gfx::BufferUsage> {
case gfx::mojom::BufferUsage::SCANOUT:
*out = gfx::BufferUsage::SCANOUT;
return true;
+ case gfx::mojom::BufferUsage::SCANOUT_CAMERA_READ_WRITE:
+ *out = gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE;
+ return true;
case gfx::mojom::BufferUsage::SCANOUT_CPU_READ_WRITE:
*out = gfx::BufferUsage::SCANOUT_CPU_READ_WRITE;
return true;
+ case gfx::mojom::BufferUsage::SCANOUT_VDA_WRITE:
+ *out = gfx::BufferUsage::SCANOUT_VDA_WRITE;
+ return true;
case gfx::mojom::BufferUsage::GPU_READ_CPU_READ_WRITE:
*out = gfx::BufferUsage::GPU_READ_CPU_READ_WRITE;
return true;
@@ -239,10 +249,6 @@ struct StructTraits<gfx::mojom::NativePixmapPlaneDataView,
template <>
struct StructTraits<gfx::mojom::NativePixmapHandleDataView,
gfx::NativePixmapHandle> {
- static void* SetUpContext(const gfx::NativePixmapHandle& handle);
- static void TearDownContext(const gfx::NativePixmapHandle& handle,
- void* context);
-
static bool IsNull(const gfx::NativePixmapHandle& handle) {
#if defined(OS_LINUX)
return false;
@@ -251,9 +257,8 @@ struct StructTraits<gfx::mojom::NativePixmapHandleDataView,
return true;
#endif
}
- static std::vector<mojo::ScopedHandle>& fds(
- const gfx::NativePixmapHandle& pixmap_handle,
- void* context);
+ static std::vector<mojo::ScopedHandle> fds(
+ const gfx::NativePixmapHandle& pixmap_handle);
static const std::vector<gfx::NativePixmapPlane>& planes(
const gfx::NativePixmapHandle& pixmap_handle) {
diff --git a/chromium/ui/gfx/mojo/selection_bound.typemap b/chromium/ui/gfx/mojo/selection_bound.typemap
index d188a3a234a..e2b16f7a264 100644
--- a/chromium/ui/gfx/mojo/selection_bound.typemap
+++ b/chromium/ui/gfx/mojo/selection_bound.typemap
@@ -5,7 +5,4 @@
mojom = "//ui/gfx/mojo/selection_bound.mojom"
public_headers = [ "//ui/gfx/selection_bound.h" ]
traits_headers = [ "//ui/gfx/mojo/selection_bound_struct_traits.h" ]
-deps = [
- "//ui/gfx/mojo:struct_traits",
-]
type_mappings = [ "gfx.mojom.SelectionBound=gfx::SelectionBound" ]
diff --git a/chromium/ui/gfx/mojo/transform.typemap b/chromium/ui/gfx/mojo/transform.typemap
index 28da3090487..b675c8f1df4 100644
--- a/chromium/ui/gfx/mojo/transform.typemap
+++ b/chromium/ui/gfx/mojo/transform.typemap
@@ -5,7 +5,4 @@
mojom = "//ui/gfx/mojo/transform.mojom"
public_headers = [ "//ui/gfx/transform.h" ]
traits_headers = [ "//ui/gfx/mojo/transform_struct_traits.h" ]
-deps = [
- "//ui/gfx/mojo:struct_traits",
-]
type_mappings = [ "gfx.mojom.Transform=gfx::Transform" ]
diff --git a/chromium/ui/gfx/native_widget_types.h b/chromium/ui/gfx/native_widget_types.h
index fbe0fef01ac..17f9be2b46e 100644
--- a/chromium/ui/gfx/native_widget_types.h
+++ b/chromium/ui/gfx/native_widget_types.h
@@ -11,7 +11,7 @@
#include "build/build_config.h"
#if defined(OS_ANDROID)
-#include <jni.h>
+#include "base/android/scoped_java_ref.h"
#elif defined(OS_MACOSX)
#include <objc/objc.h>
#endif
@@ -104,7 +104,7 @@ class ViewAndroid;
#endif
class SkBitmap;
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#if defined(USE_X11)
extern "C" {
struct _AtkObject;
typedef struct _AtkObject AtkObject;
@@ -132,13 +132,7 @@ typedef NSEvent* NativeEvent;
typedef void* NativeCursor;
typedef ui::ViewAndroid* NativeView;
typedef ui::WindowAndroid* NativeWindow;
-typedef jobject NativeEvent;
-#elif defined(OS_FUCHSIA)
-// TODO(fuchsia): Update when we have a plan for UI on Fuchsia.
-typedef void* NativeCursor;
-typedef void* NativeView;
-typedef void* NativeWindow;
-typedef void* NativeEvent;
+typedef base::android::ScopedJavaGlobalRef<jobject> NativeEvent;
#else
#error Unknown build environment.
#endif
@@ -154,7 +148,7 @@ typedef NSFont* NativeFont;
typedef id NativeViewAccessible;
#else // Android, Linux, Chrome OS, etc.
// Linux doesn't have a native font type.
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#if defined(USE_X11)
typedef AtkObject* NativeViewAccessible;
#else
typedef void* NativeViewAccessible;
@@ -203,10 +197,6 @@ constexpr AcceleratedWidget kNullAcceleratedWidget = 0;
#elif defined(USE_OZONE)
typedef int32_t AcceleratedWidget;
constexpr AcceleratedWidget kNullAcceleratedWidget = 0;
-#elif defined(OS_FUCHSIA)
-// TODO(fuchsia): Update when we have a plan for UI on Fuchsia.
-typedef void* AcceleratedWidget;
-constexpr AcceleratedWidget kNullAcceleratedWidget = 0;
#else
#error unknown platform
#endif
diff --git a/chromium/ui/gfx/paint_vector_icon.cc b/chromium/ui/gfx/paint_vector_icon.cc
index 0c642bf4ec6..97edb15adeb 100644
--- a/chromium/ui/gfx/paint_vector_icon.cc
+++ b/chromium/ui/gfx/paint_vector_icon.cc
@@ -66,6 +66,7 @@ class PathParser {
case V_LINE_TO:
case R_V_LINE_TO:
case CANVAS_DIMENSIONS:
+ case PATH_COLOR_ALPHA:
return 1;
case MOVE_TO:
@@ -123,6 +124,7 @@ CommandType CommandFromString(const std::string& source) {
return command;
RETURN_IF_IS(NEW_PATH);
+ RETURN_IF_IS(PATH_COLOR_ALPHA);
RETURN_IF_IS(PATH_COLOR_ARGB);
RETURN_IF_IS(PATH_MODE_CLEAR);
RETURN_IF_IS(STROKE);
@@ -213,6 +215,10 @@ void PaintPath(Canvas* canvas,
case NEW_PATH:
break;
+ case PATH_COLOR_ALPHA:
+ flags.setAlpha(SkScalarFloorToInt(arg(0)));
+ break;
+
case PATH_COLOR_ARGB:
flags.setColor(SkColorSetARGB(
SkScalarFloorToInt(arg(0)), SkScalarFloorToInt(arg(1)),
@@ -392,8 +398,9 @@ void PaintPath(Canvas* canvas,
if (elapsed_time >= delay + duration) {
state = 1;
} else if (elapsed_time > delay) {
- state = (elapsed_time - delay).ToInternalValue() /
- static_cast<double>(duration.ToInternalValue());
+ DCHECK(!duration.is_zero());
+ state = (elapsed_time - delay).InMicroseconds() /
+ static_cast<double>(duration.InMicroseconds());
}
auto weight = Tween::CalculateValue(
@@ -432,13 +439,15 @@ void PaintPath(Canvas* canvas,
previous_command_type = command_type;
}
- ScopedRTLFlipCanvas scoped_rtl_flip_canvas(canvas, canvas_size, flips_in_rtl);
+ ScopedCanvas scoped_canvas(canvas);
if (dip_size != canvas_size) {
SkScalar scale = SkIntToScalar(dip_size) / SkIntToScalar(canvas_size);
canvas->sk_canvas()->scale(scale, scale);
}
+ ScopedRTLFlipCanvas scoped_rtl_flip_canvas(canvas, canvas_size, flips_in_rtl);
+
if (!clip_rect.isEmpty())
canvas->sk_canvas()->clipRect(clip_rect);
@@ -497,7 +506,7 @@ class VectorIconCache {
if (iter != images_.end())
return iter->second;
- ImageSkia icon_image(new VectorIconSource(description),
+ ImageSkia icon_image(base::MakeUnique<VectorIconSource>(description),
Size(description.dip_size, description.dip_size));
images_.insert(std::make_pair(description, icon_image));
return icon_image;
diff --git a/chromium/ui/gfx/platform_font_fuchsia.cc b/chromium/ui/gfx/platform_font_fuchsia.cc
new file mode 100644
index 00000000000..d1500668323
--- /dev/null
+++ b/chromium/ui/gfx/platform_font_fuchsia.cc
@@ -0,0 +1,26 @@
+// 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/gfx/platform_font.h"
+
+#include "base/logging.h"
+
+namespace gfx {
+
+// static
+PlatformFont* PlatformFont::CreateDefault() {
+ // TODO(fuchsia): Stubbed during headless bringup, https://crbug.com/743296.
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
+// static
+PlatformFont* PlatformFont::CreateFromNameAndSize(const std::string& font_name,
+ int font_size) {
+ // TODO(fuchsia): Stubbed during headless bringup, https://crbug.com/743296.
+ NOTIMPLEMENTED();
+ return NULL;
+}
+
+} // namespace gfx
diff --git a/chromium/ui/gfx/platform_font_win.cc b/chromium/ui/gfx/platform_font_win.cc
index 100ee944050..35f5a212bcd 100644
--- a/chromium/ui/gfx/platform_font_win.cc
+++ b/chromium/ui/gfx/platform_font_win.cc
@@ -395,6 +395,11 @@ void PlatformFontWin::SetDirectWriteFactory(IDWriteFactory* factory) {
}
// static
+bool PlatformFontWin::IsDirectWriteEnabled() {
+ return direct_write_factory_ != nullptr;
+}
+
+// static
void PlatformFontWin::GetTextMetricsForFont(HDC hdc,
HFONT font,
TEXTMETRIC* text_metrics) {
@@ -465,7 +470,7 @@ PlatformFontWin::HFontRef* PlatformFontWin::CreateHFontRef(HFONT font) {
GetTextMetricsForFont(screen_dc, font, &font_metrics);
}
- if (direct_write_factory_)
+ if (IsDirectWriteEnabled())
return CreateHFontRefFromSkia(font, font_metrics);
return CreateHFontRefFromGDI(font, font_metrics);
diff --git a/chromium/ui/gfx/platform_font_win.h b/chromium/ui/gfx/platform_font_win.h
index ac4f6640802..5e8e72f4283 100644
--- a/chromium/ui/gfx/platform_font_win.h
+++ b/chromium/ui/gfx/platform_font_win.h
@@ -71,6 +71,8 @@ class GFX_EXPORT PlatformFontWin : public PlatformFont {
// from skia and DirectWrite.
static void SetDirectWriteFactory(IDWriteFactory* factory);
+ static bool IsDirectWriteEnabled();
+
// Returns the GDI metrics for the font passed in.
static void GetTextMetricsForFont(HDC hdc,
HFONT font,
diff --git a/chromium/ui/gfx/render_text.cc b/chromium/ui/gfx/render_text.cc
index 041c9f27ee4..f8999eb9f61 100644
--- a/chromium/ui/gfx/render_text.cc
+++ b/chromium/ui/gfx/render_text.cc
@@ -18,6 +18,7 @@
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/trace_event.h"
#include "build/build_config.h"
+#include "cc/base/math_util.h"
#include "cc/paint/paint_canvas.h"
#include "cc/paint/paint_shader.h"
#include "third_party/icu/source/common/unicode/rbbi.h"
@@ -231,8 +232,16 @@ void SkiaTextRenderer::SetShader(sk_sp<cc::PaintShader> shader) {
void SkiaTextRenderer::DrawPosText(const SkPoint* pos,
const uint16_t* glyphs,
size_t glyph_count) {
- const size_t byte_length = glyph_count * sizeof(glyphs[0]);
- canvas_skia_->drawPosText(&glyphs[0], byte_length, &pos[0], flags_);
+ SkTextBlobBuilder builder;
+ const auto& run_buffer = builder.allocRunPos(flags_.ToSkPaint(), glyph_count);
+
+ static_assert(sizeof(*glyphs) == sizeof(*run_buffer.glyphs), "");
+ memcpy(run_buffer.glyphs, glyphs, glyph_count * sizeof(*glyphs));
+
+ static_assert(sizeof(*pos) == 2 * sizeof(*run_buffer.pos), "");
+ memcpy(run_buffer.pos, pos, glyph_count * sizeof(*pos));
+
+ canvas_skia_->drawTextBlob(builder.make(), 0, 0, flags_);
}
void SkiaTextRenderer::DrawUnderline(int x, int y, int width) {
@@ -1424,11 +1433,34 @@ base::string16 RenderText::Elide(const base::string16& text,
StringSlicer slicer(text, ellipsis, elide_in_middle, elide_at_beginning);
- // Use binary search to compute the elided text.
+ // Use binary(-like) search to compute the elided text. In particular, do
+ // an interpolation search, which is a binary search in which each guess
+ // is an attempt to smartly calculate the right point rather than blindly
+ // guessing midway between the endpoints.
size_t lo = 0;
size_t hi = text.length() - 1;
+ size_t guess = std::string::npos;
+ // These two widths are not exactly right but they're good enough to provide
+ // some guidance to the search. For example, |text_width| is actually the
+ // length of text.length(), not text.length()-1.
+ float lo_width = 0;
+ float hi_width = text_width;
const base::i18n::TextDirection text_direction = GetTextDirection(text);
- for (size_t guess = (lo + hi) / 2; lo <= hi; guess = (lo + hi) / 2) {
+ while (lo <= hi) {
+ // Linearly interpolate between |lo| and |hi|, which correspond to widths
+ // of |lo_width| and |hi_width| to estimate at what position
+ // |available_width| would be at. Because |lo_width| and |hi_width| are
+ // both estimates (may be off by a little because, for example, |lo_width|
+ // may have been calculated from |lo| minus one, not |lo|), we clamp to the
+ // the valid range.
+ // |last_guess| is merely used to verify that we're not repeating guesses.
+ const size_t last_guess = guess;
+ guess = lo + static_cast<size_t>(ToRoundedInt((available_width - lo_width) *
+ (hi - lo) /
+ (hi_width - lo_width)));
+ guess = cc::MathUtil::ClampToRange(guess, lo, hi);
+ DCHECK_NE(last_guess, guess);
+
// Restore colors. They will be truncated to size by SetText.
render_text->colors_ = colors_;
base::string16 new_text =
@@ -1469,11 +1501,15 @@ base::string16 RenderText::Elide(const base::string16& text,
break;
if (guess_width > available_width) {
hi = guess - 1;
+ hi_width = guess_width;
// Move back on the loop terminating condition when the guess is too wide.
- if (hi < lo)
+ if (hi < lo) {
lo = hi;
+ lo_width = guess_width;
+ }
} else {
lo = guess + 1;
+ lo_width = guess_width;
}
}
diff --git a/chromium/ui/gfx/render_text.h b/chromium/ui/gfx/render_text.h
index 24ea3d4123d..024c73ed1ac 100644
--- a/chromium/ui/gfx/render_text.h
+++ b/chromium/ui/gfx/render_text.h
@@ -64,6 +64,7 @@ class GFX_EXPORT SkiaTextRenderer {
void SetForegroundColor(SkColor foreground);
void SetShader(sk_sp<cc::PaintShader> shader);
void DrawSelection(const std::vector<Rect>& selection, SkColor color);
+ // TODO(vmpstr): Change this API to mimic SkCanvas::drawTextBlob instead.
virtual void DrawPosText(const SkPoint* pos,
const uint16_t* glyphs,
size_t glyph_count);
diff --git a/chromium/ui/gfx/render_text_harfbuzz.cc b/chromium/ui/gfx/render_text_harfbuzz.cc
index 2f0286217a5..07a4bbd44b0 100644
--- a/chromium/ui/gfx/render_text_harfbuzz.cc
+++ b/chromium/ui/gfx/render_text_harfbuzz.cc
@@ -15,6 +15,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/profiler/scoped_tracker.h"
+#include "base/strings/string_number_conversions.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/trace_event.h"
@@ -207,8 +208,9 @@ bool IsNewlineSegment(const base::string16& text,
// Helper template function for |TextRunHarfBuzz::GetClusterAt()|. |Iterator|
// can be a forward or reverse iterator type depending on the text direction.
+// Returns true on success, or false if an error is encountered.
template <class Iterator>
-void GetClusterAtImpl(size_t pos,
+bool GetClusterAtImpl(size_t pos,
Range range,
Iterator elements_begin,
Iterator elements_end,
@@ -216,10 +218,14 @@ void GetClusterAtImpl(size_t pos,
Range* chars,
Range* glyphs) {
Iterator element = std::upper_bound(elements_begin, elements_end, pos);
+ if (element == elements_begin) {
+ *chars = range;
+ *glyphs = Range();
+ return false;
+ }
+
chars->set_end(element == elements_end ? range.end() : *element);
glyphs->set_end(reversed ? elements_end - element : element - elements_begin);
-
- DCHECK(element != elements_begin);
while (--element != elements_begin && *element == *(element - 1));
chars->set_start(*element);
glyphs->set_start(
@@ -231,6 +237,7 @@ void GetClusterAtImpl(size_t pos,
DCHECK(!chars->is_empty());
DCHECK(!glyphs->is_reversed());
DCHECK(!glyphs->is_empty());
+ return true;
}
// Returns the line segment index for the |line|, |text_x| pair. |text_x| is
@@ -680,24 +687,37 @@ size_t TextRunHarfBuzz::CountMissingGlyphs() const {
void TextRunHarfBuzz::GetClusterAt(size_t pos,
Range* chars,
Range* glyphs) const {
- DCHECK(range.Contains(Range(pos, pos + 1)));
DCHECK(chars);
DCHECK(glyphs);
- if (glyph_count == 0) {
+ bool success = true;
+ if (glyph_count == 0 || !range.Contains(Range(pos, pos + 1))) {
*chars = range;
*glyphs = Range();
- return;
+ success = false;
}
if (is_rtl) {
- GetClusterAtImpl(pos, range, glyph_to_char.rbegin(), glyph_to_char.rend(),
- true, chars, glyphs);
- return;
+ success &= GetClusterAtImpl(pos, range, glyph_to_char.rbegin(),
+ glyph_to_char.rend(), true, chars, glyphs);
+ } else {
+ success &= GetClusterAtImpl(pos, range, glyph_to_char.begin(),
+ glyph_to_char.end(), false, chars, glyphs);
}
- GetClusterAtImpl(pos, range, glyph_to_char.begin(), glyph_to_char.end(),
- false, chars, glyphs);
+ if (!success) {
+ std::string glyph_to_char_string;
+ for (size_t i = 0; i < glyph_count && i < glyph_to_char.size(); ++i) {
+ glyph_to_char_string += base::SizeTToString(i) + "->" +
+ base::UintToString(glyph_to_char[i]) + ", ";
+ }
+ LOG(ERROR) << " TextRunHarfBuzz error, please report at crbug.com/724880:"
+ << " range: " << range.ToString() << ", rtl: " << is_rtl << ","
+ << " level: '" << level << "', script: " << script << ","
+ << " font: '" << font.GetActualFontNameForTesting() << "',"
+ << " glyph_count: " << glyph_count << ", pos: " << pos << ","
+ << " glyph_to_char: " << glyph_to_char_string;
+ }
}
RangeF TextRunHarfBuzz::GetGraphemeBounds(RenderTextHarfBuzz* render_text,
diff --git a/chromium/ui/gfx/render_text_unittest.cc b/chromium/ui/gfx/render_text_unittest.cc
index 72b1673b51b..1eee0004e3f 100644
--- a/chromium/ui/gfx/render_text_unittest.cc
+++ b/chromium/ui/gfx/render_text_unittest.cc
@@ -24,7 +24,7 @@
#include "base/test/scoped_task_environment.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "third_party/skia/include/core/SkRefCnt.h"
+#include "third_party/skia/include/core/SkFontStyle.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "third_party/skia/include/core/SkTypeface.h"
#include "ui/gfx/break_list.h"
@@ -70,7 +70,7 @@ class RenderTextTestApi {
// Callers should ensure that the associated RenderText object is a
// RenderTextHarfBuzz instance.
- internal::TextRunList* GetHarfBuzzRunList() {
+ const internal::TextRunList* GetHarfBuzzRunList() const {
RenderTextHarfBuzz* render_text =
static_cast<RenderTextHarfBuzz*>(render_text_);
return render_text->GetRunList();
@@ -428,6 +428,14 @@ class RenderTextTest : public testing::Test,
renderer_(canvas()) {}
protected:
+ bool IsWin8Plus() const {
+#if defined(OS_WIN)
+ return base::win::GetVersion() >= base::win::VERSION_WIN8;
+#else
+ return false;
+#endif
+ }
+
std::unique_ptr<RenderText> CreateRenderTextInstance() const {
switch (GetParam()) {
case RENDER_TEXT_HARFBUZZ:
@@ -450,14 +458,43 @@ class RenderTextTest : public testing::Test,
void DrawVisualText() { test_api_->DrawVisualText(renderer()); }
- internal::TextRunList* GetHarfBuzzRunList() {
+ const internal::TextRunList* GetHarfBuzzRunList() const {
DCHECK_EQ(RENDER_TEXT_HARFBUZZ, GetParam());
return test_api_->GetHarfBuzzRunList();
}
+ // Converts the current run list into a human-readable string. Can be used in
+ // test assertions for a readable expectation and failure message.
+ //
+ // The string shows the runs in visual order. Each run is enclosed in square
+ // brackets, and shows the begin and end inclusive logical character position,
+ // with an arrow indicating the direction of the run. Single-character runs
+ // just show the character position.
+ //
+ // For example, the the logical bidirectional string "abc+\x05d0\x05d1\x05d2"
+ // (visual string: "abc+אבג") yields "[0->2][3][6<-4]".
+ std::string GetRunListStructureString() const {
+ const internal::TextRunList* run_list = GetHarfBuzzRunList();
+ std::string result;
+ for (size_t i = 0; i < run_list->size(); ++i) {
+ size_t logical_index = run_list->visual_to_logical(i);
+ const internal::TextRunHarfBuzz& run = *run_list->runs()[logical_index];
+ if (run.range.length() == 1) {
+ result.append(base::StringPrintf("[%d]", run.range.start()));
+ } else if (run.is_rtl) {
+ result.append(base::StringPrintf("[%d<-%d]", run.range.end() - 1,
+ run.range.start()));
+ } else {
+ result.append(base::StringPrintf("[%d->%d]", run.range.start(),
+ run.range.end() - 1));
+ }
+ }
+ return result;
+ }
+
// Returns a vector of text fragments corresponding to the current list of
// text runs.
- std::vector<base::string16> GetRuns() {
+ std::vector<base::string16> GetRunListStrings() const {
std::vector<base::string16> runs_as_text;
const std::vector<RenderText::FontSpan> spans =
render_text_->GetFontSpansForTesting();
@@ -468,11 +505,11 @@ class RenderTextTest : public testing::Test,
return runs_as_text;
}
- // Sets the text to |text|, then returns GetRuns().
+ // Sets the text to |text|, then returns GetRunListStrings().
std::vector<base::string16> RunsFor(const base::string16& text) {
render_text_->SetText(text);
test_api()->EnsureLayout();
- return GetRuns();
+ return GetRunListStrings();
}
void ResetRenderTextInstance() {
@@ -968,43 +1005,58 @@ TEST_P(RenderTextTest, ElidedText) {
const wchar_t* display_text;
const bool elision_expected;
} cases[] = {
- // Strings shorter than the elision width should be laid out in full.
- { L"", L"" , false },
- { L"M", L"" , false },
- { L" . ", L" . " , false },
- { kWeak, kWeak , false },
- { kLtr, kLtr , false },
- { kLtrRtl, kLtrRtl , false },
- { kLtrRtlLtr, kLtrRtlLtr, false },
- { kRtl, kRtl , false },
- { kRtlLtr, kRtlLtr , false },
- { kRtlLtrRtl, kRtlLtrRtl, false },
- // Strings as long as the elision width should be laid out in full.
- { L"012ab", L"012ab" , false },
- // Long strings should be elided with an ellipsis appended at the end.
- { L"012abc", L"012a\x2026", true },
- { L"012ab" L"\x5d0\x5d1", L"012a\x2026", true },
- { L"012a" L"\x5d1" L"b", L"012a\x2026", true },
- // No RLM marker added as digits (012) have weak directionality.
- { L"01" L"\x5d0\x5d1\x5d2", L"01\x5d0\x5d1\x2026", true },
- // RLM marker added as "ab" have strong LTR directionality.
- { L"ab" L"\x5d0\x5d1\x5d2", L"ab\x5d0\x5d1\x2026\x200f", true },
- // Test surrogate pairs. \xd834\xdd1e forms a single code point U+1D11E;
- // \xd834\xdd22 forms a second code point U+1D122. The first should be kept;
- // the second removed (no surrogate pair should be partially elided).
- { L"0123\xd834\xdd1e\xd834\xdd22", L"0123\xd834\xdd1e\x2026", true },
- // Test combining character sequences. U+0915 U+093F forms a compound glyph;
- // U+0915 U+0942 forms a second compound glyph. The first should be kept;
- // the second removed (no combining sequence should be partially elided).
- { L"0123\x0915\x093f\x0915\x0942", L"0123\x0915\x093f\x2026", true },
- // U+05E9 U+05BC U+05C1 U+05B8 forms a four-character compound glyph. Again,
- // it should be either fully elided, or not elided at all. If completely
- // elided, an LTR Mark (U+200E) should be added.
- { L"0\x05e9\x05bc\x05c1\x05b8", L"0\x05e9\x05bc\x05c1\x05b8", false },
- { L"0\x05e9\x05bc\x05c1\x05b8", L"0\x2026\x200E" , true },
- { L"01\x05e9\x05bc\x05c1\x05b8", L"01\x2026\x200E" , true },
- { L"012\x05e9\x05bc\x05c1\x05b8", L"012\x2026\x200E" , true },
- { L"012\xF0\x9D\x84\x9E", L"012\xF0\x2026" , true },
+ // Strings shorter than the elision width should be laid out in full.
+ {L"", L"", false},
+ {L"M", L"", false},
+ {L" . ", L" . ", false},
+ {kWeak, kWeak, false},
+ {kLtr, kLtr, false},
+ {kLtrRtl, kLtrRtl, false},
+ {kLtrRtlLtr, kLtrRtlLtr, false},
+ {kRtl, kRtl, false},
+ {kRtlLtr, kRtlLtr, false},
+ {kRtlLtrRtl, kRtlLtrRtl, false},
+ // Strings as long as the elision width should be laid out in full.
+ {L"012ab", L"012ab", false},
+ // Long strings should be elided with an ellipsis appended at the end.
+ {L"012abc", L"012a\x2026", true},
+ {L"012ab"
+ L"\x5d0\x5d1",
+ L"012a\x2026", true},
+ {L"012a"
+ L"\x5d1"
+ L"b",
+ L"012a\x2026", true},
+ // No RLM marker added as digits (012) have weak directionality.
+ {L"01"
+ L"\x5d0\x5d1\x5d2",
+ L"01\x5d0\x5d1\x2026", true},
+ // RLM marker added as "ab" have strong LTR directionality.
+ {L"ab"
+ L"\x5d0\x5d1\x5d2",
+ L"ab\x5d0\x5d1\x2026\x200f", true},
+ // Test surrogate pairs. \xd834\xdd1e forms a single code point U+1D11E;
+ // \xd834\xdd22 forms a second code point U+1D122. The first should be
+ // kept;
+ // the second removed (no surrogate pair should be partially elided).
+ {L"0123\xd834\xdd1e\xd834\xdd22", L"0123\xd834\xdd1e\x2026", true},
+ // Test combining character sequences. U+0915 U+093F forms a compound
+ // glyph;
+ // U+0915 U+0942 forms a second compound glyph. The first should be kept;
+ // the second removed (no combining sequence should be partially elided).
+ {L"0123\x0915\x093f\x0915\x0942", L"0123\x0915\x093f\x2026", true},
+ // U+05E9 U+05BC U+05C1 U+05B8 forms a four-character compound glyph.
+ // Again,
+ // it should be either fully elided, or not elided at all. If completely
+ // elided, an LTR Mark (U+200E) should be added.
+ {L"0\x05e9\x05bc\x05c1\x05b8", L"0\x05e9\x05bc\x05c1\x05b8", false},
+ {L"0\x05e9\x05bc\x05c1\x05b8", L"0\x2026\x200E", true},
+ {L"01\x05e9\x05bc\x05c1\x05b8", L"01\x2026\x200E", true},
+ {L"012\x05e9\x05bc\x05c1\x05b8", L"012\x2026\x200E", true},
+ // \xF0\x9D\x84\x9E is the UTF-8 bytestring for MUSICAL SYMBOL G CLEF. It
+ // should not have any internal grapheme boundaries; it should be
+ // completely removed when eliding.
+ {L"012\xF0\x9D\x84\x9E", L"012\x2026", true},
};
std::unique_ptr<RenderText> expected_render_text(CreateRenderTextInstance());
@@ -3019,8 +3071,11 @@ TEST_P(RenderTextHarfBuzzTest, Multiline_NormalWidth) {
{L"abc defg hijkl", Range(0, 9), Range(9, 14), {3, 1, 4, 1, 5}, 4, true},
{L"qwertyzxcvbn", Range(0, 10), Range(10, 12), {10, 2}, 1, true},
// RTL: should render left-to-right as "<space>43210 \n cba9876".
+ // Note this used to say "Arabic language", in Arabic, but the last
+ // character in the string (\x0629) got fancy in an updated Mac font, so
+ // now the penultimate character repeats. (See "NOTE" below).
{L"\x0627\x0644\x0644\x063A\x0629 "
- L"\x0627\x0644\x0639\x0631\x0628\x064A\x0629",
+ L"\x0627\x0644\x0639\x0631\x0628\x064A\x064A",
Range(0, 6),
Range(6, 13),
{1 /* space first */, 5, 7},
@@ -3184,24 +3239,27 @@ TEST_P(RenderTextHarfBuzzTest, Multiline_NewlineCharacterReplacement) {
// Ensure horizontal alignment works in multiline mode.
TEST_P(RenderTextHarfBuzzTest, Multiline_HorizontalAlignment) {
- const struct {
+ constexpr struct {
const wchar_t* const text;
const HorizontalAlignment alignment;
+ const base::i18n::TextDirection display_text_direction;
} kTestStrings[] = {
- { L"abcdefghij\nhijkl", ALIGN_LEFT },
- { L"nhijkl\nabcdefghij", ALIGN_LEFT },
- // hebrew, 2nd line shorter
- { L"\x5d0\x5d1\x5d2\x5d3\x5d4\x5d5\x5d6\x5d7\n\x5d0\x5d1\x5d2\x5d3",
- ALIGN_RIGHT },
- // hebrew, 2nd line longer
- { L"\x5d0\x5d1\x5d2\x5d3\n\x5d0\x5d1\x5d2\x5d3\x5d4\x5d5\x5d6\x5d7",
- ALIGN_RIGHT },
- // arabic, 2nd line shorter
- { L"\x62a\x62b\x62c\x62d\x62e\x62f\x630\n\x660\x661\x662\x663\x664",
- ALIGN_RIGHT },
- // arabic, 2nd line longer
- { L"\x660\x661\x662\x663\x664\n\x62a\x62b\x62c\x62d\x62e\x62f\x630",
- ALIGN_RIGHT },
+ {L"abcdefghi\nhijk", ALIGN_LEFT, base::i18n::LEFT_TO_RIGHT},
+ {L"nhij\nabcdefghi", ALIGN_LEFT, base::i18n::LEFT_TO_RIGHT},
+ // Hebrew, 2nd line shorter
+ {L"\x5d0\x5d1\x5d2\x5d3\x5d4\x5d5\x5d6\x5d7\n\x5d0\x5d1\x5d2\x5d3",
+ ALIGN_RIGHT, base::i18n::RIGHT_TO_LEFT},
+ // Hebrew, 2nd line longer
+ {L"\x5d0\x5d1\x5d2\x5d3\n\x5d0\x5d1\x5d2\x5d3\x5d4\x5d5\x5d6\x5d7",
+ ALIGN_RIGHT, base::i18n::RIGHT_TO_LEFT},
+ // Arabic, 2nd line shorter.
+ {L"\x0627\x0627\x0627\x0627\x0627\x0627\x0627\x0627\n\x0627\x0644\x0644"
+ L"\x063A",
+ ALIGN_RIGHT, base::i18n::RIGHT_TO_LEFT},
+ // Arabic, 2nd line longer.
+ {L"\x0627\x0644\x0644\x063A\n\x0627\x0627\x0627\x0627\x0627\x0627\x0627"
+ L"\x0627",
+ ALIGN_RIGHT, base::i18n::RIGHT_TO_LEFT},
};
const int kGlyphSize = 5;
RenderTextHarfBuzz* render_text = GetRenderTextHarfBuzz();
@@ -3211,9 +3269,11 @@ TEST_P(RenderTextHarfBuzzTest, Multiline_HorizontalAlignment) {
render_text->SetMultiline(true);
for (size_t i = 0; i < arraysize(kTestStrings); ++i) {
- SCOPED_TRACE(base::StringPrintf("kTestStrings[%" PRIuS "] %ls", i,
- kTestStrings[i].text));
+ SCOPED_TRACE(testing::Message("kTestStrings[")
+ << i << "] = " << kTestStrings[i].text);
render_text->SetText(WideToUTF16(kTestStrings[i].text));
+ EXPECT_EQ(kTestStrings[i].display_text_direction,
+ render_text->GetDisplayTextDirection());
render_text->Draw(canvas());
ASSERT_LE(2u, test_api()->lines().size());
if (kTestStrings[i].alignment == ALIGN_LEFT) {
@@ -3224,6 +3284,16 @@ TEST_P(RenderTextHarfBuzzTest, Multiline_HorizontalAlignment) {
base::WideToUTF16(kTestStrings[i].text),
base::string16(1, '\n'), base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
ASSERT_EQ(2u, lines.size());
+
+ // Sanity check the input string lengths match the glyph lengths.
+ EXPECT_EQ(4u, std::min(lines[0].length(), lines[1].length()));
+ EXPECT_EQ(8u, std::max(lines[0].length(), lines[1].length()));
+ const internal::TextRunList* run_list = GetHarfBuzzRunList();
+ ASSERT_EQ(3U, run_list->runs().size());
+ EXPECT_EQ(lines[0].length(), run_list->runs()[0]->glyph_count);
+ EXPECT_EQ(1u, run_list->runs()[1]->glyph_count); // \n.
+ EXPECT_EQ(lines[1].length(), run_list->runs()[2]->glyph_count);
+
int difference = (lines[0].length() - lines[1].length()) * kGlyphSize;
EXPECT_EQ(test_api()->GetAlignmentOffset(0).x() + difference,
test_api()->GetAlignmentOffset(1).x());
@@ -3434,14 +3504,12 @@ TEST_P(RenderTextHarfBuzzTest, NewlineWithoutMultilineFlag) {
TEST_P(RenderTextHarfBuzzTest, HarfBuzz_HorizontalPositions) {
const struct {
const wchar_t* const text;
- const Range first_run_char_range;
- const Range second_run_char_range;
- bool is_rtl;
+ const char* expected_runs;
} kTestStrings[] = {
- { L"abc\x3042\x3044\x3046\x3048\x304A", Range(0, 3), Range(3, 8), false },
- { L"\x062A\x0641\x0627\x062D"
- L"\x05EA\x05E4\x05D5\x05D6\x05D9\x05DA\x05DB\x05DD",
- Range(0, 4), Range(4, 12), true },
+ {L"abc\x3042\x3044\x3046\x3048\x304A", "[0->2][3->7]"},
+ {L"\x062A\x0641\x0627\x062D"
+ L"\x05EA\x05E4\x05D5\x05D6\x05D9\x05DA\x05DB\x05DD",
+ "[11<-4][3<-0]"},
};
RenderTextHarfBuzz* render_text = GetRenderTextHarfBuzz();
@@ -3451,26 +3519,16 @@ TEST_P(RenderTextHarfBuzzTest, HarfBuzz_HorizontalPositions) {
render_text->SetText(WideToUTF16(kTestStrings[i].text));
test_api()->EnsureLayout();
- const internal::TextRunList* run_list = GetHarfBuzzRunList();
- ASSERT_EQ(2U, run_list->runs().size());
- EXPECT_EQ(kTestStrings[i].first_run_char_range, run_list->runs()[0]->range);
- EXPECT_EQ(kTestStrings[i].second_run_char_range,
- run_list->runs()[1]->range);
- // If it's RTL, the visual order is reversed.
- if (kTestStrings[i].is_rtl) {
- EXPECT_EQ(1U, run_list->logical_to_visual(0));
- EXPECT_EQ(0U, run_list->logical_to_visual(1));
- } else {
- EXPECT_EQ(0U, run_list->logical_to_visual(0));
- EXPECT_EQ(1U, run_list->logical_to_visual(1));
- }
+ EXPECT_EQ(kTestStrings[i].expected_runs, GetRunListStructureString());
DrawVisualText();
std::vector<TestSkiaTextRenderer::TextLog> text_log;
renderer()->GetTextLogAndReset(&text_log);
- EXPECT_EQ(2U, text_log.size());
+ const internal::TextRunList* run_list = GetHarfBuzzRunList();
+ ASSERT_EQ(2U, run_list->size());
+ ASSERT_EQ(2U, text_log.size());
// Verifies the DrawText happens in the visual order and left-to-right.
// If the text is RTL, the logically first run should be drawn at last.
@@ -3538,6 +3596,19 @@ TEST_P(RenderTextHarfBuzzTest, HarfBuzz_Clusters) {
}
}
+// Ensures GetClusterAt does not crash on invalid conditions. crbug.com/724880
+TEST_P(RenderTextHarfBuzzTest, HarfBuzz_NoCrashOnTextRunGetClusterAt) {
+ internal::TextRunHarfBuzz run((Font()));
+ run.range = Range(0, 4);
+ run.glyph_count = 4;
+ // Construct a |glyph_to_char| map where no glyph maps to the first character.
+ run.glyph_to_char = {1u, 1u, 2u, 3u};
+
+ Range chars, glyphs;
+ // GetClusterAt should not crash asking for the cluster at position 0.
+ ASSERT_NO_FATAL_FAILURE(run.GetClusterAt(0, &chars, &glyphs));
+}
+
// Ensure that graphemes with multiple code points do not get split.
TEST_P(RenderTextHarfBuzzTest, HarfBuzz_SubglyphGraphemeCases) {
const wchar_t* cases[] = {
@@ -3558,7 +3629,7 @@ TEST_P(RenderTextHarfBuzzTest, HarfBuzz_SubglyphGraphemeCases) {
base::string16 text = WideToUTF16(cases[i]);
render_text->SetText(text);
test_api()->EnsureLayout();
- internal::TextRunList* run_list = GetHarfBuzzRunList();
+ const internal::TextRunList* run_list = GetHarfBuzzRunList();
ASSERT_EQ(1U, run_list->size());
internal::TextRunHarfBuzz* run = run_list->runs()[0].get();
@@ -3635,33 +3706,11 @@ TEST_P(RenderTextHarfBuzzTest, HarfBuzz_RunDirection) {
// Get the run list for both display directions.
render_text->SetDirectionalityMode(DIRECTIONALITY_FORCE_LTR);
test_api()->EnsureLayout();
- internal::TextRunList* run_list = GetHarfBuzzRunList();
- ASSERT_EQ(4U, run_list->size());
- EXPECT_TRUE(run_list->runs()[0]->is_rtl);
- EXPECT_FALSE(run_list->runs()[1]->is_rtl);
- EXPECT_TRUE(run_list->runs()[2]->is_rtl);
- EXPECT_FALSE(run_list->runs()[3]->is_rtl);
-
- // The Latin letters should appear to the right of the other runs.
- EXPECT_EQ(2U, run_list->logical_to_visual(0));
- EXPECT_EQ(1U, run_list->logical_to_visual(1));
- EXPECT_EQ(0U, run_list->logical_to_visual(2));
- EXPECT_EQ(3U, run_list->logical_to_visual(3));
+ EXPECT_EQ("[7<-6][2->5][1<-0][8->10]", GetRunListStructureString());
render_text->SetDirectionalityMode(DIRECTIONALITY_FORCE_RTL);
test_api()->EnsureLayout();
- run_list = GetHarfBuzzRunList();
- ASSERT_EQ(4U, run_list->size());
- EXPECT_TRUE(run_list->runs()[0]->is_rtl);
- EXPECT_FALSE(run_list->runs()[1]->is_rtl);
- EXPECT_TRUE(run_list->runs()[2]->is_rtl);
- EXPECT_FALSE(run_list->runs()[3]->is_rtl);
-
- // The Latin letters should appear to the left of the other runs.
- EXPECT_EQ(3U, run_list->logical_to_visual(0));
- EXPECT_EQ(2U, run_list->logical_to_visual(1));
- EXPECT_EQ(1U, run_list->logical_to_visual(2));
- EXPECT_EQ(0U, run_list->logical_to_visual(3));
+ EXPECT_EQ("[8->10][7<-6][2->5][1<-0]", GetRunListStructureString());
}
TEST_P(RenderTextHarfBuzzTest, HarfBuzz_BreakRunsByUnicodeBlocks) {
@@ -3670,23 +3719,13 @@ TEST_P(RenderTextHarfBuzzTest, HarfBuzz_BreakRunsByUnicodeBlocks) {
// The '\x25B6' "play character" should break runs. http://crbug.com/278913
render_text->SetText(WideToUTF16(L"x\x25B6y"));
test_api()->EnsureLayout();
- internal::TextRunList* run_list = GetHarfBuzzRunList();
- EXPECT_EQ(ToString16Vec({"x", "▶", "y"}), GetRuns());
- ASSERT_EQ(3U, run_list->size());
- EXPECT_EQ(Range(0, 1), run_list->runs()[0]->range);
- EXPECT_EQ(Range(1, 2), run_list->runs()[1]->range);
- EXPECT_EQ(Range(2, 3), run_list->runs()[2]->range);
+ EXPECT_EQ(ToString16Vec({"x", "▶", "y"}), GetRunListStrings());
+ EXPECT_EQ("[0][1][2]", GetRunListStructureString());
render_text->SetText(WideToUTF16(L"x \x25B6 y"));
test_api()->EnsureLayout();
- run_list = GetHarfBuzzRunList();
- EXPECT_EQ(ToString16Vec({"x", " ", "▶", " ", "y"}), GetRuns());
- ASSERT_EQ(5U, run_list->size());
- EXPECT_EQ(Range(0, 1), run_list->runs()[0]->range);
- EXPECT_EQ(Range(1, 2), run_list->runs()[1]->range);
- EXPECT_EQ(Range(2, 3), run_list->runs()[2]->range);
- EXPECT_EQ(Range(3, 4), run_list->runs()[3]->range);
- EXPECT_EQ(Range(4, 5), run_list->runs()[4]->range);
+ EXPECT_EQ(ToString16Vec({"x", " ", "▶", " ", "y"}), GetRunListStrings());
+ EXPECT_EQ("[0][1][2][3][4]", GetRunListStructureString());
}
TEST_P(RenderTextHarfBuzzTest, HarfBuzz_BreakRunsByEmoji) {
@@ -3697,13 +3736,9 @@ TEST_P(RenderTextHarfBuzzTest, HarfBuzz_BreakRunsByEmoji) {
// separated. See crbug.com/448909
render_text->SetText(UTF8ToUTF16("x\xF0\x9F\x98\x81y\xE2\x9C\xA8"));
test_api()->EnsureLayout();
- internal::TextRunList* run_list = GetHarfBuzzRunList();
- ASSERT_EQ(4U, run_list->size());
- EXPECT_EQ(Range(0, 1), run_list->runs()[0]->range);
- // The length is 2 since U+1F601 is represented as a surrogate pair in UTF16.
- EXPECT_EQ(Range(1, 3), run_list->runs()[1]->range);
- EXPECT_EQ(Range(3, 4), run_list->runs()[2]->range);
- EXPECT_EQ(Range(4, 5), run_list->runs()[3]->range);
+ EXPECT_EQ(ToString16Vec({"x", "😁", "y", "✨"}), GetRunListStrings());
+ // U+1F601 is represented as a surrogate pair in UTF-16.
+ EXPECT_EQ("[0][1->2][3][4]", GetRunListStructureString());
}
TEST_P(RenderTextHarfBuzzTest, HarfBuzz_BreakRunsByAscii) {
@@ -3713,11 +3748,9 @@ TEST_P(RenderTextHarfBuzzTest, HarfBuzz_BreakRunsByAscii) {
// run from the ASCII period character.
render_text->SetText(UTF8ToUTF16("\xF0\x9F\x90\xB1."));
test_api()->EnsureLayout();
- internal::TextRunList* run_list = GetHarfBuzzRunList();
- ASSERT_EQ(2U, run_list->size());
- // U+1F431 is represented as a surrogate pair in UTF16.
- EXPECT_EQ(Range(0, 2), run_list->runs()[0]->range);
- EXPECT_EQ(Range(2, 3), run_list->runs()[1]->range);
+ EXPECT_EQ(ToString16Vec({"🐱", "."}), GetRunListStrings());
+ // U+1F431 is represented as a surrogate pair in UTF-16.
+ EXPECT_EQ("[0->1][2]", GetRunListStructureString());
}
TEST_P(RenderTextHarfBuzzTest, GlyphBounds) {
@@ -3740,7 +3773,7 @@ TEST_P(RenderTextHarfBuzzTest, HarfBuzz_NonExistentFont) {
RenderTextHarfBuzz* render_text = GetRenderTextHarfBuzz();
render_text->SetText(ASCIIToUTF16("test"));
test_api()->EnsureLayout();
- internal::TextRunList* run_list = GetHarfBuzzRunList();
+ const internal::TextRunList* run_list = GetHarfBuzzRunList();
ASSERT_EQ(1U, run_list->size());
internal::TextRunHarfBuzz* run = run_list->runs()[0].get();
ShapeRunWithFont(render_text->text(), Font("TheFontThatDoesntExist", 13),
@@ -3836,7 +3869,7 @@ TEST_P(RenderTextHarfBuzzTest, HarfBuzz_UniscribeFallback) {
// Korean character "han".
render_text->SetText(WideToUTF16(L"\xd55c"));
test_api()->EnsureLayout();
- internal::TextRunList* run_list = GetHarfBuzzRunList();
+ const internal::TextRunList* run_list = GetHarfBuzzRunList();
ASSERT_EQ(1U, run_list->size());
EXPECT_EQ(0U, run_list->runs()[0]->CountMissingGlyphs());
}
@@ -3855,7 +3888,7 @@ TEST_P(RenderTextHarfBuzzTest, HarfBuzz_UnicodeFallback) {
// Korean character "han".
render_text->SetText(WideToUTF16(L"\xd55c"));
test_api()->EnsureLayout();
- internal::TextRunList* run_list = GetHarfBuzzRunList();
+ const internal::TextRunList* run_list = GetHarfBuzzRunList();
ASSERT_EQ(1U, run_list->size());
EXPECT_EQ(0U, run_list->runs()[0]->CountMissingGlyphs());
}
@@ -3921,11 +3954,11 @@ TEST_P(RenderTextTest, TextDoesntClip) {
{
#if !defined(OS_CHROMEOS)
int top_test_height = kTestSize;
-#if defined(OS_WIN)
- // Windows 8+ draws 1 pixel above the display rect.
- if (base::win::GetVersion() >= base::win::VERSION_WIN8)
+ // Windows 8+ and RenderTextMac (since 10.13) draw 1 pixel above the
+ // display rect.
+ if (IsWin8Plus() || GetParam() == RENDER_TEXT_MAC)
top_test_height = kTestSize - 1;
-#endif // OS_WIN
+
// TODO(dschuyler): On ChromeOS text draws above the GetStringSize rect.
SCOPED_TRACE("TextDoesntClip Top Side");
rect_buffer.EnsureSolidRect(SK_ColorWHITE, 0, 0, kCanvasSize.width(),
@@ -3935,13 +3968,11 @@ TEST_P(RenderTextTest, TextDoesntClip) {
{
int bottom_test_y = kTestSize + string_size.height();
int bottom_test_height = kTestSize;
-#if defined(OS_WIN)
// Windows 8+ draws 1 pixel below the display rect.
- if (base::win::GetVersion() >= base::win::VERSION_WIN8) {
+ if (IsWin8Plus()) {
bottom_test_y = kTestSize + string_size.height() + 1;
bottom_test_height = kTestSize - 1;
}
-#endif // OS_WIN
SCOPED_TRACE("TextDoesntClip Bottom Side");
rect_buffer.EnsureSolidRect(SK_ColorWHITE, 0, bottom_test_y,
kCanvasSize.width(), bottom_test_height);
@@ -4094,19 +4125,22 @@ TEST_P(RenderTextTest, StylePropagated) {
render_text->SetFontList(font_list);
DrawVisualText();
- EXPECT_EQ(SkTypeface::kNormal, GetRendererPaint().getTypeface()->style());
+ EXPECT_EQ(SkFontStyle::Normal(),
+ GetRendererPaint().getTypeface()->fontStyle());
render_text->SetWeight(Font::Weight::BOLD);
DrawVisualText();
- EXPECT_EQ(SkTypeface::kBold, GetRendererPaint().getTypeface()->style());
+ EXPECT_EQ(SkFontStyle::Bold(), GetRendererPaint().getTypeface()->fontStyle());
render_text->SetStyle(TextStyle::ITALIC, true);
DrawVisualText();
- EXPECT_EQ(SkTypeface::kBoldItalic, GetRendererPaint().getTypeface()->style());
+ EXPECT_EQ(SkFontStyle::BoldItalic(),
+ GetRendererPaint().getTypeface()->fontStyle());
render_text->SetWeight(Font::Weight::NORMAL);
DrawVisualText();
- EXPECT_EQ(SkTypeface::kItalic, GetRendererPaint().getTypeface()->style());
+ EXPECT_EQ(SkFontStyle::Italic(),
+ GetRendererPaint().getTypeface()->fontStyle());
}
// Ensure the painter adheres to RenderText::subpixel_rendering_suppressed().
diff --git a/chromium/ui/gfx/sequential_id_generator.cc b/chromium/ui/gfx/sequential_id_generator.cc
index cdfc62c5b21..5a1fb1fcd00 100644
--- a/chromium/ui/gfx/sequential_id_generator.cc
+++ b/chromium/ui/gfx/sequential_id_generator.cc
@@ -48,6 +48,11 @@ bool SequentialIDGenerator::HasGeneratedIDFor(uint32_t number) const {
return number_to_id_.find(number) != number_to_id_.end();
}
+void SequentialIDGenerator::MaybeReleaseNumber(uint32_t number) {
+ if (HasGeneratedIDFor(number))
+ ReleaseNumber(number);
+}
+
void SequentialIDGenerator::ReleaseGeneratedID(uint32_t id) {
UpdateNextAvailableIDAfterRelease(id);
Remove(id, &id_to_number_, &number_to_id_);
diff --git a/chromium/ui/gfx/sequential_id_generator.h b/chromium/ui/gfx/sequential_id_generator.h
index 53c36859cd4..7e247d3c981 100644
--- a/chromium/ui/gfx/sequential_id_generator.h
+++ b/chromium/ui/gfx/sequential_id_generator.h
@@ -32,6 +32,9 @@ class GFX_EXPORT SequentialIDGenerator {
// |number|.
bool HasGeneratedIDFor(uint32_t number) const;
+ // Removes the ID previously generated for |number| if necessary.
+ void MaybeReleaseNumber(uint32_t number);
+
// Removes the generated ID |id| from the internal mapping. Since the ID is
// no longer mapped to any number, subsequent calls to |GetGeneratedID()| can
// use this ID.
diff --git a/chromium/ui/gfx/sequential_id_generator_unittest.cc b/chromium/ui/gfx/sequential_id_generator_unittest.cc
index ee0aac61bfa..c728f96927e 100644
--- a/chromium/ui/gfx/sequential_id_generator_unittest.cc
+++ b/chromium/ui/gfx/sequential_id_generator_unittest.cc
@@ -61,4 +61,14 @@ TEST(SequentialIDGeneratorTest, RemoveMultipleNumbers) {
EXPECT_EQ(4U, generator.GetGeneratedID(0));
}
+TEST(SequentialIDGeneratorTest, MaybeRemoveNumbers) {
+ const uint32_t kMinID = 0;
+ SequentialIDGenerator generator(kMinID);
+
+ EXPECT_EQ(0U, generator.GetGeneratedID(42));
+
+ generator.MaybeReleaseNumber(42);
+ EXPECT_FALSE(generator.HasGeneratedIDFor(42));
+ generator.MaybeReleaseNumber(42);
+}
} // namespace ui
diff --git a/chromium/ui/gfx/shadow_util.cc b/chromium/ui/gfx/shadow_util.cc
index cc1d7ad6042..10fc06b3185 100644
--- a/chromium/ui/gfx/shadow_util.cc
+++ b/chromium/ui/gfx/shadow_util.cc
@@ -8,6 +8,7 @@
#include <vector>
#include "base/lazy_instance.h"
+#include "base/memory/ptr_util.h"
#include "third_party/skia/include/core/SkDrawLooper.h"
#include "third_party/skia/include/core/SkRRect.h"
#include "ui/gfx/canvas.h"
@@ -95,7 +96,7 @@ const ShadowDetails& ShadowDetails::Get(int elevation, int corner_radius) {
ShadowDetails* shadow = &insertion.first->second;
shadow->values = ShadowValue::MakeMdShadowValues(elevation);
auto* source = new ShadowNineboxSource(shadow->values, corner_radius);
- shadow->ninebox_image = ImageSkia(source, source->size());
+ shadow->ninebox_image = ImageSkia(base::WrapUnique(source), source->size());
return *shadow;
}
diff --git a/chromium/ui/gfx/skia_color_space_util.cc b/chromium/ui/gfx/skia_color_space_util.cc
index 47f1da259d5..b840f7e62cc 100644
--- a/chromium/ui/gfx/skia_color_space_util.cc
+++ b/chromium/ui/gfx/skia_color_space_util.cc
@@ -14,94 +14,6 @@ namespace gfx {
namespace {
-// Evaluate the gradient of the linear component of fn
-void SkTransferFnEvalGradientLinear(const SkColorSpaceTransferFn& fn,
- float x,
- float* d_fn_d_fC_at_x,
- float* d_fn_d_fF_at_x) {
- *d_fn_d_fC_at_x = x;
- *d_fn_d_fF_at_x = 1.f;
-}
-
-// Solve for the parameters fC and fF, given the parameter fD.
-void SkTransferFnSolveLinear(SkColorSpaceTransferFn* fn,
- const float* x,
- const float* t,
- size_t n) {
- // If this has no linear segment, don't try to solve for one.
- if (fn->fD <= 0) {
- fn->fC = 1;
- fn->fF = 0;
- return;
- }
-
- // Let ne_lhs be the left hand side of the normal equations, and let ne_rhs
- // be the right hand side. This is a 4x4 matrix, but we will only update the
- // upper-left 2x2 sub-matrix.
- SkMatrix44 ne_lhs;
- SkVector4 ne_rhs;
- for (int row = 0; row < 2; ++row) {
- for (int col = 0; col < 2; ++col) {
- ne_lhs.set(row, col, 0);
- }
- }
- for (int row = 0; row < 4; ++row)
- ne_rhs.fData[row] = 0;
-
- // Add the contributions from each sample to the normal equations.
- float x_linear_max = 0;
- for (size_t i = 0; i < n; ++i) {
- // Ignore points in the nonlinear segment.
- if (x[i] >= fn->fD)
- continue;
- x_linear_max = std::max(x_linear_max, x[i]);
-
- // Let J be the gradient of fn with respect to parameters C and F, evaluated
- // at this point.
- float J[2];
- SkTransferFnEvalGradientLinear(*fn, x[i], &J[0], &J[1]);
-
- // Let r be the residual at this point.
- float r = t[i];
-
- // Update the normal equations left hand side with the outer product of J
- // with itself.
- for (int row = 0; row < 2; ++row) {
- for (int col = 0; col < 2; ++col) {
- ne_lhs.set(row, col, ne_lhs.get(row, col) + J[row] * J[col]);
- }
- // Update the normal equations right hand side the product of J with the
- // residual
- ne_rhs.fData[row] += J[row] * r;
- }
- }
-
- // If we only have a single x point at 0, that isn't enough to construct a
- // linear segment, so add an additional point connecting to the nonlinear
- // segment.
- if (x_linear_max == 0) {
- float J[2];
- SkTransferFnEvalGradientLinear(*fn, fn->fD, &J[0], &J[1]);
- float r = SkTransferFnEval(*fn, fn->fD);
- for (int row = 0; row < 2; ++row) {
- for (int col = 0; col < 2; ++col) {
- ne_lhs.set(row, col, ne_lhs.get(row, col) + J[row] * J[col]);
- }
- ne_rhs.fData[row] += J[row] * r;
- }
- }
-
- // Solve the normal equations.
- SkMatrix44 ne_lhs_inv;
- bool invert_result = ne_lhs.invert(&ne_lhs_inv);
- DCHECK(invert_result);
- SkVector4 solution = ne_lhs_inv * ne_rhs;
-
- // Update the transfer function.
- fn->fC = solution.fData[0];
- fn->fF = solution.fData[1];
-}
-
// Evaluate the gradient of the nonlinear component of fn
void SkTransferFnEvalGradientNonlinear(const SkColorSpaceTransferFn& fn,
float x,
@@ -282,9 +194,10 @@ bool SkApproximateTransferFnInternal(const float* x,
size_t n,
SkColorSpaceTransferFn* fn) {
// First, guess at a value of fD. Assume that the nonlinear segment applies
- // to all x >= 0.25. This is generally a safe assumption (fD is usually less
+ // to all x >= 0.15. This is generally a safe assumption (fD is usually less
// than 0.1).
- fn->fD = 0.25f;
+ const float kLinearSegmentMaximum = 0.15f;
+ fn->fD = kLinearSegmentMaximum;
// Do a nonlinear regression on the nonlinear segment. Use a number of guesses
// for the initial value of fG, because not all values will converge.
@@ -322,21 +235,32 @@ bool SkApproximateTransferFnInternal(const float* x,
}
// Now find the maximum x value where this nonlinear fit is no longer
- // accurate or no longer defined.
+ // accurate, no longer defined, or no longer nonnegative.
fn->fD = 0.f;
float max_x_where_nonlinear_does_not_fit = -1.f;
for (size_t i = 0; i < n; ++i) {
+ if (x[i] >= kLinearSegmentMaximum)
+ continue;
+
+ // The nonlinear segment is only undefined when fA * x + fB is
+ // nonnegative.
+ float fn_at_xi = -1;
+ if (fn->fA * x[i] + fn->fB >= 0)
+ fn_at_xi = SkTransferFnEvalUnclamped(*fn, x[i]);
+
+ // If the value is negative (or undefined), say that the fit was bad.
bool nonlinear_fits_xi = true;
- if (fn->fA * x[i] + fn->fB < 0) {
- // The nonlinear segment is undefined when fA * x + fB is less than 0.
+ if (fn_at_xi < 0)
nonlinear_fits_xi = false;
- } else {
- // Define "no longer accurate" as "has more than 10% more error than
- // the maximum error in the fit segment".
- float error_at_xi = std::abs(t[i] - SkTransferFnEval(*fn, x[i]));
+
+ // Compute the error, and define "no longer accurate" as "has more than
+ // 10% more error than the maximum error in the fit segment".
+ if (nonlinear_fits_xi) {
+ float error_at_xi = std::abs(t[i] - fn_at_xi);
if (error_at_xi > 1.1f * max_error_in_nonlinear_fit)
nonlinear_fits_xi = false;
}
+
if (!nonlinear_fits_xi) {
max_x_where_nonlinear_does_not_fit =
std::max(max_x_where_nonlinear_does_not_fit, x[i]);
@@ -353,7 +277,17 @@ bool SkApproximateTransferFnInternal(const float* x,
}
// Compute the linear segment, now that we have our definitive fD.
- SkTransferFnSolveLinear(fn, x, t, n);
+ if (fn->fD <= 0) {
+ // If this has no linear segment, don't try to solve for one.
+ fn->fC = 1;
+ fn->fF = 0;
+ } else {
+ // Set the linear portion such that it go through the origin and be
+ // continuous with the nonlinear segment.
+ float fn_at_fD = SkTransferFnEval(*fn, fn->fD);
+ fn->fC = fn_at_fD / fn->fD;
+ fn->fF = 0;
+ }
return true;
}
diff --git a/chromium/ui/gfx/skia_paint_util.cc b/chromium/ui/gfx/skia_paint_util.cc
index c18fbd1002e..2f3e2957232 100644
--- a/chromium/ui/gfx/skia_paint_util.cc
+++ b/chromium/ui/gfx/skia_paint_util.cc
@@ -5,6 +5,7 @@
#include "ui/gfx/skia_paint_util.h"
#include "base/memory/ptr_util.h"
+#include "cc/paint/paint_image_builder.h"
#include "third_party/skia/include/core/SkColorFilter.h"
#include "third_party/skia/include/effects/SkBlurMaskFilter.h"
#include "third_party/skia/include/effects/SkGradientShader.h"
@@ -38,8 +39,11 @@ sk_sp<cc::PaintShader> CreateImageRepShaderForScale(
shader_scale.setScaleY(local_matrix.getScaleY() / scale);
return cc::PaintShader::MakeImage(
- SkImage::MakeFromBitmap(image_rep.sk_bitmap()), tile_mode, tile_mode,
- &shader_scale);
+ cc::PaintImageBuilder()
+ .set_id(cc::PaintImage::kNonLazyStableId)
+ .set_image(SkImage::MakeFromBitmap(image_rep.sk_bitmap()))
+ .TakePaintImage(),
+ tile_mode, tile_mode, &shader_scale);
}
sk_sp<cc::PaintShader> CreateGradientShader(int start_point,
diff --git a/chromium/ui/gfx/vector_icon_types.h b/chromium/ui/gfx/vector_icon_types.h
index facc054f7eb..cb6f36d7e9e 100644
--- a/chromium/ui/gfx/vector_icon_types.h
+++ b/chromium/ui/gfx/vector_icon_types.h
@@ -21,6 +21,8 @@ const int kReferenceSizeDip = 48;
enum CommandType {
// A new <path> element. For the first path, this is assumed.
NEW_PATH,
+ // Sets the alpha for the current path.
+ PATH_COLOR_ALPHA,
// Sets the color for the current path.
PATH_COLOR_ARGB,
// Sets the path to clear mode (Skia's kClear_Mode).
diff --git a/chromium/ui/gl/BUILD.gn b/chromium/ui/gl/BUILD.gn
index e2dac179caf..760c94378f2 100644
--- a/chromium/ui/gl/BUILD.gn
+++ b/chromium/ui/gl/BUILD.gn
@@ -45,8 +45,6 @@ component("gl") {
output_name = "gl_wrapper" # Avoid colliding with OS X"s libGL.dylib.
sources = [
- "android/gl_jni_registrar.cc",
- "android/gl_jni_registrar.h",
"android/scoped_java_surface.cc",
"android/scoped_java_surface.h",
"android/surface_texture.cc",
@@ -57,6 +55,8 @@ component("gl") {
"ca_renderer_layer_params.h",
"dc_renderer_layer_params.cc",
"dc_renderer_layer_params.h",
+ "extension_set.cc",
+ "extension_set.h",
"gl_bindings.cc",
"gl_bindings.h",
"gl_bindings_autogen_gl.cc",
@@ -262,6 +262,7 @@ component("gl") {
"//third_party/angle:libEGL",
"//third_party/angle:libGLESv2",
"//third_party/mesa:osmesa",
+ "//third_party/swiftshader",
]
deps += [ "//third_party/angle:includes" ]
@@ -375,7 +376,11 @@ source_set("run_all_unittests") {
]
if (use_ozone) {
- deps += [ "//ui/ozone" ]
+ deps += [
+ "//mojo/edk/system",
+ "//services/service_manager/public/cpp/test:test_support",
+ "//ui/ozone",
+ ]
}
}
diff --git a/chromium/ui/gl/android/scoped_java_surface.cc b/chromium/ui/gl/android/scoped_java_surface.cc
index 1f0501bd687..bbe2d396891 100644
--- a/chromium/ui/gl/android/scoped_java_surface.cc
+++ b/chromium/ui/gl/android/scoped_java_surface.cc
@@ -20,7 +20,7 @@ ScopedJavaSurface::ScopedJavaSurface(
: auto_release_(true),
is_protected_(false) {
JNIEnv* env = base::android::AttachCurrentThread();
- DCHECK(env->IsInstanceOf(surface.obj(), Surface_clazz(env)));
+ DCHECK(env->IsInstanceOf(surface.obj(), android_view_Surface_clazz(env)));
j_surface_.Reset(surface);
}
diff --git a/chromium/ui/gl/android/surface_texture_listener.cc b/chromium/ui/gl/android/surface_texture_listener.cc
index 5b2c713aeae..091facced5e 100644
--- a/chromium/ui/gl/android/surface_texture_listener.cc
+++ b/chromium/ui/gl/android/surface_texture_listener.cc
@@ -38,9 +38,4 @@ void SurfaceTextureListener::FrameAvailable(JNIEnv* env,
}
}
-// static
-bool SurfaceTextureListener::RegisterSurfaceTextureListener(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
} // namespace gl
diff --git a/chromium/ui/gl/android/surface_texture_listener.h b/chromium/ui/gl/android/surface_texture_listener.h
index 6e2080daf35..d0221858778 100644
--- a/chromium/ui/gl/android/surface_texture_listener.h
+++ b/chromium/ui/gl/android/surface_texture_listener.h
@@ -30,8 +30,6 @@ class GL_EXPORT SurfaceTextureListener {
void FrameAvailable(JNIEnv* env,
const base::android::JavaParamRef<jobject>& obj);
- static bool RegisterSurfaceTextureListener(JNIEnv* env);
-
private:
friend class base::DeleteHelper<SurfaceTextureListener>;
diff --git a/chromium/ui/gl/angle_platform_impl.cc b/chromium/ui/gl/angle_platform_impl.cc
index 1363fb97b4e..3e6f4903b6e 100644
--- a/chromium/ui/gl/angle_platform_impl.cc
+++ b/chromium/ui/gl/angle_platform_impl.cc
@@ -4,45 +4,55 @@
#include "ui/gl/angle_platform_impl.h"
+#include "base/base64.h"
+#include "base/callback.h"
+#include "base/lazy_instance.h"
#include "base/metrics/histogram.h"
#include "base/metrics/histogram_macros.h"
#include "base/trace_event/trace_event.h"
#include "third_party/angle/include/platform/Platform.h"
#include "ui/gl/gl_bindings.h"
-namespace gl {
+namespace angle {
namespace {
-angle::ResetDisplayPlatformFunc g_angle_reset_platform = nullptr;
+// This platform context stores user data accessible inside the impl methods.
+struct PlatformContext {
+ CacheProgramCallback cache_program_callback;
+};
-double ANGLEPlatformImpl_currentTime(angle::PlatformMethods* platform) {
+base::LazyInstance<PlatformContext>::DestructorAtExit g_platform_context =
+ LAZY_INSTANCE_INITIALIZER;
+ResetDisplayPlatformFunc g_angle_reset_platform = nullptr;
+
+double ANGLEPlatformImpl_currentTime(PlatformMethods* platform) {
return base::Time::Now().ToDoubleT();
}
double ANGLEPlatformImpl_monotonicallyIncreasingTime(
- angle::PlatformMethods* platform) {
+ PlatformMethods* platform) {
return (base::TimeTicks::Now() - base::TimeTicks()).InSecondsF();
}
const unsigned char* ANGLEPlatformImpl_getTraceCategoryEnabledFlag(
- angle::PlatformMethods* platform,
+ PlatformMethods* platform,
const char* category_group) {
return TRACE_EVENT_API_GET_CATEGORY_GROUP_ENABLED(category_group);
}
-void ANGLEPlatformImpl_logError(angle::PlatformMethods* platform,
+void ANGLEPlatformImpl_logError(PlatformMethods* platform,
const char* errorMessage) {
LOG(ERROR) << errorMessage;
}
-void ANGLEPlatformImpl_logWarning(angle::PlatformMethods* platform,
+void ANGLEPlatformImpl_logWarning(PlatformMethods* platform,
const char* warningMessage) {
LOG(WARNING) << warningMessage;
}
-angle::TraceEventHandle ANGLEPlatformImpl_addTraceEvent(
- angle::PlatformMethods* platform,
+TraceEventHandle ANGLEPlatformImpl_addTraceEvent(
+ PlatformMethods* platform,
char phase,
const unsigned char* category_group_enabled,
const char* name,
@@ -61,23 +71,23 @@ angle::TraceEventHandle ANGLEPlatformImpl_addTraceEvent(
trace_event_internal::kGlobalScope, id, trace_event_internal::kNoId,
base::PlatformThread::CurrentId(), timestamp_tt, num_args, arg_names,
arg_types, arg_values, nullptr, flags);
- angle::TraceEventHandle result;
+ TraceEventHandle result;
memcpy(&result, &handle, sizeof(result));
return result;
}
void ANGLEPlatformImpl_updateTraceEventDuration(
- angle::PlatformMethods* platform,
+ PlatformMethods* platform,
const unsigned char* category_group_enabled,
const char* name,
- angle::TraceEventHandle handle) {
+ TraceEventHandle handle) {
base::trace_event::TraceEventHandle trace_event_handle;
memcpy(&trace_event_handle, &handle, sizeof(handle));
TRACE_EVENT_API_UPDATE_TRACE_EVENT_DURATION(category_group_enabled, name,
trace_event_handle);
}
-void ANGLEPlatformImpl_histogramCustomCounts(angle::PlatformMethods* platform,
+void ANGLEPlatformImpl_histogramCustomCounts(PlatformMethods* platform,
const char* name,
int sample,
int min,
@@ -92,7 +102,7 @@ void ANGLEPlatformImpl_histogramCustomCounts(angle::PlatformMethods* platform,
counter->Add(sample);
}
-void ANGLEPlatformImpl_histogramEnumeration(angle::PlatformMethods* platform,
+void ANGLEPlatformImpl_histogramEnumeration(PlatformMethods* platform,
const char* name,
int sample,
int boundary_value) {
@@ -105,7 +115,7 @@ void ANGLEPlatformImpl_histogramEnumeration(angle::PlatformMethods* platform,
counter->Add(sample);
}
-void ANGLEPlatformImpl_histogramSparse(angle::PlatformMethods* platform,
+void ANGLEPlatformImpl_histogramSparse(PlatformMethods* platform,
const char* name,
int sample) {
// For sparse histograms, we can use the macro, as it does not incorporate a
@@ -113,30 +123,49 @@ void ANGLEPlatformImpl_histogramSparse(angle::PlatformMethods* platform,
UMA_HISTOGRAM_SPARSE_SLOWLY(name, sample);
}
-void ANGLEPlatformImpl_histogramBoolean(angle::PlatformMethods* platform,
+void ANGLEPlatformImpl_histogramBoolean(PlatformMethods* platform,
const char* name,
bool sample) {
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 InitializeANGLEPlatform(EGLDisplay display) {
- angle::GetDisplayPlatformFunc angle_get_platform =
- reinterpret_cast<angle::GetDisplayPlatformFunc>(
+bool InitializePlatform(EGLDisplay display) {
+ GetDisplayPlatformFunc angle_get_platform =
+ reinterpret_cast<GetDisplayPlatformFunc>(
eglGetProcAddress("ANGLEGetDisplayPlatform"));
if (!angle_get_platform)
return false;
// Save the pointer to the destroy function here to avoid crash.
- g_angle_reset_platform = reinterpret_cast<angle::ResetDisplayPlatformFunc>(
+ g_angle_reset_platform = reinterpret_cast<ResetDisplayPlatformFunc>(
eglGetProcAddress("ANGLEResetDisplayPlatform"));
- angle::PlatformMethods* platformMethods = nullptr;
- if (!angle_get_platform(static_cast<angle::EGLDisplayType>(display),
- angle::g_PlatformMethodNames,
- angle::g_NumPlatformMethods, nullptr,
- &platformMethods))
+ PlatformMethods* platformMethods = nullptr;
+ if (!angle_get_platform(static_cast<EGLDisplayType>(display),
+ g_PlatformMethodNames, g_NumPlatformMethods,
+ &g_platform_context.Get(), &platformMethods))
return false;
platformMethods->currentTime = ANGLEPlatformImpl_currentTime;
platformMethods->addTraceEvent = ANGLEPlatformImpl_addTraceEvent;
@@ -155,13 +184,23 @@ bool InitializeANGLEPlatform(EGLDisplay display) {
ANGLEPlatformImpl_monotonicallyIncreasingTime;
platformMethods->updateTraceEventDuration =
ANGLEPlatformImpl_updateTraceEventDuration;
+ platformMethods->cacheProgram = ANGLEPlatformImpl_cacheProgram;
return true;
}
-void ResetANGLEPlatform(EGLDisplay display) {
+void ResetPlatform(EGLDisplay display) {
if (!g_angle_reset_platform)
return;
- g_angle_reset_platform(static_cast<angle::EGLDisplayType>(display));
+ g_angle_reset_platform(static_cast<EGLDisplayType>(display));
+ ResetCacheProgramCallback();
+}
+
+void SetCacheProgramCallback(CacheProgramCallback callback) {
+ g_platform_context.Get().cache_program_callback = callback;
+}
+
+void ResetCacheProgramCallback() {
+ g_platform_context.Get().cache_program_callback.Reset();
}
-} // namespace gl
+} // namespace angle
diff --git a/chromium/ui/gl/angle_platform_impl.h b/chromium/ui/gl/angle_platform_impl.h
index 38c93ab678a..927850cc7f0 100644
--- a/chromium/ui/gl/angle_platform_impl.h
+++ b/chromium/ui/gl/angle_platform_impl.h
@@ -8,13 +8,20 @@
// Implements the ANGLE platform interface, for functionality like
// histograms and trace profiling.
+#include "base/callback_forward.h"
#include "ui/gl/gl_context_egl.h"
+#include "ui/gl/gl_export.h"
-namespace gl {
+namespace angle {
-bool InitializeANGLEPlatform(EGLDisplay display);
-void ResetANGLEPlatform(EGLDisplay display);
+GL_EXPORT bool InitializePlatform(EGLDisplay display);
+GL_EXPORT void ResetPlatform(EGLDisplay display);
-} // namespace gl
+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_api_unittest.cc b/chromium/ui/gl/egl_api_unittest.cc
index 772cf0646a1..1d8babc927b 100644
--- a/chromium/ui/gl/egl_api_unittest.cc
+++ b/chromium/ui/gl/egl_api_unittest.cc
@@ -4,7 +4,6 @@
#include <memory>
-#include "base/command_line.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/gl_egl_api_implementation.h"
#include "ui/gl/gl_surface_egl.h"
@@ -26,6 +25,8 @@ class EGLApiTest : public testing::Test {
g_driver_egl.fn.eglGetDisplayFn = &FakeGetDisplay;
g_driver_egl.fn.eglGetErrorFn = &FakeGetError;
g_driver_egl.fn.eglGetProcAddressFn = &FakeGetProcAddress;
+
+ SetGLImplementation(kGLImplementationEGLGLES2);
}
void TearDown() override {
@@ -37,13 +38,13 @@ class EGLApiTest : public testing::Test {
fake_extension_string_ = "";
}
- void InitializeAPI(base::CommandLine* command_line) {
+ void InitializeAPI(const char* disabled_extensions) {
api_.reset(new RealEGLApi());
g_current_egl_context = api_.get();
- if (command_line)
- api_->InitializeWithCommandLine(&g_driver_egl, command_line);
- else
- api_->Initialize(&g_driver_egl);
+ api_->Initialize(&g_driver_egl);
+ if (disabled_extensions) {
+ SetDisabledExtensionsEGL(disabled_extensions);
+ }
g_driver_egl.InitializeClientExtensionBindings();
GLSurfaceEGL::InitializeDisplay(EGL_DEFAULT_DISPLAY);
g_driver_egl.InitializeExtensionBindings();
@@ -114,23 +115,21 @@ TEST_F(EGLApiTest, DisabledExtensionBitTest) {
EXPECT_TRUE(g_driver_egl.ext.b_EGL_KHR_fence_sync);
- base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
- command_line.AppendSwitchASCII(switches::kDisableGLExtensions,
- kFakeDisabledExtensions);
- InitializeAPI(&command_line);
+ InitializeAPI(kFakeDisabledExtensions);
EXPECT_FALSE(g_driver_egl.ext.b_EGL_KHR_fence_sync);
}
TEST_F(EGLApiTest, DisabledExtensionStringTest) {
- static const char* kFakeExtensions = "EGL_EXT_1 EGL_EXT_2"
- " EGL_EXT_3 EGL_EXT_4";
+ static const char* kFakeExtensions =
+ "EGL_EXT_1 EGL_KHR_fence_sync EGL_EXT_3 EGL_KHR_wait_sync";
static const char* kFakeClientExtensions =
"EGL_CLIENT_EXT_1 EGL_CLIENT_EXT_2";
static const char* kFakeDisabledExtensions =
- "EGL_EXT_1,EGL_EXT_2,EGL_FAKE,EGL_CLIENT_EXT_1";
- static const char* kFilteredExtensions = "EGL_EXT_3 EGL_EXT_4";
- static const char* kFilteredClientExtensions = "EGL_CLIENT_EXT_2";
+ "EGL_KHR_fence_sync,EGL_KHR_wait_sync";
+ static const char* kFilteredExtensions = "EGL_EXT_1 EGL_EXT_3";
+ static const char* kFilteredClientExtensions =
+ "EGL_CLIENT_EXT_1 EGL_CLIENT_EXT_2";
SetFakeExtensionString(kFakeExtensions, kFakeClientExtensions);
InitializeAPI(nullptr);
@@ -138,10 +137,7 @@ TEST_F(EGLApiTest, DisabledExtensionStringTest) {
EXPECT_STREQ(kFakeClientExtensions, GetExtensions().first);
EXPECT_STREQ(kFakeExtensions, GetExtensions().second);
- base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
- command_line.AppendSwitchASCII(switches::kDisableGLExtensions,
- kFakeDisabledExtensions);
- InitializeAPI(&command_line);
+ InitializeAPI(kFakeDisabledExtensions);
EXPECT_STREQ(kFilteredClientExtensions, GetExtensions().first);
EXPECT_STREQ(kFilteredExtensions, GetExtensions().second);
diff --git a/chromium/ui/gl/extension_set.cc b/chromium/ui/gl/extension_set.cc
new file mode 100644
index 00000000000..f1b0154e37b
--- /dev/null
+++ b/chromium/ui/gl/extension_set.cc
@@ -0,0 +1,20 @@
+// 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/gl/extension_set.h"
+#include "base/strings/string_split.h"
+
+namespace gl {
+
+ExtensionSet MakeExtensionSet(const base::StringPiece& extensions_string) {
+ return ExtensionSet(SplitStringPiece(
+ extensions_string, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL));
+}
+
+bool HasExtension(const ExtensionSet& extension_set,
+ const base::StringPiece& extension) {
+ return extension_set.find(extension) != extension_set.end();
+}
+
+} // namespace gl
diff --git a/chromium/ui/gl/extension_set.h b/chromium/ui/gl/extension_set.h
new file mode 100644
index 00000000000..e8d36227c1a
--- /dev/null
+++ b/chromium/ui/gl/extension_set.h
@@ -0,0 +1,30 @@
+// 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_GL_EXTENSION_SET_H_
+#define UI_GL_EXTENSION_SET_H_
+
+#include "base/containers/flat_set.h"
+#include "base/strings/string_piece.h"
+#include "ui/gl/gl_export.h"
+
+namespace gl {
+
+using ExtensionSet = base::flat_set<base::StringPiece>;
+
+GL_EXPORT ExtensionSet
+MakeExtensionSet(const base::StringPiece& extensions_string);
+
+GL_EXPORT bool HasExtension(const ExtensionSet& extension_set,
+ const base::StringPiece& extension);
+
+template <size_t N>
+inline bool HasExtension(const ExtensionSet& extension_set,
+ const char (&extension)[N]) {
+ return HasExtension(extension_set, base::StringPiece(extension, N - 1));
+}
+
+} // namespace gl
+
+#endif // UI_GL_EXTENSION_SET_H_
diff --git a/chromium/ui/gl/generate_bindings.py b/chromium/ui/gl/generate_bindings.py
index 5dbc228dbaa..7c20a09eb51 100755
--- a/chromium/ui/gl/generate_bindings.py
+++ b/chromium/ui/gl/generate_bindings.py
@@ -760,7 +760,8 @@ GL_FUNCTIONS = [
'arguments':
'GLenum pname, GLsizei bufSize, GLsizei* length, GLint* data', },
{ 'return_type': 'void',
- 'versions': [{ 'name': 'glGetInternalformativ' }],
+ 'versions': [{'name': 'glGetInternalformativ',
+ 'extensions': ['GL_ARB_internalformat_query']}],
'arguments': 'GLenum target, GLenum internalformat, GLenum pname, '
'GLsizei bufSize, GLint* params', },
{ 'return_type': 'void',
@@ -770,6 +771,10 @@ GL_FUNCTIONS = [
'GLenum target, GLenum internalformat, GLenum pname, GLsizei bufSize, '
'GLsizei* length, GLint* params', },
{ 'return_type': 'void',
+ 'versions': [{'name': 'glGetMultisamplefv',
+ 'extensions': ['GL_ARB_texture_multisample']}],
+ 'arguments': 'GLenum pname, GLuint index, GLfloat* val', },
+{ 'return_type': 'void',
'versions': [{'name': 'glGetMultisamplefvRobustANGLE',
'extensions': ['GL_ANGLE_robust_client_memory']}],
'arguments':
@@ -1273,6 +1278,9 @@ GL_FUNCTIONS = [
'names': ['glPointParameteri'],
'arguments': 'GLenum pname, GLint param', },
{ 'return_type': 'void',
+ 'names': ['glPolygonMode'],
+ 'arguments': 'GLenum face, GLenum mode', },
+{ 'return_type': 'void',
'names': ['glPolygonOffset'],
'arguments': 'GLfloat factor, GLfloat units', },
{ 'return_type': 'void',
@@ -1506,6 +1514,14 @@ GL_FUNCTIONS = [
'names': ['glTestFenceNV'],
'arguments': 'GLuint fence', },
{ 'return_type': 'void',
+ 'names': ['glTexBuffer', 'glTexBufferOES', 'glTexBufferEXT'],
+ 'arguments': 'GLenum target, GLenum internalformat, GLuint buffer', } ,
+{ 'return_type': 'void',
+ 'names': ['glTexBufferRange', 'glTexBufferRangeOES', 'glTexBufferRangeEXT'],
+ 'arguments':
+ 'GLenum target, GLenum internalformat, GLuint buffer, '
+ 'GLintptr offset, GLsizeiptr size', },
+{ 'return_type': 'void',
'names': ['glTexImage2D'],
'arguments':
'GLenum target, GLint level, GLint internalformat, GLsizei width, '
@@ -1757,7 +1773,7 @@ GL_FUNCTIONS = [
{ 'return_type': 'void',
'known_as': 'glVertexAttribDivisorANGLE',
'names': ['glVertexAttribDivisorARB', 'glVertexAttribDivisorANGLE',
- 'glVertexAttribDivisor'],
+ 'glVertexAttribDivisorEXT', 'glVertexAttribDivisor'],
'arguments':
'GLuint index, GLuint divisor', },
{ 'return_type': 'void',
@@ -1783,7 +1799,7 @@ GL_FUNCTIONS = [
{ 'return_type': 'void',
'names': ['glViewport'],
'arguments': 'GLint x, GLint y, GLsizei width, GLsizei height', },
-{ 'return_type': 'GLenum',
+{ 'return_type': 'void',
'versions': [{ 'name': 'glWaitSync',
'extensions': ['GL_ARB_sync'] }],
'arguments':
@@ -2438,6 +2454,8 @@ def GenerateHeader(file, functions, set_name,
#ifndef UI_GL_GL_BINDINGS_AUTOGEN_%(name)s_H_
#define UI_GL_GL_BINDINGS_AUTOGEN_%(name)s_H_
+#include <string>
+
namespace gl {
class GLContext;
@@ -2475,6 +2493,9 @@ class GLContext;
%(name)sApi();
virtual ~%(name)sApi();
+ virtual void SetDisabledExtensions(
+ const std::string& disabled_extensions) {}
+
""" % {'name': set_name.upper()})
for func in functions:
file.write(' virtual %s %sFn(%s) = 0;\n' %
@@ -2703,25 +2724,22 @@ namespace gl {
if set_name == 'gl':
file.write("""\
-void DriverGL::InitializeDynamicBindings(
- const GLVersionInfo* ver, const std::string& context_extensions) {
- std::string extensions = context_extensions + " ";
- ALLOW_UNUSED_LOCAL(extensions);
-
+void DriverGL::InitializeDynamicBindings(const GLVersionInfo* ver,
+ const ExtensionSet& extensions) {
""")
elif set_name == 'egl':
file.write("""\
void DriverEGL::InitializeClientExtensionBindings() {
std::string client_extensions(GetClientExtensions());
- client_extensions += " ";
- ALLOW_UNUSED_LOCAL(client_extensions);
+ ExtensionSet extensions(MakeExtensionSet(client_extensions));
+ ALLOW_UNUSED_LOCAL(extensions);
""")
else:
file.write("""\
void Driver%s::InitializeExtensionBindings() {
- std::string extensions(GetPlatformExtensions());
- extensions += " ";
+ std::string platform_extensions(GetPlatformExtensions());
+ ExtensionSet extensions(MakeExtensionSet(platform_extensions));
ALLOW_UNUSED_LOCAL(extensions);
""" % (set_name.upper(),))
@@ -2730,7 +2748,7 @@ void Driver%s::InitializeExtensionBindings() {
# Extra space at the end of the extension name is intentional,
# it is used as a separator
for extension in extensions:
- file.write(' ext.b_%s = %s.find("%s ") != std::string::npos;\n' %
+ file.write(' ext.b_%s = HasExtension(%s, "%s");\n' %
(extension, extension_var, extension))
for func in extension_funcs:
@@ -2739,7 +2757,7 @@ void Driver%s::InitializeExtensionBindings() {
WriteConditionalFuncBinding(file, func)
OutputExtensionBindings(
- 'client_extensions',
+ 'extensions',
sorted(used_client_extensions),
[ f for f in functions if IsClientExtensionFunc(f) ])
@@ -2748,8 +2766,8 @@ void Driver%s::InitializeExtensionBindings() {
}
void DriverEGL::InitializeExtensionBindings() {
- std::string extensions(GetPlatformExtensions());
- extensions += " ";
+ std::string platform_extensions(GetPlatformExtensions());
+ ExtensionSet extensions(MakeExtensionSet(platform_extensions));
ALLOW_UNUSED_LOCAL(extensions);
""")
@@ -3306,7 +3324,8 @@ def main(argv):
parser.add_option('--verify-order', action='store_true')
parser.add_option('--generate-dchecks', action='store_true',
help='Generates DCHECKs into the logging functions '
- 'asserting no GL errors (useful for debugging)')
+ 'asserting no GL errors (useful for debugging with '
+ '--enable-gpu-service-logging)')
parser.add_option('--validate-bindings', action='store_true',
help='Generate DCHECKs to validate function bindings '
' were correctly supplied (useful for debugging)')
diff --git a/chromium/ui/gl/gl_angle_util_win.cc b/chromium/ui/gl/gl_angle_util_win.cc
index 45e37ab423b..291ba107eee 100644
--- a/chromium/ui/gl/gl_angle_util_win.cc
+++ b/chromium/ui/gl/gl_angle_util_win.cc
@@ -101,7 +101,7 @@ base::win::ScopedComPtr<IDCompositionDevice2> QueryDirectCompositionDevice(
UINT data_size = sizeof(dcomp_device.Get());
HRESULT hr = d3d11_device->GetPrivateData(kDirectCompositionGUID, &data_size,
- &dcomp_device);
+ dcomp_device.GetAddressOf());
if (SUCCEEDED(hr) && dcomp_device)
return dcomp_device;
diff --git a/chromium/ui/gl/gl_api_unittest.cc b/chromium/ui/gl/gl_api_unittest.cc
index f0185c670e1..b57f54f2355 100644
--- a/chromium/ui/gl/gl_api_unittest.cc
+++ b/chromium/ui/gl/gl_api_unittest.cc
@@ -46,23 +46,28 @@ class GLApiTest : public testing::Test {
fake_extension_strings_ = nullptr;
}
- void InitializeAPI(base::CommandLine* command_line) {
+ void InitializeAPI(const char* disabled_extensions) {
driver_.reset(new DriverGL());
driver_->fn.glGetStringFn = &FakeGetString;
driver_->fn.glGetStringiFn = &FakeGetStringi;
driver_->fn.glGetIntegervFn = &FakeGetIntegervFn;
api_.reset(new RealGLApi());
- if (command_line)
- api_->InitializeWithCommandLine(driver_.get(), command_line);
- else
- api_->Initialize(driver_.get());
-
- api_->InitializeFilteredExtensions();
- std::unique_ptr<GLVersionInfo> version =
- GetVersionInfoFromContext(api_.get());
- driver_->InitializeDynamicBindings(
- version.get(), GetGLExtensionsFromCurrentContext(api_.get()));
+ if (disabled_extensions) {
+ api_->SetDisabledExtensions(disabled_extensions);
+ }
+ api_->Initialize(driver_.get());
+
+ std::string extensions_string =
+ GetGLExtensionsFromCurrentContext(api_.get());
+ ExtensionSet extension_set = MakeExtensionSet(extensions_string);
+
+ auto version = std::make_unique<GLVersionInfo>(
+ reinterpret_cast<const char*>(api_->glGetStringFn(GL_VERSION)),
+ reinterpret_cast<const char*>(api_->glGetStringFn(GL_RENDERER)),
+ extension_set);
+
+ driver_->InitializeDynamicBindings(version.get(), extension_set);
api_->set_version(std::move(version));
}
@@ -135,14 +140,9 @@ TEST_F(GLApiTest, DisabledExtensionStringTest) {
SetFakeExtensionString(kFakeExtensions);
InitializeAPI(nullptr);
-
EXPECT_STREQ(kFakeExtensions, GetExtensions());
- base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
- command_line.AppendSwitchASCII(switches::kDisableGLExtensions,
- kFakeDisabledExtensions);
- InitializeAPI(&command_line);
-
+ InitializeAPI(kFakeDisabledExtensions);
EXPECT_STREQ(kFilteredExtensions, GetExtensions());
}
@@ -154,14 +154,9 @@ TEST_F(GLApiTest, DisabledExtensionBitTest) {
SetFakeExtensionStrings(kFakeExtensions, arraysize(kFakeExtensions));
InitializeAPI(nullptr);
-
EXPECT_TRUE(driver_->ext.b_GL_ARB_timer_query);
- base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
- command_line.AppendSwitchASCII(switches::kDisableGLExtensions,
- kFakeDisabledExtensions);
- InitializeAPI(&command_line);
-
+ InitializeAPI(kFakeDisabledExtensions);
EXPECT_FALSE(driver_->ext.b_GL_ARB_timer_query);
}
@@ -186,11 +181,7 @@ TEST_F(GLApiTest, DisabledExtensionStringIndexTest) {
EXPECT_STREQ(kFakeExtensions[i], GetExtensioni(i));
}
- base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
- command_line.AppendSwitchASCII(switches::kDisableGLExtensions,
- kFakeDisabledExtensions);
- InitializeAPI(&command_line);
-
+ InitializeAPI(kFakeDisabledExtensions);
EXPECT_EQ(arraysize(kFilteredExtensions), GetNumExtensions());
for (uint32_t i = 0; i < arraysize(kFilteredExtensions); ++i) {
EXPECT_STREQ(kFilteredExtensions[i], GetExtensioni(i));
diff --git a/chromium/ui/gl/gl_bindings.cc b/chromium/ui/gl/gl_bindings.cc
index 9e7bcfea0d6..05c45495fa0 100644
--- a/chromium/ui/gl/gl_bindings.cc
+++ b/chromium/ui/gl/gl_bindings.cc
@@ -47,6 +47,27 @@ std::string DriverEGL::GetPlatformExtensions() {
return str ? std::string(str) : "";
}
+void DriverEGL::UpdateConditionalExtensionBindings() {
+ // For the moment, only two extensions can be conditionally disabled
+ // through GPU driver bug workarounds mechanism:
+ // EGL_KHR_fence_sync
+ // EGL_KHR_wait_sync
+
+ // In theory it's OK to allow disabling other EGL extensions, as far as they
+ // are not the ones used in GLSurfaceEGL::InitializeOneOff().
+
+ std::string extensions(GetPlatformExtensions());
+ extensions += " ";
+
+ ext.b_EGL_KHR_fence_sync =
+ extensions.find("EGL_KHR_fence_sync ") != std::string::npos;
+ ext.b_EGL_KHR_wait_sync =
+ extensions.find("EGL_KHR_wait_sync ") != std::string::npos;
+ if (!ext.b_EGL_KHR_wait_sync) {
+ fn.eglWaitSyncKHRFn = nullptr;
+ }
+}
+
// static
std::string DriverEGL::GetClientExtensions() {
const char* str = eglQueryString(EGL_NO_DISPLAY, EGL_EXTENSIONS);
diff --git a/chromium/ui/gl/gl_bindings.h b/chromium/ui/gl/gl_bindings.h
index f0e7f583c31..df7895eed20 100644
--- a/chromium/ui/gl/gl_bindings.h
+++ b/chromium/ui/gl/gl_bindings.h
@@ -29,6 +29,7 @@
#include "base/logging.h"
#include "base/threading/thread_local.h"
#include "build/build_config.h"
+#include "ui/gl/extension_set.h"
#include "ui/gl/gl_export.h"
// The standard OpenGL native extension headers are also included.
@@ -163,6 +164,15 @@
#define GL_SUBSCRIBED_VALUES_BUFFER_CHROMIUM 0x924B
#define GL_MOUSE_POSITION_CHROMIUM 0x924C
+// GL_CHROMIUM_texture_filtering_hint
+#define GL_TEXTURE_FILTERING_HINT_CHROMIUM 0x8AF0
+
+// GL_CHROMIUM_resize
+#define GL_COLOR_SPACE_UNSPECIFIED_CHROMIUM 0x8AF1
+#define GL_COLOR_SPACE_SCRGB_LINEAR_CHROMIUM 0x8AF2
+#define GL_COLOR_SPACE_SRGB_CHROMIUM 0x8AF3
+#define GL_COLOR_SPACE_DISPLAY_P3_CHROMIUM 0x8AF4
+
// GL_OES_texure_3D
#define GL_SAMPLER_3D_OES 0x8B5F
@@ -415,7 +425,7 @@ struct GLVersionInfo;
struct GL_EXPORT DriverGL {
void InitializeStaticBindings();
void InitializeDynamicBindings(const GLVersionInfo* ver,
- const std::string& context_extensions);
+ const ExtensionSet& extensions);
void ClearBindings();
ProcsGL fn;
@@ -460,6 +470,7 @@ struct GL_EXPORT DriverEGL {
void InitializeClientExtensionBindings();
void InitializeExtensionBindings();
void ClearBindings();
+ void UpdateConditionalExtensionBindings();
ProcsEGL fn;
ExtensionsEGL ext;
diff --git a/chromium/ui/gl/gl_bindings_api_autogen_gl.h b/chromium/ui/gl/gl_bindings_api_autogen_gl.h
index 5403786bb53..1df021c8718 100644
--- a/chromium/ui/gl/gl_bindings_api_autogen_gl.h
+++ b/chromium/ui/gl/gl_bindings_api_autogen_gl.h
@@ -528,6 +528,7 @@ void glGetInternalformativRobustANGLEFn(GLenum target,
GLsizei bufSize,
GLsizei* length,
GLint* params) override;
+void glGetMultisamplefvFn(GLenum pname, GLuint index, GLfloat* val) override;
void glGetMultisamplefvRobustANGLEFn(GLenum pname,
GLuint index,
GLsizei bufSize,
@@ -861,6 +862,7 @@ void glPathStencilFuncNVFn(GLenum func, GLint ref, GLuint mask) override;
void glPauseTransformFeedbackFn(void) override;
void glPixelStoreiFn(GLenum pname, GLint param) override;
void glPointParameteriFn(GLenum pname, GLint param) override;
+void glPolygonModeFn(GLenum face, GLenum mode) override;
void glPolygonOffsetFn(GLfloat factor, GLfloat units) override;
void glPopDebugGroupFn() override;
void glPopGroupMarkerEXTFn(void) override;
@@ -1039,6 +1041,14 @@ void glStencilThenCoverStrokePathNVFn(GLuint path,
GLenum coverMode) override;
GLboolean glTestFenceAPPLEFn(GLuint fence) override;
GLboolean glTestFenceNVFn(GLuint fence) override;
+void glTexBufferFn(GLenum target,
+ GLenum internalformat,
+ GLuint buffer) override;
+void glTexBufferRangeFn(GLenum target,
+ GLenum internalformat,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size) override;
void glTexImage2DFn(GLenum target,
GLint level,
GLint internalformat,
@@ -1271,4 +1281,4 @@ void glVertexAttribPointerFn(GLuint indx,
GLsizei stride,
const void* ptr) override;
void glViewportFn(GLint x, GLint y, GLsizei width, GLsizei height) override;
-GLenum glWaitSyncFn(GLsync sync, GLbitfield flags, GLuint64 timeout) override;
+void glWaitSyncFn(GLsync sync, GLbitfield flags, GLuint64 timeout) override;
diff --git a/chromium/ui/gl/gl_bindings_autogen_egl.cc b/chromium/ui/gl/gl_bindings_autogen_egl.cc
index 637996d7ec3..52c8aafc841 100644
--- a/chromium/ui/gl/gl_bindings_autogen_egl.cc
+++ b/chromium/ui/gl/gl_bindings_autogen_egl.cc
@@ -128,11 +128,11 @@ void DriverEGL::InitializeStaticBindings() {
void DriverEGL::InitializeClientExtensionBindings() {
std::string client_extensions(GetClientExtensions());
- client_extensions += " ";
- ALLOW_UNUSED_LOCAL(client_extensions);
+ ExtensionSet extensions(MakeExtensionSet(client_extensions));
+ ALLOW_UNUSED_LOCAL(extensions);
ext.b_EGL_EXT_platform_base =
- client_extensions.find("EGL_EXT_platform_base ") != std::string::npos;
+ HasExtension(extensions, "EGL_EXT_platform_base");
if (ext.b_EGL_EXT_platform_base) {
fn.eglGetPlatformDisplayEXTFn =
@@ -142,51 +142,41 @@ void DriverEGL::InitializeClientExtensionBindings() {
}
void DriverEGL::InitializeExtensionBindings() {
- std::string extensions(GetPlatformExtensions());
- extensions += " ";
+ std::string platform_extensions(GetPlatformExtensions());
+ ExtensionSet extensions(MakeExtensionSet(platform_extensions));
ALLOW_UNUSED_LOCAL(extensions);
ext.b_EGL_ANGLE_d3d_share_handle_client_buffer =
- extensions.find("EGL_ANGLE_d3d_share_handle_client_buffer ") !=
- std::string::npos;
+ HasExtension(extensions, "EGL_ANGLE_d3d_share_handle_client_buffer");
ext.b_EGL_ANGLE_program_cache_control =
- extensions.find("EGL_ANGLE_program_cache_control ") != std::string::npos;
+ HasExtension(extensions, "EGL_ANGLE_program_cache_control");
ext.b_EGL_ANGLE_query_surface_pointer =
- extensions.find("EGL_ANGLE_query_surface_pointer ") != std::string::npos;
+ HasExtension(extensions, "EGL_ANGLE_query_surface_pointer");
ext.b_EGL_ANGLE_stream_producer_d3d_texture_nv12 =
- extensions.find("EGL_ANGLE_stream_producer_d3d_texture_nv12 ") !=
- std::string::npos;
+ HasExtension(extensions, "EGL_ANGLE_stream_producer_d3d_texture_nv12");
ext.b_EGL_ANGLE_surface_d3d_texture_2d_share_handle =
- extensions.find("EGL_ANGLE_surface_d3d_texture_2d_share_handle ") !=
- std::string::npos;
+ HasExtension(extensions, "EGL_ANGLE_surface_d3d_texture_2d_share_handle");
ext.b_EGL_CHROMIUM_sync_control =
- extensions.find("EGL_CHROMIUM_sync_control ") != std::string::npos;
+ HasExtension(extensions, "EGL_CHROMIUM_sync_control");
ext.b_EGL_EXT_image_flush_external =
- extensions.find("EGL_EXT_image_flush_external ") != std::string::npos;
- ext.b_EGL_KHR_fence_sync =
- extensions.find("EGL_KHR_fence_sync ") != std::string::npos;
+ HasExtension(extensions, "EGL_EXT_image_flush_external");
+ ext.b_EGL_KHR_fence_sync = HasExtension(extensions, "EGL_KHR_fence_sync");
ext.b_EGL_KHR_gl_texture_2D_image =
- extensions.find("EGL_KHR_gl_texture_2D_image ") != std::string::npos;
- ext.b_EGL_KHR_image = extensions.find("EGL_KHR_image ") != std::string::npos;
- ext.b_EGL_KHR_image_base =
- extensions.find("EGL_KHR_image_base ") != std::string::npos;
- ext.b_EGL_KHR_stream =
- extensions.find("EGL_KHR_stream ") != std::string::npos;
+ HasExtension(extensions, "EGL_KHR_gl_texture_2D_image");
+ ext.b_EGL_KHR_image = HasExtension(extensions, "EGL_KHR_image");
+ ext.b_EGL_KHR_image_base = HasExtension(extensions, "EGL_KHR_image_base");
+ ext.b_EGL_KHR_stream = HasExtension(extensions, "EGL_KHR_stream");
ext.b_EGL_KHR_stream_consumer_gltexture =
- extensions.find("EGL_KHR_stream_consumer_gltexture ") !=
- std::string::npos;
+ HasExtension(extensions, "EGL_KHR_stream_consumer_gltexture");
ext.b_EGL_KHR_swap_buffers_with_damage =
- extensions.find("EGL_KHR_swap_buffers_with_damage ") != std::string::npos;
- ext.b_EGL_KHR_wait_sync =
- extensions.find("EGL_KHR_wait_sync ") != std::string::npos;
+ HasExtension(extensions, "EGL_KHR_swap_buffers_with_damage");
+ ext.b_EGL_KHR_wait_sync = HasExtension(extensions, "EGL_KHR_wait_sync");
ext.b_EGL_NV_post_sub_buffer =
- extensions.find("EGL_NV_post_sub_buffer ") != std::string::npos;
+ HasExtension(extensions, "EGL_NV_post_sub_buffer");
ext.b_EGL_NV_stream_consumer_gltexture_yuv =
- extensions.find("EGL_NV_stream_consumer_gltexture_yuv ") !=
- std::string::npos;
+ HasExtension(extensions, "EGL_NV_stream_consumer_gltexture_yuv");
ext.b_GL_CHROMIUM_egl_khr_fence_sync_hack =
- extensions.find("GL_CHROMIUM_egl_khr_fence_sync_hack ") !=
- std::string::npos;
+ HasExtension(extensions, "GL_CHROMIUM_egl_khr_fence_sync_hack");
if (ext.b_EGL_KHR_image || ext.b_EGL_KHR_image_base ||
ext.b_EGL_KHR_gl_texture_2D_image) {
diff --git a/chromium/ui/gl/gl_bindings_autogen_egl.h b/chromium/ui/gl/gl_bindings_autogen_egl.h
index f054e576db0..834d697eb79 100644
--- a/chromium/ui/gl/gl_bindings_autogen_egl.h
+++ b/chromium/ui/gl/gl_bindings_autogen_egl.h
@@ -11,6 +11,8 @@
#ifndef UI_GL_GL_BINDINGS_AUTOGEN_EGL_H_
#define UI_GL_GL_BINDINGS_AUTOGEN_EGL_H_
+#include <string>
+
namespace gl {
class GLContext;
@@ -321,6 +323,8 @@ class GL_EXPORT EGLApi {
EGLApi();
virtual ~EGLApi();
+ virtual void SetDisabledExtensions(const std::string& disabled_extensions) {}
+
virtual EGLBoolean eglBindAPIFn(EGLenum api) = 0;
virtual EGLBoolean eglBindTexImageFn(EGLDisplay dpy,
EGLSurface surface,
diff --git a/chromium/ui/gl/gl_bindings_autogen_gl.cc b/chromium/ui/gl/gl_bindings_autogen_gl.cc
index 95faee85992..fadb5c0288e 100644
--- a/chromium/ui/gl/gl_bindings_autogen_gl.cc
+++ b/chromium/ui/gl/gl_bindings_autogen_gl.cc
@@ -237,6 +237,7 @@ void DriverGL::InitializeStaticBindings() {
fn.glGetIntegervRobustANGLEFn = 0;
fn.glGetInternalformativFn = 0;
fn.glGetInternalformativRobustANGLEFn = 0;
+ fn.glGetMultisamplefvFn = 0;
fn.glGetMultisamplefvRobustANGLEFn = 0;
fn.glGetnUniformfvRobustANGLEFn = 0;
fn.glGetnUniformivRobustANGLEFn = 0;
@@ -368,6 +369,7 @@ void DriverGL::InitializeStaticBindings() {
fn.glPixelStoreiFn =
reinterpret_cast<glPixelStoreiProc>(GetGLProcAddress("glPixelStorei"));
fn.glPointParameteriFn = 0;
+ fn.glPolygonModeFn = 0;
fn.glPolygonOffsetFn = reinterpret_cast<glPolygonOffsetProc>(
GetGLProcAddress("glPolygonOffset"));
fn.glPopDebugGroupFn = 0;
@@ -431,6 +433,8 @@ void DriverGL::InitializeStaticBindings() {
fn.glStencilThenCoverStrokePathNVFn = 0;
fn.glTestFenceAPPLEFn = 0;
fn.glTestFenceNVFn = 0;
+ fn.glTexBufferFn = 0;
+ fn.glTexBufferRangeFn = 0;
fn.glTexImage2DFn =
reinterpret_cast<glTexImage2DProc>(GetGLProcAddress("glTexImage2D"));
fn.glTexImage2DRobustANGLEFn = 0;
@@ -543,140 +547,128 @@ void DriverGL::InitializeStaticBindings() {
fn.glWaitSyncFn = 0;
}
-void DriverGL::InitializeDynamicBindings(
- const GLVersionInfo* ver,
- const std::string& context_extensions) {
- std::string extensions = context_extensions + " ";
- ALLOW_UNUSED_LOCAL(extensions);
-
+void DriverGL::InitializeDynamicBindings(const GLVersionInfo* ver,
+ const ExtensionSet& extensions) {
ext.b_GL_ANGLE_framebuffer_blit =
- extensions.find("GL_ANGLE_framebuffer_blit ") != std::string::npos;
+ HasExtension(extensions, "GL_ANGLE_framebuffer_blit");
ext.b_GL_ANGLE_framebuffer_multisample =
- extensions.find("GL_ANGLE_framebuffer_multisample ") != std::string::npos;
+ HasExtension(extensions, "GL_ANGLE_framebuffer_multisample");
ext.b_GL_ANGLE_instanced_arrays =
- extensions.find("GL_ANGLE_instanced_arrays ") != std::string::npos;
+ HasExtension(extensions, "GL_ANGLE_instanced_arrays");
ext.b_GL_ANGLE_request_extension =
- extensions.find("GL_ANGLE_request_extension ") != std::string::npos;
+ HasExtension(extensions, "GL_ANGLE_request_extension");
ext.b_GL_ANGLE_robust_client_memory =
- extensions.find("GL_ANGLE_robust_client_memory ") != std::string::npos;
+ HasExtension(extensions, "GL_ANGLE_robust_client_memory");
ext.b_GL_ANGLE_translated_shader_source =
- extensions.find("GL_ANGLE_translated_shader_source ") !=
- std::string::npos;
- ext.b_GL_APPLE_fence =
- extensions.find("GL_APPLE_fence ") != std::string::npos;
+ HasExtension(extensions, "GL_ANGLE_translated_shader_source");
+ ext.b_GL_APPLE_fence = HasExtension(extensions, "GL_APPLE_fence");
ext.b_GL_APPLE_vertex_array_object =
- extensions.find("GL_APPLE_vertex_array_object ") != std::string::npos;
+ HasExtension(extensions, "GL_APPLE_vertex_array_object");
ext.b_GL_ARB_blend_func_extended =
- extensions.find("GL_ARB_blend_func_extended ") != std::string::npos;
- ext.b_GL_ARB_draw_buffers =
- extensions.find("GL_ARB_draw_buffers ") != std::string::npos;
+ HasExtension(extensions, "GL_ARB_blend_func_extended");
+ ext.b_GL_ARB_draw_buffers = HasExtension(extensions, "GL_ARB_draw_buffers");
ext.b_GL_ARB_draw_instanced =
- extensions.find("GL_ARB_draw_instanced ") != std::string::npos;
+ HasExtension(extensions, "GL_ARB_draw_instanced");
ext.b_GL_ARB_get_program_binary =
- extensions.find("GL_ARB_get_program_binary ") != std::string::npos;
+ HasExtension(extensions, "GL_ARB_get_program_binary");
ext.b_GL_ARB_instanced_arrays =
- extensions.find("GL_ARB_instanced_arrays ") != std::string::npos;
+ HasExtension(extensions, "GL_ARB_instanced_arrays");
+ ext.b_GL_ARB_internalformat_query =
+ HasExtension(extensions, "GL_ARB_internalformat_query");
ext.b_GL_ARB_map_buffer_range =
- extensions.find("GL_ARB_map_buffer_range ") != std::string::npos;
+ HasExtension(extensions, "GL_ARB_map_buffer_range");
ext.b_GL_ARB_occlusion_query =
- extensions.find("GL_ARB_occlusion_query ") != std::string::npos;
+ HasExtension(extensions, "GL_ARB_occlusion_query");
ext.b_GL_ARB_program_interface_query =
- extensions.find("GL_ARB_program_interface_query ") != std::string::npos;
- ext.b_GL_ARB_robustness =
- extensions.find("GL_ARB_robustness ") != std::string::npos;
+ HasExtension(extensions, "GL_ARB_program_interface_query");
+ ext.b_GL_ARB_robustness = HasExtension(extensions, "GL_ARB_robustness");
ext.b_GL_ARB_sampler_objects =
- extensions.find("GL_ARB_sampler_objects ") != std::string::npos;
+ HasExtension(extensions, "GL_ARB_sampler_objects");
ext.b_GL_ARB_shader_image_load_store =
- extensions.find("GL_ARB_shader_image_load_store ") != std::string::npos;
- ext.b_GL_ARB_sync = extensions.find("GL_ARB_sync ") != std::string::npos;
+ HasExtension(extensions, "GL_ARB_shader_image_load_store");
+ ext.b_GL_ARB_sync = HasExtension(extensions, "GL_ARB_sync");
+ ext.b_GL_ARB_texture_multisample =
+ HasExtension(extensions, "GL_ARB_texture_multisample");
ext.b_GL_ARB_texture_storage =
- extensions.find("GL_ARB_texture_storage ") != std::string::npos;
- ext.b_GL_ARB_timer_query =
- extensions.find("GL_ARB_timer_query ") != std::string::npos;
+ HasExtension(extensions, "GL_ARB_texture_storage");
+ ext.b_GL_ARB_timer_query = HasExtension(extensions, "GL_ARB_timer_query");
ext.b_GL_ARB_transform_feedback2 =
- extensions.find("GL_ARB_transform_feedback2 ") != std::string::npos;
+ HasExtension(extensions, "GL_ARB_transform_feedback2");
ext.b_GL_ARB_vertex_array_object =
- extensions.find("GL_ARB_vertex_array_object ") != std::string::npos;
+ HasExtension(extensions, "GL_ARB_vertex_array_object");
ext.b_GL_CHROMIUM_bind_uniform_location =
- extensions.find("GL_CHROMIUM_bind_uniform_location ") !=
- std::string::npos;
+ HasExtension(extensions, "GL_CHROMIUM_bind_uniform_location");
ext.b_GL_CHROMIUM_compressed_copy_texture =
- extensions.find("GL_CHROMIUM_compressed_copy_texture ") !=
- std::string::npos;
+ HasExtension(extensions, "GL_CHROMIUM_compressed_copy_texture");
ext.b_GL_CHROMIUM_copy_compressed_texture =
- extensions.find("GL_CHROMIUM_copy_compressed_texture ") !=
- std::string::npos;
+ HasExtension(extensions, "GL_CHROMIUM_copy_compressed_texture");
ext.b_GL_CHROMIUM_copy_texture =
- extensions.find("GL_CHROMIUM_copy_texture ") != std::string::npos;
+ HasExtension(extensions, "GL_CHROMIUM_copy_texture");
ext.b_GL_CHROMIUM_gles_depth_binding_hack =
- extensions.find("GL_CHROMIUM_gles_depth_binding_hack ") !=
- std::string::npos;
+ HasExtension(extensions, "GL_CHROMIUM_gles_depth_binding_hack");
ext.b_GL_CHROMIUM_glgetstringi_hack =
- extensions.find("GL_CHROMIUM_glgetstringi_hack ") != std::string::npos;
+ HasExtension(extensions, "GL_CHROMIUM_glgetstringi_hack");
ext.b_GL_EXT_blend_func_extended =
- extensions.find("GL_EXT_blend_func_extended ") != std::string::npos;
- ext.b_GL_EXT_debug_marker =
- extensions.find("GL_EXT_debug_marker ") != std::string::npos;
+ HasExtension(extensions, "GL_EXT_blend_func_extended");
+ ext.b_GL_EXT_debug_marker = HasExtension(extensions, "GL_EXT_debug_marker");
ext.b_GL_EXT_direct_state_access =
- extensions.find("GL_EXT_direct_state_access ") != std::string::npos;
+ HasExtension(extensions, "GL_EXT_direct_state_access");
ext.b_GL_EXT_discard_framebuffer =
- extensions.find("GL_EXT_discard_framebuffer ") != std::string::npos;
+ HasExtension(extensions, "GL_EXT_discard_framebuffer");
ext.b_GL_EXT_disjoint_timer_query =
- extensions.find("GL_EXT_disjoint_timer_query ") != std::string::npos;
- ext.b_GL_EXT_draw_buffers =
- extensions.find("GL_EXT_draw_buffers ") != std::string::npos;
+ HasExtension(extensions, "GL_EXT_disjoint_timer_query");
+ ext.b_GL_EXT_draw_buffers = HasExtension(extensions, "GL_EXT_draw_buffers");
ext.b_GL_EXT_framebuffer_blit =
- extensions.find("GL_EXT_framebuffer_blit ") != std::string::npos;
+ HasExtension(extensions, "GL_EXT_framebuffer_blit");
ext.b_GL_EXT_framebuffer_multisample =
- extensions.find("GL_EXT_framebuffer_multisample ") != std::string::npos;
+ HasExtension(extensions, "GL_EXT_framebuffer_multisample");
ext.b_GL_EXT_framebuffer_object =
- extensions.find("GL_EXT_framebuffer_object ") != std::string::npos;
- ext.b_GL_EXT_gpu_shader4 =
- extensions.find("GL_EXT_gpu_shader4 ") != std::string::npos;
+ HasExtension(extensions, "GL_EXT_framebuffer_object");
+ ext.b_GL_EXT_gpu_shader4 = HasExtension(extensions, "GL_EXT_gpu_shader4");
+ ext.b_GL_EXT_instanced_arrays =
+ HasExtension(extensions, "GL_EXT_instanced_arrays");
ext.b_GL_EXT_map_buffer_range =
- extensions.find("GL_EXT_map_buffer_range ") != std::string::npos;
+ HasExtension(extensions, "GL_EXT_map_buffer_range");
ext.b_GL_EXT_multisampled_render_to_texture =
- extensions.find("GL_EXT_multisampled_render_to_texture ") !=
- std::string::npos;
+ HasExtension(extensions, "GL_EXT_multisampled_render_to_texture");
ext.b_GL_EXT_occlusion_query_boolean =
- extensions.find("GL_EXT_occlusion_query_boolean ") != std::string::npos;
- ext.b_GL_EXT_robustness =
- extensions.find("GL_EXT_robustness ") != std::string::npos;
+ HasExtension(extensions, "GL_EXT_occlusion_query_boolean");
+ ext.b_GL_EXT_robustness = HasExtension(extensions, "GL_EXT_robustness");
ext.b_GL_EXT_shader_image_load_store =
- extensions.find("GL_EXT_shader_image_load_store ") != std::string::npos;
+ HasExtension(extensions, "GL_EXT_shader_image_load_store");
+ ext.b_GL_EXT_texture_buffer =
+ HasExtension(extensions, "GL_EXT_texture_buffer");
+ ext.b_GL_EXT_texture_buffer_object =
+ HasExtension(extensions, "GL_EXT_texture_buffer_object");
ext.b_GL_EXT_texture_storage =
- extensions.find("GL_EXT_texture_storage ") != std::string::npos;
- ext.b_GL_EXT_timer_query =
- extensions.find("GL_EXT_timer_query ") != std::string::npos;
+ HasExtension(extensions, "GL_EXT_texture_storage");
+ ext.b_GL_EXT_timer_query = HasExtension(extensions, "GL_EXT_timer_query");
ext.b_GL_EXT_transform_feedback =
- extensions.find("GL_EXT_transform_feedback ") != std::string::npos;
+ HasExtension(extensions, "GL_EXT_transform_feedback");
ext.b_GL_EXT_unpack_subimage =
- extensions.find("GL_EXT_unpack_subimage ") != std::string::npos;
+ HasExtension(extensions, "GL_EXT_unpack_subimage");
ext.b_GL_IMG_multisampled_render_to_texture =
- extensions.find("GL_IMG_multisampled_render_to_texture ") !=
- std::string::npos;
+ HasExtension(extensions, "GL_IMG_multisampled_render_to_texture");
ext.b_GL_INTEL_framebuffer_CMAA =
- extensions.find("GL_INTEL_framebuffer_CMAA ") != std::string::npos;
+ HasExtension(extensions, "GL_INTEL_framebuffer_CMAA");
ext.b_GL_KHR_blend_equation_advanced =
- extensions.find("GL_KHR_blend_equation_advanced ") != std::string::npos;
- ext.b_GL_KHR_debug = extensions.find("GL_KHR_debug ") != std::string::npos;
- ext.b_GL_KHR_robustness =
- extensions.find("GL_KHR_robustness ") != std::string::npos;
+ HasExtension(extensions, "GL_KHR_blend_equation_advanced");
+ ext.b_GL_KHR_debug = HasExtension(extensions, "GL_KHR_debug");
+ ext.b_GL_KHR_robustness = HasExtension(extensions, "GL_KHR_robustness");
ext.b_GL_NV_blend_equation_advanced =
- extensions.find("GL_NV_blend_equation_advanced ") != std::string::npos;
- ext.b_GL_NV_fence = extensions.find("GL_NV_fence ") != std::string::npos;
+ HasExtension(extensions, "GL_NV_blend_equation_advanced");
+ ext.b_GL_NV_fence = HasExtension(extensions, "GL_NV_fence");
ext.b_GL_NV_framebuffer_mixed_samples =
- extensions.find("GL_NV_framebuffer_mixed_samples ") != std::string::npos;
- ext.b_GL_NV_path_rendering =
- extensions.find("GL_NV_path_rendering ") != std::string::npos;
- ext.b_GL_OES_EGL_image =
- extensions.find("GL_OES_EGL_image ") != std::string::npos;
+ HasExtension(extensions, "GL_NV_framebuffer_mixed_samples");
+ ext.b_GL_NV_path_rendering = HasExtension(extensions, "GL_NV_path_rendering");
+ ext.b_GL_OES_EGL_image = HasExtension(extensions, "GL_OES_EGL_image");
ext.b_GL_OES_get_program_binary =
- extensions.find("GL_OES_get_program_binary ") != std::string::npos;
- ext.b_GL_OES_mapbuffer =
- extensions.find("GL_OES_mapbuffer ") != std::string::npos;
+ HasExtension(extensions, "GL_OES_get_program_binary");
+ ext.b_GL_OES_mapbuffer = HasExtension(extensions, "GL_OES_mapbuffer");
+ ext.b_GL_OES_texture_buffer =
+ HasExtension(extensions, "GL_OES_texture_buffer");
ext.b_GL_OES_vertex_array_object =
- extensions.find("GL_OES_vertex_array_object ") != std::string::npos;
+ HasExtension(extensions, "GL_OES_vertex_array_object");
if (ext.b_GL_INTEL_framebuffer_CMAA) {
fn.glApplyFramebufferAttachmentCMAAINTELFn =
@@ -1453,7 +1445,8 @@ void DriverGL::InitializeDynamicBindings(
GetGLProcAddress("glGetIntegervRobustANGLE"));
}
- if (ver->IsAtLeastGL(4u, 2u) || ver->IsAtLeastGLES(3u, 0u)) {
+ if (ver->IsAtLeastGL(4u, 2u) || ver->IsAtLeastGLES(3u, 0u) ||
+ ext.b_GL_ARB_internalformat_query) {
fn.glGetInternalformativFn = reinterpret_cast<glGetInternalformativProc>(
GetGLProcAddress("glGetInternalformativ"));
}
@@ -1464,6 +1457,12 @@ void DriverGL::InitializeDynamicBindings(
GetGLProcAddress("glGetInternalformativRobustANGLE"));
}
+ if (ver->IsAtLeastGL(3u, 2u) || ver->IsAtLeastGLES(3u, 1u) ||
+ ext.b_GL_ARB_texture_multisample) {
+ fn.glGetMultisamplefvFn = reinterpret_cast<glGetMultisamplefvProc>(
+ GetGLProcAddress("glGetMultisamplefv"));
+ }
+
if (ext.b_GL_ANGLE_robust_client_memory) {
fn.glGetMultisamplefvRobustANGLEFn =
reinterpret_cast<glGetMultisamplefvRobustANGLEProc>(
@@ -2020,6 +2019,11 @@ void DriverGL::InitializeDynamicBindings(
GetGLProcAddress("glPointParameteri"));
}
+ if (!ver->is_es) {
+ fn.glPolygonModeFn =
+ reinterpret_cast<glPolygonModeProc>(GetGLProcAddress("glPolygonMode"));
+ }
+
if (ver->IsAtLeastGL(4u, 3u) || ver->IsAtLeastGLES(3u, 2u)) {
fn.glPopDebugGroupFn = reinterpret_cast<glPopDebugGroupProc>(
GetGLProcAddress("glPopDebugGroup"));
@@ -2271,6 +2275,29 @@ void DriverGL::InitializeDynamicBindings(
reinterpret_cast<glTestFenceNVProc>(GetGLProcAddress("glTestFenceNV"));
}
+ if (ver->IsAtLeastGLES(3u, 2u) || ver->IsAtLeastGL(3u, 1u)) {
+ fn.glTexBufferFn =
+ reinterpret_cast<glTexBufferProc>(GetGLProcAddress("glTexBuffer"));
+ } else if (ext.b_GL_OES_texture_buffer) {
+ fn.glTexBufferFn =
+ reinterpret_cast<glTexBufferProc>(GetGLProcAddress("glTexBufferOES"));
+ } else if (ext.b_GL_EXT_texture_buffer_object ||
+ ext.b_GL_EXT_texture_buffer) {
+ fn.glTexBufferFn =
+ reinterpret_cast<glTexBufferProc>(GetGLProcAddress("glTexBufferEXT"));
+ }
+
+ if (ver->IsAtLeastGL(4u, 3u) || ver->IsAtLeastGLES(3u, 2u)) {
+ fn.glTexBufferRangeFn = reinterpret_cast<glTexBufferRangeProc>(
+ GetGLProcAddress("glTexBufferRange"));
+ } else if (ext.b_GL_OES_texture_buffer) {
+ fn.glTexBufferRangeFn = reinterpret_cast<glTexBufferRangeProc>(
+ GetGLProcAddress("glTexBufferRangeOES"));
+ } else if (ext.b_GL_EXT_texture_buffer) {
+ fn.glTexBufferRangeFn = reinterpret_cast<glTexBufferRangeProc>(
+ GetGLProcAddress("glTexBufferRangeEXT"));
+ }
+
if (ext.b_GL_ANGLE_robust_client_memory) {
fn.glTexImage2DRobustANGLEFn =
reinterpret_cast<glTexImage2DRobustANGLEProc>(
@@ -2449,6 +2476,10 @@ void DriverGL::InitializeDynamicBindings(
fn.glVertexAttribDivisorANGLEFn =
reinterpret_cast<glVertexAttribDivisorANGLEProc>(
GetGLProcAddress("glVertexAttribDivisorANGLE"));
+ } else if (ext.b_GL_EXT_instanced_arrays) {
+ fn.glVertexAttribDivisorANGLEFn =
+ reinterpret_cast<glVertexAttribDivisorANGLEProc>(
+ GetGLProcAddress("glVertexAttribDivisorEXT"));
}
if (ver->IsAtLeastGL(3u, 0u) || ver->IsAtLeastGLES(3u, 0u)) {
@@ -3560,6 +3591,10 @@ void GLApiBase::glGetInternalformativRobustANGLEFn(GLenum target,
bufSize, length, params);
}
+void GLApiBase::glGetMultisamplefvFn(GLenum pname, GLuint index, GLfloat* val) {
+ driver_->fn.glGetMultisamplefvFn(pname, index, val);
+}
+
void GLApiBase::glGetMultisamplefvRobustANGLEFn(GLenum pname,
GLuint index,
GLsizei bufSize,
@@ -4271,6 +4306,10 @@ void GLApiBase::glPointParameteriFn(GLenum pname, GLint param) {
driver_->fn.glPointParameteriFn(pname, param);
}
+void GLApiBase::glPolygonModeFn(GLenum face, GLenum mode) {
+ driver_->fn.glPolygonModeFn(face, mode);
+}
+
void GLApiBase::glPolygonOffsetFn(GLfloat factor, GLfloat units) {
driver_->fn.glPolygonOffsetFn(factor, units);
}
@@ -4630,6 +4669,20 @@ GLboolean GLApiBase::glTestFenceNVFn(GLuint fence) {
return driver_->fn.glTestFenceNVFn(fence);
}
+void GLApiBase::glTexBufferFn(GLenum target,
+ GLenum internalformat,
+ GLuint buffer) {
+ driver_->fn.glTexBufferFn(target, internalformat, buffer);
+}
+
+void GLApiBase::glTexBufferRangeFn(GLenum target,
+ GLenum internalformat,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size) {
+ driver_->fn.glTexBufferRangeFn(target, internalformat, buffer, offset, size);
+}
+
void GLApiBase::glTexImage2DFn(GLenum target,
GLint level,
GLint internalformat,
@@ -5121,10 +5174,8 @@ void GLApiBase::glViewportFn(GLint x, GLint y, GLsizei width, GLsizei height) {
driver_->fn.glViewportFn(x, y, width, height);
}
-GLenum GLApiBase::glWaitSyncFn(GLsync sync,
- GLbitfield flags,
- GLuint64 timeout) {
- return driver_->fn.glWaitSyncFn(sync, flags, timeout);
+void GLApiBase::glWaitSyncFn(GLsync sync, GLbitfield flags, GLuint64 timeout) {
+ driver_->fn.glWaitSyncFn(sync, flags, timeout);
}
void TraceGLApi::glActiveTextureFn(GLenum texture) {
@@ -6390,6 +6441,13 @@ void TraceGLApi::glGetInternalformativRobustANGLEFn(GLenum target,
bufSize, length, params);
}
+void TraceGLApi::glGetMultisamplefvFn(GLenum pname,
+ GLuint index,
+ GLfloat* val) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glGetMultisamplefv")
+ gl_api_->glGetMultisamplefvFn(pname, index, val);
+}
+
void TraceGLApi::glGetMultisamplefvRobustANGLEFn(GLenum pname,
GLuint index,
GLsizei bufSize,
@@ -7231,6 +7289,11 @@ void TraceGLApi::glPointParameteriFn(GLenum pname, GLint param) {
gl_api_->glPointParameteriFn(pname, param);
}
+void TraceGLApi::glPolygonModeFn(GLenum face, GLenum mode) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glPolygonMode")
+ gl_api_->glPolygonModeFn(face, mode);
+}
+
void TraceGLApi::glPolygonOffsetFn(GLfloat factor, GLfloat units) {
TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glPolygonOffset")
gl_api_->glPolygonOffsetFn(factor, units);
@@ -7655,6 +7718,22 @@ GLboolean TraceGLApi::glTestFenceNVFn(GLuint fence) {
return gl_api_->glTestFenceNVFn(fence);
}
+void TraceGLApi::glTexBufferFn(GLenum target,
+ GLenum internalformat,
+ GLuint buffer) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glTexBuffer")
+ gl_api_->glTexBufferFn(target, internalformat, buffer);
+}
+
+void TraceGLApi::glTexBufferRangeFn(GLenum target,
+ GLenum internalformat,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size) {
+ TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glTexBufferRange")
+ gl_api_->glTexBufferRangeFn(target, internalformat, buffer, offset, size);
+}
+
void TraceGLApi::glTexImage2DFn(GLenum target,
GLint level,
GLint internalformat,
@@ -8222,11 +8301,9 @@ void TraceGLApi::glViewportFn(GLint x, GLint y, GLsizei width, GLsizei height) {
gl_api_->glViewportFn(x, y, width, height);
}
-GLenum TraceGLApi::glWaitSyncFn(GLsync sync,
- GLbitfield flags,
- GLuint64 timeout) {
+void TraceGLApi::glWaitSyncFn(GLsync sync, GLbitfield flags, GLuint64 timeout) {
TRACE_EVENT_BINARY_EFFICIENT0("gpu", "TraceGLAPI::glWaitSync")
- return gl_api_->glWaitSyncFn(sync, flags, timeout);
+ gl_api_->glWaitSyncFn(sync, flags, timeout);
}
void DebugGLApi::glActiveTextureFn(GLenum texture) {
@@ -9891,6 +9968,15 @@ void DebugGLApi::glGetInternalformativRobustANGLEFn(GLenum target,
bufSize, length, params);
}
+void DebugGLApi::glGetMultisamplefvFn(GLenum pname,
+ GLuint index,
+ GLfloat* val) {
+ GL_SERVICE_LOG("glGetMultisamplefv"
+ << "(" << GLEnums::GetStringEnum(pname) << ", " << index
+ << ", " << static_cast<const void*>(val) << ")");
+ gl_api_->glGetMultisamplefvFn(pname, index, val);
+}
+
void DebugGLApi::glGetMultisamplefvRobustANGLEFn(GLenum pname,
GLuint index,
GLsizei bufSize,
@@ -11015,6 +11101,13 @@ void DebugGLApi::glPointParameteriFn(GLenum pname, GLint param) {
gl_api_->glPointParameteriFn(pname, param);
}
+void DebugGLApi::glPolygonModeFn(GLenum face, GLenum mode) {
+ GL_SERVICE_LOG("glPolygonMode"
+ << "(" << GLEnums::GetStringEnum(face) << ", "
+ << GLEnums::GetStringEnum(mode) << ")");
+ gl_api_->glPolygonModeFn(face, mode);
+}
+
void DebugGLApi::glPolygonOffsetFn(GLfloat factor, GLfloat units) {
GL_SERVICE_LOG("glPolygonOffset"
<< "(" << factor << ", " << units << ")");
@@ -11581,6 +11674,28 @@ GLboolean DebugGLApi::glTestFenceNVFn(GLuint fence) {
return result;
}
+void DebugGLApi::glTexBufferFn(GLenum target,
+ GLenum internalformat,
+ GLuint buffer) {
+ GL_SERVICE_LOG("glTexBuffer"
+ << "(" << GLEnums::GetStringEnum(target) << ", "
+ << GLEnums::GetStringEnum(internalformat) << ", " << buffer
+ << ")");
+ gl_api_->glTexBufferFn(target, internalformat, buffer);
+}
+
+void DebugGLApi::glTexBufferRangeFn(GLenum target,
+ GLenum internalformat,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size) {
+ GL_SERVICE_LOG("glTexBufferRange"
+ << "(" << GLEnums::GetStringEnum(target) << ", "
+ << GLEnums::GetStringEnum(internalformat) << ", " << buffer
+ << ", " << offset << ", " << size << ")");
+ gl_api_->glTexBufferRangeFn(target, internalformat, buffer, offset, size);
+}
+
void DebugGLApi::glTexImage2DFn(GLenum target,
GLint level,
GLint internalformat,
@@ -12325,14 +12440,10 @@ void DebugGLApi::glViewportFn(GLint x, GLint y, GLsizei width, GLsizei height) {
gl_api_->glViewportFn(x, y, width, height);
}
-GLenum DebugGLApi::glWaitSyncFn(GLsync sync,
- GLbitfield flags,
- GLuint64 timeout) {
+void DebugGLApi::glWaitSyncFn(GLsync sync, GLbitfield flags, GLuint64 timeout) {
GL_SERVICE_LOG("glWaitSync"
<< "(" << sync << ", " << flags << ", " << timeout << ")");
- GLenum result = gl_api_->glWaitSyncFn(sync, flags, timeout);
- GL_SERVICE_LOG("GL_RESULT: " << result);
- return result;
+ gl_api_->glWaitSyncFn(sync, flags, timeout);
}
void NoContextGLApi::glActiveTextureFn(GLenum texture) {
@@ -13743,6 +13854,15 @@ void NoContextGLApi::glGetInternalformativRobustANGLEFn(GLenum target,
"current GL context";
}
+void NoContextGLApi::glGetMultisamplefvFn(GLenum pname,
+ GLuint index,
+ GLfloat* val) {
+ NOTREACHED()
+ << "Trying to call glGetMultisamplefv() without current GL context";
+ LOG(ERROR)
+ << "Trying to call glGetMultisamplefv() without current GL context";
+}
+
void NoContextGLApi::glGetMultisamplefvRobustANGLEFn(GLenum pname,
GLuint index,
GLsizei bufSize,
@@ -14711,6 +14831,11 @@ void NoContextGLApi::glPointParameteriFn(GLenum pname, GLint param) {
LOG(ERROR) << "Trying to call glPointParameteri() without current GL context";
}
+void NoContextGLApi::glPolygonModeFn(GLenum face, GLenum mode) {
+ NOTREACHED() << "Trying to call glPolygonMode() without current GL context";
+ LOG(ERROR) << "Trying to call glPolygonMode() without current GL context";
+}
+
void NoContextGLApi::glPolygonOffsetFn(GLfloat factor, GLfloat units) {
NOTREACHED() << "Trying to call glPolygonOffset() without current GL context";
LOG(ERROR) << "Trying to call glPolygonOffset() without current GL context";
@@ -15185,6 +15310,23 @@ GLboolean NoContextGLApi::glTestFenceNVFn(GLuint fence) {
return GL_FALSE;
}
+void NoContextGLApi::glTexBufferFn(GLenum target,
+ GLenum internalformat,
+ GLuint buffer) {
+ NOTREACHED() << "Trying to call glTexBuffer() without current GL context";
+ LOG(ERROR) << "Trying to call glTexBuffer() without current GL context";
+}
+
+void NoContextGLApi::glTexBufferRangeFn(GLenum target,
+ GLenum internalformat,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size) {
+ NOTREACHED()
+ << "Trying to call glTexBufferRange() without current GL context";
+ LOG(ERROR) << "Trying to call glTexBufferRange() without current GL context";
+}
+
void NoContextGLApi::glTexImage2DFn(GLenum target,
GLint level,
GLint internalformat,
@@ -15814,12 +15956,11 @@ void NoContextGLApi::glViewportFn(GLint x,
LOG(ERROR) << "Trying to call glViewport() without current GL context";
}
-GLenum NoContextGLApi::glWaitSyncFn(GLsync sync,
- GLbitfield flags,
- GLuint64 timeout) {
+void NoContextGLApi::glWaitSyncFn(GLsync sync,
+ GLbitfield flags,
+ GLuint64 timeout) {
NOTREACHED() << "Trying to call glWaitSync() without current GL context";
LOG(ERROR) << "Trying to call glWaitSync() without current GL context";
- return static_cast<GLenum>(0);
}
} // namespace gl
diff --git a/chromium/ui/gl/gl_bindings_autogen_gl.h b/chromium/ui/gl/gl_bindings_autogen_gl.h
index db088a34b09..816a0c5dda1 100644
--- a/chromium/ui/gl/gl_bindings_autogen_gl.h
+++ b/chromium/ui/gl/gl_bindings_autogen_gl.h
@@ -11,6 +11,8 @@
#ifndef UI_GL_GL_BINDINGS_AUTOGEN_GL_H_
#define UI_GL_GL_BINDINGS_AUTOGEN_GL_H_
+#include <string>
+
namespace gl {
class GLContext;
@@ -611,6 +613,9 @@ typedef void(GL_BINDING_CALL* glGetInternalformativRobustANGLEProc)(
GLsizei bufSize,
GLsizei* length,
GLint* params);
+typedef void(GL_BINDING_CALL* glGetMultisamplefvProc)(GLenum pname,
+ GLuint index,
+ GLfloat* val);
typedef void(GL_BINDING_CALL* glGetMultisamplefvRobustANGLEProc)(
GLenum pname,
GLuint index,
@@ -1014,6 +1019,7 @@ typedef void(GL_BINDING_CALL* glPathStencilFuncNVProc)(GLenum func,
typedef void(GL_BINDING_CALL* glPauseTransformFeedbackProc)(void);
typedef void(GL_BINDING_CALL* glPixelStoreiProc)(GLenum pname, GLint param);
typedef void(GL_BINDING_CALL* glPointParameteriProc)(GLenum pname, GLint param);
+typedef void(GL_BINDING_CALL* glPolygonModeProc)(GLenum face, GLenum mode);
typedef void(GL_BINDING_CALL* glPolygonOffsetProc)(GLfloat factor,
GLfloat units);
typedef void(GL_BINDING_CALL* glPopDebugGroupProc)();
@@ -1223,6 +1229,14 @@ typedef void(GL_BINDING_CALL* glStencilThenCoverStrokePathNVProc)(
GLenum coverMode);
typedef GLboolean(GL_BINDING_CALL* glTestFenceAPPLEProc)(GLuint fence);
typedef GLboolean(GL_BINDING_CALL* glTestFenceNVProc)(GLuint fence);
+typedef void(GL_BINDING_CALL* glTexBufferProc)(GLenum target,
+ GLenum internalformat,
+ GLuint buffer);
+typedef void(GL_BINDING_CALL* glTexBufferRangeProc)(GLenum target,
+ GLenum internalformat,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size);
typedef void(GL_BINDING_CALL* glTexImage2DProc)(GLenum target,
GLint level,
GLint internalformat,
@@ -1525,9 +1539,9 @@ typedef void(GL_BINDING_CALL* glViewportProc)(GLint x,
GLint y,
GLsizei width,
GLsizei height);
-typedef GLenum(GL_BINDING_CALL* glWaitSyncProc)(GLsync sync,
- GLbitfield flags,
- GLuint64 timeout);
+typedef void(GL_BINDING_CALL* glWaitSyncProc)(GLsync sync,
+ GLbitfield flags,
+ GLuint64 timeout);
struct ExtensionsGL {
bool b_GL_ANGLE_framebuffer_blit;
@@ -1543,6 +1557,7 @@ struct ExtensionsGL {
bool b_GL_ARB_draw_instanced;
bool b_GL_ARB_get_program_binary;
bool b_GL_ARB_instanced_arrays;
+ bool b_GL_ARB_internalformat_query;
bool b_GL_ARB_map_buffer_range;
bool b_GL_ARB_occlusion_query;
bool b_GL_ARB_program_interface_query;
@@ -1550,6 +1565,7 @@ struct ExtensionsGL {
bool b_GL_ARB_sampler_objects;
bool b_GL_ARB_shader_image_load_store;
bool b_GL_ARB_sync;
+ bool b_GL_ARB_texture_multisample;
bool b_GL_ARB_texture_storage;
bool b_GL_ARB_timer_query;
bool b_GL_ARB_transform_feedback2;
@@ -1570,11 +1586,14 @@ struct ExtensionsGL {
bool b_GL_EXT_framebuffer_multisample;
bool b_GL_EXT_framebuffer_object;
bool b_GL_EXT_gpu_shader4;
+ bool b_GL_EXT_instanced_arrays;
bool b_GL_EXT_map_buffer_range;
bool b_GL_EXT_multisampled_render_to_texture;
bool b_GL_EXT_occlusion_query_boolean;
bool b_GL_EXT_robustness;
bool b_GL_EXT_shader_image_load_store;
+ bool b_GL_EXT_texture_buffer;
+ bool b_GL_EXT_texture_buffer_object;
bool b_GL_EXT_texture_storage;
bool b_GL_EXT_timer_query;
bool b_GL_EXT_transform_feedback;
@@ -1591,6 +1610,7 @@ struct ExtensionsGL {
bool b_GL_OES_EGL_image;
bool b_GL_OES_get_program_binary;
bool b_GL_OES_mapbuffer;
+ bool b_GL_OES_texture_buffer;
bool b_GL_OES_vertex_array_object;
};
@@ -1769,6 +1789,7 @@ struct ProcsGL {
glGetIntegervRobustANGLEProc glGetIntegervRobustANGLEFn;
glGetInternalformativProc glGetInternalformativFn;
glGetInternalformativRobustANGLEProc glGetInternalformativRobustANGLEFn;
+ glGetMultisamplefvProc glGetMultisamplefvFn;
glGetMultisamplefvRobustANGLEProc glGetMultisamplefvRobustANGLEFn;
glGetnUniformfvRobustANGLEProc glGetnUniformfvRobustANGLEFn;
glGetnUniformivRobustANGLEProc glGetnUniformivRobustANGLEFn;
@@ -1879,6 +1900,7 @@ struct ProcsGL {
glPauseTransformFeedbackProc glPauseTransformFeedbackFn;
glPixelStoreiProc glPixelStoreiFn;
glPointParameteriProc glPointParameteriFn;
+ glPolygonModeProc glPolygonModeFn;
glPolygonOffsetProc glPolygonOffsetFn;
glPopDebugGroupProc glPopDebugGroupFn;
glPopGroupMarkerEXTProc glPopGroupMarkerEXTFn;
@@ -1934,6 +1956,8 @@ struct ProcsGL {
glStencilThenCoverStrokePathNVProc glStencilThenCoverStrokePathNVFn;
glTestFenceAPPLEProc glTestFenceAPPLEFn;
glTestFenceNVProc glTestFenceNVFn;
+ glTexBufferProc glTexBufferFn;
+ glTexBufferRangeProc glTexBufferRangeFn;
glTexImage2DProc glTexImage2DFn;
glTexImage2DRobustANGLEProc glTexImage2DRobustANGLEFn;
glTexImage3DProc glTexImage3DFn;
@@ -2014,6 +2038,8 @@ class GL_EXPORT GLApi {
GLApi();
virtual ~GLApi();
+ virtual void SetDisabledExtensions(const std::string& disabled_extensions) {}
+
virtual void glActiveTextureFn(GLenum texture) = 0;
virtual void glApplyFramebufferAttachmentCMAAINTELFn(void) = 0;
virtual void glAttachShaderFn(GLuint program, GLuint shader) = 0;
@@ -2543,6 +2569,9 @@ class GL_EXPORT GLApi {
GLsizei bufSize,
GLsizei* length,
GLint* params) = 0;
+ virtual void glGetMultisamplefvFn(GLenum pname,
+ GLuint index,
+ GLfloat* val) = 0;
virtual void glGetMultisamplefvRobustANGLEFn(GLenum pname,
GLuint index,
GLsizei bufSize,
@@ -2896,6 +2925,7 @@ class GL_EXPORT GLApi {
virtual void glPauseTransformFeedbackFn(void) = 0;
virtual void glPixelStoreiFn(GLenum pname, GLint param) = 0;
virtual void glPointParameteriFn(GLenum pname, GLint param) = 0;
+ virtual void glPolygonModeFn(GLenum face, GLenum mode) = 0;
virtual void glPolygonOffsetFn(GLfloat factor, GLfloat units) = 0;
virtual void glPopDebugGroupFn() = 0;
virtual void glPopGroupMarkerEXTFn(void) = 0;
@@ -3082,6 +3112,14 @@ class GL_EXPORT GLApi {
GLenum coverMode) = 0;
virtual GLboolean glTestFenceAPPLEFn(GLuint fence) = 0;
virtual GLboolean glTestFenceNVFn(GLuint fence) = 0;
+ virtual void glTexBufferFn(GLenum target,
+ GLenum internalformat,
+ GLuint buffer) = 0;
+ virtual void glTexBufferRangeFn(GLenum target,
+ GLenum internalformat,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size) = 0;
virtual void glTexImage2DFn(GLenum target,
GLint level,
GLint internalformat,
@@ -3356,9 +3394,9 @@ class GL_EXPORT GLApi {
GLint y,
GLsizei width,
GLsizei height) = 0;
- virtual GLenum glWaitSyncFn(GLsync sync,
- GLbitfield flags,
- GLuint64 timeout) = 0;
+ virtual void glWaitSyncFn(GLsync sync,
+ GLbitfield flags,
+ GLuint64 timeout) = 0;
};
} // namespace gl
@@ -3596,6 +3634,7 @@ class GL_EXPORT GLApi {
::gl::g_current_gl_context->glGetInternalformativFn
#define glGetInternalformativRobustANGLE \
::gl::g_current_gl_context->glGetInternalformativRobustANGLEFn
+#define glGetMultisamplefv ::gl::g_current_gl_context->glGetMultisamplefvFn
#define glGetMultisamplefvRobustANGLE \
::gl::g_current_gl_context->glGetMultisamplefvRobustANGLEFn
#define glGetnUniformfvRobustANGLE \
@@ -3756,6 +3795,7 @@ class GL_EXPORT GLApi {
::gl::g_current_gl_context->glPauseTransformFeedbackFn
#define glPixelStorei ::gl::g_current_gl_context->glPixelStoreiFn
#define glPointParameteri ::gl::g_current_gl_context->glPointParameteriFn
+#define glPolygonMode ::gl::g_current_gl_context->glPolygonModeFn
#define glPolygonOffset ::gl::g_current_gl_context->glPolygonOffsetFn
#define glPopDebugGroup ::gl::g_current_gl_context->glPopDebugGroupFn
#define glPopGroupMarkerEXT ::gl::g_current_gl_context->glPopGroupMarkerEXTFn
@@ -3833,6 +3873,8 @@ class GL_EXPORT GLApi {
::gl::g_current_gl_context->glStencilThenCoverStrokePathNVFn
#define glTestFenceAPPLE ::gl::g_current_gl_context->glTestFenceAPPLEFn
#define glTestFenceNV ::gl::g_current_gl_context->glTestFenceNVFn
+#define glTexBuffer ::gl::g_current_gl_context->glTexBufferFn
+#define glTexBufferRange ::gl::g_current_gl_context->glTexBufferRangeFn
#define glTexImage2D ::gl::g_current_gl_context->glTexImage2DFn
#define glTexImage2DRobustANGLE \
::gl::g_current_gl_context->glTexImage2DRobustANGLEFn
diff --git a/chromium/ui/gl/gl_bindings_autogen_glx.cc b/chromium/ui/gl/gl_bindings_autogen_glx.cc
index ef9f9ef9152..ed79f1dd778 100644
--- a/chromium/ui/gl/gl_bindings_autogen_glx.cc
+++ b/chromium/ui/gl/gl_bindings_autogen_glx.cc
@@ -114,26 +114,22 @@ void DriverGLX::InitializeStaticBindings() {
}
void DriverGLX::InitializeExtensionBindings() {
- std::string extensions(GetPlatformExtensions());
- extensions += " ";
+ std::string platform_extensions(GetPlatformExtensions());
+ ExtensionSet extensions(MakeExtensionSet(platform_extensions));
ALLOW_UNUSED_LOCAL(extensions);
ext.b_GLX_ARB_create_context =
- extensions.find("GLX_ARB_create_context ") != std::string::npos;
- ext.b_GLX_EXT_swap_control =
- extensions.find("GLX_EXT_swap_control ") != std::string::npos;
+ HasExtension(extensions, "GLX_ARB_create_context");
+ ext.b_GLX_EXT_swap_control = HasExtension(extensions, "GLX_EXT_swap_control");
ext.b_GLX_EXT_texture_from_pixmap =
- extensions.find("GLX_EXT_texture_from_pixmap ") != std::string::npos;
+ HasExtension(extensions, "GLX_EXT_texture_from_pixmap");
ext.b_GLX_MESA_copy_sub_buffer =
- extensions.find("GLX_MESA_copy_sub_buffer ") != std::string::npos;
+ HasExtension(extensions, "GLX_MESA_copy_sub_buffer");
ext.b_GLX_MESA_swap_control =
- extensions.find("GLX_MESA_swap_control ") != std::string::npos;
- ext.b_GLX_OML_sync_control =
- extensions.find("GLX_OML_sync_control ") != std::string::npos;
- ext.b_GLX_SGIX_fbconfig =
- extensions.find("GLX_SGIX_fbconfig ") != std::string::npos;
- ext.b_GLX_SGI_video_sync =
- extensions.find("GLX_SGI_video_sync ") != std::string::npos;
+ HasExtension(extensions, "GLX_MESA_swap_control");
+ ext.b_GLX_OML_sync_control = HasExtension(extensions, "GLX_OML_sync_control");
+ ext.b_GLX_SGIX_fbconfig = HasExtension(extensions, "GLX_SGIX_fbconfig");
+ ext.b_GLX_SGI_video_sync = HasExtension(extensions, "GLX_SGI_video_sync");
if (ext.b_GLX_EXT_texture_from_pixmap) {
fn.glXBindTexImageEXTFn = reinterpret_cast<glXBindTexImageEXTProc>(
diff --git a/chromium/ui/gl/gl_bindings_autogen_glx.h b/chromium/ui/gl/gl_bindings_autogen_glx.h
index 2f75778150d..2cd87ed127d 100644
--- a/chromium/ui/gl/gl_bindings_autogen_glx.h
+++ b/chromium/ui/gl/gl_bindings_autogen_glx.h
@@ -11,6 +11,8 @@
#ifndef UI_GL_GL_BINDINGS_AUTOGEN_GLX_H_
#define UI_GL_GL_BINDINGS_AUTOGEN_GLX_H_
+#include <string>
+
namespace gl {
class GLContext;
@@ -229,6 +231,8 @@ class GL_EXPORT GLXApi {
GLXApi();
virtual ~GLXApi();
+ virtual void SetDisabledExtensions(const std::string& disabled_extensions) {}
+
virtual void glXBindTexImageEXTFn(Display* dpy,
GLXDrawable drawable,
int buffer,
diff --git a/chromium/ui/gl/gl_bindings_autogen_mock.cc b/chromium/ui/gl/gl_bindings_autogen_mock.cc
index 616ac6918c8..812f9103eac 100644
--- a/chromium/ui/gl/gl_bindings_autogen_mock.cc
+++ b/chromium/ui/gl/gl_bindings_autogen_mock.cc
@@ -1715,6 +1715,13 @@ MockGLInterface::Mock_glGetInternalformativRobustANGLE(GLenum target,
bufSize, length, params);
}
+void GL_BINDING_CALL MockGLInterface::Mock_glGetMultisamplefv(GLenum pname,
+ GLuint index,
+ GLfloat* val) {
+ MakeFunctionUnique("glGetMultisamplefv");
+ interface_->GetMultisamplefv(pname, index, val);
+}
+
void GL_BINDING_CALL
MockGLInterface::Mock_glGetMultisamplefvRobustANGLE(GLenum pname,
GLuint index,
@@ -2797,6 +2804,12 @@ void GL_BINDING_CALL MockGLInterface::Mock_glPointParameteri(GLenum pname,
interface_->PointParameteri(pname, param);
}
+void GL_BINDING_CALL MockGLInterface::Mock_glPolygonMode(GLenum face,
+ GLenum mode) {
+ MakeFunctionUnique("glPolygonMode");
+ interface_->PolygonMode(face, mode);
+}
+
void GL_BINDING_CALL MockGLInterface::Mock_glPolygonOffset(GLfloat factor,
GLfloat units) {
MakeFunctionUnique("glPolygonOffset");
@@ -3281,6 +3294,57 @@ GLboolean GL_BINDING_CALL MockGLInterface::Mock_glTestFenceNV(GLuint fence) {
return interface_->TestFenceNV(fence);
}
+void GL_BINDING_CALL MockGLInterface::Mock_glTexBuffer(GLenum target,
+ GLenum internalformat,
+ GLuint buffer) {
+ MakeFunctionUnique("glTexBuffer");
+ interface_->TexBuffer(target, internalformat, buffer);
+}
+
+void GL_BINDING_CALL MockGLInterface::Mock_glTexBufferEXT(GLenum target,
+ GLenum internalformat,
+ GLuint buffer) {
+ MakeFunctionUnique("glTexBufferEXT");
+ interface_->TexBuffer(target, internalformat, buffer);
+}
+
+void GL_BINDING_CALL MockGLInterface::Mock_glTexBufferOES(GLenum target,
+ GLenum internalformat,
+ GLuint buffer) {
+ MakeFunctionUnique("glTexBufferOES");
+ interface_->TexBuffer(target, internalformat, buffer);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glTexBufferRange(GLenum target,
+ GLenum internalformat,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size) {
+ MakeFunctionUnique("glTexBufferRange");
+ interface_->TexBufferRange(target, internalformat, buffer, offset, size);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glTexBufferRangeEXT(GLenum target,
+ GLenum internalformat,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size) {
+ MakeFunctionUnique("glTexBufferRangeEXT");
+ interface_->TexBufferRange(target, internalformat, buffer, offset, size);
+}
+
+void GL_BINDING_CALL
+MockGLInterface::Mock_glTexBufferRangeOES(GLenum target,
+ GLenum internalformat,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size) {
+ MakeFunctionUnique("glTexBufferRangeOES");
+ interface_->TexBufferRange(target, internalformat, buffer, offset, size);
+}
+
void GL_BINDING_CALL MockGLInterface::Mock_glTexImage2D(GLenum target,
GLint level,
GLint internalformat,
@@ -3881,6 +3945,12 @@ MockGLInterface::Mock_glVertexAttribDivisorARB(GLuint index, GLuint divisor) {
interface_->VertexAttribDivisorANGLE(index, divisor);
}
+void GL_BINDING_CALL
+MockGLInterface::Mock_glVertexAttribDivisorEXT(GLuint index, GLuint divisor) {
+ MakeFunctionUnique("glVertexAttribDivisorEXT");
+ interface_->VertexAttribDivisorANGLE(index, divisor);
+}
+
void GL_BINDING_CALL MockGLInterface::Mock_glVertexAttribI4i(GLuint indx,
GLint x,
GLint y,
@@ -3940,11 +4010,11 @@ void GL_BINDING_CALL MockGLInterface::Mock_glViewport(GLint x,
interface_->Viewport(x, y, width, height);
}
-GLenum GL_BINDING_CALL MockGLInterface::Mock_glWaitSync(GLsync sync,
- GLbitfield flags,
- GLuint64 timeout) {
+void GL_BINDING_CALL MockGLInterface::Mock_glWaitSync(GLsync sync,
+ GLbitfield flags,
+ GLuint64 timeout) {
MakeFunctionUnique("glWaitSync");
- return interface_->WaitSync(sync, flags, timeout);
+ interface_->WaitSync(sync, flags, timeout);
}
static void MockInvalidFunction() {
@@ -4445,6 +4515,8 @@ MockGLInterface::GetGLProcAddress(const char* name) {
if (strcmp(name, "glGetInternalformativRobustANGLE") == 0)
return reinterpret_cast<GLFunctionPointerType>(
Mock_glGetInternalformativRobustANGLE);
+ if (strcmp(name, "glGetMultisamplefv") == 0)
+ return reinterpret_cast<GLFunctionPointerType>(Mock_glGetMultisamplefv);
if (strcmp(name, "glGetMultisamplefvRobustANGLE") == 0)
return reinterpret_cast<GLFunctionPointerType>(
Mock_glGetMultisamplefvRobustANGLE);
@@ -4761,6 +4833,8 @@ MockGLInterface::GetGLProcAddress(const char* name) {
return reinterpret_cast<GLFunctionPointerType>(Mock_glPixelStorei);
if (strcmp(name, "glPointParameteri") == 0)
return reinterpret_cast<GLFunctionPointerType>(Mock_glPointParameteri);
+ if (strcmp(name, "glPolygonMode") == 0)
+ return reinterpret_cast<GLFunctionPointerType>(Mock_glPolygonMode);
if (strcmp(name, "glPolygonOffset") == 0)
return reinterpret_cast<GLFunctionPointerType>(Mock_glPolygonOffset);
if (strcmp(name, "glPopDebugGroup") == 0)
@@ -4897,6 +4971,18 @@ MockGLInterface::GetGLProcAddress(const char* name) {
return reinterpret_cast<GLFunctionPointerType>(Mock_glTestFenceAPPLE);
if (strcmp(name, "glTestFenceNV") == 0)
return reinterpret_cast<GLFunctionPointerType>(Mock_glTestFenceNV);
+ if (strcmp(name, "glTexBuffer") == 0)
+ return reinterpret_cast<GLFunctionPointerType>(Mock_glTexBuffer);
+ if (strcmp(name, "glTexBufferEXT") == 0)
+ return reinterpret_cast<GLFunctionPointerType>(Mock_glTexBufferEXT);
+ if (strcmp(name, "glTexBufferOES") == 0)
+ return reinterpret_cast<GLFunctionPointerType>(Mock_glTexBufferOES);
+ if (strcmp(name, "glTexBufferRange") == 0)
+ return reinterpret_cast<GLFunctionPointerType>(Mock_glTexBufferRange);
+ if (strcmp(name, "glTexBufferRangeEXT") == 0)
+ return reinterpret_cast<GLFunctionPointerType>(Mock_glTexBufferRangeEXT);
+ if (strcmp(name, "glTexBufferRangeOES") == 0)
+ return reinterpret_cast<GLFunctionPointerType>(Mock_glTexBufferRangeOES);
if (strcmp(name, "glTexImage2D") == 0)
return reinterpret_cast<GLFunctionPointerType>(Mock_glTexImage2D);
if (strcmp(name, "glTexImage2DRobustANGLE") == 0)
@@ -5049,6 +5135,9 @@ MockGLInterface::GetGLProcAddress(const char* name) {
if (strcmp(name, "glVertexAttribDivisorARB") == 0)
return reinterpret_cast<GLFunctionPointerType>(
Mock_glVertexAttribDivisorARB);
+ if (strcmp(name, "glVertexAttribDivisorEXT") == 0)
+ return reinterpret_cast<GLFunctionPointerType>(
+ Mock_glVertexAttribDivisorEXT);
if (strcmp(name, "glVertexAttribI4i") == 0)
return reinterpret_cast<GLFunctionPointerType>(Mock_glVertexAttribI4i);
if (strcmp(name, "glVertexAttribI4iv") == 0)
diff --git a/chromium/ui/gl/gl_bindings_autogen_mock.h b/chromium/ui/gl/gl_bindings_autogen_mock.h
index 89ca6cd59de..6a2e2c6873d 100644
--- a/chromium/ui/gl/gl_bindings_autogen_mock.h
+++ b/chromium/ui/gl/gl_bindings_autogen_mock.h
@@ -710,6 +710,9 @@ Mock_glGetInternalformativRobustANGLE(GLenum target,
GLsizei bufSize,
GLsizei* length,
GLint* params);
+static void GL_BINDING_CALL Mock_glGetMultisamplefv(GLenum pname,
+ GLuint index,
+ GLfloat* val);
static void GL_BINDING_CALL Mock_glGetMultisamplefvRobustANGLE(GLenum pname,
GLuint index,
GLsizei bufSize,
@@ -1172,6 +1175,7 @@ static void GL_BINDING_CALL Mock_glPathStencilFuncNV(GLenum func,
static void GL_BINDING_CALL Mock_glPauseTransformFeedback(void);
static void GL_BINDING_CALL Mock_glPixelStorei(GLenum pname, GLint param);
static void GL_BINDING_CALL Mock_glPointParameteri(GLenum pname, GLint param);
+static void GL_BINDING_CALL Mock_glPolygonMode(GLenum face, GLenum mode);
static void GL_BINDING_CALL Mock_glPolygonOffset(GLfloat factor, GLfloat units);
static void GL_BINDING_CALL Mock_glPopDebugGroup();
static void GL_BINDING_CALL Mock_glPopDebugGroupKHR();
@@ -1392,6 +1396,30 @@ Mock_glStencilThenCoverStrokePathNV(GLuint path,
GLenum coverMode);
static GLboolean GL_BINDING_CALL Mock_glTestFenceAPPLE(GLuint fence);
static GLboolean GL_BINDING_CALL Mock_glTestFenceNV(GLuint fence);
+static void GL_BINDING_CALL Mock_glTexBuffer(GLenum target,
+ GLenum internalformat,
+ GLuint buffer);
+static void GL_BINDING_CALL Mock_glTexBufferEXT(GLenum target,
+ GLenum internalformat,
+ GLuint buffer);
+static void GL_BINDING_CALL Mock_glTexBufferOES(GLenum target,
+ GLenum internalformat,
+ GLuint buffer);
+static void GL_BINDING_CALL Mock_glTexBufferRange(GLenum target,
+ GLenum internalformat,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size);
+static void GL_BINDING_CALL Mock_glTexBufferRangeEXT(GLenum target,
+ GLenum internalformat,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size);
+static void GL_BINDING_CALL Mock_glTexBufferRangeOES(GLenum target,
+ GLenum internalformat,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size);
static void GL_BINDING_CALL Mock_glTexImage2D(GLenum target,
GLint level,
GLint internalformat,
@@ -1664,6 +1692,8 @@ static void GL_BINDING_CALL Mock_glVertexAttribDivisorANGLE(GLuint index,
GLuint divisor);
static void GL_BINDING_CALL Mock_glVertexAttribDivisorARB(GLuint index,
GLuint divisor);
+static void GL_BINDING_CALL Mock_glVertexAttribDivisorEXT(GLuint index,
+ GLuint divisor);
static void GL_BINDING_CALL
Mock_glVertexAttribI4i(GLuint indx, GLint x, GLint y, GLint z, GLint w);
static void GL_BINDING_CALL Mock_glVertexAttribI4iv(GLuint indx,
@@ -1687,6 +1717,6 @@ static void GL_BINDING_CALL Mock_glViewport(GLint x,
GLint y,
GLsizei width,
GLsizei height);
-static GLenum GL_BINDING_CALL Mock_glWaitSync(GLsync sync,
- GLbitfield flags,
- GLuint64 timeout);
+static void GL_BINDING_CALL Mock_glWaitSync(GLsync sync,
+ GLbitfield flags,
+ GLuint64 timeout);
diff --git a/chromium/ui/gl/gl_bindings_autogen_osmesa.cc b/chromium/ui/gl/gl_bindings_autogen_osmesa.cc
index 27185e32f95..c629e834820 100644
--- a/chromium/ui/gl/gl_bindings_autogen_osmesa.cc
+++ b/chromium/ui/gl/gl_bindings_autogen_osmesa.cc
@@ -48,8 +48,8 @@ void DriverOSMESA::InitializeStaticBindings() {
}
void DriverOSMESA::InitializeExtensionBindings() {
- std::string extensions(GetPlatformExtensions());
- extensions += " ";
+ std::string platform_extensions(GetPlatformExtensions());
+ ExtensionSet extensions(MakeExtensionSet(platform_extensions));
ALLOW_UNUSED_LOCAL(extensions);
}
diff --git a/chromium/ui/gl/gl_bindings_autogen_osmesa.h b/chromium/ui/gl/gl_bindings_autogen_osmesa.h
index a40bf7875bb..baa9587bc56 100644
--- a/chromium/ui/gl/gl_bindings_autogen_osmesa.h
+++ b/chromium/ui/gl/gl_bindings_autogen_osmesa.h
@@ -11,6 +11,8 @@
#ifndef UI_GL_GL_BINDINGS_AUTOGEN_OSMESA_H_
#define UI_GL_GL_BINDINGS_AUTOGEN_OSMESA_H_
+#include <string>
+
namespace gl {
class GLContext;
@@ -69,6 +71,8 @@ class GL_EXPORT OSMESAApi {
OSMESAApi();
virtual ~OSMESAApi();
+ virtual void SetDisabledExtensions(const std::string& disabled_extensions) {}
+
virtual void OSMesaColorClampFn(GLboolean enable) = 0;
virtual OSMesaContext OSMesaCreateContextFn(GLenum format,
OSMesaContext sharelist) = 0;
diff --git a/chromium/ui/gl/gl_bindings_autogen_wgl.cc b/chromium/ui/gl/gl_bindings_autogen_wgl.cc
index 465f13a2986..d6bdc1ea004 100644
--- a/chromium/ui/gl/gl_bindings_autogen_wgl.cc
+++ b/chromium/ui/gl/gl_bindings_autogen_wgl.cc
@@ -58,22 +58,19 @@ void DriverWGL::InitializeStaticBindings() {
}
void DriverWGL::InitializeExtensionBindings() {
- std::string extensions(GetPlatformExtensions());
- extensions += " ";
+ std::string platform_extensions(GetPlatformExtensions());
+ ExtensionSet extensions(MakeExtensionSet(platform_extensions));
ALLOW_UNUSED_LOCAL(extensions);
ext.b_WGL_ARB_create_context =
- extensions.find("WGL_ARB_create_context ") != std::string::npos;
+ HasExtension(extensions, "WGL_ARB_create_context");
ext.b_WGL_ARB_extensions_string =
- extensions.find("WGL_ARB_extensions_string ") != std::string::npos;
- ext.b_WGL_ARB_pbuffer =
- extensions.find("WGL_ARB_pbuffer ") != std::string::npos;
- ext.b_WGL_ARB_pixel_format =
- extensions.find("WGL_ARB_pixel_format ") != std::string::npos;
+ HasExtension(extensions, "WGL_ARB_extensions_string");
+ ext.b_WGL_ARB_pbuffer = HasExtension(extensions, "WGL_ARB_pbuffer");
+ ext.b_WGL_ARB_pixel_format = HasExtension(extensions, "WGL_ARB_pixel_format");
ext.b_WGL_EXT_extensions_string =
- extensions.find("WGL_EXT_extensions_string ") != std::string::npos;
- ext.b_WGL_EXT_swap_control =
- extensions.find("WGL_EXT_swap_control ") != std::string::npos;
+ HasExtension(extensions, "WGL_EXT_extensions_string");
+ ext.b_WGL_EXT_swap_control = HasExtension(extensions, "WGL_EXT_swap_control");
if (ext.b_WGL_ARB_pixel_format) {
fn.wglChoosePixelFormatARBFn =
diff --git a/chromium/ui/gl/gl_bindings_autogen_wgl.h b/chromium/ui/gl/gl_bindings_autogen_wgl.h
index 2377f416585..c6b787d395f 100644
--- a/chromium/ui/gl/gl_bindings_autogen_wgl.h
+++ b/chromium/ui/gl/gl_bindings_autogen_wgl.h
@@ -11,6 +11,8 @@
#ifndef UI_GL_GL_BINDINGS_AUTOGEN_WGL_H_
#define UI_GL_GL_BINDINGS_AUTOGEN_WGL_H_
+#include <string>
+
namespace gl {
class GLContext;
@@ -91,6 +93,8 @@ class GL_EXPORT WGLApi {
WGLApi();
virtual ~WGLApi();
+ virtual void SetDisabledExtensions(const std::string& disabled_extensions) {}
+
virtual BOOL wglChoosePixelFormatARBFn(HDC dc,
const int* int_attrib_list,
const float* float_attrib_list,
diff --git a/chromium/ui/gl/gl_context.cc b/chromium/ui/gl/gl_context.cc
index 80622b2f6e1..9dd442dc457 100644
--- a/chromium/ui/gl/gl_context.cc
+++ b/chromium/ui/gl/gl_context.cc
@@ -32,6 +32,13 @@ base::LazyInstance<base::ThreadLocalPointer<GLContext>>::Leaky
current_real_context_ = LAZY_INSTANCE_INITIALIZER;
} // namespace
+// static
+base::subtle::Atomic32 GLContext::total_gl_contexts_ = 0;
+// static
+bool GLContext::switchable_gpus_supported_ = false;
+// static
+GpuPreference GLContext::forced_gpu_preference_ = GpuPreferenceNone;
+
GLContext::ScopedReleaseCurrent::ScopedReleaseCurrent() : canceled_(false) {}
GLContext::ScopedReleaseCurrent::~ScopedReleaseCurrent() {
@@ -48,6 +55,7 @@ GLContext::GLContext(GLShareGroup* share_group) : share_group_(share_group) {
if (!share_group_.get())
share_group_ = new gl::GLShareGroup();
share_group_->AddContext(this);
+ base::subtle::NoBarrier_AtomicIncrement(&total_gl_contexts_, 1);
}
GLContext::~GLContext() {
@@ -56,12 +64,53 @@ GLContext::~GLContext() {
SetCurrent(nullptr);
SetCurrentGL(nullptr);
}
+ base::subtle::Atomic32 after_value =
+ base::subtle::NoBarrier_AtomicIncrement(&total_gl_contexts_, -1);
+ DCHECK(after_value >= 0);
+}
+
+// static
+int32_t GLContext::TotalGLContexts() {
+ return static_cast<int32_t>(
+ base::subtle::NoBarrier_Load(&total_gl_contexts_));
+}
+
+// static
+bool GLContext::SwitchableGPUsSupported() {
+ return switchable_gpus_supported_;
+}
+
+// static
+void GLContext::SetSwitchableGPUsSupported() {
+ DCHECK(!switchable_gpus_supported_);
+ switchable_gpus_supported_ = true;
+}
+
+// static
+void GLContext::SetForcedGpuPreference(GpuPreference gpu_preference) {
+ DCHECK_EQ(GpuPreferenceNone, forced_gpu_preference_);
+ forced_gpu_preference_ = gpu_preference;
+}
+
+// static
+GpuPreference GLContext::AdjustGpuPreference(GpuPreference gpu_preference) {
+ switch (forced_gpu_preference_) {
+ case GpuPreferenceNone:
+ return gpu_preference;
+ case PreferIntegratedGpu:
+ case PreferDiscreteGpu:
+ return forced_gpu_preference_;
+ default:
+ NOTREACHED();
+ return GpuPreferenceNone;
+ }
}
GLApi* GLContext::CreateGLApi(DriverGL* driver) {
real_gl_api_ = new RealGLApi;
- real_gl_api_->Initialize(driver);
real_gl_api_->set_gl_workarounds(gl_workarounds_);
+ real_gl_api_->SetDisabledExtensions(disabled_gl_extensions_);
+ real_gl_api_->Initialize(driver);
return real_gl_api_;
}
@@ -76,11 +125,6 @@ void GLContext::SetUnbindFboOnMakeCurrent() {
NOTIMPLEMENTED();
}
-std::string GLContext::GetExtensions() {
- DCHECK(IsCurrent(nullptr));
- return GetGLExtensionsFromCurrentContext(gl_api_.get());
-}
-
std::string GLContext::GetGLVersion() {
DCHECK(IsCurrent(nullptr));
DCHECK(gl_api_ != nullptr);
@@ -97,7 +141,8 @@ std::string GLContext::GetGLRenderer() {
return std::string(renderer ? renderer : "");
}
-YUVToRGBConverter* GLContext::GetYUVToRGBConverter() {
+YUVToRGBConverter* GLContext::GetYUVToRGBConverter(
+ const gfx::ColorSpace& color_space) {
return nullptr;
}
@@ -134,6 +179,7 @@ CurrentGL* GLContext::GetCurrentGL() {
void GLContext::ReinitializeDynamicBindings() {
DCHECK(IsCurrent(nullptr));
dynamic_bindings_initialized_ = false;
+ ResetExtensions();
InitializeDynamicBindings();
}
@@ -142,13 +188,7 @@ void GLContext::ForceReleaseVirtuallyCurrent() {
}
bool GLContext::HasExtension(const char* name) {
- std::string extensions = GetExtensions();
- extensions += " ";
-
- std::string delimited_name(name);
- delimited_name += " ";
-
- return extensions.find(delimited_name) != std::string::npos;
+ return gl::HasExtension(GetExtensions(), name);
}
const GLVersionInfo* GLContext::GetVersionInfo() {
@@ -196,7 +236,7 @@ GLContext* GLContext::GetRealCurrent() {
std::unique_ptr<gl::GLVersionInfo> GLContext::GenerateGLVersionInfo() {
return base::MakeUnique<GLVersionInfo>(
- GetGLVersion().c_str(), GetGLRenderer().c_str(), GetExtensions().c_str());
+ GetGLVersion().c_str(), GetGLRenderer().c_str(), GetExtensions());
}
void GLContext::SetCurrent(GLSurface* surface) {
@@ -212,11 +252,14 @@ void GLContext::SetCurrent(GLSurface* surface) {
}
void GLContext::SetGLWorkarounds(const GLWorkarounds& workarounds) {
- DCHECK(IsCurrent(nullptr));
+ DCHECK(!real_gl_api_);
gl_workarounds_ = workarounds;
- if (real_gl_api_) {
- real_gl_api_->set_gl_workarounds(gl_workarounds_);
- }
+}
+
+void GLContext::SetDisabledGLExtensions(
+ const std::string& disabled_extensions) {
+ DCHECK(!real_gl_api_);
+ disabled_gl_extensions_ = disabled_extensions;
}
GLStateRestorer* GLContext::GetGLStateRestorer() {
@@ -250,7 +293,11 @@ void GLContext::InitializeDynamicBindings() {
DCHECK(static_bindings_initialized_);
if (!dynamic_bindings_initialized_) {
if (real_gl_api_) {
- real_gl_api_->InitializeFilteredExtensions();
+ // This is called everytime DoRequestExtensionCHROMIUM() is called in
+ // passthrough command buffer. So the underlying ANGLE driver will have
+ // different GL extensions, therefore we need to clear the cache and
+ // recompute on demand later.
+ real_gl_api_->ClearCachedGLExtensions();
real_gl_api_->set_version(GenerateGLVersionInfo());
}
@@ -336,6 +383,14 @@ scoped_refptr<GPUTimingClient> GLContextReal::CreateGPUTimingClient() {
return gpu_timing_->CreateGPUTimingClient();
}
+const ExtensionSet& GLContextReal::GetExtensions() {
+ DCHECK(IsCurrent(nullptr));
+ if (!extensions_initialized_) {
+ SetExtensionsFromString(GetGLExtensionsFromCurrentContext(gl_api()));
+ }
+ return extensions_;
+}
+
GLContextReal::~GLContextReal() {
if (GetRealCurrent() == this)
current_real_context_.Pointer()->Set(nullptr);
@@ -354,4 +409,16 @@ scoped_refptr<GLContext> InitializeGLContext(scoped_refptr<GLContext> context,
return context;
}
+void GLContextReal::SetExtensionsFromString(std::string extensions) {
+ extensions_string_ = std::move(extensions);
+ extensions_ = MakeExtensionSet(extensions_string_);
+ extensions_initialized_ = true;
+}
+
+void GLContextReal::ResetExtensions() {
+ extensions_.clear();
+ extensions_string_.clear();
+ extensions_initialized_ = false;
+}
+
} // namespace gl
diff --git a/chromium/ui/gl/gl_context.h b/chromium/ui/gl/gl_context.h
index ff9cfdbbb5d..5fe126a56a1 100644
--- a/chromium/ui/gl/gl_context.h
+++ b/chromium/ui/gl/gl_context.h
@@ -7,18 +7,23 @@
#include <memory>
#include <string>
-#include <vector>
+#include "base/atomicops.h"
#include "base/cancelable_callback.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "base/synchronization/cancellation_flag.h"
+#include "ui/gl/extension_set.h"
#include "ui/gl/gl_export.h"
#include "ui/gl/gl_share_group.h"
#include "ui/gl/gl_state_restorer.h"
#include "ui/gl/gl_workarounds.h"
#include "ui/gl/gpu_preference.h"
+namespace gfx {
+class ColorSpace;
+} // namespace gfx
+
namespace gl {
class YUVToRGBConverter;
} // namespace gl
@@ -74,6 +79,19 @@ class GL_EXPORT GLContext : public base::RefCounted<GLContext> {
public:
explicit GLContext(GLShareGroup* share_group);
+ static int32_t TotalGLContexts();
+
+ static bool SwitchableGPUsSupported();
+ // This should be called at most once at GPU process startup time.
+ // By default, GPU switching is not supported unless this is called.
+ static void SetSwitchableGPUsSupported();
+
+ // This should be called at most once at GPU process startup time.
+ static void SetForcedGpuPreference(GpuPreference gpu_preference);
+ // If a gpu preference is forced (by GPU driver bug workaround, etc), return
+ // it. Otherwise, return the original input preference.
+ static GpuPreference AdjustGpuPreference(GpuPreference gpu_preference);
+
// Initializes the GL context to be compatible with the given surface. The GL
// context can be made with other surface's of the same type. The compatible
// surface is only needed for certain platforms like WGL, OSMesa and GLX. It
@@ -100,6 +118,8 @@ class GL_EXPORT GLContext : public base::RefCounted<GLContext> {
// Set the GL workarounds.
void SetGLWorkarounds(const GLWorkarounds& workarounds);
+ void SetDisabledGLExtensions(const std::string& disabled_gl_extensions);
+
// Gets the GLStateRestorer for the context.
GLStateRestorer* GetGLStateRestorer();
@@ -113,8 +133,8 @@ class GL_EXPORT GLContext : public base::RefCounted<GLContext> {
// passed to SetSwapInterval.
void ForceSwapIntervalZero(bool force);
- // Returns space separated list of extensions. The context must be current.
- virtual std::string GetExtensions();
+ // Returns set of extensions. The context must be current.
+ virtual const ExtensionSet& GetExtensions() = 0;
// Indicate that it is safe to force this context to switch GPUs, since
// transitioning can cause corruption and hangs (OS X only).
@@ -167,8 +187,10 @@ class GL_EXPORT GLContext : public base::RefCounted<GLContext> {
// Returns the GL renderer string. The context must be current.
virtual std::string GetGLRenderer();
- // Returns a helper structure to convert YUV textures to RGB textures.
- virtual YUVToRGBConverter* GetYUVToRGBConverter();
+ // Returns a helper structure to convert the YUV color space |color_space|
+ // to its associated full-range RGB color space.
+ virtual YUVToRGBConverter* GetYUVToRGBConverter(
+ const gfx::ColorSpace& color_space);
// Get the CurrentGL object for this context containing the driver, version
// and API.
@@ -217,6 +239,9 @@ class GL_EXPORT GLContext : public base::RefCounted<GLContext> {
static GLContext* GetRealCurrent();
virtual void OnSetSwapInterval(int interval) = 0;
+ virtual void ResetExtensions() = 0;
+
+ GLApi* gl_api() { return gl_api_.get(); }
private:
friend class base::RefCounted<GLContext>;
@@ -226,7 +251,14 @@ class GL_EXPORT GLContext : public base::RefCounted<GLContext> {
std::unique_ptr<GLVersionInfo> GenerateGLVersionInfo();
+ static base::subtle::Atomic32 total_gl_contexts_;
+
+ static bool switchable_gpus_supported_;
+
+ static GpuPreference forced_gpu_preference_;
+
GLWorkarounds gl_workarounds_;
+ std::string disabled_gl_extensions_;
bool static_bindings_initialized_ = false;
bool dynamic_bindings_initialized_ = false;
@@ -256,14 +288,22 @@ class GL_EXPORT GLContextReal : public GLContext {
public:
explicit GLContextReal(GLShareGroup* share_group);
scoped_refptr<GPUTimingClient> CreateGPUTimingClient() override;
+ const ExtensionSet& GetExtensions() override;
protected:
~GLContextReal() override;
+ void ResetExtensions() override;
+
void SetCurrent(GLSurface* surface) override;
+ void SetExtensionsFromString(std::string extensions);
+ const std::string& extension_string() { return extensions_string_; }
private:
std::unique_ptr<GPUTiming> gpu_timing_;
+ std::string extensions_string_;
+ ExtensionSet extensions_;
+ bool extensions_initialized_ = false;
DISALLOW_COPY_AND_ASSIGN(GLContextReal);
};
diff --git a/chromium/ui/gl/gl_context_cgl.cc b/chromium/ui/gl/gl_context_cgl.cc
index 06e5e73b93a..6b85039c6dd 100644
--- a/chromium/ui/gl/gl_context_cgl.cc
+++ b/chromium/ui/gl/gl_context_cgl.cc
@@ -46,7 +46,7 @@ static CGLPixelFormatObj GetPixelFormat() {
std::vector<CGLPixelFormatAttribute> attribs;
// If the system supports dual gpus then allow offline renderers for every
// context, so that they can all be in the same share group.
- if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) {
+ if (GLContext::SwitchableGPUsSupported()) {
attribs.push_back(kCGLPFAAllowOfflineRenderers);
g_support_renderer_switching = true;
}
@@ -101,8 +101,7 @@ bool GLContextCGL::Initialize(GLSurface* compatible_surface,
attribs.bind_generates_resource);
GpuPreference gpu_preference =
- ui::GpuSwitchingManager::GetInstance()->AdjustGpuPreference(
- attribs.gpu_preference);
+ GLContext::AdjustGpuPreference(attribs.gpu_preference);
GLContextCGL* share_context = share_group() ?
static_cast<GLContextCGL*>(share_group()->GetContext()) : nullptr;
@@ -113,7 +112,7 @@ bool GLContextCGL::Initialize(GLSurface* compatible_surface,
// If using the discrete gpu, create a pixel format requiring it before we
// create the context.
- if (!ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus() ||
+ if (!GLContext::SwitchableGPUsSupported() ||
gpu_preference == PreferDiscreteGpu) {
std::vector<CGLPixelFormatAttribute> discrete_attribs;
discrete_attribs.push_back((CGLPixelFormatAttribute) 0);
@@ -149,7 +148,7 @@ bool GLContextCGL::Initialize(GLSurface* compatible_surface,
}
void GLContextCGL::Destroy() {
- if (yuv_to_rgb_converter_) {
+ if (!yuv_to_rgb_converters_.empty()) {
// If this context is not current, bind this context's API so that the YUV
// converter can safely destruct
GLContext* current_context = GetRealCurrent();
@@ -158,7 +157,7 @@ void GLContextCGL::Destroy() {
}
ScopedCGLSetCurrentContext(static_cast<CGLContextObj>(context_));
- yuv_to_rgb_converter_.reset();
+ yuv_to_rgb_converters_.clear();
// Rebind the current context's API if needed.
if (current_context && current_context != this) {
@@ -224,10 +223,14 @@ bool GLContextCGL::ForceGpuSwitchIfNeeded() {
return true;
}
-YUVToRGBConverter* GLContextCGL::GetYUVToRGBConverter() {
- if (!yuv_to_rgb_converter_)
- yuv_to_rgb_converter_.reset(new YUVToRGBConverter(*GetVersionInfo()));
- return yuv_to_rgb_converter_.get();
+YUVToRGBConverter* GLContextCGL::GetYUVToRGBConverter(
+ const gfx::ColorSpace& color_space) {
+ std::unique_ptr<YUVToRGBConverter>& yuv_to_rgb_converter =
+ yuv_to_rgb_converters_[color_space];
+ if (!yuv_to_rgb_converter)
+ yuv_to_rgb_converter.reset(
+ new YUVToRGBConverter(*GetVersionInfo(), color_space));
+ return yuv_to_rgb_converter.get();
}
bool GLContextCGL::MakeCurrent(GLSurface* surface) {
@@ -239,6 +242,16 @@ bool GLContextCGL::MakeCurrent(GLSurface* surface) {
if (IsCurrent(surface))
return true;
+ // It's likely we're going to switch OpenGL contexts at this point.
+ // Before doing so, if there is a current context, flush it. There
+ // are many implicit assumptions of flush ordering between contexts
+ // at higher levels, and if a flush isn't performed, OpenGL commands
+ // may be issued in unexpected orders, causing flickering and other
+ // artifacts.
+ if (CGLGetCurrentContext() != nullptr) {
+ glFlush();
+ }
+
ScopedReleaseCurrent release_current;
TRACE_EVENT0("gpu", "GLContextCGL::MakeCurrent");
@@ -267,6 +280,12 @@ void GLContextCGL::ReleaseCurrent(GLSurface* surface) {
if (!IsCurrent(surface))
return;
+ // Before releasing the current context, flush it. This ensures that
+ // all commands issued by higher levels will be seen by the OpenGL
+ // implementation, which is assumed throughout the code. See comment
+ // in MakeCurrent, above.
+ glFlush();
+
SetCurrent(nullptr);
CGLSetCurrentContext(nullptr);
}
diff --git a/chromium/ui/gl/gl_context_cgl.h b/chromium/ui/gl/gl_context_cgl.h
index 72fbb4d6c8c..737f326c0f9 100644
--- a/chromium/ui/gl/gl_context_cgl.h
+++ b/chromium/ui/gl/gl_context_cgl.h
@@ -7,9 +7,11 @@
#include <OpenGL/CGLTypes.h>
+#include <map>
#include <memory>
#include "base/macros.h"
+#include "ui/gfx/color_space.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_export.h"
@@ -32,7 +34,8 @@ class GL_EXPORT GLContextCGL : public GLContextReal {
void OnSetSwapInterval(int interval) override;
void SetSafeToForceGpuSwitch() override;
bool ForceGpuSwitchIfNeeded() override;
- YUVToRGBConverter* GetYUVToRGBConverter() override;
+ YUVToRGBConverter* GetYUVToRGBConverter(
+ const gfx::ColorSpace& color_space) override;
protected:
~GLContextCGL() override;
@@ -43,7 +46,8 @@ class GL_EXPORT GLContextCGL : public GLContextReal {
void* context_;
GpuPreference gpu_preference_;
- std::unique_ptr<YUVToRGBConverter> yuv_to_rgb_converter_;
+ std::map<gfx::ColorSpace, std::unique_ptr<YUVToRGBConverter>>
+ yuv_to_rgb_converters_;
CGLPixelFormatObj discrete_pixelformat_;
diff --git a/chromium/ui/gl/gl_context_egl.cc b/chromium/ui/gl/gl_context_egl.cc
index 2fbfe08205a..716c0ca6c1f 100644
--- a/chromium/ui/gl/gl_context_egl.cc
+++ b/chromium/ui/gl/gl_context_egl.cc
@@ -154,7 +154,7 @@ bool GLContextEGL::Initialize(GLSurface* compatible_surface,
}
}
- if (GLSurfaceEGL::HasEGLExtension("EGL_ANGLE_display_texture_share_group")) {
+ if (GLSurfaceEGL::IsDisplayTextureShareGroupSupported()) {
context_attributes.push_back(EGL_DISPLAY_TEXTURE_SHARE_GROUP_ANGLE);
context_attributes.push_back(
attribs.global_texture_share_group ? EGL_TRUE : EGL_FALSE);
@@ -162,7 +162,7 @@ bool GLContextEGL::Initialize(GLSurface* compatible_surface,
DCHECK(!attribs.global_texture_share_group);
}
- if (GLSurfaceEGL::HasEGLExtension("EGL_ANGLE_create_context_client_arrays")) {
+ if (GLSurfaceEGL::IsCreateContextClientArraysSupported()) {
// Disable client arrays if the context supports it
context_attributes.push_back(EGL_CONTEXT_CLIENT_ARRAYS_ENABLED_ANGLE);
context_attributes.push_back(EGL_FALSE);
@@ -291,15 +291,6 @@ void GLContextEGL::OnSetSwapInterval(int interval) {
}
}
-std::string GLContextEGL::GetExtensions() {
- const char* extensions = eglQueryString(display_,
- EGL_EXTENSIONS);
- if (!extensions)
- return GLContext::GetExtensions();
-
- return GLContext::GetExtensions() + " " + extensions;
-}
-
bool GLContextEGL::WasAllocatedUsingRobustnessExtension() {
return GLSurfaceEGL::IsCreateContextRobustnessSupported();
}
diff --git a/chromium/ui/gl/gl_context_egl.h b/chromium/ui/gl/gl_context_egl.h
index 6a436dc596d..75b2f3208c1 100644
--- a/chromium/ui/gl/gl_context_egl.h
+++ b/chromium/ui/gl/gl_context_egl.h
@@ -33,7 +33,6 @@ class GL_EXPORT GLContextEGL : public GLContextReal {
bool IsCurrent(GLSurface* surface) override;
void* GetHandle() override;
void OnSetSwapInterval(int interval) override;
- std::string GetExtensions() override;
bool WasAllocatedUsingRobustnessExtension() override;
void SetUnbindFboOnMakeCurrent() override;
diff --git a/chromium/ui/gl/gl_context_glx.cc b/chromium/ui/gl/gl_context_glx.cc
index a4493a29a3a..d66d3119382 100644
--- a/chromium/ui/gl/gl_context_glx.cc
+++ b/chromium/ui/gl/gl_context_glx.cc
@@ -172,16 +172,9 @@ bool GLContextGLX::Initialize(GLSurface* compatible_surface,
if (GLSurfaceGLX::IsCreateContextSupported()) {
DVLOG(1) << "GLX_ARB_create_context supported.";
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kCreateDefaultGLContext)) {
- context_ = CreateContextAttribs(
- display_, static_cast<GLXFBConfig>(compatible_surface->GetConfig()),
- share_handle, GLVersion(0, 0), 0);
- } else {
- context_ = CreateHighestVersionContext(
- display_, static_cast<GLXFBConfig>(compatible_surface->GetConfig()),
- share_handle);
- }
+ context_ = CreateHighestVersionContext(
+ display_, static_cast<GLXFBConfig>(compatible_surface->GetConfig()),
+ share_handle);
if (!context_) {
LOG(ERROR) << "Failed to create GL context with "
<< "glXCreateContextAttribsARB.";
@@ -304,16 +297,6 @@ void GLContextGLX::OnSetSwapInterval(int interval) {
}
}
-std::string GLContextGLX::GetExtensions() {
- DCHECK(IsCurrent(nullptr));
- const char* extensions = GLSurfaceGLX::GetGLXExtensions();
- if (extensions) {
- return GLContext::GetExtensions() + " " + extensions;
- }
-
- return GLContext::GetExtensions();
-}
-
bool GLContextGLX::WasAllocatedUsingRobustnessExtension() {
return GLSurfaceGLX::IsCreateContextRobustnessSupported();
}
diff --git a/chromium/ui/gl/gl_context_glx.h b/chromium/ui/gl/gl_context_glx.h
index 62c78e73327..fd5d8d082ec 100644
--- a/chromium/ui/gl/gl_context_glx.h
+++ b/chromium/ui/gl/gl_context_glx.h
@@ -32,7 +32,6 @@ class GL_EXPORT GLContextGLX : public GLContextReal {
bool IsCurrent(GLSurface* surface) override;
void* GetHandle() override;
void OnSetSwapInterval(int interval) override;
- std::string GetExtensions() override;
bool WasAllocatedUsingRobustnessExtension() override;
protected:
diff --git a/chromium/ui/gl/gl_context_stub.cc b/chromium/ui/gl/gl_context_stub.cc
index 1c54f9dd42c..7f60b288cd8 100644
--- a/chromium/ui/gl/gl_context_stub.cc
+++ b/chromium/ui/gl/gl_context_stub.cc
@@ -13,8 +13,9 @@ GLContextStub::GLContextStub() : GLContextStub(nullptr) {}
GLContextStub::GLContextStub(GLShareGroup* share_group)
: GLContextReal(share_group),
use_stub_api_(false),
- version_str_("OpenGL ES 3.0"),
- extensions_("GL_EXT_framebuffer_object") {}
+ version_str_("OpenGL ES 3.0") {
+ SetExtensionsString("GL_EXT_framebuffer_object");
+}
bool GLContextStub::Initialize(GLSurface* compatible_surface,
const GLContextAttribs& attribs) {
@@ -56,16 +57,12 @@ bool GLContextStub::WasAllocatedUsingRobustnessExtension() {
HasExtension("GL_KHR_robustness") || HasExtension("GL_EXT_robustness");
}
-std::string GLContextStub::GetExtensions() {
- return extensions_;
-}
-
void GLContextStub::SetUseStubApi(bool stub_api) {
use_stub_api_ = stub_api;
}
void GLContextStub::SetExtensionsString(const char* extensions) {
- extensions_ = extensions;
+ SetExtensionsFromString(extensions);
}
void GLContextStub::SetGLVersionString(const char* version_str) {
@@ -80,8 +77,8 @@ GLApi* GLContextStub::CreateGLApi(DriverGL* driver) {
if (!version_str_.empty()) {
stub_api->set_version(version_str_);
}
- if (!extensions_.empty()) {
- stub_api->set_extensions(extensions_);
+ if (!extension_string().empty()) {
+ stub_api->set_extensions(extension_string());
}
return stub_api;
}
diff --git a/chromium/ui/gl/gl_context_stub.h b/chromium/ui/gl/gl_context_stub.h
index 7ddc3d1f028..ca1514ca875 100644
--- a/chromium/ui/gl/gl_context_stub.h
+++ b/chromium/ui/gl/gl_context_stub.h
@@ -30,7 +30,6 @@ class GL_EXPORT GLContextStub : public GLContextReal {
std::string GetGLVersion() override;
std::string GetGLRenderer() override;
bool WasAllocatedUsingRobustnessExtension() override;
- std::string GetExtensions() override;
void SetUseStubApi(bool stub_api);
void SetExtensionsString(const char* extensions);
@@ -44,7 +43,6 @@ class GL_EXPORT GLContextStub : public GLContextReal {
private:
bool use_stub_api_;
std::string version_str_;
- std::string extensions_;
DISALLOW_COPY_AND_ASSIGN(GLContextStub);
};
diff --git a/chromium/ui/gl/gl_context_wgl.cc b/chromium/ui/gl/gl_context_wgl.cc
index 726fcb62496..520b4cac101 100644
--- a/chromium/ui/gl/gl_context_wgl.cc
+++ b/chromium/ui/gl/gl_context_wgl.cc
@@ -162,19 +162,6 @@ void GLContextWGL::OnSetSwapInterval(int interval) {
}
}
-std::string GLContextWGL::GetExtensions() {
- const char* extensions = nullptr;
- if (g_driver_wgl.fn.wglGetExtensionsStringARBFn)
- extensions = wglGetExtensionsStringARB(GLSurfaceWGL::GetDisplayDC());
- else if (g_driver_wgl.fn.wglGetExtensionsStringEXTFn)
- extensions = wglGetExtensionsStringEXT();
-
- if (extensions)
- return GLContext::GetExtensions() + " " + extensions;
-
- return GLContext::GetExtensions();
-}
-
GLContextWGL::~GLContextWGL() {
Destroy();
}
diff --git a/chromium/ui/gl/gl_context_wgl.h b/chromium/ui/gl/gl_context_wgl.h
index aed32873305..52653a08ce0 100644
--- a/chromium/ui/gl/gl_context_wgl.h
+++ b/chromium/ui/gl/gl_context_wgl.h
@@ -29,7 +29,6 @@ class GL_EXPORT GLContextWGL : public GLContextReal {
bool IsCurrent(GLSurface* surface) override;
void* GetHandle() override;
void OnSetSwapInterval(int interval) override;
- std::string GetExtensions() override;
private:
~GLContextWGL() override;
diff --git a/chromium/ui/gl/gl_egl_api_implementation.cc b/chromium/ui/gl/gl_egl_api_implementation.cc
index e0520524b4b..f3bcf751041 100644
--- a/chromium/ui/gl/gl_egl_api_implementation.cc
+++ b/chromium/ui/gl/gl_egl_api_implementation.cc
@@ -9,6 +9,7 @@
#include "base/strings/string_util.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_surface_egl.h"
namespace gl {
@@ -68,22 +69,25 @@ RealEGLApi::~RealEGLApi() {
}
void RealEGLApi::Initialize(DriverEGL* driver) {
- InitializeWithCommandLine(driver, base::CommandLine::ForCurrentProcess());
-}
-
-void RealEGLApi::InitializeWithCommandLine(DriverEGL* driver,
- base::CommandLine* command_line) {
- DCHECK(command_line);
InitializeBase(driver);
+}
- const std::string disabled_extensions = command_line->GetSwitchValueASCII(
- switches::kDisableGLExtensions);
+void RealEGLApi::SetDisabledExtensions(const std::string& disabled_extensions) {
+ DCHECK(GLContext::TotalGLContexts() == 0);
disabled_exts_.clear();
filtered_exts_.clear();
if (!disabled_extensions.empty()) {
- disabled_exts_ = base::SplitString(
- disabled_extensions, ", ;",
- base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
+ std::vector<std::string> candidates =
+ base::SplitString(disabled_extensions, ", ;", base::KEEP_WHITESPACE,
+ base::SPLIT_WANT_NONEMPTY);
+ for (const auto& ext : candidates) {
+ if (!base::StartsWith(ext, "EGL_", base::CompareCase::SENSITIVE))
+ continue;
+ // For the moment, only the following two extensions can be disabled.
+ // See DriverEGL::UpdateConditionalExtensionBindings().
+ DCHECK(ext == "EGL_KHR_fence_sync" || ext == "EGL_KHR_wait_sync");
+ disabled_exts_.push_back(ext);
+ }
}
}
@@ -104,9 +108,23 @@ DebugEGLApi::DebugEGLApi(EGLApi* egl_api) : egl_api_(egl_api) {}
DebugEGLApi::~DebugEGLApi() {}
+void DebugEGLApi::SetDisabledExtensions(
+ const std::string& disabled_extensions) {
+ if (egl_api_) {
+ egl_api_->SetDisabledExtensions(disabled_extensions);
+ }
+}
+
TraceEGLApi::~TraceEGLApi() {
}
+void TraceEGLApi::SetDisabledExtensions(
+ const std::string& disabled_extensions) {
+ if (egl_api_) {
+ egl_api_->SetDisabledExtensions(disabled_extensions);
+ }
+}
+
bool GetGLWindowSystemBindingInfoEGL(GLWindowSystemBindingInfo* info) {
EGLDisplay display = eglGetCurrentDisplay();
const char* vendor = eglQueryString(display, EGL_VENDOR);
@@ -122,4 +140,14 @@ bool GetGLWindowSystemBindingInfoEGL(GLWindowSystemBindingInfo* info) {
return true;
}
+void SetDisabledExtensionsEGL(const std::string& disabled_extensions) {
+ DCHECK(g_current_egl_context);
+ DCHECK(GLContext::TotalGLContexts() == 0);
+ g_current_egl_context->SetDisabledExtensions(disabled_extensions);
+}
+
+bool InitializeExtensionSettingsOneOffEGL() {
+ return GLSurfaceEGL::InitializeExtensionSettingsOneOff();
+}
+
} // namespace gl
diff --git a/chromium/ui/gl/gl_egl_api_implementation.h b/chromium/ui/gl/gl_egl_api_implementation.h
index f120aab53fe..2c44df7d937 100644
--- a/chromium/ui/gl/gl_egl_api_implementation.h
+++ b/chromium/ui/gl/gl_egl_api_implementation.h
@@ -6,15 +6,13 @@
#define UI_GL_GL_EGL_API_IMPLEMENTATION_H_
#include <map>
+#include <string>
#include <vector>
#include "base/compiler_specific.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_export.h"
-namespace base {
-class CommandLine;
-}
namespace gl {
struct GLWindowSystemBindingInfo;
@@ -23,6 +21,8 @@ GL_EXPORT void InitializeStaticGLBindingsEGL();
GL_EXPORT void InitializeDebugGLBindingsEGL();
GL_EXPORT void ClearBindingsEGL();
GL_EXPORT bool GetGLWindowSystemBindingInfoEGL(GLWindowSystemBindingInfo* info);
+GL_EXPORT void SetDisabledExtensionsEGL(const std::string& disabled_extensions);
+GL_EXPORT bool InitializeExtensionSettingsOneOffEGL();
class GL_EXPORT EGLApiBase : public EGLApi {
public:
@@ -44,8 +44,7 @@ class GL_EXPORT RealEGLApi : public EGLApiBase {
RealEGLApi();
~RealEGLApi() override;
void Initialize(DriverEGL* driver);
- void InitializeWithCommandLine(DriverEGL* driver,
- base::CommandLine* command_line);
+ void SetDisabledExtensions(const std::string& disabled_extensions) override;
const char* eglQueryStringFn(EGLDisplay dpy, EGLint name) override;
@@ -60,6 +59,7 @@ class GL_EXPORT DebugEGLApi : public EGLApi {
public:
DebugEGLApi(EGLApi* egl_api);
~DebugEGLApi() override;
+ void SetDisabledExtensions(const std::string& disabled_extensions) override;
// Include the auto-generated part of this class. We split this because
// it means we can easily edit the non-auto generated parts right here in
@@ -75,6 +75,7 @@ class GL_EXPORT TraceEGLApi : public EGLApi {
public:
TraceEGLApi(EGLApi* egl_api) : egl_api_(egl_api) { }
~TraceEGLApi() override;
+ void SetDisabledExtensions(const std::string& disabled_extensions) override;
// Include the auto-generated part of this class. We split this because
// it means we can easily edit the non-auto generated parts right here in
@@ -88,6 +89,3 @@ class GL_EXPORT TraceEGLApi : public EGLApi {
} // namespace gl
#endif // UI_GL_GL_EGL_API_IMPLEMENTATION_H_
-
-
-
diff --git a/chromium/ui/gl/gl_enums_implementation_autogen.h b/chromium/ui/gl/gl_enums_implementation_autogen.h
index a7469082237..d9d51d8054f 100644
--- a/chromium/ui/gl/gl_enums_implementation_autogen.h
+++ b/chromium/ui/gl/gl_enums_implementation_autogen.h
@@ -1909,6 +1909,21 @@ static const GLEnums::EnumToString enum_to_string_table[] = {
0x8A57, "GL_COMPRESSED_SRGB_ALPHA_PVRTC_4BPPV1_EXT",
},
{
+ 0x8AF0, "GL_TEXTURE_FILTERING_HINT_CHROMIUM",
+ },
+ {
+ 0x8AF1, "GL_COLOR_SPACE_UNSPECIFIED_CHROMIUM",
+ },
+ {
+ 0x8AF2, "GL_COLOR_SPACE_SCRGB_LINEAR_CHROMIUM",
+ },
+ {
+ 0x8AF3, "GL_COLOR_SPACE_SRGB_CHROMIUM",
+ },
+ {
+ 0x8AF4, "GL_COLOR_SPACE_DISPLAY_P3_CHROMIUM",
+ },
+ {
0x8B30, "GL_FRAGMENT_SHADER",
},
{
diff --git a/chromium/ui/gl/gl_gl_api_implementation.cc b/chromium/ui/gl/gl_gl_api_implementation.cc
index bc55bfb5433..592e1ac511f 100644
--- a/chromium/ui/gl/gl_gl_api_implementation.cc
+++ b/chromium/ui/gl/gl_gl_api_implementation.cc
@@ -6,7 +6,6 @@
#include <vector>
-#include "base/command_line.h"
#include "base/memory/ptr_util.h"
#include "base/stl_util.h"
#include "base/strings/string_split.h"
@@ -283,37 +282,18 @@ void GLApiBase::InitializeBase(DriverGL* driver) {
}
RealGLApi::RealGLApi() {
-#if DCHECK_IS_ON()
- filtered_exts_initialized_ = false;
-#endif
}
RealGLApi::~RealGLApi() {
}
void RealGLApi::Initialize(DriverGL* driver) {
- InitializeWithCommandLine(driver, base::CommandLine::ForCurrentProcess());
-}
-
-void RealGLApi::InitializeWithCommandLine(DriverGL* driver,
- base::CommandLine* command_line) {
- DCHECK(command_line);
InitializeBase(driver);
-
- const std::string disabled_extensions = command_line->GetSwitchValueASCII(
- switches::kDisableGLExtensions);
- if (!disabled_extensions.empty()) {
- disabled_exts_ = base::SplitString(
- disabled_extensions, ", ;",
- base::KEEP_WHITESPACE, base::SPLIT_WANT_NONEMPTY);
- }
}
void RealGLApi::glGetIntegervFn(GLenum pname, GLint* params) {
if (pname == GL_NUM_EXTENSIONS && disabled_exts_.size()) {
-#if DCHECK_IS_ON()
- DCHECK(filtered_exts_initialized_);
-#endif
+ InitializeFilteredExtensionsIfNeeded();
*params = static_cast<GLint>(filtered_exts_.size());
} else {
GLApiBase::glGetIntegervFn(pname, params);
@@ -322,9 +302,7 @@ void RealGLApi::glGetIntegervFn(GLenum pname, GLint* params) {
const GLubyte* RealGLApi::glGetStringFn(GLenum name) {
if (name == GL_EXTENSIONS && disabled_exts_.size()) {
-#if DCHECK_IS_ON()
- DCHECK(filtered_exts_initialized_);
-#endif
+ InitializeFilteredExtensionsIfNeeded();
return reinterpret_cast<const GLubyte*>(filtered_exts_str_.c_str());
}
return GLApiBase::glGetStringFn(name);
@@ -332,11 +310,9 @@ const GLubyte* RealGLApi::glGetStringFn(GLenum name) {
const GLubyte* RealGLApi::glGetStringiFn(GLenum name, GLuint index) {
if (name == GL_EXTENSIONS && disabled_exts_.size()) {
-#if DCHECK_IS_ON()
- DCHECK(filtered_exts_initialized_);
-#endif
+ InitializeFilteredExtensionsIfNeeded();
if (index >= filtered_exts_.size()) {
- return NULL;
+ return nullptr;
}
return reinterpret_cast<const GLubyte*>(filtered_exts_[index].c_str());
}
@@ -356,6 +332,21 @@ void RealGLApi::glTexImage2DFn(GLenum target,
GetTexInternalFormat(version_.get(), internalformat, format, type);
GLenum gl_format = GetTexFormat(version_.get(), format);
GLenum gl_type = GetTexType(version_.get(), type);
+
+ // TODO(yizhou): Check if cubemap, 3d texture or texture2d array has the same
+ // bug on intel mac.
+ if (gl_workarounds_.reset_teximage2d_base_level && target == GL_TEXTURE_2D) {
+ GLint base_level = 0;
+ GLApiBase::glGetTexParameterivFn(target, GL_TEXTURE_BASE_LEVEL,
+ &base_level);
+ if (base_level) {
+ GLApiBase::glTexParameteriFn(target, GL_TEXTURE_BASE_LEVEL, 0);
+ GLApiBase::glTexImage2DFn(target, level, gl_internal_format, width,
+ height, border, gl_format, gl_type, pixels);
+ GLApiBase::glTexParameteriFn(target, GL_TEXTURE_BASE_LEVEL, base_level);
+ return;
+ }
+ }
GLApiBase::glTexImage2DFn(target, level, gl_internal_format, width, height,
border, gl_format, gl_type, pixels);
}
@@ -478,34 +469,47 @@ void RealGLApi::glDepthRangeFn(GLclampd z_near, GLclampd z_far) {
}
}
-void RealGLApi::InitializeFilteredExtensions() {
- if (disabled_exts_.size()) {
- filtered_exts_.clear();
- if (WillUseGLGetStringForExtensions(this)) {
- filtered_exts_str_ =
- FilterGLExtensionList(reinterpret_cast<const char*>(
- GLApiBase::glGetStringFn(GL_EXTENSIONS)),
- disabled_exts_);
- filtered_exts_ = base::SplitString(
- filtered_exts_str_, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
- } else {
- GLint num_extensions = 0;
- GLApiBase::glGetIntegervFn(GL_NUM_EXTENSIONS, &num_extensions);
- for (GLint i = 0; i < num_extensions; ++i) {
- const char* gl_extension = reinterpret_cast<const char*>(
- GLApiBase::glGetStringiFn(GL_EXTENSIONS, i));
- DCHECK(gl_extension != NULL);
- if (!base::ContainsValue(disabled_exts_, gl_extension))
- filtered_exts_.push_back(gl_extension);
- }
- filtered_exts_str_ = base::JoinString(filtered_exts_, " ");
+void RealGLApi::InitializeFilteredExtensionsIfNeeded() {
+ DCHECK(disabled_exts_.size());
+ if (filtered_exts_.size())
+ return;
+ DCHECK(filtered_exts_str_.empty());
+ if (WillUseGLGetStringForExtensions(this)) {
+ filtered_exts_str_ = FilterGLExtensionList(
+ reinterpret_cast<const char*>(GLApiBase::glGetStringFn(GL_EXTENSIONS)),
+ disabled_exts_);
+ filtered_exts_ = base::SplitString(
+ filtered_exts_str_, " ", base::TRIM_WHITESPACE, base::SPLIT_WANT_ALL);
+ } else {
+ GLint num_extensions = 0;
+ GLApiBase::glGetIntegervFn(GL_NUM_EXTENSIONS, &num_extensions);
+ for (GLint i = 0; i < num_extensions; ++i) {
+ const char* gl_extension = reinterpret_cast<const char*>(
+ GLApiBase::glGetStringiFn(GL_EXTENSIONS, i));
+ DCHECK(gl_extension);
+ if (!base::ContainsValue(disabled_exts_, gl_extension))
+ filtered_exts_.push_back(gl_extension);
}
-#if DCHECK_IS_ON()
- filtered_exts_initialized_ = true;
-#endif
+ filtered_exts_str_ = base::JoinString(filtered_exts_, " ");
}
}
+void RealGLApi::SetDisabledExtensions(const std::string& disabled_extensions) {
+ ClearCachedGLExtensions();
+ disabled_exts_.clear();
+ if (disabled_extensions.empty())
+ return;
+ disabled_exts_ =
+ base::SplitString(disabled_extensions, ", ;", base::KEEP_WHITESPACE,
+ base::SPLIT_WANT_NONEMPTY);
+ DCHECK(disabled_exts_.size());
+}
+
+void RealGLApi::ClearCachedGLExtensions() {
+ filtered_exts_.clear();
+ filtered_exts_str_.clear();
+}
+
void RealGLApi::set_gl_workarounds(const GLWorkarounds& workarounds) {
gl_workarounds_ = workarounds;
}
diff --git a/chromium/ui/gl/gl_gl_api_implementation.h b/chromium/ui/gl/gl_gl_api_implementation.h
index db0fcc720a2..e6311517adf 100644
--- a/chromium/ui/gl/gl_gl_api_implementation.h
+++ b/chromium/ui/gl/gl_gl_api_implementation.h
@@ -13,10 +13,6 @@
#include "ui/gl/gl_export.h"
#include "ui/gl/gl_workarounds.h"
-namespace base {
-class CommandLine;
-}
-
namespace gl {
struct GLVersionInfo;
@@ -53,8 +49,7 @@ class GL_EXPORT RealGLApi : public GLApiBase {
RealGLApi();
~RealGLApi() override;
void Initialize(DriverGL* driver);
- void InitializeWithCommandLine(DriverGL* driver,
- base::CommandLine* command_line);
+ void SetDisabledExtensions(const std::string& disabled_extensions) override;
void glGetIntegervFn(GLenum pname, GLint* params) override;
const GLubyte* glGetStringFn(GLenum name) override;
@@ -117,22 +112,21 @@ class GL_EXPORT RealGLApi : public GLApiBase {
void glClearDepthFn(GLclampd depth) override;
void glDepthRangeFn(GLclampd z_near, GLclampd z_far) override;
- void InitializeFilteredExtensions();
void set_gl_workarounds(const GLWorkarounds& workarounds);
void set_version(std::unique_ptr<GLVersionInfo> version);
+ void ClearCachedGLExtensions();
private:
- // Filtered GL_EXTENSIONS we return to glGetString(i) calls.
+ // Compute |filtered_exts_| & |filtered_exts_str_| from |disabled_ext_|.
+ void InitializeFilteredExtensionsIfNeeded();
+
std::vector<std::string> disabled_exts_;
+ // Filtered GL_EXTENSIONS we return to glGetString(i) calls.
std::vector<std::string> filtered_exts_;
std::string filtered_exts_str_;
GLWorkarounds gl_workarounds_;
std::unique_ptr<GLVersionInfo> version_;
-
-#if DCHECK_IS_ON()
- bool filtered_exts_initialized_;
-#endif
};
// Inserts a TRACE for every GL call.
diff --git a/chromium/ui/gl/gl_glx_api_implementation.cc b/chromium/ui/gl/gl_glx_api_implementation.cc
index 413a385f2e6..d7903a2654d 100644
--- a/chromium/ui/gl/gl_glx_api_implementation.cc
+++ b/chromium/ui/gl/gl_glx_api_implementation.cc
@@ -7,7 +7,9 @@
#include "base/command_line.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
+#include "ui/gl/gl_context.h"
#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_surface_glx.h"
namespace gl {
@@ -21,7 +23,6 @@ void InitializeStaticGLBindingsGLX() {
}
g_real_glx->Initialize(&g_driver_glx);
g_current_glx_context = g_real_glx;
- g_driver_glx.InitializeExtensionBindings();
}
void InitializeDebugGLBindingsGLX() {
@@ -68,16 +69,10 @@ RealGLXApi::~RealGLXApi() {
}
void RealGLXApi::Initialize(DriverGLX* driver) {
- InitializeWithCommandLine(driver, base::CommandLine::ForCurrentProcess());
-}
-
-void RealGLXApi::InitializeWithCommandLine(DriverGLX* driver,
- base::CommandLine* command_line) {
- DCHECK(command_line);
InitializeBase(driver);
+}
- const std::string disabled_extensions = command_line->GetSwitchValueASCII(
- switches::kDisableGLExtensions);
+void RealGLXApi::SetDisabledExtensions(const std::string& disabled_extensions) {
disabled_exts_.clear();
filtered_exts_ = "";
if (!disabled_extensions.empty()) {
@@ -105,11 +100,26 @@ const char* RealGLXApi::glXQueryExtensionsStringFn(Display* dpy,
}
DebugGLXApi::DebugGLXApi(GLXApi* glx_api) : glx_api_(glx_api) {}
+
DebugGLXApi::~DebugGLXApi() {}
+void DebugGLXApi::SetDisabledExtensions(
+ const std::string& disabled_extensions) {
+ if (glx_api_) {
+ glx_api_->SetDisabledExtensions(disabled_extensions);
+ }
+}
+
TraceGLXApi::~TraceGLXApi() {
}
+void TraceGLXApi::SetDisabledExtensions(
+ const std::string& disabled_extensions) {
+ if (glx_api_) {
+ glx_api_->SetDisabledExtensions(disabled_extensions);
+ }
+}
+
bool GetGLWindowSystemBindingInfoGLX(GLWindowSystemBindingInfo* info) {
Display* display = glXGetCurrentDisplay();
const int kDefaultScreen = 0;
@@ -130,4 +140,14 @@ bool GetGLWindowSystemBindingInfoGLX(GLWindowSystemBindingInfo* info) {
return true;
}
+void SetDisabledExtensionsGLX(const std::string& disabled_extensions) {
+ DCHECK(g_current_glx_context);
+ DCHECK(GLContext::TotalGLContexts() == 0);
+ g_current_glx_context->SetDisabledExtensions(disabled_extensions);
+}
+
+bool InitializeExtensionSettingsOneOffGLX() {
+ return GLSurfaceGLX::InitializeExtensionSettingsOneOff();
+}
+
} // namespace gl
diff --git a/chromium/ui/gl/gl_glx_api_implementation.h b/chromium/ui/gl/gl_glx_api_implementation.h
index 2c1815757ca..f3ac47ec91c 100644
--- a/chromium/ui/gl/gl_glx_api_implementation.h
+++ b/chromium/ui/gl/gl_glx_api_implementation.h
@@ -5,15 +5,13 @@
#ifndef UI_GL_GL_GLX_API_IMPLEMENTATION_H_
#define UI_GL_GL_GLX_API_IMPLEMENTATION_H_
+#include <string>
#include <vector>
#include "base/compiler_specific.h"
#include "gl_bindings.h"
#include "ui/gl/gl_export.h"
-namespace base {
-class CommandLine;
-}
namespace gl {
struct GLWindowSystemBindingInfo;
@@ -22,6 +20,8 @@ GL_EXPORT void InitializeStaticGLBindingsGLX();
GL_EXPORT void InitializeDebugGLBindingsGLX();
GL_EXPORT void ClearBindingsGLX();
GL_EXPORT bool GetGLWindowSystemBindingInfoGLX(GLWindowSystemBindingInfo* info);
+GL_EXPORT void SetDisabledExtensionsGLX(const std::string& disabled_extensions);
+GL_EXPORT bool InitializeExtensionSettingsOneOffGLX();
class GL_EXPORT GLXApiBase : public GLXApi {
public:
@@ -43,8 +43,7 @@ class GL_EXPORT RealGLXApi : public GLXApiBase {
RealGLXApi();
~RealGLXApi() override;
void Initialize(DriverGLX* driver);
- void InitializeWithCommandLine(DriverGLX* driver,
- base::CommandLine* command_line);
+ void SetDisabledExtensions(const std::string& disabled_extensions) override;
const char* glXQueryExtensionsStringFn(Display* dpy, int screen) override;
private:
@@ -59,6 +58,8 @@ class GL_EXPORT DebugGLXApi : public GLXApi {
DebugGLXApi(GLXApi* glx_api);
~DebugGLXApi() override;
+ void SetDisabledExtensions(const std::string& disabled_extensions) override;
+
// Include the auto-generated part of this class. We split this because
// it means we can easily edit the non-auto generated parts right here in
// this file instead of having to edit some template or the code generator.
@@ -74,6 +75,8 @@ class GL_EXPORT TraceGLXApi : public GLXApi {
TraceGLXApi(GLXApi* glx_api) : glx_api_(glx_api) { }
~TraceGLXApi() override;
+ void SetDisabledExtensions(const std::string& disabled_extensions) override;
+
// Include the auto-generated part of this class. We split this because
// it means we can easily edit the non-auto generated parts right here in
// this file instead of having to edit some template or the code generator.
@@ -86,6 +89,3 @@ class GL_EXPORT TraceGLXApi : public GLXApi {
} // namespace gl
#endif // UI_GL_GL_GLX_API_IMPLEMENTATION_H_
-
-
-
diff --git a/chromium/ui/gl/gl_image.h b/chromium/ui/gl/gl_image.h
index 3e34bbf32b0..c29eff60d28 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 "ui/gfx/color_space.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
@@ -96,9 +97,17 @@ class GL_EXPORT GLImage : public base::RefCounted<GLImage> {
enum class Type { NONE, MEMORY, IOSURFACE, DXGI_IMAGE };
virtual Type GetType() const;
+ void SetColorSpaceForScanout(const gfx::ColorSpace& color_space) {
+ color_space_ = color_space;
+ }
+
+ const gfx::ColorSpace& color_space() const { return color_space_; }
+
protected:
virtual ~GLImage() {}
+ gfx::ColorSpace color_space_;
+
private:
friend class base::RefCounted<GLImage>;
diff --git a/chromium/ui/gl/gl_image_io_surface.h b/chromium/ui/gl/gl_image_io_surface.h
index 9cffcec6254..bf5f0699d96 100644
--- a/chromium/ui/gl/gl_image_io_surface.h
+++ b/chromium/ui/gl/gl_image_io_surface.h
@@ -71,6 +71,11 @@ class GL_EXPORT GLImageIOSurface : public GLImage {
// signal about whether the Window Server is still using the IOSurface.
bool CanCheckIOSurfaceIsInUse() const;
+ // For IOSurfaces that need manual conversion to a GL texture before being
+ // sampled from, specify the color space in which to do the required YUV to
+ // RGB transformation.
+ void SetColorSpaceForYUVToRGBConversion(const gfx::ColorSpace& color_space);
+
static unsigned GetInternalFormatForTesting(gfx::BufferFormat format);
// Downcasts from |image|. Returns |nullptr| on failure.
@@ -97,6 +102,8 @@ class GL_EXPORT GLImageIOSurface : public GLImage {
base::ScopedCFTypeRef<CVPixelBufferRef> cv_pixel_buffer_;
gfx::GenericSharedMemoryId io_surface_id_;
base::ThreadChecker thread_checker_;
+ // The default value of Rec. 601 is based on historical shader code.
+ gfx::ColorSpace color_space_for_yuv_to_rgb_ = gfx::ColorSpace::CreateREC601();
DISALLOW_COPY_AND_ASSIGN(GLImageIOSurface);
};
diff --git a/chromium/ui/gl/gl_image_io_surface.mm b/chromium/ui/gl/gl_image_io_surface.mm
index c9fabee5a26..1dc5a6dbf1f 100644
--- a/chromium/ui/gl/gl_image_io_surface.mm
+++ b/chromium/ui/gl/gl_image_io_surface.mm
@@ -14,6 +14,7 @@
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/process_memory_dump.h"
#include "base/trace_event/trace_event.h"
+#include "ui/gfx/color_space.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/scoped_binders.h"
@@ -298,7 +299,8 @@ bool GLImageIOSurface::CopyTexImage(unsigned target) {
GLContext* gl_context = GLContext::GetCurrent();
DCHECK(gl_context);
- YUVToRGBConverter* yuv_to_rgb_converter = gl_context->GetYUVToRGBConverter();
+ YUVToRGBConverter* yuv_to_rgb_converter =
+ gl_context->GetYUVToRGBConverter(color_space_for_yuv_to_rgb_);
DCHECK(yuv_to_rgb_converter);
// Note that state restoration is done explicitly instead of scoped binders to
@@ -405,6 +407,13 @@ bool GLImageIOSurface::CanCheckIOSurfaceIsInUse() const {
return !cv_pixel_buffer_;
}
+void GLImageIOSurface::SetColorSpaceForYUVToRGBConversion(
+ const gfx::ColorSpace& color_space) {
+ DCHECK(color_space.IsValid());
+ DCHECK_NE(color_space, color_space.GetAsFullRangeRGB());
+ color_space_for_yuv_to_rgb_ = color_space;
+}
+
base::ScopedCFTypeRef<IOSurfaceRef> GLImageIOSurface::io_surface() {
return io_surface_;
}
diff --git a/chromium/ui/gl/gl_image_io_surface_unittest.cc b/chromium/ui/gl/gl_image_io_surface_unittest.cc
index 31dd78b8280..a55e63f1697 100644
--- a/chromium/ui/gl/gl_image_io_surface_unittest.cc
+++ b/chromium/ui/gl/gl_image_io_surface_unittest.cc
@@ -14,10 +14,10 @@
namespace gl {
namespace {
-// These values are picked so that RGB -> YUV on the CPU converted
-// back to RGB on the GPU produces the original RGB values without
-// any error.
-const uint8_t kYuvImageColor[] = {0x10, 0x20, 0, 0xFF};
+// These values are picked so that RGB -> YUV on the CPU converted back to RGB
+// on the GPU produces the original RGB values without any error. Note that
+// some values will be off-by-one.
+const uint8_t kYuvImageColor[] = {0x30, 0x40, 0x10, 0xFF};
template <gfx::BufferFormat format>
class GLImageIOSurfaceTestDelegate {
diff --git a/chromium/ui/gl/gl_image_shared_memory.cc b/chromium/ui/gl/gl_image_shared_memory.cc
index cef422b4a16..3b832c9e04e 100644
--- a/chromium/ui/gl/gl_image_shared_memory.cc
+++ b/chromium/ui/gl/gl_image_shared_memory.cc
@@ -13,7 +13,6 @@
#include "base/trace_event/memory_dump_manager.h"
#include "base/trace_event/process_memory_dump.h"
#include "ui/gfx/buffer_format_util.h"
-#include "ui/gfx/gpu_memory_buffer_tracing.h"
namespace gl {
@@ -87,11 +86,9 @@ void GLImageSharedMemory::OnMemoryDump(
base::trace_event::MemoryAllocatorDump::kUnitsBytes,
static_cast<uint64_t>(size_in_bytes));
- auto guid =
- gfx::GetSharedMemoryGUIDForTracing(process_tracing_id, shared_memory_id_);
auto shared_memory_guid = shared_memory_->mapped_id();
if (!shared_memory_guid.is_empty()) {
- pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), guid, shared_memory_guid,
+ pmd->CreateSharedMemoryOwnershipEdge(dump->guid(), shared_memory_guid,
0 /* importance */);
}
}
diff --git a/chromium/ui/gl/gl_image_stub.cc b/chromium/ui/gl/gl_image_stub.cc
index 5bfd62be2f7..3d99c4e7eec 100644
--- a/chromium/ui/gl/gl_image_stub.cc
+++ b/chromium/ui/gl/gl_image_stub.cc
@@ -21,13 +21,13 @@ unsigned GLImageStub::GetInternalFormat() { return GL_RGBA; }
bool GLImageStub::BindTexImage(unsigned target) { return true; }
bool GLImageStub::CopyTexImage(unsigned target) {
- return true;
+ return false;
}
bool GLImageStub::CopyTexSubImage(unsigned target,
const gfx::Point& offset,
const gfx::Rect& rect) {
- return true;
+ return false;
}
bool GLImageStub::ScheduleOverlayPlane(gfx::AcceleratedWidget widget,
diff --git a/chromium/ui/gl/gl_implementation.cc b/chromium/ui/gl/gl_implementation.cc
index 8942d7e8733..c97e8f37bfd 100644
--- a/chromium/ui/gl/gl_implementation.cc
+++ b/chromium/ui/gl/gl_implementation.cc
@@ -82,7 +82,11 @@ GLImplementation GetNamedGLImplementation(const std::string& name) {
}
GLImplementation GetSoftwareGLImplementation() {
+#if defined(OS_WIN)
+ return kGLImplementationSwiftShaderGL;
+#else
return kGLImplementationOSMesaGL;
+#endif
}
const char* GetGLImplementationName(GLImplementation implementation) {
@@ -225,14 +229,6 @@ bool WillUseGLGetStringForExtensions(GLApi* api) {
return is_es || major_version < 3;
}
-std::unique_ptr<GLVersionInfo> GetVersionInfoFromContext(GLApi* api) {
- std::string extensions = GetGLExtensionsFromCurrentContext(api);
- return base::MakeUnique<GLVersionInfo>(
- reinterpret_cast<const char*>(api->glGetStringFn(GL_VERSION)),
- reinterpret_cast<const char*>(api->glGetStringFn(GL_RENDERER)),
- extensions.c_str());
-}
-
base::NativeLibrary LoadLibraryAndPrintError(
const base::FilePath::CharType* filename) {
return LoadLibraryAndPrintError(base::FilePath(filename));
diff --git a/chromium/ui/gl/gl_implementation.h b/chromium/ui/gl/gl_implementation.h
index 28cbde27188..507b39fbf10 100644
--- a/chromium/ui/gl/gl_implementation.h
+++ b/chromium/ui/gl/gl_implementation.h
@@ -18,7 +18,6 @@
namespace gl {
class GLApi;
-struct GLVersionInfo;
// The GL implementation currently in use.
enum GLImplementation {
@@ -126,8 +125,6 @@ GL_EXPORT std::string GetGLExtensionsFromCurrentContext(GLApi* api);
GL_EXPORT bool WillUseGLGetStringForExtensions();
GL_EXPORT bool WillUseGLGetStringForExtensions(GLApi* api);
-GL_EXPORT std::unique_ptr<GLVersionInfo> GetVersionInfoFromContext(GLApi* api);
-
// Helpers to load a library and log error on failure.
GL_EXPORT base::NativeLibrary LoadLibraryAndPrintError(
const base::FilePath::CharType* filename);
diff --git a/chromium/ui/gl/gl_mock_autogen_gl.h b/chromium/ui/gl/gl_mock_autogen_gl.h
index 60f96b0b58a..4e89f056eee 100644
--- a/chromium/ui/gl/gl_mock_autogen_gl.h
+++ b/chromium/ui/gl/gl_mock_autogen_gl.h
@@ -515,6 +515,7 @@ MOCK_METHOD6(GetInternalformativRobustANGLE,
GLsizei bufSize,
GLsizei* length,
GLint* params));
+MOCK_METHOD3(GetMultisamplefv, void(GLenum pname, GLuint index, GLfloat* val));
MOCK_METHOD5(GetMultisamplefvRobustANGLE,
void(GLenum pname,
GLuint index,
@@ -876,6 +877,7 @@ MOCK_METHOD3(PathStencilFuncNV, void(GLenum func, GLint ref, GLuint mask));
MOCK_METHOD0(PauseTransformFeedback, void());
MOCK_METHOD2(PixelStorei, void(GLenum pname, GLint param));
MOCK_METHOD2(PointParameteri, void(GLenum pname, GLint param));
+MOCK_METHOD2(PolygonMode, void(GLenum face, GLenum mode));
MOCK_METHOD2(PolygonOffset, void(GLfloat factor, GLfloat units));
MOCK_METHOD0(PopDebugGroup, void());
MOCK_METHOD0(PopGroupMarkerEXT, void());
@@ -1032,6 +1034,14 @@ MOCK_METHOD4(StencilThenCoverStrokePathNV,
void(GLuint path, GLint reference, GLuint mask, GLenum coverMode));
MOCK_METHOD1(TestFenceAPPLE, GLboolean(GLuint fence));
MOCK_METHOD1(TestFenceNV, GLboolean(GLuint fence));
+MOCK_METHOD3(TexBuffer,
+ void(GLenum target, GLenum internalformat, GLuint buffer));
+MOCK_METHOD5(TexBufferRange,
+ void(GLenum target,
+ GLenum internalformat,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size));
MOCK_METHOD9(TexImage2D,
void(GLenum target,
GLint level,
@@ -1237,4 +1247,4 @@ MOCK_METHOD6(VertexAttribPointer,
GLsizei stride,
const void* ptr));
MOCK_METHOD4(Viewport, void(GLint x, GLint y, GLsizei width, GLsizei height));
-MOCK_METHOD3(WaitSync, GLenum(GLsync sync, GLbitfield flags, GLuint64 timeout));
+MOCK_METHOD3(WaitSync, void(GLsync sync, GLbitfield flags, GLuint64 timeout));
diff --git a/chromium/ui/gl/gl_stub_api.cc b/chromium/ui/gl/gl_stub_api.cc
index c7ce0ba6f7b..e73f87a611d 100644
--- a/chromium/ui/gl/gl_stub_api.cc
+++ b/chromium/ui/gl/gl_stub_api.cc
@@ -336,10 +336,4 @@ GLboolean GLStubApi::glUnmapBufferFn(GLenum target) {
return GL_TRUE;
}
-GLenum GLStubApi::glWaitSyncFn(GLsync sync,
- GLbitfield flags,
- GLuint64 timeout) {
- return GL_TRUE;
-}
-
} // namespace gl
diff --git a/chromium/ui/gl/gl_stub_api.h b/chromium/ui/gl/gl_stub_api.h
index 4c9f8ad2d64..01bd331346f 100644
--- a/chromium/ui/gl/gl_stub_api.h
+++ b/chromium/ui/gl/gl_stub_api.h
@@ -70,9 +70,6 @@ class GL_EXPORT GLStubApi: public GLStubApiBase {
GLboolean glTestFenceAPPLEFn(GLuint fence) override;
GLboolean glTestFenceNVFn(GLuint fence) override;
GLboolean glUnmapBufferFn(GLenum target) override;
- GLenum glWaitSyncFn(GLsync sync,
- GLbitfield flags,
- GLuint64 timeout) override;
private:
std::string version_;
diff --git a/chromium/ui/gl/gl_stub_autogen_gl.cc b/chromium/ui/gl/gl_stub_autogen_gl.cc
index 95f664301f6..e30dbfd7eaf 100644
--- a/chromium/ui/gl/gl_stub_autogen_gl.cc
+++ b/chromium/ui/gl/gl_stub_autogen_gl.cc
@@ -164,10 +164,4 @@ GLboolean GLStubApiBase::glUnmapBufferFn(GLenum target) {
return 0;
}
-GLenum GLStubApiBase::glWaitSyncFn(GLsync sync,
- GLbitfield flags,
- GLuint64 timeout) {
- return 0;
-}
-
} // namespace gl
diff --git a/chromium/ui/gl/gl_stub_autogen_gl.h b/chromium/ui/gl/gl_stub_autogen_gl.h
index e14d946a831..c0097ebf94e 100644
--- a/chromium/ui/gl/gl_stub_autogen_gl.h
+++ b/chromium/ui/gl/gl_stub_autogen_gl.h
@@ -531,6 +531,7 @@ void glGetInternalformativRobustANGLEFn(GLenum target,
GLsizei bufSize,
GLsizei* length,
GLint* params) override {}
+void glGetMultisamplefvFn(GLenum pname, GLuint index, GLfloat* val) override {}
void glGetMultisamplefvRobustANGLEFn(GLenum pname,
GLuint index,
GLsizei bufSize,
@@ -873,6 +874,7 @@ void glPathStencilFuncNVFn(GLenum func, GLint ref, GLuint mask) override {}
void glPauseTransformFeedbackFn() override {}
void glPixelStoreiFn(GLenum pname, GLint param) override {}
void glPointParameteriFn(GLenum pname, GLint param) override {}
+void glPolygonModeFn(GLenum face, GLenum mode) override {}
void glPolygonOffsetFn(GLfloat factor, GLfloat units) override {}
void glPopDebugGroupFn() override {}
void glPopGroupMarkerEXTFn() override {}
@@ -1055,6 +1057,14 @@ void glStencilThenCoverStrokePathNVFn(GLuint path,
GLenum coverMode) override {}
GLboolean glTestFenceAPPLEFn(GLuint fence) override;
GLboolean glTestFenceNVFn(GLuint fence) override;
+void glTexBufferFn(GLenum target,
+ GLenum internalformat,
+ GLuint buffer) override {}
+void glTexBufferRangeFn(GLenum target,
+ GLenum internalformat,
+ GLuint buffer,
+ GLintptr offset,
+ GLsizeiptr size) override {}
void glTexImage2DFn(GLenum target,
GLint level,
GLint internalformat,
@@ -1292,4 +1302,4 @@ void glVertexAttribPointerFn(GLuint indx,
GLsizei stride,
const void* ptr) override {}
void glViewportFn(GLint x, GLint y, GLsizei width, GLsizei height) override {}
-GLenum glWaitSyncFn(GLsync sync, GLbitfield flags, GLuint64 timeout) override;
+void glWaitSyncFn(GLsync sync, GLbitfield flags, GLuint64 timeout) override {}
diff --git a/chromium/ui/gl/gl_surface.cc b/chromium/ui/gl/gl_surface.cc
index 67671902974..7ed029bb8f7 100644
--- a/chromium/ui/gl/gl_surface.cc
+++ b/chromium/ui/gl/gl_surface.cc
@@ -38,6 +38,7 @@ bool GLSurface::Initialize(GLSurfaceFormat format) {
bool GLSurface::Resize(const gfx::Size& size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha) {
NOTIMPLEMENTED();
return false;
@@ -182,6 +183,10 @@ bool GLSurface::SupportsDCLayers() const {
return false;
}
+bool GLSurface::UseOverlaysForVideo() const {
+ return false;
+}
+
bool GLSurface::SetDrawRectangle(const gfx::Rect& rect) {
return false;
}
@@ -238,8 +243,9 @@ void GLSurfaceAdapter::Destroy() {
bool GLSurfaceAdapter::Resize(const gfx::Size& size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha) {
- return surface_->Resize(size, scale_factor, has_alpha);
+ return surface_->Resize(size, scale_factor, color_space, has_alpha);
}
bool GLSurfaceAdapter::Recreate() {
@@ -391,6 +397,10 @@ bool GLSurfaceAdapter::SupportsDCLayers() const {
return surface_->SupportsDCLayers();
}
+bool GLSurfaceAdapter::UseOverlaysForVideo() const {
+ return surface_->UseOverlaysForVideo();
+}
+
bool GLSurfaceAdapter::SetDrawRectangle(const gfx::Rect& rect) {
return surface_->SetDrawRectangle(rect);
}
diff --git a/chromium/ui/gl/gl_surface.h b/chromium/ui/gl/gl_surface.h
index 5261d7c3b0b..5bc78d8a6cd 100644
--- a/chromium/ui/gl/gl_surface.h
+++ b/chromium/ui/gl/gl_surface.h
@@ -57,8 +57,17 @@ class GL_EXPORT GLSurface : public base::RefCounted<GLSurface> {
// Destroys the surface.
virtual void Destroy() = 0;
+ // Color spaces that can be dynamically specified to the surface when resized.
+ enum class ColorSpace {
+ UNSPECIFIED,
+ SRGB,
+ DISPLAY_P3,
+ SCRGB_LINEAR,
+ };
+
virtual bool Resize(const gfx::Size& size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha);
// Recreate the surface without changing the size.
@@ -213,6 +222,8 @@ class GL_EXPORT GLSurface : public base::RefCounted<GLSurface> {
virtual bool SupportsDCLayers() const;
+ virtual bool UseOverlaysForVideo() const;
+
// Set the rectangle that will be drawn into on the surface.
virtual bool SetDrawRectangle(const gfx::Rect& rect);
@@ -254,6 +265,7 @@ class GL_EXPORT GLSurfaceAdapter : public GLSurface {
void Destroy() override;
bool Resize(const gfx::Size& size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha) override;
bool Recreate() override;
bool DeferDraws() override;
@@ -298,6 +310,7 @@ class GL_EXPORT GLSurfaceAdapter : public GLSurface {
bool FlipsVertically() const override;
bool BuffersFlipped() const override;
bool SupportsDCLayers() const override;
+ bool UseOverlaysForVideo() const override;
bool SetDrawRectangle(const gfx::Rect& rect) override;
gfx::Vector2d GetDrawOffset() const override;
void WaitForSnapshotRendering() override;
diff --git a/chromium/ui/gl/gl_surface_egl.cc b/chromium/ui/gl/gl_surface_egl.cc
index e51132ae38f..17c46a68408 100644
--- a/chromium/ui/gl/gl_surface_egl.cc
+++ b/chromium/ui/gl/gl_surface_egl.cc
@@ -34,7 +34,7 @@
#include "ui/gl/scoped_make_current.h"
#include "ui/gl/sync_control_vsync_provider.h"
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#if defined(USE_X11)
extern "C" {
#include <X11/Xlib.h>
#define Status int
@@ -144,6 +144,9 @@ bool g_egl_context_priority_supported = false;
bool g_egl_khr_colorspace = false;
bool g_egl_ext_colorspace_display_p3 = false;
bool g_use_direct_composition = false;
+bool g_egl_robust_resource_init_supported = false;
+bool g_egl_display_texture_share_group_supported = false;
+bool g_egl_create_context_client_arrays_supported = false;
class EGLSyncControlVSyncProvider : public SyncControlVSyncProvider {
public:
@@ -204,7 +207,7 @@ EGLDisplay GetPlatformANGLEDisplay(EGLNativeDisplayType native_display,
display_attribs.push_back(EGL_TRUE);
}
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#if defined(USE_X11)
// ANGLE_NULL doesn't use the visual, and may run without X11 where we can't
// get it anyway.
if (platform_type != EGL_PLATFORM_ANGLE_TYPE_NULL_ANGLE) {
@@ -314,7 +317,7 @@ EGLConfig ChooseConfig(GLSurfaceFormat format, bool surfaceless) {
EGLint stencil_size = format.GetStencilBits();
EGLint samples = format.GetSamples();
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#if defined(USE_X11)
// If we're using ANGLE_NULL, we may not have a display, in which case we
// can't use XVisualManager.
if (g_native_display) {
@@ -575,6 +578,11 @@ bool GLSurfaceEGL::InitializeOneOff(EGLNativeDisplayType native_display) {
!base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDisableDirectComposition);
+ g_egl_display_texture_share_group_supported =
+ HasEGLExtension("EGL_ANGLE_display_texture_share_group");
+ g_egl_create_context_client_arrays_supported =
+ HasEGLExtension("EGL_ANGLE_create_context_client_arrays");
+
// TODO(oetuaho@nvidia.com): Surfaceless is disabled on Android as a temporary
// workaround, since code written for Android WebView takes different paths
// based on whether GL surface objects have underlying EGL surface handles,
@@ -603,14 +611,24 @@ bool GLSurfaceEGL::InitializeOneOff(EGLNativeDisplayType native_display) {
}
}
#endif
+
initialized_ = true;
+ return true;
+}
+
+// static
+bool GLSurfaceEGL::InitializeExtensionSettingsOneOff() {
+ if (!initialized_)
+ return false;
+ g_driver_egl.UpdateConditionalExtensionBindings();
+ g_egl_extensions = eglQueryString(g_display, EGL_EXTENSIONS);
return true;
}
// static
void GLSurfaceEGL::ShutdownOneOff() {
- ResetANGLEPlatform(g_display);
+ angle::ResetPlatform(g_display);
if (g_display != EGL_NO_DISPLAY)
eglTerminate(g_display);
@@ -625,6 +643,9 @@ void GLSurfaceEGL::ShutdownOneOff() {
g_egl_surface_orientation_supported = false;
g_use_direct_composition = false;
g_egl_surfaceless_context_supported = false;
+ g_egl_robust_resource_init_supported = false;
+ g_egl_display_texture_share_group_supported = false;
+ g_egl_create_context_client_arrays_supported = false;
initialized_ = false;
}
@@ -677,6 +698,18 @@ bool GLSurfaceEGL::IsDirectCompositionSupported() {
return g_use_direct_composition;
}
+bool GLSurfaceEGL::IsRobustResourceInitSupported() {
+ return g_egl_robust_resource_init_supported;
+}
+
+bool GLSurfaceEGL::IsDisplayTextureShareGroupSupported() {
+ return g_egl_display_texture_share_group_supported;
+}
+
+bool GLSurfaceEGL::IsCreateContextClientArraysSupported() {
+ return g_egl_create_context_client_arrays_supported;
+}
+
GLSurfaceEGL::~GLSurfaceEGL() {}
// InitializeDisplay is necessary because the static binding code
@@ -709,12 +742,12 @@ EGLDisplay GLSurfaceEGL::InitializeDisplay(
ExtensionsContain(client_extensions, "EGL_ANGLE_platform_angle_null");
}
- bool supports_robust_resource_init =
+ g_egl_robust_resource_init_supported =
client_extensions &&
ExtensionsContain(client_extensions,
"EGL_ANGLE_display_robust_resource_initialization");
bool use_robust_resource_init =
- supports_robust_resource_init &&
+ g_egl_robust_resource_init_supported &&
UsePassthroughCommandDecoder(base::CommandLine::ForCurrentProcess());
std::vector<DisplayType> init_displays;
@@ -733,7 +766,7 @@ EGLDisplay GLSurfaceEGL::InitializeDisplay(
// Init ANGLE platform now that we have the global display.
if (supports_angle_d3d || supports_angle_opengl || supports_angle_null) {
- if (!InitializeANGLEPlatform(display)) {
+ if (!angle::InitializePlatform(display)) {
LOG(ERROR) << "ANGLE Platform initialization failed.";
}
}
@@ -941,6 +974,7 @@ gfx::Size NativeViewGLSurfaceEGL::GetSize() {
bool NativeViewGLSurfaceEGL::Resize(const gfx::Size& size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha) {
if (size == GetSize())
return true;
@@ -1177,6 +1211,7 @@ gfx::Size PbufferGLSurfaceEGL::GetSize() {
bool PbufferGLSurfaceEGL::Resize(const gfx::Size& size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha) {
if (size == size_)
return true;
@@ -1260,6 +1295,7 @@ gfx::Size SurfacelessEGL::GetSize() {
bool SurfacelessEGL::Resize(const gfx::Size& size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha) {
size_ = size;
return true;
diff --git a/chromium/ui/gl/gl_surface_egl.h b/chromium/ui/gl/gl_surface_egl.h
index 779b5a6bfb8..042bf077d21 100644
--- a/chromium/ui/gl/gl_surface_egl.h
+++ b/chromium/ui/gl/gl_surface_egl.h
@@ -58,6 +58,7 @@ class GL_EXPORT GLSurfaceEGL : public GLSurface {
GLSurfaceFormat GetFormat() override;
static bool InitializeOneOff(EGLNativeDisplayType native_display);
+ static bool InitializeExtensionSettingsOneOff();
static void ShutdownOneOff();
static EGLDisplay GetHardwareDisplay();
static EGLDisplay InitializeDisplay(EGLNativeDisplayType native_display);
@@ -74,6 +75,9 @@ class GL_EXPORT GLSurfaceEGL : public GLSurface {
static bool IsEGLSurfacelessContextSupported();
static bool IsEGLContextPrioritySupported();
static bool IsDirectCompositionSupported();
+ static bool IsRobustResourceInitSupported();
+ static bool IsDisplayTextureShareGroupSupported();
+ static bool IsCreateContextClientArraysSupported();
protected:
~GLSurfaceEGL() override;
@@ -98,6 +102,7 @@ class GL_EXPORT NativeViewGLSurfaceEGL : public GLSurfaceEGL {
void Destroy() override;
bool Resize(const gfx::Size& size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha) override;
bool Recreate() override;
bool IsOffscreen() override;
@@ -160,6 +165,7 @@ class GL_EXPORT PbufferGLSurfaceEGL : public GLSurfaceEGL {
gfx::Size GetSize() override;
bool Resize(const gfx::Size& size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha) override;
EGLSurface GetHandle() override;
void* GetShareHandle() override;
@@ -190,6 +196,7 @@ class GL_EXPORT SurfacelessEGL : public GLSurfaceEGL {
gfx::Size GetSize() override;
bool Resize(const gfx::Size& size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha) override;
EGLSurface GetHandle() override;
void* GetShareHandle() override;
diff --git a/chromium/ui/gl/gl_surface_egl_unittest.cc b/chromium/ui/gl/gl_surface_egl_unittest.cc
index 2bb9057e131..5d2dad9c0a5 100644
--- a/chromium/ui/gl/gl_surface_egl_unittest.cc
+++ b/chromium/ui/gl/gl_surface_egl_unittest.cc
@@ -77,7 +77,7 @@ TEST(GLSurfaceEGLTest, FixedSizeExtension) {
EXPECT_EQ(window_size, surface->GetSize());
gfx::Size resize_size(200, 300);
- surface->Resize(resize_size, 1.0, false);
+ surface->Resize(resize_size, 1.0, GLSurface::ColorSpace::UNSPECIFIED, false);
EXPECT_EQ(resize_size, surface->GetSize());
}
diff --git a/chromium/ui/gl/gl_surface_egl_x11.cc b/chromium/ui/gl/gl_surface_egl_x11.cc
index a72b45bf0dc..4d0cd09010e 100644
--- a/chromium/ui/gl/gl_surface_egl_x11.cc
+++ b/chromium/ui/gl/gl_surface_egl_x11.cc
@@ -144,6 +144,7 @@ EGLConfig NativeViewGLSurfaceEGLX11::GetConfig() {
bool NativeViewGLSurfaceEGLX11::Resize(const gfx::Size& size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha) {
if (size == GetSize())
return true;
diff --git a/chromium/ui/gl/gl_surface_egl_x11.h b/chromium/ui/gl/gl_surface_egl_x11.h
index f84ba41cab1..999d5b7ae79 100644
--- a/chromium/ui/gl/gl_surface_egl_x11.h
+++ b/chromium/ui/gl/gl_surface_egl_x11.h
@@ -27,6 +27,7 @@ class GL_EXPORT NativeViewGLSurfaceEGLX11 : public NativeViewGLSurfaceEGL,
void Destroy() override;
bool Resize(const gfx::Size& size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha) override;
bool InitializeNativeWindow() override;
diff --git a/chromium/ui/gl/gl_surface_glx.cc b/chromium/ui/gl/gl_surface_glx.cc
index 4c0afc9d2c1..c656c109161 100644
--- a/chromium/ui/gl/gl_surface_glx.cc
+++ b/chromium/ui/gl/gl_surface_glx.cc
@@ -383,25 +383,31 @@ GLXContext SGIVideoSyncProviderThreadShim::context_ = 0;
} // namespace
+bool GLSurfaceGLX::initialized_ = false;
+
GLSurfaceGLX::GLSurfaceGLX() {}
bool GLSurfaceGLX::InitializeOneOff() {
- static bool initialized = false;
- if (initialized)
+ if (initialized_)
return true;
// http://crbug.com/245466
setenv("force_s3tc_enable", "true", 1);
+ {
+ // As a hack to avoid sandbox threading violation on certain NVidia drivers,
+ // this block of code needs to be put before gfx::InitializeThreadedX11().
+ // See crbug.com/756885.
+ g_display = gfx::GetXDisplay();
+ if (!g_display) {
+ LOG(ERROR) << "XOpenDisplay failed.";
+ return false;
+ }
+ glXQueryExtensionsString(g_display, 0);
+ }
// SGIVideoSyncProviderShim (if instantiated) will issue X commands on
// it's own thread.
gfx::InitializeThreadedX11();
- g_display = gfx::GetXDisplay();
-
- if (!g_display) {
- LOG(ERROR) << "XOpenDisplay failed.";
- return false;
- }
int major, minor;
if (!glXQueryVersion(g_display, &major, &minor)) {
@@ -414,21 +420,6 @@ bool GLSurfaceGLX::InitializeOneOff() {
return false;
}
- g_glx_context_create = HasGLXExtension("GLX_ARB_create_context");
- g_glx_create_context_robustness_supported =
- HasGLXExtension("GLX_ARB_create_context_robustness");
- g_glx_create_context_profile_supported =
- HasGLXExtension("GLX_ARB_create_context_profile");
- g_glx_create_context_profile_es2_supported =
- HasGLXExtension("GLX_ARB_create_context_es2_profile");
- g_glx_texture_from_pixmap_supported =
- HasGLXExtension("GLX_EXT_texture_from_pixmap");
- g_glx_oml_sync_control_supported = HasGLXExtension("GLX_OML_sync_control");
- g_glx_get_msc_rate_oml_supported = g_glx_oml_sync_control_supported;
- g_glx_ext_swap_control_supported = HasGLXExtension("GLX_EXT_swap_control");
- g_glx_mesa_swap_control_supported = HasGLXExtension("GLX_MESA_swap_control");
- g_glx_sgi_video_sync_supported = HasGLXExtension("GLX_SGI_video_sync");
-
const XVisualInfo& visual_info =
gl::GLVisualPickerGLX::GetInstance()->system_visual();
g_visual = visual_info.visual;
@@ -447,6 +438,32 @@ bool GLSurfaceGLX::InitializeOneOff() {
return false;
}
+ initialized_ = true;
+ return true;
+}
+
+// static
+bool GLSurfaceGLX::InitializeExtensionSettingsOneOff() {
+ if (!initialized_)
+ return false;
+
+ g_driver_glx.InitializeExtensionBindings();
+
+ g_glx_context_create = HasGLXExtension("GLX_ARB_create_context");
+ g_glx_create_context_robustness_supported =
+ HasGLXExtension("GLX_ARB_create_context_robustness");
+ g_glx_create_context_profile_supported =
+ HasGLXExtension("GLX_ARB_create_context_profile");
+ g_glx_create_context_profile_es2_supported =
+ HasGLXExtension("GLX_ARB_create_context_es2_profile");
+ g_glx_texture_from_pixmap_supported =
+ HasGLXExtension("GLX_EXT_texture_from_pixmap");
+ g_glx_oml_sync_control_supported = HasGLXExtension("GLX_OML_sync_control");
+ g_glx_get_msc_rate_oml_supported = g_glx_oml_sync_control_supported;
+ g_glx_ext_swap_control_supported = HasGLXExtension("GLX_EXT_swap_control");
+ g_glx_mesa_swap_control_supported = HasGLXExtension("GLX_MESA_swap_control");
+ g_glx_sgi_video_sync_supported = HasGLXExtension("GLX_SGI_video_sync");
+
if (!g_glx_get_msc_rate_oml_supported && g_glx_sgi_video_sync_supported) {
Display* video_sync_display = gfx::OpenNewXDisplay();
if (!CreateDummyWindow(video_sync_display)) {
@@ -455,8 +472,6 @@ bool GLSurfaceGLX::InitializeOneOff() {
}
SGIVideoSyncProviderThreadShim::display_ = video_sync_display;
}
-
- initialized = true;
return true;
}
@@ -592,6 +607,7 @@ void NativeViewGLSurfaceGLX::Destroy() {
bool NativeViewGLSurfaceGLX::Resize(const gfx::Size& size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha) {
size_ = size;
glXWaitGL();
diff --git a/chromium/ui/gl/gl_surface_glx.h b/chromium/ui/gl/gl_surface_glx.h
index 10a213c9010..e67ed7ed132 100644
--- a/chromium/ui/gl/gl_surface_glx.h
+++ b/chromium/ui/gl/gl_surface_glx.h
@@ -27,6 +27,7 @@ class GL_EXPORT GLSurfaceGLX : public GLSurface {
GLSurfaceGLX();
static bool InitializeOneOff();
+ static bool InitializeExtensionSettingsOneOff();
// These aren't particularly tied to surfaces, but since we already
// have the static InitializeOneOff here, it's easiest to reuse its
@@ -55,6 +56,7 @@ class GL_EXPORT GLSurfaceGLX : public GLSurface {
private:
DISALLOW_COPY_AND_ASSIGN(GLSurfaceGLX);
+ static bool initialized_;
};
// A surface used to render to a view.
@@ -67,6 +69,7 @@ class GL_EXPORT NativeViewGLSurfaceGLX : public GLSurfaceGLX {
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() override;
diff --git a/chromium/ui/gl/gl_surface_osmesa.cc b/chromium/ui/gl/gl_surface_osmesa.cc
index 741f535696f..fd0347107e2 100644
--- a/chromium/ui/gl/gl_surface_osmesa.cc
+++ b/chromium/ui/gl/gl_surface_osmesa.cc
@@ -26,7 +26,7 @@ GLSurfaceOSMesa::GLSurfaceOSMesa(GLSurfaceFormat format,
}
bool GLSurfaceOSMesa::Initialize(GLSurfaceFormat format) {
- return Resize(size_, 1.f, true);
+ return Resize(size_, 1.f, ColorSpace::UNSPECIFIED, true);
}
void GLSurfaceOSMesa::Destroy() {
@@ -35,6 +35,7 @@ void GLSurfaceOSMesa::Destroy() {
bool GLSurfaceOSMesa::Resize(const gfx::Size& new_size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha) {
std::unique_ptr<ui::ScopedMakeCurrent> scoped_make_current;
GLContext* current_context = GLContext::GetCurrent();
diff --git a/chromium/ui/gl/gl_surface_osmesa.h b/chromium/ui/gl/gl_surface_osmesa.h
index 55e92957806..246bc2922e3 100644
--- a/chromium/ui/gl/gl_surface_osmesa.h
+++ b/chromium/ui/gl/gl_surface_osmesa.h
@@ -28,6 +28,7 @@ class GL_EXPORT GLSurfaceOSMesa : public GLSurface {
void Destroy() override;
bool Resize(const gfx::Size& new_size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha) override;
bool IsOffscreen() override;
gfx::SwapResult SwapBuffers() override;
diff --git a/chromium/ui/gl/gl_surface_osmesa_x11.cc b/chromium/ui/gl/gl_surface_osmesa_x11.cc
index 62141cdfae2..988d3c600a8 100644
--- a/chromium/ui/gl/gl_surface_osmesa_x11.cc
+++ b/chromium/ui/gl/gl_surface_osmesa_x11.cc
@@ -78,8 +78,9 @@ void GLSurfaceOSMesaX11::Destroy() {
bool GLSurfaceOSMesaX11::Resize(const gfx::Size& new_size,
float scale_factor,
+ ColorSpace color_space,
bool alpha) {
- if (!GLSurfaceOSMesa::Resize(new_size, scale_factor, alpha))
+ if (!GLSurfaceOSMesa::Resize(new_size, scale_factor, color_space, alpha))
return false;
XWindowAttributes attributes;
diff --git a/chromium/ui/gl/gl_surface_osmesa_x11.h b/chromium/ui/gl/gl_surface_osmesa_x11.h
index 96072c7f844..e51fbc8791e 100644
--- a/chromium/ui/gl/gl_surface_osmesa_x11.h
+++ b/chromium/ui/gl/gl_surface_osmesa_x11.h
@@ -28,6 +28,7 @@ class GL_EXPORT GLSurfaceOSMesaX11 : public GLSurfaceOSMesa {
void Destroy() override;
bool Resize(const gfx::Size& new_size,
float scale_factor,
+ ColorSpace color_space,
bool alpha) override;
bool IsOffscreen() override;
gfx::SwapResult SwapBuffers() override;
diff --git a/chromium/ui/gl/gl_surface_stub.cc b/chromium/ui/gl/gl_surface_stub.cc
index 6f93fa8c058..af66724a8c4 100644
--- a/chromium/ui/gl/gl_surface_stub.cc
+++ b/chromium/ui/gl/gl_surface_stub.cc
@@ -11,6 +11,7 @@ void GLSurfaceStub::Destroy() {
bool GLSurfaceStub::Resize(const gfx::Size& size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha) {
return true;
}
diff --git a/chromium/ui/gl/gl_surface_stub.h b/chromium/ui/gl/gl_surface_stub.h
index 7e11a9dfbae..c6fe52f8bbe 100644
--- a/chromium/ui/gl/gl_surface_stub.h
+++ b/chromium/ui/gl/gl_surface_stub.h
@@ -24,6 +24,7 @@ class GL_EXPORT GLSurfaceStub : public GLSurface {
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() override;
diff --git a/chromium/ui/gl/gl_surface_wgl.cc b/chromium/ui/gl/gl_surface_wgl.cc
index eb48cc462e4..65b64a161ca 100644
--- a/chromium/ui/gl/gl_surface_wgl.cc
+++ b/chromium/ui/gl/gl_surface_wgl.cc
@@ -148,6 +148,9 @@ class DisplayWGL {
DisplayWGL* g_display;
} // namespace
+// static
+bool GLSurfaceWGL::initialized_ = false;
+
GLSurfaceWGL::GLSurfaceWGL() {
}
@@ -158,9 +161,9 @@ void* GLSurfaceWGL::GetDisplay() {
return GetDisplayDC();
}
+// static
bool GLSurfaceWGL::InitializeOneOff() {
- static bool initialized = false;
- if (initialized)
+ if (initialized_)
return true;
DCHECK(g_display == NULL);
@@ -169,7 +172,15 @@ bool GLSurfaceWGL::InitializeOneOff() {
return false;
g_display = wgl_display.release();
- initialized = true;
+ initialized_ = true;
+ return true;
+}
+
+// static
+bool GLSurfaceWGL::InitializeExtensionSettingsOneOff() {
+ if (!initialized_)
+ return false;
+ g_driver_wgl.InitializeExtensionBindings();
return true;
}
@@ -257,6 +268,7 @@ void NativeViewGLSurfaceWGL::Destroy() {
bool NativeViewGLSurfaceWGL::Resize(const gfx::Size& size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha) {
RECT rect;
if (!GetClientRect(window_, &rect)) {
diff --git a/chromium/ui/gl/gl_surface_wgl.h b/chromium/ui/gl/gl_surface_wgl.h
index 1396f059cef..ee4a67fc7d4 100644
--- a/chromium/ui/gl/gl_surface_wgl.h
+++ b/chromium/ui/gl/gl_surface_wgl.h
@@ -21,6 +21,7 @@ class GL_EXPORT GLSurfaceWGL : public GLSurface {
void* GetDisplay() override;
static bool InitializeOneOff();
+ static bool InitializeExtensionSettingsOneOff();
static void InitializeOneOffForTesting();
static HDC GetDisplayDC();
@@ -29,6 +30,7 @@ class GL_EXPORT GLSurfaceWGL : public GLSurface {
private:
DISALLOW_COPY_AND_ASSIGN(GLSurfaceWGL);
+ static bool initialized_;
};
// A surface used to render to a view.
@@ -41,6 +43,7 @@ class GL_EXPORT NativeViewGLSurfaceWGL : public GLSurfaceWGL {
void Destroy() override;
bool Resize(const gfx::Size& size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha) override;
bool Recreate() override;
bool IsOffscreen() override;
diff --git a/chromium/ui/gl/gl_switches.cc b/chromium/ui/gl/gl_switches.cc
index a09d9592b63..f34a0b7eff2 100644
--- a/chromium/ui/gl/gl_switches.cc
+++ b/chromium/ui/gl/gl_switches.cc
@@ -28,10 +28,6 @@ const char kANGLEImplementationNullName[] = "null";
namespace switches {
-// Ask the GLX driver for the default context instead of trying to get the
-// highest version possible.
-const char kCreateDefaultGLContext[] = "create-default-gl-context";
-
// Disables use of D3D11.
const char kDisableD3D11[] = "disable-d3d11";
@@ -79,9 +75,6 @@ const char kGpuNoContextLost[] = "gpu-no-context-lost";
// Disables the use of DirectComposition to draw to the screen.
const char kDisableDirectComposition[] = "disable-direct-composition";
-// Indicates whether the dual GPU switching is supported or not.
-const char kSupportsDualGpus[] = "supports-dual-gpus";
-
// Flag used for Linux tests: for desktop GL bindings, try to load this GL
// library first, but fall back to regular library if loading fails.
const char kTestGLLib[] = "test-gl-lib";
@@ -129,9 +122,10 @@ const char kUsePassthroughCmdDecoder[] = "use-passthrough-cmd-decoder";
// This is the list of switches passed from this file that are passed from the
// GpuProcessHost to the GPU Process. Add your switch to this list if you need
// to read it in the GPU process, else don't add it.
-const char* kGLSwitchesCopiedFromGpuProcessHost[] = {
+const char* const kGLSwitchesCopiedFromGpuProcessHost[] = {
kDisableGpuVsync,
kDisableD3D11,
+ kDisableES3GLContext,
kEnableGPUServiceLogging,
kEnableGPUServiceTracing,
kEnableSgiVideoSync,
@@ -139,7 +133,6 @@ const char* kGLSwitchesCopiedFromGpuProcessHost[] = {
kDisableGLDrawingForTests,
kOverrideUseSoftwareGLForTests,
kUseANGLE,
- kDisableDirectComposition,
kEnableSwapBuffersWithBounds,
kEnableDirectCompositionLayers,
kDisableDirectCompositionLayers,
@@ -169,4 +162,8 @@ const base::Feature kDirectCompositionUnderlays{
const base::Feature kDirectCompositionComplexOverlays{
"DirectCompositionComplexOverlays", base::FEATURE_DISABLED_BY_DEFAULT};
+// Allow using overlays for non-root render passes.
+const base::Feature kDirectCompositionNonrootOverlays{
+ "DirectCompositionNonrootOverlays", base::FEATURE_DISABLED_BY_DEFAULT};
+
} // namespace features
diff --git a/chromium/ui/gl/gl_switches.h b/chromium/ui/gl/gl_switches.h
index 04d3bc7be57..75a8a24e03b 100644
--- a/chromium/ui/gl/gl_switches.h
+++ b/chromium/ui/gl/gl_switches.h
@@ -34,7 +34,6 @@ GL_EXPORT extern const char kANGLEImplementationNullName[];
namespace switches {
-GL_EXPORT extern const char kCreateDefaultGLContext[];
GL_EXPORT extern const char kDisableD3D11[];
GL_EXPORT extern const char kDisableES3GLContext[];
GL_EXPORT extern const char kDisableGpuVsync[];
@@ -43,8 +42,6 @@ GL_EXPORT extern const char kEnableGPUServiceTracing[];
GL_EXPORT extern const char kGpuNoContextLost[];
GL_EXPORT extern const char kDisableDirectComposition[];
-GL_EXPORT extern const char kSupportsDualGpus[];
-
GL_EXPORT extern const char kUseANGLE[];
GL_EXPORT extern const char kUseGL[];
GL_EXPORT extern const char kTestGLLib[];
@@ -63,7 +60,7 @@ GL_EXPORT extern const char kUsePassthroughCmdDecoder[];
GL_EXPORT extern const char kDisableGLDrawingForTests[];
GL_EXPORT extern const char kOverrideUseSoftwareGLForTests[];
-GL_EXPORT extern const char* kGLSwitchesCopiedFromGpuProcessHost[];
+GL_EXPORT extern const char* const kGLSwitchesCopiedFromGpuProcessHost[];
GL_EXPORT extern const int kGLSwitchesCopiedFromGpuProcessHostNumSwitches;
} // namespace switches
@@ -76,6 +73,7 @@ GL_EXPORT extern const base::Feature kD3DVsync;
GL_EXPORT extern const base::Feature kDirectCompositionUnderlays;
GL_EXPORT extern const base::Feature kDirectCompositionComplexOverlays;
+GL_EXPORT extern const base::Feature kDirectCompositionNonrootOverlays;
} // namespace features
diff --git a/chromium/ui/gl/gl_utils.cc b/chromium/ui/gl/gl_utils.cc
index a1ac0693d14..3cc2e6336d1 100644
--- a/chromium/ui/gl/gl_utils.cc
+++ b/chromium/ui/gl/gl_utils.cc
@@ -6,6 +6,8 @@
#include "ui/gl/gl_utils.h"
+#include "ui/gfx/color_space.h"
+#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_switches.h"
namespace gl {
@@ -13,4 +15,10 @@ namespace gl {
bool UsePassthroughCommandDecoder(const base::CommandLine* command_line) {
return command_line->HasSwitch(switches::kUsePassthroughCmdDecoder);
}
+
+int GetGLColorSpace(const gfx::ColorSpace& color_space) {
+ if (color_space == gfx::ColorSpace::CreateSCRGBLinear())
+ return GL_COLOR_SPACE_SCRGB_LINEAR_CHROMIUM;
+ return GL_COLOR_SPACE_UNSPECIFIED_CHROMIUM;
+}
}
diff --git a/chromium/ui/gl/gl_utils.h b/chromium/ui/gl/gl_utils.h
index db0bf3a9b52..7a362fe2991 100644
--- a/chromium/ui/gl/gl_utils.h
+++ b/chromium/ui/gl/gl_utils.h
@@ -10,9 +10,15 @@
#include "base/command_line.h"
#include "ui/gl/gl_export.h"
+namespace gfx {
+class ColorSpace;
+} // namespace gfx
+
namespace gl {
GL_EXPORT bool UsePassthroughCommandDecoder(
const base::CommandLine* command_line);
-}
+
+GL_EXPORT int GetGLColorSpace(const gfx::ColorSpace& color_space);
+} // namespace gl
#endif // UI_GL_GL_UTILS_H_
diff --git a/chromium/ui/gl/gl_version_info.cc b/chromium/ui/gl/gl_version_info.cc
index 5bf6a7f406b..9e1b1cc0492 100644
--- a/chromium/ui/gl/gl_version_info.cc
+++ b/chromium/ui/gl/gl_version_info.cc
@@ -24,25 +24,7 @@ namespace gl {
GLVersionInfo::GLVersionInfo(const char* version_str,
const char* renderer_str,
- const char* extensions_str)
- : GLVersionInfo() {
- std::set<std::string> extensions;
- if (extensions_str) {
- auto split = base::SplitString(extensions_str, " ", base::KEEP_WHITESPACE,
- base::SPLIT_WANT_NONEMPTY);
- extensions.insert(split.begin(), split.end());
- }
- Initialize(version_str, renderer_str, extensions);
-}
-
-GLVersionInfo::GLVersionInfo(const char* version_str,
- const char* renderer_str,
- const std::set<std::string>& extensions)
- : GLVersionInfo() {
- Initialize(version_str, renderer_str, extensions);
-}
-
-GLVersionInfo::GLVersionInfo()
+ const ExtensionSet& extensions)
: is_es(false),
is_angle(false),
is_mesa(false),
@@ -52,11 +34,13 @@ GLVersionInfo::GLVersionInfo()
is_es2(false),
is_es3(false),
is_desktop_core_profile(false),
- is_es3_capable(false) {}
+ is_es3_capable(false) {
+ Initialize(version_str, renderer_str, extensions);
+}
void GLVersionInfo::Initialize(const char* version_str,
const char* renderer_str,
- const std::set<std::string>& extensions) {
+ const ExtensionSet& extensions) {
if (version_str) {
ParseVersionString(version_str, &major_version, &minor_version,
&is_es, &is_es2, &is_es3);
@@ -71,16 +55,11 @@ void GLVersionInfo::Initialize(const char* version_str,
}
is_desktop_core_profile =
DesktopCoreCommonCheck(is_es, major_version, minor_version) &&
- extensions.find("GL_ARB_compatibility") == extensions.end();
+ !HasExtension(extensions, "GL_ARB_compatibility");
is_es3_capable = IsES3Capable(extensions);
}
-bool GLVersionInfo::IsES3Capable(
- const std::set<std::string>& extensions) const {
- auto has_extension = [&extensions](std::string extension) -> bool {
- return extensions.find(extension) != extensions.end();
- };
-
+bool GLVersionInfo::IsES3Capable(const ExtensionSet& extensions) const {
// Version ES3 capable without extensions needed.
if (IsAtLeastGLES(3, 0) || IsAtLeastGL(4, 2)) {
return true;
@@ -92,7 +71,8 @@ bool GLVersionInfo::IsES3Capable(
}
bool has_transform_feedback =
- (IsAtLeastGL(4, 0) || has_extension("GL_ARB_transform_feedback2"));
+ (IsAtLeastGL(4, 0) ||
+ HasExtension(extensions, "GL_ARB_transform_feedback2"));
// This code used to require the GL_ARB_gpu_shader5 extension in order to
// have support for dynamic indexing of sampler arrays, which was
@@ -101,7 +81,7 @@ bool GLVersionInfo::IsES3Capable(
// Mesa/Gallium on AMD GPUs) don't support it, we no longer require it.
// tex storage is available in core spec since GL 4.2.
- bool has_tex_storage = has_extension("GL_ARB_texture_storage");
+ bool has_tex_storage = HasExtension(extensions, "GL_ARB_texture_storage");
// TODO(cwallez) check for texture related extensions. See crbug.com/623577
diff --git a/chromium/ui/gl/gl_version_info.h b/chromium/ui/gl/gl_version_info.h
index 1775716c33b..a0278fbcfed 100644
--- a/chromium/ui/gl/gl_version_info.h
+++ b/chromium/ui/gl/gl_version_info.h
@@ -9,16 +9,15 @@
#include <string>
#include "base/macros.h"
#include "build/build_config.h"
+#include "ui/gl/extension_set.h"
#include "ui/gl/gl_export.h"
namespace gl {
struct GL_EXPORT GLVersionInfo {
- GLVersionInfo(const char* version_str, const char* renderer_str,
- const char* extensions_str);
-
- GLVersionInfo(const char* version_str, const char* renderer_str,
- const std::set<std::string>& exts);
+ GLVersionInfo(const char* version_str,
+ const char* renderer_str,
+ const ExtensionSet& exts);
bool IsAtLeastGL(unsigned major, unsigned minor) const {
return !is_es && (major_version > major ||
@@ -62,11 +61,10 @@ struct GL_EXPORT GLVersionInfo {
bool is_es3_capable;
private:
- GLVersionInfo();
void Initialize(const char* version_str,
const char* renderer_str,
- const std::set<std::string>& extensions);
- bool IsES3Capable(const std::set<std::string>& extensions) const;
+ const ExtensionSet& extensions);
+ bool IsES3Capable(const ExtensionSet& extensions) const;
DISALLOW_COPY_AND_ASSIGN(GLVersionInfo);
};
diff --git a/chromium/ui/gl/gl_version_info_unittest.cc b/chromium/ui/gl/gl_version_info_unittest.cc
index 2463e0eef00..fed30da954e 100644
--- a/chromium/ui/gl/gl_version_info_unittest.cc
+++ b/chromium/ui/gl/gl_version_info_unittest.cc
@@ -15,14 +15,13 @@ TEST(GLVersionInfoTest, MajorMinorVersionTest) {
"OpenGL ES 2.0 (ANGLE 2.1.0.cd1b12260360)",
"2.1 INTEL-10.6.33"};
const char* renderer_str[] = {NULL, NULL, NULL, NULL};
- const char* extensions_str[] = {"extensions", "extensions",
- "extensions", "extensions"};
+ ExtensionSet extensions = {"extensions"};
unsigned expected_major[] = {4, 4, 2, 2};
unsigned expected_minor[] = {3, 5, 0, 1};
std::unique_ptr<GLVersionInfo> version_info;
for (unsigned i = 0; i < arraysize(version_str); i++) {
- version_info.reset(new GLVersionInfo(version_str[i],
- renderer_str[i], extensions_str[i]));
+ version_info.reset(
+ new GLVersionInfo(version_str[i], renderer_str[i], extensions));
unsigned major, minor;
bool is_es, is_es2, is_es3;
version_info->ParseVersionString(version_str[i], &major, &minor,
diff --git a/chromium/ui/gl/gl_wgl_api_implementation.cc b/chromium/ui/gl/gl_wgl_api_implementation.cc
index c6a500fc6d8..7cda14ed652 100644
--- a/chromium/ui/gl/gl_wgl_api_implementation.cc
+++ b/chromium/ui/gl/gl_wgl_api_implementation.cc
@@ -7,7 +7,9 @@
#include "base/command_line.h"
#include "base/strings/string_split.h"
#include "base/strings/string_util.h"
+#include "ui/gl/gl_context.h"
#include "ui/gl/gl_implementation.h"
+#include "ui/gl/gl_surface_wgl.h"
namespace gl {
@@ -21,7 +23,6 @@ void InitializeStaticGLBindingsWGL() {
}
g_real_wgl->Initialize(&g_driver_wgl);
g_current_wgl_context = g_real_wgl;
- g_driver_wgl.InitializeExtensionBindings();
}
void InitializeDebugGLBindingsWGL() {
@@ -68,16 +69,10 @@ RealWGLApi::~RealWGLApi() {
}
void RealWGLApi::Initialize(DriverWGL* driver) {
- InitializeWithCommandLine(driver, base::CommandLine::ForCurrentProcess());
-}
-
-void RealWGLApi::InitializeWithCommandLine(DriverWGL* driver,
- base::CommandLine* command_line) {
- DCHECK(command_line);
InitializeBase(driver);
+}
- const std::string disabled_extensions = command_line->GetSwitchValueASCII(
- switches::kDisableGLExtensions);
+void RealWGLApi::SetDisabledExtensions(const std::string& disabled_extensions) {
disabled_exts_.clear();
filtered_ext_exts_ = "";
filtered_arb_exts_ = "";
@@ -123,9 +118,23 @@ DebugWGLApi::DebugWGLApi(WGLApi* wgl_api) : wgl_api_(wgl_api) {}
DebugWGLApi::~DebugWGLApi() {}
+void DebugWGLApi::SetDisabledExtensions(
+ const std::string& disabled_extensions) {
+ if (wgl_api_) {
+ wgl_api_->SetDisabledExtensions(disabled_extensions);
+ }
+}
+
TraceWGLApi::~TraceWGLApi() {
}
+void TraceWGLApi::SetDisabledExtensions(
+ const std::string& disabled_extensions) {
+ if (wgl_api_) {
+ wgl_api_->SetDisabledExtensions(disabled_extensions);
+ }
+}
+
bool GetGLWindowSystemBindingInfoWGL(GLWindowSystemBindingInfo* info) {
const char* extensions = wglGetExtensionsStringEXT();
*info = GLWindowSystemBindingInfo();
@@ -134,4 +143,14 @@ bool GetGLWindowSystemBindingInfoWGL(GLWindowSystemBindingInfo* info) {
return true;
}
+void SetDisabledExtensionsWGL(const std::string& disabled_extensions) {
+ DCHECK(g_current_wgl_context);
+ DCHECK(GLContext::TotalGLContexts() == 0);
+ g_current_wgl_context->SetDisabledExtensions(disabled_extensions);
+}
+
+bool InitializeExtensionSettingsOneOffWGL() {
+ return GLSurfaceWGL::InitializeExtensionSettingsOneOff();
+}
+
} // namespace gl
diff --git a/chromium/ui/gl/gl_wgl_api_implementation.h b/chromium/ui/gl/gl_wgl_api_implementation.h
index cc3628c15df..8db7ab42c6d 100644
--- a/chromium/ui/gl/gl_wgl_api_implementation.h
+++ b/chromium/ui/gl/gl_wgl_api_implementation.h
@@ -5,15 +5,13 @@
#ifndef UI_GL_GL_WGL_API_IMPLEMENTATION_H_
#define UI_GL_GL_WGL_API_IMPLEMENTATION_H_
+#include <string>
#include <vector>
#include "base/compiler_specific.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_export.h"
-namespace base {
-class CommandLine;
-}
namespace gl {
struct GLWindowSystemBindingInfo;
@@ -22,6 +20,8 @@ GL_EXPORT void InitializeStaticGLBindingsWGL();
GL_EXPORT void InitializeDebugGLBindingsWGL();
GL_EXPORT void ClearBindingsWGL();
GL_EXPORT bool GetGLWindowSystemBindingInfoWGL(GLWindowSystemBindingInfo* info);
+GL_EXPORT void SetDisabledExtensionsWGL(const std::string& disabled_extensions);
+GL_EXPORT bool InitializeExtensionSettingsOneOffWGL();
class GL_EXPORT WGLApiBase : public WGLApi {
public:
@@ -43,8 +43,7 @@ class GL_EXPORT RealWGLApi : public WGLApiBase {
RealWGLApi();
~RealWGLApi() override;
void Initialize(DriverWGL* driver);
- void InitializeWithCommandLine(DriverWGL* driver,
- base::CommandLine* command_line);
+ void SetDisabledExtensions(const std::string& disabled_extensions) override;
const char* wglGetExtensionsStringARBFn(HDC hDC) override;
const char* wglGetExtensionsStringEXTFn() override;
@@ -60,6 +59,7 @@ class GL_EXPORT DebugWGLApi : public WGLApi {
public:
DebugWGLApi(WGLApi* wgl_api);
~DebugWGLApi() override;
+ void SetDisabledExtensions(const std::string& disabled_extensions) override;
// Include the auto-generated part of this class. We split this because
// it means we can easily edit the non-auto generated parts right here in
@@ -75,6 +75,7 @@ class GL_EXPORT TraceWGLApi : public WGLApi {
public:
TraceWGLApi(WGLApi* wgl_api) : wgl_api_(wgl_api) { }
~TraceWGLApi() override;
+ void SetDisabledExtensions(const std::string& disabled_extensions) override;
// Include the auto-generated part of this class. We split this because
// it means we can easily edit the non-auto generated parts right here in
@@ -88,6 +89,3 @@ class GL_EXPORT TraceWGLApi : public WGLApi {
} // namespace gl
#endif // UI_GL_GL_WGL_API_IMPLEMENTATION_H_
-
-
-
diff --git a/chromium/ui/gl/gl_workarounds.h b/chromium/ui/gl/gl_workarounds.h
index 2b93214209a..8660dba058b 100644
--- a/chromium/ui/gl/gl_workarounds.h
+++ b/chromium/ui/gl/gl_workarounds.h
@@ -11,6 +11,9 @@ struct GLWorkarounds {
// glClearColor does not always work on Intel 6xxx Mac drivers. See
// crbug.com/710443.
bool clear_to_zero_or_one_broken = false;
+ // Reset texImage2D base level to workaround pixel comparison failure
+ // above Mac OS 10.12.4 on Intel Mac. See crbug.com/705865.
+ bool reset_teximage2d_base_level = false;
};
} // namespace gl
diff --git a/chromium/ui/gl/glx_api_unittest.cc b/chromium/ui/gl/glx_api_unittest.cc
index c36c7259228..1b2dfc9fc7f 100644
--- a/chromium/ui/gl/glx_api_unittest.cc
+++ b/chromium/ui/gl/glx_api_unittest.cc
@@ -4,7 +4,6 @@
#include <memory>
-#include "base/command_line.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gl/gl_glx_api_implementation.h"
#include "ui/gl/gl_implementation.h"
@@ -31,13 +30,13 @@ class GLXApiTest : public testing::Test {
fake_extension_string_ = "";
}
- void InitializeAPI(base::CommandLine* command_line) {
+ void InitializeAPI(const char* disabled_extensions) {
api_.reset(new RealGLXApi());
g_current_glx_context = api_.get();
- if (command_line)
- api_->InitializeWithCommandLine(&g_driver_glx, command_line);
- else
- api_->Initialize(&g_driver_glx);
+ api_->Initialize(&g_driver_glx);
+ if (disabled_extensions) {
+ SetDisabledExtensionsGLX(disabled_extensions);
+ }
g_driver_glx.InitializeExtensionBindings();
}
@@ -88,10 +87,7 @@ TEST_F(GLXApiTest, DisabledExtensionBitTest) {
EXPECT_TRUE(g_driver_glx.ext.b_GLX_ARB_create_context);
- base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
- command_line.AppendSwitchASCII(switches::kDisableGLExtensions,
- kFakeDisabledExtensions);
- InitializeAPI(&command_line);
+ InitializeAPI(kFakeDisabledExtensions);
EXPECT_FALSE(g_driver_glx.ext.b_GLX_ARB_create_context);
}
@@ -108,10 +104,7 @@ TEST_F(GLXApiTest, DisabledExtensionStringTest) {
EXPECT_STREQ(kFakeExtensions, GetExtensions());
- base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
- command_line.AppendSwitchASCII(switches::kDisableGLExtensions,
- kFakeDisabledExtensions);
- InitializeAPI(&command_line);
+ InitializeAPI(kFakeDisabledExtensions);
EXPECT_STREQ(kFilteredExtensions, GetExtensions());
}
diff --git a/chromium/ui/gl/gpu_preference.h b/chromium/ui/gl/gpu_preference.h
index 67abb755800..edfb679839b 100644
--- a/chromium/ui/gl/gpu_preference.h
+++ b/chromium/ui/gl/gpu_preference.h
@@ -15,6 +15,7 @@ namespace gl {
// This API will likely need to be adjusted as the functionality is
// implemented on more operating systems.
enum GpuPreference {
+ GpuPreferenceNone,
PreferIntegratedGpu,
PreferDiscreteGpu,
GpuPreferenceLast = PreferDiscreteGpu
diff --git a/chromium/ui/gl/gpu_switching_manager.cc b/chromium/ui/gl/gpu_switching_manager.cc
index 9718114c538..be715646580 100644
--- a/chromium/ui/gl/gpu_switching_manager.cc
+++ b/chromium/ui/gl/gpu_switching_manager.cc
@@ -4,120 +4,16 @@
#include "ui/gl/gpu_switching_manager.h"
-#include "base/command_line.h"
-#include "base/logging.h"
-#include "build/build_config.h"
-#include "ui/gl/gl_switches.h"
-
-#if defined(OS_MACOSX)
-#include <OpenGL/OpenGL.h>
-#include "ui/gl/gl_context_cgl.h"
-#endif // OS_MACOSX
-
namespace ui {
-struct GpuSwitchingManager::PlatformSpecific {
-#if defined(OS_MACOSX)
- CGLPixelFormatObj discrete_pixel_format;
-#endif // OS_MACOSX
-};
-
// static
GpuSwitchingManager* GpuSwitchingManager::GetInstance() {
return base::Singleton<GpuSwitchingManager>::get();
}
-GpuSwitchingManager::GpuSwitchingManager()
- : gpu_switching_option_(gl::PreferIntegratedGpu),
- gpu_switching_option_set_(false),
- supports_dual_gpus_(false),
- supports_dual_gpus_set_(false),
- platform_specific_(new PlatformSpecific) {
-#if defined(OS_MACOSX)
- platform_specific_->discrete_pixel_format = nullptr;
-#endif // OS_MACOSX
-}
-
-GpuSwitchingManager::~GpuSwitchingManager() {
-#if defined(OS_MACOSX)
- if (platform_specific_->discrete_pixel_format)
- CGLReleasePixelFormat(platform_specific_->discrete_pixel_format);
-#endif // OS_MACOSX
-}
-
-void GpuSwitchingManager::ForceUseOfIntegratedGpu() {
- DCHECK(SupportsDualGpus());
- if (gpu_switching_option_set_) {
- DCHECK_EQ(gpu_switching_option_, gl::PreferIntegratedGpu);
- } else {
- gpu_switching_option_ = gl::PreferIntegratedGpu;
- gpu_switching_option_set_ = true;
- }
-}
-
-void GpuSwitchingManager::ForceUseOfDiscreteGpu() {
- DCHECK(SupportsDualGpus());
- if (gpu_switching_option_set_) {
- DCHECK_EQ(gpu_switching_option_, gl::PreferDiscreteGpu);
- } else {
- gpu_switching_option_ = gl::PreferDiscreteGpu;
- gpu_switching_option_set_ = true;
-#if defined(OS_MACOSX)
- // Create a pixel format that lasts the lifespan of Chrome, so Chrome
- // stays on the discrete GPU.
- SwitchToDiscreteGpuMac();
-#endif // OS_MACOSX
- }
-}
-
-bool GpuSwitchingManager::SupportsDualGpus() {
- if (!supports_dual_gpus_set_) {
- const base::CommandLine& command_line =
- *base::CommandLine::ForCurrentProcess();
- bool flag = false;
- if (command_line.HasSwitch(switches::kSupportsDualGpus)) {
- // GPU process, flag is passed down from browser process.
- std::string flag_string = command_line.GetSwitchValueASCII(
- switches::kSupportsDualGpus);
- if (flag_string == "true") {
- flag = true;
- } else if (flag_string == "false") {
- flag = false;
- } else {
- NOTIMPLEMENTED();
- }
- } else {
- // Browser process.
- // We only compute this flag in the browser process.
-#if defined(OS_MACOSX)
- flag = (vendor_ids_.size() == 2);
- if (flag && command_line.HasSwitch(switches::kUseGL) &&
- command_line.GetSwitchValueASCII(switches::kUseGL) !=
- gl::kGLImplementationDesktopName)
- flag = false;
+GpuSwitchingManager::GpuSwitchingManager() {}
- if (flag) {
- // Only advertise that we have two GPUs to the rest of
- // Chrome's code if we find an Intel GPU and some other
- // vendor's GPU. Otherwise we don't understand the
- // configuration and don't deal well with it (an example being
- // the dual AMD GPUs in recent Mac Pros).
- const uint32_t intel = 0x8086;
- flag = ((vendor_ids_[0] == intel && vendor_ids_[1] != intel) ||
- (vendor_ids_[0] != intel && vendor_ids_[1] == intel));
- }
-#endif // OS_MACOSX
- }
- supports_dual_gpus_ = flag;
- supports_dual_gpus_set_ = true;
- }
- return supports_dual_gpus_;
-}
-
-void GpuSwitchingManager::SetGpuVendorIds(
- const std::vector<uint32_t>& vendor_ids) {
- vendor_ids_ = vendor_ids;
-}
+GpuSwitchingManager::~GpuSwitchingManager() {}
void GpuSwitchingManager::AddObserver(GpuSwitchingObserver* observer) {
observer_list_.AddObserver(observer);
@@ -132,23 +28,4 @@ void GpuSwitchingManager::NotifyGpuSwitched() {
observer.OnGpuSwitched();
}
-gl::GpuPreference GpuSwitchingManager::AdjustGpuPreference(
- gl::GpuPreference gpu_preference) {
- if (!gpu_switching_option_set_)
- return gpu_preference;
- return gpu_switching_option_;
-}
-
-#if defined(OS_MACOSX)
-void GpuSwitchingManager::SwitchToDiscreteGpuMac() {
- if (platform_specific_->discrete_pixel_format)
- return;
- CGLPixelFormatAttribute attribs[1];
- attribs[0] = static_cast<CGLPixelFormatAttribute>(0);
- GLint num_pixel_formats = 0;
- CGLChoosePixelFormat(attribs, &platform_specific_->discrete_pixel_format,
- &num_pixel_formats);
-}
-#endif // OS_MACOSX
-
} // namespace ui
diff --git a/chromium/ui/gl/gpu_switching_manager.h b/chromium/ui/gl/gpu_switching_manager.h
index 4ac76200235..4308bbed939 100644
--- a/chromium/ui/gl/gpu_switching_manager.h
+++ b/chromium/ui/gl/gpu_switching_manager.h
@@ -5,17 +5,10 @@
#ifndef UI_GL_GPU_SWITCHING_MANAGER_H_
#define UI_GL_GPU_SWITCHING_MANAGER_H_
-#include <stdint.h>
-
-#include <memory>
-#include <vector>
-
-#include "base/macros.h"
#include "base/memory/singleton.h"
#include "base/observer_list.h"
#include "build/build_config.h"
#include "ui/gl/gl_export.h"
-#include "ui/gl/gpu_preference.h"
#include "ui/gl/gpu_switching_observer.h"
namespace ui {
@@ -25,26 +18,6 @@ class GL_EXPORT GpuSwitchingManager {
// Getter for the singleton. This will return NULL on failure.
static GpuSwitchingManager* GetInstance();
- // Set the switching option to PreferIntegratedGpu.
- void ForceUseOfIntegratedGpu();
- // Set the switching option to PreferDiscreteGpu; switch to discrete GPU
- // immediately on Mac where dual GPU switching is supported.
- void ForceUseOfDiscreteGpu();
-
- // If no GPU is forced, return the original GpuPreference; otherwise, return
- // the forced GPU.
- gl::GpuPreference AdjustGpuPreference(gl::GpuPreference gpu_preference);
-
- // In the browser process, the value for this flag is computed the first time
- // this function is called.
- // In the GPU process, the value is passed from the browser process using the
- // --supports-dual-gpus commandline switch.
- bool SupportsDualGpus();
-
- // Sets the vendor IDs of the GPUs on the system. The length of this
- // vector defines the count of GPUs.
- void SetGpuVendorIds(const std::vector<uint32_t>& vendor_ids);
-
void AddObserver(GpuSwitchingObserver* observer);
void RemoveObserver(GpuSwitchingObserver* observer);
@@ -61,21 +34,6 @@ class GL_EXPORT GpuSwitchingManager {
GpuSwitchingManager();
virtual ~GpuSwitchingManager();
-#if defined(OS_MACOSX)
- void SwitchToDiscreteGpuMac();
-#endif // OS_MACOSX
-
- gl::GpuPreference gpu_switching_option_;
- bool gpu_switching_option_set_;
-
- std::vector<uint32_t> vendor_ids_;
-
- bool supports_dual_gpus_;
- bool supports_dual_gpus_set_;
-
- struct PlatformSpecific;
- std::unique_ptr<PlatformSpecific> platform_specific_;
-
base::ObserverList<GpuSwitchingObserver> observer_list_;
DISALLOW_COPY_AND_ASSIGN(GpuSwitchingManager);
diff --git a/chromium/ui/gl/init/BUILD.gn b/chromium/ui/gl/init/BUILD.gn
index bd43b3eee78..dea64ed0c05 100644
--- a/chromium/ui/gl/init/BUILD.gn
+++ b/chromium/ui/gl/init/BUILD.gn
@@ -49,11 +49,6 @@ component("init") {
]
libs = [ "OpenGL.framework" ]
- } else if (is_fuchsia) {
- sources += [
- "gl_factory_fuchsia.cc",
- "gl_initializer_fuchsia.cc",
- ]
} else if (use_x11) {
sources += [
"gl_factory_x11.cc",
diff --git a/chromium/ui/gl/init/gl_factory.cc b/chromium/ui/gl/init/gl_factory.cc
index 744b430d733..643941be273 100644
--- a/chromium/ui/gl/init/gl_factory.cc
+++ b/chromium/ui/gl/init/gl_factory.cc
@@ -17,9 +17,8 @@
namespace gl {
namespace init {
-bool InitializeGLOneOff() {
- TRACE_EVENT0("gpu,startup", "gl::init::InitializeOneOff");
-
+namespace {
+bool InitializeGLOneOffHelper(bool init_extensions) {
DCHECK_EQ(kGLImplementationNone, GetGLImplementation());
std::vector<GLImplementation> allowed_impls = GetAllowedGLImplementations();
@@ -56,14 +55,28 @@ bool InitializeGLOneOff() {
bool gpu_service_logging = cmd->HasSwitch(switches::kEnableGPUServiceLogging);
bool disable_gl_drawing = cmd->HasSwitch(switches::kDisableGLDrawingForTests);
- return InitializeGLOneOffImplementation(
- impl, fallback_to_software_gl, gpu_service_logging, disable_gl_drawing);
+ return InitializeGLOneOffImplementation(impl, fallback_to_software_gl,
+ gpu_service_logging,
+ disable_gl_drawing, init_extensions);
+}
+
+} // namespace
+
+bool InitializeGLOneOff() {
+ TRACE_EVENT0("gpu,startup", "gl::init::InitializeOneOff");
+ return InitializeGLOneOffHelper(true);
+}
+
+bool InitializeGLNoExtensionsOneOff() {
+ TRACE_EVENT0("gpu,startup", "gl::init::InitializeNoExtensionsOneOff");
+ return InitializeGLOneOffHelper(false);
}
bool InitializeGLOneOffImplementation(GLImplementation impl,
bool fallback_to_software_gl,
bool gpu_service_logging,
- bool disable_gl_drawing) {
+ bool disable_gl_drawing,
+ bool init_extensions) {
bool initialized =
InitializeStaticGLBindings(impl) && InitializeGLOneOffPlatform();
if (!initialized && fallback_to_software_gl) {
@@ -71,6 +84,10 @@ bool InitializeGLOneOffImplementation(GLImplementation impl,
initialized = InitializeStaticGLBindings(GetSoftwareGLImplementation()) &&
InitializeGLOneOffPlatform();
}
+ if (initialized && init_extensions) {
+ initialized = InitializeExtensionSettingsOneOffPlatform();
+ }
+
if (!initialized)
ShutdownGL();
diff --git a/chromium/ui/gl/init/gl_factory.h b/chromium/ui/gl/init/gl_factory.h
index 52dcbe1a074..44819daaca2 100644
--- a/chromium/ui/gl/init/gl_factory.h
+++ b/chromium/ui/gl/init/gl_factory.h
@@ -6,6 +6,7 @@
#define UI_GL_INIT_GL_FACTORY_H_
#include <memory>
+#include <string>
#include <vector>
#include "base/memory/ref_counted.h"
@@ -36,13 +37,21 @@ GL_INIT_EXPORT std::vector<GLImplementation> GetAllowedGLImplementations();
// Initializes GL bindings.
GL_INIT_EXPORT bool InitializeGLOneOff();
+// Initializes GL bindings without initializing extension settings.
+GL_INIT_EXPORT bool InitializeGLNoExtensionsOneOff();
+
+// Initialize plaiform dependent extension settings, including bindings,
+// capabilities, etc.
+GL_INIT_EXPORT bool InitializeExtensionSettingsOneOffPlatform();
+
// Initializes GL bindings using the provided parameters. This might be required
// for use in tests, otherwise use InitializeGLOneOff() instead.
GL_INIT_EXPORT bool InitializeGLOneOffImplementation(
GLImplementation impl,
bool fallback_to_software_gl,
bool gpu_service_logging,
- bool disable_gl_drawing);
+ bool disable_gl_drawing,
+ bool init_extensions);
// Clears GL bindings and resets GL implementation.
GL_INIT_EXPORT void ShutdownGL();
@@ -87,6 +96,11 @@ GL_INIT_EXPORT scoped_refptr<GLSurface> CreateOffscreenGLSurface(
GL_INIT_EXPORT scoped_refptr<GLSurface> CreateOffscreenGLSurfaceWithFormat(
const gfx::Size& size, GLSurfaceFormat format);
+// Set platform dependent disabled extensions and re-initialize extension
+// bindings.
+GL_INIT_EXPORT void SetDisabledExtensionsPlatform(
+ const std::string& disabled_extensions);
+
} // namespace init
} // namespace gl
diff --git a/chromium/ui/gl/init/gl_factory_android.cc b/chromium/ui/gl/init/gl_factory_android.cc
index dff62b16213..476c61730f6 100644
--- a/chromium/ui/gl/init/gl_factory_android.cc
+++ b/chromium/ui/gl/init/gl_factory_android.cc
@@ -39,7 +39,6 @@ class GLNonOwnedContext : public GLContextReal {
bool IsCurrent(GLSurface* surface) override { return true; }
void* GetHandle() override { return nullptr; }
void OnSetSwapInterval(int interval) override {}
- std::string GetExtensions() override;
protected:
~GLNonOwnedContext() override {}
@@ -66,14 +65,6 @@ bool GLNonOwnedContext::MakeCurrent(GLSurface* surface) {
return true;
}
-std::string GLNonOwnedContext::GetExtensions() {
- const char* extensions = eglQueryString(display_, EGL_EXTENSIONS);
- if (!extensions)
- return GLContext::GetExtensions();
-
- return GLContext::GetExtensions() + " " + extensions;
-}
-
} // namespace
std::vector<GLImplementation> GetAllowedGLImplementations() {
@@ -166,5 +157,37 @@ scoped_refptr<GLSurface> CreateOffscreenGLSurfaceWithFormat(
}
}
+void SetDisabledExtensionsPlatform(const std::string& disabled_extensions) {
+ GLImplementation implementation = GetGLImplementation();
+ DCHECK_NE(kGLImplementationNone, implementation);
+ switch (implementation) {
+ case kGLImplementationEGLGLES2:
+ SetDisabledExtensionsEGL(disabled_extensions);
+ break;
+ case kGLImplementationMockGL:
+ case kGLImplementationStubGL:
+ case kGLImplementationOSMesaGL:
+ break;
+ default:
+ NOTREACHED();
+ }
+}
+
+bool InitializeExtensionSettingsOneOffPlatform() {
+ GLImplementation implementation = GetGLImplementation();
+ DCHECK_NE(kGLImplementationNone, implementation);
+ switch (implementation) {
+ case kGLImplementationEGLGLES2:
+ return InitializeExtensionSettingsOneOffEGL();
+ case kGLImplementationMockGL:
+ case kGLImplementationStubGL:
+ case kGLImplementationOSMesaGL:
+ return true;
+ default:
+ NOTREACHED();
+ return false;
+ }
+}
+
} // namespace init
} // namespace gl
diff --git a/chromium/ui/gl/init/gl_factory_fuchsia.cc b/chromium/ui/gl/init/gl_factory_fuchsia.cc
deleted file mode 100644
index 9ec54533292..00000000000
--- a/chromium/ui/gl/init/gl_factory_fuchsia.cc
+++ /dev/null
@@ -1,45 +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/gl/init/gl_factory.h"
-
-#include "ui/gl/gl_context.h"
-#include "ui/gl/gl_surface.h"
-
-namespace gl {
-namespace init {
-
-// TODO(fuchsia): Implement these functions.
-
-std::vector<GLImplementation> GetAllowedGLImplementations() {
- NOTIMPLEMENTED();
- return std::vector<GLImplementation>();
-}
-
-bool GetGLWindowSystemBindingInfo(GLWindowSystemBindingInfo* info) {
- NOTIMPLEMENTED();
- return false;
-}
-
-scoped_refptr<GLContext> CreateGLContext(GLShareGroup* share_group,
- GLSurface* compatible_surface,
- const GLContextAttribs& attribs) {
- NOTIMPLEMENTED();
- return nullptr;
-}
-
-scoped_refptr<GLSurface> CreateViewGLSurface(gfx::AcceleratedWidget window) {
- NOTIMPLEMENTED();
- return nullptr;
-}
-
-scoped_refptr<GLSurface> CreateOffscreenGLSurfaceWithFormat(
- const gfx::Size& size,
- GLSurfaceFormat format) {
- NOTIMPLEMENTED();
- return nullptr;
-}
-
-} // namespace init
-} // namespace gl
diff --git a/chromium/ui/gl/init/gl_factory_mac.cc b/chromium/ui/gl/init/gl_factory_mac.cc
index 6716f4109df..2a34dbe549e 100644
--- a/chromium/ui/gl/init/gl_factory_mac.cc
+++ b/chromium/ui/gl/init/gl_factory_mac.cc
@@ -143,5 +143,18 @@ scoped_refptr<GLSurface> CreateOffscreenGLSurfaceWithFormat(
}
}
+void SetDisabledExtensionsPlatform(const std::string& disabled_extensions) {
+ GLImplementation implementation = GetGLImplementation();
+ DCHECK_NE(kGLImplementationNone, implementation);
+ // TODO(zmo): Implement this if needs arise.
+}
+
+bool InitializeExtensionSettingsOneOffPlatform() {
+ GLImplementation implementation = GetGLImplementation();
+ DCHECK_NE(kGLImplementationNone, implementation);
+ // TODO(zmo): Implement this if needs arise.
+ return true;
+}
+
} // namespace init
} // namespace gl
diff --git a/chromium/ui/gl/init/gl_factory_ozone.cc b/chromium/ui/gl/init/gl_factory_ozone.cc
index a4e0097cb20..cad4a4715ef 100644
--- a/chromium/ui/gl/init/gl_factory_ozone.cc
+++ b/chromium/ui/gl/init/gl_factory_ozone.cc
@@ -8,6 +8,7 @@
#include "base/trace_event/trace_event.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_context_stub.h"
+#include "ui/gl/gl_egl_api_implementation.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_share_group.h"
#include "ui/gl/gl_surface.h"
@@ -104,5 +105,47 @@ scoped_refptr<GLSurface> CreateOffscreenGLSurfaceWithFormat(
return nullptr;
}
+void SetDisabledExtensionsPlatform(const std::string& disabled_extensions) {
+ GLImplementation implementation = GetGLImplementation();
+ DCHECK_NE(kGLImplementationNone, implementation);
+ switch (implementation) {
+ case kGLImplementationEGLGLES2:
+ SetDisabledExtensionsEGL(disabled_extensions);
+ break;
+ case kGLImplementationDesktopGL:
+ // TODO(zmo): I don't think ozone goes down this path except for testing.
+ // This might change in the future though.
+ break;
+ case kGLImplementationSwiftShaderGL:
+ case kGLImplementationOSMesaGL:
+ case kGLImplementationMockGL:
+ case kGLImplementationStubGL:
+ break;
+ default:
+ NOTREACHED();
+ }
+}
+
+bool InitializeExtensionSettingsOneOffPlatform() {
+ GLImplementation implementation = GetGLImplementation();
+ DCHECK_NE(kGLImplementationNone, implementation);
+ switch (implementation) {
+ case kGLImplementationEGLGLES2:
+ return InitializeExtensionSettingsOneOffEGL();
+ case kGLImplementationDesktopGL:
+ // TODO(zmo): I don't think ozone goes down this path except for testing.
+ // This might change in the future though.
+ return true;
+ case kGLImplementationSwiftShaderGL:
+ case kGLImplementationOSMesaGL:
+ case kGLImplementationMockGL:
+ case kGLImplementationStubGL:
+ return true;
+ default:
+ NOTREACHED();
+ return false;
+ }
+}
+
} // namespace init
} // namespace gl
diff --git a/chromium/ui/gl/init/gl_factory_win.cc b/chromium/ui/gl/init/gl_factory_win.cc
index ca5b04b62f3..b9f442cd4e3 100644
--- a/chromium/ui/gl/init/gl_factory_win.cc
+++ b/chromium/ui/gl/init/gl_factory_win.cc
@@ -136,5 +136,44 @@ scoped_refptr<GLSurface> CreateOffscreenGLSurfaceWithFormat(
}
}
+void SetDisabledExtensionsPlatform(const std::string& disabled_extensions) {
+ GLImplementation implementation = GetGLImplementation();
+ DCHECK_NE(kGLImplementationNone, implementation);
+ switch (implementation) {
+ case kGLImplementationDesktopGL:
+ SetDisabledExtensionsWGL(disabled_extensions);
+ break;
+ case kGLImplementationEGLGLES2:
+ SetDisabledExtensionsEGL(disabled_extensions);
+ break;
+ case kGLImplementationSwiftShaderGL:
+ case kGLImplementationOSMesaGL:
+ case kGLImplementationMockGL:
+ case kGLImplementationStubGL:
+ break;
+ default:
+ NOTREACHED();
+ }
+}
+
+bool InitializeExtensionSettingsOneOffPlatform() {
+ GLImplementation implementation = GetGLImplementation();
+ DCHECK_NE(kGLImplementationNone, implementation);
+ switch (implementation) {
+ case kGLImplementationDesktopGL:
+ return InitializeExtensionSettingsOneOffWGL();
+ case kGLImplementationEGLGLES2:
+ return InitializeExtensionSettingsOneOffEGL();
+ case kGLImplementationSwiftShaderGL:
+ case kGLImplementationOSMesaGL:
+ case kGLImplementationMockGL:
+ case kGLImplementationStubGL:
+ return true;
+ default:
+ NOTREACHED();
+ return false;
+ }
+}
+
} // namespace init
} // namespace gl
diff --git a/chromium/ui/gl/init/gl_factory_x11.cc b/chromium/ui/gl/init/gl_factory_x11.cc
index 9b0f48174b0..b55fe76b197 100644
--- a/chromium/ui/gl/init/gl_factory_x11.cc
+++ b/chromium/ui/gl/init/gl_factory_x11.cc
@@ -124,5 +124,44 @@ scoped_refptr<GLSurface> CreateOffscreenGLSurfaceWithFormat(
}
}
+void SetDisabledExtensionsPlatform(const std::string& disabled_extensions) {
+ GLImplementation implementation = GetGLImplementation();
+ DCHECK_NE(kGLImplementationNone, implementation);
+ switch (implementation) {
+ case kGLImplementationDesktopGL:
+ SetDisabledExtensionsGLX(disabled_extensions);
+ break;
+ case kGLImplementationEGLGLES2:
+ SetDisabledExtensionsEGL(disabled_extensions);
+ break;
+ case kGLImplementationSwiftShaderGL:
+ case kGLImplementationOSMesaGL:
+ case kGLImplementationMockGL:
+ case kGLImplementationStubGL:
+ break;
+ default:
+ NOTREACHED();
+ }
+}
+
+bool InitializeExtensionSettingsOneOffPlatform() {
+ GLImplementation implementation = GetGLImplementation();
+ DCHECK_NE(kGLImplementationNone, implementation);
+ switch (implementation) {
+ case kGLImplementationDesktopGL:
+ return InitializeExtensionSettingsOneOffGLX();
+ case kGLImplementationEGLGLES2:
+ return InitializeExtensionSettingsOneOffEGL();
+ case kGLImplementationSwiftShaderGL:
+ case kGLImplementationOSMesaGL:
+ case kGLImplementationMockGL:
+ case kGLImplementationStubGL:
+ return true;
+ default:
+ NOTREACHED();
+ return false;
+ }
+}
+
} // namespace init
} // namespace gl
diff --git a/chromium/ui/gl/init/gl_initializer_fuchsia.cc b/chromium/ui/gl/init/gl_initializer_fuchsia.cc
deleted file mode 100644
index 73d543d5ebc..00000000000
--- a/chromium/ui/gl/init/gl_initializer_fuchsia.cc
+++ /dev/null
@@ -1,31 +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/gl/init/gl_initializer.h"
-
-namespace gl {
-namespace init {
-
-// TODO(fuchsia): Implement these functions.
-
-bool InitializeGLOneOffPlatform() {
- NOTIMPLEMENTED();
- return false;
-}
-
-bool InitializeStaticGLBindings(GLImplementation implementation) {
- NOTIMPLEMENTED();
- return false;
-}
-
-void InitializeDebugGLBindings() {
- NOTIMPLEMENTED();
-}
-
-void ShutdownGLPlatform() {
- NOTIMPLEMENTED();
-}
-
-} // namespace init
-} // namespace gl
diff --git a/chromium/ui/gl/init/gl_initializer_mac.cc b/chromium/ui/gl/init/gl_initializer_mac.cc
index a574fb9df48..828ce9bb013 100644
--- a/chromium/ui/gl/init/gl_initializer_mac.cc
+++ b/chromium/ui/gl/init/gl_initializer_mac.cc
@@ -16,6 +16,7 @@
#include "base/path_service.h"
#include "base/threading/thread_restrictions.h"
#include "ui/gl/gl_bindings.h"
+#include "ui/gl/gl_context.h"
#include "ui/gl/gl_gl_api_implementation.h"
#include "ui/gl/gl_implementation.h"
#include "ui/gl/gl_osmesa_api_implementation.h"
@@ -39,7 +40,7 @@ bool InitializeOneOffForSandbox() {
// GPU-related stuff is very slow without this, probably because
// the sandbox prevents loading graphics drivers or some such.
std::vector<CGLPixelFormatAttribute> attribs;
- if (ui::GpuSwitchingManager::GetInstance()->SupportsDualGpus()) {
+ if (GLContext::SwitchableGPUsSupported()) {
// Avoid switching to the discrete GPU just for this pixel
// format selection.
attribs.push_back(kCGLPFAAllowOfflineRenderers);
diff --git a/chromium/ui/gl/sync_control_vsync_provider.cc b/chromium/ui/gl/sync_control_vsync_provider.cc
index f9dc5c56e47..d45840e8a65 100644
--- a/chromium/ui/gl/sync_control_vsync_provider.cc
+++ b/chromium/ui/gl/sync_control_vsync_provider.cc
@@ -40,8 +40,6 @@ void SyncControlVSyncProvider::GetVSyncParameters(
const UpdateVSyncCallback& callback) {
TRACE_EVENT0("gpu", "SyncControlVSyncProvider::GetVSyncParameters");
#if defined(OS_LINUX)
- base::TimeTicks timebase;
-
// The actual clock used for the system time returned by glXGetSyncValuesOML
// is unspecified. In practice, the clock used is likely to be either
// CLOCK_REALTIME or CLOCK_MONOTONIC, so we compare the returned time to the
@@ -67,16 +65,18 @@ void SyncControlVSyncProvider::GetVSyncParameters(
}
struct timespec real_time;
- struct timespec monotonic_time;
clock_gettime(CLOCK_REALTIME, &real_time);
- clock_gettime(CLOCK_MONOTONIC, &monotonic_time);
+ // Note: A thread context switch could happen here, between the sampling of
+ // the two different clocks.
+ const base::TimeTicks monotonic_time = base::TimeTicks::Now();
+ DCHECK_EQ(base::TimeTicks::GetClock(),
+ base::TimeTicks::Clock::LINUX_CLOCK_MONOTONIC);
int64_t real_time_in_microseconds =
real_time.tv_sec * base::Time::kMicrosecondsPerSecond +
real_time.tv_nsec / base::Time::kNanosecondsPerMicrosecond;
int64_t monotonic_time_in_microseconds =
- monotonic_time.tv_sec * base::Time::kMicrosecondsPerSecond +
- monotonic_time.tv_nsec / base::Time::kNanosecondsPerMicrosecond;
+ monotonic_time.since_origin().InMicroseconds();
// We need the time according to CLOCK_MONOTONIC, so if we've been given
// a time from CLOCK_REALTIME, we need to convert.
@@ -102,7 +102,8 @@ void SyncControlVSyncProvider::GetVSyncParameters(
base::Time::kMicrosecondsPerSecond)
return;
- timebase = base::TimeTicks::FromInternalValue(system_time);
+ const base::TimeTicks timebase =
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(system_time);
// Only need the previous calculated interval for our filtering.
while (last_computed_intervals_.size() > 1)
@@ -140,11 +141,10 @@ void SyncControlVSyncProvider::GetVSyncParameters(
#else
LOG(FATAL)
#endif // USE_ASH
- << "Calculated bogus refresh interval="
- << new_interval.InMicroseconds()
- << " us., last_timebase_=" << last_timebase_.ToInternalValue()
- << " us., timebase=" << timebase.ToInternalValue()
- << " us., last_media_stream_counter_=" << last_media_stream_counter_
+ << "Calculated bogus refresh interval=" << new_interval
+ << ", last_timebase_=" << last_timebase_
+ << ", timebase=" << timebase
+ << ", last_media_stream_counter_=" << last_media_stream_counter_
<< ", media_stream_counter=" << media_stream_counter;
} else {
last_good_interval_ = new_interval;
diff --git a/chromium/ui/gl/vsync_provider_win.cc b/chromium/ui/gl/vsync_provider_win.cc
index 8025ca9059a..b5c7c612ab7 100644
--- a/chromium/ui/gl/vsync_provider_win.cc
+++ b/chromium/ui/gl/vsync_provider_win.cc
@@ -105,7 +105,7 @@ void VSyncProviderWin::GetVSyncParameters(const UpdateVSyncCallback& callback) {
}
}
- if (interval.ToInternalValue() != 0) {
+ if (!interval.is_zero()) {
callback.Run(timebase, interval);
}
}
diff --git a/chromium/ui/gl/wgl_api_unittest.cc b/chromium/ui/gl/wgl_api_unittest.cc
index 041d3dfaf9f..a0fe216ffba 100644
--- a/chromium/ui/gl/wgl_api_unittest.cc
+++ b/chromium/ui/gl/wgl_api_unittest.cc
@@ -37,13 +37,13 @@ class WGLApiTest : public testing::Test {
fake_arb_extension_string_ = "";
}
- void InitializeAPI(base::CommandLine* command_line) {
+ void InitializeAPI(const char* disabled_extensions) {
api_.reset(new RealWGLApi());
g_current_wgl_context = api_.get();
- if (command_line)
- api_->InitializeWithCommandLine(&g_driver_wgl, command_line);
- else
- api_->Initialize(&g_driver_wgl);
+ api_->Initialize(&g_driver_wgl);
+ if (disabled_extensions) {
+ SetDisabledExtensionsWGL(disabled_extensions);
+ }
g_driver_wgl.InitializeExtensionBindings();
}
@@ -94,18 +94,14 @@ TEST_F(WGLApiTest, DisabledExtensionBitTest) {
EXPECT_FALSE(g_driver_wgl.ext.b_WGL_ARB_extensions_string);
- base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
- command_line.AppendSwitchASCII(switches::kDisableGLExtensions,
- kFakeDisabledExtensions);
-
// NULL simulates not being able to resolve wglGetExtensionsStringARB
- SetFakeARBExtensionString(NULL);
+ SetFakeARBExtensionString(nullptr);
SetFakeEXTExtensionString(kFakeExtensions);
InitializeAPI(nullptr);
EXPECT_TRUE(g_driver_wgl.ext.b_WGL_ARB_extensions_string);
- InitializeAPI(&command_line);
+ InitializeAPI(kFakeExtensions);
EXPECT_FALSE(g_driver_wgl.ext.b_WGL_ARB_extensions_string);
SetFakeARBExtensionString("");
@@ -123,7 +119,7 @@ TEST_F(WGLApiTest, DisabledExtensionBitTest) {
InitializeAPI(nullptr);
EXPECT_TRUE(g_driver_wgl.ext.b_WGL_ARB_extensions_string);
- InitializeAPI(&command_line);
+ InitializeAPI(kFakeDisabledExtensions);
EXPECT_FALSE(g_driver_wgl.ext.b_WGL_ARB_extensions_string);
}
@@ -134,10 +130,6 @@ TEST_F(WGLApiTest, DisabledExtensionStringTest) {
"EGL_EXT_1,EGL_EXT_2,EGL_FAKE";
static const char* kFilteredExtensions = "EGL_EXT_3 EGL_EXT_4";
- base::CommandLine command_line(base::CommandLine::NO_PROGRAM);
- command_line.AppendSwitchASCII(switches::kDisableGLExtensions,
- kFakeDisabledExtensions);
-
SetFakeARBExtensionString(kFakeExtensions);
SetFakeEXTExtensionString(kFakeExtensions);
@@ -145,7 +137,7 @@ TEST_F(WGLApiTest, DisabledExtensionStringTest) {
EXPECT_EQ(stringpair(kFakeExtensions, kFakeExtensions),
GetExtensions());
- InitializeAPI(&command_line);
+ InitializeAPI(kFakeDisabledExtensions);
EXPECT_EQ(stringpair(kFilteredExtensions, kFilteredExtensions),
GetExtensions());
}
diff --git a/chromium/ui/gl/yuv_to_rgb_converter.cc b/chromium/ui/gl/yuv_to_rgb_converter.cc
index daef3990fbc..73410cb1c04 100644
--- a/chromium/ui/gl/yuv_to_rgb_converter.cc
+++ b/chromium/ui/gl/yuv_to_rgb_converter.cc
@@ -6,6 +6,7 @@
#include "base/strings/stringize_macros.h"
#include "base/strings/stringprintf.h"
+#include "ui/gfx/color_transform.h"
#include "ui/gl/gl_helper.h"
#include "ui/gl/gl_version_info.h"
#include "ui/gl/scoped_binders.h"
@@ -55,21 +56,25 @@ STRINGIZE(
uniform sampler2DRect a_uv_texture;
VARYING vec2 v_texCoord;
void main() {
- vec3 yuv_adj = vec3(-0.0625, -0.5, -0.5);
- mat3 yuv_matrix = mat3(vec3(1.164, 1.164, 1.164),
- vec3(0.0, -.391, 2.018),
- vec3(1.596, -.813, 0.0));
vec3 yuv = vec3(
TEX(a_y_texture, v_texCoord).r,
TEX(a_uv_texture, v_texCoord * 0.5).rg);
- FRAGCOLOR = vec4(yuv_matrix * (yuv + yuv_adj), 1.0);
+ FRAGCOLOR = vec4(DoColorConversion(yuv), 1.0);
}
);
// clang-format on
} // namespace
-YUVToRGBConverter::YUVToRGBConverter(const GLVersionInfo& gl_version_info) {
+YUVToRGBConverter::YUVToRGBConverter(const GLVersionInfo& gl_version_info,
+ const gfx::ColorSpace color_space) {
+ std::unique_ptr<gfx::ColorTransform> color_transform =
+ gfx::ColorTransform::NewColorTransform(
+ color_space, color_space.GetAsFullRangeRGB(),
+ gfx::ColorTransform::Intent::INTENT_PERCEPTUAL);
+ DCHECK(color_transform->CanGetShaderSource());
+ std::string do_color_conversion = color_transform->GetShaderSource();
+
bool use_core_profile = gl_version_info.is_desktop_core_profile;
glGenFramebuffersEXT(1, &framebuffer_);
vertex_buffer_ = GLHelper::SetupQuadVertexBuffer();
@@ -82,10 +87,10 @@ YUVToRGBConverter::YUVToRGBConverter(const GLVersionInfo& gl_version_info) {
.c_str());
fragment_shader_ = GLHelper::LoadShader(
GL_FRAGMENT_SHADER,
- base::StringPrintf("%s\n%s",
+ base::StringPrintf("%s\n%s\n%s",
use_core_profile ? kFragmentHeaderCoreProfile
: kFragmentHeaderCompatiblityProfile,
- kFragmentShader)
+ do_color_conversion.c_str(), kFragmentShader)
.c_str());
program_ = GLHelper::SetupProgram(vertex_shader_, fragment_shader_);
diff --git a/chromium/ui/gl/yuv_to_rgb_converter.h b/chromium/ui/gl/yuv_to_rgb_converter.h
index 7d9f8222589..94fbf6a2edb 100644
--- a/chromium/ui/gl/yuv_to_rgb_converter.h
+++ b/chromium/ui/gl/yuv_to_rgb_converter.h
@@ -7,13 +7,18 @@
#include "ui/gfx/geometry/size.h"
+namespace gfx {
+class ColorSpace;
+} // namespace gfx
+
namespace gl {
struct GLVersionInfo;
class YUVToRGBConverter {
public:
- explicit YUVToRGBConverter(const GLVersionInfo& gl_version_info);
+ explicit YUVToRGBConverter(const GLVersionInfo& gl_version_info,
+ const gfx::ColorSpace color_space);
~YUVToRGBConverter();
// The input Y and UV textures should be bound to these texture objects
diff --git a/chromium/ui/keyboard/content/keyboard_ui_content.cc b/chromium/ui/keyboard/content/keyboard_ui_content.cc
index 4a40c654709..7a01622e498 100644
--- a/chromium/ui/keyboard/content/keyboard_ui_content.cc
+++ b/chromium/ui/keyboard/content/keyboard_ui_content.cc
@@ -230,7 +230,6 @@ void KeyboardUIContent::ReloadKeyboardIfNeeded() {
TRACE_EVENT0("vk", "ReloadKeyboardIfNeeded");
GetContentsWindow()->SetBounds(gfx::Rect());
keyboard_contents_->ClosePage();
- keyboard_controller()->SetKeyboardMode(FULL_WIDTH);
}
LoadContents(GetVirtualKeyboardUrl());
}
diff --git a/chromium/ui/keyboard/keyboard_controller.cc b/chromium/ui/keyboard/keyboard_controller.cc
index 343ee92cdd4..8eb698f5c7d 100644
--- a/chromium/ui/keyboard/keyboard_controller.cc
+++ b/chromium/ui/keyboard/keyboard_controller.cc
@@ -192,7 +192,7 @@ namespace keyboard {
class CallbackAnimationObserver : public ui::LayerAnimationObserver {
public:
CallbackAnimationObserver(const scoped_refptr<ui::LayerAnimator>& animator,
- base::Callback<void(void)> callback);
+ base::OnceCallback<void(void)> callback);
~CallbackAnimationObserver() override;
private:
@@ -202,16 +202,15 @@ class CallbackAnimationObserver : public ui::LayerAnimationObserver {
void OnLayerAnimationScheduled(ui::LayerAnimationSequence* seq) override {}
scoped_refptr<ui::LayerAnimator> animator_;
- base::Callback<void(void)> callback_;
+ base::OnceCallback<void(void)> callback_;
DISALLOW_COPY_AND_ASSIGN(CallbackAnimationObserver);
};
CallbackAnimationObserver::CallbackAnimationObserver(
const scoped_refptr<ui::LayerAnimator>& animator,
- base::Callback<void(void)> callback)
- : animator_(animator), callback_(callback) {
-}
+ base::OnceCallback<void(void)> callback)
+ : animator_(animator), callback_(std::move(callback)) {}
CallbackAnimationObserver::~CallbackAnimationObserver() {
animator_->RemoveObserver(this);
@@ -222,7 +221,8 @@ void CallbackAnimationObserver::OnLayerAnimationEnded(
if (animator_->is_animating())
return;
animator_->RemoveObserver(this);
- callback_.Run();
+ DCHECK(!callback_.is_null());
+ std::move(callback_).Run();
}
void CallbackAnimationObserver::OnLayerAnimationAborted(
@@ -237,9 +237,8 @@ KeyboardController::KeyboardController(std::unique_ptr<KeyboardUI> ui,
KeyboardLayoutDelegate* delegate)
: ui_(std::move(ui)),
layout_delegate_(delegate),
- show_on_resize_(false),
+ show_on_content_update_(false),
keyboard_locked_(false),
- keyboard_mode_(FULL_WIDTH),
state_(KeyboardControllerState::UNKNOWN),
weak_factory_report_lingering_state_(this),
weak_factory_will_hide_(this) {
@@ -319,7 +318,7 @@ void KeyboardController::SetContainerBounds(const gfx::Rect& new_bounds,
container_->SetBounds(new_bounds);
if (contents_loaded) {
- bool should_show = show_on_resize();
+ const bool should_show = show_on_content_update_;
if (state_ == KeyboardControllerState::LOADING_EXTENSION)
ChangeState(KeyboardControllerState::HIDDEN);
if (should_show) {
@@ -341,14 +340,10 @@ void KeyboardController::SetContainerBounds(const gfx::Rect& new_bounds,
}
}
- if (keyboard_mode() == FULL_WIDTH) {
- // We need to send out this notification only if keyboard is visible since
- // the contents window is resized even if keyboard is hidden.
- if (keyboard_visible())
- NotifyContentsBoundsChanging(new_bounds);
- } else if (keyboard_mode() == FLOATING) {
- NotifyContentsBoundsChanging(gfx::Rect());
- }
+ // We need to send out this notification only if keyboard is visible since
+ // the contents window is resized even if keyboard is hidden.
+ if (keyboard_visible())
+ NotifyContentsBoundsChanging(new_bounds);
}
void KeyboardController::AddObserver(KeyboardControllerObserver* observer) {
@@ -364,23 +359,6 @@ void KeyboardController::RemoveObserver(KeyboardControllerObserver* observer) {
observer_list_.RemoveObserver(observer);
}
-void KeyboardController::SetKeyboardMode(KeyboardMode mode) {
- if (keyboard_mode_ == mode)
- return;
-
- keyboard_mode_ = mode;
- // When keyboard is floating, no overscroll or resize is necessary. Sets
- // keyboard bounds to zero so overscroll or resize is disabled.
- if (keyboard_mode_ == FLOATING) {
- NotifyContentsBoundsChanging(gfx::Rect());
- } else if (keyboard_mode_ == FULL_WIDTH) {
- AdjustKeyboardBounds();
- // No animation is needed. Just change the bounds and ensure caret in
- // workarea.
- NotifyKeyboardBoundsChangingAndEnsrueCaretInWorkArea();
- }
-}
-
void KeyboardController::HideKeyboard(HideReason reason) {
TRACE_EVENT0("vk", "HideKeyboard");
@@ -389,7 +367,7 @@ void KeyboardController::HideKeyboard(HideReason reason) {
case KeyboardControllerState::HIDDEN:
return;
case KeyboardControllerState::LOADING_EXTENSION:
- show_on_resize_ = false;
+ show_on_content_update_ = false;
return;
case KeyboardControllerState::WILL_HIDE:
@@ -476,28 +454,17 @@ void KeyboardController::OnWindowBoundsChanged(aura::Window* window,
return;
int container_height = container_->bounds().height();
- if (keyboard_mode_ == FULL_WIDTH) {
- container_->SetBounds(gfx::Rect(new_bounds.x(),
- new_bounds.bottom() - container_height,
- new_bounds.width(),
- container_height));
- } else if (keyboard_mode_ == FLOATING) {
- // When screen rotate, horizontally center floating virtual keyboard
- // window and vertically align it to the bottom.
- int container_width = container_->bounds().width();
- container_->SetBounds(gfx::Rect(
- new_bounds.x() + (new_bounds.width() - container_width) / 2,
- new_bounds.bottom() - container_height,
- container_width,
- container_height));
- }
+
+ container_->SetBounds(gfx::Rect(new_bounds.x(),
+ new_bounds.bottom() - container_height,
+ new_bounds.width(), container_height));
}
void KeyboardController::Reload() {
if (ui_->HasContentsWindow()) {
// A reload should never try to show virtual keyboard. If keyboard is not
// visible before reload, it should keep invisible after reload.
- show_on_resize_ = false;
+ show_on_content_update_ = false;
ui_->ReloadKeyboardIfNeeded();
}
}
@@ -519,16 +486,16 @@ void KeyboardController::OnTextInputStateChanged(
if (should_hide) {
switch (state_) {
case KeyboardControllerState::LOADING_EXTENSION:
- show_on_resize_ = false;
+ show_on_content_update_ = false;
return;
case KeyboardControllerState::SHOWN:
ChangeState(KeyboardControllerState::WILL_HIDE);
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
- base::Bind(&KeyboardController::HideKeyboard,
- weak_factory_will_hide_.GetWeakPtr(),
- HIDE_REASON_AUTOMATIC),
+ base::BindOnce(&KeyboardController::HideKeyboard,
+ weak_factory_will_hide_.GetWeakPtr(),
+ HIDE_REASON_AUTOMATIC),
base::TimeDelta::FromMilliseconds(kHideKeyboardDelayMs));
return;
default:
@@ -597,7 +564,7 @@ void KeyboardController::PopulateKeyboardContent(int64_t display_id,
case KeyboardControllerState::SHOWN:
return;
case KeyboardControllerState::LOADING_EXTENSION:
- show_on_resize_ |= show_keyboard;
+ show_on_content_update_ |= show_keyboard;
return;
default:
break;
@@ -628,7 +595,7 @@ void KeyboardController::PopulateKeyboardContent(int64_t display_id,
switch (state_) {
case KeyboardControllerState::INITIAL:
DCHECK(ui_->GetContentsWindow()->bounds().height() == 0);
- show_on_resize_ = show_keyboard;
+ show_on_content_update_ = show_keyboard;
ChangeState(KeyboardControllerState::LOADING_EXTENSION);
return;
case KeyboardControllerState::WILL_HIDE:
@@ -654,15 +621,11 @@ void KeyboardController::PopulateKeyboardContent(int64_t display_id,
container_animator->set_preemption_strategy(
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET);
- if (keyboard_mode_ == FLOATING) {
- animation_observer_.reset();
- } else {
- animation_observer_.reset(new CallbackAnimationObserver(
- container_animator,
- base::Bind(&KeyboardController::ShowAnimationFinished,
- base::Unretained(this))));
- container_animator->AddObserver(animation_observer_.get());
- }
+ animation_observer_.reset(new CallbackAnimationObserver(
+ container_animator,
+ base::BindOnce(&KeyboardController::ShowAnimationFinished,
+ base::Unretained(this))));
+ container_animator->AddObserver(animation_observer_.get());
ui_->ShowKeyboardContainer(container_.get());
@@ -675,7 +638,7 @@ void KeyboardController::PopulateKeyboardContent(int64_t display_id,
container_->layer()->SetOpacity(1.0);
ChangeState(KeyboardControllerState::SHOWN);
- NotifyKeyboardBoundsChangingAndEnsrueCaretInWorkArea();
+ NotifyKeyboardBoundsChangingAndEnsureCaretInWorkArea();
}
bool KeyboardController::WillHideKeyboard() const {
@@ -689,7 +652,7 @@ void KeyboardController::ShowAnimationFinished() {
}
void KeyboardController::
- NotifyKeyboardBoundsChangingAndEnsrueCaretInWorkArea() {
+ NotifyKeyboardBoundsChangingAndEnsureCaretInWorkArea() {
// Notify observers after animation finished to prevent reveal desktop
// background during animation.
NotifyContentsBoundsChanging(container_->bounds());
@@ -697,20 +660,12 @@ void KeyboardController::
}
void KeyboardController::AdjustKeyboardBounds() {
- // When keyboard is floating, no resize is necessary.
- if (keyboard_mode_ == FLOATING)
- return;
-
- if (keyboard_mode_ == FULL_WIDTH) {
- // TODO(bshe): revisit this logic after we decide to support resize virtual
- // keyboard.
- int keyboard_height = GetContainerWindow()->bounds().height();
- const gfx::Rect& root_bounds = container_->GetRootWindow()->bounds();
- gfx::Rect new_bounds = root_bounds;
- new_bounds.set_y(root_bounds.height() - keyboard_height);
- new_bounds.set_height(keyboard_height);
- GetContainerWindow()->SetBounds(new_bounds);
- }
+ int keyboard_height = GetContainerWindow()->bounds().height();
+ const gfx::Rect& root_bounds = container_->GetRootWindow()->bounds();
+ gfx::Rect new_bounds = root_bounds;
+ new_bounds.set_y(root_bounds.height() - keyboard_height);
+ new_bounds.set_height(keyboard_height);
+ GetContainerWindow()->SetBounds(new_bounds);
}
void KeyboardController::CheckStateTransition(KeyboardControllerState prev,
@@ -745,7 +700,7 @@ void KeyboardController::ChangeState(KeyboardControllerState state) {
if (state != KeyboardControllerState::WILL_HIDE)
weak_factory_will_hide_.InvalidateWeakPtrs();
if (state != KeyboardControllerState::LOADING_EXTENSION)
- show_on_resize_ = false;
+ show_on_content_update_ = false;
for (KeyboardControllerObserver& observer : observer_list_)
observer.OnStateChanged(state);
@@ -755,8 +710,8 @@ void KeyboardController::ChangeState(KeyboardControllerState state) {
case KeyboardControllerState::WILL_HIDE:
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
FROM_HERE,
- base::Bind(&KeyboardController::ReportLingeringState,
- weak_factory_report_lingering_state_.GetWeakPtr()),
+ base::BindOnce(&KeyboardController::ReportLingeringState,
+ weak_factory_report_lingering_state_.GetWeakPtr()),
base::TimeDelta::FromMilliseconds(kReportLingeringStateDelayMs));
break;
default:
diff --git a/chromium/ui/keyboard/keyboard_controller.h b/chromium/ui/keyboard/keyboard_controller.h
index a8da8554f2e..47331edca04 100644
--- a/chromium/ui/keyboard/keyboard_controller.h
+++ b/chromium/ui/keyboard/keyboard_controller.h
@@ -35,17 +35,6 @@ class KeyboardUI;
// or hide animation finishes.
constexpr int kAnimationDistance = 30;
-enum KeyboardMode {
- // Invalid mode.
- NONE,
- // Full width virtual keyboard. The virtual keyboard window has the same width
- // as the display.
- FULL_WIDTH,
- // Floating virtual keyboard. The virtual keyboard window has customizable
- // width and is draggable.
- FLOATING,
-};
-
// Represents the current state of the keyboard managed by the controller.
// Don't change the numeric value of the members because they are used in UMA
// - VirtualKeyboard.ControllerStateTransition.
@@ -113,10 +102,6 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver,
bool keyboard_locked() const { return keyboard_locked_; }
- KeyboardMode keyboard_mode() const { return keyboard_mode_; }
-
- void SetKeyboardMode(KeyboardMode mode);
-
// Immediately starts hiding animation of virtual keyboard and notifies
// observers bounds change. This method forcibly sets keyboard_locked_
// false while closing the keyboard.
@@ -163,8 +148,6 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver,
// For access to SetContainerBounds.
friend class KeyboardLayoutManager;
- bool show_on_resize() const { return show_on_resize_; }
-
// aura::WindowObserver overrides
void OnWindowHierarchyChanged(const HierarchyChangeParams& params) override;
void OnWindowAddedToRootWindow(aura::Window* window) override;
@@ -183,8 +166,8 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver,
void OnShowImeIfNeeded() override;
// Sets the bounds of the container window. Shows the keyboard if contents
- // is first loaded and show_on_resize() is true. Called by
- // KayboardLayoutManager.
+ // is first loaded and show_on_content_update_ is true. Called by
+ // KeyboardLayoutManager.
void SetContainerBounds(const gfx::Rect& new_bounds,
const bool contents_loaded);
@@ -199,7 +182,7 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver,
// is aborted, it won't be called.
void ShowAnimationFinished();
- void NotifyKeyboardBoundsChangingAndEnsrueCaretInWorkArea();
+ void NotifyKeyboardBoundsChangingAndEnsureCaretInWorkArea();
// Called when the keyboard mode is set or the keyboard is moved to another
// display.
@@ -222,10 +205,11 @@ class KEYBOARD_EXPORT KeyboardController : public ui::InputMethodObserver,
// uses container_'s animator.
std::unique_ptr<CallbackAnimationObserver> animation_observer_;
- bool show_on_resize_;
+ // If true, show the keyboard window when keyboard UI content updates.
+ bool show_on_content_update_;
+
// If true, the keyboard is always visible even if no window has input focus.
bool keyboard_locked_;
- KeyboardMode keyboard_mode_;
KeyboardEventFilter event_filter_;
base::ObserverList<KeyboardControllerObserver> observer_list_;
diff --git a/chromium/ui/keyboard/keyboard_controller_unittest.cc b/chromium/ui/keyboard/keyboard_controller_unittest.cc
index 170ef7668cf..b1e23d904d8 100644
--- a/chromium/ui/keyboard/keyboard_controller_unittest.cc
+++ b/chromium/ui/keyboard/keyboard_controller_unittest.cc
@@ -11,6 +11,7 @@
#include "base/memory/ptr_util.h"
#include "base/run_loop.h"
#include "base/test/scoped_task_environment.h"
+#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/test/aura_test_helper.h"
@@ -293,8 +294,8 @@ class KeyboardControllerTest : public testing::TestWithParam<bool>,
if (controller_->ui()->GetContentsWindow()->bounds().height() == 0) {
// Set initial bounds for test keyboard window.
controller_->ui()->GetContentsWindow()->SetBounds(
- FullWidthKeyboardBoundsFromRootBounds(
- root_window()->bounds(), kDefaultVirtualKeyboardHeight));
+ KeyboardBoundsFromRootBounds(root_window()->bounds(),
+ kDefaultVirtualKeyboardHeight));
}
}
}
@@ -345,16 +346,16 @@ TEST_P(KeyboardControllerTest, KeyboardSize) {
ASSERT_EQ(screen_bounds.height(), initial_bounds.y());
VerifyKeyboardWindowSize(container, keyboard);
- // In FULL_WIDTH mode, attempt to change window width or move window up from
- // the bottom are ignored. Changing window height is supported.
+ // Attempt to change window width or move window up from the bottom are
+ // ignored. Changing window height is supported.
gfx::Rect expected_bounds(0,
screen_bounds.height() - 50,
screen_bounds.width(),
50);
// The x position of new bounds may not be 0 if shelf is on the left side of
- // screen. In FULL_WIDTH mode, the virtual keyboard should always align with
- // the left edge of screen. See http://crbug.com/510595.
+ // screen. The virtual keyboard should always align with the left edge of
+ // screen. See http://crbug.com/510595.
gfx::Rect new_bounds(10, 0, 50, 50);
keyboard->SetBounds(new_bounds);
ASSERT_EQ(expected_bounds, container->bounds());
@@ -371,7 +372,18 @@ TEST_P(KeyboardControllerTest, KeyboardSize) {
VerifyKeyboardWindowSize(container, keyboard);
}
-TEST_P(KeyboardControllerTest, KeyboardSizeMultiRootWindow) {
+// Flaky on Windows. See http://crbug.com/757044
+#if defined(OS_WIN)
+#define MAYBE_KeyboardSizeMultiRootWindow DISABLED_KeyboardSizeMultiRootWindow
+#else
+#define MAYBE_KeyboardSizeMultiRootWindow KeyboardSizeMultiRootWindow
+#endif
+
+// Since TEST_P does concatenation, macro prescan only occurs if it's invoked
+// indirectly.
+#define TEST_P_INDIRECT(a, b) TEST_P(a, b)
+
+TEST_P_INDIRECT(KeyboardControllerTest, MAYBE_KeyboardSizeMultiRootWindow) {
aura::Window* container(controller()->GetContainerWindow());
aura::Window* keyboard(ui()->GetContentsWindow());
gfx::Rect screen_bounds = root_window()->bounds();
@@ -403,18 +415,6 @@ TEST_P(KeyboardControllerTest, KeyboardSizeMultiRootWindow) {
VerifyKeyboardWindowSize(container, keyboard);
}
-TEST_P(KeyboardControllerTest, FloatingKeyboardSize) {
- aura::Window* container(controller()->GetContainerWindow());
- aura::Window* keyboard(ui()->GetContentsWindow());
- root_window()->AddChild(container);
- controller()->SetKeyboardMode(FLOATING);
- container->AddChild(keyboard);
- gfx::Rect new_bounds(0, 50, 50, 50);
- keyboard->SetBounds(new_bounds);
- ASSERT_EQ(new_bounds, container->bounds());
- VerifyKeyboardWindowSize(container, keyboard);
-}
-
// Tests that tapping/clicking inside the keyboard does not give it focus.
TEST_P(KeyboardControllerTest, ClickDoesNotFocusKeyboard) {
ScopedAccessibilityKeyboardEnabler scoped_keyboard_enabler;
@@ -529,66 +529,6 @@ TEST_P(KeyboardControllerTest, CheckOverscrollInsetDuringVisibilityChange) {
EXPECT_TRUE(ShouldEnableInsets(ui()->GetContentsWindow()));
}
-// Verify switch to FLOATING mode will reset the overscroll or resize and when
-// in FLOATING mode, overscroll or resize wont be triggered.
-TEST_P(KeyboardControllerTest, FloatingKeyboardDontOverscrollOrResize) {
- ScopedAccessibilityKeyboardEnabler scoped_keyboard_enabler;
- ui::DummyTextInputClient input_client(ui::TEXT_INPUT_TYPE_TEXT);
- ui::DummyTextInputClient no_input_client(ui::TEXT_INPUT_TYPE_NONE);
-
- base::RunLoop run_loop;
- aura::Window* container(controller()->GetContainerWindow());
- root_window()->AddChild(container);
- std::unique_ptr<KeyboardContainerObserver> keyboard_container_observer(
- new KeyboardContainerObserver(container, &run_loop));
- gfx::Rect screen_bounds = root_window()->bounds();
- ScopedTouchKeyboardEnabler scoped_touch_keyboard_enabler;
-
- SetFocus(&input_client);
- gfx::Rect expected_bounds(
- 0, screen_bounds.height() - kDefaultVirtualKeyboardHeight,
- screen_bounds.width(), kDefaultVirtualKeyboardHeight);
- // Verify overscroll or resize is in effect.
- EXPECT_EQ(expected_bounds, notified_bounds());
- EXPECT_EQ(1, number_of_calls());
-
- controller()->SetKeyboardMode(FLOATING);
- // Switch to FLOATING should clear overscroll or resize.
- EXPECT_EQ(gfx::Rect(), notified_bounds());
- EXPECT_EQ(2, number_of_calls());
- SetFocus(&no_input_client);
- run_loop.Run();
- EXPECT_EQ(gfx::Rect(), notified_bounds());
- EXPECT_EQ(3, number_of_calls());
- SetFocus(&input_client);
- // In FLOATING mode, no overscroll or resize should be triggered.
- EXPECT_EQ(3, number_of_calls());
- EXPECT_EQ(gfx::Rect(), controller()->current_keyboard_bounds());
-}
-
-// Verify switch to FULL_WIDTH mode will move virtual keyboard to the right
-// place and sets the correct overscroll.
-TEST_P(KeyboardControllerTest, SwitchToFullWidthVirtualKeyboard) {
- ScopedTouchKeyboardEnabler scoped_keyboard_enabler;
- ui::DummyTextInputClient input_client(ui::TEXT_INPUT_TYPE_TEXT);
-
- aura::Window* container(controller()->GetContainerWindow());
- root_window()->AddChild(container);
- gfx::Rect screen_bounds = root_window()->bounds();
- SetFocus(&input_client);
-
- controller()->SetKeyboardMode(FLOATING);
- EXPECT_EQ(gfx::Rect(), notified_bounds());
- EXPECT_EQ(gfx::Rect(), controller()->current_keyboard_bounds());
-
- controller()->SetKeyboardMode(FULL_WIDTH);
- gfx::Rect expected_bounds(
- 0, screen_bounds.height() - kDefaultVirtualKeyboardHeight,
- screen_bounds.width(), kDefaultVirtualKeyboardHeight);
- EXPECT_EQ(expected_bounds, notified_bounds());
- EXPECT_EQ(expected_bounds, controller()->current_keyboard_bounds());
-}
-
TEST_P(KeyboardControllerTest, AlwaysVisibleWhenLocked) {
ScopedAccessibilityKeyboardEnabler scoped_keyboard_enabler;
ui::DummyTextInputClient input_client_0(ui::TEXT_INPUT_TYPE_TEXT);
@@ -750,24 +690,25 @@ TEST_P(KeyboardControllerAnimationTest, ContainerShowWhileHide) {
EXPECT_EQ(1.0, layer->opacity());
}
-// Test for crbug.com/568274.
-TEST_P(KeyboardControllerTest, FloatingKeyboardShowOnFirstTap) {
- ScopedTouchKeyboardEnabler scoped_keyboard_enabler;
- aura::Window* container(controller()->GetContainerWindow());
- aura::Window* keyboard(ui()->GetContentsWindow());
- root_window()->AddChild(container);
+TEST_P(KeyboardControllerAnimationTest, SetBoundsOnOldKeyboardUiReference) {
+ ScopedAccessibilityKeyboardEnabler scoped_keyboard_enabler;
- controller()->SetKeyboardMode(FLOATING);
- container->AddChild(keyboard);
- // Mock focus on an input field.
- ui()->GetInputMethod()->ShowImeIfNeeded();
- // Mock set keyboard size from javascript side. In floating mode, virtual
- // keyboard's size is decided by client.
- gfx::Rect new_bounds(0, 50, 50, 50);
- keyboard->SetBounds(new_bounds);
- ASSERT_EQ(new_bounds, container->bounds());
- EXPECT_TRUE(keyboard->IsVisible());
- EXPECT_TRUE(container->IsVisible());
+ // Ensure keyboard ui is populated
+ ui::Layer* layer = keyboard_container()->layer();
+ ShowKeyboard();
+ RunAnimationForLayer(layer);
+
+ ASSERT_TRUE(controller()->ui());
+
+ aura::Window* container_window = controller()->GetContainerWindow();
+
+ // Simulate removal of keyboard controller from root window as done by
+ // RootWindowController::DeactivateKeyboard()
+ container_window->parent()->RemoveChild(container_window);
+
+ // lingering handle to the contents window is adjusted.
+ // container_window's LayoutManager should abort silently and not crash.
+ controller()->ui()->GetContentsWindow()->SetBounds(gfx::Rect());
}
TEST_P(KeyboardControllerTest, DisplayChangeShouldNotifyBoundsChange) {
@@ -777,7 +718,6 @@ TEST_P(KeyboardControllerTest, DisplayChangeShouldNotifyBoundsChange) {
aura::Window* container(controller()->GetContainerWindow());
root_window()->AddChild(container);
- controller()->SetKeyboardMode(FULL_WIDTH);
SetFocus(&input_client);
gfx::Rect new_bounds(0, 0, 1280, 800);
ASSERT_NE(new_bounds, root_window()->bounds());
diff --git a/chromium/ui/keyboard/keyboard_layout_manager.cc b/chromium/ui/keyboard/keyboard_layout_manager.cc
index 8b718c15da0..68d34977049 100644
--- a/chromium/ui/keyboard/keyboard_layout_manager.cc
+++ b/chromium/ui/keyboard/keyboard_layout_manager.cc
@@ -16,30 +16,19 @@ void KeyboardLayoutManager::OnWindowResized() {
if (contents_window_) {
gfx::Rect container_bounds = controller_->GetContainerWindow()->bounds();
// Always align container window and keyboard window.
- if (controller_->keyboard_mode() == FULL_WIDTH) {
- SetChildBounds(contents_window_, gfx::Rect(container_bounds.size()));
- } else {
- SetChildBoundsDirect(contents_window_,
- gfx::Rect(container_bounds.size()));
- }
+ SetChildBounds(contents_window_, gfx::Rect(container_bounds.size()));
}
}
void KeyboardLayoutManager::OnWindowAddedToLayout(aura::Window* child) {
DCHECK(!contents_window_);
contents_window_ = child;
- if (controller_->keyboard_mode() == FULL_WIDTH) {
- controller_->GetContainerWindow()->SetBounds(gfx::Rect());
- } else if (controller_->keyboard_mode() == FLOATING) {
- controller_->GetContainerWindow()->SetBounds(child->bounds());
- SetChildBoundsDirect(contents_window_, gfx::Rect(child->bounds().size()));
- }
+ controller_->GetContainerWindow()->SetBounds(gfx::Rect());
}
void KeyboardLayoutManager::SetChildBounds(aura::Window* child,
const gfx::Rect& requested_bounds) {
DCHECK(child == contents_window_);
-
TRACE_EVENT0("vk", "KeyboardLayoutSetChildBounds");
// Request to change the bounds of the contents window
@@ -49,17 +38,22 @@ void KeyboardLayoutManager::SetChildBounds(aura::Window* child,
const aura::Window* root_window =
controller_->GetContainerWindow()->GetRootWindow();
+
+ // If the keyboard has been deactivated, this reference will be null.
+ if (!root_window)
+ return;
+
gfx::Rect new_bounds = requested_bounds;
- if (controller_->keyboard_mode() == FULL_WIDTH) {
- // Honors only the height of the request bounds
- const gfx::Rect& window_bounds = root_window->bounds();
- new_bounds.set_y(window_bounds.height() - requested_bounds.height());
- // If shelf is positioned on the left side of screen, x is not 0. In
- // FULL_WIDTH mode, the virtual keyboard should always align with the left
- // edge of the screen. So manually set x to 0 here.
- new_bounds.set_x(0);
- new_bounds.set_width(window_bounds.width());
- }
+
+ // Honors only the height of the request bounds
+ const gfx::Rect& window_bounds = root_window->bounds();
+ new_bounds.set_y(window_bounds.height() - requested_bounds.height());
+ // If shelf is positioned on the left side of screen, x is not 0. In
+ // FULL_WIDTH mode, the virtual keyboard should always align with the left
+ // edge of the screen. So manually set x to 0 here.
+ new_bounds.set_x(0);
+ new_bounds.set_width(window_bounds.width());
+
// Containar bounds should only be reset when the contents window bounds
// actually change. Otherwise it interrupts the initial animation of showing
// the keyboard. Described in crbug.com/356753.
diff --git a/chromium/ui/keyboard/keyboard_test_util.cc b/chromium/ui/keyboard/keyboard_test_util.cc
index f62b41a538a..ebd8b715aba 100644
--- a/chromium/ui/keyboard/keyboard_test_util.cc
+++ b/chromium/ui/keyboard/keyboard_test_util.cc
@@ -92,8 +92,8 @@ void WaitControllerStateChangesTo(KeyboardControllerState state) {
waiter.Wait();
}
-gfx::Rect FullWidthKeyboardBoundsFromRootBounds(const gfx::Rect& root_bounds,
- int keyboard_height) {
+gfx::Rect KeyboardBoundsFromRootBounds(const gfx::Rect& root_bounds,
+ int keyboard_height) {
return gfx::Rect(root_bounds.x(), root_bounds.bottom() - keyboard_height,
root_bounds.width(), keyboard_height);
}
diff --git a/chromium/ui/keyboard/keyboard_test_util.h b/chromium/ui/keyboard/keyboard_test_util.h
index edca936431d..3d7dc4f6620 100644
--- a/chromium/ui/keyboard/keyboard_test_util.h
+++ b/chromium/ui/keyboard/keyboard_test_util.h
@@ -27,10 +27,9 @@ bool WaitUntilHidden();
void WaitControllerStateChangesTo(const KeyboardControllerState state);
// Gets the calculated keyboard bounds from |root_bounds|. The keyboard height
-// is specified by |keyboard_height|. This should be only called when keyboard
-// is in FULL_WDITH mode.
-gfx::Rect FullWidthKeyboardBoundsFromRootBounds(const gfx::Rect& root_bounds,
- int keyboard_height);
+// is specified by |keyboard_height|.
+gfx::Rect KeyboardBoundsFromRootBounds(const gfx::Rect& root_bounds,
+ int keyboard_height);
class FakeKeyboardUI : public KeyboardUI {
public:
diff --git a/chromium/ui/latency/latency_info.cc b/chromium/ui/latency/latency_info.cc
index ff1fffe2980..dbc6da7f05f 100644
--- a/chromium/ui/latency/latency_info.cc
+++ b/chromium/ui/latency/latency_info.cc
@@ -338,8 +338,8 @@ LatencyInfo::AsTraceableData() {
new base::DictionaryValue());
component_info->SetDouble("comp_id", static_cast<double>(lc.first.second));
component_info->SetDouble(
- "time",
- static_cast<double>(lc.second.event_time.ToInternalValue()));
+ "time", static_cast<double>(
+ lc.second.event_time.since_origin().InMicroseconds()));
component_info->SetDouble("count", lc.second.event_count);
component_info->SetDouble("sequence_number",
lc.second.sequence_number);
diff --git a/chromium/ui/latency/latency_info_unittest.cc b/chromium/ui/latency/latency_info_unittest.cc
index 16e4abd3681..3e872d4ac6c 100644
--- a/chromium/ui/latency/latency_info_unittest.cc
+++ b/chromium/ui/latency/latency_info_unittest.cc
@@ -10,21 +10,24 @@
namespace ui {
+namespace {
+
+// Returns a fake TimeTicks based on the given microsecond offset.
+base::TimeTicks ToTestTimeTicks(int64_t micros) {
+ return base::TimeTicks() + base::TimeDelta::FromMicroseconds(micros);
+}
+
+} // namespace
+
TEST(LatencyInfoTest, AddTwoSeparateEvent) {
LatencyInfo info;
info.set_trace_id(1);
EXPECT_FALSE(info.began());
- info.AddLatencyNumberWithTimestamp(INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT,
- 0,
- 1,
- base::TimeTicks::FromInternalValue(100),
- 1);
+ info.AddLatencyNumberWithTimestamp(INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0,
+ 1, ToTestTimeTicks(100), 1);
EXPECT_TRUE(info.began());
- info.AddLatencyNumberWithTimestamp(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
- 1,
- 5,
- base::TimeTicks::FromInternalValue(1000),
- 2);
+ info.AddLatencyNumberWithTimestamp(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 1,
+ 5, ToTestTimeTicks(1000), 2);
EXPECT_EQ(info.latency_components().size(), 2u);
LatencyInfo::LatencyComponent component;
@@ -36,27 +39,21 @@ TEST(LatencyInfoTest, AddTwoSeparateEvent) {
info.FindLatency(INPUT_EVENT_LATENCY_BEGIN_RWH_COMPONENT, 0, &component));
EXPECT_EQ(component.sequence_number, 1);
EXPECT_EQ(component.event_count, 1u);
- EXPECT_EQ(component.event_time.ToInternalValue(), 100);
+ EXPECT_EQ(component.event_time, ToTestTimeTicks(100));
EXPECT_TRUE(
info.FindLatency(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 1, &component));
EXPECT_EQ(component.sequence_number, 5);
EXPECT_EQ(component.event_count, 2u);
- EXPECT_EQ(component.event_time.ToInternalValue(), 1000);
+ EXPECT_EQ(component.event_time, ToTestTimeTicks(1000));
}
TEST(LatencyInfoTest, AddTwoSameEvent) {
LatencyInfo info;
info.set_trace_id(1);
- info.AddLatencyNumberWithTimestamp(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
- 0,
- 30,
- base::TimeTicks::FromInternalValue(100),
- 2);
- info.AddLatencyNumberWithTimestamp(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT,
- 0,
- 13,
- base::TimeTicks::FromInternalValue(200),
- 3);
+ info.AddLatencyNumberWithTimestamp(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0,
+ 30, ToTestTimeTicks(100), 2);
+ info.AddLatencyNumberWithTimestamp(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0,
+ 13, ToTestTimeTicks(200), 3);
EXPECT_EQ(info.latency_components().size(), 1u);
LatencyInfo::LatencyComponent component;
@@ -68,7 +65,7 @@ TEST(LatencyInfoTest, AddTwoSameEvent) {
info.FindLatency(INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, &component));
EXPECT_EQ(component.sequence_number, 30);
EXPECT_EQ(component.event_count, 5u);
- EXPECT_EQ(component.event_time.ToInternalValue(), (100 * 2 + 200 * 3) / 5);
+ EXPECT_EQ(component.event_time, ToTestTimeTicks((100 * 2 + 200 * 3) / 5));
}
TEST(LatencyInfoTest, RemoveLatency) {
diff --git a/chromium/ui/login/account_picker/md_screen_account_picker.js b/chromium/ui/login/account_picker/md_screen_account_picker.js
index fbd0d800d60..81741683f54 100644
--- a/chromium/ui/login/account_picker/md_screen_account_picker.js
+++ b/chromium/ui/login/account_picker/md_screen_account_picker.js
@@ -32,7 +32,7 @@ login.createScreen('AccountPickerScreen', 'account-picker', function() {
'removeUserPodFingerprintIcon',
'setPinEnabledForUser',
'setAuthType',
- 'setTouchViewState',
+ 'setTabletModeState',
'setPublicSessionDisplayName',
'setPublicSessionLocales',
'setPublicSessionKeyboardLayouts',
@@ -146,7 +146,7 @@ login.createScreen('AccountPickerScreen', 'account-picker', function() {
// again already. If that happens, ignore the onShow() call.
return;
}
- chrome.send('getTouchViewState');
+ chrome.send('getTabletModeState');
if (!this.firstShown_) return;
this.firstShown_ = false;
@@ -348,11 +348,11 @@ login.createScreen('AccountPickerScreen', 'account-picker', function() {
},
/**
- * Sets the state of touch view mode.
- * @param {boolean} isTouchViewEnabled true if the mode is on.
+ * Sets the state of tablet mode.
+ * @param {boolean} isTabletModeEnabled true if the mode is on.
*/
- setTouchViewState: function(isTouchViewEnabled) {
- $('pod-row').setTouchViewState(isTouchViewEnabled);
+ setTabletModeState: function(isTabletModeEnabled) {
+ $('pod-row').setTabletModeState(isTabletModeEnabled);
},
/**
diff --git a/chromium/ui/login/account_picker/md_user_pod_row.js b/chromium/ui/login/account_picker/md_user_pod_row.js
index c51218a828a..9f30bcfa6d7 100644
--- a/chromium/ui/login/account_picker/md_user_pod_row.js
+++ b/chromium/ui/login/account_picker/md_user_pod_row.js
@@ -2909,8 +2909,8 @@ cr.define('login', function() {
// Array of users that are shown (public/supervised/regular).
users_: [],
- // If we're in Touch View mode.
- touchViewEnabled_: false,
+ // If we're in tablet mode.
+ tabletModeEnabled_: false,
// If testing mode is enabled.
testingModeEnabled_: false,
@@ -2957,14 +2957,14 @@ cr.define('login', function() {
/**
* Return true if user pod row has only single user pod in it, which should
- * always be focused except desktop and touch view modes.
+ * always be focused except desktop and tablet modes.
* @type {boolean}
*/
get alwaysFocusSinglePod() {
var isDesktopUserManager = Oobe.getInstance().displayType ==
DISPLAY_TYPE.DESKTOP_USER_MANAGER;
- return (isDesktopUserManager || this.touchViewEnabled_) ?
+ return (isDesktopUserManager || this.tabletModeEnabled_) ?
false :
this.pods.length == 1;
},
@@ -3519,16 +3519,18 @@ cr.define('login', function() {
},
/**
- * Sets the state of touch view mode.
- * @param {boolean} isTouchViewEnabled true if the mode is on.
+ * Sets the state of tablet mode.
+ * @param {boolean} isTabletModeEnabled true if the mode is on.
*/
- setTouchViewState: function(isTouchViewEnabled) {
- this.touchViewEnabled_ = isTouchViewEnabled;
+ setTabletModeState: function(isTabletModeEnabled) {
+ this.tabletModeEnabled_ = isTabletModeEnabled;
this.pods.forEach(function(pod, index) {
- pod.actionBoxAreaElement.classList.toggle('forced', isTouchViewEnabled);
- if (pod.isPublicSessionPod)
+ pod.actionBoxAreaElement.classList.toggle(
+ 'forced', isTabletModeEnabled);
+ if (pod.isPublicSessionPod) {
pod.querySelector('.button-container')
- .classList.toggle('forced', isTouchViewEnabled);
+ .classList.toggle('forced', isTabletModeEnabled);
+ }
});
},
@@ -3677,6 +3679,8 @@ cr.define('login', function() {
// apply to account picker.
// This is a hacky solution: we can make #scroll-container hide the
// overflow area and manully position #inner-container.
+ // NOTE: The global states set here might need to be cleared in
+ // handleHide. Please update the code there when adding new stuff here.
var isScreenShrinked = this.isScreenShrinked_();
$('scroll-container')
.classList.toggle('disable-scroll', isScreenShrinked);
@@ -4784,6 +4788,11 @@ cr.define('login', function() {
event, this.listeners_[event][0], this.listeners_[event][1]);
}
$('login-header-bar').buttonsTabIndex = 0;
+
+ // Clear global states that should only applies to account picker.
+ $('scroll-container').classList.remove('disable-scroll');
+ $('inner-container').classList.remove('disable-scroll');
+ $('inner-container').style.top = 'unset';
},
/**
diff --git a/chromium/ui/login/account_picker/screen_account_picker.js b/chromium/ui/login/account_picker/screen_account_picker.js
index 9af9bf08945..dd272b971c4 100644
--- a/chromium/ui/login/account_picker/screen_account_picker.js
+++ b/chromium/ui/login/account_picker/screen_account_picker.js
@@ -39,7 +39,7 @@ login.createScreen('AccountPickerScreen', 'account-picker', function() {
'removeUserPodFingerprintIcon',
'setPinEnabledForUser',
'setAuthType',
- 'setTouchViewState',
+ 'setTabletModeState',
'setPublicSessionDisplayName',
'setPublicSessionLocales',
'setPublicSessionKeyboardLayouts',
@@ -148,7 +148,7 @@ login.createScreen('AccountPickerScreen', 'account-picker', function() {
// again already. If that happens, ignore the onShow() call.
return;
}
- chrome.send('getTouchViewState');
+ chrome.send('getTabletModeState');
if (!this.firstShown_) return;
this.firstShown_ = false;
@@ -425,11 +425,11 @@ login.createScreen('AccountPickerScreen', 'account-picker', function() {
},
/**
- * Sets the state of touch view mode.
- * @param {boolean} isTouchViewEnabled true if the mode is on.
+ * Sets the state of tablet mode.
+ * @param {boolean} isTabletModeEnabled true if the mode is on.
*/
- setTouchViewState: function(isTouchViewEnabled) {
- $('pod-row').setTouchViewState(isTouchViewEnabled);
+ setTabletModeState: function(isTabletModeEnabled) {
+ $('pod-row').setTabletModeState(isTabletModeEnabled);
},
/**
diff --git a/chromium/ui/login/account_picker/user_pod_row.css b/chromium/ui/login/account_picker/user_pod_row.css
index b8a0ef64dd6..29bc6f66bf4 100644
--- a/chromium/ui/login/account_picker/user_pod_row.css
+++ b/chromium/ui/login/account_picker/user_pod_row.css
@@ -163,7 +163,7 @@ html[dir=rtl] .main-pane {
}
.name-container,
-.pod.focused:not(.multiprofiles-policy-applied):not(.public-account) .auth-container {
+.pod.focused:not(.multiprofiles-policy-applied) .auth-container {
background-color: white;
display: flex;
position: absolute;
diff --git a/chromium/ui/login/account_picker/user_pod_row.js b/chromium/ui/login/account_picker/user_pod_row.js
index 2bbe7060b88..eeaf35190a4 100644
--- a/chromium/ui/login/account_picker/user_pod_row.js
+++ b/chromium/ui/login/account_picker/user_pod_row.js
@@ -2684,8 +2684,8 @@ cr.define('login', function() {
// Array of users that are shown (public/supervised/regular).
users_: [],
- // If we're in Touch View mode.
- touchViewEnabled_: false,
+ // If we're in tablet mode.
+ tabletModeEnabled_: false,
/** @override */
decorate: function() {
@@ -2721,15 +2721,16 @@ cr.define('login', function() {
/**
* Return true if user pod row has only single user pod in it, which should
- * always be focused except desktop and touch view modes.
+ * always be focused except desktop and tablet modes.
* @type {boolean}
*/
get alwaysFocusSinglePod() {
var isDesktopUserManager = Oobe.getInstance().displayType ==
DISPLAY_TYPE.DESKTOP_USER_MANAGER;
- return (isDesktopUserManager || this.touchViewEnabled_) ?
- false : this.children.length == 1;
+ return (isDesktopUserManager || this.tabletModeEnabled_) ?
+ false :
+ this.children.length == 1;
},
/**
@@ -3246,13 +3247,14 @@ cr.define('login', function() {
},
/**
- * Sets the state of touch view mode.
- * @param {boolean} isTouchViewEnabled true if the mode is on.
+ * Sets the state of tablet mode.
+ * @param {boolean} isTabletModeEnabled true if the mode is on.
*/
- setTouchViewState: function(isTouchViewEnabled) {
- this.touchViewEnabled_ = isTouchViewEnabled;
+ setTabletModeState: function(isTabletModeEnabled) {
+ this.tabletModeEnabled_ = isTabletModeEnabled;
this.pods.forEach(function(pod, index) {
- pod.actionBoxAreaElement.classList.toggle('forced', isTouchViewEnabled);
+ pod.actionBoxAreaElement.classList.toggle(
+ 'forced', isTabletModeEnabled);
});
},
diff --git a/chromium/ui/message_center/BUILD.gn b/chromium/ui/message_center/BUILD.gn
index 15f7dd5d819..95c62220a34 100644
--- a/chromium/ui/message_center/BUILD.gn
+++ b/chromium/ui/message_center/BUILD.gn
@@ -4,8 +4,9 @@
import("//build/config/features.gni")
import("//build/config/ui.gni")
-import("//testing/test.gni")
import("//components/vector_icons/vector_icons.gni")
+import("//testing/test.gni")
+import("//ui/base/ui_features.gni")
aggregate_vector_icons("message_center_vector_icons") {
icon_directory = "vector_icons"
@@ -27,12 +28,13 @@ component("message_center") {
deps = [
"//base",
"//ui/base",
+ "//ui/strings",
"//url",
]
defines = [ "MESSAGE_CENTER_IMPLEMENTATION" ]
- if (!is_ios && !is_android) {
+ if (enable_message_center) {
deps += [
":message_center_vector_icons",
"//base:i18n",
@@ -46,7 +48,6 @@ component("message_center") {
"//ui/gfx/geometry",
"//ui/native_theme",
"//ui/resources",
- "//ui/strings",
]
configs += [
@@ -122,10 +123,6 @@ component("message_center") {
"views/constants.h",
"views/desktop_popup_alignment_delegate.cc",
"views/desktop_popup_alignment_delegate.h",
- "views/message_bubble_base.cc",
- "views/message_bubble_base.h",
- "views/message_center_bubble.cc",
- "views/message_center_bubble.h",
"views/message_center_button_bar.cc",
"views/message_center_button_bar.h",
"views/message_center_controller.h",
@@ -192,16 +189,17 @@ component("message_center") {
}
}
-static_library("test_support") {
- testonly = true
+if (enable_message_center) {
+ static_library("test_support") {
+ testonly = true
- if (!is_ios && !is_android) {
sources = [
"fake_message_center.cc",
"fake_message_center.h",
"fake_message_center_tray_delegate.cc",
"fake_message_center_tray_delegate.h",
]
+
deps = [
"//base",
"//base/test:test_support",
@@ -209,53 +207,52 @@ static_library("test_support") {
"//ui/gfx",
"//ui/gfx/geometry",
]
- }
-
- public_deps = [
- ":message_center",
- ]
-}
-
-test("message_center_unittests") {
- sources = [
- "test/run_all_unittests.cc",
- ]
- deps = [
- ":message_center",
- ":test_support",
- "//base",
- "//base/test:test_support",
- "//skia",
- "//testing/gmock",
- "//testing/gtest",
- "//ui/base",
- "//ui/base:test_support",
- "//ui/events",
- "//ui/events:test_support",
- "//ui/gfx",
- "//ui/gfx/geometry",
- "//ui/gl",
- "//ui/gl:test_support",
- "//ui/resources",
- "//ui/resources:ui_test_pak",
- "//url",
- ]
-
- data_deps = [
- "//third_party/mesa:osmesa",
- "//ui/resources:ui_test_pak_data",
- ]
+ public_deps = [
+ ":message_center",
+ ]
+ }
- if (!is_ios && !is_android) {
- sources += [
+ test("message_center_unittests") {
+ sources = [
"cocoa/notification_controller_unittest.mm",
"cocoa/popup_collection_unittest.mm",
"cocoa/popup_controller_unittest.mm",
"message_center_impl_unittest.cc",
"message_center_tray_unittest.cc",
+ "mojo/struct_traits_unittest.cc",
"notification_delegate_unittest.cc",
"notification_list_unittest.cc",
+ "test/run_all_unittests.cc",
+ ]
+
+ deps = [
+ ":message_center",
+ ":test_support",
+ "//base",
+ "//base/test:test_support",
+ "//mojo/edk/system",
+ "//skia",
+ "//testing/gmock",
+ "//testing/gtest",
+ "//ui/base",
+ "//ui/base:test_support",
+ "//ui/events",
+ "//ui/events:test_support",
+ "//ui/gfx",
+ "//ui/gfx:test_support",
+ "//ui/gfx/geometry",
+ "//ui/gl",
+ "//ui/gl:test_support",
+ "//ui/message_center/mojo:test_interfaces",
+ "//ui/resources",
+ "//ui/resources:ui_test_pak",
+ "//url",
+ ]
+
+ data_deps = [
+ "//third_party/mesa:osmesa",
+ "//ui/resources:ui_test_pak_data",
]
if (is_mac) {
@@ -281,14 +278,5 @@ test("message_center_unittests") {
"//ui/views:test_support",
]
}
-
- if (!is_ios) {
- sources += [ "mojo/struct_traits_unittest.cc" ]
- deps += [
- "//mojo/edk/system",
- "//ui/gfx:test_support",
- "//ui/message_center/mojo:test_interfaces",
- ]
- }
- } # !is_ios && !is_android
+ }
}
diff --git a/chromium/ui/message_center/OWNERS b/chromium/ui/message_center/OWNERS
index cc04892d667..134480b4cbc 100644
--- a/chromium/ui/message_center/OWNERS
+++ b/chromium/ui/message_center/OWNERS
@@ -1,5 +1,6 @@
dewittj@chromium.org
mukai@chromium.org
+peter@chromium.org
stevenjb@chromium.org
yoshiki@chromium.org
diff --git a/chromium/ui/message_center/dummy_message_center.cc b/chromium/ui/message_center/dummy_message_center.cc
index 26225db6e72..56410a6ec3d 100644
--- a/chromium/ui/message_center/dummy_message_center.cc
+++ b/chromium/ui/message_center/dummy_message_center.cc
@@ -6,11 +6,11 @@
#include "ui/message_center/message_center.h"
// This file contains dummy implementation of MessageCenter and used to compile
-// and link with Android and iOS implementations of Chrome which do not have
+// and link with Android implementations of Chrome which do not have
// notification systems yet. This is to avoid spreading compile-time flags
// everywhere in the code.
-#if !defined(OS_ANDROID) && !defined(OS_IOS)
-#error This file should only be used in Android or iOS builds.
+#if !defined(OS_ANDROID)
+#error This file should only be used in Android.
#endif
namespace message_center {
diff --git a/chromium/ui/message_center/fake_message_center.cc b/chromium/ui/message_center/fake_message_center.cc
index 1900b0e65f6..c61176eda10 100644
--- a/chromium/ui/message_center/fake_message_center.cc
+++ b/chromium/ui/message_center/fake_message_center.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "ui/message_center/fake_message_center.h"
+#include "base/strings/string_util.h"
#include "ui/message_center/notification_list.h"
namespace message_center {
@@ -52,7 +53,11 @@ bool FakeMessageCenter::HasClickedListener(const std::string& id) {
message_center::Notification* FakeMessageCenter::FindVisibleNotificationById(
const std::string& id) {
- return NULL;
+ for (auto* notification : GetVisibleNotifications()) {
+ if (id == notification->id())
+ return notification;
+ }
+ return nullptr;
}
const NotificationList::Notifications&
@@ -142,6 +147,13 @@ void FakeMessageCenter::RestartPopupTimers() {}
void FakeMessageCenter::PausePopupTimers() {}
+const base::string16& FakeMessageCenter::GetProductOSName() const {
+ return base::EmptyString16();
+}
+
+void FakeMessageCenter::SetProductOSName(
+ const base::string16& product_os_name) {}
+
void FakeMessageCenter::DisableTimersForTest() {}
void FakeMessageCenter::EnableChangeQueueForTest(bool enabled) {}
diff --git a/chromium/ui/message_center/fake_message_center.h b/chromium/ui/message_center/fake_message_center.h
index 7a8766ab2be..c489f6721b1 100644
--- a/chromium/ui/message_center/fake_message_center.h
+++ b/chromium/ui/message_center/fake_message_center.h
@@ -68,6 +68,8 @@ class FakeMessageCenter : public MessageCenter {
bool IsMessageCenterVisible() const override;
void RestartPopupTimers() override;
void PausePopupTimers() override;
+ const base::string16& GetProductOSName() const override;
+ void SetProductOSName(const base::string16& product_os_name) override;
protected:
void DisableTimersForTest() override;
diff --git a/chromium/ui/message_center/message_center.cc b/chromium/ui/message_center/message_center.cc
index fde6d8d280b..aa305a37a2e 100644
--- a/chromium/ui/message_center/message_center.cc
+++ b/chromium/ui/message_center/message_center.cc
@@ -4,8 +4,10 @@
#include "ui/message_center/message_center.h"
+#include "base/command_line.h"
#include "base/observer_list.h"
#include "ui/message_center/message_center_impl.h"
+#include "ui/message_center/message_center_switches.h"
namespace message_center {
@@ -34,6 +36,21 @@ void MessageCenter::Shutdown() {
g_message_center = NULL;
}
+// static
+bool MessageCenter::IsNewStyleNotificationEnabled() {
+// For Chrome OS, the default is Enabled.
+// For other platforms, the default is Disabled.
+#if defined(OS_CHROMEOS)
+ // Returns true if not explicitly disabled.
+ return !base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kDisableMessageCenterNewStyleNotification);
+#else
+ // Returns true if explicitly enabled.
+ return base::CommandLine::ForCurrentProcess()->HasSwitch(
+ switches::kEnableMessageCenterNewStyleNotification);
+#endif
+}
+
MessageCenter::MessageCenter() {
}
diff --git a/chromium/ui/message_center/message_center.h b/chromium/ui/message_center/message_center.h
index 05c00662d43..2eebf0ff4b7 100644
--- a/chromium/ui/message_center/message_center.h
+++ b/chromium/ui/message_center/message_center.h
@@ -63,6 +63,10 @@ class MESSAGE_CENTER_EXPORT MessageCenter {
// Destroys the global message_center object.
static void Shutdown();
+ // Returns if new style notification is enabled, i.e. NotificationViewMD is
+ // used instead of NotificationView.
+ static bool IsNewStyleNotificationEnabled();
+
// Management of the observer list.
virtual void AddObserver(MessageCenterObserver* observer) = 0;
virtual void RemoveObserver(MessageCenterObserver* observer) = 0;
@@ -189,6 +193,11 @@ class MESSAGE_CENTER_EXPORT MessageCenter {
// example, after the mouse leaves the popup.)
virtual void RestartPopupTimers() = 0;
+ // "Chromium OS" or "Chrome OS" in the current locale.
+ // Return empty string if not on these platforms.
+ virtual const base::string16& GetProductOSName() const = 0;
+ virtual void SetProductOSName(const base::string16& product_os_name) = 0;
+
protected:
friend class ::DownloadNotification;
friend class ::DownloadNotificationTestBase;
diff --git a/chromium/ui/message_center/message_center_impl.cc b/chromium/ui/message_center/message_center_impl.cc
index c4396746704..e2369ca3cb2 100644
--- a/chromium/ui/message_center/message_center_impl.cc
+++ b/chromium/ui/message_center/message_center_impl.cc
@@ -15,6 +15,7 @@
#include "base/memory/ptr_util.h"
#include "base/observer_list.h"
#include "base/stl_util.h"
+#include "base/strings/string_util.h"
#include "build/build_config.h"
#include "ui/message_center/message_center_style.h"
#include "ui/message_center/message_center_switches.h"
@@ -943,6 +944,15 @@ void MessageCenterImpl::PausePopupTimers() {
popup_timers_controller_->PauseAll();
}
+const base::string16& MessageCenterImpl::GetProductOSName() const {
+ return product_os_name_;
+}
+
+void MessageCenterImpl::SetProductOSName(
+ const base::string16& product_os_name) {
+ product_os_name_ = product_os_name;
+}
+
void MessageCenterImpl::DisableTimersForTest() {
popup_timers_controller_.reset();
}
diff --git a/chromium/ui/message_center/message_center_impl.h b/chromium/ui/message_center/message_center_impl.h
index 3dd9c7f349a..ea4348a36ef 100644
--- a/chromium/ui/message_center/message_center_impl.h
+++ b/chromium/ui/message_center/message_center_impl.h
@@ -84,6 +84,8 @@ class MessageCenterImpl : public MessageCenter,
void EnterQuietModeWithExpire(const base::TimeDelta& expires_in) override;
void RestartPopupTimers() override;
void PausePopupTimers() override;
+ const base::string16& GetProductOSName() const override;
+ void SetProductOSName(const base::string16& product_os_name) override;
void ForceNotificationFlush(const std::string& id) override;
// NotificationBlocker::Observer overrides:
@@ -137,6 +139,8 @@ class MessageCenterImpl : public MessageCenter,
// center is visible.
std::unique_ptr<internal::ChangeQueue> notification_queue_;
+ base::string16 product_os_name_;
+
DISALLOW_COPY_AND_ASSIGN(MessageCenterImpl);
};
diff --git a/chromium/ui/message_center/message_center_style.h b/chromium/ui/message_center/message_center_style.h
index be5acf24780..0caf6711cb7 100644
--- a/chromium/ui/message_center/message_center_style.h
+++ b/chromium/ui/message_center/message_center_style.h
@@ -9,6 +9,7 @@
#include "build/build_config.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/color_palette.h"
#include "ui/gfx/geometry/size.h"
#include "ui/message_center/message_center_export.h"
@@ -28,6 +29,7 @@ const int kNotificationImageBorderSize = 10;
const int kNotificationPreferredImageWidth = 360;
const int kNotificationPreferredImageHeight = 240;
const int kSmallImageSize = 16;
+const int kSmallImageSizeMD = 18;
const int kSmallImagePadding = 4;
// Limits.
@@ -100,6 +102,15 @@ const SkColor kSmallImageMaskBackgroundColor = SkColorSetRGB(0xa3, 0xa3, 0xa3);
const SkColor kControlButtonBackgroundColor =
SkColorSetA(SK_ColorWHITE, 0.9 * 0xff);
+// Accent colors of system notifications.
+const SkColor kSystemNotificationColorNormal = SkColorSetRGB(0x33, 0x67, 0xd6);
+const SkColor kSystemNotificationColorWarning = SkColorSetRGB(0xea, 0x61, 0x0);
+const SkColor kSystemNotificationColorCriticalWarning =
+ SkColorSetRGB(0xc5, 0x39, 0x29);
+
+// Default accent color of notifications that are not generated by system.
+const SkColor kNotificationDefaultAccentColor = gfx::kChromeIconGrey;
+
// Limits.
// Given the size of an image, returns the size of the properly scaled-up image
diff --git a/chromium/ui/message_center/message_center_tray.h b/chromium/ui/message_center/message_center_tray.h
index 339654d5d90..50a5acc0060 100644
--- a/chromium/ui/message_center/message_center_tray.h
+++ b/chromium/ui/message_center/message_center_tray.h
@@ -21,10 +21,6 @@ namespace message_center {
class MessageCenter;
-// Implementation found with each supported platform's implementation of
-// MessageCenterTrayDelegate.
-MessageCenterTrayDelegate* CreateMessageCenterTray();
-
// Class that observes a MessageCenter. Manages the popup and message center
// bubbles. Tells the MessageCenterTrayHost when the tray is changed, as well
// as when bubbles are shown and hidden.
diff --git a/chromium/ui/message_center/notification.cc b/chromium/ui/message_center/notification.cc
index b3387f0b81f..6e1bc1711cb 100644
--- a/chromium/ui/message_center/notification.cc
+++ b/chromium/ui/message_center/notification.cc
@@ -5,8 +5,17 @@
#include "ui/message_center/notification.h"
#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/gfx/image/image_skia.h"
+#include "ui/gfx/image/image_skia_operations.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/gfx/vector_icon_types.h"
+#include "ui/message_center/message_center.h"
+#include "ui/message_center/message_center_style.h"
#include "ui/message_center/notification_delegate.h"
#include "ui/message_center/notification_types.h"
+#include "ui/strings/grit/ui_strings.h"
namespace message_center {
@@ -14,6 +23,15 @@ namespace {
unsigned g_next_serial_number_ = 0;
+const gfx::ImageSkia CreateSolidColorImage(int width,
+ int height,
+ SkColor color) {
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(width, height);
+ bitmap.eraseColor(color);
+ return gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
+}
+
} // namespace
NotificationItem::NotificationItem(const base::string16& title,
@@ -43,6 +61,7 @@ RichNotificationData::RichNotificationData(const RichNotificationData& other)
small_image(other.small_image),
items(other.items),
progress(other.progress),
+ progress_status(other.progress_status),
buttons(other.buttons),
should_make_spoken_feedback_for_popup_updates(
other.should_make_spoken_feedback_for_popup_updates),
@@ -53,7 +72,10 @@ RichNotificationData::RichNotificationData(const RichNotificationData& other)
vibration_pattern(other.vibration_pattern),
renotify(other.renotify),
silent(other.silent),
- accessible_name(other.accessible_name) {}
+ accessible_name(other.accessible_name),
+ accent_color(other.accent_color),
+ use_image_as_icon(other.use_image_as_icon) {
+}
RichNotificationData::~RichNotificationData() = default;
@@ -161,6 +183,18 @@ bool Notification::UseOriginAsContextMessage() const {
origin_url_.SchemeIsHTTPOrHTTPS();
}
+gfx::Image Notification::GenerateMaskedSmallIcon(SkColor color) const {
+ if (!vector_small_image().is_empty())
+ return gfx::Image(gfx::CreateVectorIcon(vector_small_image(), color));
+
+ if (small_image().IsEmpty())
+ return small_image();
+
+ gfx::ImageSkia image = small_image().AsImageSkia();
+ return gfx::Image(gfx::ImageSkiaOperations::CreateMaskedImage(
+ CreateSolidColorImage(image.width(), image.height(), color), image));
+}
+
// static
std::unique_ptr<Notification> Notification::CreateSystemNotification(
const std::string& notification_id,
@@ -169,14 +203,60 @@ std::unique_ptr<Notification> Notification::CreateSystemNotification(
const gfx::Image& icon,
const std::string& system_component_id,
const base::Closure& click_callback) {
- std::unique_ptr<Notification> notification(new Notification(
+ std::unique_ptr<Notification> notification = CreateSystemNotification(
NOTIFICATION_TYPE_SIMPLE, notification_id, title, message, icon,
base::string16() /* display_source */, GURL(),
NotifierId(NotifierId::SYSTEM_COMPONENT, system_component_id),
RichNotificationData(),
- new HandleNotificationClickedDelegate(click_callback)));
+ new HandleNotificationClickedDelegate(click_callback), gfx::kNoneIcon,
+ SystemNotificationWarningLevel::CRITICAL_WARNING);
notification->SetSystemPriority();
return notification;
}
+// static
+std::unique_ptr<Notification> Notification::CreateSystemNotification(
+ NotificationType type,
+ const std::string& id,
+ const base::string16& title,
+ const base::string16& message,
+ const gfx::Image& icon,
+ const base::string16& display_source,
+ const GURL& origin_url,
+ const NotifierId& notifier_id,
+ const RichNotificationData& optional_fields,
+ scoped_refptr<NotificationDelegate> delegate,
+ const gfx::VectorIcon& small_image,
+ SystemNotificationWarningLevel color_type) {
+ SkColor color = message_center::kSystemNotificationColorNormal;
+ switch (color_type) {
+ case SystemNotificationWarningLevel::NORMAL:
+ color = message_center::kSystemNotificationColorNormal;
+ break;
+ case SystemNotificationWarningLevel::WARNING:
+ color = message_center::kSystemNotificationColorWarning;
+ break;
+ case SystemNotificationWarningLevel::CRITICAL_WARNING:
+ color = message_center::kSystemNotificationColorCriticalWarning;
+ break;
+ }
+ base::string16 display_source_or_default = display_source;
+ if (display_source_or_default.empty()) {
+ display_source_or_default = l10n_util::GetStringFUTF16(
+ IDS_MESSAGE_CENTER_NOTIFICATION_CHROMEOS_SYSTEM,
+ MessageCenter::Get()->GetProductOSName());
+ }
+ std::unique_ptr<Notification> notification = base::MakeUnique<Notification>(
+ type, id, title, message, icon, display_source_or_default, origin_url,
+ notifier_id, optional_fields, delegate);
+ notification->set_accent_color(color);
+ notification->set_small_image(
+ small_image.is_empty()
+ ? gfx::Image()
+ : gfx::Image(gfx::CreateVectorIcon(small_image, color)));
+ if (!small_image.is_empty())
+ notification->set_vector_small_image(small_image);
+ return notification;
+}
+
} // namespace message_center
diff --git a/chromium/ui/message_center/notification.h b/chromium/ui/message_center/notification.h
index b8277519199..a3cd1dfe04b 100644
--- a/chromium/ui/message_center/notification.h
+++ b/chromium/ui/message_center/notification.h
@@ -14,24 +14,28 @@
#include "base/strings/string16.h"
#include "base/time/time.h"
#include "base/values.h"
+#include "mojo/public/cpp/bindings/struct_traits.h" // nogncheck
+#include "third_party/skia/include/core/SkColor.h"
+#include "ui/gfx/color_palette.h"
#include "ui/gfx/image/image.h"
+#include "ui/gfx/paint_vector_icon.h"
+#include "ui/gfx/skia_util.h"
+#include "ui/gfx/vector_icon_types.h"
#include "ui/message_center/message_center_export.h"
#include "ui/message_center/notification_delegate.h"
#include "ui/message_center/notification_types.h"
#include "ui/message_center/notifier_settings.h"
#include "url/gurl.h"
-#if !defined(OS_IOS)
-#include "mojo/public/cpp/bindings/struct_traits.h" // nogncheck
-#endif
+namespace gfx {
+struct VectorIcon;
+} // namespace gfx
namespace message_center {
-#if !defined(OS_IOS)
namespace mojom {
class NotificationDataView;
}
-#endif
// Represents an individual item in NOTIFICATION_TYPE_MULTIPLE notifications.
struct MESSAGE_CENTER_EXPORT NotificationItem {
@@ -50,6 +54,8 @@ enum class ButtonType {
TEXT
};
+enum class SystemNotificationWarningLevel { NORMAL, WARNING, CRITICAL_WARNING };
+
// Represents a button to be shown as part of a notification.
struct MESSAGE_CENTER_EXPORT ButtonInfo {
explicit ButtonInfo(const base::string16& title);
@@ -102,13 +108,33 @@ class MESSAGE_CENTER_EXPORT RichNotificationData {
// notification. Optional.
gfx::Image small_image;
+ // Vector version of |small_image|.
+ // Used by Notification::GenerateMaskedSmallIcon.
+ // If not available, |small_image| will be used by the method. Optional.
+ //
+ // Due to the restriction of CreateVectorIcon, this should be a pointer to
+ // globally defined VectorIcon instance e.g. kNotificationCapsLockIcon.
+ // gfx::Image created by gfx::CreateVectorIcon internally stores reference to
+ // VectorIcon, so the VectorIcon should live longer than gfx::Image instance.
+ // As a temporary solution to this problem, we make this variable a pointer
+ // and only pass globally defined constants.
+ // TODO(tetsui): Remove the pointer, after fixing VectorIconSource not to
+ // retain VectorIcon reference. https://crbug.com/760866
+ const gfx::VectorIcon* vector_small_image = &gfx::kNoneIcon;
+
// Items to display on the notification. Only applicable for notifications
// that have type NOTIFICATION_TYPE_MULTIPLE.
std::vector<NotificationItem> items;
// Progress, in range of [0-100], of NOTIFICATION_TYPE_PROGRESS notifications.
+ // Values outside of the range (e.g. -1) will show an infinite loading
+ // progress bar.
int progress = 0;
+ // Status text string shown in NOTIFICATION_TYPE_PROGRESS notifications.
+ // If MD style notification is not enabled, this attribute is ignored.
+ base::string16 progress_status;
+
// Buttons that should show up on the notification. A maximum of 16 buttons
// is supported by the current implementation, but this may differ between
// platforms.
@@ -142,6 +168,17 @@ class MESSAGE_CENTER_EXPORT RichNotificationData {
// An accessible description of the notification's contents.
base::string16 accessible_name;
+
+ // Unified theme color used in new style notification.
+ // Usually, it should not be set directly.
+ // For system notification, CreateSystemNotification with
+ // SystemNotificationWarningLevel should be used.
+ SkColor accent_color = SK_ColorTRANSPARENT;
+
+ // Shows |image| as the right icon when notification is collapsed,
+ // and hides the icon when the notification is expanded.
+ // This is only effective when new style notification is enabled.
+ bool use_image_as_icon = false;
};
class MESSAGE_CENTER_EXPORT Notification {
@@ -275,6 +312,14 @@ class MESSAGE_CENTER_EXPORT Notification {
int progress() const { return optional_fields_.progress; }
void set_progress(int progress) { optional_fields_.progress = progress; }
+
+ base::string16 progress_status() const {
+ return optional_fields_.progress_status;
+ }
+ void set_progress_status(const base::string16& progress_status) {
+ optional_fields_.progress_status = progress_status;
+ }
+
// End unpacked values.
// Images fetched asynchronously.
@@ -289,6 +334,23 @@ class MESSAGE_CENTER_EXPORT Notification {
optional_fields_.small_image = image;
}
+ const gfx::VectorIcon& vector_small_image() const {
+ return *optional_fields_.vector_small_image;
+ }
+ // Due to the restriction of CreateVectorIcon, this should be a pointer to
+ // globally defined VectorIcon instance e.g. kNotificationCapsLockIcon.
+ // See detailed comment in RichNotificationData::vector_small_image.
+ void set_vector_small_image(const gfx::VectorIcon& image) {
+ optional_fields_.vector_small_image = &image;
+ }
+
+ // Mask the color of |small_image| to the given |color|.
+ // If |vector_small_image| is available, it returns the vector image
+ // filled by the |color|.
+ // Otherwise, it uses alpha channel of the rasterized |small_image| for
+ // masking.
+ gfx::Image GenerateMaskedSmallIcon(SkColor color) const;
+
// Buttons, with icons fetched asynchronously.
const std::vector<ButtonInfo>& buttons() const {
return optional_fields_.buttons;
@@ -338,6 +400,16 @@ class MESSAGE_CENTER_EXPORT Notification {
return optional_fields_.accessible_name;
}
+ SkColor accent_color() const { return optional_fields_.accent_color; }
+ void set_accent_color(SkColor accent_color) {
+ optional_fields_.accent_color = accent_color;
+ }
+
+ bool use_image_as_icon() const { return optional_fields_.use_image_as_icon; }
+ void set_use_image_as_icon(bool use_image_as_icon) {
+ optional_fields_.use_image_as_icon = use_image_as_icon;
+ }
+
NotificationDelegate* delegate() const { return delegate_.get(); }
const RichNotificationData& rich_notification_data() const {
@@ -357,6 +429,13 @@ class MESSAGE_CENTER_EXPORT Notification {
// Helper method to create a simple system notification. |click_callback|
// will be invoked when the notification is clicked.
+ //
+ // It should only be used for critical notification, as SetSystemPriority and
+ // CRITICAL_WARNING color are set inside, which means the notification would
+ // not go away without user interaction.
+ //
+ // TODO(tetsui): Add a function parameter |small_image| of gfx::VectorIcon, so
+ // display source of critical system notification is illustrated by icon.
static std::unique_ptr<Notification> CreateSystemNotification(
const std::string& notification_id,
const base::string16& title,
@@ -365,6 +444,25 @@ class MESSAGE_CENTER_EXPORT Notification {
const std::string& system_component_id,
const base::Closure& click_callback);
+ // Factory method to create all kinds of notifications generated by system,
+ // from normal priority ones to critical priority ones.
+ // |small_image| is a small icon show on the upper left header to illustrate
+ // |display_source| of the notification.
+ // One specified in the |optional_fields| is overridden.
+ static std::unique_ptr<Notification> CreateSystemNotification(
+ NotificationType type,
+ const std::string& id,
+ const base::string16& title,
+ const base::string16& message,
+ const gfx::Image& icon,
+ const base::string16& display_source,
+ const GURL& origin_url,
+ const NotifierId& notifier_id,
+ const RichNotificationData& optional_fields,
+ scoped_refptr<NotificationDelegate> delegate,
+ const gfx::VectorIcon& small_image,
+ SystemNotificationWarningLevel color_type);
+
protected:
// The type of notification we'd like displayed.
NotificationType type_;
@@ -377,10 +475,13 @@ class MESSAGE_CENTER_EXPORT Notification {
gfx::Image icon_;
// The display string for the source of the notification. Could be
- // the same as origin_url_, or the name of an extension.
+ // the same as |origin_url_|, or the name of an extension.
+ // Expected to be a localized user facing string.
base::string16 display_source_;
private:
+ friend struct mojo::StructTraits<mojom::NotificationDataView, Notification>;
+
// The origin URL of the script which requested the notification.
// Can be empty if requested through a chrome app or extension or if
// it's a system notification.
@@ -394,10 +495,6 @@ class MESSAGE_CENTER_EXPORT Notification {
// A proxy object that allows access back to the JavaScript object that
// represents the notification, for firing events.
scoped_refptr<NotificationDelegate> delegate_;
-
-#if !defined(OS_IOS)
- friend struct mojo::StructTraits<mojom::NotificationDataView, Notification>;
-#endif
};
} // namespace message_center
diff --git a/chromium/ui/message_center/vector_icons/notification_expand_less.icon b/chromium/ui/message_center/vector_icons/notification_expand_less.icon
index b68afa7189f..b30ee4211b5 100644
--- a/chromium/ui/message_center/vector_icons/notification_expand_less.icon
+++ b/chromium/ui/message_center/vector_icons/notification_expand_less.icon
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-CANVAS_DIMENSIONS, 24,
-MOVE_TO, 12, 8,
-R_LINE_TO, -6, 6,
-R_LINE_TO, 1.41f, 1.41f,
-LINE_TO, 12, 10.83f,
-R_LINE_TO, 4.59f, 4.58f,
-LINE_TO, 18, 14,
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 2.62f, 13,
+LINE_TO, 8, 7.75f,
+LINE_TO, 13.33f, 13,
+LINE_TO, 15, 11.31f,
+R_LINE_TO, -7, -6.89f,
+R_LINE_TO, -7, 6.89f,
CLOSE,
END
diff --git a/chromium/ui/message_center/vector_icons/notification_expand_more.icon b/chromium/ui/message_center/vector_icons/notification_expand_more.icon
index d54e1e058b3..b779f5f8e5c 100644
--- a/chromium/ui/message_center/vector_icons/notification_expand_more.icon
+++ b/chromium/ui/message_center/vector_icons/notification_expand_more.icon
@@ -2,12 +2,12 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-CANVAS_DIMENSIONS, 24,
-MOVE_TO, 16.59f, 8.59f,
-LINE_TO, 12, 13.17f,
-LINE_TO, 7.41f, 8.59f,
-LINE_TO, 6, 10,
-R_LINE_TO, 6, 6,
-R_LINE_TO, 6, -6,
+CANVAS_DIMENSIONS, 16,
+MOVE_TO, 2.62f, 3,
+LINE_TO, 8, 8.25f,
+LINE_TO, 13.33f, 3,
+LINE_TO, 15, 4.69f,
+R_LINE_TO, -7, 6.89f,
+R_LINE_TO, -7, -6.89f,
CLOSE,
END
diff --git a/chromium/ui/message_center/views/desktop_popup_alignment_delegate.cc b/chromium/ui/message_center/views/desktop_popup_alignment_delegate.cc
index f57d23ad449..90c14c1b443 100644
--- a/chromium/ui/message_center/views/desktop_popup_alignment_delegate.cc
+++ b/chromium/ui/message_center/views/desktop_popup_alignment_delegate.cc
@@ -8,7 +8,6 @@
#include "ui/display/screen.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/message_center/message_center_style.h"
-#include "ui/message_center/views/message_popup_collection.h"
namespace message_center {
diff --git a/chromium/ui/message_center/views/message_bubble_base.cc b/chromium/ui/message_center/views/message_bubble_base.cc
deleted file mode 100644
index 25f0120c3b3..00000000000
--- a/chromium/ui/message_center/views/message_bubble_base.cc
+++ /dev/null
@@ -1,66 +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/message_center/views/message_bubble_base.h"
-
-#include "base/bind.h"
-#include "base/location.h"
-#include "base/single_thread_task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "ui/views/widget/widget.h"
-#include "ui/views/widget/widget_observer.h"
-
-namespace {
-// Delay laying out the MessageBubbleBase until all notifications have been
-// added and icons have had a chance to load.
-const int kUpdateDelayMs = 50;
-const int kMessageBubbleBaseDefaultMaxHeight = 400;
-}
-
-namespace message_center {
-
-MessageBubbleBase::MessageBubbleBase(MessageCenter* message_center,
- MessageCenterTray* tray)
- : message_center_(message_center),
- tray_(tray),
- bubble_view_(NULL),
- max_height_(kMessageBubbleBaseDefaultMaxHeight),
- weak_ptr_factory_(this) {
-}
-
-MessageBubbleBase::~MessageBubbleBase() {
- if (bubble_view_)
- bubble_view_->ResetDelegate();
-}
-
-void MessageBubbleBase::BubbleViewDestroyed() {
- bubble_view_ = NULL;
- OnBubbleViewDestroyed();
-}
-
-void MessageBubbleBase::ScheduleUpdate() {
- weak_ptr_factory_.InvalidateWeakPtrs(); // Cancel any pending update.
- base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
- FROM_HERE, base::Bind(&MessageBubbleBase::UpdateBubbleView,
- weak_ptr_factory_.GetWeakPtr()),
- base::TimeDelta::FromMilliseconds(kUpdateDelayMs));
-}
-
-bool MessageBubbleBase::IsVisible() const {
- return bubble_view() && bubble_view()->GetWidget()->IsVisible();
-}
-
-void MessageBubbleBase::SetMaxHeight(int height) {
- // Maximum height makes sense only for the new design.
- if (height == 0)
- height = kMessageBubbleBaseDefaultMaxHeight;
- if (height == max_height_)
- return;
-
- max_height_ = height;
- if (bubble_view_)
- bubble_view_->SetMaxHeight(max_height_);
-}
-
-} // namespace message_center
diff --git a/chromium/ui/message_center/views/message_bubble_base.h b/chromium/ui/message_center/views/message_bubble_base.h
deleted file mode 100644
index 779b9b3fa03..00000000000
--- a/chromium/ui/message_center/views/message_bubble_base.h
+++ /dev/null
@@ -1,76 +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_MESSAGE_CENTER_VIEWS_MESSAGE_BUBBLE_BASE_H_
-#define UI_MESSAGE_CENTER_VIEWS_MESSAGE_BUBBLE_BASE_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "ui/gfx/native_widget_types.h"
-#include "ui/message_center/message_center.h"
-#include "ui/message_center/message_center_export.h"
-#include "ui/views/bubble/tray_bubble_view.h"
-
-namespace message_center {
-class MessageCenterTray;
-
-class MESSAGE_CENTER_EXPORT MessageBubbleBase {
- public:
- MessageBubbleBase(MessageCenter* message_center, MessageCenterTray* tray);
-
- virtual ~MessageBubbleBase();
-
- // Gets called when the bubble view associated with this bubble is
- // destroyed. Clears |bubble_view_| and calls OnBubbleViewDestroyed.
- void BubbleViewDestroyed();
-
- // Sets/Gets the maximum height of the bubble view. Setting 0 changes the
- // bubble to the default size. max_height() will return the default size
- // if SetMaxHeight() has not been called yet.
- void SetMaxHeight(int height);
- int max_height() const { return max_height_; }
-
- // Called after the bubble view has been constructed. Creates and initializes
- // the bubble contents.
- virtual void InitializeContents(views::TrayBubbleView* bubble_view) = 0;
-
- // Called from BubbleViewDestroyed for implementation specific details.
- virtual void OnBubbleViewDestroyed() = 0;
-
- // Updates the bubble; implementation dependent.
- virtual void UpdateBubbleView() = 0;
-
- // Called when the mouse enters/exists the view.
- virtual void OnMouseEnteredView() = 0;
- virtual void OnMouseExitedView() = 0;
-
- // Schedules bubble for layout after all notifications have been
- // added and icons have had a chance to load.
- void ScheduleUpdate();
-
- bool IsVisible() const;
-
- views::TrayBubbleView* bubble_view() const { return bubble_view_; }
-
- protected:
- MessageCenter* message_center() { return message_center_; }
- MessageCenterTray* tray() { return tray_; }
- void set_bubble_view(views::TrayBubbleView* bubble_view) {
- bubble_view_ = bubble_view;
- }
-
- private:
- MessageCenter* message_center_;
- MessageCenterTray* tray_;
- views::TrayBubbleView* bubble_view_;
- int max_height_;
- base::WeakPtrFactory<MessageBubbleBase> weak_ptr_factory_;
-
- DISALLOW_COPY_AND_ASSIGN(MessageBubbleBase);
-};
-
-} // namespace message_center
-
-#endif // UI_MESSAGE_CENTER_VIEWS_MESSAGE_BUBBLE_BASE_H_
diff --git a/chromium/ui/message_center/views/message_center_bubble.cc b/chromium/ui/message_center/views/message_center_bubble.cc
deleted file mode 100644
index ad76cef5ace..00000000000
--- a/chromium/ui/message_center/views/message_center_bubble.cc
+++ /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 "ui/message_center/views/message_center_bubble.h"
-
-#include "base/macros.h"
-#include "ui/message_center/message_center_style.h"
-#include "ui/message_center/views/message_center_view.h"
-#include "ui/views/layout/fill_layout.h"
-#include "ui/views/widget/widget.h"
-
-namespace message_center {
-
-// ContentsView ////////////////////////////////////////////////////////////////
-
-// Handles changes in MessageCenterView sizes.
-class ContentsView : public views::View {
- public:
- explicit ContentsView(MessageCenterBubble* bubble, views::View* contents);
- ~ContentsView() override;
-
- // Overridden from views::View:
- int GetHeightForWidth(int width) const override;
-
- protected:
- // Overridden from views::View:
- void ChildPreferredSizeChanged(View* child) override;
-
- private:
- base::WeakPtr<MessageCenterBubble> bubble_;
-
- DISALLOW_COPY_AND_ASSIGN(ContentsView);
-};
-
-ContentsView::ContentsView(MessageCenterBubble* bubble, views::View* contents)
- : bubble_(bubble->AsWeakPtr()) {
- SetLayoutManager(new views::FillLayout());
- AddChildView(contents);
-}
-
-ContentsView::~ContentsView() {
-}
-
-int ContentsView::GetHeightForWidth(int width) const {
- DCHECK_EQ(1, child_count());
- int contents_width = std::max(width - GetInsets().width(), 0);
- int contents_height = child_at(0)->GetHeightForWidth(contents_width);
- return contents_height + GetInsets().height();
-}
-
-void ContentsView::ChildPreferredSizeChanged(View* child) {
- // TODO(dharcourt): Reduce the amount of updating this requires.
- if (bubble_.get())
- bubble_->bubble_view()->UpdateBubble();
-}
-
-// MessageCenterBubble /////////////////////////////////////////////////////////
-
-MessageCenterBubble::MessageCenterBubble(MessageCenter* message_center,
- MessageCenterTray* tray)
- : MessageBubbleBase(message_center, tray),
- message_center_view_(NULL),
- initially_settings_visible_(false) {}
-
-MessageCenterBubble::~MessageCenterBubble() {
- // Removs this from the widget observers just in case. MessageCenterBubble
- // might be destoryed without calling its Widget's Close/CloseNow.
- if (bubble_view() && bubble_view()->GetWidget())
- bubble_view()->GetWidget()->RemoveObserver(this);
-}
-
-void MessageCenterBubble::SetSettingsVisible() {
- if (message_center_view_)
- message_center_view_->SetSettingsVisible(true);
- else
- initially_settings_visible_ = true;
-}
-
-void MessageCenterBubble::InitializeContents(
- views::TrayBubbleView* new_bubble_view) {
- set_bubble_view(new_bubble_view);
- bubble_view()->GetWidget()->AddObserver(this);
- message_center_view_ = new MessageCenterView(
- message_center(), tray(), max_height(), initially_settings_visible_);
- bubble_view()->AddChildView(new ContentsView(this, message_center_view_));
- message_center_view_->Init();
- // Resize the content of the bubble view to the given bubble size. This is
- // necessary in case of the bubble border forcing a bigger size then the
- // |new_bubble_view| actually wants. See crbug.com/169390.
- bubble_view()->Layout();
- UpdateBubbleView();
-}
-
-void MessageCenterBubble::OnBubbleViewDestroyed() {
- message_center_view_ = NULL;
-}
-
-void MessageCenterBubble::UpdateBubbleView() {
- if (!bubble_view())
- return; // Could get called after view is closed
- const NotificationList::Notifications& notifications =
- message_center()->GetVisibleNotifications();
- message_center_view_->SetNotifications(notifications);
- bubble_view()->GetWidget()->Show();
- bubble_view()->UpdateBubble();
-}
-
-void MessageCenterBubble::OnWidgetClosing(views::Widget* widget) {
- if (bubble_view() && bubble_view()->GetWidget())
- bubble_view()->GetWidget()->RemoveObserver(this);
- if (message_center_view_)
- message_center_view_->SetIsClosing(true);
-}
-
-void MessageCenterBubble::OnMouseEnteredView() {
-}
-
-void MessageCenterBubble::OnMouseExitedView() {
-}
-
-size_t MessageCenterBubble::NumMessageViewsForTest() const {
- return message_center_view_->NumMessageViewsForTest();
-}
-
-} // namespace message_center
diff --git a/chromium/ui/message_center/views/message_center_bubble.h b/chromium/ui/message_center/views/message_center_bubble.h
deleted file mode 100644
index 138c562ea03..00000000000
--- a/chromium/ui/message_center/views/message_center_bubble.h
+++ /dev/null
@@ -1,55 +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_MESSAGE_CENTER_VIEWS_MESSAGE_CENTER_BUBBLE_H_
-#define UI_MESSAGE_CENTER_VIEWS_MESSAGE_CENTER_BUBBLE_H_
-
-#include <stddef.h>
-
-#include "base/macros.h"
-#include "base/memory/weak_ptr.h"
-#include "ui/message_center/message_center_export.h"
-#include "ui/message_center/views/message_bubble_base.h"
-#include "ui/views/widget/widget_observer.h"
-
-namespace message_center {
-
-class MessageCenterView;
-
-// Bubble for message center.
-class MESSAGE_CENTER_EXPORT MessageCenterBubble
- : public MessageBubbleBase,
- public views::WidgetObserver,
- public base::SupportsWeakPtr<MessageCenterBubble> {
- public:
- MessageCenterBubble(MessageCenter* message_center, MessageCenterTray* tray);
-
- ~MessageCenterBubble() override;
-
- void SetSettingsVisible();
-
- // Overridden from views::WidgetObserver:
- void OnWidgetClosing(views::Widget* widget) override;
-
- // Overridden from MessageBubbleBase:
- void InitializeContents(views::TrayBubbleView* bubble_view) override;
- void OnBubbleViewDestroyed() override;
- void UpdateBubbleView() override;
- void OnMouseEnteredView() override;
- void OnMouseExitedView() override;
-
- size_t NumMessageViewsForTest() const;
-
- private:
- MessageCenterView* message_center_view_;
-
- // Use settings view as the initially visible content if true.
- bool initially_settings_visible_;
-
- DISALLOW_COPY_AND_ASSIGN(MessageCenterBubble);
-};
-
-} // namespace message_center
-
-#endif // UI_MESSAGE_CENTER_VIEWS_MESSAGE_CENTER_BUBBLE_H_
diff --git a/chromium/ui/message_center/views/message_center_button_bar.cc b/chromium/ui/message_center/views/message_center_button_bar.cc
index f08fc1655ca..95500a59060 100644
--- a/chromium/ui/message_center/views/message_center_button_bar.cc
+++ b/chromium/ui/message_center/views/message_center_button_bar.cc
@@ -44,11 +44,11 @@ views::ToggleImageButton* CreateNotificationCenterButton(
int text_id) {
auto* button = new views::ToggleImageButton(listener);
ui::ResourceBundle& resource_bundle = ui::ResourceBundle::GetSharedInstance();
- button->SetImage(views::CustomButton::STATE_NORMAL,
+ button->SetImage(views::Button::STATE_NORMAL,
*resource_bundle.GetImageSkiaNamed(normal_id));
- button->SetImage(views::CustomButton::STATE_HOVERED,
+ button->SetImage(views::Button::STATE_HOVERED,
*resource_bundle.GetImageSkiaNamed(hover_id));
- button->SetImage(views::CustomButton::STATE_PRESSED,
+ button->SetImage(views::Button::STATE_PRESSED,
*resource_bundle.GetImageSkiaNamed(pressed_id));
button->SetImageAlignment(views::ImageButton::ALIGN_CENTER,
views::ImageButton::ALIGN_MIDDLE);
diff --git a/chromium/ui/message_center/views/message_center_view.cc b/chromium/ui/message_center/views/message_center_view.cc
index ae14fb94d9c..256689a02ce 100644
--- a/chromium/ui/message_center/views/message_center_view.cc
+++ b/chromium/ui/message_center/views/message_center_view.cc
@@ -179,7 +179,6 @@ void MessageCenterView::ClearAllClosableNotifications() {
}
void MessageCenterView::OnAllNotificationsCleared() {
- is_clearing_all_notifications_ = false;
SetViewHierarchyEnabled(scroller_, true);
button_bar_->SetCloseAllButtonEnabled(false);
@@ -189,6 +188,7 @@ void MessageCenterView::OnAllNotificationsCleared() {
message_center_->RemoveAllNotifications(
true /* by_user */,
message_center::MessageCenter::RemoveType::NON_PINNED);
+ is_clearing_all_notifications_ = false;
}
size_t MessageCenterView::NumMessageViewsForTest() const {
@@ -358,7 +358,10 @@ void MessageCenterView::OnNotificationRemoved(const std::string& id,
MessageView* view = view_iter->second;
int index = message_list_view_->GetIndexOf(view);
DCHECK_LE(0, index);
- if (by_user) {
+
+ // We skip repositioning during clear-all anomation, since we don't need keep
+ // positions.
+ if (by_user && !is_clearing_all_notifications_) {
message_list_view_->SetRepositionTarget(view->bounds());
// Moves the keyboard focus to the next notification if the removed
// notification is focused so that the user can dismiss notifications
@@ -645,7 +648,7 @@ void MessageCenterView::EnableCloseAllIfAppropriate() {
if (mode_ == Mode::NOTIFICATIONS) {
bool no_closable_views = true;
for (const auto& view : notification_views_) {
- if (!view.second->pinned()) {
+ if (!view.second->GetPinned()) {
no_closable_views = false;
break;
}
@@ -668,29 +671,28 @@ void MessageCenterView::UpdateNotification(const std::string& id) {
if (view_iter == notification_views_.end())
return;
- // TODO(dimich): add MessageCenter::GetVisibleNotificationById(id)
MessageView* view = view_iter->second;
- const NotificationList::Notifications& notifications =
- message_center_->GetVisibleNotifications();
- for (NotificationList::Notifications::const_iterator iter =
- notifications.begin();
- iter != notifications.end(); ++iter) {
- if ((*iter)->id() == id) {
- int old_width = view->width();
- int old_height = view->height();
- bool old_pinned = view->pinned();
- message_list_view_->UpdateNotification(view, **iter);
- if (view->GetHeightForWidth(old_width) != old_height) {
- Update(true /* animate */);
- } else if (view->pinned() != old_pinned) {
- // Animate flag is false, since the pinned flag transition doesn't need
- // animation.
- Update(false /* animate */);
- }
- break;
+ Notification* notification = message_center_->FindVisibleNotificationById(id);
+ if (notification) {
+ int old_width = view->width();
+ int old_height = view->height();
+ bool old_pinned = view->GetPinned();
+ message_list_view_->UpdateNotification(view, *notification);
+ if (view->GetHeightForWidth(old_width) != old_height) {
+ Update(true /* animate */);
+ } else if (view->GetPinned() != old_pinned) {
+ // Animate flag is false, since the pinned flag transition doesn't need
+ // animation.
+ Update(false /* animate */);
}
}
+ // Checks for investigation of the crash crbug.com/737858. It looks the view
+ // is stale, but we're not sure. These checks are to confirm that assumption.
+ // TODO(yoshiki): remove these after fixing the crash.
+ CHECK(notification_views_.find(id) != notification_views_.end());
+ CHECK(message_list_view_->Contains(view));
+
// Notify accessibility that the contents have changed.
view->NotifyAccessibilityEvent(ui::AX_EVENT_CHILDREN_CHANGED, false);
}
diff --git a/chromium/ui/message_center/views/message_center_view_unittest.cc b/chromium/ui/message_center/views/message_center_view_unittest.cc
index 7a5a4f9b10b..b48b0003ce1 100644
--- a/chromium/ui/message_center/views/message_center_view_unittest.cc
+++ b/chromium/ui/message_center/views/message_center_view_unittest.cc
@@ -458,7 +458,10 @@ TEST_F(MessageCenterViewTest, Size) {
GetMessageListView()->GetInsets().height());
}
-TEST_F(MessageCenterViewTest, SizeAfterUpdate) {
+// TODO(tetsui): The test is broken because there's no guarantee anymore that
+// height would change after setting longer message, as NotificationViewMD
+// implements collapse / expand functionality of long message.
+TEST_F(MessageCenterViewTest, DISABLED_SizeAfterUpdate) {
EXPECT_EQ(2, GetMessageListView()->child_count());
int width =
GetMessageListView()->width() - GetMessageListView()->GetInsets().width();
diff --git a/chromium/ui/message_center/views/message_list_view.cc b/chromium/ui/message_center/views/message_list_view.cc
index 6a1b78426e6..9e261afe14d 100644
--- a/chromium/ui/message_center/views/message_list_view.cc
+++ b/chromium/ui/message_center/views/message_list_view.cc
@@ -6,7 +6,7 @@
#include "base/command_line.h"
#include "base/location.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/stl_util.h"
#include "base/threading/thread_task_runner_handle.h"
@@ -177,12 +177,12 @@ int MessageListView::GetHeightForWidth(int width) const {
return height + GetInsets().height();
}
-void MessageListView::PaintChildren(const ui::PaintContext& context) {
+void MessageListView::PaintChildren(const views::PaintInfo& paint_info) {
// Paint in the inversed order. Otherwise upper notification may be
// hidden by the lower one.
for (int i = child_count() - 1; i >= 0; --i) {
if (!child_at(i)->layer())
- child_at(i)->Paint(context);
+ child_at(i)->Paint(paint_info);
}
}
@@ -260,7 +260,7 @@ void MessageListView::ClearAllClosableNotifications(
continue;
if (gfx::IntersectRects(child->bounds(), visible_scroll_rect).IsEmpty())
continue;
- if (child->pinned())
+ if (child->GetPinned())
continue;
if (deleting_views_.find(child) != deleting_views_.end() ||
deleted_when_done_.find(child) != deleted_when_done_.end()) {
@@ -300,18 +300,28 @@ void MessageListView::OnBoundsAnimatorProgressed(
}
void MessageListView::OnBoundsAnimatorDone(views::BoundsAnimator* animator) {
+ // It's possible for the delayed task that queues the next animation for
+ // clearing all notifications to be delayed more than we want. In this case,
+ // the BoundsAnimator can finish while a clear all is still happening. So,
+ // explicitly check if |clearing_all_views_| is empty.
+ if (clear_all_started_ && !clearing_all_views_.empty()) {
+ return;
+ }
+
bool need_update = false;
if (clear_all_started_) {
clear_all_started_ = false;
- // TODO(yoshiki): we shouldn't touch views in OnAllNotificationsCleared().
- // Or rename it to like OnAllNotificationsClearing().
for (auto& observer : observers_)
observer.OnAllNotificationsCleared();
- // Need to update layout after deleting the views.
- if (!deleted_when_done_.empty())
- need_update = true;
+ // Just return here if new animation is initiated in the above observers,
+ // since the code below assumes no animation is running. In the current
+ // impelementation, the observer tries removing the notification and their
+ // views and starts animation if the message center keeps opening.
+ // The code below will be executed when the new animation is finished.
+ if (animator_.IsAnimating())
+ return;
}
// None of these views should be deleted.
@@ -334,7 +344,7 @@ void MessageListView::OnBoundsAnimatorDone(views::BoundsAnimator* animator) {
GetWidget()->SynthesizeMouseMoveEvent();
if (quit_message_loop_after_animation_for_test_)
- base::MessageLoop::current()->QuitWhenIdle();
+ base::RunLoop::QuitCurrentWhenIdleDeprecated();
}
bool MessageListView::IsValidChild(const views::View* child) const {
@@ -356,9 +366,17 @@ void MessageListView::DoUpdateIfPossible() {
return;
}
- if (!clearing_all_views_.empty()) {
- if (!clear_all_started_)
- AnimateClearingOneNotification();
+ // Start the clearing all animation if necessary.
+ if (!clearing_all_views_.empty() && !clear_all_started_) {
+ AnimateClearingOneNotification();
+ return;
+ }
+
+ // Skip during the clering all animation.
+ // This checks |clear_all_started_! rather than |clearing_all_views_|, since
+ // the latter is empty during the animation of the last element.
+ if (clear_all_started_) {
+ DCHECK(!clearing_all_views_.empty());
return;
}
@@ -539,6 +557,10 @@ bool MessageListView::AnimateChild(views::View* child,
int top,
int height,
bool animate_on_move) {
+ // Do not call this during clearing all animation.
+ DCHECK(clearing_all_views_.empty());
+ DCHECK(!clear_all_started_);
+
gfx::Rect child_area = GetContentsBounds();
if (adding_views_.find(child) != adding_views_.end()) {
child->SetBounds(child_area.right(), top, child_area.width(), height);
@@ -573,9 +595,6 @@ void MessageListView::AnimateClearingOneNotification() {
new_bounds.set_x(new_bounds.right() + kMarginBetweenItems);
animator_.AnimateViewTo(child, new_bounds);
- // Deleting the child after animation.
- deleted_when_done_.insert(child);
-
// Schedule to start sliding out next notification after a short delay.
if (!clearing_all_views_.empty()) {
base::ThreadTaskRunnerHandle::Get()->PostDelayedTask(
diff --git a/chromium/ui/message_center/views/message_list_view.h b/chromium/ui/message_center/views/message_list_view.h
index b12f80f692a..a2232fa08ac 100644
--- a/chromium/ui/message_center/views/message_list_view.h
+++ b/chromium/ui/message_center/views/message_list_view.h
@@ -63,7 +63,7 @@ class MESSAGE_CENTER_EXPORT MessageListView
void Layout() override;
gfx::Size CalculatePreferredSize() const override;
int GetHeightForWidth(int width) const override;
- void PaintChildren(const ui::PaintContext& context) override;
+ void PaintChildren(const views::PaintInfo& paint_info) override;
void ReorderChildLayers(ui::Layer* parent_layer) override;
// Overridden from views::BoundsAnimatorObserver.
diff --git a/chromium/ui/message_center/views/message_list_view_unittest.cc b/chromium/ui/message_center/views/message_list_view_unittest.cc
index 2615a975785..ba561c1d529 100644
--- a/chromium/ui/message_center/views/message_list_view_unittest.cc
+++ b/chromium/ui/message_center/views/message_list_view_unittest.cc
@@ -156,12 +156,18 @@ class MessageListViewTest : public views::ViewsTestBase,
RunPendingMessages();
}
+ bool is_on_all_notifications_cleared_called() const {
+ return is_on_all_notifications_cleared_called_;
+ }
+
private:
// MockNotificationView::Test override
void RegisterCall(CallType type) override {}
// MessageListView::Observer override
- void OnAllNotificationsCleared() override {}
+ void OnAllNotificationsCleared() override {
+ is_on_all_notifications_cleared_called_ = true;
+ }
// MessageCenterController override:
void ClickOnNotification(const std::string& notification_id) override {}
@@ -186,6 +192,8 @@ class MessageListViewTest : public views::ViewsTestBase,
// MessageListView to be tested.
std::unique_ptr<MessageListView> message_list_view_;
+ bool is_on_all_notifications_cleared_called_ = false;
+
DISALLOW_COPY_AND_ASSIGN(MessageListViewTest);
};
@@ -445,7 +453,7 @@ TEST_F(MessageListViewTest, ClearAllClosableNotifications) {
RunPendingAnimations();
- EXPECT_EQ(0, message_list_view()->child_count());
+ EXPECT_TRUE(is_on_all_notifications_cleared_called());
}
// Regression test for crbug.com/713983
@@ -467,13 +475,9 @@ TEST_F(MessageListViewTest, RemoveWhileClearAll) {
message_center::RichNotificationData(), nullptr));
message_list_view()->AddNotificationAt(notification_view1, 0);
- EXPECT_EQ(1, message_list_view()->child_count());
-
RunPendingAnimations();
message_list_view()->AddNotificationAt(notification_view2, 1);
- EXPECT_EQ(2, message_list_view()->child_count());
-
RunPendingAnimations();
// Call RemoveNotification()
@@ -486,7 +490,7 @@ TEST_F(MessageListViewTest, RemoveWhileClearAll) {
message_list_view()->bounds());
RunPendingAnimations();
- EXPECT_EQ(0, message_list_view()->child_count());
+ EXPECT_TRUE(is_on_all_notifications_cleared_called());
}
} // namespace
diff --git a/chromium/ui/message_center/views/message_popup_collection.cc b/chromium/ui/message_center/views/message_popup_collection.cc
index be17705b3d7..5695d1b76cd 100644
--- a/chromium/ui/message_center/views/message_popup_collection.cc
+++ b/chromium/ui/message_center/views/message_popup_collection.cc
@@ -195,20 +195,13 @@ void MessagePopupCollection::UpdateWidgets() {
continue;
#endif
- MessageView* view;
// Create top-level notification.
+ MessageView* view = MessageViewFactory::Create(NULL, *(*iter), true);
#if defined(OS_CHROMEOS)
- if ((*iter)->pinned()) {
- Notification notification = *(*iter);
- // Override pinned status, since toasts should be closable even when it's
- // pinned.
- notification.set_pinned(false);
- view = MessageViewFactory::Create(NULL, notification, true);
- } else
+ // Disable pinned feature since this is a popup.
+ view->set_force_disable_pinned();
#endif // defined(OS_CHROMEOS)
- {
- view = MessageViewFactory::Create(NULL, *(*iter), true);
- }
+ view->SetExpanded(true);
// TODO(yoshiki): Temporary disable context menu on custom notifications.
// See crbug.com/750307 for detail.
diff --git a/chromium/ui/message_center/views/message_view.cc b/chromium/ui/message_center/views/message_view.cc
index 340d9bcce8d..be708d9ed29 100644
--- a/chromium/ui/message_center/views/message_view.cc
+++ b/chromium/ui/message_center/views/message_view.cc
@@ -91,7 +91,7 @@ void MessageView::UpdateWithNotification(const Notification& notification) {
display_source_ = notification.display_source();
pinned_ = notification.pinned();
accessible_name_ = CreateAccessibleName(notification);
- slide_out_controller_.set_enabled(!notification.pinned());
+ slide_out_controller_.set_enabled(!GetPinned());
}
// static
@@ -113,6 +113,15 @@ void MessageView::SetIsNested() {
-gfx::ShadowValue::GetMargin(shadow.values)));
}
+void MessageView::SetExpanded(bool expanded) {
+ // Not implemented by default.
+}
+
+bool MessageView::IsExpanded() const {
+ // Not implemented by default.
+ return false;
+}
+
void MessageView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
node_data->role = ui::AX_ROLE_BUTTON;
node_data->AddStringAttribute(
@@ -148,7 +157,7 @@ bool MessageView::OnKeyPressed(const ui::KeyEvent& event) {
bool MessageView::OnKeyReleased(const ui::KeyEvent& event) {
// Space key handling is triggerred at key-release timing. See
- // ui/views/controls/buttons/custom_button.cc for why.
+ // ui/views/controls/buttons/button.cc for why.
if (event.flags() != ui::EF_NONE || event.key_code() != ui::VKEY_SPACE)
return false;
@@ -231,6 +240,10 @@ void MessageView::OnSlideOut() {
controller_->RemoveNotification(notification_id_, true); // By user.
}
+bool MessageView::GetPinned() const {
+ return pinned_ && !force_disable_pinned_;
+}
+
void MessageView::OnCloseButtonPressed() {
controller_->RemoveNotification(notification_id_, true); // By user.
}
diff --git a/chromium/ui/message_center/views/message_view.h b/chromium/ui/message_center/views/message_view.h
index d07d76a6760..e6aeacdc991 100644
--- a/chromium/ui/message_center/views/message_view.h
+++ b/chromium/ui/message_center/views/message_view.h
@@ -55,6 +55,9 @@ class MESSAGE_CENTER_EXPORT MessageView
virtual void RequestFocusOnCloseButton() = 0;
virtual void UpdateControlButtonsVisibility() = 0;
+ virtual void SetExpanded(bool expanded);
+ virtual bool IsExpanded() const;
+
void OnCloseButtonPressed();
void OnSettingsButtonPressed();
@@ -74,16 +77,21 @@ class MESSAGE_CENTER_EXPORT MessageView
void OnSlideChanged() override;
void OnSlideOut() override;
+ bool GetPinned() const;
+
void set_scroller(views::ScrollView* scroller) { scroller_ = scroller; }
std::string notification_id() { return notification_id_; }
NotifierId notifier_id() { return notifier_id_; }
const base::string16& display_source() const { return display_source_; }
- bool pinned() const { return pinned_; }
-
void set_controller(MessageCenterController* controller) {
controller_ = controller;
}
+#if defined(OS_CHROMEOS)
+ // By calling this, all notifications are treated as non-pinned forcibly.
+ void set_force_disable_pinned() { force_disable_pinned_ = true; }
+#endif
+
protected:
// Creates and add close button to view hierarchy when necessary. Derived
// classes should call this after its view hierarchy is populated to ensure
@@ -108,7 +116,12 @@ class MESSAGE_CENTER_EXPORT MessageView
base::string16 accessible_name_;
base::string16 display_source_;
+
+ // Flag if the notification is set to pinned or not.
bool pinned_ = false;
+ // Flag if pin is forcibly disabled on this view. If true, the view is never
+ // pinned regardless of the value of |pinned_|.
+ bool force_disable_pinned_ = false;
std::unique_ptr<views::Painter> focus_painter_;
diff --git a/chromium/ui/message_center/views/message_view_factory.cc b/chromium/ui/message_center/views/message_view_factory.cc
index 60567af4533..bbd2b49fbb7 100644
--- a/chromium/ui/message_center/views/message_view_factory.cc
+++ b/chromium/ui/message_center/views/message_view_factory.cc
@@ -5,7 +5,7 @@
#include "ui/message_center/views/message_view_factory.h"
#include "base/command_line.h"
-#include "ui/message_center/message_center_switches.h"
+#include "ui/message_center/message_center.h"
#include "ui/message_center/notification_types.h"
#include "ui/message_center/views/notification_view.h"
#include "ui/message_center/views/notification_view_md.h"
@@ -26,23 +26,13 @@ MessageView* MessageViewFactory::Create(MessageCenterController* controller,
case NOTIFICATION_TYPE_IMAGE:
case NOTIFICATION_TYPE_MULTIPLE:
case NOTIFICATION_TYPE_SIMPLE:
- case NOTIFICATION_TYPE_PROGRESS: {
- bool new_style_notification_enabled = false; // default value
- if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kEnableMessageCenterNewStyleNotification)) {
- new_style_notification_enabled = true;
- } else if (base::CommandLine::ForCurrentProcess()->HasSwitch(
- switches::kDisableMessageCenterNewStyleNotification)) {
- new_style_notification_enabled = false;
- }
-
+ case NOTIFICATION_TYPE_PROGRESS:
// All above roads lead to the generic NotificationView.
- if (new_style_notification_enabled)
+ if (MessageCenter::IsNewStyleNotificationEnabled())
notification_view = new NotificationViewMD(controller, notification);
else
notification_view = new NotificationView(controller, notification);
break;
- }
#if defined(TOOLKIT_VIEWS) && !defined(OS_MACOSX)
case NOTIFICATION_TYPE_CUSTOM:
notification_view =
diff --git a/chromium/ui/message_center/views/notification_button.cc b/chromium/ui/message_center/views/notification_button.cc
index fe0877a8041..8b7b9f7880f 100644
--- a/chromium/ui/message_center/views/notification_button.cc
+++ b/chromium/ui/message_center/views/notification_button.cc
@@ -18,7 +18,7 @@
namespace message_center {
NotificationButton::NotificationButton(views::ButtonListener* listener)
- : views::CustomButton(listener), icon_(NULL), title_(NULL) {
+ : views::Button(listener), icon_(NULL), title_(NULL) {
SetFocusForPlatform();
// Create a background so that it does not change when the MessageView
// background changes to show touch feedback
@@ -81,7 +81,7 @@ int NotificationButton::GetHeightForWidth(int width) const {
}
void NotificationButton::OnFocus() {
- views::CustomButton::OnFocus();
+ views::Button::OnFocus();
ScrollRectToVisible(GetLocalBounds());
}
diff --git a/chromium/ui/message_center/views/notification_button.h b/chromium/ui/message_center/views/notification_button.h
index 3d3d2186b5b..21d54c43aca 100644
--- a/chromium/ui/message_center/views/notification_button.h
+++ b/chromium/ui/message_center/views/notification_button.h
@@ -7,7 +7,7 @@
#include "base/macros.h"
#include "ui/gfx/image/image_skia.h"
-#include "ui/views/controls/button/custom_button.h"
+#include "ui/views/controls/button/button.h"
#include "ui/views/painter.h"
#include "ui/views/view.h"
@@ -19,7 +19,7 @@ class Label;
namespace message_center {
// NotificationButtons render the action buttons of notifications.
-class NotificationButton : public views::CustomButton {
+class NotificationButton : public views::Button {
public:
NotificationButton(views::ButtonListener* listener);
~NotificationButton() override;
@@ -34,7 +34,7 @@ class NotificationButton : public views::CustomButton {
void ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) override;
- // Overridden from views::CustomButton:
+ // Overridden from views::Button:
void StateChanged(ButtonState old_state) override;
private:
diff --git a/chromium/ui/message_center/views/notification_control_buttons_view.cc b/chromium/ui/message_center/views/notification_control_buttons_view.cc
index bb10972f525..e3dbd3dc5e8 100644
--- a/chromium/ui/message_center/views/notification_control_buttons_view.cc
+++ b/chromium/ui/message_center/views/notification_control_buttons_view.cc
@@ -55,7 +55,7 @@ void NotificationControlButtonsView::ShowCloseButton(bool show) {
if (show && !close_button_) {
close_button_ = base::MakeUnique<message_center::PaddedButton>(this);
close_button_->set_owned_by_client();
- close_button_->SetImage(views::CustomButton::STATE_NORMAL,
+ close_button_->SetImage(views::Button::STATE_NORMAL,
message_center::GetCloseIcon());
close_button_->SetAccessibleName(l10n_util::GetStringUTF16(
IDS_MESSAGE_CENTER_CLOSE_NOTIFICATION_BUTTON_ACCESSIBLE_NAME));
@@ -77,7 +77,7 @@ void NotificationControlButtonsView::ShowSettingsButton(bool show) {
if (show && !settings_button_) {
settings_button_ = base::MakeUnique<message_center::PaddedButton>(this);
settings_button_->set_owned_by_client();
- settings_button_->SetImage(views::CustomButton::STATE_NORMAL,
+ settings_button_->SetImage(views::Button::STATE_NORMAL,
message_center::GetSettingsIcon());
settings_button_->SetAccessibleName(l10n_util::GetStringUTF16(
IDS_MESSAGE_NOTIFICATION_SETTINGS_BUTTON_ACCESSIBLE_NAME));
@@ -131,13 +131,11 @@ bool NotificationControlButtonsView::IsSettingsButtonFocused() const {
return settings_button_ && settings_button_->HasFocus();
}
-message_center::PaddedButton* NotificationControlButtonsView::close_button()
- const {
+views::Button* NotificationControlButtonsView::close_button() const {
return close_button_.get();
}
-message_center::PaddedButton* NotificationControlButtonsView::settings_button()
- const {
+views::Button* NotificationControlButtonsView::settings_button() const {
return settings_button_.get();
}
diff --git a/chromium/ui/message_center/views/notification_control_buttons_view.h b/chromium/ui/message_center/views/notification_control_buttons_view.h
index 627f0bc9c66..31441a979dc 100644
--- a/chromium/ui/message_center/views/notification_control_buttons_view.h
+++ b/chromium/ui/message_center/views/notification_control_buttons_view.h
@@ -20,6 +20,10 @@ namespace gfx {
class LinearAnimation;
}
+namespace views {
+class Button;
+}
+
namespace message_center {
class MessageView;
@@ -55,8 +59,8 @@ class MESSAGE_CENTER_EXPORT NotificationControlButtonsView
bool IsSettingsButtonFocused() const;
// Methods for retrieving the control buttons directly.
- message_center::PaddedButton* close_button() const;
- message_center::PaddedButton* settings_button() const;
+ views::Button* close_button() const;
+ views::Button* settings_button() const;
// views::View
const char* GetClassName() const override;
diff --git a/chromium/ui/message_center/views/notification_header_view.cc b/chromium/ui/message_center/views/notification_header_view.cc
index a43e6eaaf37..b5c7e9f23d9 100644
--- a/chromium/ui/message_center/views/notification_header_view.cc
+++ b/chromium/ui/message_center/views/notification_header_view.cc
@@ -8,17 +8,17 @@
#include "base/strings/string_number_conversions.h"
#include "base/strings/utf_string_conversions.h"
#include "base/time/time.h"
+#include "ui/accessibility/ax_node_data.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/gfx/color_palette.h"
#include "ui/gfx/font_list.h"
#include "ui/gfx/paint_vector_icon.h"
#include "ui/message_center/message_center_style.h"
#include "ui/message_center/vector_icons.h"
-#include "ui/message_center/views/padded_button.h"
+#include "ui/message_center/views/notification_control_buttons_view.h"
#include "ui/strings/grit/ui_strings.h"
-#include "ui/views/animation/flood_fill_ink_drop_ripple.h"
-#include "ui/views/animation/ink_drop_highlight.h"
-#include "ui/views/animation/ink_drop_impl.h"
+#include "ui/views/animation/ink_drop_stub.h"
+#include "ui/views/border.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
@@ -29,22 +29,38 @@ namespace message_center {
namespace {
-constexpr int kHeaderHeight = 28;
-constexpr int kAppIconSize = 12;
-constexpr int kExpandIconSize = 12;
-constexpr gfx::Insets kHeaderPadding(0, 12, 0, 2);
+constexpr int kHeaderHeight = 32;
constexpr int kHeaderHorizontalSpacing = 2;
-constexpr int kAppInfoConatainerTopPadding = 12;
+
+// The padding outer the header and the control buttons.
+constexpr gfx::Insets kHeaderOuterPadding(2, 2, 0, 2);
+
+// Paddings of the views of texts.
+// Top: 9px = 11px (from the mock) - 2px (outer padding)
+// Buttom: 6px from the mock
+constexpr gfx::Insets kTextViewPadding(9, 0, 6, 0);
+
+// Paddings of the entire header.
+// Left: 14px = 16px (from the mock) - 2px (outer padding)
+// Right: 2px = minimum padding between the control buttons and the header
+constexpr gfx::Insets kHeaderPadding(0, 14, 0, 2);
+
+// Paddings of the app icon (small image).
+// Top: 8px = 10px (from the mock) - 2px (outer padding)
+// Bottom: 4px from the mock
+// Right: 4px = 6px (from the mock) - kHeaderHorizontalSpacing
+constexpr gfx::Insets kAppIconPadding(8, 0, 4, 4);
+
+// Size of the expand icon. 8px = 32px - 15px - 9px (values from the mock).
+constexpr int kExpandIconSize = 8;
+// Paddings of the expand buttons.
+// Top: 13px = 15px (from the mock) - 2px (outer padding)
+// Bottom: 9px from the mock
+constexpr gfx::Insets kExpandIconViewPadding(13, 0, 9, 0);
+
// Bullet character. The divider symbol between different parts of the header.
constexpr wchar_t kNotificationHeaderDivider[] = L" \u2022 ";
-// Base ink drop color of action buttons.
-const SkColor kInkDropBaseColor = SkColorSetRGB(0x0, 0x0, 0x0);
-// Ripple ink drop opacity of action buttons.
-constexpr float kInkDropRippleVisibleOpacity = 0.08f;
-// Highlight (hover) ink drop opacity of action buttons.
-constexpr float kInkDropHighlightVisibleOpacity = 0.08f;
-
// base::TimeBase has similar constants, but some of them are missing.
constexpr int64_t kMinuteInMillis = 60LL * 1000LL;
constexpr int64_t kHourInMillis = 60LL * kMinuteInMillis;
@@ -52,6 +68,9 @@ constexpr int64_t kDayInMillis = 24LL * kHourInMillis;
// In Android, DateUtils.YEAR_IN_MILLIS is 364 days.
constexpr int64_t kYearInMillis = 364LL * kDayInMillis;
+// "Roboto-Regular, 12sp" is specified in the mock.
+constexpr int kHeaderTextFontSize = 12;
+
// ExpandButtton forwards all mouse and key events to NotificationHeaderView,
// but takes tab focus for accessibility purpose.
class ExpandButton : public views::ImageView {
@@ -59,17 +78,17 @@ class ExpandButton : public views::ImageView {
ExpandButton();
~ExpandButton() override;
+ // Overridden from views::ImageView:
void OnPaint(gfx::Canvas* canvas) override;
void OnFocus() override;
void OnBlur() override;
+ void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
private:
std::unique_ptr<views::Painter> focus_painter_;
};
ExpandButton::ExpandButton() {
- SetImage(gfx::CreateVectorIcon(kNotificationExpandMoreIcon, kExpandIconSize,
- gfx::kChromeIconGrey));
focus_painter_ = views::Painter::CreateSolidFocusPainter(
kFocusBorderColor, gfx::Insets(1, 2, 2, 2));
SetFocusBehavior(FocusBehavior::ALWAYS);
@@ -92,6 +111,11 @@ void ExpandButton::OnBlur() {
SchedulePaint();
}
+void ExpandButton::GetAccessibleNodeData(ui::AXNodeData* node_data) {
+ node_data->role = ui::AX_ROLE_BUTTON;
+ node_data->SetName(views::ImageView::GetTooltipText());
+}
+
// Do relative time string formatting that is similar to
// com.java.android.widget.DateTimeView.updateRelativeTime.
// Chromium has its own base::TimeFormat::Simple(), but none of the formats
@@ -121,44 +145,59 @@ base::string16 FormatToRelativeTime(base::Time past) {
}
}
+gfx::FontList GetHeaderTextFontList() {
+ gfx::Font default_font;
+ int font_size_delta = kHeaderTextFontSize - default_font.GetFontSize();
+ gfx::Font font = default_font.Derive(font_size_delta, gfx::Font::NORMAL,
+ gfx::Font::Weight::NORMAL);
+ DCHECK_EQ(kHeaderTextFontSize, font.GetFontSize());
+ return gfx::FontList(font);
+}
+
} // namespace
-NotificationHeaderView::NotificationHeaderView(views::ButtonListener* listener)
- : views::CustomButton(listener) {
- SetInkDropMode(InkDropMode::ON);
- set_has_ink_drop_action_on_click(true);
- set_animate_on_state_change(true);
- set_notify_enter_exit_on_child(true);
- set_ink_drop_base_color(kInkDropBaseColor);
- set_ink_drop_visible_opacity(kInkDropRippleVisibleOpacity);
+NotificationHeaderView::NotificationHeaderView(
+ NotificationControlButtonsView* control_buttons_view,
+ views::ButtonListener* listener)
+ : views::Button(listener) {
+ const int kInnerHeaderHeight = kHeaderHeight - kHeaderOuterPadding.height();
- views::BoxLayout* layout = new views::BoxLayout(
- views::BoxLayout::kHorizontal, kHeaderPadding, kHeaderHorizontalSpacing);
+ views::BoxLayout* layout =
+ new views::BoxLayout(views::BoxLayout::kHorizontal, kHeaderOuterPadding,
+ kHeaderHorizontalSpacing);
layout->set_cross_axis_alignment(
- views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER);
+ views::BoxLayout::CROSS_AXIS_ALIGNMENT_START);
SetLayoutManager(layout);
views::View* app_info_container = new views::View();
- views::BoxLayout* app_info_layout =
- new views::BoxLayout(views::BoxLayout::kHorizontal,
- gfx::Insets(kAppInfoConatainerTopPadding, 0, 0, 0),
- kHeaderHorizontalSpacing);
+ views::BoxLayout* app_info_layout = new views::BoxLayout(
+ views::BoxLayout::kHorizontal, kHeaderPadding, kHeaderHorizontalSpacing);
app_info_layout->set_cross_axis_alignment(
- views::BoxLayout::CROSS_AXIS_ALIGNMENT_CENTER);
+ views::BoxLayout::CROSS_AXIS_ALIGNMENT_START);
app_info_container->SetLayoutManager(app_info_layout);
AddChildView(app_info_container);
// App icon view
app_icon_view_ = new views::ImageView();
- app_icon_view_->SetImageSize(gfx::Size(kAppIconSize, kAppIconSize));
+ app_icon_view_->SetImageSize(gfx::Size(kSmallImageSizeMD, kSmallImageSizeMD));
+ app_icon_view_->SetBorder(views::CreateEmptyBorder(kAppIconPadding));
+ app_icon_view_->SetVerticalAlignment(views::ImageView::LEADING);
+ app_icon_view_->SetHorizontalAlignment(views::ImageView::LEADING);
+ DCHECK_EQ(kInnerHeaderHeight, app_icon_view_->GetPreferredSize().height());
app_info_container->AddChildView(app_icon_view_);
+ // Font list for text views.
+ const gfx::FontList& font_list = GetHeaderTextFontList();
+ // The height must be 15px to match with the mock.
+ DCHECK_EQ(15, font_list.GetHeight());
+
// App name view
- const gfx::FontList& font_list = views::Label().font_list().Derive(
- -2, gfx::Font::NORMAL, gfx::Font::Weight::NORMAL);
app_name_view_ = new views::Label(base::string16());
app_name_view_->SetFontList(font_list);
app_name_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ app_name_view_->SetEnabledColor(accent_color_);
+ app_name_view_->SetBorder(views::CreateEmptyBorder(kTextViewPadding));
+ DCHECK_EQ(kInnerHeaderHeight, app_name_view_->GetPreferredSize().height());
app_info_container->AddChildView(app_name_view_);
// Summary text divider
@@ -166,14 +205,20 @@ NotificationHeaderView::NotificationHeaderView(views::ButtonListener* listener)
new views::Label(base::WideToUTF16(kNotificationHeaderDivider));
summary_text_divider_->SetFontList(font_list);
summary_text_divider_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ summary_text_divider_->SetBorder(views::CreateEmptyBorder(kTextViewPadding));
summary_text_divider_->SetVisible(false);
+ DCHECK_EQ(kInnerHeaderHeight,
+ summary_text_divider_->GetPreferredSize().height());
app_info_container->AddChildView(summary_text_divider_);
// Summary text view
summary_text_view_ = new views::Label(base::string16());
summary_text_view_->SetFontList(font_list);
summary_text_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ summary_text_view_->SetBorder(views::CreateEmptyBorder(kTextViewPadding));
summary_text_view_->SetVisible(false);
+ DCHECK_EQ(kInnerHeaderHeight,
+ summary_text_view_->GetPreferredSize().height());
app_info_container->AddChildView(summary_text_view_);
// Timestamp divider
@@ -181,49 +226,51 @@ NotificationHeaderView::NotificationHeaderView(views::ButtonListener* listener)
new views::Label(base::WideToUTF16(kNotificationHeaderDivider));
timestamp_divider_->SetFontList(font_list);
timestamp_divider_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ timestamp_divider_->SetBorder(views::CreateEmptyBorder(kTextViewPadding));
timestamp_divider_->SetVisible(false);
+ DCHECK_EQ(kInnerHeaderHeight,
+ timestamp_divider_->GetPreferredSize().height());
app_info_container->AddChildView(timestamp_divider_);
// Timestamp view
timestamp_view_ = new views::Label(base::string16());
timestamp_view_->SetFontList(font_list);
timestamp_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ timestamp_view_->SetBorder(views::CreateEmptyBorder(kTextViewPadding));
timestamp_view_->SetVisible(false);
+ DCHECK_EQ(kInnerHeaderHeight, timestamp_view_->GetPreferredSize().height());
app_info_container->AddChildView(timestamp_view_);
// Expand button view
expand_button_ = new ExpandButton();
+ SetExpanded(is_expanded_);
+ expand_button_->SetBorder(views::CreateEmptyBorder(kExpandIconViewPadding));
+ expand_button_->SetVerticalAlignment(views::ImageView::LEADING);
+ expand_button_->SetHorizontalAlignment(views::ImageView::LEADING);
+ expand_button_->SetImageSize(gfx::Size(kExpandIconSize, kExpandIconSize));
+ DCHECK_EQ(kInnerHeaderHeight, expand_button_->GetPreferredSize().height());
app_info_container->AddChildView(expand_button_);
// Spacer between left-aligned views and right-aligned views
views::View* spacer = new views::View;
- spacer->SetPreferredSize(gfx::Size(1, kHeaderHeight));
+ spacer->SetPreferredSize(gfx::Size(1, kInnerHeaderHeight));
AddChildView(spacer);
layout->SetFlexForView(spacer, 1);
- // Settings button view
- settings_button_ = new PaddedButton(listener);
- settings_button_->SetImage(views::Button::STATE_NORMAL, GetSettingsIcon());
- settings_button_->SetAccessibleName(l10n_util::GetStringUTF16(
- IDS_MESSAGE_NOTIFICATION_SETTINGS_BUTTON_ACCESSIBLE_NAME));
- settings_button_->SetTooltipText(l10n_util::GetStringUTF16(
- IDS_MESSAGE_NOTIFICATION_SETTINGS_BUTTON_ACCESSIBLE_NAME));
- AddChildView(settings_button_);
-
- // Close button view
- close_button_ = new PaddedButton(listener);
- close_button_->SetImage(views::Button::STATE_NORMAL, GetCloseIcon());
- close_button_->SetAccessibleName(l10n_util::GetStringUTF16(
- IDS_MESSAGE_CENTER_CLOSE_NOTIFICATION_BUTTON_ACCESSIBLE_NAME));
- close_button_->SetTooltipText(l10n_util::GetStringUTF16(
- IDS_MESSAGE_CENTER_CLOSE_NOTIFICATION_BUTTON_TOOLTIP));
- AddChildView(close_button_);
+ // Settings and close buttons view
+ AddChildView(control_buttons_view);
+
+ SetPreferredSize(gfx::Size(kNotificationWidth, kHeaderHeight));
}
void NotificationHeaderView::SetAppIcon(const gfx::ImageSkia& img) {
app_icon_view_->SetImage(img);
}
+void NotificationHeaderView::ClearAppIcon() {
+ app_icon_view_->SetImage(gfx::CreateVectorIcon(kProductIcon, accent_color_));
+}
+
void NotificationHeaderView::SetAppName(const base::string16& name) {
app_name_view_->SetText(name);
}
@@ -277,75 +324,27 @@ void NotificationHeaderView::SetExpandButtonEnabled(bool enabled) {
}
void NotificationHeaderView::SetExpanded(bool expanded) {
- expand_button_->SetImage(
- gfx::CreateVectorIcon(
- expanded ? kNotificationExpandLessIcon : kNotificationExpandMoreIcon,
- kExpandIconSize, gfx::kChromeIconGrey));
-}
-
-void NotificationHeaderView::SetSettingsButtonEnabled(bool enabled) {
- if (settings_button_enabled_ != enabled) {
- settings_button_enabled_ = enabled;
- UpdateControlButtonsVisibility();
- }
-}
-
-void NotificationHeaderView::SetCloseButtonEnabled(bool enabled) {
- if (close_button_enabled_ != enabled) {
- close_button_enabled_ = enabled;
- UpdateControlButtonsVisibility();
- }
+ is_expanded_ = expanded;
+ expand_button_->SetImage(gfx::CreateVectorIcon(
+ expanded ? kNotificationExpandLessIcon : kNotificationExpandMoreIcon,
+ kExpandIconSize, accent_color_));
+ expand_button_->SetTooltipText(l10n_util::GetStringUTF16(
+ expanded ? IDS_MESSAGE_CENTER_COLLAPSE_NOTIFICATION
+ : IDS_MESSAGE_CENTER_EXPAND_NOTIFICATION));
}
-void NotificationHeaderView::SetControlButtonsVisible(bool visible) {
- if (is_control_buttons_visible_ != visible) {
- is_control_buttons_visible_ = visible;
- UpdateControlButtonsVisibility();
- }
+void NotificationHeaderView::SetAccentColor(SkColor color) {
+ accent_color_ = color;
+ app_name_view_->SetEnabledColor(accent_color_);
+ SetExpanded(is_expanded_);
}
bool NotificationHeaderView::IsExpandButtonEnabled() {
return expand_button_->visible();
}
-bool NotificationHeaderView::IsSettingsButtonEnabled() {
- return settings_button_enabled_;
-}
-
-bool NotificationHeaderView::IsCloseButtonEnabled() {
- return close_button_enabled_;
-}
-
std::unique_ptr<views::InkDrop> NotificationHeaderView::CreateInkDrop() {
- auto ink_drop = base::MakeUnique<views::InkDropImpl>(this, size());
- ink_drop->SetAutoHighlightMode(
- views::InkDropImpl::AutoHighlightMode::SHOW_ON_RIPPLE);
- ink_drop->SetShowHighlightOnHover(false);
- return ink_drop;
-}
-
-std::unique_ptr<views::InkDropRipple>
-NotificationHeaderView::CreateInkDropRipple() const {
- return base::MakeUnique<views::FloodFillInkDropRipple>(
- size(), GetInkDropCenterBasedOnLastEvent(), GetInkDropBaseColor(),
- ink_drop_visible_opacity());
-}
-
-std::unique_ptr<views::InkDropHighlight>
-NotificationHeaderView::CreateInkDropHighlight() const {
- auto highlight = base::MakeUnique<views::InkDropHighlight>(
- size(), kInkDropSmallCornerRadius,
- gfx::RectF(GetLocalBounds()).CenterPoint(), GetInkDropBaseColor());
- highlight->set_visible_opacity(kInkDropHighlightVisibleOpacity);
- return highlight;
-}
-
-void NotificationHeaderView::UpdateControlButtonsVisibility() {
- settings_button_->SetVisible(settings_button_enabled_ &&
- is_control_buttons_visible_);
- close_button_->SetVisible(close_button_enabled_ &&
- is_control_buttons_visible_);
- Layout();
+ return base::MakeUnique<views::InkDropStub>();
}
void NotificationHeaderView::UpdateSummaryTextVisibility() {
diff --git a/chromium/ui/message_center/views/notification_header_view.h b/chromium/ui/message_center/views/notification_header_view.h
index 2471c67a405..403475ec6a3 100644
--- a/chromium/ui/message_center/views/notification_header_view.h
+++ b/chromium/ui/message_center/views/notification_header_view.h
@@ -6,20 +6,22 @@
#define UI_MESSAGE_CENTER_VIEWS_NOTIFICATION_HEADER_VIEW_H_
#include "base/macros.h"
-#include "ui/message_center/views/padded_button.h"
-#include "ui/views/controls/button/custom_button.h"
+#include "ui/message_center/message_center_style.h"
+#include "ui/views/controls/button/button.h"
namespace views {
-class ImageButton;
class ImageView;
class Label;
}
namespace message_center {
-class NotificationHeaderView : public views::CustomButton {
+class NotificationControlButtonsView;
+
+class NotificationHeaderView : public views::Button {
public:
- NotificationHeaderView(views::ButtonListener* listener);
+ NotificationHeaderView(NotificationControlButtonsView* control_buttons_view,
+ views::ButtonListener* listener);
void SetAppIcon(const gfx::ImageSkia& img);
void SetAppName(const base::string16& name);
void SetProgress(int progress);
@@ -30,29 +32,28 @@ class NotificationHeaderView : public views::CustomButton {
void SetSettingsButtonEnabled(bool enabled);
void SetCloseButtonEnabled(bool enabled);
void SetControlButtonsVisible(bool visible);
+ // Set the unified theme color used among the app icon, app name, and expand
+ // button.
+ void SetAccentColor(SkColor color);
+ void ClearAppIcon();
void ClearProgress();
void ClearOverflowIndicator();
void ClearTimestamp();
bool IsExpandButtonEnabled();
- bool IsSettingsButtonEnabled();
- bool IsCloseButtonEnabled();
- bool IsCloseButtonFocused();
- // CustomButton override:
+ // Button override:
std::unique_ptr<views::InkDrop> CreateInkDrop() override;
- std::unique_ptr<views::InkDropRipple> CreateInkDropRipple() const override;
- std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight()
- const override;
views::ImageView* expand_button() { return expand_button_; }
- views::ImageButton* settings_button() { return settings_button_; }
- views::ImageButton* close_button() { return close_button_; }
+
+ SkColor accent_color_for_testing() { return accent_color_; }
private:
- void UpdateControlButtonsVisibility();
// Update visibility for both |summary_text_view_| and |timestamp_view_|.
void UpdateSummaryTextVisibility();
+ SkColor accent_color_ = message_center::kNotificationDefaultAccentColor;
+
views::Label* app_name_view_ = nullptr;
views::Label* summary_text_divider_ = nullptr;
views::Label* summary_text_view_ = nullptr;
@@ -60,15 +61,12 @@ class NotificationHeaderView : public views::CustomButton {
views::Label* timestamp_view_ = nullptr;
views::ImageView* app_icon_view_ = nullptr;
views::ImageView* expand_button_ = nullptr;
- PaddedButton* settings_button_ = nullptr;
- PaddedButton* close_button_ = nullptr;
bool settings_button_enabled_ = false;
- bool close_button_enabled_ = false;
- bool is_control_buttons_visible_ = false;
bool has_progress_ = false;
bool has_overflow_indicator_ = false;
bool has_timestamp_ = false;
+ bool is_expanded_ = false;
DISALLOW_COPY_AND_ASSIGN(NotificationHeaderView);
};
diff --git a/chromium/ui/message_center/views/notification_view.cc b/chromium/ui/message_center/views/notification_view.cc
index 0a1ad48595f..d536729d02f 100644
--- a/chromium/ui/message_center/views/notification_view.cc
+++ b/chromium/ui/message_center/views/notification_view.cc
@@ -289,6 +289,7 @@ void NotificationView::Layout() {
// Top views.
int top_height = top_view_->GetHeightForWidth(content_width);
top_view_->SetBounds(insets.left(), insets.top(), content_width, top_height);
+ ShrinkTopmostLabel();
// Icon.
icon_view_->SetBounds(insets.left(), insets.top(), kNotificationIconSize,
@@ -340,10 +341,6 @@ gfx::NativeCursor NotificationView::GetCursor(const ui::MouseEvent& event) {
return views::GetNativeHandCursor();
}
-void NotificationView::OnMouseMoved(const ui::MouseEvent& event) {
- MessageView::OnMouseMoved(event);
- UpdateControlButtonsVisibility();
-}
void NotificationView::OnMouseEntered(const ui::MouseEvent& event) {
MessageView::OnMouseEntered(event);
@@ -655,7 +652,7 @@ void NotificationView::UpdateControlButtonsVisibilityWithNotification(
control_buttons_view_->ShowSettingsButton(
notification.delegate() &&
notification.delegate()->ShouldDisplaySettingsButton());
- control_buttons_view_->ShowCloseButton(!notification.pinned());
+ control_buttons_view_->ShowCloseButton(!GetPinned());
UpdateControlButtonsVisibility();
}
@@ -722,4 +719,18 @@ int NotificationView::GetMessageHeight(int width, int limit) const {
message_view_->GetSizeForWidthAndLines(width, limit).height() : 0;
}
+void NotificationView::ShrinkTopmostLabel() {
+// Reduce width of the topmost label not to be covered by the control buttons
+// only on non Chrome OS platform.
+#if !defined(OS_CHROMEOS)
+ const int content_width = width() - GetInsets().width();
+ const int buttons_width = control_buttons_view_->GetPreferredSize().width();
+ if (top_view_->child_count() > 0) {
+ gfx::Rect bounds = top_view_->child_at(0)->bounds();
+ bounds.set_width(content_width - buttons_width);
+ top_view_->child_at(0)->SetBoundsRect(bounds);
+ }
+#endif
+}
+
} // namespace message_center
diff --git a/chromium/ui/message_center/views/notification_view.h b/chromium/ui/message_center/views/notification_view.h
index 23e18509b0e..972a21ff9f4 100644
--- a/chromium/ui/message_center/views/notification_view.h
+++ b/chromium/ui/message_center/views/notification_view.h
@@ -47,7 +47,6 @@ class MESSAGE_CENTER_EXPORT NotificationView
void OnFocus() override;
void ScrollRectToVisible(const gfx::Rect& rect) override;
gfx::NativeCursor GetCursor(const ui::MouseEvent& event) override;
- void OnMouseMoved(const ui::MouseEvent& event) override;
void OnMouseEntered(const ui::MouseEvent& event) override;
void OnMouseExited(const ui::MouseEvent& event) override;
@@ -87,6 +86,7 @@ class MESSAGE_CENTER_EXPORT NotificationView
void CreateOrUpdateSmallIconView(const Notification& notification);
void CreateOrUpdateImageView(const Notification& notification);
void CreateOrUpdateActionButtonViews(const Notification& notification);
+ // TODO(yoshiki): Move this to message_center::MessageView
void UpdateControlButtonsVisibilityWithNotification(
const Notification& notification);
@@ -99,6 +99,9 @@ class MESSAGE_CENTER_EXPORT NotificationView
// notification.
base::string16 FormatContextMessage(const Notification& notification) const;
+ // Shrink the topmost label not to be covered by the control button.
+ void ShrinkTopmostLabel();
+
// Describes whether the view should display a hand pointer or not.
bool clickable_;
diff --git a/chromium/ui/message_center/views/notification_view_md.cc b/chromium/ui/message_center/views/notification_view_md.cc
index 39555c6e1a5..3c6a123c721 100644
--- a/chromium/ui/message_center/views/notification_view_md.cc
+++ b/chromium/ui/message_center/views/notification_view_md.cc
@@ -24,6 +24,7 @@
#include "ui/message_center/views/bounded_label.h"
#include "ui/message_center/views/constants.h"
#include "ui/message_center/views/message_center_controller.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"
#include "ui/message_center/views/proportional_image_view.h"
@@ -31,7 +32,6 @@
#include "ui/views/animation/ink_drop_highlight.h"
#include "ui/views/background.h"
#include "ui/views/border.h"
-#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/progress_bar.h"
@@ -47,20 +47,21 @@ namespace message_center {
namespace {
// Dimensions.
-constexpr gfx::Insets kContentRowPadding(4, 12, 12, 12);
+constexpr gfx::Insets kContentRowPadding(2, 12, 12, 12);
constexpr gfx::Insets kActionsRowPadding(8, 8, 8, 8);
constexpr int kActionsRowHorizontalSpacing = 8;
constexpr gfx::Insets kActionButtonPadding(0, 12, 0, 12);
-constexpr gfx::Size kActionButtonMinSize(88, 32);
-constexpr gfx::Size kIconViewSize(30, 30);
+constexpr gfx::Insets kStatusTextPadding(4, 0, 0, 0);
+constexpr gfx::Size kActionButtonMinSize(0, 32);
+// TODO(tetsui): Move |kIconViewSize| to message_center_style.h and merge with
+// contradicting |kNotificationIconSize|.
+constexpr gfx::Size kIconViewSize(36, 36);
constexpr gfx::Insets kLargeImageContainerPadding(0, 12, 12, 12);
constexpr gfx::Size kLargeImageMinSize(328, 0);
constexpr gfx::Size kLargeImageMaxSize(328, 218);
+constexpr gfx::Insets kLeftContentPadding(0, 4, 0, 4);
+constexpr gfx::Insets kLeftContentPaddingWithIcon(0, 4, 0, 12);
-// Foreground of small icon image.
-constexpr SkColor kSmallImageBackgroundColor = SK_ColorWHITE;
-// Background of small icon image.
-const SkColor kSmallImageColor = SkColorSetRGB(0x43, 0x43, 0x43);
// Background of inline actions area.
const SkColor kActionsRowBackgroundColor = SkColorSetRGB(0xee, 0xee, 0xee);
// Base ink drop color of action buttons.
@@ -74,6 +75,9 @@ const SkColor kActionButtonTextColor = SkColorSetRGB(0x33, 0x67, 0xD6);
// Background color of the large image.
const SkColor kLargeImageBackgroundColor = SkColorSetRGB(0xf5, 0xf5, 0xf5);
+const SkColor kRegularTextColorMD = SkColorSetRGB(0x21, 0x21, 0x21);
+const SkColor kDimTextColorMD = SkColorSetRGB(0x75, 0x75, 0x75);
+
// Max number of lines for message_view_.
constexpr int kMaxLinesForMessageView = 1;
constexpr int kMaxLinesForExpandedMessageView = 4;
@@ -82,40 +86,66 @@ constexpr int kCompactTitleMessageViewSpacing = 12;
constexpr int kProgressBarHeight = 4;
-constexpr int kMessageViewWidth =
+constexpr int kMessageViewWidthWithIcon =
message_center::kNotificationWidth - kIconViewSize.width() -
+ kLeftContentPaddingWithIcon.left() - kLeftContentPaddingWithIcon.right() -
kContentRowPadding.left() - kContentRowPadding.right();
-const gfx::ImageSkia CreateSolidColorImage(int width,
- int height,
- SkColor color) {
- SkBitmap bitmap;
- bitmap.allocN32Pixels(width, height);
- bitmap.eraseColor(color);
- return gfx::ImageSkia::CreateFrom1xBitmap(bitmap);
-}
-
-// Take the alpha channel of icon, mask it with the foreground,
-// then add the masked foreground on top of the background
-const gfx::ImageSkia GetMaskedIcon(const gfx::ImageSkia& icon) {
- int width = icon.width();
- int height = icon.height();
-
- // Background color grey
- const gfx::ImageSkia background = CreateSolidColorImage(
- width, height, message_center::kSmallImageBackgroundColor);
- // Foreground color white
- const gfx::ImageSkia foreground =
- CreateSolidColorImage(width, height, message_center::kSmallImageColor);
- const gfx::ImageSkia masked_small_image =
- gfx::ImageSkiaOperations::CreateMaskedImage(foreground, icon);
- return gfx::ImageSkiaOperations::CreateSuperimposedImage(background,
- masked_small_image);
-}
-
-const gfx::ImageSkia GetProductIcon() {
- return gfx::CreateVectorIcon(kProductIcon, kSmallImageColor);
-}
+constexpr int kMessageViewWidth =
+ message_center::kNotificationWidth - kLeftContentPadding.left() -
+ kLeftContentPadding.right() - kContentRowPadding.left() -
+ kContentRowPadding.right();
+
+// "Roboto-Regular, 13sp" is specified in the mock.
+constexpr int kTextFontSize = 13;
+
+// FontList for the texts except for the header.
+gfx::FontList GetTextFontList() {
+ gfx::Font default_font;
+ int font_size_delta = kTextFontSize - default_font.GetFontSize();
+ gfx::Font font = default_font.Derive(font_size_delta, gfx::Font::NORMAL,
+ gfx::Font::Weight::NORMAL);
+ DCHECK_EQ(kTextFontSize, font.GetFontSize());
+ return gfx::FontList(font);
+}
+
+#if defined(OS_CHROMEOS)
+// Return true if the default |display_source| should be used for the
+// notifications from the notifier.
+//
+// Ideally, we shuold fix the callers to set appropriate |display_source|, but
+// string resource is frozen in M62. For now, we should use this to prevent
+// empty |display_source| in system notifications.
+// TODO(tetsui): Remove this hack after M62 is released.
+bool ShowDefaultDisplaySource(const NotifierId& notifier) {
+ // The string constants are written in plain to prevent circular dependencies.
+ // This should not be accepted usually but I think it's OK here, as this
+ // function has a clear plan to be removed soon.
+ return notifier.type == NotifierId::SYSTEM_COMPONENT &&
+ (
+ // ARC notification.
+ // chrome/browser/chromeos/arc/arc_auth_notification.cc
+ notifier.id == "arc_auth" ||
+ // chrome/browser/chromeos/arc/notification/
+ // arc_boot_error_notification.cc
+ notifier.id == "arc_boot_error" ||
+ // chrome/browser/chromeos/arc/notification/
+ // arc_provision_notification_service.cc
+ notifier.id == "arc_managed_provision" ||
+ // Happiness survey notification.
+ // chrome/browser/chromeos/hats/hats_notification_controller.cc
+ notifier.id == "ash.hats" ||
+ // Sign-in error notification.
+ // chrome/browser/signin/signin_error_notifier_ash.cc
+ // chrome/browser/chromeos/authpolicy/
+ // auth_policy_credentials_manager.cc
+ notifier.id == "chrome://settings/signin/" ||
+ // CUPS printing notification.
+ // chrome/browser/chromeos/printing/cups_print_job_notification.cc
+ notifier.id ==
+ "chrome://settings/printing/cups-print-job-notification");
+}
+#endif
// ItemView ////////////////////////////////////////////////////////////////////
@@ -136,18 +166,22 @@ ItemView::ItemView(const message_center::NotificationItem& item) {
SetLayoutManager(
new views::BoxLayout(views::BoxLayout::kHorizontal, gfx::Insets(), 0));
+ const gfx::FontList font_list = GetTextFontList();
+
views::Label* title = new views::Label(item.title);
+ title->SetFontList(font_list);
title->set_collapse_when_hidden(true);
title->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- title->SetEnabledColor(message_center::kRegularTextColor);
+ title->SetEnabledColor(message_center::kRegularTextColorMD);
title->SetBackgroundColor(message_center::kDimTextBackgroundColor);
AddChildView(title);
views::Label* message = new views::Label(l10n_util::GetStringFUTF16(
IDS_MESSAGE_CENTER_LIST_NOTIFICATION_MESSAGE_WITH_DIVIDER, item.message));
+ message->SetFontList(font_list);
message->set_collapse_when_hidden(true);
message->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- message->SetEnabledColor(message_center::kDimTextColor);
+ message->SetEnabledColor(kDimTextColorMD);
message->SetBackgroundColor(message_center::kDimTextBackgroundColor);
AddChildView(message);
}
@@ -193,19 +227,18 @@ const char* CompactTitleMessageView::GetClassName() const {
CompactTitleMessageView::CompactTitleMessageView() {
SetLayoutManager(new views::FillLayout());
- const gfx::FontList& font_list = views::Label().font_list().Derive(
- 1, gfx::Font::NORMAL, gfx::Font::Weight::NORMAL);
+ const gfx::FontList& font_list = GetTextFontList();
title_view_ = new views::Label();
title_view_->SetFontList(font_list);
title_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- title_view_->SetEnabledColor(message_center::kRegularTextColor);
+ title_view_->SetEnabledColor(kRegularTextColorMD);
AddChildView(title_view_);
message_view_ = new views::Label();
message_view_->SetFontList(font_list);
message_view_->SetHorizontalAlignment(gfx::ALIGN_RIGHT);
- message_view_->SetEnabledColor(message_center::kDimTextColor);
+ message_view_->SetEnabledColor(kDimTextColorMD);
AddChildView(message_view_);
}
@@ -213,8 +246,7 @@ void CompactTitleMessageView::OnPaint(gfx::Canvas* canvas) {
base::string16 title = title_;
base::string16 message = message_;
- const gfx::FontList& font_list = views::Label().font_list().Derive(
- 1, gfx::Font::NORMAL, gfx::Font::Weight::NORMAL);
+ const gfx::FontList& font_list = GetTextFontList();
// Elides title and message. The behavior is based on Android's one.
// * If the title is too long, only the title is shown.
@@ -239,61 +271,6 @@ void CompactTitleMessageView::OnPaint(gfx::Canvas* canvas) {
views::View::OnPaint(canvas);
}
-// NotificationButtonMD ////////////////////////////////////////////////////////
-
-// This class is needed in addition to LabelButton mainly becuase we want to set
-// visible_opacity of InkDropHighlight.
-// This button capitalizes the given label string.
-class NotificationButtonMD : public views::LabelButton {
- public:
- NotificationButtonMD(views::ButtonListener* listener,
- const base::string16& text);
- ~NotificationButtonMD() override;
-
- void SetText(const base::string16& text) override;
- const char* GetClassName() const override;
-
- std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight()
- const override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(NotificationButtonMD);
-};
-
-NotificationButtonMD::NotificationButtonMD(views::ButtonListener* listener,
- const base::string16& text)
- : views::LabelButton(listener,
- base::i18n::ToUpper(text),
- views::style::CONTEXT_BUTTON_MD) {
- SetHorizontalAlignment(gfx::ALIGN_CENTER);
- SetInkDropMode(views::LabelButton::InkDropMode::ON);
- set_has_ink_drop_action_on_click(true);
- set_ink_drop_base_color(kActionButtonInkDropBaseColor);
- set_ink_drop_visible_opacity(kActionButtonInkDropRippleVisibleOpacity);
- SetEnabledTextColors(kActionButtonTextColor);
- SetBorder(views::CreateEmptyBorder(kActionButtonPadding));
- SetMinSize(kActionButtonMinSize);
- SetFocusForPlatform();
-}
-
-NotificationButtonMD::~NotificationButtonMD() = default;
-
-void NotificationButtonMD::SetText(const base::string16& text) {
- views::LabelButton::SetText(base::i18n::ToUpper(text));
-}
-
-const char* NotificationButtonMD::GetClassName() const {
- return "NotificationButtonMD";
-}
-
-std::unique_ptr<views::InkDropHighlight>
-NotificationButtonMD::CreateInkDropHighlight() const {
- std::unique_ptr<views::InkDropHighlight> highlight =
- views::LabelButton::CreateInkDropHighlight();
- highlight->set_visible_opacity(kActionButtonInkDropHighlightVisibleOpacity);
- return highlight;
-}
-
// LargeImageView //////////////////////////////////////////////////////////////
class LargeImageView : public views::View {
@@ -409,6 +386,42 @@ const char* LargeImageContainerView::GetClassName() const {
} // anonymous namespace
+// NotificationButtonMD ////////////////////////////////////////////////////////
+
+NotificationButtonMD::NotificationButtonMD(views::ButtonListener* listener,
+ const base::string16& text)
+ : views::LabelButton(listener,
+ base::i18n::ToUpper(text),
+ views::style::CONTEXT_BUTTON_MD) {
+ SetHorizontalAlignment(gfx::ALIGN_CENTER);
+ SetInkDropMode(views::LabelButton::InkDropMode::ON);
+ set_has_ink_drop_action_on_click(true);
+ set_ink_drop_base_color(kActionButtonInkDropBaseColor);
+ set_ink_drop_visible_opacity(kActionButtonInkDropRippleVisibleOpacity);
+ SetEnabledTextColors(kActionButtonTextColor);
+ SetBorder(views::CreateEmptyBorder(kActionButtonPadding));
+ SetMinSize(kActionButtonMinSize);
+ SetFocusForPlatform();
+}
+
+NotificationButtonMD::~NotificationButtonMD() = default;
+
+void NotificationButtonMD::SetText(const base::string16& text) {
+ views::LabelButton::SetText(base::i18n::ToUpper(text));
+}
+
+const char* NotificationButtonMD::GetClassName() const {
+ return "NotificationButtonMD";
+}
+
+std::unique_ptr<views::InkDropHighlight>
+NotificationButtonMD::CreateInkDropHighlight() const {
+ std::unique_ptr<views::InkDropHighlight> highlight =
+ views::LabelButton::CreateInkDropHighlight();
+ highlight->set_visible_opacity(kActionButtonInkDropHighlightVisibleOpacity);
+ return highlight;
+}
+
// ////////////////////////////////////////////////////////////
// NotificationViewMD
// ////////////////////////////////////////////////////////////
@@ -426,10 +439,6 @@ views::View* NotificationViewMD::TargetForRect(views::View* root,
// called. But buttons are exceptions, they'll have their own event handlings.
std::vector<views::View*> buttons(action_buttons_.begin(),
action_buttons_.end());
- if (header_row_->settings_button())
- buttons.push_back(header_row_->settings_button());
- if (header_row_->close_button())
- buttons.push_back(header_row_->close_button());
if (header_row_->expand_button())
buttons.push_back(header_row_->expand_button());
buttons.push_back(header_row_);
@@ -450,12 +459,11 @@ void NotificationViewMD::CreateOrUpdateViews(const Notification& notification) {
CreateOrUpdateMessageView(notification);
CreateOrUpdateCompactTitleMessageView(notification);
CreateOrUpdateProgressBarView(notification);
+ CreateOrUpdateProgressStatusView(notification);
CreateOrUpdateListItemViews(notification);
CreateOrUpdateIconView(notification);
CreateOrUpdateSmallIconView(notification);
CreateOrUpdateImageView(notification);
- CreateOrUpdateCloseButtonView(notification);
- CreateOrUpdateSettingsButtonView(notification);
UpdateViewForExpandedState(expanded_);
// Should be called at the last because SynthesizeMouseMoveEvent() requires
// everything is in the right location when called.
@@ -469,8 +477,13 @@ NotificationViewMD::NotificationViewMD(MessageCenterController* controller,
SetLayoutManager(
new views::BoxLayout(views::BoxLayout::kVertical, gfx::Insets(), 0));
+ control_buttons_view_ =
+ base::MakeUnique<NotificationControlButtonsView>(this);
+ control_buttons_view_->set_owned_by_client();
+ control_buttons_view_->SetBackgroundColor(SK_ColorTRANSPARENT);
+
// |header_row_| contains app_icon, app_name, control buttons, etc...
- header_row_ = new NotificationHeaderView(this);
+ header_row_ = new NotificationHeaderView(control_buttons_view_.get(), this);
AddChildView(header_row_);
// |content_row_| contains title, message, image, progressbar, etc...
@@ -486,6 +499,7 @@ NotificationViewMD::NotificationViewMD(MessageCenterController* controller,
left_content_ = new views::View();
left_content_->SetLayoutManager(
new views::BoxLayout(views::BoxLayout::kVertical, gfx::Insets(), 0));
+ left_content_->SetBorder(views::CreateEmptyBorder(kLeftContentPadding));
content_row_->AddChildView(left_content_);
content_row_layout->SetFlexForView(left_content_, 1);
@@ -505,9 +519,11 @@ NotificationViewMD::NotificationViewMD(MessageCenterController* controller,
AddChildView(actions_row_);
CreateOrUpdateViews(notification);
+ UpdateControlButtonsVisibilityWithNotification(notification);
SetEventTargeter(
std::unique_ptr<views::ViewTargeter>(new views::ViewTargeter(this)));
+ set_notify_enter_exit_on_child(true);
}
NotificationViewMD::~NotificationViewMD() {}
@@ -539,11 +555,6 @@ gfx::NativeCursor NotificationViewMD::GetCursor(const ui::MouseEvent& event) {
return views::GetNativeHandCursor();
}
-void NotificationViewMD::OnMouseMoved(const ui::MouseEvent& event) {
- MessageView::OnMouseMoved(event);
- UpdateControlButtonsVisibility();
-}
-
void NotificationViewMD::OnMouseEntered(const ui::MouseEvent& event) {
MessageView::OnMouseEntered(event);
UpdateControlButtonsVisibility();
@@ -557,12 +568,23 @@ void NotificationViewMD::OnMouseExited(const ui::MouseEvent& event) {
void NotificationViewMD::UpdateWithNotification(
const Notification& notification) {
MessageView::UpdateWithNotification(notification);
+ UpdateControlButtonsVisibilityWithNotification(notification);
CreateOrUpdateViews(notification);
Layout();
SchedulePaint();
}
+// TODO(yoshiki): Move this to the parent class (MessageView).
+void NotificationViewMD::UpdateControlButtonsVisibilityWithNotification(
+ const Notification& notification) {
+ control_buttons_view_->ShowSettingsButton(
+ notification.delegate() &&
+ notification.delegate()->ShouldDisplaySettingsButton());
+ control_buttons_view_->ShowCloseButton(!GetPinned());
+ UpdateControlButtonsVisibility();
+}
+
void NotificationViewMD::ButtonPressed(views::Button* sender,
const ui::Event& event) {
// Certain operations can cause |this| to be destructed, so copy the members
@@ -570,20 +592,6 @@ void NotificationViewMD::ButtonPressed(views::Button* sender,
// TODO(dewittj): Remove this hack.
std::string id(notification_id());
- if (header_row_->IsCloseButtonEnabled() &&
- sender == header_row_->close_button()) {
- // Warning: This causes the NotificationViewMD itself to be deleted, so
- // don't do anything afterwards.
- OnCloseButtonPressed();
- return;
- }
-
- if (header_row_->IsSettingsButtonEnabled() &&
- sender == header_row_->settings_button()) {
- controller()->ClickOnSettingsButton(id);
- return;
- }
-
// Tapping anywhere on |header_row_| can expand the notification, though only
// |expand_button| can be focused by TAB.
if (IsExpandable() && sender == header_row_) {
@@ -603,22 +611,39 @@ void NotificationViewMD::ButtonPressed(views::Button* sender,
}
bool NotificationViewMD::IsCloseButtonFocused() const {
- if (!header_row_->IsCloseButtonEnabled())
- return false;
-
- const views::FocusManager* focus_manager = GetFocusManager();
- return focus_manager &&
- focus_manager->GetFocusedView() == header_row_->close_button();
+ return control_buttons_view_->IsCloseButtonFocused();
}
void NotificationViewMD::RequestFocusOnCloseButton() {
- if (header_row_->IsCloseButtonEnabled())
- header_row_->close_button()->RequestFocus();
+ control_buttons_view_->RequestFocusOnCloseButton();
}
void NotificationViewMD::CreateOrUpdateContextTitleView(
const Notification& notification) {
+#if defined(OS_CHROMEOS)
+ // If |origin_url| and |display_source| are both empty, assume it is
+ // system notification, and use default |display_source| and
+ // |accent_color| for system notification.
+ // TODO(tetsui): Remove this after all system notification transition is
+ // completed.
+ // All system notification should use Notification::CreateSystemNotification()
+ if ((notification.display_source().empty() &&
+ notification.origin_url().is_empty()) ||
+ ShowDefaultDisplaySource(notification.notifier_id())) {
+ header_row_->SetAppName(l10n_util::GetStringFUTF16(
+ IDS_MESSAGE_CENTER_NOTIFICATION_CHROMEOS_SYSTEM,
+ MessageCenter::Get()->GetProductOSName()));
+ header_row_->SetAccentColor(message_center::kSystemNotificationColorNormal);
+ header_row_->SetTimestamp(notification.timestamp());
+ return;
+ }
+#endif
+
header_row_->SetAppName(notification.display_source());
+ header_row_->SetAccentColor(
+ notification.accent_color() == SK_ColorTRANSPARENT
+ ? message_center::kNotificationDefaultAccentColor
+ : notification.accent_color());
header_row_->SetTimestamp(notification.timestamp());
}
@@ -631,8 +656,6 @@ void NotificationViewMD::CreateOrUpdateTitleView(
title_view_ = nullptr;
return;
}
- const gfx::FontList& font_list = views::Label().font_list().Derive(
- 1, gfx::Font::NORMAL, gfx::Font::Weight::NORMAL);
int title_character_limit =
kNotificationWidth * kMaxTitleLines / kMinPixelsPerTitleCharacter;
@@ -640,10 +663,12 @@ void NotificationViewMD::CreateOrUpdateTitleView(
base::string16 title = gfx::TruncateString(
notification.title(), title_character_limit, gfx::WORD_BREAK);
if (!title_view_) {
+ const gfx::FontList& font_list = GetTextFontList();
+
title_view_ = new views::Label(title);
title_view_->SetFontList(font_list);
title_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- title_view_->SetEnabledColor(message_center::kRegularTextColor);
+ title_view_->SetEnabledColor(kRegularTextColorMD);
left_content_->AddChildView(title_view_);
} else {
title_view_->SetText(title);
@@ -663,22 +688,12 @@ void NotificationViewMD::CreateOrUpdateMessageView(
base::string16 text = gfx::TruncateString(
notification.message(), kMessageCharacterLimit, gfx::WORD_BREAK);
- const gfx::FontList& font_list = views::Label().font_list().Derive(
- 1, gfx::Font::NORMAL, gfx::Font::Weight::NORMAL);
+ const gfx::FontList& font_list = GetTextFontList();
if (!message_view_) {
message_view_ = new BoundedLabel(text, font_list);
message_view_->SetLineLimit(kMaxLinesForMessageView);
- message_view_->SetColors(message_center::kDimTextColor,
- kContextTextBackgroundColor);
-
- // TODO(tetsui): Workaround https://crbug.com/682266 by explicitly setting
- // the width.
- // Ideally, we should fix the original bug, but it seems there's no obvious
- // solution for the bug according to https://crbug.com/678337#c7, we should
- // ensure that the change won't break any of the users of BoxLayout class.
- DCHECK(right_content_);
- message_view_->SizeToFit(kMessageViewWidth);
+ message_view_->SetColors(kDimTextColorMD, kContextTextBackgroundColor);
left_content_->AddChildView(message_view_);
} else {
@@ -730,7 +745,35 @@ void NotificationViewMD::CreateOrUpdateProgressBarView(
progress_bar_view_->SetValue(notification.progress() / 100.0);
progress_bar_view_->SetVisible(notification.items().empty());
- header_row_->SetProgress(notification.progress());
+ if (0 <= notification.progress() && notification.progress() <= 100)
+ header_row_->SetProgress(notification.progress());
+ else
+ header_row_->ClearProgress();
+}
+
+void NotificationViewMD::CreateOrUpdateProgressStatusView(
+ const Notification& notification) {
+ if (notification.type() != NOTIFICATION_TYPE_PROGRESS ||
+ notification.progress_status().empty()) {
+ if (!status_view_)
+ return;
+ DCHECK(left_content_->Contains(status_view_));
+ delete status_view_;
+ status_view_ = nullptr;
+ return;
+ }
+
+ if (!status_view_) {
+ const gfx::FontList& font_list = GetTextFontList();
+ status_view_ = new views::Label();
+ status_view_->SetFontList(font_list);
+ status_view_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ status_view_->SetEnabledColor(kDimTextColorMD);
+ status_view_->SetBorder(views::CreateEmptyBorder(kStatusTextPadding));
+ left_content_->AddChildView(status_view_);
+ }
+
+ status_view_->SetText(notification.progress_status());
}
void NotificationViewMD::CreateOrUpdateListItemViews(
@@ -758,8 +801,7 @@ void NotificationViewMD::CreateOrUpdateListItemViews(
void NotificationViewMD::CreateOrUpdateIconView(
const Notification& notification) {
if (notification.type() == NOTIFICATION_TYPE_PROGRESS ||
- notification.type() == NOTIFICATION_TYPE_MULTIPLE ||
- notification.type() == NOTIFICATION_TYPE_IMAGE) {
+ notification.type() == NOTIFICATION_TYPE_MULTIPLE) {
DCHECK(!icon_view_ || right_content_->Contains(icon_view_));
delete icon_view_;
icon_view_ = nullptr;
@@ -771,17 +813,26 @@ void NotificationViewMD::CreateOrUpdateIconView(
right_content_->AddChildView(icon_view_);
}
- gfx::ImageSkia icon = notification.icon().AsImageSkia();
+ // If |use_image_as_icon| is set, use |image| as the icon on the right
+ // side, instead of |icon|.
+ gfx::ImageSkia icon;
+ if (notification.use_image_as_icon())
+ icon = notification.image().AsImageSkia();
+ else
+ icon = notification.icon().AsImageSkia();
icon_view_->SetImage(icon, icon.size());
+
+ // If |use_image_as_icon| is set, hide the icon on the right side when
+ // the notification is expanded.
+ hide_icon_on_expanded_ = notification.use_image_as_icon();
}
void NotificationViewMD::CreateOrUpdateSmallIconView(
const Notification& notification) {
- gfx::ImageSkia icon =
- notification.small_image().IsEmpty()
- ? GetProductIcon()
- : GetMaskedIcon(notification.small_image().AsImageSkia());
- header_row_->SetAppIcon(icon);
+ if (notification.small_image().IsEmpty())
+ header_row_->ClearAppIcon();
+ else
+ header_row_->SetAppIcon(notification.small_image().AsImageSkia());
}
void NotificationViewMD::CreateOrUpdateImageView(
@@ -829,6 +880,12 @@ void NotificationViewMD::CreateOrUpdateActionButtonViews(
action_buttons_[i]->SchedulePaint();
action_buttons_[i]->Layout();
}
+
+ // Change action button color to the accent color.
+ action_buttons_[i]->SetEnabledTextColors(notification.accent_color() ==
+ SK_ColorTRANSPARENT
+ ? kActionButtonTextColor
+ : notification.accent_color());
}
// Inherit mouse hover state when action button views reset.
@@ -845,24 +902,6 @@ void NotificationViewMD::CreateOrUpdateActionButtonViews(
}
}
-void NotificationViewMD::CreateOrUpdateCloseButtonView(
- const Notification& notification) {
- if (!notification.pinned()) {
- header_row_->SetCloseButtonEnabled(true);
- } else {
- header_row_->SetCloseButtonEnabled(false);
- }
-}
-
-void NotificationViewMD::CreateOrUpdateSettingsButtonView(
- const Notification& notification) {
- if (notification.delegate() &&
- notification.delegate()->ShouldDisplaySettingsButton())
- header_row_->SetSettingsButtonEnabled(true);
- else
- header_row_->SetSettingsButtonEnabled(false);
-}
-
bool NotificationViewMD::IsExpandable() {
// Expandable if the message exceeds one line.
if (message_view_ && message_view_->visible() &&
@@ -887,11 +926,7 @@ bool NotificationViewMD::IsExpandable() {
}
void NotificationViewMD::ToggleExpanded() {
- expanded_ = !expanded_;
- UpdateViewForExpandedState(expanded_);
- content_row_->InvalidateLayout();
- if (controller())
- controller()->UpdateNotificationSize(notification_id());
+ SetExpanded(!expanded_);
}
void NotificationViewMD::UpdateViewForExpandedState(bool expanded) {
@@ -906,27 +941,61 @@ void NotificationViewMD::UpdateViewForExpandedState(bool expanded) {
for (size_t i = kMaxLinesForMessageView; i < item_views_.size(); ++i) {
item_views_[i]->SetVisible(expanded);
}
+ if (status_view_)
+ status_view_->SetVisible(expanded);
header_row_->SetOverflowIndicator(
list_items_count_ -
(expanded ? item_views_.size() : kMaxLinesForMessageView));
+
+ if (icon_view_)
+ icon_view_->SetVisible(!hide_icon_on_expanded_ || !expanded);
+
+ if (icon_view_ && icon_view_->visible()) {
+ left_content_->SetBorder(
+ views::CreateEmptyBorder(kLeftContentPaddingWithIcon));
+
+ // TODO(tetsui): Workaround https://crbug.com/682266 by explicitly setting
+ // the width.
+ // Ideally, we should fix the original bug, but it seems there's no obvious
+ // solution for the bug according to https://crbug.com/678337#c7, we should
+ // ensure that the change won't break any of the users of BoxLayout class.
+ if (message_view_)
+ message_view_->SizeToFit(kMessageViewWidthWithIcon);
+ } else {
+ left_content_->SetBorder(views::CreateEmptyBorder(kLeftContentPadding));
+ if (message_view_)
+ message_view_->SizeToFit(kMessageViewWidth);
+ }
}
+// TODO(yoshiki): Move this to the parent class (MessageView) and share the code
+// among NotificationView and ArcNotificationView.
void NotificationViewMD::UpdateControlButtonsVisibility() {
- const bool target_visibility = IsMouseHovered() || HasFocus() ||
- (header_row_->IsExpandButtonEnabled() &&
- header_row_->expand_button()->HasFocus()) ||
- (header_row_->IsCloseButtonEnabled() &&
- header_row_->close_button()->HasFocus()) ||
- (header_row_->IsSettingsButtonEnabled() &&
- header_row_->settings_button()->HasFocus());
+ const bool target_visibility =
+ IsMouseHovered() || control_buttons_view_->IsCloseButtonFocused() ||
+ control_buttons_view_->IsSettingsButtonFocused();
- header_row_->SetControlButtonsVisible(target_visibility);
+ control_buttons_view_->SetVisible(target_visibility);
}
NotificationControlButtonsView* NotificationViewMD::GetControlButtonsView()
const {
- // TODO(yoshiki): have this view use NotificationControlButtonsView.
- return nullptr;
+ return control_buttons_view_.get();
+}
+
+bool NotificationViewMD::IsExpanded() const {
+ return expanded_;
+}
+
+void NotificationViewMD::SetExpanded(bool expanded) {
+ if (expanded_ == expanded)
+ return;
+ expanded_ = expanded;
+
+ UpdateViewForExpandedState(expanded_);
+ content_row_->InvalidateLayout();
+ if (controller())
+ controller()->UpdateNotificationSize(notification_id());
}
} // namespace message_center
diff --git a/chromium/ui/message_center/views/notification_view_md.h b/chromium/ui/message_center/views/notification_view_md.h
index 8d595d92f1f..51f8f723868 100644
--- a/chromium/ui/message_center/views/notification_view_md.h
+++ b/chromium/ui/message_center/views/notification_view_md.h
@@ -12,6 +12,7 @@
#include "ui/message_center/message_center_export.h"
#include "ui/message_center/views/message_view.h"
#include "ui/views/controls/button/button.h"
+#include "ui/views/controls/button/label_button.h"
#include "ui/views/view_targeter_delegate.h"
namespace views {
@@ -32,6 +33,27 @@ class ItemView;
class LargeImageContainerView;
}
+// This class is needed in addition to LabelButton mainly becuase we want to set
+// visible_opacity of InkDropHighlight.
+// This button capitalizes the given label string.
+class NotificationButtonMD : public views::LabelButton {
+ public:
+ NotificationButtonMD(views::ButtonListener* listener,
+ const base::string16& text);
+ ~NotificationButtonMD() override;
+
+ void SetText(const base::string16& text) override;
+ const char* GetClassName() const override;
+
+ std::unique_ptr<views::InkDropHighlight> CreateInkDropHighlight()
+ const override;
+
+ SkColor enabled_color_for_testing() { return label()->enabled_color(); }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(NotificationButtonMD);
+};
+
// View that displays all current types of notification (web, basic, image, and
// list) except the custom notification. Future notification types may be
// handled by other classes, in which case instances of those classes would be
@@ -50,7 +72,6 @@ class MESSAGE_CENTER_EXPORT NotificationViewMD
void OnFocus() override;
void ScrollRectToVisible(const gfx::Rect& rect) override;
gfx::NativeCursor GetCursor(const ui::MouseEvent& event) override;
- void OnMouseMoved(const ui::MouseEvent& event) override;
void OnMouseEntered(const ui::MouseEvent& event) override;
void OnMouseExited(const ui::MouseEvent& event) override;
@@ -61,6 +82,8 @@ class MESSAGE_CENTER_EXPORT NotificationViewMD
void RequestFocusOnCloseButton() override;
void UpdateControlButtonsVisibility() override;
NotificationControlButtonsView* GetControlButtonsView() const override;
+ bool IsExpanded() const override;
+ void SetExpanded(bool expanded) override;
// views::ViewTargeterDelegate:
views::View* TargetForRect(views::View* root, const gfx::Rect& rect) override;
@@ -71,9 +94,14 @@ class MESSAGE_CENTER_EXPORT NotificationViewMD
FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, UpdateButtonsStateTest);
FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, UpdateButtonCountTest);
FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, ExpandLongMessage);
+ FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, TestAccentColor);
+ FRIEND_TEST_ALL_PREFIXES(NotificationViewMDTest, UseImageAsIcon);
friend class NotificationViewMDTest;
+ void UpdateControlButtonsVisibilityWithNotification(
+ const Notification& notification);
+
void CreateOrUpdateViews(const Notification& notification);
void CreateOrUpdateContextTitleView(const Notification& notification);
@@ -81,21 +109,26 @@ class MESSAGE_CENTER_EXPORT NotificationViewMD
void CreateOrUpdateMessageView(const Notification& notification);
void CreateOrUpdateCompactTitleMessageView(const Notification& notification);
void CreateOrUpdateProgressBarView(const Notification& notification);
+ void CreateOrUpdateProgressStatusView(const Notification& notification);
void CreateOrUpdateListItemViews(const Notification& notification);
void CreateOrUpdateIconView(const Notification& notification);
void CreateOrUpdateSmallIconView(const Notification& notification);
void CreateOrUpdateImageView(const Notification& notification);
void CreateOrUpdateActionButtonViews(const Notification& notification);
- void CreateOrUpdateCloseButtonView(const Notification& notification);
- void CreateOrUpdateSettingsButtonView(const Notification& notification);
bool IsExpandable();
void ToggleExpanded();
void UpdateViewForExpandedState(bool expanded);
+ // View containing close and settings buttons
+ std::unique_ptr<NotificationControlButtonsView> control_buttons_view_;
+
// Whether this notification is expanded or not.
bool expanded_ = false;
+ // Whether hiding icon on the right side when expanded.
+ bool hide_icon_on_expanded_ = false;
+
// Number of total list items in the given Notification class.
int list_items_count_ = 0;
@@ -114,9 +147,10 @@ class MESSAGE_CENTER_EXPORT NotificationViewMD
// Views which are dinamicallly created inside view hierarchy.
views::Label* title_view_ = nullptr;
BoundedLabel* message_view_ = nullptr;
+ views::Label* status_view_ = nullptr;
ProportionalImageView* icon_view_ = nullptr;
LargeImageContainerView* image_container_view_ = nullptr;
- std::vector<views::LabelButton*> action_buttons_;
+ std::vector<NotificationButtonMD*> action_buttons_;
std::vector<ItemView*> item_views_;
views::ProgressBar* progress_bar_view_ = nullptr;
CompactTitleMessageView* compact_title_message_view_ = nullptr;
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 f39b2d565fb..bc5af61e22d 100644
--- a/chromium/ui/message_center/views/notification_view_md_unittest.cc
+++ b/chromium/ui/message_center/views/notification_view_md_unittest.cc
@@ -16,7 +16,9 @@
#include "ui/message_center/message_center_style.h"
#include "ui/message_center/views/bounded_label.h"
#include "ui/message_center/views/message_center_controller.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"
#include "ui/message_center/views/proportional_image_view.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/button/label_button.h"
@@ -78,7 +80,7 @@ class NotificationViewMDTest : public views::ViewsTestBase,
void BeginScroll();
void EndScroll();
void ScrollBy(int dx);
- views::ImageButton* GetCloseButton();
+ views::View* GetCloseButton();
private:
std::set<std::string> removed_ids_;
@@ -263,8 +265,8 @@ void NotificationViewMDTest::ScrollBy(int dx) {
DispatchGesture(ui::GestureEventDetails(ui::ET_GESTURE_SCROLL_UPDATE, dx, 0));
}
-views::ImageButton* NotificationViewMDTest::GetCloseButton() {
- return notification_view()->header_row_->close_button();
+views::View* NotificationViewMDTest::GetCloseButton() {
+ return notification_view()->GetControlButtonsView()->close_button();
}
/* Unit tests *****************************************************************/
@@ -299,7 +301,7 @@ TEST_F(NotificationViewMDTest, CreateOrUpdateTest) {
TEST_F(NotificationViewMDTest, TestIconSizing) {
// TODO(tetsui): Remove duplicated integer literal in CreateOrUpdateIconView.
- const int kNotificationIconSize = 30;
+ const int kNotificationIconSize = 36;
notification()->set_type(NOTIFICATION_TYPE_SIMPLE);
ProportionalImageView* view = notification_view()->icon_view_;
@@ -344,7 +346,7 @@ TEST_F(NotificationViewMDTest, UpdateButtonsStateTest) {
notification_view()->ToggleExpanded();
EXPECT_TRUE(notification_view()->actions_row_->visible());
- EXPECT_EQ(views::CustomButton::STATE_NORMAL,
+ EXPECT_EQ(views::Button::STATE_NORMAL,
notification_view()->action_buttons_[0]->state());
// Now construct a mouse move event 1 pixel inside the boundary of the action
@@ -356,12 +358,12 @@ TEST_F(NotificationViewMDTest, UpdateButtonsStateTest) {
ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
widget()->OnMouseEvent(&move);
- EXPECT_EQ(views::CustomButton::STATE_HOVERED,
+ EXPECT_EQ(views::Button::STATE_HOVERED,
notification_view()->action_buttons_[0]->state());
notification_view()->CreateOrUpdateViews(*notification());
- EXPECT_EQ(views::CustomButton::STATE_HOVERED,
+ EXPECT_EQ(views::Button::STATE_HOVERED,
notification_view()->action_buttons_[0]->state());
// Now construct a mouse move event 1 pixel outside the boundary of the
@@ -371,7 +373,7 @@ TEST_F(NotificationViewMDTest, UpdateButtonsStateTest) {
ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
widget()->OnMouseEvent(&move);
- EXPECT_EQ(views::CustomButton::STATE_NORMAL,
+ EXPECT_EQ(views::Button::STATE_NORMAL,
notification_view()->action_buttons_[0]->state());
}
@@ -385,9 +387,9 @@ TEST_F(NotificationViewMDTest, UpdateButtonCountTest) {
notification_view()->ToggleExpanded();
EXPECT_TRUE(notification_view()->actions_row_->visible());
- EXPECT_EQ(views::CustomButton::STATE_NORMAL,
+ EXPECT_EQ(views::Button::STATE_NORMAL,
notification_view()->action_buttons_[0]->state());
- EXPECT_EQ(views::CustomButton::STATE_NORMAL,
+ EXPECT_EQ(views::Button::STATE_NORMAL,
notification_view()->action_buttons_[1]->state());
// Now construct a mouse move event 1 pixel inside the boundary of the action
@@ -401,15 +403,15 @@ TEST_F(NotificationViewMDTest, UpdateButtonCountTest) {
views::test::WidgetTest::GetEventSink(widget())->OnEventFromSource(&move);
EXPECT_FALSE(details.dispatcher_destroyed);
- EXPECT_EQ(views::CustomButton::STATE_HOVERED,
+ EXPECT_EQ(views::Button::STATE_HOVERED,
notification_view()->action_buttons_[0]->state());
- EXPECT_EQ(views::CustomButton::STATE_NORMAL,
+ EXPECT_EQ(views::Button::STATE_NORMAL,
notification_view()->action_buttons_[1]->state());
notification()->set_buttons(CreateButtons(1));
notification_view()->UpdateWithNotification(*notification());
- EXPECT_EQ(views::CustomButton::STATE_HOVERED,
+ EXPECT_EQ(views::Button::STATE_HOVERED,
notification_view()->action_buttons_[0]->state());
EXPECT_EQ(1u, notification_view()->action_buttons_.size());
@@ -420,7 +422,7 @@ TEST_F(NotificationViewMDTest, UpdateButtonCountTest) {
ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
widget()->OnMouseEvent(&move);
- EXPECT_EQ(views::CustomButton::STATE_NORMAL,
+ EXPECT_EQ(views::Button::STATE_NORMAL,
notification_view()->action_buttons_[0]->state());
}
@@ -491,10 +493,25 @@ TEST_F(NotificationViewMDTest, SlideOutPinned) {
}
TEST_F(NotificationViewMDTest, Pinned) {
+ // Visible at the initial state.
+ EXPECT_TRUE(GetCloseButton());
+ EXPECT_TRUE(GetCloseButton()->visible());
+
+ // Pin.
notification()->set_pinned(true);
+ UpdateNotificationViews();
+ EXPECT_FALSE(GetCloseButton());
+ // Unpin.
+ notification()->set_pinned(false);
+ UpdateNotificationViews();
+ EXPECT_TRUE(GetCloseButton());
+ EXPECT_TRUE(GetCloseButton()->visible());
+
+ // Pin again.
+ notification()->set_pinned(true);
UpdateNotificationViews();
- EXPECT_FALSE(GetCloseButton()->visible());
+ EXPECT_FALSE(GetCloseButton());
}
#endif // defined(OS_CHROMEOS)
@@ -532,4 +549,74 @@ TEST_F(NotificationViewMDTest, ExpandLongMessage) {
notification_view()->GetPreferredSize().height());
}
+TEST_F(NotificationViewMDTest, TestAccentColor) {
+ const SkColor kActionButtonTextColor = SkColorSetRGB(0x33, 0x67, 0xD6);
+ const SkColor kCustomAccentColor = SkColorSetRGB(0xea, 0x61, 0x0);
+
+ notification()->set_buttons(CreateButtons(2));
+ UpdateNotificationViews();
+ widget()->Show();
+
+ // Action buttons are hidden by collapsed state.
+ if (!notification_view()->expanded_)
+ notification_view()->ToggleExpanded();
+ EXPECT_TRUE(notification_view()->actions_row_->visible());
+
+ // By default, header does not have accent color (default grey), and
+ // buttons have default accent color.
+ EXPECT_EQ(message_center::kNotificationDefaultAccentColor,
+ notification_view()->header_row_->accent_color_for_testing());
+ EXPECT_EQ(
+ kActionButtonTextColor,
+ notification_view()->action_buttons_[0]->enabled_color_for_testing());
+ EXPECT_EQ(
+ kActionButtonTextColor,
+ notification_view()->action_buttons_[1]->enabled_color_for_testing());
+
+ // If custom accent color is set, the header and the buttons should have the
+ // same accent color.
+ notification()->set_accent_color(kCustomAccentColor);
+ UpdateNotificationViews();
+ EXPECT_EQ(kCustomAccentColor,
+ notification_view()->header_row_->accent_color_for_testing());
+ EXPECT_EQ(
+ kCustomAccentColor,
+ notification_view()->action_buttons_[0]->enabled_color_for_testing());
+ EXPECT_EQ(
+ kCustomAccentColor,
+ notification_view()->action_buttons_[1]->enabled_color_for_testing());
+}
+
+TEST_F(NotificationViewMDTest, UseImageAsIcon) {
+ // TODO(tetsui): Remove duplicated integer literal in CreateOrUpdateIconView.
+ const int kNotificationIconSize = 30;
+
+ notification()->set_type(NotificationType::NOTIFICATION_TYPE_IMAGE);
+ notification()->set_icon(
+ CreateTestImage(kNotificationIconSize, kNotificationIconSize));
+
+ // Test normal notification.
+ UpdateNotificationViews();
+ EXPECT_FALSE(notification_view()->expanded_);
+ EXPECT_TRUE(notification_view()->icon_view_->visible());
+
+ // Icon on the right side is still visible when expanded.
+ notification_view()->ToggleExpanded();
+ EXPECT_TRUE(notification_view()->expanded_);
+ EXPECT_TRUE(notification_view()->icon_view_->visible());
+
+ notification_view()->ToggleExpanded();
+ EXPECT_FALSE(notification_view()->expanded_);
+
+ // Test notification with use_image_as_icon e.g. screenshot preview.
+ notification()->set_use_image_as_icon(true);
+ UpdateNotificationViews();
+ EXPECT_TRUE(notification_view()->icon_view_->visible());
+
+ // Icon on the right side is not visible when expanded.
+ notification_view()->ToggleExpanded();
+ EXPECT_TRUE(notification_view()->expanded_);
+ EXPECT_FALSE(notification_view()->icon_view_->visible());
+}
+
} // namespace message_center
diff --git a/chromium/ui/message_center/views/notification_view_unittest.cc b/chromium/ui/message_center/views/notification_view_unittest.cc
index 4e5ac153ed8..1ecd9270ee0 100644
--- a/chromium/ui/message_center/views/notification_view_unittest.cc
+++ b/chromium/ui/message_center/views/notification_view_unittest.cc
@@ -9,6 +9,7 @@
#include "base/macros.h"
#include "base/strings/string_util.h"
#include "base/strings/utf_string_conversions.h"
+#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
@@ -38,6 +39,10 @@
#include "ui/views/test/widget_test.h"
#include "ui/views/widget/widget_delegate.h"
+#if defined(OS_WIN)
+#include "ui/base/win/shell.h"
+#endif
+
namespace message_center {
// A test delegate used for tests that deal with the notification settings
@@ -162,11 +167,11 @@ class NotificationViewTest : public views::ViewsTestBase,
}
}
- PaddedButton* GetCloseButton() {
+ views::Button* GetCloseButton() {
return notification_view()->control_buttons_view_->close_button();
}
- PaddedButton* GetSettingsButton() {
+ views::Button* GetSettingsButton() {
return notification_view()->control_buttons_view_->settings_button();
}
@@ -238,8 +243,21 @@ void NotificationViewTest::SetUp() {
notification_->set_image(CreateTestImage(320, 240));
// Then create a new NotificationView with that single notification.
- notification_view_.reset(static_cast<NotificationView*>(
- MessageViewFactory::Create(this, *notification_, true)));
+ notification_view_.reset(new NotificationView(this, *notification_));
+
+ // It depends on platform whether shadows are added.
+ // See MessageViewFactory::Create.
+ bool is_nested = true;
+#if defined(OS_LINUX)
+ is_nested = false;
+#endif
+#if defined(OS_WIN)
+ if (!ui::win::IsAeroGlassEnabled())
+ is_nested = false;
+#endif
+ if (is_nested)
+ notification_view_->SetIsNested();
+
notification_view_->set_owned_by_client();
views::Widget::InitParams init_params(
@@ -463,7 +481,7 @@ TEST_F(NotificationViewTest, UpdateButtonsStateTest) {
notification_view()->UpdateWithNotification(*notification());
widget()->Show();
- EXPECT_EQ(views::CustomButton::STATE_NORMAL,
+ EXPECT_EQ(views::Button::STATE_NORMAL,
notification_view()->action_buttons_[0]->state());
// Now construct a mouse move event 1 pixel inside the boundary of the action
@@ -475,12 +493,12 @@ TEST_F(NotificationViewTest, UpdateButtonsStateTest) {
ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
widget()->OnMouseEvent(&move);
- EXPECT_EQ(views::CustomButton::STATE_HOVERED,
+ EXPECT_EQ(views::Button::STATE_HOVERED,
notification_view()->action_buttons_[0]->state());
notification_view()->UpdateWithNotification(*notification());
- EXPECT_EQ(views::CustomButton::STATE_HOVERED,
+ EXPECT_EQ(views::Button::STATE_HOVERED,
notification_view()->action_buttons_[0]->state());
// Now construct a mouse move event 1 pixel outside the boundary of the
@@ -490,7 +508,7 @@ TEST_F(NotificationViewTest, UpdateButtonsStateTest) {
ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
widget()->OnMouseEvent(&move);
- EXPECT_EQ(views::CustomButton::STATE_NORMAL,
+ EXPECT_EQ(views::Button::STATE_NORMAL,
notification_view()->action_buttons_[0]->state());
}
@@ -499,9 +517,9 @@ TEST_F(NotificationViewTest, UpdateButtonCountTest) {
notification_view()->UpdateWithNotification(*notification());
widget()->Show();
- EXPECT_EQ(views::CustomButton::STATE_NORMAL,
+ EXPECT_EQ(views::Button::STATE_NORMAL,
notification_view()->action_buttons_[0]->state());
- EXPECT_EQ(views::CustomButton::STATE_NORMAL,
+ EXPECT_EQ(views::Button::STATE_NORMAL,
notification_view()->action_buttons_[1]->state());
// Now construct a mouse move event 1 pixel inside the boundary of the action
@@ -515,15 +533,15 @@ TEST_F(NotificationViewTest, UpdateButtonCountTest) {
views::test::WidgetTest::GetEventSink(widget())->OnEventFromSource(&move);
EXPECT_FALSE(details.dispatcher_destroyed);
- EXPECT_EQ(views::CustomButton::STATE_HOVERED,
+ EXPECT_EQ(views::Button::STATE_HOVERED,
notification_view()->action_buttons_[0]->state());
- EXPECT_EQ(views::CustomButton::STATE_NORMAL,
+ EXPECT_EQ(views::Button::STATE_NORMAL,
notification_view()->action_buttons_[1]->state());
notification()->set_buttons(CreateButtons(1));
notification_view()->UpdateWithNotification(*notification());
- EXPECT_EQ(views::CustomButton::STATE_HOVERED,
+ EXPECT_EQ(views::Button::STATE_HOVERED,
notification_view()->action_buttons_[0]->state());
EXPECT_EQ(1u, notification_view()->action_buttons_.size());
@@ -534,7 +552,7 @@ TEST_F(NotificationViewTest, UpdateButtonCountTest) {
ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
widget()->OnMouseEvent(&move);
- EXPECT_EQ(views::CustomButton::STATE_NORMAL,
+ EXPECT_EQ(views::Button::STATE_NORMAL,
notification_view()->action_buttons_[0]->state());
}
@@ -552,7 +570,7 @@ TEST_F(NotificationViewTest, SettingsButtonTest) {
widget()->Show();
EXPECT_TRUE(NULL != GetSettingsButton());
- EXPECT_EQ(views::CustomButton::STATE_NORMAL, GetSettingsButton()->state());
+ EXPECT_EQ(views::Button::STATE_NORMAL, GetSettingsButton()->state());
// Now construct a mouse move event 1 pixel inside the boundary of the action
// button.
@@ -565,7 +583,7 @@ TEST_F(NotificationViewTest, SettingsButtonTest) {
views::test::WidgetTest::GetEventSink(widget())->OnEventFromSource(&move);
EXPECT_FALSE(details.dispatcher_destroyed);
- EXPECT_EQ(views::CustomButton::STATE_HOVERED, GetSettingsButton()->state());
+ EXPECT_EQ(views::Button::STATE_HOVERED, GetSettingsButton()->state());
// Now construct a mouse move event 1 pixel outside the boundary of the
// widget.
@@ -574,7 +592,7 @@ TEST_F(NotificationViewTest, SettingsButtonTest) {
ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
widget()->OnMouseEvent(&move);
- EXPECT_EQ(views::CustomButton::STATE_NORMAL, GetSettingsButton()->state());
+ EXPECT_EQ(views::Button::STATE_NORMAL, GetSettingsButton()->state());
}
TEST_F(NotificationViewTest, ViewOrderingTest) {
@@ -731,11 +749,31 @@ TEST_F(NotificationViewTest, SlideOutPinned) {
EXPECT_FALSE(IsRemoved(notification_id));
}
-TEST_F(NotificationViewTest, Pinned) {
+TEST_F(NotificationViewTest, SlideOutForceDisablePinned) {
+ ui::ScopedAnimationDurationScaleMode zero_duration_scope(
+ ui::ScopedAnimationDurationScaleMode::ZERO_DURATION);
+
notification()->set_pinned(true);
+ notification_view()->set_force_disable_pinned();
+ UpdateNotificationViews();
+ std::string notification_id = notification()->id();
+
+ BeginScroll();
+ ScrollBy(-200);
+ EXPECT_FALSE(IsRemoved(notification_id));
+ EXPECT_EQ(-200.f, GetNotificationSlideAmount());
+ EndScroll();
+ EXPECT_TRUE(IsRemoved(notification_id));
+}
+TEST_F(NotificationViewTest, Pinned) {
+ notification()->set_pinned(true);
UpdateNotificationViews();
EXPECT_EQ(NULL, GetCloseButton());
+
+ notification_view()->set_force_disable_pinned();
+ UpdateNotificationViews();
+ EXPECT_TRUE(GetCloseButton());
}
#endif // defined(OS_CHROMEOS)
diff --git a/chromium/ui/message_center/views/notifier_settings_view.cc b/chromium/ui/message_center/views/notifier_settings_view.cc
index 7958f037b9f..639c3341439 100644
--- a/chromium/ui/message_center/views/notifier_settings_view.cc
+++ b/chromium/ui/message_center/views/notifier_settings_view.cc
@@ -234,7 +234,7 @@ NotifierSettingsView::NotifierButton::NotifierButton(
NotifierSettingsProvider* provider,
std::unique_ptr<Notifier> notifier,
views::ButtonListener* listener)
- : views::CustomButton(listener),
+ : views::Button(listener),
provider_(provider),
notifier_(std::move(notifier)),
icon_view_(new views::ImageView()),
@@ -337,7 +337,7 @@ void NotifierSettingsView::NotifierButton::ButtonPressed(
// the state on NotifierSettingsView::ButtonPressed() too, so here change
// back to the previous state.
checkbox_->SetChecked(!checkbox_->checked());
- CustomButton::NotifyClick(event);
+ Button::NotifyClick(event);
} else if (button == learn_more_) {
DCHECK(provider_);
provider_->OnNotifierAdvancedSettingsRequested(notifier_->notifier_id,
diff --git a/chromium/ui/message_center/views/notifier_settings_view.h b/chromium/ui/message_center/views/notifier_settings_view.h
index e6ed209b1b2..18d8659891d 100644
--- a/chromium/ui/message_center/views/notifier_settings_view.h
+++ b/chromium/ui/message_center/views/notifier_settings_view.h
@@ -12,7 +12,6 @@
#include "base/macros.h"
#include "ui/message_center/message_center_export.h"
#include "ui/message_center/notifier_settings.h"
-#include "ui/message_center/views/message_bubble_base.h"
#include "ui/views/controls/button/checkbox.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/combobox/combobox_listener.h"
@@ -57,8 +56,8 @@ class MESSAGE_CENTER_EXPORT NotifierSettingsView
private:
FRIEND_TEST_ALL_PREFIXES(NotifierSettingsViewTest, TestLearnMoreButton);
- class MESSAGE_CENTER_EXPORT NotifierButton : public views::CustomButton,
- public views::ButtonListener {
+ class MESSAGE_CENTER_EXPORT NotifierButton : public views::Button,
+ public views::ButtonListener {
public:
NotifierButton(NotifierSettingsProvider* provider,
std::unique_ptr<Notifier> notifier,
diff --git a/chromium/ui/native_theme/common_theme.cc b/chromium/ui/native_theme/common_theme.cc
index 96c817021b6..d299f91dbb7 100644
--- a/chromium/ui/native_theme/common_theme.cc
+++ b/chromium/ui/native_theme/common_theme.cc
@@ -35,7 +35,7 @@ SkColor GetAuraColor(NativeTheme::ColorId color_id,
// FocusableBorder
case NativeTheme::kColorId_UnfocusedBorderColor:
- return SkColorSetA(SK_ColorBLACK, 0x33);
+ return SkColorSetA(SK_ColorBLACK, 0x4e);
// Textfields
case NativeTheme::kColorId_TextfieldDefaultColor:
diff --git a/chromium/ui/native_theme/native_theme_features.cc b/chromium/ui/native_theme/native_theme_features.cc
index 25cf50a4605..28d388ca3ed 100644
--- a/chromium/ui/native_theme/native_theme_features.cc
+++ b/chromium/ui/native_theme/native_theme_features.cc
@@ -20,6 +20,17 @@ constexpr base::FeatureState kOverlayScrollbarFeatureState =
const base::Feature kOverlayScrollbar{"OverlayScrollbar",
kOverlayScrollbarFeatureState};
+// Experiment: Enables will flash all scrollbars in page after any scroll
+// update.
+const base::Feature kOverlayScrollbarFlashAfterAnyScrollUpdate{
+ "OverlayScrollbarFlashAfterAnyScrollUpdate",
+ base::FEATURE_DISABLED_BY_DEFAULT};
+
+// Experiment: Enables will flash scorllbar when user move mouse enter a
+// scrollable area.
+const base::Feature kOverlayScrollbarFlashWhenMouseEnter{
+ "OverlayScrollbarFlashWhenMouseEnter", base::FEATURE_DISABLED_BY_DEFAULT};
+
} // namespace features
namespace ui {
@@ -28,4 +39,14 @@ bool IsOverlayScrollbarEnabled() {
return base::FeatureList::IsEnabled(features::kOverlayScrollbar);
}
+bool OverlayScrollbarFlashAfterAnyScrollUpdate() {
+ return base::FeatureList::IsEnabled(
+ features::kOverlayScrollbarFlashAfterAnyScrollUpdate);
+}
+
+bool OverlayScrollbarFlashWhenMouseEnter() {
+ return base::FeatureList::IsEnabled(
+ features::kOverlayScrollbarFlashWhenMouseEnter);
+}
+
} // namespace ui
diff --git a/chromium/ui/native_theme/native_theme_features.h b/chromium/ui/native_theme/native_theme_features.h
index 85e898574c2..e6cbdec5944 100644
--- a/chromium/ui/native_theme/native_theme_features.h
+++ b/chromium/ui/native_theme/native_theme_features.h
@@ -13,12 +13,18 @@
namespace features {
NATIVE_THEME_EXPORT extern const base::Feature kOverlayScrollbar;
+NATIVE_THEME_EXPORT extern const base::Feature
+ kOverlayScrollbarFlashAfterAnyScrollUpdate;
+NATIVE_THEME_EXPORT extern const base::Feature
+ kOverlayScrollbarFlashWhenMouseEnter;
} // namespace features
namespace ui {
NATIVE_THEME_EXPORT bool IsOverlayScrollbarEnabled();
+NATIVE_THEME_EXPORT bool OverlayScrollbarFlashAfterAnyScrollUpdate();
+NATIVE_THEME_EXPORT bool OverlayScrollbarFlashWhenMouseEnter();
} // namespace ui
diff --git a/chromium/ui/native_theme/native_theme_win.cc b/chromium/ui/native_theme/native_theme_win.cc
index 3340f3744cf..649f3b21edc 100644
--- a/chromium/ui/native_theme/native_theme_win.cc
+++ b/chromium/ui/native_theme/native_theme_win.cc
@@ -457,8 +457,12 @@ SkColor NativeThemeWin::GetSystemColor(ColorId color_id) const {
// FocusableBorder
case kColorId_FocusedBorderColor:
+ if (ui::MaterialDesignController::IsSecondaryUiMaterial())
+ break;
return kFocusedBorderColor;
case kColorId_UnfocusedBorderColor:
+ if (ui::MaterialDesignController::IsSecondaryUiMaterial())
+ break;
return kUnfocusedBorderColor;
// Button
diff --git a/chromium/ui/ozone/common/BUILD.gn b/chromium/ui/ozone/common/BUILD.gn
index f079f53ef07..cc1ee3f2e29 100644
--- a/chromium/ui/ozone/common/BUILD.gn
+++ b/chromium/ui/ozone/common/BUILD.gn
@@ -8,8 +8,6 @@ assert(use_ozone)
source_set("common") {
sources = [
- "display_snapshot_proxy.cc",
- "display_snapshot_proxy.h",
"egl_util.cc",
"egl_util.h",
"gl_ozone_egl.cc",
diff --git a/chromium/ui/ozone/common/display_snapshot_proxy.cc b/chromium/ui/ozone/common/display_snapshot_proxy.cc
deleted file mode 100644
index 88ef6cc377f..00000000000
--- a/chromium/ui/ozone/common/display_snapshot_proxy.cc
+++ /dev/null
@@ -1,61 +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/common/display_snapshot_proxy.h"
-
-#include <stddef.h>
-
-#include "base/memory/ptr_util.h"
-#include "ui/display/types/display_mode.h"
-#include "ui/ozone/common/gpu/ozone_gpu_message_params.h"
-
-namespace ui {
-
-namespace {
-
-bool SameModes(const DisplayMode_Params& lhs, const DisplayMode_Params& rhs) {
- return lhs.size == rhs.size && lhs.is_interlaced == rhs.is_interlaced &&
- lhs.refresh_rate == rhs.refresh_rate;
-}
-
-} // namespace
-
-DisplaySnapshotProxy::DisplaySnapshotProxy(const DisplaySnapshot_Params& params)
- : DisplaySnapshotMojo(
- params.display_id,
- params.origin,
- params.physical_size,
- params.type,
- params.is_aspect_preserving_scaling,
- params.has_overscan,
- params.has_color_correction_matrix,
- params.display_name,
- params.sys_path,
- std::vector<std::unique_ptr<const display::DisplayMode>>(),
- params.edid,
- nullptr,
- nullptr,
- params.string_representation) {
- for (size_t i = 0; i < params.modes.size(); ++i) {
- modes_.push_back(base::MakeUnique<display::DisplayMode>(
- params.modes[i].size, params.modes[i].is_interlaced,
- params.modes[i].refresh_rate));
-
- if (params.has_current_mode &&
- SameModes(params.modes[i], params.current_mode))
- current_mode_ = modes_.back().get();
-
- if (params.has_native_mode &&
- SameModes(params.modes[i], params.native_mode))
- native_mode_ = modes_.back().get();
- }
-
- product_id_ = params.product_id;
- maximum_cursor_size_ = params.maximum_cursor_size;
-}
-
-DisplaySnapshotProxy::~DisplaySnapshotProxy() {
-}
-
-} // namespace ui
diff --git a/chromium/ui/ozone/common/display_snapshot_proxy.h b/chromium/ui/ozone/common/display_snapshot_proxy.h
deleted file mode 100644
index a53e2121f67..00000000000
--- a/chromium/ui/ozone/common/display_snapshot_proxy.h
+++ /dev/null
@@ -1,26 +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_COMMON_DISPLAY_SNAPSHOT_PROXY_H_
-#define UI_OZONE_COMMON_DISPLAY_SNAPSHOT_PROXY_H_
-
-#include "base/macros.h"
-#include "ui/display/types/display_snapshot_mojo.h"
-
-namespace ui {
-
-struct DisplaySnapshot_Params;
-
-class DisplaySnapshotProxy : public display::DisplaySnapshotMojo {
- public:
- DisplaySnapshotProxy(const DisplaySnapshot_Params& params);
- ~DisplaySnapshotProxy() override;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(DisplaySnapshotProxy);
-};
-
-} // namespace ui
-
-#endif // UI_OZONE_COMMON_DISPLAY_SNAPSHOT_PROXY_H_
diff --git a/chromium/ui/ozone/common/gl_ozone_osmesa.cc b/chromium/ui/ozone/common/gl_ozone_osmesa.cc
index 2ee4dbba2d6..e7ccc733f59 100644
--- a/chromium/ui/ozone/common/gl_ozone_osmesa.cc
+++ b/chromium/ui/ozone/common/gl_ozone_osmesa.cc
@@ -4,6 +4,7 @@
#include "ui/ozone/common/gl_ozone_osmesa.h"
+#include "build/build_config.h"
#include "ui/gl/gl_bindings.h"
#include "ui/gl/gl_context.h"
#include "ui/gl/gl_context_osmesa.h"
@@ -27,7 +28,14 @@ bool GLOzoneOSMesa::InitializeGLOneOffPlatform() {
bool GLOzoneOSMesa::InitializeStaticGLBindings(
gl::GLImplementation implementation) {
+#if defined(OS_FUCHSIA)
+ // TODO(fuchsia): Enable this once there's EGL available, see
+ // https://crbug.com/750943.
+ NOTIMPLEMENTED();
+ return false;
+#else
return gl::InitializeStaticGLBindingsOSMesaGL();
+#endif
}
void GLOzoneOSMesa::InitializeDebugGLBindings() {
diff --git a/chromium/ui/ozone/common/gpu/ozone_gpu_message_params.cc b/chromium/ui/ozone/common/gpu/ozone_gpu_message_params.cc
index 29692cacea4..79ddb77c77c 100644
--- a/chromium/ui/ozone/common/gpu/ozone_gpu_message_params.cc
+++ b/chromium/ui/ozone/common/gpu/ozone_gpu_message_params.cc
@@ -31,23 +31,12 @@ OverlayCheck_Params::OverlayCheck_Params(
format(candidate.format),
display_rect(gfx::ToNearestRect(candidate.display_rect)),
crop_rect(candidate.crop_rect),
- plane_z_order(candidate.plane_z_order) {}
+ plane_z_order(candidate.plane_z_order),
+ is_overlay_candidate(candidate.overlay_handled) {}
OverlayCheck_Params::OverlayCheck_Params(const OverlayCheck_Params& other) =
default;
OverlayCheck_Params::~OverlayCheck_Params() {}
-bool OverlayCheck_Params::operator<(const OverlayCheck_Params& param) const {
- int lwidth = buffer_size.width();
- int lheight = buffer_size.height();
- int rwidth = param.buffer_size.width();
- int rheight = param.buffer_size.height();
-
- return std::tie(plane_z_order, format, display_rect, lwidth, lheight,
- transform) < std::tie(param.plane_z_order, param.format,
- param.display_rect, rwidth, rheight,
- param.transform);
-}
-
} // namespace ui
diff --git a/chromium/ui/ozone/common/gpu/ozone_gpu_message_params.h b/chromium/ui/ozone/common/gpu/ozone_gpu_message_params.h
index 67d138ee680..204051857d5 100644
--- a/chromium/ui/ozone/common/gpu/ozone_gpu_message_params.h
+++ b/chromium/ui/ozone/common/gpu/ozone_gpu_message_params.h
@@ -52,7 +52,6 @@ struct DisplaySnapshot_Params {
bool has_native_mode = false;
DisplayMode_Params native_mode;
int64_t product_id = 0;
- std::string string_representation;
gfx::Size maximum_cursor_size;
};
@@ -62,7 +61,6 @@ struct OverlayCheck_Params {
OverlayCheck_Params(const OverlayCheck_Params& other);
~OverlayCheck_Params();
- bool operator<(const OverlayCheck_Params& plane) const;
gfx::Size buffer_size;
gfx::OverlayTransform transform = gfx::OVERLAY_TRANSFORM_NONE;
diff --git a/chromium/ui/ozone/common/gpu/ozone_gpu_messages.h b/chromium/ui/ozone/common/gpu/ozone_gpu_messages.h
index c20cc0813a5..b97616c4e65 100644
--- a/chromium/ui/ozone/common/gpu/ozone_gpu_messages.h
+++ b/chromium/ui/ozone/common/gpu/ozone_gpu_messages.h
@@ -60,7 +60,6 @@ IPC_STRUCT_TRAITS_BEGIN(ui::DisplaySnapshot_Params)
IPC_STRUCT_TRAITS_MEMBER(has_native_mode)
IPC_STRUCT_TRAITS_MEMBER(native_mode)
IPC_STRUCT_TRAITS_MEMBER(product_id)
- IPC_STRUCT_TRAITS_MEMBER(string_representation)
IPC_STRUCT_TRAITS_MEMBER(maximum_cursor_size)
IPC_STRUCT_TRAITS_END()
diff --git a/chromium/ui/ozone/demo/gl_renderer.cc b/chromium/ui/ozone/demo/gl_renderer.cc
index 970a299bb50..53f5e96b9f9 100644
--- a/chromium/ui/ozone/demo/gl_renderer.cc
+++ b/chromium/ui/ozone/demo/gl_renderer.cc
@@ -30,7 +30,7 @@ bool GlRenderer::Initialize() {
return false;
}
- surface_->Resize(size_, 1.f, true);
+ surface_->Resize(size_, 1.f, gl::GLSurface::ColorSpace::UNSPECIFIED, true);
if (!context_->MakeCurrent(surface_.get())) {
LOG(ERROR) << "Failed to make GL context current";
diff --git a/chromium/ui/ozone/demo/ozone_demo.cc b/chromium/ui/ozone/demo/ozone_demo.cc
index bf9aa69977e..d5879e685d0 100644
--- a/chromium/ui/ozone/demo/ozone_demo.cc
+++ b/chromium/ui/ozone/demo/ozone_demo.cc
@@ -80,7 +80,7 @@ class RendererFactory {
class WindowManager : public display::NativeDisplayObserver {
public:
- WindowManager(const base::Closure& quit_closure);
+ explicit WindowManager(const base::Closure& quit_closure);
~WindowManager() override;
void Quit();
@@ -285,7 +285,6 @@ void WindowManager::OnConfigurationChanged() {
}
is_configuring_ = true;
- delegate_->GrabServer();
delegate_->GetDisplays(
base::Bind(&WindowManager::OnDisplaysAquired, base::Unretained(this)));
}
@@ -310,7 +309,6 @@ void WindowManager::OnDisplaysAquired(
gfx::Rect(origin, display->native_mode()->size())));
origin.Offset(display->native_mode()->size().width(), 0);
}
- delegate_->UngrabServer();
is_configuring_ = false;
if (should_configure_) {
diff --git a/chromium/ui/ozone/demo/surfaceless_gl_renderer.cc b/chromium/ui/ozone/demo/surfaceless_gl_renderer.cc
index f68bd5ddd70..2708ffc6085 100644
--- a/chromium/ui/ozone/demo/surfaceless_gl_renderer.cc
+++ b/chromium/ui/ozone/demo/surfaceless_gl_renderer.cc
@@ -24,6 +24,36 @@
namespace ui {
+namespace {
+
+OverlaySurfaceCandidate MakeOverlayCandidate(int z_order,
+ gfx::Rect bounds_rect,
+ gfx::RectF crop_rect) {
+ // The overlay checking interface is designed to satisfy the needs of CC which
+ // will be producing RectF target rectangles. But we use the bounds produced
+ // in RenderFrame for GLSurface::ScheduleOverlayPlane.
+ gfx::RectF display_rect(bounds_rect.x(), bounds_rect.y(), bounds_rect.width(),
+ bounds_rect.height());
+
+ OverlaySurfaceCandidate overlay_candidate;
+
+ // The bounds rectangle of the candidate overlay buffer.
+ overlay_candidate.buffer_size = bounds_rect.size();
+ // The same rectangle in floating point coordinates.
+ overlay_candidate.display_rect = display_rect;
+
+ // Show the entire buffer by setting the crop to a unity square.
+ overlay_candidate.crop_rect = gfx::RectF(0, 0, 1, 1);
+
+ // The demo overlay instance is always ontop and not clipped. Clipped quads
+ // cannot be placed in overlays.
+ overlay_candidate.is_clipped = false;
+
+ return overlay_candidate;
+}
+
+} // namespace
+
SurfacelessGlRenderer::BufferWrapper::BufferWrapper() {
}
@@ -107,66 +137,58 @@ bool SurfacelessGlRenderer::Initialize() {
base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
if (command_line->HasSwitch("enable-overlay")) {
gfx::Size overlay_size = gfx::Size(size_.width() / 8, size_.height() / 8);
- overlay_buffer_.reset(new BufferWrapper());
- overlay_buffer_->Initialize(gfx::kNullAcceleratedWidget, overlay_size);
-
- glViewport(0, 0, overlay_size.width(), overlay_size.height());
- glClearColor(1.0, 1.0, 0.0, 1.0);
- glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ for (size_t i = 0; i < arraysize(overlay_buffer_); ++i) {
+ overlay_buffer_[i].reset(new BufferWrapper());
+ overlay_buffer_[i]->Initialize(gfx::kNullAcceleratedWidget, overlay_size);
+
+ glViewport(0, 0, overlay_size.width(), overlay_size.height());
+ glClearColor(i, 1.0, 0.0, 1.0);
+ glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+ }
}
+ disable_primary_plane_ = command_line->HasSwitch("disable-primary-plane");
PostRenderFrameTask(gfx::SwapResult::SWAP_ACK);
return true;
}
-// OverlayChecker demonstrates how to use the
-// OverlayCandidatesOzone::CheckOverlaySupport to determine if a given overlay
-// can be successfully displayed.
-void SurfacelessGlRenderer::OverlayChecker(int z_order,
- gfx::Rect bounds_rect,
- gfx::RectF crop_rect) {
- // The overlay checking interface is designed to satisfy the needs of CC which
- // will be producing RectF target rectangles. But we use the bounds produced
- // in RenderFrame for GLSurface::ScheduleOverlayPlane.
- gfx::RectF display_rect(bounds_rect.x(), bounds_rect.y(), bounds_rect.width(),
- bounds_rect.height());
-
- OverlaySurfaceCandidate overlay_candidate;
-
- // The bounds rectangle of the candidate overlay buffer.
- overlay_candidate.buffer_size = bounds_rect.size();
- // The same rectangle in floating point coordinates.
- overlay_candidate.display_rect = display_rect;
-
- // Show the entire buffer by setting the crop to a unity square.
- overlay_candidate.crop_rect = gfx::RectF(0, 0, 1, 1);
-
- // The clip region is the entire screen.
- overlay_candidate.clip_rect = gfx::Rect(size_);
-
- // The demo overlay instance is always ontop and not clipped. Clipped quads
- // cannot be placed in overlays.
- overlay_candidate.is_clipped = false;
-
- OverlayCandidatesOzone::OverlaySurfaceCandidateList list;
- list.push_back(overlay_candidate);
-
- // Ask ozone platform to determine if this rect can be placed in an overlay.
- // Ozone will update the list and return it.
- overlay_checker_->CheckOverlaySupport(&list);
-
- // Note what the checker decided.
- // say more about it.
- TRACE_EVENT2("hwoverlays", "SurfacelessGlRenderer::OverlayChecker", "canihaz",
- list[0].overlay_handled, "display_rect",
- list[0].display_rect.ToString());
-}
-
void SurfacelessGlRenderer::RenderFrame() {
TRACE_EVENT0("ozone", "SurfacelessGlRenderer::RenderFrame");
float fraction = NextFraction();
+ gfx::Rect overlay_rect;
+
+ OverlayCandidatesOzone::OverlaySurfaceCandidateList overlay_list;
+ if (!disable_primary_plane_) {
+ overlay_list.push_back(
+ MakeOverlayCandidate(1, gfx::Rect(size_), gfx::RectF(0, 0, 1, 1)));
+ // We know at least the primary plane can be scanned out.
+ overlay_list.back().overlay_handled = true;
+ }
+ if (overlay_buffer_[0]) {
+ overlay_rect = gfx::Rect(overlay_buffer_[0]->size());
+
+ float steps_num = 5.0f;
+ float stepped_fraction =
+ std::floor((fraction + 0.5f / steps_num) * steps_num) / steps_num;
+ gfx::Vector2d offset(
+ stepped_fraction * (size_.width() - overlay_rect.width()),
+ (size_.height() - overlay_rect.height()) / 2);
+ overlay_rect += offset;
+ overlay_list.push_back(
+ MakeOverlayCandidate(1, overlay_rect, gfx::RectF(0, 0, 1, 1)));
+ }
+
+ // The actual validation for a specific overlay configuration is done
+ // asynchronously and then cached inside overlay_checker_ once a reply
+ // is sent back.
+ // This means that the first few frames we call this method for a specific
+ // overlay_list, all the overlays but the primary plane, that we explicitly
+ // marked as handled, will be rejected even if they might be handled at a
+ // later time.
+ overlay_checker_->CheckOverlaySupport(&overlay_list);
+
context_->MakeCurrent(surface_.get());
buffers_[back_buffer_]->BindFramebuffer();
@@ -174,23 +196,17 @@ void SurfacelessGlRenderer::RenderFrame() {
glClearColor(1 - fraction, 0.0, fraction, 1.0);
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
- surface_->ScheduleOverlayPlane(0, gfx::OVERLAY_TRANSFORM_NONE,
- buffers_[back_buffer_]->image(),
- gfx::Rect(size_), gfx::RectF(0, 0, 1, 1));
-
- if (overlay_buffer_) {
- gfx::Rect overlay_rect(overlay_buffer_->size());
- gfx::Vector2d offset(fraction * (size_.width() - overlay_rect.width()),
- (size_.height() - overlay_rect.height()) / 2);
- overlay_rect += offset;
-
- // TODO(rjkroege): Overlay checking should gate the following and will
- // be added after solving http://crbug.com/735640
- OverlayChecker(1, overlay_rect, gfx::RectF(0, 0, 1, 1));
+ if (!disable_primary_plane_) {
+ CHECK(overlay_list.front().overlay_handled);
+ surface_->ScheduleOverlayPlane(0, gfx::OVERLAY_TRANSFORM_NONE,
+ buffers_[back_buffer_]->image(),
+ gfx::Rect(size_), gfx::RectF(0, 0, 1, 1));
+ }
+ if (overlay_buffer_[0] && overlay_list.back().overlay_handled) {
surface_->ScheduleOverlayPlane(1, gfx::OVERLAY_TRANSFORM_NONE,
- overlay_buffer_->image(), overlay_rect,
- gfx::RectF(0, 0, 1, 1));
+ overlay_buffer_[back_buffer_]->image(),
+ overlay_rect, gfx::RectF(0, 0, 1, 1));
}
back_buffer_ ^= 1;
diff --git a/chromium/ui/ozone/demo/surfaceless_gl_renderer.h b/chromium/ui/ozone/demo/surfaceless_gl_renderer.h
index 5467435c7f3..20e75cdee5b 100644
--- a/chromium/ui/ozone/demo/surfaceless_gl_renderer.h
+++ b/chromium/ui/ozone/demo/surfaceless_gl_renderer.h
@@ -32,7 +32,6 @@ class SurfacelessGlRenderer : public GlRenderer {
// GlRenderer:
void RenderFrame() override;
void PostRenderFrameTask(gfx::SwapResult result) override;
- void OverlayChecker(int z_order, gfx::Rect bounds_rect, gfx::RectF crop_rect);
class BufferWrapper {
public:
@@ -57,7 +56,8 @@ class SurfacelessGlRenderer : public GlRenderer {
std::unique_ptr<BufferWrapper> buffers_[2];
- std::unique_ptr<BufferWrapper> overlay_buffer_;
+ std::unique_ptr<BufferWrapper> overlay_buffer_[2];
+ bool disable_primary_plane_ = false;
std::unique_ptr<OverlayCandidatesOzone> overlay_checker_;
diff --git a/chromium/ui/ozone/gl/gl_image_ozone_native_pixmap_unittest.cc b/chromium/ui/ozone/gl/gl_image_ozone_native_pixmap_unittest.cc
index 525ba66bb94..3b3eb346de5 100644
--- a/chromium/ui/ozone/gl/gl_image_ozone_native_pixmap_unittest.cc
+++ b/chromium/ui/ozone/gl/gl_image_ozone_native_pixmap_unittest.cc
@@ -40,7 +40,8 @@ class GLImageNativePixmapTestDelegate {
surface_factory->CreateNativePixmap(gfx::kNullAcceleratedWidget, size,
format, usage);
DCHECK(pixmap);
- if (usage == gfx::BufferUsage::GPU_READ_CPU_READ_WRITE) {
+ if (usage == gfx::BufferUsage::GPU_READ_CPU_READ_WRITE ||
+ usage == gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE) {
auto client_pixmap = client_pixmap_factory_->ImportFromHandle(
pixmap->ExportHandle(), size, usage);
bool mapped = client_pixmap->Map();
@@ -67,7 +68,8 @@ class GLImageNativePixmapTestDelegate {
const uint8_t* GetImageColor() {
if (format == gfx::BufferFormat::R_8) {
return kRed;
- } else if (format == gfx::BufferFormat::YVU_420) {
+ } else if (format == gfx::BufferFormat::YVU_420 ||
+ format == gfx::BufferFormat::YUV_420_BIPLANAR) {
return kYvuColor;
}
return kGreen;
@@ -87,7 +89,9 @@ INSTANTIATE_TYPED_TEST_CASE_P(GLImageNativePixmapScanout,
using GLImageReadWriteType = testing::Types<
GLImageNativePixmapTestDelegate<gfx::BufferUsage::GPU_READ_CPU_READ_WRITE,
- gfx::BufferFormat::R_8>>;
+ gfx::BufferFormat::R_8>,
+ GLImageNativePixmapTestDelegate<gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE,
+ gfx::BufferFormat::YUV_420_BIPLANAR>>;
using GLImageBindTestTypes = testing::Types<
GLImageNativePixmapTestDelegate<gfx::BufferUsage::GPU_READ_CPU_READ_WRITE,
@@ -97,6 +101,8 @@ using GLImageBindTestTypes = testing::Types<
GLImageNativePixmapTestDelegate<gfx::BufferUsage::GPU_READ_CPU_READ_WRITE,
gfx::BufferFormat::YVU_420>,
GLImageNativePixmapTestDelegate<gfx::BufferUsage::GPU_READ_CPU_READ_WRITE,
+ gfx::BufferFormat::YUV_420_BIPLANAR>,
+ GLImageNativePixmapTestDelegate<gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE,
gfx::BufferFormat::YUV_420_BIPLANAR>>;
// These tests are disabled since the trybots are running with Ozone X11
diff --git a/chromium/ui/ozone/platform/cast/DEPS b/chromium/ui/ozone/platform/cast/DEPS
index a967e61a1a2..ffc9eafa338 100644
--- a/chromium/ui/ozone/platform/cast/DEPS
+++ b/chromium/ui/ozone/platform/cast/DEPS
@@ -1,4 +1,5 @@
include_rules = [
+ "+chromecast/base/cast_features.h",
"+chromecast/base/chromecast_switches.h",
"+chromecast/chromecast_features.h",
"+chromecast/public"
diff --git a/chromium/ui/ozone/platform/cast/gl_surface_cast.cc b/chromium/ui/ozone/platform/cast/gl_surface_cast.cc
index 04d7d64c2d1..28822a35841 100644
--- a/chromium/ui/ozone/platform/cast/gl_surface_cast.cc
+++ b/chromium/ui/ozone/platform/cast/gl_surface_cast.cc
@@ -4,16 +4,25 @@
#include "ui/ozone/platform/cast/gl_surface_cast.h"
+#include "base/feature_list.h"
#include "base/memory/ptr_util.h"
+#include "chromecast/base/cast_features.h"
#include "ui/gfx/vsync_provider.h"
#include "ui/ozone/common/egl_util.h"
#include "ui/ozone/platform/cast/gl_ozone_egl_cast.h"
namespace {
-// Target fixed 30fps.
+// Target fixed 30fps, or 60fps if doing triple-buffer 720p.
// TODO(halliwell): We might need to customize this value on various devices
// or make it dynamic that throttles framerate if device is overheating.
-const base::TimeDelta kVSyncInterval = base::TimeDelta::FromSeconds(2) / 59.9;
+base::TimeDelta GetVSyncInterval() {
+ if (base::FeatureList::IsEnabled(chromecast::kTripleBuffer720)) {
+ return base::TimeDelta::FromSeconds(1) / 59.9;
+ } else {
+ return base::TimeDelta::FromSeconds(2) / 59.9;
+ }
+}
+
} // namespace
namespace ui {
@@ -23,7 +32,7 @@ GLSurfaceCast::GLSurfaceCast(gfx::AcceleratedWidget widget,
: NativeViewGLSurfaceEGL(
parent->GetNativeWindow(),
base::MakeUnique<gfx::FixedVSyncProvider>(base::TimeTicks(),
- kVSyncInterval)),
+ GetVSyncInterval())),
widget_(widget),
parent_(parent),
supports_swap_buffer_with_bounds_(
@@ -66,9 +75,11 @@ gfx::SwapResult GLSurfaceCast::SwapBuffersWithBounds(
bool GLSurfaceCast::Resize(const gfx::Size& size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha) {
return parent_->ResizeDisplay(size) &&
- NativeViewGLSurfaceEGL::Resize(size, scale_factor, has_alpha);
+ NativeViewGLSurfaceEGL::Resize(size, scale_factor, color_space,
+ has_alpha);
}
bool GLSurfaceCast::ScheduleOverlayPlane(int z_order,
diff --git a/chromium/ui/ozone/platform/cast/gl_surface_cast.h b/chromium/ui/ozone/platform/cast/gl_surface_cast.h
index 2fb3fe98fcb..e93119af556 100644
--- a/chromium/ui/ozone/platform/cast/gl_surface_cast.h
+++ b/chromium/ui/ozone/platform/cast/gl_surface_cast.h
@@ -28,6 +28,7 @@ class GLSurfaceCast : public gl::NativeViewGLSurfaceEGL {
const std::vector<gfx::Rect>& rects) override;
bool Resize(const gfx::Size& size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha) override;
bool ScheduleOverlayPlane(int z_order,
gfx::OverlayTransform transform,
diff --git a/chromium/ui/ozone/platform/cast/surface_factory_cast.cc b/chromium/ui/ozone/platform/cast/surface_factory_cast.cc
index 6cc1392991a..522a837c062 100644
--- a/chromium/ui/ozone/platform/cast/surface_factory_cast.cc
+++ b/chromium/ui/ozone/platform/cast/surface_factory_cast.cc
@@ -29,8 +29,8 @@ class DummySurface : public SurfaceOzoneCanvas {
sk_sp<SkSurface> GetSurface() override { return surface_; }
void ResizeCanvas(const gfx::Size& viewport_size) override {
- surface_ = SkSurface::MakeRaster(SkImageInfo::MakeN32Premul(
- viewport_size.width(), viewport_size.height()));
+ surface_ =
+ SkSurface::MakeNull(viewport_size.width(), viewport_size.height());
}
void PresentCanvas(const gfx::Rect& damage) override {}
diff --git a/chromium/ui/ozone/platform/drm/BUILD.gn b/chromium/ui/ozone/platform/drm/BUILD.gn
index 05f649dac31..732e2d52f39 100644
--- a/chromium/ui/ozone/platform/drm/BUILD.gn
+++ b/chromium/ui/ozone/platform/drm/BUILD.gn
@@ -16,8 +16,6 @@ source_set("gbm") {
"common/drm_util.h",
"common/scoped_drm_types.cc",
"common/scoped_drm_types.h",
- "cursor_proxy_mojo.cc",
- "cursor_proxy_mojo.h",
"gpu/crtc_controller.cc",
"gpu/crtc_controller.h",
"gpu/drm_buffer.cc",
@@ -103,8 +101,10 @@ source_set("gbm") {
"host/drm_window_host_manager.h",
"host/gpu_thread_adapter.h",
"host/gpu_thread_observer.h",
- "mus_thread_proxy.cc",
- "mus_thread_proxy.h",
+ "host/host_cursor_proxy.cc",
+ "host/host_cursor_proxy.h",
+ "host/host_drm_device.cc",
+ "host/host_drm_device.h",
"ozone_platform_gbm.cc",
"ozone_platform_gbm.h",
]
diff --git a/chromium/ui/ozone/platform/drm/OWNERS b/chromium/ui/ozone/platform/drm/OWNERS
index 0d77c0eae94..363a93a5f95 100644
--- a/chromium/ui/ozone/platform/drm/OWNERS
+++ b/chromium/ui/ozone/platform/drm/OWNERS
@@ -1 +1,2 @@
+dcastagna@chromium.org
dnicoara@chromium.org
diff --git a/chromium/ui/ozone/platform/drm/common/display_types.h b/chromium/ui/ozone/platform/drm/common/display_types.h
index 5d0b1acf653..da8b5c07533 100644
--- a/chromium/ui/ozone/platform/drm/common/display_types.h
+++ b/chromium/ui/ozone/platform/drm/common/display_types.h
@@ -6,13 +6,13 @@
#define UI_OZONE_PLATFORM_DRM_COMMON_DISPLAY_TYPES_H_
namespace display {
-class DisplaySnapshotMojo;
+class DisplaySnapshot;
} // namespace display
namespace ui {
using MovableDisplaySnapshots =
- std::vector<std::unique_ptr<display::DisplaySnapshotMojo>>;
+ std::vector<std::unique_ptr<display::DisplaySnapshot>>;
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/common/drm_util.cc b/chromium/ui/ozone/platform/drm/common/drm_util.cc
index 97130378d93..b452b33122b 100644
--- a/chromium/ui/ozone/platform/drm/common/drm_util.cc
+++ b/chromium/ui/ozone/platform/drm/common/drm_util.cc
@@ -16,9 +16,8 @@
#include "base/containers/flat_map.h"
#include "base/memory/ptr_util.h"
#include "ui/display/types/display_mode.h"
-#include "ui/display/types/display_snapshot_mojo.h"
+#include "ui/display/types/display_snapshot.h"
#include "ui/display/util/edid_parser.h"
-#include "ui/ozone/common/display_snapshot_proxy.h"
#if !defined(DRM_FORMAT_R16)
// TODO(riju): crbug.com/733703
@@ -204,6 +203,12 @@ bool HasColorCorrectionMatrix(int fd, drmModeCrtc* crtc) {
return false;
}
+bool DisplayModeEquals(const DisplayMode_Params& lhs,
+ const DisplayMode_Params& rhs) {
+ return lhs.size == rhs.size && lhs.is_interlaced == rhs.is_interlaced &&
+ lhs.refresh_rate == rhs.refresh_rate;
+}
+
} // namespace
DisplayMode_Params GetDisplayModeParams(const display::DisplayMode& mode) {
@@ -427,7 +432,6 @@ std::vector<DisplaySnapshot_Params> CreateParamsFromSnapshot(
}
p.product_id = d->product_id();
- p.string_representation = d->ToString();
p.maximum_cursor_size = d->maximum_cursor_size();
params.push_back(p);
@@ -435,6 +439,29 @@ std::vector<DisplaySnapshot_Params> CreateParamsFromSnapshot(
return params;
}
+std::unique_ptr<display::DisplaySnapshot> CreateDisplaySnapshotFromParams(
+ const DisplaySnapshot_Params& params) {
+ display::DisplaySnapshot::DisplayModeList modes;
+ const display::DisplayMode* current_mode = nullptr;
+ const display::DisplayMode* native_mode = nullptr;
+
+ // Find pointers to current and native mode in the copied data.
+ for (auto& mode : params.modes) {
+ modes.push_back(CreateDisplayModeFromParams(mode));
+ if (params.has_current_mode && DisplayModeEquals(mode, params.current_mode))
+ current_mode = modes.back().get();
+ if (params.has_native_mode && DisplayModeEquals(mode, params.native_mode))
+ native_mode = modes.back().get();
+ }
+
+ return std::make_unique<display::DisplaySnapshot>(
+ params.display_id, params.origin, params.physical_size, params.type,
+ params.is_aspect_preserving_scaling, params.has_overscan,
+ params.has_color_correction_matrix, params.display_name, params.sys_path,
+ std::move(modes), params.edid, current_mode, native_mode,
+ params.product_id, params.maximum_cursor_size);
+}
+
int GetFourCCFormatFromBufferFormat(gfx::BufferFormat format) {
switch (format) {
case gfx::BufferFormat::R_8:
@@ -522,8 +549,57 @@ MovableDisplaySnapshots CreateMovableDisplaySnapshotsFromParams(
const std::vector<DisplaySnapshot_Params>& displays) {
MovableDisplaySnapshots snapshots;
for (const auto& d : displays)
- snapshots.push_back(base::MakeUnique<DisplaySnapshotProxy>(d));
+ snapshots.push_back(CreateDisplaySnapshotFromParams(d));
return snapshots;
}
+OverlaySurfaceCandidateList CreateOverlaySurfaceCandidateListFrom(
+ const std::vector<OverlayCheck_Params>& params) {
+ OverlaySurfaceCandidateList candidates;
+ for (auto& p : params) {
+ OverlaySurfaceCandidate osc;
+ osc.transform = p.transform;
+ osc.buffer_size = p.buffer_size;
+ osc.format = p.format;
+ osc.display_rect = gfx::RectF(p.display_rect);
+ osc.crop_rect = p.crop_rect;
+ osc.plane_z_order = p.plane_z_order;
+ osc.overlay_handled = p.is_overlay_candidate;
+ candidates.push_back(osc);
+ }
+
+ return candidates;
+}
+
+std::vector<OverlayCheck_Params> CreateParamsFromOverlaySurfaceCandidate(
+ const OverlaySurfaceCandidateList& candidates) {
+ std::vector<OverlayCheck_Params> overlay_params;
+ for (auto& candidate : candidates) {
+ overlay_params.push_back(OverlayCheck_Params(candidate));
+ }
+
+ return overlay_params;
+}
+
+OverlayStatusList CreateOverlayStatusListFrom(
+ const std::vector<OverlayCheckReturn_Params>& params) {
+ OverlayStatusList returns;
+ for (auto& p : params) {
+ returns.push_back(p.status);
+ }
+
+ return returns;
+}
+
+std::vector<OverlayCheckReturn_Params> CreateParamsFromOverlayStatusList(
+ const OverlayStatusList& returns) {
+ std::vector<OverlayCheckReturn_Params> params;
+ for (auto& s : returns) {
+ OverlayCheckReturn_Params p;
+ p.status = s;
+ params.push_back(p);
+ }
+ return params;
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/common/drm_util.h b/chromium/ui/ozone/platform/drm/common/drm_util.h
index 9fdfb016244..593be0c7333 100644
--- a/chromium/ui/ozone/platform/drm/common/drm_util.h
+++ b/chromium/ui/ozone/platform/drm/common/drm_util.h
@@ -12,7 +12,6 @@
#include "base/files/file_path.h"
#include "base/macros.h"
-#include "ui/display/types/display_mode.h"
#include "ui/ozone/common/gpu/ozone_gpu_message_params.h"
#include "ui/ozone/platform/drm/common/display_types.h"
#include "ui/ozone/platform/drm/common/scoped_drm_types.h"
@@ -21,6 +20,7 @@ typedef struct _drmModeModeInfo drmModeModeInfo;
namespace display {
class DisplayMode;
+class DisplaySnapshot;
} // namespace display
namespace gfx {
@@ -72,6 +72,9 @@ DisplaySnapshot_Params CreateDisplaySnapshotParams(
std::vector<DisplaySnapshot_Params> CreateParamsFromSnapshot(
const MovableDisplaySnapshots& displays);
+std::unique_ptr<display::DisplaySnapshot> CreateDisplaySnapshotFromParams(
+ const DisplaySnapshot_Params& params);
+
int GetFourCCFormatFromBufferFormat(gfx::BufferFormat format);
gfx::BufferFormat GetBufferFormatFromFourCCFormat(int format);
@@ -96,6 +99,18 @@ bool ModeIsInterlaced(const drmModeModeInfo& mode);
MovableDisplaySnapshots CreateMovableDisplaySnapshotsFromParams(
const std::vector<DisplaySnapshot_Params>& displays);
+OverlaySurfaceCandidateList CreateOverlaySurfaceCandidateListFrom(
+ const std::vector<OverlayCheck_Params>& params);
+
+std::vector<OverlayCheck_Params> CreateParamsFromOverlaySurfaceCandidate(
+ const OverlaySurfaceCandidateList& candidates);
+
+OverlayStatusList CreateOverlayStatusListFrom(
+ const std::vector<OverlayCheckReturn_Params>& params);
+
+std::vector<OverlayCheckReturn_Params> CreateParamsFromOverlayStatusList(
+ const OverlayStatusList& returns);
+
} // namespace ui
#endif // UI_OZONE_PLATFORM_DRM_COMMON_DRM_UTIL_H_
diff --git a/chromium/ui/ozone/platform/drm/common/drm_util_unittest.cc b/chromium/ui/ozone/platform/drm/common/drm_util_unittest.cc
index f8a4f5e1a04..88835c29d4e 100644
--- a/chromium/ui/ozone/platform/drm/common/drm_util_unittest.cc
+++ b/chromium/ui/ozone/platform/drm/common/drm_util_unittest.cc
@@ -4,8 +4,10 @@
#include "ui/ozone/platform/drm/common/drm_util.h"
+#include <map>
+
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/display/types/display_snapshot_mojo.h"
+#include "ui/display/types/display_snapshot.h"
#include "ui/gfx/geometry/size.h"
#include "ui/ozone/common/gpu/ozone_gpu_message_params.h"
@@ -31,7 +33,6 @@ bool operator==(const ui::DisplaySnapshot_Params& a,
a.current_mode == b.current_mode &&
a.has_native_mode == b.has_native_mode &&
a.native_mode == b.native_mode && a.product_id == b.product_id &&
- a.string_representation == b.string_representation &&
a.maximum_cursor_size == b.maximum_cursor_size;
}
@@ -63,7 +64,6 @@ void DetailedCompare(const ui::DisplaySnapshot_Params& a,
EXPECT_EQ(a.has_native_mode, b.has_native_mode);
EXPECT_EQ(a.native_mode, b.native_mode);
EXPECT_EQ(a.product_id, b.product_id);
- EXPECT_EQ(a.string_representation, b.string_representation);
EXPECT_EQ(a.maximum_cursor_size, b.maximum_cursor_size);
}
@@ -104,7 +104,6 @@ TEST_F(DrmUtilTest, RoundTripDisplaySnapshot) {
fp.has_native_mode = true;
fp.native_mode = MakeDisplay(1.1);
fp.product_id = 7;
- fp.string_representation = "bending glass display";
fp.maximum_cursor_size = gfx::Size(103, 44);
sp.display_id = 1002;
@@ -123,7 +122,6 @@ TEST_F(DrmUtilTest, RoundTripDisplaySnapshot) {
sp.has_native_mode = true;
sp.native_mode = MakeDisplay(500.2);
sp.product_id = 8;
- sp.string_representation = "rigid glass display";
sp.maximum_cursor_size = gfx::Size(500, 44);
ep.display_id = 2002;
@@ -142,7 +140,6 @@ TEST_F(DrmUtilTest, RoundTripDisplaySnapshot) {
ep.current_mode = MakeDisplay(1000.2);
ep.has_native_mode = false;
ep.product_id = 9;
- ep.string_representation = "fluted glass display";
ep.maximum_cursor_size = gfx::Size(1000, 44);
orig_params.push_back(fp);
@@ -162,4 +159,46 @@ TEST_F(DrmUtilTest, RoundTripDisplaySnapshot) {
EXPECT_EQ(ep, roundtrip_params[2]);
}
+TEST_F(DrmUtilTest, OverlaySurfaceCandidate) {
+ OverlaySurfaceCandidateList input;
+
+ OverlaySurfaceCandidate input_osc;
+ input_osc.transform = gfx::OVERLAY_TRANSFORM_FLIP_VERTICAL;
+ input_osc.format = gfx::BufferFormat::YUV_420_BIPLANAR;
+ input_osc.buffer_size = gfx::Size(100, 50);
+ input_osc.display_rect = gfx::RectF(1., 2., 3., 4.);
+ input_osc.crop_rect = gfx::RectF(10., 20., 30., 40.);
+ input_osc.clip_rect = gfx::Rect(10, 20, 30, 40);
+ input_osc.is_clipped = true;
+ input_osc.plane_z_order = 42;
+ input_osc.overlay_handled = true;
+
+ input.push_back(input_osc);
+
+ // Roundtrip the conversions.
+ auto output = CreateOverlaySurfaceCandidateListFrom(
+ CreateParamsFromOverlaySurfaceCandidate(input));
+
+ EXPECT_EQ(input.size(), output.size());
+ OverlaySurfaceCandidate output_osc = output[0];
+
+ EXPECT_EQ(input_osc.transform, output_osc.transform);
+ EXPECT_EQ(input_osc.format, output_osc.format);
+ EXPECT_EQ(input_osc.buffer_size, output_osc.buffer_size);
+ EXPECT_EQ(input_osc.display_rect, output_osc.display_rect);
+ EXPECT_EQ(input_osc.crop_rect, output_osc.crop_rect);
+ EXPECT_EQ(input_osc.plane_z_order, output_osc.plane_z_order);
+ EXPECT_EQ(input_osc.overlay_handled, output_osc.overlay_handled);
+
+ EXPECT_FALSE(input < output);
+ EXPECT_FALSE(output < input);
+
+ std::map<OverlaySurfaceCandidateList, int> map;
+ map[input] = 42;
+ const auto& iter = map.find(output);
+
+ EXPECT_NE(map.end(), iter);
+ EXPECT_EQ(42, iter->second);
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/gpu/crtc_controller.cc b/chromium/ui/ozone/platform/drm/gpu/crtc_controller.cc
index 68d504aaecd..ae4f9b02266 100644
--- a/chromium/ui/ozone/platform/drm/gpu/crtc_controller.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/crtc_controller.cc
@@ -81,20 +81,19 @@ bool CrtcController::SchedulePageFlip(
DCHECK(!page_flip_request_.get() || test_only);
DCHECK(!is_disabled_);
const OverlayPlane* primary = OverlayPlane::GetPrimaryPlane(overlays);
- if (!primary) {
- LOG(ERROR) << "No primary plane to display on crtc " << crtc_;
- page_flip_request->Signal(gfx::SwapResult::SWAP_ACK);
- return true;
- }
- DCHECK(primary->buffer.get());
-
- if (primary->buffer->GetSize() != gfx::Size(mode_.hdisplay, mode_.vdisplay)) {
- VLOG(2) << "Trying to pageflip a buffer with the wrong size. Expected "
- << mode_.hdisplay << "x" << mode_.vdisplay << " got "
- << primary->buffer->GetSize().ToString() << " for"
- << " crtc=" << crtc_ << " connector=" << connector_;
- page_flip_request->Signal(gfx::SwapResult::SWAP_ACK);
- return true;
+ if (primary) {
+ DCHECK(primary->buffer.get());
+ // TODO(dcastagna): Get rid of this. Scaling on the primary plane is
+ // supported on all the devices.
+ if (primary->buffer->GetSize() !=
+ gfx::Size(mode_.hdisplay, mode_.vdisplay)) {
+ VLOG(2) << "Trying to pageflip a buffer with the wrong size. Expected "
+ << mode_.hdisplay << "x" << mode_.vdisplay << " got "
+ << primary->buffer->GetSize().ToString() << " for"
+ << " crtc=" << crtc_ << " connector=" << connector_;
+ page_flip_request->Signal(gfx::SwapResult::SWAP_ACK);
+ return true;
+ }
}
if (!drm_->plane_manager()->AssignOverlayPlanes(plane_list, overlays, crtc_,
@@ -125,12 +124,8 @@ std::vector<uint64_t> CrtcController::GetFormatModifiers(uint32_t format) {
}
void CrtcController::OnPageFlipEvent(unsigned int frame,
- unsigned int seconds,
- unsigned int useconds) {
- time_of_last_flip_ =
- static_cast<uint64_t>(seconds) * base::Time::kMicrosecondsPerSecond +
- useconds;
-
+ base::TimeTicks timestamp) {
+ time_of_last_flip_ = timestamp;
SignalPageFlipRequest(gfx::SwapResult::SWAP_ACK);
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/crtc_controller.h b/chromium/ui/ozone/platform/drm/gpu/crtc_controller.h
index 1bdae0385b0..5222b63ee36 100644
--- a/chromium/ui/ozone/platform/drm/gpu/crtc_controller.h
+++ b/chromium/ui/ozone/platform/drm/gpu/crtc_controller.h
@@ -12,6 +12,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
+#include "base/time/time.h"
#include "ui/gfx/swap_result.h"
#include "ui/ozone/platform/drm/common/scoped_drm_types.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h"
@@ -39,7 +40,7 @@ class CrtcController : public base::SupportsWeakPtr<CrtcController> {
uint32_t connector() const { return connector_; }
const scoped_refptr<DrmDevice>& drm() const { return drm_; }
bool is_disabled() const { return is_disabled_; }
- uint64_t time_of_last_flip() const { return time_of_last_flip_; }
+ base::TimeTicks time_of_last_flip() const { return time_of_last_flip_; }
// Perform the initial modesetting operation using |plane| as the buffer for
// the primary plane. The CRTC configuration is specified by |mode|.
@@ -76,12 +77,7 @@ class CrtcController : public base::SupportsWeakPtr<CrtcController> {
// Called when the page flip event occurred. The event is provided by the
// kernel when a VBlank event finished. This allows the controller to
// update internal state and propagate the update to the surface.
- // The tuple (seconds, useconds) represents the event timestamp. |seconds|
- // represents the number of seconds while |useconds| represents the
- // microseconds (< 1 second) in the timestamp.
- void OnPageFlipEvent(unsigned int frame,
- unsigned int seconds,
- unsigned int useconds);
+ void OnPageFlipEvent(unsigned int frame, base::TimeTicks timestamp);
bool SetCursor(const scoped_refptr<ScanoutBuffer>& buffer);
bool MoveCursor(const gfx::Point& location);
@@ -110,7 +106,7 @@ class CrtcController : public base::SupportsWeakPtr<CrtcController> {
bool is_disabled_ = true;
// The time of the last page flip event as reported by the kernel callback.
- uint64_t time_of_last_flip_ = 0;
+ base::TimeTicks time_of_last_flip_;
DISALLOW_COPY_AND_ASSIGN(CrtcController);
};
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_device.cc b/chromium/ui/ozone/platform/drm/gpu/drm_device.cc
index ed132f15e55..315b1c0879e 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_device.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_device.cc
@@ -30,10 +30,9 @@ namespace ui {
namespace {
-typedef base::Callback<void(uint32_t /* frame */,
- uint32_t /* seconds */,
- uint32_t /* useconds */,
- uint64_t /* id */)> DrmEventHandler;
+using DrmEventHandler = base::Callback<void(uint32_t /* frame */,
+ base::TimeTicks /* timestamp */,
+ uint64_t /* id */)>;
bool DrmCreateDumbBuffer(int fd,
const SkImageInfo& info,
@@ -97,8 +96,17 @@ bool ProcessDrmEvent(int fd, const DrmEventHandler& callback) {
TRACE_EVENT_INSTANT1("benchmark,drm", "DrmEventFlipComplete",
TRACE_EVENT_SCOPE_THREAD, "data",
std::move(drm_data));
- callback.Run(vblank.sequence, vblank.tv_sec, vblank.tv_usec,
- vblank.user_data);
+ // Warning: It is generally unsafe to manufacture TimeTicks values; but
+ // here it is required for interfacing with libdrm. Assumption: libdrm
+ // is providing the timestamp from the CLOCK_MONOTONIC POSIX clock.
+ DCHECK_EQ(base::TimeTicks::GetClock(),
+ base::TimeTicks::Clock::LINUX_CLOCK_MONOTONIC);
+ const base::TimeTicks timestamp =
+ base::TimeTicks() + base::TimeDelta::FromMicroseconds(
+ static_cast<int64_t>(vblank.tv_sec) *
+ base::Time::kMicrosecondsPerSecond +
+ vblank.tv_usec);
+ callback.Run(vblank.sequence, timestamp, vblank.user_data);
} break;
case DRM_EVENT_VBLANK:
break;
@@ -298,10 +306,7 @@ class DrmDevice::PageFlipManager {
PageFlipManager() : next_id_(0) {}
~PageFlipManager() {}
- void OnPageFlip(uint32_t frame,
- uint32_t seconds,
- uint32_t useconds,
- uint64_t id) {
+ void OnPageFlip(uint32_t frame, base::TimeTicks timestamp, uint64_t id) {
auto it =
std::find_if(callbacks_.begin(), callbacks_.end(), FindCallback(id));
if (it == callbacks_.end()) {
@@ -315,7 +320,7 @@ class DrmDevice::PageFlipManager {
return;
callbacks_.erase(it);
- callback.Run(frame, seconds, useconds);
+ callback.Run(frame, timestamp);
}
uint64_t GetNextId() { return next_id_++; }
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_device.h b/chromium/ui/ozone/platform/drm/gpu/drm_device.h
index 132b5dc5ec2..4e197848279 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_device.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_device.h
@@ -15,6 +15,7 @@
#include "base/files/file_path.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
+#include "base/time/time.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
#include "ui/gfx/overlay_transform.h"
@@ -39,9 +40,9 @@ class HardwareDisplayPlaneManager;
// would be called. In unit tests this interface would be stubbed.
class DrmDevice : public base::RefCountedThreadSafe<DrmDevice> {
public:
- typedef base::Callback<void(unsigned int /* frame */,
- unsigned int /* seconds */,
- unsigned int /* useconds */)> PageFlipCallback;
+ using PageFlipCallback =
+ base::Callback<void(unsigned int /* frame */,
+ base::TimeTicks /* timestamp */)>;
DrmDevice(const base::FilePath& device_path,
base::File file,
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 6b8142bc7df..da86d3bde63 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_device_manager.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_device_manager.cc
@@ -38,8 +38,7 @@ DrmDeviceManager::~DrmDeviceManager() {
}
bool DrmDeviceManager::AddDrmDevice(const base::FilePath& path,
- const base::FileDescriptor& fd) {
- base::File file(fd.fd);
+ base::File file) {
auto it =
std::find_if(devices_.begin(), devices_.end(), FindByDevicePath(path));
if (it != devices_.end()) {
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 52f59ad845b..a1241b7d92d 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_device_manager.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_device_manager.h
@@ -9,13 +9,13 @@
#include <memory>
#include <vector>
+#include "base/files/file.h"
#include "base/macros.h"
#include "base/memory/ref_counted.h"
#include "ui/gfx/native_widget_types.h"
namespace base {
class FilePath;
-struct FileDescriptor;
}
namespace ui {
@@ -33,7 +33,7 @@ class DrmDeviceManager {
~DrmDeviceManager();
// The first device registered is assumed to be the primary device.
- bool AddDrmDevice(const base::FilePath& path, const base::FileDescriptor& fd);
+ bool AddDrmDevice(const base::FilePath& path, base::File file);
void RemoveDrmDevice(const base::FilePath& path);
// Updates the device associated with |widget|.
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc b/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc
index eb333ee7d06..f8d5daa2aeb 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_thread.cc
@@ -14,8 +14,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "ui/display/types/display_mode.h"
-#include "ui/display/types/display_snapshot_mojo.h"
-#include "ui/ozone/common/display_snapshot_proxy.h"
+#include "ui/display/types/display_snapshot.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"
@@ -77,7 +76,7 @@ class GbmDeviceGenerator : public DrmDeviceGenerator {
} // namespace
-DrmThread::DrmThread() : base::Thread("DrmThread") {}
+DrmThread::DrmThread() : base::Thread("DrmThread"), binding_(this) {}
DrmThread::~DrmThread() {
Stop();
@@ -117,16 +116,24 @@ void DrmThread::CreateBuffer(gfx::AcceleratedWidget widget,
uint32_t flags = 0;
switch (usage) {
case gfx::BufferUsage::GPU_READ:
+ flags = GBM_BO_USE_TEXTURING;
break;
case gfx::BufferUsage::SCANOUT:
- flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING;
+ flags = GBM_BO_USE_RENDERING | GBM_BO_USE_SCANOUT | GBM_BO_USE_TEXTURING;
+ break;
+ case gfx::BufferUsage::SCANOUT_CAMERA_READ_WRITE:
+ flags = GBM_BO_USE_LINEAR | GBM_BO_USE_CAMERA_WRITE | GBM_BO_USE_SCANOUT |
+ GBM_BO_USE_TEXTURING;
break;
case gfx::BufferUsage::SCANOUT_CPU_READ_WRITE:
- flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_LINEAR;
+ flags = GBM_BO_USE_LINEAR | GBM_BO_USE_SCANOUT | GBM_BO_USE_TEXTURING;
+ break;
+ case gfx::BufferUsage::SCANOUT_VDA_WRITE:
+ flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_TEXTURING;
break;
case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE:
case gfx::BufferUsage::GPU_READ_CPU_READ_WRITE_PERSISTENT:
- flags = GBM_BO_USE_LINEAR;
+ flags = GBM_BO_USE_LINEAR | GBM_BO_USE_TEXTURING;
break;
}
@@ -140,11 +147,21 @@ void DrmThread::CreateBuffer(gfx::AcceleratedWidget widget,
if (window && window->GetController())
modifiers = window->GetController()->GetFormatModifiers(fourcc_format);
- if (modifiers.size() > 0 && !(flags & GBM_BO_USE_LINEAR))
- *buffer = GbmBuffer::CreateBufferWithModifiers(gbm, fourcc_format, size,
- flags, modifiers);
- else
- *buffer = GbmBuffer::CreateBuffer(gbm, fourcc_format, size, flags);
+ // NOTE: BufferUsage::SCANOUT is used to create buffers that will be
+ // explicitly set via kms on a CRTC (e.g: BufferQueue buffers), therefore
+ // allocation should fail if it's not possible to allocate a BO_USE_SCANOUT
+ // buffer in that case.
+ bool retry_without_scanout = usage != gfx::BufferUsage::SCANOUT;
+ do {
+ if (modifiers.size() > 0 && !(flags & GBM_BO_USE_LINEAR))
+ *buffer = GbmBuffer::CreateBufferWithModifiers(gbm, fourcc_format, size,
+ flags, modifiers);
+ else
+ *buffer = GbmBuffer::CreateBuffer(gbm, fourcc_format, size, flags);
+ retry_without_scanout =
+ retry_without_scanout && !*buffer && (flags & GBM_BO_USE_SCANOUT);
+ flags &= ~GBM_BO_USE_SCANOUT;
+ } while (retry_without_scanout);
}
void DrmThread::CreateBufferFromFds(
@@ -189,19 +206,19 @@ void DrmThread::GetVSyncParameters(
window->GetVSyncParameters(callback);
}
-void DrmThread::CreateWindow(gfx::AcceleratedWidget widget) {
+void DrmThread::CreateWindow(const gfx::AcceleratedWidget& widget) {
std::unique_ptr<DrmWindow> window(
new DrmWindow(widget, device_manager_.get(), screen_manager_.get()));
window->Initialize(buffer_generator_.get());
screen_manager_->AddWindow(widget, std::move(window));
}
-void DrmThread::DestroyWindow(gfx::AcceleratedWidget widget) {
+void DrmThread::DestroyWindow(const gfx::AcceleratedWidget& widget) {
std::unique_ptr<DrmWindow> window = screen_manager_->RemoveWindow(widget);
window->Shutdown();
}
-void DrmThread::SetWindowBounds(gfx::AcceleratedWidget widget,
+void DrmThread::SetWindowBounds(const gfx::AcceleratedWidget& widget,
const gfx::Rect& bounds) {
screen_manager_->GetWindow(widget)->SetBounds(bounds);
}
@@ -220,17 +237,18 @@ void DrmThread::MoveCursor(const gfx::AcceleratedWidget& widget,
}
void DrmThread::CheckOverlayCapabilities(
- gfx::AcceleratedWidget widget,
- const std::vector<OverlayCheck_Params>& overlays,
- base::OnceCallback<void(gfx::AcceleratedWidget,
- const std::vector<OverlayCheck_Params>&,
- const std::vector<OverlayCheckReturn_Params>&)>
- callback) {
+ const gfx::AcceleratedWidget& widget,
+ const OverlaySurfaceCandidateList& overlays,
+ base::OnceCallback<void(const gfx::AcceleratedWidget&,
+ const OverlaySurfaceCandidateList&,
+ const OverlayStatusList&)> callback) {
TRACE_EVENT0("drm,hwoverlays", "DrmThread::CheckOverlayCapabilities");
+ auto params = CreateParamsFromOverlaySurfaceCandidate(overlays);
std::move(callback).Run(
widget, overlays,
- screen_manager_->GetWindow(widget)->TestPageFlip(overlays));
+ CreateOverlayStatusListFrom(
+ screen_manager_->GetWindow(widget)->TestPageFlip(params)));
}
void DrmThread::RefreshNativeDisplays(
@@ -265,9 +283,8 @@ void DrmThread::RelinquishDisplayControl(
std::move(callback).Run(true);
}
-void DrmThread::AddGraphicsDevice(const base::FilePath& path,
- const base::FileDescriptor& fd) {
- device_manager_->AddDrmDevice(path, fd);
+void DrmThread::AddGraphicsDevice(const base::FilePath& path, base::File file) {
+ device_manager_->AddDrmDevice(path, std::move(file));
}
void DrmThread::RemoveGraphicsDevice(const base::FilePath& path) {
@@ -298,10 +315,24 @@ void DrmThread::SetColorCorrection(
correction_matrix);
}
+void DrmThread::StartDrmDevice(StartDrmDeviceCallback callback) {
+ // We currently assume that |Init| always succeeds so return true to indicate
+ // when the DRM thread has completed launching. In particular, the invocation
+ // of the callback in the client triggers the invocation of DRM thread
+ // readiness observers.
+ std::move(callback).Run(true);
+}
+
// DrmThread requires a BindingSet instead of a simple Binding because it will
// be used from multiple threads in multiple processes.
-void DrmThread::AddBinding(ozone::mojom::DeviceCursorRequest request) {
+void DrmThread::AddBindingCursorDevice(
+ ozone::mojom::DeviceCursorRequest request) {
bindings_.AddBinding(this, std::move(request));
}
+void DrmThread::AddBindingDrmDevice(ozone::mojom::DrmDeviceRequest request) {
+ TRACE_EVENT0("drm", "DrmThread::AddBindingDrmDevice");
+ binding_.Bind(std::move(request));
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_thread.h b/chromium/ui/ozone/platform/drm/gpu/drm_thread.h
index 8fdecc94db7..973409b073d 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_thread.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_thread.h
@@ -9,6 +9,7 @@
#include <memory>
+#include "base/files/file.h"
#include "base/files/scoped_file.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
@@ -20,10 +21,11 @@
#include "ui/ozone/common/gpu/ozone_gpu_message_params.h"
#include "ui/ozone/platform/drm/common/display_types.h"
#include "ui/ozone/public/interfaces/device_cursor.mojom.h"
+#include "ui/ozone/public/interfaces/drm_device.mojom.h"
#include "ui/ozone/public/swap_completion_callback.h"
namespace base {
-struct FileDescriptor;
+class FilePath;
}
namespace display {
@@ -53,14 +55,17 @@ struct OverlayPlane;
// (for example jank in the cursor if the GPU main thread is performing heavy
// operations). The inverse is also true as blocking operations on the DRM
// thread (such as modesetting) no longer block the GPU main thread.
-class DrmThread : public base::Thread, public ozone::mojom::DeviceCursor {
+class DrmThread : public base::Thread,
+ public ozone::mojom::DeviceCursor,
+ public ozone::mojom::DrmDevice {
public:
DrmThread();
~DrmThread() override;
void Start();
- // Must be called on the DRM thread.
+ // Must be called on the DRM thread. All methods for use from the GPU thread.
+ // DrmThreadProxy (on GPU)thread) is the client for these methods.
void CreateBuffer(gfx::AcceleratedWidget widget,
const gfx::Size& size,
gfx::BufferFormat format,
@@ -72,9 +77,12 @@ class DrmThread : public base::Thread, public ozone::mojom::DeviceCursor {
std::vector<base::ScopedFD>&& fds,
const std::vector<gfx::NativePixmapPlane>& planes,
scoped_refptr<GbmBuffer>* buffer);
-
void GetScanoutFormats(gfx::AcceleratedWidget widget,
std::vector<gfx::BufferFormat>* scanout_formats);
+ void AddBindingCursorDevice(ozone::mojom::DeviceCursorRequest request);
+ void AddBindingDrmDevice(ozone::mojom::DrmDeviceRequest request);
+
+ // DrmWindowProxy (on GPU thread) is the client for these methods.
void SchedulePageFlip(gfx::AcceleratedWidget widget,
const std::vector<OverlayPlane>& planes,
SwapCompletionOnceCallback callback);
@@ -82,53 +90,56 @@ class DrmThread : public base::Thread, public ozone::mojom::DeviceCursor {
gfx::AcceleratedWidget widget,
const gfx::VSyncProvider::UpdateVSyncCallback& callback);
- void CreateWindow(gfx::AcceleratedWidget widget);
- void DestroyWindow(gfx::AcceleratedWidget widget);
- void SetWindowBounds(gfx::AcceleratedWidget widget, const gfx::Rect& bounds);
- void SetCursor(const gfx::AcceleratedWidget& widget,
- const std::vector<SkBitmap>& bitmaps,
- const gfx::Point& location,
- int32_t frame_delay_ms) override;
- void MoveCursor(const gfx::AcceleratedWidget& widget,
- const gfx::Point& location) override;
- void CheckOverlayCapabilities(
- gfx::AcceleratedWidget widget,
- const std::vector<OverlayCheck_Params>& overlays,
- base::OnceCallback<void(gfx::AcceleratedWidget,
- const std::vector<OverlayCheck_Params>&,
- const std::vector<OverlayCheckReturn_Params>&)>
- callback);
+ // ozone::mojom::DrmDevice
+ void StartDrmDevice(StartDrmDeviceCallback callback) override;
+ void CreateWindow(const gfx::AcceleratedWidget& widget) override;
+ void DestroyWindow(const gfx::AcceleratedWidget& widget) override;
+ void SetWindowBounds(const gfx::AcceleratedWidget& widget,
+ const gfx::Rect& bounds) override;
+ void TakeDisplayControl(base::OnceCallback<void(bool)> callback) override;
+ void RelinquishDisplayControl(
+ base::OnceCallback<void(bool)> callback) override;
void RefreshNativeDisplays(
- base::OnceCallback<void(MovableDisplaySnapshots)> callback);
- void ConfigureNativeDisplay(int64_t id,
- std::unique_ptr<display::DisplayMode> mode,
- const gfx::Point& origin,
- base::OnceCallback<void(int64_t, bool)> callback);
- void DisableNativeDisplay(int64_t id,
- base::OnceCallback<void(int64_t, bool)> callback);
- void TakeDisplayControl(base::OnceCallback<void(bool)> callback);
- void RelinquishDisplayControl(base::OnceCallback<void(bool)> callback);
- void AddGraphicsDevice(const base::FilePath& path,
- const base::FileDescriptor& fd);
- void RemoveGraphicsDevice(const base::FilePath& path);
- void GetHDCPState(
- int64_t display_id,
- base::OnceCallback<void(int64_t, bool, display::HDCPState)> callback);
+ base::OnceCallback<void(MovableDisplaySnapshots)> callback) override;
+ void AddGraphicsDevice(const base::FilePath& path, base::File file) override;
+ void RemoveGraphicsDevice(const base::FilePath& path) override;
+ void DisableNativeDisplay(
+ int64_t id,
+ base::OnceCallback<void(int64_t, bool)> callback) override;
+ void ConfigureNativeDisplay(
+ int64_t id,
+ std::unique_ptr<display::DisplayMode> mode,
+ const gfx::Point& origin,
+ base::OnceCallback<void(int64_t, bool)> callback) override;
+ void GetHDCPState(int64_t display_id,
+ base::OnceCallback<void(int64_t, bool, display::HDCPState)>
+ callback) override;
void SetHDCPState(int64_t display_id,
display::HDCPState state,
- base::OnceCallback<void(int64_t, bool)> callback);
+ base::OnceCallback<void(int64_t, bool)> callback) override;
void SetColorCorrection(
int64_t display_id,
const std::vector<display::GammaRampRGBEntry>& degamma_lut,
const std::vector<display::GammaRampRGBEntry>& gamma_lut,
- const std::vector<float>& correction_matrix);
+ const std::vector<float>& correction_matrix) override;
+ void CheckOverlayCapabilities(
+ const gfx::AcceleratedWidget& widget,
+ const OverlaySurfaceCandidateList& overlays,
+ base::OnceCallback<void(const gfx::AcceleratedWidget&,
+ const OverlaySurfaceCandidateList&,
+ const OverlayStatusList&)> callback) override;
+
+ // ozone::mojom::DeviceCursor
+ void SetCursor(const gfx::AcceleratedWidget& widget,
+ const std::vector<SkBitmap>& bitmaps,
+ const gfx::Point& location,
+ int32_t frame_delay_ms) override;
+ void MoveCursor(const gfx::AcceleratedWidget& widget,
+ const gfx::Point& location) override;
// base::Thread:
void Init() override;
- // Mojo support for DeviceCursorRequest.
- void AddBinding(ozone::mojom::DeviceCursorRequest request);
-
private:
std::unique_ptr<DrmDeviceManager> device_manager_;
std::unique_ptr<ScanoutBufferGenerator> buffer_generator_;
@@ -139,6 +150,9 @@ class DrmThread : public base::Thread, public ozone::mojom::DeviceCursor {
// requests from two different client threads.
mojo::BindingSet<ozone::mojom::DeviceCursor> bindings_;
+ // The mojo implementation of DrmDevice can use a simple binding.
+ mojo::Binding<ozone::mojom::DrmDevice> binding_;
+
DISALLOW_COPY_AND_ASSIGN(DrmThread);
};
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.cc b/chromium/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.cc
index b1add6a3d74..fb46660ae63 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_thread_message_proxy.cc
@@ -8,7 +8,7 @@
#include "base/threading/thread_task_runner_handle.h"
#include "ipc/ipc_message.h"
#include "ipc/ipc_sender.h"
-#include "ui/display/types/display_snapshot_mojo.h"
+#include "ui/display/types/display_snapshot.h"
#include "ui/ozone/common/gpu/ozone_gpu_messages.h"
#include "ui/ozone/platform/drm/common/drm_util.h"
#include "ui/ozone/platform/drm/gpu/drm_thread_proxy.h"
@@ -109,8 +109,9 @@ void DrmThreadMessageProxy::OnCursorMove(gfx::AcceleratedWidget widget,
void DrmThreadMessageProxy::OnCheckOverlayCapabilities(
gfx::AcceleratedWidget widget,
- const std::vector<OverlayCheck_Params>& overlays) {
+ const std::vector<OverlayCheck_Params>& param_overlays) {
DCHECK(drm_thread_->IsRunning());
+ auto overlays = CreateOverlaySurfaceCandidateListFrom(param_overlays);
auto callback =
base::BindOnce(&DrmThreadMessageProxy::OnCheckOverlayCapabilitiesCallback,
weak_ptr_factory_.GetWeakPtr());
@@ -191,9 +192,11 @@ void DrmThreadMessageProxy::OnAddGraphicsDevice(
const base::FilePath& path,
const base::FileDescriptor& fd) {
DCHECK(drm_thread_->IsRunning());
+ base::File file(fd.fd);
drm_thread_->task_runner()->PostTask(
- FROM_HERE, base::Bind(&DrmThread::AddGraphicsDevice,
- base::Unretained(drm_thread_), path, fd));
+ FROM_HERE,
+ base::Bind(&DrmThread::AddGraphicsDevice, base::Unretained(drm_thread_),
+ path, Passed(&file)));
}
void DrmThreadMessageProxy::OnRemoveGraphicsDevice(const base::FilePath& path) {
@@ -239,11 +242,13 @@ void DrmThreadMessageProxy::OnSetColorCorrection(
}
void DrmThreadMessageProxy::OnCheckOverlayCapabilitiesCallback(
- gfx::AcceleratedWidget widget,
- const std::vector<OverlayCheck_Params>& overlays,
- const std::vector<OverlayCheckReturn_Params>& returns) const {
- sender_->Send(
- new OzoneHostMsg_OverlayCapabilitiesReceived(widget, overlays, returns));
+ const gfx::AcceleratedWidget& widget,
+ const OverlaySurfaceCandidateList& candidates,
+ const OverlayStatusList& returns) const {
+ auto param_overlays = CreateParamsFromOverlaySurfaceCandidate(candidates);
+ auto param_returns = CreateParamsFromOverlayStatusList(returns);
+ sender_->Send(new OzoneHostMsg_OverlayCapabilitiesReceived(
+ widget, param_overlays, param_returns));
}
void DrmThreadMessageProxy::OnRefreshNativeDisplaysCallback(
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 da749ed08e9..c1ec3150c6f 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
@@ -15,6 +15,7 @@
#include "ui/gfx/native_widget_types.h"
#include "ui/ozone/platform/drm/common/display_types.h"
#include "ui/ozone/platform/drm/gpu/inter_thread_messaging_proxy.h"
+#include "ui/ozone/public/overlay_surface_candidate.h"
namespace base {
struct FileDescriptor;
@@ -30,7 +31,6 @@ namespace ui {
class DrmThread;
struct DisplayMode_Params;
struct OverlayCheck_Params;
-struct OverlayCheckReturn_Params;
class DrmThreadMessageProxy : public IPC::MessageFilter,
public InterThreadMessagingProxy {
@@ -80,9 +80,9 @@ class DrmThreadMessageProxy : public IPC::MessageFilter,
const std::vector<float>& correction_matrix);
void OnCheckOverlayCapabilitiesCallback(
- gfx::AcceleratedWidget widget,
- const std::vector<OverlayCheck_Params>& overlays,
- const std::vector<OverlayCheckReturn_Params>& returns) const;
+ const gfx::AcceleratedWidget& widget,
+ const OverlaySurfaceCandidateList& overlays,
+ const OverlayStatusList& returns) const;
void OnRefreshNativeDisplaysCallback(MovableDisplaySnapshots displays) const;
void OnConfigureNativeDisplayCallback(int64_t display_id, bool success) const;
void OnDisableNativeDisplayCallback(int64_t display_id, bool success) const;
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc b/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
index dccef01e783..8d15f12294c 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.cc
@@ -22,6 +22,10 @@ void DrmThreadProxy::BindThreadIntoMessagingProxy(
messaging_proxy->SetDrmThread(&drm_thread_);
}
+void DrmThreadProxy::StartDrmThread() {
+ drm_thread_.Start();
+}
+
std::unique_ptr<DrmWindowProxy> DrmThreadProxy::CreateDrmWindowProxy(
gfx::AcceleratedWidget widget) {
return base::MakeUnique<DrmWindowProxy>(widget, &drm_thread_);
@@ -63,11 +67,20 @@ void DrmThreadProxy::GetScanoutFormats(
widget, scanout_formats));
}
-void DrmThreadProxy::AddBinding(ozone::mojom::DeviceCursorRequest request) {
+void DrmThreadProxy::AddBindingCursorDevice(
+ ozone::mojom::DeviceCursorRequest request) {
+ drm_thread_.task_runner()->PostTask(
+ FROM_HERE,
+ base::Bind(&DrmThread::AddBindingCursorDevice,
+ base::Unretained(&drm_thread_), base::Passed(&request)));
+}
+
+void DrmThreadProxy::AddBindingDrmDevice(
+ ozone::mojom::DrmDeviceRequest request) {
drm_thread_.task_runner()->PostTask(
FROM_HERE,
- base::Bind(&DrmThread::AddBinding, base::Unretained(&drm_thread_),
- base::Passed(&request)));
+ base::Bind(&DrmThread::AddBindingDrmDevice,
+ base::Unretained(&drm_thread_), base::Passed(&request)));
}
} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.h b/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.h
index 4ae9ca2de11..c8a0b4b9c0b 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.h
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_thread_proxy.h
@@ -27,6 +27,8 @@ class DrmThreadProxy {
void BindThreadIntoMessagingProxy(InterThreadMessagingProxy* messaging_proxy);
+ void StartDrmThread();
+
std::unique_ptr<DrmWindowProxy> CreateDrmWindowProxy(
gfx::AcceleratedWidget widget);
@@ -45,7 +47,8 @@ class DrmThreadProxy {
void GetScanoutFormats(gfx::AcceleratedWidget widget,
std::vector<gfx::BufferFormat>* scanout_formats);
- void AddBinding(ozone::mojom::DeviceCursorRequest request);
+ void AddBindingCursorDevice(ozone::mojom::DeviceCursorRequest request);
+ void AddBindingDrmDevice(ozone::mojom::DrmDeviceRequest request);
private:
DrmThread drm_thread_;
diff --git a/chromium/ui/ozone/platform/drm/gpu/drm_window.cc b/chromium/ui/ozone/platform/drm/gpu/drm_window.cc
index 29447bc6307..82b86176fe6 100644
--- a/chromium/ui/ozone/platform/drm/gpu/drm_window.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/drm_window.cc
@@ -162,18 +162,11 @@ void DrmWindow::GetVSyncParameters(
// 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();
- // The value is invalid, so we can't update the parameters.
- if (controller_->GetTimeOfLastFlip() == 0 || crtc->mode().vrefresh == 0)
- return;
-
- // Stores the time of the last refresh.
- base::TimeTicks timebase =
- base::TimeTicks::FromInternalValue(controller_->GetTimeOfLastFlip());
- // Stores the refresh rate.
- base::TimeDelta interval =
- base::TimeDelta::FromSeconds(1) / crtc->mode().vrefresh;
-
- callback.Run(timebase, interval);
+ 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::ResetCursor(bool bitmap_only) {
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_buffer.cc b/chromium/ui/ozone/platform/drm/gpu/gbm_buffer.cc
index d9b42c934b7..624bcc99d48 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_buffer.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_buffer.cc
@@ -259,8 +259,9 @@ scoped_refptr<GbmBuffer> GbmBuffer::CreateBufferFromFds(
DCHECK_EQ(planes[0].offset, 0);
// Try to use scanout if supported.
- bool try_scanout = gbm_device_is_format_supported(
- gbm->device(), format, GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
+ int gbm_flags = GBM_BO_USE_SCANOUT | GBM_BO_USE_TEXTURING;
+ bool try_scanout =
+ gbm_device_is_format_supported(gbm->device(), format, gbm_flags);
gbm_bo* bo = nullptr;
if (try_scanout) {
@@ -280,18 +281,18 @@ scoped_refptr<GbmBuffer> GbmBuffer::CreateBufferFromFds(
// The fd passed to gbm_bo_import is not ref-counted and need to be
// kept open for the lifetime of the buffer.
bo = gbm_bo_import(gbm->device(), GBM_BO_IMPORT_FD_PLANAR, &fd_data,
- GBM_BO_USE_SCANOUT | GBM_BO_USE_RENDERING);
+ gbm_flags);
if (!bo) {
LOG(ERROR) << "nullptr returned from gbm_bo_import";
return nullptr;
}
+ } else {
+ gbm_flags &= ~GBM_BO_USE_SCANOUT;
}
- uint32_t flags = GBM_BO_USE_RENDERING;
- if (try_scanout)
- flags |= GBM_BO_USE_SCANOUT;
- scoped_refptr<GbmBuffer> buffer(new GbmBuffer(
- gbm, bo, format, flags, 0, 0, std::move(fds), size, std::move(planes)));
+ scoped_refptr<GbmBuffer> buffer(new GbmBuffer(gbm, bo, format, gbm_flags, 0,
+ 0, std::move(fds), size,
+ std::move(planes)));
return buffer;
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_surface.cc b/chromium/ui/ozone/platform/drm/gpu/gbm_surface.cc
index 649f4b051fb..a0cebe6ab50 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_surface.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_surface.cc
@@ -46,12 +46,14 @@ bool GbmSurface::OnMakeCurrent(gl::GLContext* 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, true) && CreatePixmaps();
+ return GbmSurfaceless::Resize(size, scale_factor, color_space, true) &&
+ CreatePixmaps();
}
bool GbmSurface::SupportsPostSubBuffer() {
diff --git a/chromium/ui/ozone/platform/drm/gpu/gbm_surface.h b/chromium/ui/ozone/platform/drm/gpu/gbm_surface.h
index ba38c01ac0d..fedff501c49 100644
--- a/chromium/ui/ozone/platform/drm/gpu/gbm_surface.h
+++ b/chromium/ui/ozone/platform/drm/gpu/gbm_surface.h
@@ -31,6 +31,7 @@ class GbmSurface : public GbmSurfaceless {
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& callback) override;
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 46218658981..37f9b17c6c6 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.cc
@@ -72,6 +72,13 @@ void HardwareDisplayController::Disable() {
for (const auto& controller : crtc_controllers_)
controller->Disable();
+ for (const auto& planes : owned_hardware_planes_) {
+ DrmDevice* drm = planes.first;
+ HardwareDisplayPlaneList* plane_list = planes.second.get();
+ bool ret = drm->plane_manager()->DisableOverlayPlanes(plane_list);
+ LOG_IF(ERROR, !ret) << "Can't disable overlays when disabling HDC.";
+ }
+
is_disabled_ = true;
}
@@ -107,7 +114,7 @@ bool HardwareDisplayController::ActualSchedulePageFlip(
[](const OverlayPlane& l, const OverlayPlane& r) {
return l.z_order < r.z_order;
});
- if (pending_planes.front().z_order != 0) {
+ if (pending_planes.front().z_order < 0) {
std::move(callback).Run(gfx::SwapResult::SWAP_FAILED);
return false;
}
@@ -283,8 +290,8 @@ gfx::Size HardwareDisplayController::GetModeSize() const {
crtc_controllers_[0]->mode().vdisplay);
}
-uint64_t HardwareDisplayController::GetTimeOfLastFlip() const {
- uint64_t time = 0;
+base::TimeTicks HardwareDisplayController::GetTimeOfLastFlip() const {
+ base::TimeTicks time;
for (const auto& controller : crtc_controllers_) {
if (time < controller->time_of_last_flip())
time = controller->time_of_last_flip();
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 31777d2c932..c80aba42352 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_controller.h
@@ -17,6 +17,7 @@
#include "base/callback.h"
#include "base/macros.h"
+#include "base/time/time.h"
#include "ui/gfx/swap_result.h"
#include "ui/ozone/platform/drm/gpu/hardware_display_plane_manager.h"
#include "ui/ozone/platform/drm/gpu/overlay_plane.h"
@@ -149,7 +150,7 @@ class HardwareDisplayController {
gfx::Point origin() const { return origin_; }
void set_origin(const gfx::Point& origin) { origin_ = origin; }
- uint64_t GetTimeOfLastFlip() const;
+ base::TimeTicks GetTimeOfLastFlip() const;
const std::vector<std::unique_ptr<CrtcController>>& crtc_controllers() const {
return crtc_controllers_;
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 0dbd989f9c8..05da38c50f3 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
@@ -400,7 +400,7 @@ TEST_F(HardwareDisplayControllerTest, FailPageFlipping) {
EXPECT_EQ(1, page_flips_);
}
-TEST_F(HardwareDisplayControllerTest, FailPageFlippingDueToNoPrimaryPlane) {
+TEST_F(HardwareDisplayControllerTest, CheckNoPrimaryPlane) {
ui::OverlayPlane plane1(scoped_refptr<ui::ScanoutBuffer>(
new ui::MockScanoutBuffer(kDefaultModeSize)),
1, gfx::OVERLAY_TRANSFORM_NONE,
@@ -413,7 +413,7 @@ TEST_F(HardwareDisplayControllerTest, FailPageFlippingDueToNoPrimaryPlane) {
base::Unretained(this)));
drm_->RunCallbacks();
- EXPECT_EQ(gfx::SwapResult::SWAP_FAILED, last_swap_result_);
+ EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_);
EXPECT_EQ(1, page_flips_);
}
@@ -452,3 +452,33 @@ TEST_F(HardwareDisplayControllerTest, RemoveCrtcMidPageFlip) {
EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_);
EXPECT_EQ(1, page_flips_);
}
+
+TEST_F(HardwareDisplayControllerTest, Disable) {
+ ui::OverlayPlane plane1(scoped_refptr<ui::ScanoutBuffer>(
+ new ui::MockScanoutBuffer(kDefaultModeSize)));
+ EXPECT_TRUE(controller_->Modeset(plane1, kDefaultMode));
+
+ ui::OverlayPlane plane2(new ui::MockScanoutBuffer(kOverlaySize), 1,
+ gfx::OVERLAY_TRANSFORM_NONE, gfx::Rect(kOverlaySize),
+ gfx::RectF(kDefaultModeSizeF));
+ std::vector<ui::OverlayPlane> planes;
+ planes.push_back(plane1);
+ planes.push_back(plane2);
+
+ controller_->SchedulePageFlip(
+ planes, base::Bind(&HardwareDisplayControllerTest::PageFlipCallback,
+ base::Unretained(this)));
+ drm_->RunCallbacks();
+ EXPECT_EQ(gfx::SwapResult::SWAP_ACK, last_swap_result_);
+ EXPECT_EQ(1, page_flips_);
+
+ controller_->Disable();
+
+ int planes_in_use = 0;
+ for (const auto& plane : drm_->plane_manager()->planes()) {
+ if (plane->in_use())
+ planes_in_use++;
+ }
+ // Only the primary plane is in use.
+ ASSERT_EQ(1, planes_in_use);
+}
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 90050f98a89..0cf28072e60 100644
--- a/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane.h
+++ b/chromium/ui/ozone/platform/drm/gpu/hardware_display_plane.h
@@ -45,6 +45,7 @@ class HardwareDisplayPlane {
uint32_t plane_id() const { return plane_id_; }
Type type() const { return type_; }
+ void set_type(const Type type) { type_ = type; }
void set_owning_crtc(uint32_t crtc) { owning_crtc_ = crtc; }
uint32_t owning_crtc() const { return owning_crtc_; }
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 15538c5e85f..2a9f0bd1246 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
@@ -89,6 +89,10 @@ class HardwareDisplayPlaneManager {
virtual bool Commit(HardwareDisplayPlaneList* plane_list,
bool test_only) = 0;
+ // Disable all the overlay planes previously submitted and now stored in
+ // plane_list->old_plane_list.
+ virtual bool DisableOverlayPlanes(HardwareDisplayPlaneList* plane_list) = 0;
+
const std::vector<std::unique_ptr<HardwareDisplayPlane>>& planes() {
return planes_;
}
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 67bea1230f5..eb0655d9a58 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
@@ -17,12 +17,11 @@ namespace {
void AtomicPageFlipCallback(std::vector<base::WeakPtr<CrtcController>> crtcs,
unsigned int frame,
- unsigned int seconds,
- unsigned int useconds) {
+ base::TimeTicks timestamp) {
for (auto& crtc : crtcs) {
auto* crtc_ptr = crtc.get();
if (crtc_ptr)
- crtc_ptr->OnPageFlipEvent(frame, seconds, useconds);
+ crtc_ptr->OnPageFlipEvent(frame, timestamp);
}
}
@@ -75,8 +74,12 @@ bool HardwareDisplayPlaneManagerAtomic::Commit(
if (!drm_->CommitProperties(plane_list->atomic_property_set.get(), flags,
crtcs.size(),
base::Bind(&AtomicPageFlipCallback, crtcs))) {
- PLOG(ERROR) << "Failed to commit properties. test_only:" << std::boolalpha
- << test_only << " error";
+ if (!test_only) {
+ PLOG(ERROR) << "Failed to commit properties for page flip.";
+ } else {
+ VPLOG(2) << "Failed to commit properties for MODE_ATOMIC_TEST_ONLY.";
+ }
+
ResetCurrentPlaneList(plane_list);
return false;
}
@@ -86,6 +89,33 @@ bool HardwareDisplayPlaneManagerAtomic::Commit(
return true;
}
+bool HardwareDisplayPlaneManagerAtomic::DisableOverlayPlanes(
+ HardwareDisplayPlaneList* plane_list) {
+ for (HardwareDisplayPlane* plane : plane_list->old_plane_list) {
+ if (plane->type() != HardwareDisplayPlane::kOverlay)
+ continue;
+ plane->set_in_use(false);
+ plane->set_owning_crtc(0);
+
+ HardwareDisplayPlaneAtomic* atomic_plane =
+ static_cast<HardwareDisplayPlaneAtomic*>(plane);
+ atomic_plane->SetPlaneData(plane_list->atomic_property_set.get(), 0, 0,
+ gfx::Rect(), gfx::Rect(),
+ gfx::OVERLAY_TRANSFORM_NONE);
+ }
+ // The list of crtcs is only useful if flags contains DRM_MODE_PAGE_FLIP_EVENT
+ // to get the pageflip callback. In this case we don't need to be notified
+ // at the next page flip, so the list of crtcs can be empty.
+ std::vector<base::WeakPtr<CrtcController>> crtcs;
+ bool ret = drm_->CommitProperties(plane_list->atomic_property_set.get(),
+ DRM_MODE_ATOMIC_NONBLOCK, crtcs.size(),
+ base::Bind(&AtomicPageFlipCallback, crtcs));
+ PLOG_IF(ERROR, !ret) << "Failed to commit properties for page flip.";
+
+ plane_list->atomic_property_set.reset(drmModeAtomicAlloc());
+ return ret;
+}
+
bool HardwareDisplayPlaneManagerAtomic::SetPlaneData(
HardwareDisplayPlaneList* plane_list,
HardwareDisplayPlane* hw_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 7847d43700c..968ff37897e 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
@@ -20,6 +20,7 @@ class HardwareDisplayPlaneManagerAtomic : public HardwareDisplayPlaneManager {
// HardwareDisplayPlaneManager:
bool Commit(HardwareDisplayPlaneList* plane_list,
bool test_only) override;
+ bool DisableOverlayPlanes(HardwareDisplayPlaneList* plane_list) override;
private:
bool SetPlaneData(HardwareDisplayPlaneList* plane_list,
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 501dfabcf6d..50d4334dc1e 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
@@ -98,6 +98,17 @@ bool HardwareDisplayPlaneManagerLegacy::Commit(
return ret;
}
+bool HardwareDisplayPlaneManagerLegacy::DisableOverlayPlanes(
+ HardwareDisplayPlaneList* plane_list) {
+ // We're never going to ship legacy pageflip with overlays enabled.
+ DCHECK(std::find_if(plane_list->old_plane_list.begin(),
+ plane_list->old_plane_list.end(),
+ [](HardwareDisplayPlane* plane) {
+ return plane->type() == HardwareDisplayPlane::kOverlay;
+ }) == plane_list->old_plane_list.end());
+ return true;
+}
+
bool HardwareDisplayPlaneManagerLegacy::SetPlaneData(
HardwareDisplayPlaneList* plane_list,
HardwareDisplayPlane* hw_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 56c55766e0f..1f9786028b7 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
@@ -20,6 +20,7 @@ class HardwareDisplayPlaneManagerLegacy : public HardwareDisplayPlaneManager {
// HardwareDisplayPlaneManager:
bool Commit(HardwareDisplayPlaneList* plane_list,
bool test_only) override;
+ bool DisableOverlayPlanes(HardwareDisplayPlaneList* plane_list) override;
protected:
bool SetPlaneData(HardwareDisplayPlaneList* plane_list,
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 c294771a5f5..c3845221469 100644
--- a/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/mock_drm_device.cc
@@ -126,7 +126,7 @@ bool MockDrmDevice::PageFlip(uint32_t crtc_id,
current_framebuffer_ = framebuffer;
if (page_flip_expectation_) {
if (use_sync_flips_)
- callback.Run(0, 0, 0);
+ callback.Run(0, base::TimeTicks());
else
callbacks_.push(callback);
}
@@ -241,7 +241,7 @@ void MockDrmDevice::RunCallbacks() {
while (!callbacks_.empty()) {
PageFlipCallback callback = callbacks_.front();
callbacks_.pop();
- callback.Run(0, 0, 0);
+ callback.Run(0, base::TimeTicks());
}
}
diff --git a/chromium/ui/ozone/platform/drm/gpu/mock_hardware_display_plane_manager.cc b/chromium/ui/ozone/platform/drm/gpu/mock_hardware_display_plane_manager.cc
index ec26ff89a11..68e7659b836 100644
--- a/chromium/ui/ozone/platform/drm/gpu/mock_hardware_display_plane_manager.cc
+++ b/chromium/ui/ozone/platform/drm/gpu/mock_hardware_display_plane_manager.cc
@@ -28,6 +28,8 @@ MockHardwareDisplayPlaneManager::MockHardwareDisplayPlaneManager(
plane->Initialize(drm, std::vector<uint32_t>(1, DRM_FORMAT_XRGB8888),
std::vector<drm_format_modifier>(1, linear_modifier),
false, true);
+ plane->set_type(i ? HardwareDisplayPlane::kOverlay
+ : HardwareDisplayPlane::kPrimary);
planes_.push_back(std::move(plane));
}
}
@@ -99,6 +101,18 @@ void MockHardwareDisplayPlaneManager::SetCrtcInfo(
ResetPlaneCount();
}
+bool MockHardwareDisplayPlaneManager::DisableOverlayPlanes(
+ HardwareDisplayPlaneList* plane_list) {
+ for (HardwareDisplayPlane* plane : plane_list->old_plane_list) {
+ if (plane->type() != HardwareDisplayPlane::kOverlay)
+ continue;
+ plane->set_in_use(false);
+ plane->set_owning_crtc(0);
+ }
+
+ return true;
+}
+
bool MockHardwareDisplayPlaneManager::SetPlaneData(
HardwareDisplayPlaneList* plane_list,
HardwareDisplayPlane* hw_plane,
diff --git a/chromium/ui/ozone/platform/drm/gpu/mock_hardware_display_plane_manager.h b/chromium/ui/ozone/platform/drm/gpu/mock_hardware_display_plane_manager.h
index 60f159e517f..dc567a9f4a0 100644
--- a/chromium/ui/ozone/platform/drm/gpu/mock_hardware_display_plane_manager.h
+++ b/chromium/ui/ozone/platform/drm/gpu/mock_hardware_display_plane_manager.h
@@ -33,6 +33,7 @@ class MockHardwareDisplayPlaneManager
void SetPlaneProperties(const std::vector<FakePlaneInfo>& planes);
void SetCrtcInfo(const std::vector<uint32_t>& crtcs);
+ bool DisableOverlayPlanes(HardwareDisplayPlaneList* plane_list) override;
bool SetPlaneData(HardwareDisplayPlaneList* plane_list,
HardwareDisplayPlane* hw_plane,
const OverlayPlane& overlay,
diff --git a/chromium/ui/ozone/platform/drm/host/drm_display_host.cc b/chromium/ui/ozone/platform/drm/host/drm_display_host.cc
index 463c108f9c2..824287f2382 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_display_host.cc
+++ b/chromium/ui/ozone/platform/drm/host/drm_display_host.cc
@@ -9,7 +9,7 @@
#include "base/memory/ptr_util.h"
#include "base/threading/thread_task_runner_handle.h"
#include "ui/display/types/display_mode.h"
-#include "ui/ozone/common/display_snapshot_proxy.h"
+#include "ui/display/types/display_snapshot.h"
#include "ui/ozone/platform/drm/common/drm_util.h"
#include "ui/ozone/platform/drm/host/gpu_thread_adapter.h"
@@ -19,7 +19,7 @@ DrmDisplayHost::DrmDisplayHost(GpuThreadAdapter* sender,
const DisplaySnapshot_Params& params,
bool is_dummy)
: sender_(sender),
- snapshot_(new DisplaySnapshotProxy(params)),
+ snapshot_(CreateDisplaySnapshotFromParams(params)),
is_dummy_(is_dummy) {
sender_->AddGpuThreadObserver(this);
}
@@ -31,7 +31,7 @@ DrmDisplayHost::~DrmDisplayHost() {
void DrmDisplayHost::UpdateDisplaySnapshot(
const DisplaySnapshot_Params& params) {
- snapshot_ = base::MakeUnique<DisplaySnapshotProxy>(params);
+ snapshot_ = CreateDisplaySnapshotFromParams(params);
}
void DrmDisplayHost::Configure(const display::DisplayMode* mode,
diff --git a/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.cc b/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.cc
index 8411915dfde..f160a2ce760 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.cc
+++ b/chromium/ui/ozone/platform/drm/host/drm_display_host_manager.cc
@@ -288,8 +288,7 @@ void DrmDisplayHostManager::OnAddGraphicsDevice(
std::unique_ptr<DrmDeviceHandle> handle) {
if (handle->IsValid()) {
drm_devices_[dev_path] = sys_path;
- proxy_->GpuAddGraphicsDevice(sys_path,
- base::FileDescriptor(handle->PassFD()));
+ proxy_->GpuAddGraphicsDevice(sys_path, handle->PassFD());
NotifyDisplayDelegate();
}
@@ -332,7 +331,7 @@ void DrmDisplayHostManager::OnGpuProcessLaunched() {
// Send the primary device first since this is used to initialize graphics
// state.
proxy_->GpuAddGraphicsDevice(drm_devices_[primary_graphics_card_path_],
- base::FileDescriptor(handle->PassFD()));
+ handle->PassFD());
}
void DrmDisplayHostManager::OnGpuThreadReady() {
diff --git a/chromium/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc b/chromium/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc
index ccbcbeb21c7..52e08ed5cc4 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc
+++ b/chromium/ui/ozone/platform/drm/host/drm_gpu_platform_support_host.cc
@@ -9,6 +9,7 @@
#include "base/trace_event/trace_event.h"
#include "ui/ozone/common/gpu/ozone_gpu_message_params.h"
#include "ui/ozone/common/gpu/ozone_gpu_messages.h"
+#include "ui/ozone/platform/drm/common/drm_util.h"
#include "ui/ozone/platform/drm/host/drm_cursor.h"
#include "ui/ozone/platform/drm/host/drm_display_host_manager.h"
#include "ui/ozone/platform/drm/host/drm_overlay_candidates_host.h"
@@ -244,10 +245,10 @@ bool DrmGpuPlatformSupportHost::GpuRelinquishDisplayControl() {
return Send(new OzoneGpuMsg_RelinquishDisplayControl());
}
-bool DrmGpuPlatformSupportHost::GpuAddGraphicsDevice(
- const base::FilePath& path,
- const base::FileDescriptor& fd) {
- IPC::Message* message = new OzoneGpuMsg_AddGraphicsDevice(path, fd);
+bool DrmGpuPlatformSupportHost::GpuAddGraphicsDevice(const base::FilePath& path,
+ base::ScopedFD fd) {
+ IPC::Message* message = new OzoneGpuMsg_AddGraphicsDevice(
+ path, base::FileDescriptor(std::move(fd)));
// This function may be called from two places:
// - DrmDisplayHostManager::OnGpuProcessLaunched() invoked synchronously
@@ -294,14 +295,17 @@ bool DrmGpuPlatformSupportHost::OnMessageReceivedForDrmOverlayManager(
void DrmGpuPlatformSupportHost::OnOverlayResult(
gfx::AcceleratedWidget widget,
const std::vector<OverlayCheck_Params>& params,
- const std::vector<OverlayCheckReturn_Params>& returns) {
- overlay_manager_->GpuSentOverlayResult(widget, params, returns);
+ const std::vector<OverlayCheckReturn_Params>& param_returns) {
+ auto candidates = CreateOverlaySurfaceCandidateListFrom(params);
+ auto returns = CreateOverlayStatusListFrom(param_returns);
+ overlay_manager_->GpuSentOverlayResult(widget, candidates, returns);
}
bool DrmGpuPlatformSupportHost::GpuCheckOverlayCapabilities(
gfx::AcceleratedWidget widget,
- const std::vector<OverlayCheck_Params>& new_params) {
- return Send(new OzoneGpuMsg_CheckOverlayCapabilities(widget, new_params));
+ const OverlaySurfaceCandidateList& candidates) {
+ auto params = CreateParamsFromOverlaySurfaceCandidate(candidates);
+ return Send(new OzoneGpuMsg_CheckOverlayCapabilities(widget, params));
}
// DrmDisplayHost
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 5611b961d74..826e09d949c 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
@@ -63,7 +63,7 @@ class DrmGpuPlatformSupportHost : public GpuPlatformSupportHost,
bool GpuRefreshNativeDisplays() override;
bool GpuRelinquishDisplayControl() override;
bool GpuAddGraphicsDevice(const base::FilePath& path,
- const base::FileDescriptor& fd) override;
+ base::ScopedFD fd) override;
bool GpuRemoveGraphicsDevice(const base::FilePath& path) override;
// Methods needed for DrmOverlayManager.
@@ -74,7 +74,7 @@ class DrmGpuPlatformSupportHost : public GpuPlatformSupportHost,
// Services needed by DrmOverlayManager
bool GpuCheckOverlayCapabilities(
gfx::AcceleratedWidget widget,
- const std::vector<OverlayCheck_Params>& new_params) override;
+ const OverlaySurfaceCandidateList& new_params) override;
// Services needed by DrmDisplayHost
bool GpuConfigureNativeDisplay(int64_t display_id,
diff --git a/chromium/ui/ozone/platform/drm/host/drm_native_display_delegate.cc b/chromium/ui/ozone/platform/drm/host/drm_native_display_delegate.cc
index ffaad3c5107..f96d2d9bbd9 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_native_display_delegate.cc
+++ b/chromium/ui/ozone/platform/drm/host/drm_native_display_delegate.cc
@@ -34,12 +34,6 @@ void DrmNativeDisplayDelegate::Initialize() {
display_manager_->AddDelegate(this);
}
-void DrmNativeDisplayDelegate::GrabServer() {
-}
-
-void DrmNativeDisplayDelegate::UngrabServer() {
-}
-
void DrmNativeDisplayDelegate::TakeDisplayControl(
const display::DisplayControlCallback& callback) {
display_manager_->TakeDisplayControl(callback);
@@ -50,23 +44,11 @@ void DrmNativeDisplayDelegate::RelinquishDisplayControl(
display_manager_->RelinquishDisplayControl(callback);
}
-void DrmNativeDisplayDelegate::SyncWithServer() {
-}
-
-void DrmNativeDisplayDelegate::SetBackgroundColor(uint32_t color_argb) {
-}
-
-void DrmNativeDisplayDelegate::ForceDPMSOn() {
-}
-
void DrmNativeDisplayDelegate::GetDisplays(
const display::GetDisplaysCallback& callback) {
display_manager_->UpdateDisplays(callback);
}
-void DrmNativeDisplayDelegate::AddMode(const display::DisplaySnapshot& output,
- const display::DisplayMode* mode) {}
-
void DrmNativeDisplayDelegate::Configure(
const display::DisplaySnapshot& output,
const display::DisplayMode* mode,
@@ -76,9 +58,6 @@ void DrmNativeDisplayDelegate::Configure(
display->Configure(mode, origin, callback);
}
-void DrmNativeDisplayDelegate::CreateFrameBuffer(const gfx::Size& size) {
-}
-
void DrmNativeDisplayDelegate::GetHDCPState(
const display::DisplaySnapshot& output,
const display::GetHDCPStateCallback& callback) {
@@ -94,19 +73,6 @@ void DrmNativeDisplayDelegate::SetHDCPState(
display->SetHDCPState(state, callback);
}
-std::vector<display::ColorCalibrationProfile>
-DrmNativeDisplayDelegate::GetAvailableColorCalibrationProfiles(
- const display::DisplaySnapshot& output) {
- return std::vector<display::ColorCalibrationProfile>();
-}
-
-bool DrmNativeDisplayDelegate::SetColorCalibrationProfile(
- const display::DisplaySnapshot& output,
- display::ColorCalibrationProfile new_profile) {
- NOTIMPLEMENTED();
- return false;
-}
-
bool DrmNativeDisplayDelegate::SetColorCorrection(
const display::DisplaySnapshot& output,
const std::vector<display::GammaRampRGBEntry>& degamma_lut,
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 e37a37366b9..0b1d5336aff 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
@@ -17,7 +17,7 @@ class DrmDisplayHostManager;
class DrmNativeDisplayDelegate : public display::NativeDisplayDelegate {
public:
- DrmNativeDisplayDelegate(DrmDisplayHostManager* display_manager);
+ explicit DrmNativeDisplayDelegate(DrmDisplayHostManager* display_manager);
~DrmNativeDisplayDelegate() override;
void OnConfigurationChanged();
@@ -25,34 +25,20 @@ class DrmNativeDisplayDelegate : public display::NativeDisplayDelegate {
// display::NativeDisplayDelegate overrides:
void Initialize() override;
- void GrabServer() override;
- void UngrabServer() override;
void TakeDisplayControl(
const display::DisplayControlCallback& callback) override;
void RelinquishDisplayControl(
const display::DisplayControlCallback& callback) override;
- void SyncWithServer() override;
- void SetBackgroundColor(uint32_t color_argb) override;
- void ForceDPMSOn() override;
void GetDisplays(const display::GetDisplaysCallback& callback) override;
- void AddMode(const display::DisplaySnapshot& output,
- const display::DisplayMode* mode) override;
void Configure(const display::DisplaySnapshot& output,
const display::DisplayMode* mode,
const gfx::Point& origin,
const display::ConfigureCallback& callback) override;
- void CreateFrameBuffer(const gfx::Size& size) override;
void GetHDCPState(const display::DisplaySnapshot& output,
const display::GetHDCPStateCallback& callback) override;
void SetHDCPState(const display::DisplaySnapshot& output,
display::HDCPState state,
const display::SetHDCPStateCallback& callback) override;
- std::vector<display::ColorCalibrationProfile>
- GetAvailableColorCalibrationProfiles(
- const display::DisplaySnapshot& output) override;
- bool SetColorCalibrationProfile(
- const display::DisplaySnapshot& output,
- display::ColorCalibrationProfile new_profile) override;
bool SetColorCorrection(
const display::DisplaySnapshot& output,
const std::vector<display::GammaRampRGBEntry>& degamma_lut,
diff --git a/chromium/ui/ozone/platform/drm/host/drm_overlay_manager.cc b/chromium/ui/ozone/platform/drm/host/drm_overlay_manager.cc
index 2d144393cb4..34099f1cc3e 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_overlay_manager.cc
+++ b/chromium/ui/ozone/platform/drm/host/drm_overlay_manager.cc
@@ -12,6 +12,7 @@
#include "base/memory/ptr_util.h"
#include "base/trace_event/trace_event.h"
#include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/ozone/platform/drm/common/drm_util.h"
#include "ui/ozone/platform/drm/host/drm_overlay_candidates_host.h"
#include "ui/ozone/platform/drm/host/drm_window_host.h"
#include "ui/ozone/platform/drm/host/drm_window_host_manager.h"
@@ -49,13 +50,14 @@ void DrmOverlayManager::CheckOverlaySupport(
OverlayCandidatesOzone::OverlaySurfaceCandidateList* candidates,
gfx::AcceleratedWidget widget) {
TRACE_EVENT0("hwoverlays", "DrmOverlayManager::CheckOverlaySupport");
- std::vector<OverlayCheck_Params> overlay_params;
+
+ OverlaySurfaceCandidateList result_candidates;
for (auto& candidate : *candidates) {
// Reject candidates that don't fall on a pixel boundary.
if (!gfx::IsNearestRectWithinDistance(candidate.display_rect, 0.01f)) {
DCHECK(candidate.plane_z_order != 0);
- overlay_params.push_back(OverlayCheck_Params());
- overlay_params.back().is_overlay_candidate = false;
+ result_candidates.push_back(OverlaySurfaceCandidate());
+ result_candidates.back().overlay_handled = false;
continue;
}
@@ -64,29 +66,29 @@ void DrmOverlayManager::CheckOverlaySupport(
if (candidate.plane_z_order == 0)
candidate.buffer_size = gfx::ToNearestRect(candidate.display_rect).size();
- overlay_params.push_back(OverlayCheck_Params(candidate));
+ result_candidates.push_back(OverlaySurfaceCandidate(candidate));
+ // Start out hoping that we can have an overlay.
+ result_candidates.back().overlay_handled = true;
if (!CanHandleCandidate(candidate, widget)) {
DCHECK(candidate.plane_z_order != 0);
- overlay_params.back().is_overlay_candidate = false;
+ result_candidates.back().overlay_handled = false;
}
}
size_t size = candidates->size();
- auto iter = cache_.Get(overlay_params);
+ auto iter = cache_.Get(result_candidates);
if (iter == cache_.end()) {
// We can skip GPU side validation in case all candidates are invalid.
bool needs_gpu_validation = std::any_of(
- overlay_params.begin(), overlay_params.end(),
- [](OverlayCheck_Params& c) { return c.is_overlay_candidate; });
+ result_candidates.begin(), result_candidates.end(),
+ [](OverlaySurfaceCandidate& c) { return c.overlay_handled; });
OverlayValidationCacheValue value;
value.request_num = 0;
- value.returns.resize(overlay_params.size());
- for (size_t i = 0; i < value.returns.size(); ++i) {
- value.returns[i].status =
- needs_gpu_validation ? OVERLAY_STATUS_PENDING : OVERLAY_STATUS_NOT;
- }
- iter = cache_.Put(overlay_params, value);
+ value.status.resize(result_candidates.size(), needs_gpu_validation
+ ? OVERLAY_STATUS_PENDING
+ : OVERLAY_STATUS_NOT);
+ iter = cache_.Put(result_candidates, value);
}
OverlayValidationCacheValue& value = iter->second;
@@ -94,20 +96,19 @@ void DrmOverlayManager::CheckOverlaySupport(
value.request_num++;
} else if (value.request_num == kThrottleRequestSize) {
value.request_num++;
- if (value.returns.back().status == OVERLAY_STATUS_PENDING)
- SendOverlayValidationRequest(overlay_params, widget);
+ if (value.status.back() == OVERLAY_STATUS_PENDING)
+ SendOverlayValidationRequest(result_candidates, widget);
} else {
// We haven't received an answer yet.
- if (value.returns.back().status == OVERLAY_STATUS_PENDING)
+ if (value.status.back() == OVERLAY_STATUS_PENDING)
return;
- const std::vector<OverlayCheckReturn_Params>& returns = value.returns;
- DCHECK(size == returns.size());
+ const std::vector<OverlayStatus>& status = value.status;
+ DCHECK(size == status.size());
for (size_t i = 0; i < size; i++) {
- DCHECK(returns[i].status == OVERLAY_STATUS_ABLE ||
- returns[i].status == OVERLAY_STATUS_NOT);
- candidates->at(i).overlay_handled =
- returns[i].status == OVERLAY_STATUS_ABLE;
+ DCHECK(status[i] == OVERLAY_STATUS_ABLE ||
+ status[i] == OVERLAY_STATUS_NOT);
+ candidates->at(i).overlay_handled = status[i] == OVERLAY_STATUS_ABLE;
}
}
}
@@ -125,25 +126,25 @@ DrmOverlayManager::OverlayValidationCacheValue::~OverlayValidationCacheValue() =
default;
void DrmOverlayManager::SendOverlayValidationRequest(
- const std::vector<OverlayCheck_Params>& new_params,
+ const OverlaySurfaceCandidateList& candidates,
gfx::AcceleratedWidget widget) const {
if (!proxy_->IsConnected())
return;
TRACE_EVENT_ASYNC_BEGIN0(
"hwoverlays", "DrmOverlayManager::SendOverlayValidationRequest", this);
- proxy_->GpuCheckOverlayCapabilities(widget, new_params);
+ proxy_->GpuCheckOverlayCapabilities(widget, candidates);
}
void DrmOverlayManager::GpuSentOverlayResult(
- gfx::AcceleratedWidget widget,
- const std::vector<OverlayCheck_Params>& params,
- const std::vector<OverlayCheckReturn_Params>& returns) {
+ const gfx::AcceleratedWidget& widget,
+ const OverlaySurfaceCandidateList& candidates,
+ const OverlayStatusList& returns) {
TRACE_EVENT_ASYNC_END0(
"hwoverlays", "DrmOverlayManager::SendOverlayValidationRequest response",
this);
- auto iter = cache_.Peek(params);
+ auto iter = cache_.Peek(candidates);
if (iter != cache_.end()) {
- iter->second.returns = returns;
+ iter->second.status = returns;
}
}
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 6ad846997a2..c1915d5714e 100644
--- a/chromium/ui/ozone/platform/drm/host/drm_overlay_manager.h
+++ b/chromium/ui/ozone/platform/drm/host/drm_overlay_manager.h
@@ -35,10 +35,9 @@ class DrmOverlayManager : public OverlayManagerOzone {
// Communication-free implementations of actions performed in response to
// messages from the GPU thread.
- void GpuSentOverlayResult(
- gfx::AcceleratedWidget widget,
- const std::vector<OverlayCheck_Params>& params,
- const std::vector<OverlayCheckReturn_Params>& returns);
+ void GpuSentOverlayResult(const gfx::AcceleratedWidget& widget,
+ const OverlaySurfaceCandidateList& params,
+ const OverlayStatusList& returns);
// Service method for DrmOverlayCandidatesHost
void CheckOverlaySupport(
@@ -54,11 +53,11 @@ class DrmOverlayManager : public OverlayManagerOzone {
OverlayValidationCacheValue(const OverlayValidationCacheValue&);
~OverlayValidationCacheValue();
int request_num = 0;
- std::vector<OverlayCheckReturn_Params> returns;
+ std::vector<OverlayStatus> status;
};
void SendOverlayValidationRequest(
- const std::vector<OverlayCheck_Params>& new_params,
+ const OverlaySurfaceCandidateList& candidates,
gfx::AcceleratedWidget widget) const;
bool CanHandleCandidate(const OverlaySurfaceCandidate& candidate,
gfx::AcceleratedWidget widget) const;
@@ -66,9 +65,9 @@ class DrmOverlayManager : public OverlayManagerOzone {
GpuThreadAdapter* proxy_; // Not owned.
DrmWindowHostManager* window_manager_; // Not owned.
- // List of all OverlayCheck_Params instances which have been requested
+ // List of all OverlaySurfaceCandidate instances which have been requested
// for validation and/or validated.
- base::MRUCache<std::vector<OverlayCheck_Params>, OverlayValidationCacheValue>
+ base::MRUCache<OverlaySurfaceCandidateList, OverlayValidationCacheValue>
cache_;
DISALLOW_COPY_AND_ASSIGN(DrmOverlayManager);
diff --git a/chromium/ui/ozone/platform/drm/host/gpu_thread_adapter.h b/chromium/ui/ozone/platform/drm/host/gpu_thread_adapter.h
index 4d63d010dfd..f275e66709a 100644
--- a/chromium/ui/ozone/platform/drm/host/gpu_thread_adapter.h
+++ b/chromium/ui/ozone/platform/drm/host/gpu_thread_adapter.h
@@ -38,7 +38,7 @@ class GpuThreadAdapter {
virtual bool GpuRefreshNativeDisplays() = 0;
virtual bool GpuRelinquishDisplayControl() = 0;
virtual bool GpuAddGraphicsDevice(const base::FilePath& path,
- const base::FileDescriptor& fd) = 0;
+ base::ScopedFD fd) = 0;
virtual bool GpuRemoveGraphicsDevice(const base::FilePath& path) = 0;
// Methods for DrmOverlayManager.
@@ -49,7 +49,7 @@ class GpuThreadAdapter {
// Services needed by DrmOverlayManager
virtual bool GpuCheckOverlayCapabilities(
gfx::AcceleratedWidget widget,
- const std::vector<OverlayCheck_Params>& new_params) = 0;
+ const OverlaySurfaceCandidateList& overlays) = 0;
// Services needed by DrmDisplayHost
virtual bool GpuConfigureNativeDisplay(
diff --git a/chromium/ui/ozone/platform/drm/cursor_proxy_mojo.cc b/chromium/ui/ozone/platform/drm/host/host_cursor_proxy.cc
index c48ddcad7c4..ba5baeec450 100644
--- a/chromium/ui/ozone/platform/drm/cursor_proxy_mojo.cc
+++ b/chromium/ui/ozone/platform/drm/host/host_cursor_proxy.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/ozone/platform/drm/cursor_proxy_mojo.h"
+#include "ui/ozone/platform/drm/host/host_cursor_proxy.h"
#include "services/service_manager/public/cpp/connector.h"
#include "services/ui/public/interfaces/constants.mojom.h"
@@ -10,15 +10,15 @@
namespace ui {
// We assume that this is invoked only on the UI thread.
-CursorProxyMojo::CursorProxyMojo(service_manager::Connector* connector)
+HostCursorProxy::HostCursorProxy(service_manager::Connector* connector)
: connector_(connector->Clone()) {
ui_thread_ref_ = base::PlatformThread::CurrentRef();
connector->BindInterface(ui::mojom::kServiceName, &main_cursor_ptr_);
}
-CursorProxyMojo::~CursorProxyMojo() {}
+HostCursorProxy::~HostCursorProxy() {}
-void CursorProxyMojo::CursorSet(gfx::AcceleratedWidget widget,
+void HostCursorProxy::CursorSet(gfx::AcceleratedWidget widget,
const std::vector<SkBitmap>& bitmaps,
const gfx::Point& location,
int frame_delay_ms) {
@@ -30,7 +30,7 @@ void CursorProxyMojo::CursorSet(gfx::AcceleratedWidget widget,
}
}
-void CursorProxyMojo::Move(gfx::AcceleratedWidget widget,
+void HostCursorProxy::Move(gfx::AcceleratedWidget widget,
const gfx::Point& location) {
InitializeOnEvdevIfNecessary();
if (ui_thread_ref_ == base::PlatformThread::CurrentRef()) {
@@ -40,12 +40,12 @@ void CursorProxyMojo::Move(gfx::AcceleratedWidget widget,
}
}
-// Evdev runs this method on starting. But if a CursorProxyMojo is created long
+// Evdev runs this method on starting. But if a HostCursorProxy is created long
// after Evdev has started (e.g. if the Viz process crashes (and the
-// |CursorProxyMojo| self-destructs and then a new |CursorProxyMojo| is built
+// |HostCursorProxy| self-destructs and then a new |HostCursorProxy| is built
// when the GpuThread/DrmThread pair are once again running), we need to run it
// on cursor motions.
-void CursorProxyMojo::InitializeOnEvdevIfNecessary() {
+void HostCursorProxy::InitializeOnEvdevIfNecessary() {
if (ui_thread_ref_ != base::PlatformThread::CurrentRef()) {
connector_->BindInterface(ui::mojom::kServiceName, &evdev_cursor_ptr_);
}
diff --git a/chromium/ui/ozone/platform/drm/cursor_proxy_mojo.h b/chromium/ui/ozone/platform/drm/host/host_cursor_proxy.h
index e1bceff9208..42feece0e0e 100644
--- a/chromium/ui/ozone/platform/drm/cursor_proxy_mojo.h
+++ b/chromium/ui/ozone/platform/drm/host/host_cursor_proxy.h
@@ -2,11 +2,10 @@
// 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_CURSOR_PROXY_MOJO_H_
-#define UI_OZONE_PLATFORM_DRM_CURSOR_PROXY_MOJO_H_
+#ifndef UI_OZONE_PLATFORM_DRM_HOST_HOST_CURSOR_PROXY_H_
+#define UI_OZONE_PLATFORM_DRM_HOST_HOST_CURSOR_PROXY_H_
#include "ui/gfx/native_widget_types.h"
-#include "ui/ozone/platform/drm/gpu/inter_thread_messaging_proxy.h"
#include "ui/ozone/platform/drm/host/drm_cursor.h"
#include "ui/ozone/public/interfaces/device_cursor.mojom.h"
@@ -21,10 +20,10 @@ namespace ui {
// pointer control via Mojo-style IPC. This code runs only in the mus-ws (i.e.
// it's the client) and sends mouse pointer control messages to a less
// priviledged process.
-class CursorProxyMojo : public DrmCursorProxy {
+class HostCursorProxy : public DrmCursorProxy {
public:
- explicit CursorProxyMojo(service_manager::Connector* connector);
- ~CursorProxyMojo() override;
+ explicit HostCursorProxy(service_manager::Connector* connector);
+ ~HostCursorProxy() override;
private:
// DrmCursorProxy.
@@ -42,9 +41,9 @@ class CursorProxyMojo : public DrmCursorProxy {
ui::ozone::mojom::DeviceCursorPtr evdev_cursor_ptr_;
base::PlatformThreadRef ui_thread_ref_;
- DISALLOW_COPY_AND_ASSIGN(CursorProxyMojo);
+ DISALLOW_COPY_AND_ASSIGN(HostCursorProxy);
};
} // namespace ui
-#endif // UI_OZONE_PLATFORM_DRM_CURSOR_PROXY_MOJO_H_
+#endif // UI_OZONE_PLATFORM_DRM_HOST_HOST_CURSOR_PROXY_H_
diff --git a/chromium/ui/ozone/platform/drm/host/host_drm_device.cc b/chromium/ui/ozone/platform/drm/host/host_drm_device.cc
new file mode 100644
index 00000000000..628b3c23a16
--- /dev/null
+++ b/chromium/ui/ozone/platform/drm/host/host_drm_device.cc
@@ -0,0 +1,348 @@
+// 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/host/host_drm_device.h"
+
+#include "base/bind.h"
+#include "base/run_loop.h"
+#include "base/single_thread_task_runner.h"
+#include "base/task_runner.h"
+#include "base/threading/thread_task_runner_handle.h"
+#include "services/service_manager/public/cpp/connector.h"
+#include "services/ui/public/interfaces/constants.mojom.h"
+#include "ui/display/types/display_snapshot.h"
+#include "ui/ozone/platform/drm/common/drm_util.h"
+#include "ui/ozone/platform/drm/host/drm_display_host_manager.h"
+#include "ui/ozone/platform/drm/host/drm_overlay_manager.h"
+#include "ui/ozone/platform/drm/host/host_cursor_proxy.h"
+
+namespace ui {
+
+HostDrmDevice::HostDrmDevice(DrmCursor* cursor,
+ service_manager::Connector* connector)
+ : cursor_(cursor), connector_(connector), weak_ptr_factory_(this) {
+ // Bind the viz process pointer here.
+ // TODO(rjkroege): Reconnect on error as that would indicate that the Viz
+ // process has failed.
+ connector->BindInterface(ui::mojom::kServiceName, &drm_device_ptr_);
+}
+
+HostDrmDevice::~HostDrmDevice() {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ for (GpuThreadObserver& observer : gpu_thread_observers_)
+ observer.OnGpuThreadRetired();
+}
+
+void HostDrmDevice::AsyncStartDrmDevice() {
+ auto callback = base::BindOnce(&HostDrmDevice::OnDrmServiceStartedCallback,
+ weak_ptr_factory_.GetWeakPtr());
+ drm_device_ptr_->StartDrmDevice(std::move(callback));
+}
+
+void HostDrmDevice::BlockingStartDrmDevice() {
+ // Wait until startup related tasks posted to this thread that must precede
+ // blocking on
+ base::RunLoop().RunUntilIdle();
+
+ bool success;
+ drm_device_ptr_->StartDrmDevice(&success);
+ CHECK(success)
+ << "drm thread failed to successfully start in single process mode.";
+ if (!connected_)
+ OnDrmServiceStartedCallback(true);
+ return;
+}
+
+void HostDrmDevice::OnDrmServiceStartedCallback(bool success) {
+ // This can be called multiple times in the course of single-threaded startup.
+ if (connected_)
+ return;
+ if (success == true) {
+ connected_ = true;
+ RunObservers();
+ }
+ // TODO(rjkroege): Handle failure of launching a viz process.
+}
+
+void HostDrmDevice::ProvideManagers(DrmDisplayHostManager* display_manager,
+ DrmOverlayManager* overlay_manager) {
+ display_manager_ = display_manager;
+ overlay_manager_ = overlay_manager;
+}
+
+void HostDrmDevice::RunObservers() {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ for (GpuThreadObserver& observer : gpu_thread_observers_) {
+ observer.OnGpuProcessLaunched();
+ observer.OnGpuThreadReady();
+ }
+
+ // The cursor is special since it will process input events on the IO thread
+ // and can by-pass the UI thread. This means that we need to special case it
+ // and notify it after all other observers/handlers are notified.
+ cursor_->SetDrmCursorProxy(base::MakeUnique<HostCursorProxy>(connector_));
+
+ // TODO(rjkroege): Call ResetDrmCursorProxy when the mojo connection to the
+ // DRM thread is broken.
+}
+
+void HostDrmDevice::AddGpuThreadObserver(GpuThreadObserver* observer) {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ gpu_thread_observers_.AddObserver(observer);
+ if (IsConnected()) {
+ observer->OnGpuProcessLaunched();
+ observer->OnGpuThreadReady();
+ }
+}
+
+void HostDrmDevice::RemoveGpuThreadObserver(GpuThreadObserver* observer) {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ gpu_thread_observers_.RemoveObserver(observer);
+}
+
+bool HostDrmDevice::IsConnected() {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+
+ // TODO(rjkroege): Need to set to connected_ to false when we lose the Viz
+ // process connection.
+ return connected_;
+}
+
+// Services needed for DrmDisplayHostMananger.
+void HostDrmDevice::RegisterHandlerForDrmDisplayHostManager(
+ DrmDisplayHostManager* handler) {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ display_manager_ = handler;
+}
+
+void HostDrmDevice::UnRegisterHandlerForDrmDisplayHostManager() {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ display_manager_ = nullptr;
+}
+
+bool HostDrmDevice::GpuCreateWindow(gfx::AcceleratedWidget widget) {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ if (!IsConnected())
+ return false;
+
+ drm_device_ptr_->CreateWindow(widget);
+ return true;
+}
+
+bool HostDrmDevice::GpuDestroyWindow(gfx::AcceleratedWidget widget) {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ if (!IsConnected())
+ return false;
+
+ drm_device_ptr_->DestroyWindow(widget);
+ return true;
+}
+
+bool HostDrmDevice::GpuWindowBoundsChanged(gfx::AcceleratedWidget widget,
+ const gfx::Rect& bounds) {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ if (!IsConnected())
+ return false;
+
+ drm_device_ptr_->SetWindowBounds(widget, bounds);
+ return true;
+}
+
+// Services needed for DrmOverlayManager.
+void HostDrmDevice::RegisterHandlerForDrmOverlayManager(
+ DrmOverlayManager* handler) {
+ // TODO(rjkroege): Permit overlay manager to run in viz when the display
+ // compositor runs in viz.
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ overlay_manager_ = handler;
+}
+
+void HostDrmDevice::UnRegisterHandlerForDrmOverlayManager() {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ overlay_manager_ = nullptr;
+}
+
+bool HostDrmDevice::GpuCheckOverlayCapabilities(
+ gfx::AcceleratedWidget widget,
+ const OverlaySurfaceCandidateList& overlays) {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ if (!IsConnected())
+ return false;
+
+ auto callback =
+ base::BindOnce(&HostDrmDevice::GpuCheckOverlayCapabilitiesCallback,
+ weak_ptr_factory_.GetWeakPtr());
+
+ drm_device_ptr_->CheckOverlayCapabilities(widget, overlays,
+ std::move(callback));
+ return true;
+}
+
+bool HostDrmDevice::GpuRefreshNativeDisplays() {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ if (!IsConnected())
+ return false;
+ auto callback =
+ base::BindOnce(&HostDrmDevice::GpuRefreshNativeDisplaysCallback,
+ weak_ptr_factory_.GetWeakPtr());
+ drm_device_ptr_->RefreshNativeDisplays(std::move(callback));
+ return true;
+}
+
+bool HostDrmDevice::GpuConfigureNativeDisplay(int64_t id,
+ const DisplayMode_Params& pmode,
+ const gfx::Point& origin) {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ if (!IsConnected())
+ return false;
+
+ // TODO(rjkroege): Remove the use of mode here.
+ auto mode = CreateDisplayModeFromParams(pmode);
+ auto callback =
+ base::BindOnce(&HostDrmDevice::GpuConfigureNativeDisplayCallback,
+ weak_ptr_factory_.GetWeakPtr());
+
+ drm_device_ptr_->ConfigureNativeDisplay(id, std::move(mode), origin,
+ std::move(callback));
+ return true;
+}
+
+bool HostDrmDevice::GpuDisableNativeDisplay(int64_t id) {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ if (!IsConnected())
+ return false;
+ auto callback =
+ base::BindOnce(&HostDrmDevice::GpuDisableNativeDisplayCallback,
+ weak_ptr_factory_.GetWeakPtr());
+ drm_device_ptr_->DisableNativeDisplay(id, std::move(callback));
+ return true;
+}
+
+bool HostDrmDevice::GpuTakeDisplayControl() {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ if (!IsConnected())
+ return false;
+ auto callback = base::BindOnce(&HostDrmDevice::GpuTakeDisplayControlCallback,
+ weak_ptr_factory_.GetWeakPtr());
+ drm_device_ptr_->TakeDisplayControl(std::move(callback));
+ return true;
+}
+
+bool HostDrmDevice::GpuRelinquishDisplayControl() {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ if (!IsConnected())
+ return false;
+ auto callback =
+ base::BindOnce(&HostDrmDevice::GpuRelinquishDisplayControlCallback,
+ weak_ptr_factory_.GetWeakPtr());
+ drm_device_ptr_->TakeDisplayControl(std::move(callback));
+ return true;
+}
+
+bool HostDrmDevice::GpuAddGraphicsDevice(const base::FilePath& path,
+ base::ScopedFD fd) {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ if (!IsConnected())
+ return false;
+ base::File file(fd.release());
+ drm_device_ptr_->AddGraphicsDevice(path, std::move(file));
+ return true;
+}
+
+bool HostDrmDevice::GpuRemoveGraphicsDevice(const base::FilePath& path) {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ if (!IsConnected())
+ return false;
+ drm_device_ptr_->RemoveGraphicsDevice(std::move(path));
+ return true;
+}
+
+bool HostDrmDevice::GpuGetHDCPState(int64_t display_id) {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ if (!IsConnected())
+ return false;
+ auto callback = base::BindOnce(&HostDrmDevice::GpuGetHDCPStateCallback,
+ weak_ptr_factory_.GetWeakPtr());
+ drm_device_ptr_->GetHDCPState(display_id, std::move(callback));
+ return true;
+}
+
+bool HostDrmDevice::GpuSetHDCPState(int64_t display_id,
+ display::HDCPState state) {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ if (!IsConnected())
+ return false;
+ auto callback = base::BindOnce(&HostDrmDevice::GpuSetHDCPStateCallback,
+ weak_ptr_factory_.GetWeakPtr());
+ drm_device_ptr_->SetHDCPState(display_id, state, std::move(callback));
+ return true;
+}
+
+bool HostDrmDevice::GpuSetColorCorrection(
+ int64_t id,
+ const std::vector<display::GammaRampRGBEntry>& degamma_lut,
+ const std::vector<display::GammaRampRGBEntry>& gamma_lut,
+ const std::vector<float>& correction_matrix) {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ if (!IsConnected())
+ return false;
+
+ drm_device_ptr_->SetColorCorrection(id, degamma_lut, gamma_lut,
+ correction_matrix);
+
+ return true;
+}
+
+void HostDrmDevice::GpuCheckOverlayCapabilitiesCallback(
+ const gfx::AcceleratedWidget& widget,
+ const OverlaySurfaceCandidateList& overlays,
+ const OverlayStatusList& returns) const {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ overlay_manager_->GpuSentOverlayResult(widget, overlays, returns);
+}
+
+void HostDrmDevice::GpuConfigureNativeDisplayCallback(int64_t display_id,
+ bool success) const {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ display_manager_->GpuConfiguredDisplay(display_id, success);
+}
+
+// TODO(rjkroege): Remove the unnecessary conversion back into params.
+void HostDrmDevice::GpuRefreshNativeDisplaysCallback(
+ std::vector<std::unique_ptr<display::DisplaySnapshot>> displays) const {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ display_manager_->GpuHasUpdatedNativeDisplays(
+ CreateParamsFromSnapshot(displays));
+}
+
+void HostDrmDevice::GpuDisableNativeDisplayCallback(int64_t display_id,
+ bool success) const {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ display_manager_->GpuConfiguredDisplay(display_id, success);
+}
+
+void HostDrmDevice::GpuTakeDisplayControlCallback(bool success) const {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ display_manager_->GpuTookDisplayControl(success);
+}
+
+void HostDrmDevice::GpuRelinquishDisplayControlCallback(bool success) const {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ display_manager_->GpuRelinquishedDisplayControl(success);
+}
+
+void HostDrmDevice::GpuGetHDCPStateCallback(int64_t display_id,
+ bool success,
+ display::HDCPState state) const {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ display_manager_->GpuReceivedHDCPState(display_id, success, state);
+}
+
+void HostDrmDevice::GpuSetHDCPStateCallback(int64_t display_id,
+ bool success) const {
+ DCHECK_CALLED_ON_VALID_THREAD(on_window_server_thread_);
+ display_manager_->GpuUpdatedHDCPState(display_id, success);
+}
+
+} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/mus_thread_proxy.h b/chromium/ui/ozone/platform/drm/host/host_drm_device.h
index 63350ba6a54..47c5b18170d 100644
--- a/chromium/ui/ozone/platform/drm/mus_thread_proxy.h
+++ b/chromium/ui/ozone/platform/drm/host/host_drm_device.h
@@ -2,26 +2,23 @@
// 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_MUS_THREAD_PROXY_H_
-#define UI_OZONE_PLATFORM_DRM_MUS_THREAD_PROXY_H_
+#ifndef UI_OZONE_PLATFORM_DRM_HOST_HOST_DRM_DEVICE_H_
+#define UI_OZONE_PLATFORM_DRM_HOST_HOST_DRM_DEVICE_H_
#include "base/callback.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "base/synchronization/lock.h"
+#include "base/threading/thread_checker.h"
#include "ui/gfx/native_widget_types.h"
-#include "ui/ozone/platform/drm/gpu/inter_thread_messaging_proxy.h"
#include "ui/ozone/platform/drm/host/drm_cursor.h"
#include "ui/ozone/platform/drm/host/gpu_thread_adapter.h"
#include "ui/ozone/public/interfaces/device_cursor.mojom.h"
-
-namespace base {
-class SingleThreadTaskRunner;
-}
+#include "ui/ozone/public/interfaces/drm_device.mojom.h"
namespace display {
-class DisplaySnapshotMojo;
+class DisplaySnapshot;
}
namespace service_manager {
@@ -29,32 +26,30 @@ class Connector;
}
namespace ui {
-
class DrmDisplayHostManager;
class DrmOverlayManager;
-class DrmThread;
class GpuThreadObserver;
-class MusThreadProxy;
-
-// In Mus, the window server thread (analogous to Chrome's UI thread), GPU and
-// DRM threads coexist in a single Mus process. The |MusThreadProxy| connects
-// these threads together via cross-thread calls.
-class MusThreadProxy : public GpuThreadAdapter,
- public InterThreadMessagingProxy,
- public DrmCursorProxy {
+
+// This is the Viz host-side library for the DRM device service provided by the
+// viz process.
+class HostDrmDevice : public GpuThreadAdapter {
public:
- MusThreadProxy(DrmCursor* cursor, service_manager::Connector* connector);
- ~MusThreadProxy() override;
+ HostDrmDevice(DrmCursor* cursor, service_manager::Connector* connector);
+ ~HostDrmDevice() override;
+
+ // Start the DRM service. Runs the |OnDrmServiceStartedCallback| when the
+ // service has launched and initiates the remaining startup.
+ void AsyncStartDrmDevice();
+
+ // Blocks until the DRM service has come up. Use this entry point only when
+ // supporting launch of the service where the ozone UI and GPU
+ // reponsibilities are performed by the same underlying thread.
+ void BlockingStartDrmDevice();
- void StartDrmThread();
void ProvideManagers(DrmDisplayHostManager* display_manager,
DrmOverlayManager* overlay_manager);
- // InterThreadMessagingProxy.
- void SetDrmThread(DrmThread* thread) override;
-
- // This is the core functionality. They are invoked when we have a main
- // thread, a gpu thread and we have called initialize on both.
+ // GpuThreadAdapter
void AddGpuThreadObserver(GpuThreadObserver* observer) override;
void RemoveGpuThreadObserver(GpuThreadObserver* observer) override;
bool IsConnected() override;
@@ -68,16 +63,15 @@ class MusThreadProxy : public GpuThreadAdapter,
bool GpuRefreshNativeDisplays() override;
bool GpuRelinquishDisplayControl() override;
bool GpuAddGraphicsDevice(const base::FilePath& path,
- const base::FileDescriptor& fd) override;
+ base::ScopedFD fd) override;
bool GpuRemoveGraphicsDevice(const base::FilePath& path) override;
// Services needed for DrmOverlayManager.
void RegisterHandlerForDrmOverlayManager(DrmOverlayManager* handler) override;
void UnRegisterHandlerForDrmOverlayManager() override;
-
bool GpuCheckOverlayCapabilities(
gfx::AcceleratedWidget widget,
- const std::vector<OverlayCheck_Params>& new_params) override;
+ const OverlaySurfaceCandidateList& new_params) override;
// Services needed by DrmDisplayHost
bool GpuConfigureNativeDisplay(int64_t display_id,
@@ -98,29 +92,21 @@ class MusThreadProxy : public GpuThreadAdapter,
bool GpuWindowBoundsChanged(gfx::AcceleratedWidget widget,
const gfx::Rect& bounds) override;
- // DrmCursorProxy.
- void CursorSet(gfx::AcceleratedWidget window,
- const std::vector<SkBitmap>& bitmaps,
- const gfx::Point& point,
- int frame_delay_ms) override;
- void Move(gfx::AcceleratedWidget window, const gfx::Point& point) override;
- void InitializeOnEvdevIfNecessary() override;
-
private:
+ void OnDrmServiceStartedCallback(bool success);
+ void PollForSingleThreadReady(int previous_delay);
void RunObservers();
- void DispatchObserversFromDrmThread();
void GpuCheckOverlayCapabilitiesCallback(
- gfx::AcceleratedWidget widget,
- const std::vector<OverlayCheck_Params>& overlays,
- const std::vector<OverlayCheckReturn_Params>& returns) const;
+ const gfx::AcceleratedWidget& widget,
+ const OverlaySurfaceCandidateList& overlays,
+ const OverlayStatusList& returns) const;
void GpuConfigureNativeDisplayCallback(int64_t display_id,
bool success) const;
void GpuRefreshNativeDisplaysCallback(
- std::vector<std::unique_ptr<display::DisplaySnapshotMojo>> displays)
- const;
+ std::vector<std::unique_ptr<display::DisplaySnapshot>> displays) const;
void GpuDisableNativeDisplayCallback(int64_t display_id, bool success) const;
void GpuTakeDisplayControlCallback(bool success) const;
void GpuRelinquishDisplayControlCallback(bool success) const;
@@ -129,28 +115,24 @@ class MusThreadProxy : public GpuThreadAdapter,
display::HDCPState state) const;
void GpuSetHDCPStateCallback(int64_t display_id, bool success) const;
- scoped_refptr<base::SingleThreadTaskRunner> ws_task_runner_;
-
- DrmThread* drm_thread_; // Not owned.
-
- // Guards for multi-theaded access to drm_thread_.
- base::Lock lock_;
+ // Mojo implementation of the DrmDevice.
+ ui::ozone::mojom::DrmDevicePtr drm_device_ptr_;
DrmDisplayHostManager* display_manager_; // Not owned.
DrmOverlayManager* overlay_manager_; // Not owned.
DrmCursor* cursor_; // Not owned.
service_manager::Connector* connector_;
+ THREAD_CHECKER(on_window_server_thread_);
+ bool connected_ = false;
base::ObserverList<GpuThreadObserver> gpu_thread_observers_;
- base::ThreadChecker on_window_server_thread_;
-
- base::WeakPtrFactory<MusThreadProxy> weak_ptr_factory_;
+ base::WeakPtrFactory<HostDrmDevice> weak_ptr_factory_;
- DISALLOW_COPY_AND_ASSIGN(MusThreadProxy);
+ DISALLOW_COPY_AND_ASSIGN(HostDrmDevice);
};
} // namespace ui
-#endif // UI_OZONE_PLATFORM_DRM_MUS_THREAD_PROXY_H_
+#endif // UI_OZONE_PLATFORM_DRM_HOST_HOST_DRM_DEVICE_H_
diff --git a/chromium/ui/ozone/platform/drm/mus_thread_proxy.cc b/chromium/ui/ozone/platform/drm/mus_thread_proxy.cc
deleted file mode 100644
index 5a15795de7e..00000000000
--- a/chromium/ui/ozone/platform/drm/mus_thread_proxy.cc
+++ /dev/null
@@ -1,444 +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/mus_thread_proxy.h"
-
-#include "base/bind.h"
-#include "base/single_thread_task_runner.h"
-#include "base/task_runner.h"
-#include "base/threading/thread_task_runner_handle.h"
-#include "ui/display/types/display_snapshot_mojo.h"
-#include "ui/ozone/platform/drm/common/drm_util.h"
-#include "ui/ozone/platform/drm/cursor_proxy_mojo.h"
-#include "ui/ozone/platform/drm/gpu/drm_thread.h"
-#include "ui/ozone/platform/drm/gpu/proxy_helpers.h"
-#include "ui/ozone/platform/drm/host/drm_display_host_manager.h"
-#include "ui/ozone/platform/drm/host/drm_overlay_manager.h"
-
-namespace ui {
-
-namespace {
-
-// Forwarding proxy to handle ownership semantics.
-class CursorProxyThread : public DrmCursorProxy {
- public:
- explicit CursorProxyThread(MusThreadProxy* mus_thread_proxy);
- ~CursorProxyThread() override;
-
- private:
- // DrmCursorProxy.
- void CursorSet(gfx::AcceleratedWidget window,
- const std::vector<SkBitmap>& bitmaps,
- const gfx::Point& point,
- int frame_delay_ms) override;
- void Move(gfx::AcceleratedWidget window, const gfx::Point& point) override;
- void InitializeOnEvdevIfNecessary() override;
- MusThreadProxy* const mus_thread_proxy_; // Not owned.
- DISALLOW_COPY_AND_ASSIGN(CursorProxyThread);
-};
-
-CursorProxyThread::CursorProxyThread(MusThreadProxy* mus_thread_proxy)
- : mus_thread_proxy_(mus_thread_proxy) {}
-CursorProxyThread::~CursorProxyThread() {}
-
-void CursorProxyThread::CursorSet(gfx::AcceleratedWidget window,
- const std::vector<SkBitmap>& bitmaps,
- const gfx::Point& point,
- int frame_delay_ms) {
- mus_thread_proxy_->CursorSet(window, bitmaps, point, frame_delay_ms);
-}
-void CursorProxyThread::Move(gfx::AcceleratedWidget window,
- const gfx::Point& point) {
- mus_thread_proxy_->Move(window, point);
-}
-void CursorProxyThread::InitializeOnEvdevIfNecessary() {
- mus_thread_proxy_->InitializeOnEvdevIfNecessary();
-}
-
-} // namespace
-
-MusThreadProxy::MusThreadProxy(DrmCursor* cursor,
- service_manager::Connector* connector)
- : ws_task_runner_(base::ThreadTaskRunnerHandle::Get()),
- drm_thread_(nullptr),
- cursor_(cursor),
- connector_(connector),
- weak_ptr_factory_(this) {}
-
-MusThreadProxy::~MusThreadProxy() {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- for (GpuThreadObserver& observer : gpu_thread_observers_)
- observer.OnGpuThreadRetired();
-}
-
-// This is configured on the GPU thread.
-void MusThreadProxy::SetDrmThread(DrmThread* thread) {
- base::AutoLock acquire(lock_);
- drm_thread_ = thread;
-}
-
-void MusThreadProxy::ProvideManagers(DrmDisplayHostManager* display_manager,
- DrmOverlayManager* overlay_manager) {
- display_manager_ = display_manager;
- overlay_manager_ = overlay_manager;
-}
-
-// Runs on Gpu thread.
-void MusThreadProxy::StartDrmThread() {
- DCHECK(drm_thread_);
- drm_thread_->Start();
-
- drm_thread_->task_runner()->PostTask(
- FROM_HERE, base::Bind(&MusThreadProxy::DispatchObserversFromDrmThread,
- base::Unretained(this)));
-}
-
-void MusThreadProxy::DispatchObserversFromDrmThread() {
- ws_task_runner_->PostTask(FROM_HERE, base::Bind(&MusThreadProxy::RunObservers,
- base::Unretained(this)));
-}
-
-void MusThreadProxy::RunObservers() {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- for (GpuThreadObserver& observer : gpu_thread_observers_) {
- // TODO(rjkroege): This needs to be different when gpu process split
- // happens.
- observer.OnGpuProcessLaunched();
- observer.OnGpuThreadReady();
- }
-
- // The cursor is special since it will process input events on the IO thread
- // and can by-pass the UI thread. This means that we need to special case it
- // and notify it after all other observers/handlers are notified.
- if (connector_ == nullptr) {
- // CursorProxyThread does not need to use delegate because the non-mojo
- // MusThreadProxy is only used in tests that do not operate the cursor.
- // Future refactoring will unify the mojo and in-process modes.
- cursor_->SetDrmCursorProxy(base::MakeUnique<CursorProxyThread>(this));
- } else {
- cursor_->SetDrmCursorProxy(base::MakeUnique<CursorProxyMojo>(connector_));
- }
-
- // TODO(rjkroege): Call ResetDrmCursorProxy when the mojo connection to the
- // DRM thread is broken.
-}
-
-void MusThreadProxy::AddGpuThreadObserver(GpuThreadObserver* observer) {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
-
- gpu_thread_observers_.AddObserver(observer);
- if (IsConnected()) {
- // TODO(rjkroege): This needs to be different when gpu process split
- // happens.
- observer->OnGpuProcessLaunched();
- observer->OnGpuThreadReady();
- }
-}
-
-void MusThreadProxy::RemoveGpuThreadObserver(GpuThreadObserver* observer) {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- gpu_thread_observers_.RemoveObserver(observer);
-}
-
-bool MusThreadProxy::IsConnected() {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- base::AutoLock acquire(lock_);
- if (drm_thread_)
- return drm_thread_->IsRunning();
- return false;
-}
-
-// Services needed for DrmDisplayHostMananger.
-void MusThreadProxy::RegisterHandlerForDrmDisplayHostManager(
- DrmDisplayHostManager* handler) {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- display_manager_ = handler;
-}
-
-void MusThreadProxy::UnRegisterHandlerForDrmDisplayHostManager() {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- display_manager_ = nullptr;
-}
-
-bool MusThreadProxy::GpuCreateWindow(gfx::AcceleratedWidget widget) {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- if (!drm_thread_ || !drm_thread_->IsRunning())
- return false;
- drm_thread_->task_runner()->PostTask(
- FROM_HERE, base::Bind(&DrmThread::CreateWindow,
- base::Unretained(drm_thread_), widget));
- return true;
-}
-
-bool MusThreadProxy::GpuDestroyWindow(gfx::AcceleratedWidget widget) {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- if (!drm_thread_ || !drm_thread_->IsRunning())
- return false;
- drm_thread_->task_runner()->PostTask(
- FROM_HERE, base::Bind(&DrmThread::DestroyWindow,
- base::Unretained(drm_thread_), widget));
- return true;
-}
-
-bool MusThreadProxy::GpuWindowBoundsChanged(gfx::AcceleratedWidget widget,
- const gfx::Rect& bounds) {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- if (!drm_thread_ || !drm_thread_->IsRunning())
- return false;
- drm_thread_->task_runner()->PostTask(
- FROM_HERE, base::Bind(&DrmThread::SetWindowBounds,
- base::Unretained(drm_thread_), widget, bounds));
- return true;
-}
-
-// Services needed for DrmCursorProxy.
-void MusThreadProxy::CursorSet(gfx::AcceleratedWidget widget,
- const std::vector<SkBitmap>& bitmaps,
- const gfx::Point& location,
- int frame_delay_ms) {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- if (!drm_thread_ || !drm_thread_->IsRunning())
- return;
- drm_thread_->task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&DrmThread::SetCursor, base::Unretained(drm_thread_), widget,
- bitmaps, location, frame_delay_ms));
-}
-
-void MusThreadProxy::Move(gfx::AcceleratedWidget widget,
- const gfx::Point& location) {
- // NOTE: Input events skip the main thread to avoid jank.
- if (!drm_thread_ || !drm_thread_->IsRunning())
- return;
- drm_thread_->task_runner()->PostTask(
- FROM_HERE, base::Bind(&DrmThread::MoveCursor,
- base::Unretained(drm_thread_), widget, location));
-}
-
-void MusThreadProxy::InitializeOnEvdevIfNecessary() {}
-
-// Services needed for DrmOverlayManager.
-void MusThreadProxy::RegisterHandlerForDrmOverlayManager(
- DrmOverlayManager* handler) {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- overlay_manager_ = handler;
-}
-
-void MusThreadProxy::UnRegisterHandlerForDrmOverlayManager() {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- overlay_manager_ = nullptr;
-}
-
-bool MusThreadProxy::GpuCheckOverlayCapabilities(
- gfx::AcceleratedWidget widget,
- const std::vector<OverlayCheck_Params>& overlays) {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- if (!drm_thread_ || !drm_thread_->IsRunning())
- return false;
- auto callback =
- base::BindOnce(&MusThreadProxy::GpuCheckOverlayCapabilitiesCallback,
- weak_ptr_factory_.GetWeakPtr());
- auto safe_callback = CreateSafeOnceCallback(std::move(callback));
- drm_thread_->task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&DrmThread::CheckOverlayCapabilities,
- base::Unretained(drm_thread_), widget, overlays,
- std::move(safe_callback)));
- return true;
-}
-
-bool MusThreadProxy::GpuRefreshNativeDisplays() {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- if (!drm_thread_ || !drm_thread_->IsRunning())
- return false;
- auto callback =
- base::BindOnce(&MusThreadProxy::GpuRefreshNativeDisplaysCallback,
- weak_ptr_factory_.GetWeakPtr());
- auto safe_callback = CreateSafeOnceCallback(std::move(callback));
- drm_thread_->task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&DrmThread::RefreshNativeDisplays,
- base::Unretained(drm_thread_), std::move(safe_callback)));
- return true;
-}
-
-bool MusThreadProxy::GpuConfigureNativeDisplay(int64_t id,
- const DisplayMode_Params& pmode,
- const gfx::Point& origin) {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- if (!drm_thread_ || !drm_thread_->IsRunning())
- return false;
-
- auto mode = CreateDisplayModeFromParams(pmode);
- auto callback =
- base::BindOnce(&MusThreadProxy::GpuConfigureNativeDisplayCallback,
- weak_ptr_factory_.GetWeakPtr());
- auto safe_callback = CreateSafeOnceCallback(std::move(callback));
- drm_thread_->task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&DrmThread::ConfigureNativeDisplay,
- base::Unretained(drm_thread_), id, std::move(mode), origin,
- std::move(safe_callback)));
- return true;
-}
-
-bool MusThreadProxy::GpuDisableNativeDisplay(int64_t id) {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- if (!drm_thread_ || !drm_thread_->IsRunning())
- return false;
- auto callback =
- base::BindOnce(&MusThreadProxy::GpuDisableNativeDisplayCallback,
- weak_ptr_factory_.GetWeakPtr());
- auto safe_callback = CreateSafeOnceCallback(std::move(callback));
- drm_thread_->task_runner()->PostTask(
- FROM_HERE, base::BindOnce(&DrmThread::DisableNativeDisplay,
- base::Unretained(drm_thread_), id,
- std::move(safe_callback)));
- return true;
-}
-
-bool MusThreadProxy::GpuTakeDisplayControl() {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- if (!drm_thread_ || !drm_thread_->IsRunning())
- return false;
- auto callback = base::BindOnce(&MusThreadProxy::GpuTakeDisplayControlCallback,
- weak_ptr_factory_.GetWeakPtr());
- auto safe_callback = CreateSafeOnceCallback(std::move(callback));
- drm_thread_->task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&DrmThread::TakeDisplayControl,
- base::Unretained(drm_thread_), std::move(safe_callback)));
- return true;
-}
-
-bool MusThreadProxy::GpuRelinquishDisplayControl() {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- if (!drm_thread_ || !drm_thread_->IsRunning())
- return false;
- auto callback =
- base::BindOnce(&MusThreadProxy::GpuRelinquishDisplayControlCallback,
- weak_ptr_factory_.GetWeakPtr());
- auto safe_callback = CreateSafeOnceCallback(std::move(callback));
- drm_thread_->task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&DrmThread::RelinquishDisplayControl,
- base::Unretained(drm_thread_), std::move(safe_callback)));
- return true;
-}
-
-bool MusThreadProxy::GpuAddGraphicsDevice(const base::FilePath& path,
- const base::FileDescriptor& fd) {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- if (!drm_thread_ || !drm_thread_->IsRunning())
- return false;
- drm_thread_->task_runner()->PostTask(
- FROM_HERE, base::Bind(&DrmThread::AddGraphicsDevice,
- base::Unretained(drm_thread_), path, fd));
- return true;
-}
-
-bool MusThreadProxy::GpuRemoveGraphicsDevice(const base::FilePath& path) {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- if (!drm_thread_ || !drm_thread_->IsRunning())
- return false;
- drm_thread_->task_runner()->PostTask(
- FROM_HERE, base::Bind(&DrmThread::RemoveGraphicsDevice,
- base::Unretained(drm_thread_), path));
- return true;
-}
-
-bool MusThreadProxy::GpuGetHDCPState(int64_t display_id) {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- if (!drm_thread_ || !drm_thread_->IsRunning())
- return false;
- auto callback = base::BindOnce(&MusThreadProxy::GpuGetHDCPStateCallback,
- weak_ptr_factory_.GetWeakPtr());
- auto safe_callback = CreateSafeOnceCallback(std::move(callback));
- drm_thread_->task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&DrmThread::GetHDCPState, base::Unretained(drm_thread_),
- display_id, std::move(safe_callback)));
- return true;
-}
-
-bool MusThreadProxy::GpuSetHDCPState(int64_t display_id,
- display::HDCPState state) {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- if (!drm_thread_ || !drm_thread_->IsRunning())
- return false;
- auto callback = base::BindOnce(&MusThreadProxy::GpuSetHDCPStateCallback,
- weak_ptr_factory_.GetWeakPtr());
- auto safe_callback = CreateSafeOnceCallback(std::move(callback));
- drm_thread_->task_runner()->PostTask(
- FROM_HERE,
- base::BindOnce(&DrmThread::SetHDCPState, base::Unretained(drm_thread_),
- display_id, state, std::move(safe_callback)));
- return true;
-}
-
-bool MusThreadProxy::GpuSetColorCorrection(
- int64_t id,
- const std::vector<display::GammaRampRGBEntry>& degamma_lut,
- const std::vector<display::GammaRampRGBEntry>& gamma_lut,
- const std::vector<float>& correction_matrix) {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- if (!drm_thread_ || !drm_thread_->IsRunning())
- return false;
- drm_thread_->task_runner()->PostTask(
- FROM_HERE,
- base::Bind(&DrmThread::SetColorCorrection, base::Unretained(drm_thread_),
- id, degamma_lut, gamma_lut, correction_matrix));
- return true;
-}
-
-void MusThreadProxy::GpuCheckOverlayCapabilitiesCallback(
- gfx::AcceleratedWidget widget,
- const std::vector<OverlayCheck_Params>& overlays,
- const std::vector<OverlayCheckReturn_Params>& returns) const {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- overlay_manager_->GpuSentOverlayResult(widget, overlays, returns);
-}
-
-void MusThreadProxy::GpuConfigureNativeDisplayCallback(int64_t display_id,
- bool success) const {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- display_manager_->GpuConfiguredDisplay(display_id, success);
-}
-
-void MusThreadProxy::GpuRefreshNativeDisplaysCallback(
- std::vector<std::unique_ptr<display::DisplaySnapshotMojo>> displays) const {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- display_manager_->GpuHasUpdatedNativeDisplays(
- CreateParamsFromSnapshot(displays));
-}
-
-void MusThreadProxy::GpuDisableNativeDisplayCallback(int64_t display_id,
- bool success) const {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- display_manager_->GpuConfiguredDisplay(display_id, success);
-}
-
-void MusThreadProxy::GpuTakeDisplayControlCallback(bool success) const {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- display_manager_->GpuTookDisplayControl(success);
-}
-
-void MusThreadProxy::GpuRelinquishDisplayControlCallback(bool success) const {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- display_manager_->GpuRelinquishedDisplayControl(success);
-}
-
-void MusThreadProxy::GpuGetHDCPStateCallback(int64_t display_id,
- bool success,
- display::HDCPState state) const {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- display_manager_->GpuReceivedHDCPState(display_id, success, state);
-}
-
-void MusThreadProxy::GpuSetHDCPStateCallback(int64_t display_id,
- bool success) const {
- DCHECK(on_window_server_thread_.CalledOnValidThread());
- display_manager_->GpuUpdatedHDCPState(display_id, success);
-}
-
-} // namespace ui
diff --git a/chromium/ui/ozone/platform/drm/ozone_platform_gbm.cc b/chromium/ui/ozone/platform/drm/ozone_platform_gbm.cc
index 109c5a97ed2..cc0bb2f5720 100644
--- a/chromium/ui/ozone/platform/drm/ozone_platform_gbm.cc
+++ b/chromium/ui/ozone/platform/drm/ozone_platform_gbm.cc
@@ -17,6 +17,8 @@
#include "base/command_line.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
+#include "base/memory/weak_ptr.h"
+#include "base/threading/platform_thread.h"
#include "base/threading/thread_task_runner_handle.h"
#include "services/service_manager/public/cpp/binder_registry.h"
#include "ui/base/cursor/ozone/bitmap_cursor_factory_ozone.h"
@@ -25,7 +27,6 @@
#include "ui/events/ozone/evdev/event_factory_evdev.h"
#include "ui/events/ozone/layout/keyboard_layout_engine_manager.h"
#include "ui/ozone/platform/drm/common/drm_util.h"
-#include "ui/ozone/platform/drm/cursor_proxy_mojo.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_gpu_display_manager.h"
@@ -42,7 +43,7 @@
#include "ui/ozone/platform/drm/host/drm_overlay_manager.h"
#include "ui/ozone/platform/drm/host/drm_window_host.h"
#include "ui/ozone/platform/drm/host/drm_window_host_manager.h"
-#include "ui/ozone/platform/drm/mus_thread_proxy.h"
+#include "ui/ozone/platform/drm/host/host_drm_device.h"
#include "ui/ozone/public/cursor_factory_ozone.h"
#include "ui/ozone/public/gpu_platform_support_host.h"
#include "ui/ozone/public/ozone_platform.h"
@@ -81,7 +82,8 @@ class GlApiLoader {
class OzonePlatformGbm : public OzonePlatform {
public:
- OzonePlatformGbm() : using_mojo_(false), single_process_(false) {}
+ OzonePlatformGbm()
+ : using_mojo_(false), single_process_(false), weak_factory_(this) {}
~OzonePlatformGbm() override {}
// OzonePlatform:
@@ -106,26 +108,45 @@ class OzonePlatformGbm : public OzonePlatform {
std::unique_ptr<SystemInputInjector> CreateSystemInputInjector() override {
return event_factory_ozone_->CreateSystemInputInjector();
}
+
void AddInterfaces(
service_manager::BinderRegistryWithArgs<
const service_manager::BindSourceInfo&>* registry) override {
registry->AddInterface<ozone::mojom::DeviceCursor>(
- base::Bind(&OzonePlatformGbm::Create, base::Unretained(this)),
+ base::Bind(&OzonePlatformGbm::CreateDeviceCursorBinding,
+ weak_factory_.GetWeakPtr()),
+ gpu_task_runner_);
+
+ registry->AddInterface<ozone::mojom::DrmDevice>(
+ base::Bind(&OzonePlatformGbm::CreateDrmDeviceBinding,
+ weak_factory_.GetWeakPtr()),
gpu_task_runner_);
}
- void Create(ozone::mojom::DeviceCursorRequest request,
- const service_manager::BindSourceInfo& source_info) {
+ void CreateDeviceCursorBinding(
+ ozone::mojom::DeviceCursorRequest request,
+ const service_manager::BindSourceInfo& source_info) {
if (drm_thread_proxy_)
- drm_thread_proxy_->AddBinding(std::move(request));
+ drm_thread_proxy_->AddBindingCursorDevice(std::move(request));
else
pending_cursor_requests_.push_back(std::move(request));
}
+
+ // service_manager::InterfaceFactory<ozone::mojom::DrmDevice>:
+ void CreateDrmDeviceBinding(
+ ozone::mojom::DrmDeviceRequest request,
+ const service_manager::BindSourceInfo& source_info) {
+ if (drm_thread_proxy_)
+ drm_thread_proxy_->AddBindingDrmDevice(std::move(request));
+ else
+ pending_gpu_adapter_requests_.push_back(std::move(request));
+ }
+
std::unique_ptr<PlatformWindow> CreatePlatformWindow(
PlatformWindowDelegate* delegate,
const gfx::Rect& bounds) override {
GpuThreadAdapter* adapter = gpu_platform_support_host_.get();
if (using_mojo_ || single_process_) {
- adapter = mus_thread_proxy_.get();
+ adapter = host_drm_device_.get();
}
std::unique_ptr<DrmWindowHost> platform_window(new DrmWindowHost(
@@ -140,18 +161,18 @@ class OzonePlatformGbm : public OzonePlatform {
}
void InitializeUI(const InitParams& args) override {
// Ozone drm can operate in three modes configured at runtime:
- // 1. legacy mode where browser and gpu components communicate
+ // 1. legacy mode where host and viz components communicate
// via param traits IPC.
- // 2. single-process mode where browser and gpu components
- // communicate via PostTask.
- // 3. mojo mode where browser and gpu components communicate
+ // 2. single-process mode where host and viz components
+ // communicate via in-process mojo.
+ // 3. multi-process mode where host and viz components communicate
// via mojo IPC.
- // Currently, mojo mode uses mojo in a single process but this is
- // an interim implementation detail that will be eliminated in a
- // future CL.
single_process_ = args.single_process;
using_mojo_ = args.connector != nullptr;
- DCHECK(!(using_mojo_ && single_process_));
+ host_thread_ = base::PlatformThread::CurrentRef();
+
+ DCHECK(!(using_mojo_ && !single_process_))
+ << "Multiprocess Mojo is not supported yet.";
device_manager_ = CreateDeviceManager();
window_manager_.reset(new DrmWindowHostManager());
@@ -170,18 +191,13 @@ class OzonePlatformGbm : public OzonePlatform {
GpuThreadAdapter* adapter;
- // TODO(rjkroege): Once mus is split, only do this for single_process.
- if (single_process_ || using_mojo_)
+ if (single_process_)
gl_api_loader_.reset(new GlApiLoader());
if (using_mojo_) {
- mus_thread_proxy_ =
- base::MakeUnique<MusThreadProxy>(cursor_.get(), args.connector);
- adapter = mus_thread_proxy_.get();
- } else if (single_process_) {
- mus_thread_proxy_ =
- base::MakeUnique<MusThreadProxy>(cursor_.get(), nullptr);
- adapter = mus_thread_proxy_.get();
+ host_drm_device_ =
+ base::MakeUnique<HostDrmDevice>(cursor_.get(), args.connector);
+ adapter = host_drm_device_.get();
} else {
gpu_platform_support_host_.reset(
new DrmGpuPlatformSupportHost(cursor_.get()));
@@ -195,24 +211,27 @@ class OzonePlatformGbm : public OzonePlatform {
event_factory_ozone_->input_controller()));
cursor_factory_ozone_.reset(new BitmapCursorFactoryOzone);
- if (using_mojo_ || single_process_) {
- mus_thread_proxy_->ProvideManagers(display_manager_.get(),
- overlay_manager_.get());
+ if (using_mojo_) {
+ host_drm_device_->ProvideManagers(display_manager_.get(),
+ overlay_manager_.get());
+ host_drm_device_->AsyncStartDrmDevice();
}
}
+
void InitializeGPU(const InitParams& args) override {
// TODO(rjkroege): services/ui should initialize this with a connector.
// However, in-progress refactorings in services/ui make it difficult to
// require this at present. Set using_mojo_ like below once this is
// complete.
+ // TODO(rjk): Make it possible to turn this on.
// using_mojo_ = args.connector != nullptr;
-
gpu_task_runner_ = base::ThreadTaskRunnerHandle::Get();
- InterThreadMessagingProxy* itmp;
- if (using_mojo_ || single_process_) {
- itmp = mus_thread_proxy_.get();
- } else {
+
+ if (!single_process_)
gl_api_loader_.reset(new GlApiLoader());
+
+ InterThreadMessagingProxy* itmp;
+ if (!using_mojo_) {
scoped_refptr<DrmThreadMessageProxy> message_proxy(
new DrmThreadMessageProxy());
itmp = message_proxy.get();
@@ -222,40 +241,77 @@ class OzonePlatformGbm : public OzonePlatform {
// NOTE: Can't start the thread here since this is called before sandbox
// initialization in multi-process Chrome. In mus, we start the DRM thread.
drm_thread_proxy_.reset(new DrmThreadProxy());
- drm_thread_proxy_->BindThreadIntoMessagingProxy(itmp);
surface_factory_.reset(new GbmSurfaceFactory(drm_thread_proxy_.get()));
- if (using_mojo_ || single_process_) {
- mus_thread_proxy_->StartDrmThread();
+ if (!using_mojo_) {
+ drm_thread_proxy_->BindThreadIntoMessagingProxy(itmp);
+ } else {
+ drm_thread_proxy_->StartDrmThread();
}
+
+ // When the viz process (and hence the gpu portion of ozone/gbm) is
+ // operating in a single process, the AddInterfaces method is best
+ // invoked before the GPU thread launches. As a result, requests to add
+ // mojom bindings to the as yet un-launched service will fail so we queue
+ // incoming binding requests until the GPU thread is running and play them
+ // back here.
for (auto& request : pending_cursor_requests_)
- drm_thread_proxy_->AddBinding(std::move(request));
+ drm_thread_proxy_->AddBindingCursorDevice(std::move(request));
pending_cursor_requests_.clear();
+ for (auto& request : pending_gpu_adapter_requests_)
+ drm_thread_proxy_->AddBindingDrmDevice(std::move(request));
+ pending_gpu_adapter_requests_.clear();
+
+ // If InitializeGPU and InitializeUI are invoked on the same thread, startup
+ // sequencing is complicated because tasks are queued on the unbound mojo
+ // pipe connecting the UI (the host) to the DRM thread before the DRM thread
+ // is launched above. Special case this sequence vis the
+ // BlockingStartDrmDevice API.
+ // TODO(rjkroege): In a future when we have completed splitting Viz, it will
+ // be possible to simplify this logic.
+ if (using_mojo_ && single_process_ &&
+ host_thread_ == base::PlatformThread::CurrentRef()) {
+ CHECK(host_drm_device_)
+ << "Mojo single-process mode requires a HostDrmDevice.";
+ host_drm_device_->BlockingStartDrmDevice();
+ }
}
private:
bool using_mojo_;
bool single_process_;
-
- // Bridges the DRM, GPU and main threads in mus. This must be destroyed last.
- std::unique_ptr<MusThreadProxy> mus_thread_proxy_;
+ base::PlatformThreadRef host_thread_;
// Objects in the GPU process.
std::unique_ptr<DrmThreadProxy> drm_thread_proxy_;
std::unique_ptr<GlApiLoader> gl_api_loader_;
std::unique_ptr<GbmSurfaceFactory> surface_factory_;
scoped_refptr<IPC::MessageFilter> gpu_message_filter_;
- // TODO(sad): Once the mus gpu process split happens, this can go away.
- std::vector<ozone::mojom::DeviceCursorRequest> pending_cursor_requests_;
scoped_refptr<base::SingleThreadTaskRunner> gpu_task_runner_;
+ // TODO(rjkroege,sadrul): Provide a more elegant solution for this issue when
+ // running in single process mode.
+ std::vector<ozone::mojom::DeviceCursorRequest> pending_cursor_requests_;
+ std::vector<ozone::mojom::DrmDeviceRequest> pending_gpu_adapter_requests_;
+
+ // gpu_platform_support_host_ is the IPC bridge to the GPU process while
+ // host_drm_device_ is the mojo bridge to the Viz process. Only one can be in
+ // use at any time.
+ // TODO(rjkroege): Remove gpu_platform_support_host_ once ozone/drm with mojo
+ // has reached the stable channel.
+ // A raw pointer to either |gpu_platform_support_host_| or |host_drm_device_|
+ // is passed to |display_manager_| and |overlay_manager_| in IntializeUI.
+ // To avoid a use after free, the following two members should be declared
+ // before the two managers, so that they're deleted after them.
+ std::unique_ptr<DrmGpuPlatformSupportHost> gpu_platform_support_host_;
+ std::unique_ptr<HostDrmDevice> host_drm_device_;
+
// Objects in the Browser process.
std::unique_ptr<DeviceManager> device_manager_;
std::unique_ptr<BitmapCursorFactoryOzone> cursor_factory_ozone_;
std::unique_ptr<DrmWindowHostManager> window_manager_;
std::unique_ptr<DrmCursor> cursor_;
std::unique_ptr<EventFactoryEvdev> event_factory_ozone_;
- std::unique_ptr<DrmGpuPlatformSupportHost> gpu_platform_support_host_;
std::unique_ptr<DrmDisplayHostManager> display_manager_;
std::unique_ptr<DrmOverlayManager> overlay_manager_;
@@ -263,6 +319,8 @@ class OzonePlatformGbm : public OzonePlatform {
XkbEvdevCodes xkb_evdev_code_converter_;
#endif
+ base::WeakPtrFactory<OzonePlatformGbm> weak_factory_;
+
DISALLOW_COPY_AND_ASSIGN(OzonePlatformGbm);
};
diff --git a/chromium/ui/ozone/platform/headless/headless_surface_factory.cc b/chromium/ui/ozone/platform/headless/headless_surface_factory.cc
index d3c9f35a05f..40583a3527a 100644
--- a/chromium/ui/ozone/platform/headless/headless_surface_factory.cc
+++ b/chromium/ui/ozone/platform/headless/headless_surface_factory.cc
@@ -10,6 +10,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/task_scheduler/post_task.h"
+#include "build/build_config.h"
#include "third_party/skia/include/core/SkCanvas.h"
#include "third_party/skia/include/core/SkSurface.h"
#include "ui/gfx/codec/png_codec.h"
@@ -108,14 +109,21 @@ HeadlessSurfaceFactory::HeadlessSurfaceFactory()
HeadlessSurfaceFactory::HeadlessSurfaceFactory(
HeadlessWindowManager* window_manager)
- : window_manager_(window_manager),
- osmesa_implementation_(base::MakeUnique<GLOzoneOSMesa>()) {}
+ : window_manager_(window_manager) {
+#if !defined(OS_FUCHSIA)
+ osmesa_implementation_ = base::MakeUnique<GLOzoneOSMesa>();
+#endif
+}
HeadlessSurfaceFactory::~HeadlessSurfaceFactory() {}
std::vector<gl::GLImplementation>
HeadlessSurfaceFactory::GetAllowedGLImplementations() {
+#if defined(OS_FUCHSIA)
+ return std::vector<gl::GLImplementation>{gl::kGLImplementationStubGL};
+#else
return std::vector<gl::GLImplementation>{gl::kGLImplementationOSMesaGL};
+#endif
}
GLOzone* HeadlessSurfaceFactory::GetGLOzone(
diff --git a/chromium/ui/ozone/platform/headless/headless_window_manager.h b/chromium/ui/ozone/platform/headless/headless_window_manager.h
index d57f091e888..f0ee9120034 100644
--- a/chromium/ui/ozone/platform/headless/headless_window_manager.h
+++ b/chromium/ui/ozone/platform/headless/headless_window_manager.h
@@ -9,8 +9,8 @@
#include <memory>
+#include "base/containers/id_map.h"
#include "base/files/file_path.h"
-#include "base/id_map.h"
#include "base/macros.h"
#include "base/threading/thread_checker.h"
#include "ui/gfx/native_widget_types.h"
@@ -43,7 +43,7 @@ class HeadlessWindowManager {
private:
base::FilePath location_;
- IDMap<HeadlessWindow*> windows_;
+ base::IDMap<HeadlessWindow*> windows_;
base::ThreadChecker thread_checker_;
DISALLOW_COPY_AND_ASSIGN(HeadlessWindowManager);
diff --git a/chromium/ui/ozone/platform/wayland/gl_surface_wayland.cc b/chromium/ui/ozone/platform/wayland/gl_surface_wayland.cc
index d1e64cc216c..5827383eefe 100644
--- a/chromium/ui/ozone/platform/wayland/gl_surface_wayland.cc
+++ b/chromium/ui/ozone/platform/wayland/gl_surface_wayland.cc
@@ -35,6 +35,7 @@ GLSurfaceWayland::GLSurfaceWayland(WaylandEglWindowPtr egl_window)
bool GLSurfaceWayland::Resize(const gfx::Size& size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha) {
if (size_ == size)
return true;
diff --git a/chromium/ui/ozone/platform/wayland/gl_surface_wayland.h b/chromium/ui/ozone/platform/wayland/gl_surface_wayland.h
index ca27fbf7133..27b81f0e192 100644
--- a/chromium/ui/ozone/platform/wayland/gl_surface_wayland.h
+++ b/chromium/ui/ozone/platform/wayland/gl_surface_wayland.h
@@ -34,6 +34,7 @@ class GLSurfaceWayland : public gl::NativeViewGLSurfaceEGL {
// gl::GLSurface:
bool Resize(const gfx::Size& size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha) override;
EGLConfig GetConfig() override;
diff --git a/chromium/ui/ozone/platform/wayland/wayland_window.cc b/chromium/ui/ozone/platform/wayland/wayland_window.cc
index 85cfee522e4..a7f4313bd13 100644
--- a/chromium/ui/ozone/platform/wayland/wayland_window.cc
+++ b/chromium/ui/ozone/platform/wayland/wayland_window.cc
@@ -96,7 +96,7 @@ gfx::Rect WaylandWindow::GetBounds() {
void WaylandWindow::SetTitle(const base::string16& title) {
DCHECK(xdg_surface_);
- xdg_surface_set_title(xdg_surface_.get(), UTF16ToUTF8(title).c_str());
+ xdg_surface_set_title(xdg_surface_.get(), base::UTF16ToUTF8(title).c_str());
connection_->ScheduleFlush();
}
diff --git a/chromium/ui/ozone/platform/x11/gl_surface_egl_ozone_x11.cc b/chromium/ui/ozone/platform/x11/gl_surface_egl_ozone_x11.cc
index 0fc232ee590..ea4348778d7 100644
--- a/chromium/ui/ozone/platform/x11/gl_surface_egl_ozone_x11.cc
+++ b/chromium/ui/ozone/platform/x11/gl_surface_egl_ozone_x11.cc
@@ -80,6 +80,7 @@ EGLConfig GLSurfaceEGLOzoneX11::GetConfig() {
bool GLSurfaceEGLOzoneX11::Resize(const gfx::Size& size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha) {
if (size == GetSize())
return true;
diff --git a/chromium/ui/ozone/platform/x11/gl_surface_egl_ozone_x11.h b/chromium/ui/ozone/platform/x11/gl_surface_egl_ozone_x11.h
index ec044651872..dcb419083b9 100644
--- a/chromium/ui/ozone/platform/x11/gl_surface_egl_ozone_x11.h
+++ b/chromium/ui/ozone/platform/x11/gl_surface_egl_ozone_x11.h
@@ -21,6 +21,7 @@ class GLSurfaceEGLOzoneX11 : public gl::NativeViewGLSurfaceEGL {
EGLConfig GetConfig() override;
bool Resize(const gfx::Size& size,
float scale_factor,
+ ColorSpace color_space,
bool has_alpha) override;
private:
diff --git a/chromium/ui/ozone/platform/x11/ozone_platform_x11.cc b/chromium/ui/ozone/platform/x11/ozone_platform_x11.cc
index 072c5b02551..58176cc0fbc 100644
--- a/chromium/ui/ozone/platform/x11/ozone_platform_x11.cc
+++ b/chromium/ui/ozone/platform/x11/ozone_platform_x11.cc
@@ -9,7 +9,6 @@
#include <memory>
#include <utility>
-#include "base/command_line.h"
#include "base/memory/ptr_util.h"
#include "base/message_loop/message_loop.h"
#include "base/strings/utf_string_conversions.h"
@@ -32,16 +31,6 @@ namespace ui {
namespace {
-// Returns true if a flag is present that will cause Ozone UI and GPU to run in
-// the same process.
-// TODO(kylechar): Remove --mojo-platform-channel-handle when mus-ws process
-// split happens.
-bool HasSingleProcessFlag() {
- base::CommandLine* command_line = base::CommandLine::ForCurrentProcess();
- return command_line->HasSwitch("mojo-platform-channel-handle") ||
- command_line->HasSwitch("single-process");
-}
-
// Singleton OzonePlatform implementation for X11 platform.
class OzonePlatformX11 : public OzonePlatform {
public:
@@ -106,7 +95,7 @@ class OzonePlatformX11 : public OzonePlatform {
// In single process mode either the UI thread will create an event source
// or it's a test and an event source isn't desired.
- if (!params.single_process && !HasSingleProcessFlag())
+ if (!params.single_process)
CreatePlatformEventSource();
surface_factory_ozone_ = base::MakeUnique<X11SurfaceFactory>();
@@ -127,7 +116,7 @@ class OzonePlatformX11 : public OzonePlatform {
return;
// In single process mode XInitThreads() must be the first Xlib call.
- if (params.single_process || HasSingleProcessFlag())
+ if (params.single_process)
XInitThreads();
ui::SetDefaultX11ErrorHandlers();
diff --git a/chromium/ui/ozone/public/input_controller.cc b/chromium/ui/ozone/public/input_controller.cc
index 5aa300240b4..7ee1a3712b6 100644
--- a/chromium/ui/ozone/public/input_controller.cc
+++ b/chromium/ui/ozone/public/input_controller.cc
@@ -40,6 +40,7 @@ class StubInputController : public InputController {
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;
void GetTouchEventLog(const base::FilePath& out_dir,
@@ -121,6 +122,9 @@ void StubInputController::SetMouseSensitivity(int value) {
void StubInputController::SetPrimaryButtonRight(bool right) {
}
+void StubInputController::SetMouseReverseScroll(bool enabled) {
+}
+
void StubInputController::SetTapToClickPaused(bool state) {
}
diff --git a/chromium/ui/ozone/public/input_controller.h b/chromium/ui/ozone/public/input_controller.h
index cdec1d54b65..f791a8b5022 100644
--- a/chromium/ui/ozone/public/input_controller.h
+++ b/chromium/ui/ozone/public/input_controller.h
@@ -65,6 +65,7 @@ class OZONE_BASE_EXPORT InputController {
// Mouse settings.
virtual void SetMouseSensitivity(int value) = 0;
virtual void SetPrimaryButtonRight(bool right) = 0;
+ virtual void SetMouseReverseScroll(bool enabled) = 0;
// Touch log collection.
virtual void GetTouchDeviceStatus(GetTouchDeviceStatusReply reply) = 0;
diff --git a/chromium/ui/ozone/public/interfaces/BUILD.gn b/chromium/ui/ozone/public/interfaces/BUILD.gn
index 48221f5185c..f66bf8a1248 100644
--- a/chromium/ui/ozone/public/interfaces/BUILD.gn
+++ b/chromium/ui/ozone/public/interfaces/BUILD.gn
@@ -7,11 +7,14 @@ import("//mojo/public/tools/bindings/mojom.gni")
mojom("interfaces") {
sources = [
"device_cursor.mojom",
+ "drm_device.mojom",
"overlay_surface_candidate.mojom",
]
public_deps = [
+ "//mojo/common:common_custom_types",
"//skia/public/interfaces:interfaces",
+ "//ui/display/mojo:interfaces",
"//ui/gfx/geometry/mojo",
"//ui/gfx/mojo",
]
diff --git a/chromium/ui/ozone/public/interfaces/drm_device.mojom b/chromium/ui/ozone/public/interfaces/drm_device.mojom
new file mode 100644
index 00000000000..eede42437b0
--- /dev/null
+++ b/chromium/ui/ozone/public/interfaces/drm_device.mojom
@@ -0,0 +1,86 @@
+// 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.
+
+module ui.ozone.mojom;
+
+import "mojo/common/file.mojom";
+import "mojo/common/file_path.mojom";
+import "ui/display/mojo/display_constants.mojom";
+import "ui/display/mojo/display_mode.mojom";
+import "ui/display/mojo/display_snapshot.mojom";
+import "ui/display/mojo/gamma_ramp_rgb_entry.mojom";
+import "ui/gfx/geometry/mojo/geometry.mojom";
+import "ui/gfx/mojo/accelerated_widget.mojom";
+import "ui/ozone/public/interfaces/overlay_surface_candidate.mojom";
+
+
+// The viz process on CrOS implements the DrmDevice
+// service to let the viz host and clients manage DRM displays.
+// All functions in DrmDevice are implemented by the lower privilege viz
+// process.
+interface DrmDevice {
+ // Starts the DRM service and returns true on success.
+ [Sync]
+ StartDrmDevice() => (bool success);
+
+ // Creates scanout capable DRM buffers to back |widget|.
+ CreateWindow(gfx.mojom.AcceleratedWidget widget);
+
+ // Destroys the DRM buffers backing |widget|.
+ DestroyWindow(gfx.mojom.AcceleratedWidget widget);
+
+ // Sets the size of the DRM buffer for |widget|.
+ SetWindowBounds(gfx.mojom.AcceleratedWidget widget, gfx.mojom.Rect bounds);
+
+ // Takes control of the display and invoke a provided callback with a boolean
+ // status.
+ TakeDisplayControl() => (bool success);
+
+ // Releases control of the display and invoke a provided callback with a
+ // boolean status.
+ RelinquishDisplayControl() => (bool success);
+
+ // Requests a callback providing a list of the available displays.
+ RefreshNativeDisplays() =>
+ (array<display.mojom.DisplaySnapshot> display_snapshots);
+
+ // Transfers ownership of a DRM device to the GPU process.
+ AddGraphicsDevice(mojo.common.mojom.FilePath path,
+ mojo.common.mojom.File file);
+
+ // Instructs the GPU to abandon a DRM device.
+ RemoveGraphicsDevice(mojo.common.mojom.FilePath path);
+
+ // Instructs the GPU to disable a DRM device.
+ DisableNativeDisplay(int64 display_id) => (int64 display_id, bool success);
+
+ // Configures a DRM display returning true on success.
+ ConfigureNativeDisplay(int64 display_id,
+ display.mojom.DisplayMode display_mode,
+ gfx.mojom.Point point) =>
+ (int64 display_id, bool success);
+
+ // Gets or sets high-definition content protection (HDCP) (DRM as in
+ // digital rights management) state.
+ GetHDCPState(int64 display_id) =>
+ (int64 display_id, bool success, display.mojom.HDCPState state);
+ SetHDCPState(int64 display_id, display.mojom.HDCPState state) =>
+ (int64 display_id, bool success);
+
+ // Sets a color correction gamma table.
+ SetColorCorrection(int64 display_id,
+ array<display.mojom.GammaRampRGBEntry> degamma_lut,
+ array<display.mojom.GammaRampRGBEntry> gamma_lut,
+ array<float> correction_matrix);
+
+ // Verifies if the display controller can successfully scanout the given set
+ // of OverlaySurfaceCandidates and return the status associated with each
+ // candidate.
+ CheckOverlayCapabilities(gfx.mojom.AcceleratedWidget widget,
+ array<ui.ozone.mojom.OverlaySurfaceCandidate> candidates) =>
+ (gfx.mojom.AcceleratedWidget widget,
+ array<ui.ozone.mojom.OverlaySurfaceCandidate> candidates,
+ array<ui.ozone.mojom.OverlayStatus> status);
+};
+
diff --git a/chromium/ui/ozone/public/overlay_candidates_ozone.h b/chromium/ui/ozone/public/overlay_candidates_ozone.h
index 760721feea0..8ccc8610215 100644
--- a/chromium/ui/ozone/public/overlay_candidates_ozone.h
+++ b/chromium/ui/ozone/public/overlay_candidates_ozone.h
@@ -17,7 +17,7 @@ namespace ui {
// class from SurfaceFactoryOzone given an AcceleratedWidget.
class OZONE_BASE_EXPORT OverlayCandidatesOzone {
public:
- typedef std::vector<OverlaySurfaceCandidate> OverlaySurfaceCandidateList;
+ using OverlaySurfaceCandidateList = std::vector<OverlaySurfaceCandidate>;
// A list of possible overlay candidates is presented to this function.
// The expected result is that those candidates that can be in a separate
diff --git a/chromium/ui/ozone/public/overlay_surface_candidate.cc b/chromium/ui/ozone/public/overlay_surface_candidate.cc
index 3612d21810f..9065638d37a 100644
--- a/chromium/ui/ozone/public/overlay_surface_candidate.cc
+++ b/chromium/ui/ozone/public/overlay_surface_candidate.cc
@@ -4,6 +4,8 @@
#include "ui/ozone/public/overlay_surface_candidate.h"
+#include "ui/gfx/geometry/rect_conversions.h"
+
namespace ui {
OverlaySurfaceCandidate::OverlaySurfaceCandidate() : is_clipped(false) {}
@@ -13,4 +15,18 @@ OverlaySurfaceCandidate::OverlaySurfaceCandidate(
OverlaySurfaceCandidate::~OverlaySurfaceCandidate() {}
+bool OverlaySurfaceCandidate::operator<(
+ const OverlaySurfaceCandidate& param) const {
+ int lwidth = buffer_size.width();
+ int lheight = buffer_size.height();
+ int rwidth = param.buffer_size.width();
+ int rheight = param.buffer_size.height();
+ gfx::Rect lrect = gfx::ToNearestRect(display_rect);
+ gfx::Rect rrect = gfx::ToNearestRect(param.display_rect);
+
+ return std::tie(plane_z_order, format, lrect, lwidth, lheight, transform) <
+ std::tie(param.plane_z_order, param.format, rrect, rwidth, rheight,
+ param.transform);
+}
+
} // namespace ui
diff --git a/chromium/ui/ozone/public/overlay_surface_candidate.h b/chromium/ui/ozone/public/overlay_surface_candidate.h
index 904d69f5df8..aee7095af0c 100644
--- a/chromium/ui/ozone/public/overlay_surface_candidate.h
+++ b/chromium/ui/ozone/public/overlay_surface_candidate.h
@@ -5,6 +5,8 @@
#ifndef UI_OZONE_PUBLIC_OVERLAY_SURFACE_CANDIDATE_H_
#define UI_OZONE_PUBLIC_OVERLAY_SURFACE_CANDIDATE_H_
+#include <vector>
+
#include "ui/gfx/buffer_types.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/rect_f.h"
@@ -27,6 +29,8 @@ class OZONE_BASE_EXPORT OverlaySurfaceCandidate {
OverlaySurfaceCandidate(const OverlaySurfaceCandidate& other);
~OverlaySurfaceCandidate();
+ bool operator<(const OverlaySurfaceCandidate& plane) const;
+
// Transformation to apply to layer during composition.
gfx::OverlayTransform transform = gfx::OVERLAY_TRANSFORM_NONE;
// Format of the buffer to composite.
@@ -52,6 +56,9 @@ class OZONE_BASE_EXPORT OverlaySurfaceCandidate {
bool overlay_handled = false;
};
+using OverlaySurfaceCandidateList = std::vector<OverlaySurfaceCandidate>;
+using OverlayStatusList = std::vector<OverlayStatus>;
+
} // namespace ui
#endif // UI_OZONE_PUBLIC_OVERLAY_SURFACE_CANDIDATE_H_
diff --git a/chromium/ui/platform_window/android/platform_ime_controller_android.cc b/chromium/ui/platform_window/android/platform_ime_controller_android.cc
index d9e0edfb4da..99cf38fa016 100644
--- a/chromium/ui/platform_window/android/platform_ime_controller_android.cc
+++ b/chromium/ui/platform_window/android/platform_ime_controller_android.cc
@@ -13,11 +13,6 @@ using base::android::ScopedJavaLocalRef;
namespace ui {
-// static
-bool PlatformImeControllerAndroid::Register(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
PlatformImeControllerAndroid::PlatformImeControllerAndroid() {
}
diff --git a/chromium/ui/platform_window/android/platform_ime_controller_android.h b/chromium/ui/platform_window/android/platform_ime_controller_android.h
index 69d9682cc1b..ed47c6285e4 100644
--- a/chromium/ui/platform_window/android/platform_ime_controller_android.h
+++ b/chromium/ui/platform_window/android/platform_ime_controller_android.h
@@ -15,8 +15,6 @@ namespace ui {
class ANDROID_WINDOW_EXPORT PlatformImeControllerAndroid :
public PlatformImeController {
public:
- static bool Register(JNIEnv* env);
-
PlatformImeControllerAndroid();
~PlatformImeControllerAndroid() override;
diff --git a/chromium/ui/platform_window/android/platform_window_android.cc b/chromium/ui/platform_window/android/platform_window_android.cc
index 97bb914598a..c32b24a3dac 100644
--- a/chromium/ui/platform_window/android/platform_window_android.cc
+++ b/chromium/ui/platform_window/android/platform_window_android.cc
@@ -49,11 +49,6 @@ ui::EventType MotionEventActionToEventType(jint action) {
////////////////////////////////////////////////////////////////////////////////
// PlatformWindowAndroid, public:
-// static
-bool PlatformWindowAndroid::Register(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
PlatformWindowAndroid::PlatformWindowAndroid(PlatformWindowDelegate* delegate)
: delegate_(delegate),
window_(NULL),
diff --git a/chromium/ui/platform_window/android/platform_window_android.h b/chromium/ui/platform_window/android/platform_window_android.h
index 6ae06813727..599ff71883f 100644
--- a/chromium/ui/platform_window/android/platform_window_android.h
+++ b/chromium/ui/platform_window/android/platform_window_android.h
@@ -24,8 +24,6 @@ class PlatformWindowDelegate;
class ANDROID_WINDOW_EXPORT PlatformWindowAndroid : public PlatformWindow {
public:
- static bool Register(JNIEnv* env);
-
explicit PlatformWindowAndroid(PlatformWindowDelegate* delegate);
~PlatformWindowAndroid() override;
diff --git a/chromium/ui/platform_window/stub/stub_window.h b/chromium/ui/platform_window/stub/stub_window.h
index 080e945cdd1..b171e0a8f0e 100644
--- a/chromium/ui/platform_window/stub/stub_window.h
+++ b/chromium/ui/platform_window/stub/stub_window.h
@@ -15,7 +15,7 @@ namespace ui {
class PlatformWindowDelegate;
-class STUB_WINDOW_EXPORT StubWindow : NON_EXPORTED_BASE(public PlatformWindow) {
+class STUB_WINDOW_EXPORT StubWindow : public PlatformWindow {
public:
explicit StubWindow(PlatformWindowDelegate* delegate,
bool use_default_accelerated_widget = true,
diff --git a/chromium/ui/platform_window/win/win_window.h b/chromium/ui/platform_window/win/win_window.h
index d91d8086e6a..5e4859ce247 100644
--- a/chromium/ui/platform_window/win/win_window.h
+++ b/chromium/ui/platform_window/win/win_window.h
@@ -15,7 +15,7 @@ namespace ui {
class PlatformWindowDelegate;
-class WIN_WINDOW_EXPORT WinWindow : public NON_EXPORTED_BASE(PlatformWindow),
+class WIN_WINDOW_EXPORT WinWindow : public PlatformWindow,
public gfx::WindowImpl {
public:
WinWindow(PlatformWindowDelegate* delegate, const gfx::Rect& bounds);
diff --git a/chromium/ui/resources/BUILD.gn b/chromium/ui/resources/BUILD.gn
index e81141e3203..cee10c4ff0f 100644
--- a/chromium/ui/resources/BUILD.gn
+++ b/chromium/ui/resources/BUILD.gn
@@ -238,7 +238,7 @@ repack("repack_ui_test_pak_200_percent") {
}
# Repack just the strings for the framework locales on Mac and iOS. This
-# emulates repack_locales.py, but just for en-US. Note ui_test.pak is not simply
+# emulates repack_locales(), but just for en-US. Note ui_test.pak is not simply
# copied, because it causes leaks from allocations within system libraries when
# trying to load non-string resources. http://crbug.com/413034.
repack("repack_ui_test_mac_locale_pack") {
diff --git a/chromium/ui/shell_dialogs/BUILD.gn b/chromium/ui/shell_dialogs/BUILD.gn
index 505bf26edea..74080cd385d 100644
--- a/chromium/ui/shell_dialogs/BUILD.gn
+++ b/chromium/ui/shell_dialogs/BUILD.gn
@@ -51,8 +51,6 @@ component("shell_dialogs") {
if (is_android && !use_aura) {
sources += [
- "android/shell_dialogs_jni_registrar.cc",
- "android/shell_dialogs_jni_registrar.h",
"select_file_dialog_android.cc",
"select_file_dialog_android.h",
]
@@ -71,6 +69,10 @@ component("shell_dialogs") {
"AppKit.framework",
]
}
+
+ if (is_fuchsia) {
+ sources += [ "select_file_dialog_fuchsia.cc" ]
+ }
}
test("shell_dialogs_unittests") {
diff --git a/chromium/ui/shell_dialogs/select_file_dialog.cc b/chromium/ui/shell_dialogs/select_file_dialog.cc
index e10afac1b6b..9b60383e547 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog.cc
+++ b/chromium/ui/shell_dialogs/select_file_dialog.cc
@@ -41,17 +41,17 @@ void SelectFileDialog::Listener::FileSelectedWithExtraInfo(
// Most of the dialogs need actual local path, so default to it.
// If local path is empty, use file_path instead.
FileSelected(file.local_path.empty() ? file.file_path : file.local_path,
- index,
- params);
+ index, params);
}
void SelectFileDialog::Listener::MultiFilesSelectedWithExtraInfo(
const std::vector<ui::SelectedFileInfo>& files,
void* params) {
std::vector<base::FilePath> file_paths;
- for (size_t i = 0; i < files.size(); ++i)
- file_paths.push_back(files[i].local_path.empty() ? files[i].file_path
- : files[i].local_path);
+ for (const ui::SelectedFileInfo& file : files) {
+ file_paths.push_back(file.local_path.empty() ? file.file_path
+ : file.local_path);
+ }
MultiFilesSelected(file_paths, params);
}
@@ -65,14 +65,10 @@ void SelectFileDialog::SetFactory(ui::SelectFileDialogFactory* factory) {
// static
scoped_refptr<SelectFileDialog> SelectFileDialog::Create(
Listener* listener,
- ui::SelectFilePolicy* policy) {
- if (dialog_factory_) {
- SelectFileDialog* dialog = dialog_factory_->Create(listener, policy);
- if (dialog)
- return dialog;
- }
-
- return CreateSelectFileDialog(listener, policy);
+ std::unique_ptr<ui::SelectFilePolicy> policy) {
+ if (dialog_factory_)
+ return dialog_factory_->Create(listener, std::move(policy));
+ return CreateSelectFileDialog(listener, std::move(policy));
}
base::FilePath SelectFileDialog::GetShortenedFilePath(
@@ -135,9 +131,8 @@ bool SelectFileDialog::HasMultipleFileTypeChoices() {
}
SelectFileDialog::SelectFileDialog(Listener* listener,
- ui::SelectFilePolicy* policy)
- : listener_(listener),
- select_file_policy_(policy) {
+ std::unique_ptr<ui::SelectFilePolicy> policy)
+ : listener_(listener), select_file_policy_(std::move(policy)) {
DCHECK(listener_);
}
diff --git a/chromium/ui/shell_dialogs/select_file_dialog.h b/chromium/ui/shell_dialogs/select_file_dialog.h
index e5d288a07e9..c554ce2666a 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog.h
+++ b/chromium/ui/shell_dialogs/select_file_dialog.h
@@ -19,6 +19,7 @@
#include "ui/shell_dialogs/shell_dialogs_export.h"
namespace ui {
+
class SelectFileDialogFactory;
class SelectFilePolicy;
struct SelectedFileInfo;
@@ -102,8 +103,14 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog
// Creates a dialog box helper. This is an inexpensive wrapper around the
// platform-native file selection dialog. |policy| is an optional class that
// can prevent showing a dialog.
- static scoped_refptr<SelectFileDialog> Create(Listener* listener,
- SelectFilePolicy* policy);
+ //
+ // The lifetime of the Listener is not managed by this class. The calling
+ // code should call always ListenerDestroyed() (on the base class
+ // BaseShellDialog) when the listener is destroyed since the SelectFileDialog
+ // is refcounted and uses a background thread.
+ static scoped_refptr<SelectFileDialog> Create(
+ Listener* listener,
+ std::unique_ptr<SelectFilePolicy> policy);
// Holds information about allowed extensions on a file save dialog.
struct SHELL_DIALOGS_EXPORT FileTypeInfo {
@@ -117,7 +124,7 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog
//
// Only pass more than one extension in the inner vector if the extensions
// are equivalent. Do NOT include leading periods.
- std::vector<std::vector<base::FilePath::StringType> > extensions;
+ std::vector<std::vector<base::FilePath::StringType>> extensions;
// Overrides the system descriptions of the specified extensions. Entries
// correspond to |extensions|; if left blank the system descriptions will
@@ -179,7 +186,9 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog
protected:
friend class base::RefCountedThreadSafe<SelectFileDialog>;
- explicit SelectFileDialog(Listener* listener, SelectFilePolicy* policy);
+
+ explicit SelectFileDialog(Listener* listener,
+ std::unique_ptr<SelectFilePolicy> policy);
~SelectFileDialog() override;
// Displays the actual file-selection dialog.
@@ -217,8 +226,10 @@ class SHELL_DIALOGS_EXPORT SelectFileDialog
DISALLOW_COPY_AND_ASSIGN(SelectFileDialog);
};
-SelectFileDialog* CreateSelectFileDialog(SelectFileDialog::Listener* listener,
- SelectFilePolicy* policy);
+SelectFileDialog* CreateSelectFileDialog(
+ SelectFileDialog::Listener* listener,
+ std::unique_ptr<SelectFilePolicy> policy);
+
} // namespace ui
#endif // UI_SHELL_DIALOGS_SELECT_FILE_DIALOG_H_
diff --git a/chromium/ui/shell_dialogs/select_file_dialog_android.cc b/chromium/ui/shell_dialogs/select_file_dialog_android.cc
index 30c557d719a..954e19c34d9 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog_android.cc
+++ b/chromium/ui/shell_dialogs/select_file_dialog_android.cc
@@ -14,6 +14,7 @@
#include "base/strings/utf_string_conversions.h"
#include "jni/SelectFileDialog_jni.h"
#include "ui/android/window_android.h"
+#include "ui/shell_dialogs/select_file_policy.h"
#include "ui/shell_dialogs/selected_file_info.h"
using base::android::ConvertJavaStringToUTF8;
@@ -23,9 +24,10 @@ using base::android::ScopedJavaLocalRef;
namespace ui {
// static
-SelectFileDialogImpl* SelectFileDialogImpl::Create(Listener* listener,
- SelectFilePolicy* policy) {
- return new SelectFileDialogImpl(listener, policy);
+SelectFileDialogImpl* SelectFileDialogImpl::Create(
+ Listener* listener,
+ std::unique_ptr<SelectFilePolicy> policy) {
+ return new SelectFileDialogImpl(listener, std::move(policy));
}
void SelectFileDialogImpl::OnFileSelected(
@@ -125,16 +127,13 @@ void SelectFileDialogImpl::SelectFileImpl(
owning_window->GetJavaObject());
}
-bool SelectFileDialogImpl::RegisterSelectFileDialog(JNIEnv* env) {
- return RegisterNativesImpl(env);
-}
-
SelectFileDialogImpl::~SelectFileDialogImpl() {
}
-SelectFileDialogImpl::SelectFileDialogImpl(Listener* listener,
- SelectFilePolicy* policy)
- : SelectFileDialog(listener, policy) {
+SelectFileDialogImpl::SelectFileDialogImpl(
+ Listener* listener,
+ std::unique_ptr<SelectFilePolicy> policy)
+ : SelectFileDialog(listener, std::move(policy)) {
JNIEnv* env = base::android::AttachCurrentThread();
java_object_.Reset(
Java_SelectFileDialog_create(env, reinterpret_cast<intptr_t>(this)));
@@ -145,9 +144,10 @@ bool SelectFileDialogImpl::HasMultipleFileTypeChoicesImpl() {
return false;
}
-SelectFileDialog* CreateSelectFileDialog(SelectFileDialog::Listener* listener,
- SelectFilePolicy* policy) {
- return SelectFileDialogImpl::Create(listener, policy);
+SelectFileDialog* CreateSelectFileDialog(
+ SelectFileDialog::Listener* listener,
+ std::unique_ptr<SelectFilePolicy> policy) {
+ return SelectFileDialogImpl::Create(listener, std::move(policy));
}
} // namespace ui
diff --git a/chromium/ui/shell_dialogs/select_file_dialog_android.h b/chromium/ui/shell_dialogs/select_file_dialog_android.h
index 5291cd3c92b..5ac283abf45 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog_android.h
+++ b/chromium/ui/shell_dialogs/select_file_dialog_android.h
@@ -17,7 +17,7 @@ namespace ui {
class SelectFileDialogImpl : public SelectFileDialog {
public:
static SelectFileDialogImpl* Create(Listener* listener,
- SelectFilePolicy* policy);
+ std::unique_ptr<SelectFilePolicy> policy);
void OnFileSelected(JNIEnv* env,
const base::android::JavaParamRef<jobject>& java_object,
@@ -50,13 +50,12 @@ class SelectFileDialogImpl : public SelectFileDialog {
gfx::NativeWindow owning_window,
void* params) override;
- static bool RegisterSelectFileDialog(JNIEnv* env);
-
protected:
~SelectFileDialogImpl() override;
private:
- SelectFileDialogImpl(Listener* listener, SelectFilePolicy* policy);
+ SelectFileDialogImpl(Listener* listener,
+ std::unique_ptr<SelectFilePolicy> policy);
bool HasMultipleFileTypeChoicesImpl() override;
diff --git a/chromium/ui/shell_dialogs/select_file_dialog_factory.h b/chromium/ui/shell_dialogs/select_file_dialog_factory.h
index cb12e28be87..567f50de40b 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog_factory.h
+++ b/chromium/ui/shell_dialogs/select_file_dialog_factory.h
@@ -9,6 +9,7 @@
#include "ui/shell_dialogs/shell_dialogs_export.h"
namespace ui {
+
class SelectFilePolicy;
// Some chrome components want to create their own SelectFileDialog objects
@@ -20,8 +21,9 @@ class SHELL_DIALOGS_EXPORT SelectFileDialogFactory {
public:
virtual ~SelectFileDialogFactory();
- virtual SelectFileDialog* Create(ui::SelectFileDialog::Listener* listener,
- ui::SelectFilePolicy* policy) = 0;
+ virtual SelectFileDialog* Create(
+ ui::SelectFileDialog::Listener* listener,
+ std::unique_ptr<ui::SelectFilePolicy> policy) = 0;
};
} // namespace ui
diff --git a/chromium/ui/shell_dialogs/select_file_dialog_fuchsia.cc b/chromium/ui/shell_dialogs/select_file_dialog_fuchsia.cc
new file mode 100644
index 00000000000..ff3e29eeea3
--- /dev/null
+++ b/chromium/ui/shell_dialogs/select_file_dialog_fuchsia.cc
@@ -0,0 +1,19 @@
+// 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/shell_dialogs/select_file_dialog.h"
+
+#include "base/logging.h"
+
+namespace ui {
+
+SelectFileDialog* CreateSelectFileDialog(
+ SelectFileDialog::Listener* listener,
+ std::unique_ptr<SelectFilePolicy> policy) {
+ // TODO(fuchsia): Port once we have UI, see https://crbug.com/746674.
+ NOTREACHED();
+ return nullptr;
+}
+
+} // namespace ui
diff --git a/chromium/ui/shell_dialogs/select_file_dialog_mac.h b/chromium/ui/shell_dialogs/select_file_dialog_mac.h
index b3765ef4224..472e7e0392b 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog_mac.h
+++ b/chromium/ui/shell_dialogs/select_file_dialog_mac.h
@@ -30,7 +30,8 @@ class SelectFileDialogMacTest;
// Exported for unit tests.
class SHELL_DIALOGS_EXPORT SelectFileDialogImpl : public ui::SelectFileDialog {
public:
- SelectFileDialogImpl(Listener* listener, ui::SelectFilePolicy* policy);
+ SelectFileDialogImpl(Listener* listener,
+ std::unique_ptr<ui::SelectFilePolicy> policy);
// BaseShellDialog implementation.
bool IsRunning(gfx::NativeWindow parent_window) const override;
diff --git a/chromium/ui/shell_dialogs/select_file_dialog_mac.mm b/chromium/ui/shell_dialogs/select_file_dialog_mac.mm
index d944e479b15..e408e2158c9 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog_mac.mm
+++ b/chromium/ui/shell_dialogs/select_file_dialog_mac.mm
@@ -20,6 +20,7 @@
#include "base/threading/thread_restrictions.h"
#import "ui/base/cocoa/nib_loading.h"
#include "ui/base/l10n/l10n_util_mac.h"
+#include "ui/shell_dialogs/select_file_policy.h"
#include "ui/strings/grit/ui_strings.h"
namespace {
@@ -87,12 +88,12 @@ NSString* GetDescriptionFromExtension(const base::FilePath::StringType& ext) {
namespace ui {
-SelectFileDialogImpl::SelectFileDialogImpl(Listener* listener,
- ui::SelectFilePolicy* policy)
- : SelectFileDialog(listener, policy),
- bridge_([[SelectFileDialogBridge alloc]
- initWithSelectFileDialogImpl:this]) {
-}
+SelectFileDialogImpl::SelectFileDialogImpl(
+ Listener* listener,
+ std::unique_ptr<ui::SelectFilePolicy> policy)
+ : SelectFileDialog(listener, std::move(policy)),
+ bridge_(
+ [[SelectFileDialogBridge alloc] initWithSelectFileDialogImpl:this]) {}
bool SelectFileDialogImpl::IsRunning(gfx::NativeWindow parent_window) const {
return parents_.find(parent_window) != parents_.end();
@@ -366,9 +367,10 @@ bool SelectFileDialogImpl::HasMultipleFileTypeChoicesImpl() {
return hasMultipleFileTypeChoices_;
}
-SelectFileDialog* CreateSelectFileDialog(SelectFileDialog::Listener* listener,
- SelectFilePolicy* policy) {
- return new SelectFileDialogImpl(listener, policy);
+SelectFileDialog* CreateSelectFileDialog(
+ SelectFileDialog::Listener* listener,
+ std::unique_ptr<SelectFilePolicy> policy) {
+ return new SelectFileDialogImpl(listener, std::move(policy));
}
} // namespace ui
diff --git a/chromium/ui/shell_dialogs/select_file_dialog_win.cc b/chromium/ui/shell_dialogs/select_file_dialog_win.cc
index 411b8bd5b4e..a6f07f070e1 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog_win.cc
+++ b/chromium/ui/shell_dialogs/select_file_dialog_win.cc
@@ -31,6 +31,7 @@
#include "ui/base/win/open_file_name_win.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/shell_dialogs/base_shell_dialog_win.h"
+#include "ui/shell_dialogs/select_file_policy.h"
#include "ui/strings/grit/ui_strings.h"
namespace {
@@ -163,7 +164,7 @@ class SelectFileDialogImpl : public ui::SelectFileDialog,
public:
SelectFileDialogImpl(
Listener* listener,
- ui::SelectFilePolicy* policy,
+ std::unique_ptr<ui::SelectFilePolicy> policy,
const base::Callback<bool(OPENFILENAME*)>& get_open_file_name_impl,
const base::Callback<bool(OPENFILENAME*)>& get_save_file_name_impl);
@@ -306,15 +307,14 @@ class SelectFileDialogImpl : public ui::SelectFileDialog,
SelectFileDialogImpl::SelectFileDialogImpl(
Listener* listener,
- ui::SelectFilePolicy* policy,
+ std::unique_ptr<ui::SelectFilePolicy> policy,
const base::Callback<bool(OPENFILENAME*)>& get_open_file_name_impl,
const base::Callback<bool(OPENFILENAME*)>& get_save_file_name_impl)
- : SelectFileDialog(listener, policy),
+ : SelectFileDialog(listener, std::move(policy)),
BaseShellDialogImpl(),
has_multiple_file_type_choices_(false),
get_open_file_name_impl_(get_open_file_name_impl),
- get_save_file_name_impl_(get_save_file_name_impl) {
-}
+ get_save_file_name_impl_(get_save_file_name_impl) {}
SelectFileDialogImpl::~SelectFileDialogImpl() {
}
@@ -701,17 +701,18 @@ std::wstring AppendExtensionIfNeeded(
SelectFileDialog* CreateWinSelectFileDialog(
SelectFileDialog::Listener* listener,
- SelectFilePolicy* policy,
+ std::unique_ptr<SelectFilePolicy> policy,
const base::Callback<bool(OPENFILENAME* ofn)>& get_open_file_name_impl,
const base::Callback<bool(OPENFILENAME* ofn)>& get_save_file_name_impl) {
- return new SelectFileDialogImpl(
- listener, policy, get_open_file_name_impl, get_save_file_name_impl);
+ return new SelectFileDialogImpl(listener, std::move(policy),
+ get_open_file_name_impl,
+ get_save_file_name_impl);
}
-SelectFileDialog* CreateSelectFileDialog(SelectFileDialog::Listener* listener,
- SelectFilePolicy* policy) {
- return CreateWinSelectFileDialog(listener,
- policy,
+SelectFileDialog* CreateSelectFileDialog(
+ SelectFileDialog::Listener* listener,
+ std::unique_ptr<SelectFilePolicy> policy) {
+ return CreateWinSelectFileDialog(listener, std::move(policy),
base::Bind(&CallBuiltinGetOpenFileName),
base::Bind(&CallBuiltinGetSaveFileName));
}
diff --git a/chromium/ui/shell_dialogs/select_file_dialog_win.h b/chromium/ui/shell_dialogs/select_file_dialog_win.h
index e066c65f1d3..22ef919a919 100644
--- a/chromium/ui/shell_dialogs/select_file_dialog_win.h
+++ b/chromium/ui/shell_dialogs/select_file_dialog_win.h
@@ -14,6 +14,7 @@
#include "ui/shell_dialogs/shell_dialogs_export.h"
namespace ui {
+
class SelectFilePolicy;
// Implementation detail exported for unit tests.
@@ -24,7 +25,7 @@ SHELL_DIALOGS_EXPORT std::wstring AppendExtensionIfNeeded(
SHELL_DIALOGS_EXPORT SelectFileDialog* CreateWinSelectFileDialog(
SelectFileDialog::Listener* listener,
- SelectFilePolicy* policy,
+ std::unique_ptr<SelectFilePolicy> policy,
const base::Callback<bool(OPENFILENAME* ofn)>& get_open_file_name_impl,
const base::Callback<bool(OPENFILENAME* ofn)>& get_save_file_name_impl);
diff --git a/chromium/ui/shell_dialogs/select_file_policy.cc b/chromium/ui/shell_dialogs/select_file_policy.cc
index 7e0f5861147..548e408e52f 100644
--- a/chromium/ui/shell_dialogs/select_file_policy.cc
+++ b/chromium/ui/shell_dialogs/select_file_policy.cc
@@ -6,6 +6,6 @@
namespace ui {
-SelectFilePolicy::~SelectFilePolicy() {}
+SelectFilePolicy::~SelectFilePolicy() = default;
} // namespace ui
diff --git a/chromium/ui/shell_dialogs/shell_dialog_linux.cc b/chromium/ui/shell_dialogs/shell_dialog_linux.cc
index 685369c2baa..046c430dd46 100644
--- a/chromium/ui/shell_dialogs/shell_dialog_linux.cc
+++ b/chromium/ui/shell_dialogs/shell_dialog_linux.cc
@@ -4,6 +4,8 @@
#include "ui/shell_dialogs/shell_dialog_linux.h"
+#include "ui/shell_dialogs/select_file_policy.h"
+
namespace {
ui::ShellDialogLinux* g_shell_dialog_linux = nullptr;
@@ -20,12 +22,13 @@ const ShellDialogLinux* ShellDialogLinux::instance() {
return g_shell_dialog_linux;
}
-SelectFileDialog* CreateSelectFileDialog(SelectFileDialog::Listener* listener,
- SelectFilePolicy* policy) {
+SelectFileDialog* CreateSelectFileDialog(
+ SelectFileDialog::Listener* listener,
+ std::unique_ptr<SelectFilePolicy> policy) {
#if defined(USE_AURA) && !defined(OS_CHROMEOS)
const ui::ShellDialogLinux* shell_dialogs = ui::ShellDialogLinux::instance();
if (shell_dialogs)
- return shell_dialogs->CreateSelectFileDialog(listener, policy);
+ return shell_dialogs->CreateSelectFileDialog(listener, std::move(policy));
#endif
NOTIMPLEMENTED();
return nullptr;
diff --git a/chromium/ui/shell_dialogs/shell_dialog_linux.h b/chromium/ui/shell_dialogs/shell_dialog_linux.h
index 1dad34d15b5..be0ffd0f69c 100644
--- a/chromium/ui/shell_dialogs/shell_dialog_linux.h
+++ b/chromium/ui/shell_dialogs/shell_dialog_linux.h
@@ -31,7 +31,7 @@ class SHELL_DIALOGS_EXPORT ShellDialogLinux {
// Returns a native file selection dialog.
virtual SelectFileDialog* CreateSelectFileDialog(
SelectFileDialog::Listener* listener,
- SelectFilePolicy* policy) const = 0;
+ std::unique_ptr<SelectFilePolicy> policy) const = 0;
};
} // namespace ui
diff --git a/chromium/ui/snapshot/DEPS b/chromium/ui/snapshot/DEPS
index e7164444691..1ea69bfe1f9 100644
--- a/chromium/ui/snapshot/DEPS
+++ b/chromium/ui/snapshot/DEPS
@@ -1,7 +1,8 @@
include_rules = [
"+cc",
"-cc/blink",
- "-cc/surfaces",
+ "+components/viz/common/quads",
+ "-components/viz/service/surfaces",
"+skia/ext",
"+third_party/skia",
"+ui/aura",
diff --git a/chromium/ui/snapshot/screenshot_grabber.cc b/chromium/ui/snapshot/screenshot_grabber.cc
index da79cb28737..bd563946dac 100644
--- a/chromium/ui/snapshot/screenshot_grabber.cc
+++ b/chromium/ui/snapshot/screenshot_grabber.cc
@@ -7,7 +7,6 @@
#include <stddef.h>
#include <climits>
-#include <string>
#include "base/bind.h"
#include "base/callback.h"
@@ -18,6 +17,7 @@
#include "base/message_loop/message_loop.h"
#include "base/single_thread_task_runner.h"
#include "base/task_runner.h"
+#include "base/task_scheduler/post_task.h"
#include "base/threading/sequenced_worker_pool.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
@@ -103,10 +103,10 @@ void EnsureLocalDirectoryExists(
void ScreenshotGrabberDelegate::PrepareFileAndRunOnBlockingPool(
const base::FilePath& path,
- scoped_refptr<base::TaskRunner> blocking_task_runner,
const FileCallback& callback_on_blocking_pool) {
- blocking_task_runner->PostTask(
+ base::PostTaskWithTraits(
FROM_HERE,
+ {base::MayBlock(), base::TaskShutdownBehavior::SKIP_ON_SHUTDOWN},
base::Bind(EnsureLocalDirectoryExists, path, callback_on_blocking_pool));
}
@@ -139,13 +139,8 @@ class ScreenshotGrabber::ScopedCursorHider {
};
#endif
-ScreenshotGrabber::ScreenshotGrabber(
- ScreenshotGrabberDelegate* client,
- scoped_refptr<base::TaskRunner> blocking_task_runner)
- : client_(client),
- blocking_task_runner_(blocking_task_runner),
- factory_(this) {
-}
+ScreenshotGrabber::ScreenshotGrabber(ScreenshotGrabberDelegate* client)
+ : client_(client), factory_(this) {}
ScreenshotGrabber::~ScreenshotGrabber() {
}
@@ -169,7 +164,7 @@ void ScreenshotGrabber::TakeScreenshot(gfx::NativeWindow window,
cursor_hider_ = ScopedCursorHider::Create(aura_window->GetRootWindow());
#endif
ui::GrabWindowSnapshotAsyncPNG(
- window, rect, blocking_task_runner_,
+ window, rect,
base::Bind(&ScreenshotGrabber::GrabWindowSnapshotAsyncCallback,
factory_.GetWeakPtr(), window_identifier, screenshot_path,
is_partial));
@@ -230,7 +225,7 @@ void ScreenshotGrabber::GrabWindowSnapshotAsyncCallback(
ShowNotificationCallback notification_callback(base::Bind(
&ScreenshotGrabber::NotifyScreenshotCompleted, factory_.GetWeakPtr()));
client_->PrepareFileAndRunOnBlockingPool(
- screenshot_path, blocking_task_runner_,
+ screenshot_path,
base::Bind(&SaveScreenshot, base::ThreadTaskRunnerHandle::Get(),
notification_callback, screenshot_path, png_data));
}
diff --git a/chromium/ui/snapshot/screenshot_grabber.h b/chromium/ui/snapshot/screenshot_grabber.h
index 7a0a9473f2e..8cf7723d47d 100644
--- a/chromium/ui/snapshot/screenshot_grabber.h
+++ b/chromium/ui/snapshot/screenshot_grabber.h
@@ -6,6 +6,7 @@
#define UI_SNAPSHOT_SCREENSHOT_GRABBER_H_
#include <memory>
+#include <string>
#include "base/callback.h"
#include "base/compiler_specific.h"
@@ -20,10 +21,6 @@
#include "ui/snapshot/screenshot_grabber_observer.h"
#include "ui/snapshot/snapshot_export.h"
-namespace base {
-class TaskRunner;
-}
-
namespace ui {
// TODO(flackr): Componentize google drive so that we don't need the
@@ -50,14 +47,12 @@ class SNAPSHOT_EXPORT ScreenshotGrabberDelegate {
// the remote file and call the callback with the local path.
virtual void PrepareFileAndRunOnBlockingPool(
const base::FilePath& path,
- scoped_refptr<base::TaskRunner> blocking_task_runner,
const FileCallback& callback_on_blocking_pool);
};
class SNAPSHOT_EXPORT ScreenshotGrabber {
public:
- ScreenshotGrabber(ScreenshotGrabberDelegate* client,
- scoped_refptr<base::TaskRunner> blocking_task_runner);
+ explicit ScreenshotGrabber(ScreenshotGrabberDelegate* client);
~ScreenshotGrabber();
// Takes a screenshot of |rect| in |window| in that window's coordinate space
@@ -92,9 +87,6 @@ class SNAPSHOT_EXPORT ScreenshotGrabber {
// The timestamp when the screenshot task was issued last time.
base::TimeTicks last_screenshot_timestamp_;
- // Task runner for blocking tasks.
- scoped_refptr<base::TaskRunner> blocking_task_runner_;
-
#if defined(USE_AURA)
// The object to hide cursor when taking screenshot.
std::unique_ptr<ScopedCursorHider> cursor_hider_;
diff --git a/chromium/ui/snapshot/snapshot.cc b/chromium/ui/snapshot/snapshot.cc
index 6e5188c2a6d..cc57fa93cf4 100644
--- a/chromium/ui/snapshot/snapshot.cc
+++ b/chromium/ui/snapshot/snapshot.cc
@@ -6,7 +6,7 @@
#include "base/bind.h"
#include "base/callback.h"
-#include "base/task_runner_util.h"
+#include "base/task_scheduler/post_task.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/codec/png_codec.h"
#include "ui/gfx/image/image.h"
@@ -22,7 +22,7 @@ scoped_refptr<base::RefCountedMemory> EncodeImageAsPNG(
std::vector<uint8_t> result;
DCHECK(!image.AsImageSkia().GetRepresentation(1.0f).is_null());
gfx::PNGCodec::FastEncodeBGRASkBitmap(image.AsBitmap(), true, &result);
- return new base::RefCountedBytes(result);
+ return base::RefCountedBytes::TakeVector(&result);
}
scoped_refptr<base::RefCountedMemory> EncodeImageAsJPEG(
@@ -30,17 +30,17 @@ scoped_refptr<base::RefCountedMemory> EncodeImageAsJPEG(
std::vector<uint8_t> result;
DCHECK(!image.AsImageSkia().GetRepresentation(1.0f).is_null());
gfx::JPEG1xEncodedDataFromImage(image, 100, &result);
- return new base::RefCountedBytes(result);
+ return base::RefCountedBytes::TakeVector(&result);
}
void EncodeImageAndScheduleCallback(
scoped_refptr<base::RefCountedMemory> (*encode_func)(const gfx::Image&),
- scoped_refptr<base::TaskRunner> background_task_runner,
const base::Callback<void(scoped_refptr<base::RefCountedMemory> data)>&
callback,
const gfx::Image& image) {
- base::PostTaskAndReplyWithResult(background_task_runner.get(), FROM_HERE,
- base::Bind(encode_func, image), callback);
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
+ base::Bind(encode_func, image), callback);
}
} // namespace
@@ -48,23 +48,19 @@ void EncodeImageAndScheduleCallback(
void GrabWindowSnapshotAsyncPNG(
gfx::NativeWindow window,
const gfx::Rect& source_rect,
- scoped_refptr<base::TaskRunner> background_task_runner,
const GrabWindowSnapshotAsyncPNGCallback& callback) {
GrabWindowSnapshotAsync(
window, source_rect,
- base::Bind(EncodeImageAndScheduleCallback, &EncodeImageAsPNG,
- std::move(background_task_runner), callback));
+ base::Bind(EncodeImageAndScheduleCallback, &EncodeImageAsPNG, callback));
}
void GrabWindowSnapshotAsyncJPEG(
gfx::NativeWindow window,
const gfx::Rect& source_rect,
- scoped_refptr<base::TaskRunner> background_task_runner,
const GrabWindowSnapshotAsyncJPEGCallback& callback) {
GrabWindowSnapshotAsync(
window, source_rect,
- base::Bind(EncodeImageAndScheduleCallback, &EncodeImageAsJPEG,
- std::move(background_task_runner), callback));
+ base::Bind(EncodeImageAndScheduleCallback, &EncodeImageAsJPEG, callback));
}
} // namespace ui
diff --git a/chromium/ui/snapshot/snapshot.h b/chromium/ui/snapshot/snapshot.h
index 31b9755a9b4..f5b5fa4f335 100644
--- a/chromium/ui/snapshot/snapshot.h
+++ b/chromium/ui/snapshot/snapshot.h
@@ -13,10 +13,6 @@
#include "ui/gfx/native_widget_types.h"
#include "ui/snapshot/snapshot_export.h"
-namespace base {
-class TaskRunner;
-}
-
namespace gfx {
class Rect;
class Image;
@@ -48,7 +44,6 @@ SNAPSHOT_EXPORT void GrabWindowSnapshotAndScaleAsync(
gfx::NativeWindow window,
const gfx::Rect& source_rect,
const gfx::Size& target_size,
- scoped_refptr<base::TaskRunner> background_task_runner,
const GrabWindowSnapshotAsyncCallback& callback);
SNAPSHOT_EXPORT void GrabWindowSnapshotAsync(
@@ -66,7 +61,6 @@ using GrabWindowSnapshotAsyncPNGCallback =
SNAPSHOT_EXPORT void GrabWindowSnapshotAsyncPNG(
gfx::NativeWindow window,
const gfx::Rect& source_rect,
- scoped_refptr<base::TaskRunner> background_task_runner,
const GrabWindowSnapshotAsyncPNGCallback& callback);
using GrabWindowSnapshotAsyncJPEGCallback =
@@ -74,7 +68,6 @@ using GrabWindowSnapshotAsyncJPEGCallback =
SNAPSHOT_EXPORT void GrabWindowSnapshotAsyncJPEG(
gfx::NativeWindow window,
const gfx::Rect& source_rect,
- scoped_refptr<base::TaskRunner> background_task_runner,
const GrabWindowSnapshotAsyncJPEGCallback& callback);
} // namespace ui
diff --git a/chromium/ui/snapshot/snapshot_android.cc b/chromium/ui/snapshot/snapshot_android.cc
index 0af3a337d84..c209fa5512a 100644
--- a/chromium/ui/snapshot/snapshot_android.cc
+++ b/chromium/ui/snapshot/snapshot_android.cc
@@ -8,8 +8,7 @@
#include <utility>
#include "base/bind.h"
-#include "base/task_runner.h"
-#include "cc/output/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_request.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/android/view_android.h"
#include "ui/android/window_android.h"
@@ -38,9 +37,9 @@ bool GrabWindowSnapshot(gfx::NativeWindow window,
static void MakeAsyncCopyRequest(
gfx::NativeWindow window,
const gfx::Rect& source_rect,
- cc::CopyOutputRequest::CopyOutputRequestCallback callback) {
- std::unique_ptr<cc::CopyOutputRequest> request =
- cc::CopyOutputRequest::CreateBitmapRequest(std::move(callback));
+ viz::CopyOutputRequest::CopyOutputRequestCallback callback) {
+ std::unique_ptr<viz::CopyOutputRequest> request =
+ viz::CopyOutputRequest::CreateBitmapRequest(std::move(callback));
float scale = ui::GetScaleFactorForNativeView(window);
request->set_area(gfx::ScaleToEnclosingRect(source_rect, scale));
@@ -51,12 +50,10 @@ void GrabWindowSnapshotAndScaleAsync(
gfx::NativeWindow window,
const gfx::Rect& source_rect,
const gfx::Size& target_size,
- scoped_refptr<base::TaskRunner> background_task_runner,
const GrabWindowSnapshotAsyncCallback& callback) {
- MakeAsyncCopyRequest(
- window, source_rect,
- base::BindOnce(&SnapshotAsync::ScaleCopyOutputResult, callback,
- target_size, background_task_runner));
+ MakeAsyncCopyRequest(window, source_rect,
+ base::BindOnce(&SnapshotAsync::ScaleCopyOutputResult,
+ callback, target_size));
}
void GrabWindowSnapshotAsync(gfx::NativeWindow window,
diff --git a/chromium/ui/snapshot/snapshot_async.cc b/chromium/ui/snapshot/snapshot_async.cc
index 173f70a56ac..1eedc3c9a55 100644
--- a/chromium/ui/snapshot/snapshot_async.cc
+++ b/chromium/ui/snapshot/snapshot_async.cc
@@ -5,9 +5,8 @@
#include "ui/snapshot/snapshot_async.h"
#include "base/location.h"
-#include "base/memory/ref_counted.h"
#include "base/numerics/safe_conversions.h"
-#include "base/task_runner_util.h"
+#include "base/task_scheduler/post_task.h"
#include "skia/ext/image_operations.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/gfx/image/image.h"
@@ -37,8 +36,7 @@ SkBitmap ScaleBitmap(const SkBitmap& input_bitmap,
void SnapshotAsync::ScaleCopyOutputResult(
const GrabWindowSnapshotAsyncCallback& callback,
const gfx::Size& target_size,
- scoped_refptr<base::TaskRunner> background_task_runner,
- std::unique_ptr<cc::CopyOutputResult> result) {
+ std::unique_ptr<viz::CopyOutputResult> result) {
if (result->IsEmpty()) {
callback.Run(gfx::Image());
return;
@@ -48,16 +46,15 @@ void SnapshotAsync::ScaleCopyOutputResult(
// from GPU. Image scaling is implemented in content::GlHelper, but it's can't
// be used here because it's not in content/public. Move the scaling code
// somewhere so that it can be reused here.
- base::PostTaskAndReplyWithResult(
- background_task_runner.get(),
- FROM_HERE,
+ base::PostTaskWithTraitsAndReplyWithResult(
+ FROM_HERE, {base::TaskShutdownBehavior::CONTINUE_ON_SHUTDOWN},
base::Bind(ScaleBitmap, *result->TakeBitmap(), target_size),
base::Bind(&OnFrameScalingFinished, callback));
}
void SnapshotAsync::RunCallbackWithCopyOutputResult(
const GrabWindowSnapshotAsyncCallback& callback,
- std::unique_ptr<cc::CopyOutputResult> result) {
+ std::unique_ptr<viz::CopyOutputResult> result) {
if (result->IsEmpty()) {
callback.Run(gfx::Image());
return;
diff --git a/chromium/ui/snapshot/snapshot_async.h b/chromium/ui/snapshot/snapshot_async.h
index 79928e0ac2e..4c66cf04f03 100644
--- a/chromium/ui/snapshot/snapshot_async.h
+++ b/chromium/ui/snapshot/snapshot_async.h
@@ -8,32 +8,27 @@
#include <memory>
#include "base/macros.h"
-#include "cc/output/copy_output_result.h"
+#include "components/viz/common/quads/copy_output_result.h"
#include "ui/snapshot/snapshot.h"
-namespace base {
-class TaskRunner;
-}
-
namespace gfx {
class Size;
}
namespace ui {
-// Helper methods for async snapshots to convert a cc::CopyOutputResult into a
+// Helper methods for async snapshots to convert a viz::CopyOutputResult into a
// ui::GrabWindowSnapshot callback.
class SnapshotAsync {
public:
static void ScaleCopyOutputResult(
const GrabWindowSnapshotAsyncCallback& callback,
const gfx::Size& target_size,
- scoped_refptr<base::TaskRunner> background_task_runner,
- std::unique_ptr<cc::CopyOutputResult> result);
+ std::unique_ptr<viz::CopyOutputResult> result);
static void RunCallbackWithCopyOutputResult(
const GrabWindowSnapshotAsyncCallback& callback,
- std::unique_ptr<cc::CopyOutputResult> result);
+ std::unique_ptr<viz::CopyOutputResult> result);
private:
DISALLOW_IMPLICIT_CONSTRUCTORS(SnapshotAsync);
diff --git a/chromium/ui/snapshot/snapshot_aura.cc b/chromium/ui/snapshot/snapshot_aura.cc
index 10328ee7fc3..40b59a110a0 100644
--- a/chromium/ui/snapshot/snapshot_aura.cc
+++ b/chromium/ui/snapshot/snapshot_aura.cc
@@ -4,13 +4,14 @@
#include "ui/snapshot/snapshot_aura.h"
+#include <memory>
#include <utility>
#include "base/bind.h"
#include "base/callback.h"
#include "base/memory/ptr_util.h"
#include "base/task_runner_util.h"
-#include "cc/output/copy_output_request.h"
+#include "components/viz/common/quads/copy_output_request.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tracker.h"
@@ -31,9 +32,9 @@ bool GrabWindowSnapshotAura(aura::Window* window,
static void MakeAsyncCopyRequest(
Layer* layer,
const gfx::Rect& source_rect,
- cc::CopyOutputRequest::CopyOutputRequestCallback callback) {
- std::unique_ptr<cc::CopyOutputRequest> request =
- cc::CopyOutputRequest::CreateBitmapRequest(std::move(callback));
+ viz::CopyOutputRequest::CopyOutputRequestCallback callback) {
+ std::unique_ptr<viz::CopyOutputRequest> request =
+ viz::CopyOutputRequest::CreateBitmapRequest(std::move(callback));
request->set_area(source_rect);
layer->RequestCopyOfOutput(std::move(request));
}
@@ -41,9 +42,9 @@ static void MakeAsyncCopyRequest(
static void FinishedAsyncCopyRequest(
std::unique_ptr<aura::WindowTracker> tracker,
const gfx::Rect& source_rect,
- cc::CopyOutputRequest::CopyOutputRequestCallback callback,
+ viz::CopyOutputRequest::CopyOutputRequestCallback callback,
int retry_count,
- std::unique_ptr<cc::CopyOutputResult> result) {
+ std::unique_ptr<viz::CopyOutputResult> result) {
static const int kMaxRetries = 5;
// Retry the copy request if the previous one failed for some reason.
if (!tracker->windows().empty() && (retry_count < kMaxRetries) &&
@@ -67,7 +68,7 @@ static void FinishedAsyncCopyRequest(
static void MakeInitialAsyncCopyRequest(
aura::Window* window,
const gfx::Rect& source_rect,
- cc::CopyOutputRequest::CopyOutputRequestCallback callback) {
+ viz::CopyOutputRequest::CopyOutputRequestCallback callback) {
auto tracker = base::MakeUnique<aura::WindowTracker>();
tracker->Add(window);
MakeAsyncCopyRequest(
@@ -80,12 +81,11 @@ void GrabWindowSnapshotAndScaleAsyncAura(
aura::Window* window,
const gfx::Rect& source_rect,
const gfx::Size& target_size,
- scoped_refptr<base::TaskRunner> background_task_runner,
const GrabWindowSnapshotAsyncCallback& callback) {
MakeInitialAsyncCopyRequest(
window, source_rect,
base::BindOnce(&SnapshotAsync::ScaleCopyOutputResult, callback,
- target_size, background_task_runner));
+ target_size));
}
void GrabWindowSnapshotAsyncAura(
@@ -116,10 +116,9 @@ void GrabWindowSnapshotAndScaleAsync(
gfx::NativeWindow window,
const gfx::Rect& source_rect,
const gfx::Size& target_size,
- scoped_refptr<base::TaskRunner> background_task_runner,
const GrabWindowSnapshotAsyncCallback& callback) {
GrabWindowSnapshotAndScaleAsyncAura(window, source_rect, target_size,
- background_task_runner, callback);
+ callback);
}
void GrabWindowSnapshotAsync(gfx::NativeWindow window,
diff --git a/chromium/ui/snapshot/snapshot_aura.h b/chromium/ui/snapshot/snapshot_aura.h
index 2c5429cef1d..7f693172cd6 100644
--- a/chromium/ui/snapshot/snapshot_aura.h
+++ b/chromium/ui/snapshot/snapshot_aura.h
@@ -19,7 +19,6 @@ SNAPSHOT_EXPORT void GrabWindowSnapshotAndScaleAsyncAura(
aura::Window* window,
const gfx::Rect& source_rect,
const gfx::Size& target_size,
- scoped_refptr<base::TaskRunner> background_task_runner,
const GrabWindowSnapshotAsyncCallback& callback);
SNAPSHOT_EXPORT void GrabWindowSnapshotAsyncAura(
diff --git a/chromium/ui/snapshot/snapshot_aura_unittest.cc b/chromium/ui/snapshot/snapshot_aura_unittest.cc
index bee0b0ca79a..1f9a779b4fa 100644
--- a/chromium/ui/snapshot/snapshot_aura_unittest.cc
+++ b/chromium/ui/snapshot/snapshot_aura_unittest.cc
@@ -9,6 +9,7 @@
#include "base/bind.h"
#include "base/macros.h"
+#include "base/run_loop.h"
#include "base/test/test_simple_task_runner.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "third_party/skia/include/core/SkPixelRef.h"
diff --git a/chromium/ui/snapshot/snapshot_ios.mm b/chromium/ui/snapshot/snapshot_ios.mm
index d239b71871c..b0c57e8d3e4 100644
--- a/chromium/ui/snapshot/snapshot_ios.mm
+++ b/chromium/ui/snapshot/snapshot_ios.mm
@@ -28,7 +28,6 @@ void GrabWindowSnapshotAndScaleAsync(
gfx::NativeWindow window,
const gfx::Rect& snapshot_bounds,
const gfx::Size& target_size,
- scoped_refptr<base::TaskRunner> background_task_runner,
GrabWindowSnapshotAsyncCallback callback) {
callback.Run(gfx::Image());
}
diff --git a/chromium/ui/snapshot/snapshot_mac.mm b/chromium/ui/snapshot/snapshot_mac.mm
index 40cfaaf0e2f..fab9c68172e 100644
--- a/chromium/ui/snapshot/snapshot_mac.mm
+++ b/chromium/ui/snapshot/snapshot_mac.mm
@@ -10,7 +10,6 @@
#include "base/logging.h"
#include "base/mac/scoped_cftyperef.h"
#include "base/mac/sdk_forward_declarations.h"
-#include "base/task_runner.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/image/image.h"
@@ -69,7 +68,6 @@ void GrabWindowSnapshotAndScaleAsync(
gfx::NativeWindow window,
const gfx::Rect& snapshot_bounds,
const gfx::Size& target_size,
- scoped_refptr<base::TaskRunner> background_task_runner,
GrabWindowSnapshotAsyncCallback callback) {
callback.Run(gfx::Image());
}
diff --git a/chromium/ui/snapshot/snapshot_win.cc b/chromium/ui/snapshot/snapshot_win.cc
index cd0d8f15099..17f4278f9d8 100644
--- a/chromium/ui/snapshot/snapshot_win.cc
+++ b/chromium/ui/snapshot/snapshot_win.cc
@@ -4,8 +4,9 @@
#include "ui/snapshot/snapshot_win.h"
+#include <memory>
+
#include "base/callback.h"
-#include "base/task_runner.h"
#include "base/win/windows_version.h"
#include "skia/ext/platform_canvas.h"
#include "skia/ext/skia_utils_win.h"
@@ -149,11 +150,10 @@ void GrabWindowSnapshotAndScaleAsync(
gfx::NativeWindow window,
const gfx::Rect& source_rect,
const gfx::Size& target_size,
- scoped_refptr<base::TaskRunner> background_task_runner,
const GrabWindowSnapshotAsyncCallback& callback) {
if (UseAuraSnapshot()) {
GrabWindowSnapshotAndScaleAsyncAura(window, source_rect, target_size,
- background_task_runner, callback);
+ callback);
return;
}
NOTIMPLEMENTED();
diff --git a/chromium/ui/strings/translations/ui_strings_am.xtb b/chromium/ui/strings/translations/ui_strings_am.xtb
index e1961fdafdc..7afaa65b656 100644
--- a/chromium/ui/strings/translations/ui_strings_am.xtb
+++ b/chromium/ui/strings/translations/ui_strings_am.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(ባዶ)</translation>
<translation id="2289052229480071835">በማያ ገጽዎ ላይ ያሉት የንክኪ ዒላማዎችን መታ ያድርጉ።</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> ቴባ/ሰ</translation>
+<translation id="24452542372838207">ማሳወቂያን ዘርጋ</translation>
<translation id="2482878487686419369">ማስታወቂያዎች</translation>
<translation id="2497284189126895209">ሁሉም ፋይሎች</translation>
<translation id="2522350507219695259">ልኬት ማስተካከል ተጠናቅቋል</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">ክፈት</translation>
<translation id="9038489124413477075">ያልተሰየመ አቃፊ</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 ሰከን}one{# ሰከን}other{# ሰከን}}</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_ar.xtb b/chromium/ui/strings/translations/ui_strings_ar.xtb
index f6d28aba77b..31d047a5d8e 100644
--- a/chromium/ui/strings/translations/ui_strings_ar.xtb
+++ b/chromium/ui/strings/translations/ui_strings_ar.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(فارغ)</translation>
<translation id="2289052229480071835">انقر على أهداف اللمس على شاشتك.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> تيرابايت/ثانية</translation>
+<translation id="24452542372838207">توسيع الإشعار</translation>
<translation id="2482878487686419369">الاشعارات</translation>
<translation id="2497284189126895209">الملفّات كلّها</translation>
<translation id="2522350507219695259">اكتملت المعايرة</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">الفتح</translation>
<translation id="9038489124413477075">مجلد بدون اسم</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{ثانية واحدة}zero{# ثانية}two{ثانيتان (#)}few{# ثوانٍ}many{# ثانية}other{# من الثواني}}</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_bg.xtb b/chromium/ui/strings/translations/ui_strings_bg.xtb
index cf67b155d8c..40b817247e0 100644
--- a/chromium/ui/strings/translations/ui_strings_bg.xtb
+++ b/chromium/ui/strings/translations/ui_strings_bg.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(празно)</translation>
<translation id="2289052229480071835">Докоснете съответните цели на екрана.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> ТБ/сек</translation>
+<translation id="24452542372838207">Разгъване на известието</translation>
<translation id="2482878487686419369">Известия</translation>
<translation id="2497284189126895209">Всички файлове</translation>
<translation id="2522350507219695259">Калибрирането завърши</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">отварям</translation>
<translation id="9038489124413477075">Папка без име</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 сек}other{# сек}}</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_bn.xtb b/chromium/ui/strings/translations/ui_strings_bn.xtb
index 689f44e7790..3f86cef1ae5 100644
--- a/chromium/ui/strings/translations/ui_strings_bn.xtb
+++ b/chromium/ui/strings/translations/ui_strings_bn.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(খালি)</translation>
<translation id="2289052229480071835">আপনার স্ক্রীনে স্পর্শ লক্ষ্যগুলি আলতা চাপুন।</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">বিজ্ঞপ্তি প্রসারিত করুন</translation>
<translation id="2482878487686419369">বিজ্ঞপ্তিগুলি</translation>
<translation id="2497284189126895209">সকল ফাইল</translation>
<translation id="2522350507219695259">ক্রমাঙ্কন সম্পূর্ণ হয়েছে</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">খুলুন</translation>
<translation id="9038489124413477075">নামবিহীন ফোল্ডার</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{১ সেকেন্ড}one{# সেকেন্ড}other{# সেকেন্ড}}</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_ca.xtb b/chromium/ui/strings/translations/ui_strings_ca.xtb
index dadf2bb9000..426760e8af1 100644
--- a/chromium/ui/strings/translations/ui_strings_ca.xtb
+++ b/chromium/ui/strings/translations/ui_strings_ca.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(buit)</translation>
<translation id="2289052229480071835">Toca els elements tàctils a la pantalla.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">Desplega la notificació</translation>
<translation id="2482878487686419369">Notificacions</translation>
<translation id="2497284189126895209">Tots els fitxers</translation>
<translation id="2522350507219695259">S'ha acabat de calibrar</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">obrir</translation>
<translation id="9038489124413477075">Carpeta sense nom</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 s}other{# s}}</translation>
+<translation id="9059834730836941392">Replega la notificació</translation>
<translation id="9150735707954472829">Pestanya</translation>
<translation id="9161053988251441839">APLICACIONS SUGGERIDES</translation>
<translation id="9170848237812810038">&amp;Desfés</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_cs.xtb b/chromium/ui/strings/translations/ui_strings_cs.xtb
index 5846316ddf6..05e09b4978c 100644
--- a/chromium/ui/strings/translations/ui_strings_cs.xtb
+++ b/chromium/ui/strings/translations/ui_strings_cs.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(prázdné)</translation>
<translation id="2289052229480071835">Klepněte na cíle klepnutí na obrazovce.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">Rozbalit oznámení</translation>
<translation id="2482878487686419369">Oznámení</translation>
<translation id="2497284189126895209">Všechny soubory</translation>
<translation id="2522350507219695259">Kalibrace je dokončena</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">otevřít</translation>
<translation id="9038489124413477075">Nepojmenovaná složka</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 s}few{# s}many{# s}other{# s}}</translation>
+<translation id="9059834730836941392">Sbalit oznámení</translation>
<translation id="9150735707954472829">Karta</translation>
<translation id="9161053988251441839">NAVRHOVANÉ APLIKACE</translation>
<translation id="9170848237812810038">Z&amp;pět</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_da.xtb b/chromium/ui/strings/translations/ui_strings_da.xtb
index 2fb15912f01..6221426a06d 100644
--- a/chromium/ui/strings/translations/ui_strings_da.xtb
+++ b/chromium/ui/strings/translations/ui_strings_da.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(tom)</translation>
<translation id="2289052229480071835">Tryk på de punkter på skærmen, der kan trykkes på.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/sek.</translation>
+<translation id="24452542372838207">Udvid underretning</translation>
<translation id="2482878487686419369">Underretninger</translation>
<translation id="2497284189126895209">Alle filer</translation>
<translation id="2522350507219695259">Kalibreringen er fuldført</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">åbn</translation>
<translation id="9038489124413477075">Unavngiven mappe</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 sek.}one{# sek.}other{# sek.}}</translation>
+<translation id="9059834730836941392">Skjul underretning</translation>
<translation id="9150735707954472829">Fane</translation>
<translation id="9161053988251441839">FORESLÅEDE APPS</translation>
<translation id="9170848237812810038">&amp;Fortryd</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_de.xtb b/chromium/ui/strings/translations/ui_strings_de.xtb
index 5b1adb5cd1f..50756460234 100644
--- a/chromium/ui/strings/translations/ui_strings_de.xtb
+++ b/chromium/ui/strings/translations/ui_strings_de.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(leer)</translation>
<translation id="2289052229480071835">Tippen Sie auf die Zielelemente auf dem Bildschirm.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">Benachrichtigung erweitern</translation>
<translation id="2482878487686419369">Benachrichtigungen</translation>
<translation id="2497284189126895209">Alle Dateien</translation>
<translation id="2522350507219695259">Die Kalibrierung ist abgeschlossen</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">Öffnen</translation>
<translation id="9038489124413477075">Unbenannter Ordner</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 Sek.}other{# Sek.}}</translation>
+<translation id="9059834730836941392">Benachrichtigung minimieren</translation>
<translation id="9150735707954472829">Tab</translation>
<translation id="9161053988251441839">VORGESCHLAGENE APPS</translation>
<translation id="9170848237812810038">&amp;Rückgängig</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_el.xtb b/chromium/ui/strings/translations/ui_strings_el.xtb
index 195d2361e99..67898142fd9 100644
--- a/chromium/ui/strings/translations/ui_strings_el.xtb
+++ b/chromium/ui/strings/translations/ui_strings_el.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(κενό)</translation>
<translation id="2289052229480071835">Πατήστε τους στόχους αφής στην οθόνη σας.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">Ανάπτυξη ειδοποίησης</translation>
<translation id="2482878487686419369">Ειδοποιήσεις</translation>
<translation id="2497284189126895209">Όλα τα αρχεία</translation>
<translation id="2522350507219695259">Η βαθμονόμηση ολοκληρώθηκε</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">ανοίγω</translation>
<translation id="9038489124413477075">Φάκελος χωρίς όνομα</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 δευτ.}other{# δευτ.}}</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_en-GB.xtb b/chromium/ui/strings/translations/ui_strings_en-GB.xtb
index c878620dd04..fb094171541 100644
--- a/chromium/ui/strings/translations/ui_strings_en-GB.xtb
+++ b/chromium/ui/strings/translations/ui_strings_en-GB.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(empty)</translation>
<translation id="2289052229480071835">Tap the touch targets on your screen.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">Expand notification</translation>
<translation id="2482878487686419369">Notifications</translation>
<translation id="2497284189126895209">All Files</translation>
<translation id="2522350507219695259">Calibration is completed</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">open</translation>
<translation id="9038489124413477075">Unnamed Folder</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 sec}other{# secs}}</translation>
+<translation id="9059834730836941392">Collapse notification</translation>
<translation id="9150735707954472829">Tab</translation>
<translation id="9161053988251441839">SUGGESTED APPS</translation>
<translation id="9170848237812810038">&amp;Undo</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_es-419.xtb b/chromium/ui/strings/translations/ui_strings_es-419.xtb
index 9871a849aea..0e87a0fe1e2 100644
--- a/chromium/ui/strings/translations/ui_strings_es-419.xtb
+++ b/chromium/ui/strings/translations/ui_strings_es-419.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(vacío)</translation>
<translation id="2289052229480071835">Presiona los objetivos táctiles en tu pantalla.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">Expandir notificación</translation>
<translation id="2482878487686419369">Notificaciones</translation>
<translation id="2497284189126895209">Todos los archivos</translation>
<translation id="2522350507219695259">Se completó la calibración</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">abrir</translation>
<translation id="9038489124413477075">Carpeta sin nombre</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 s}other{# s}}</translation>
+<translation id="9059834730836941392">Contraer notificación</translation>
<translation id="9150735707954472829">Pestaña</translation>
<translation id="9161053988251441839">APPS SUGERIDAS</translation>
<translation id="9170848237812810038">&amp;Deshacer</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_es.xtb b/chromium/ui/strings/translations/ui_strings_es.xtb
index 2f13a0ddbe6..e318cf9ddfa 100644
--- a/chromium/ui/strings/translations/ui_strings_es.xtb
+++ b/chromium/ui/strings/translations/ui_strings_es.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(vacío)</translation>
<translation id="2289052229480071835">Toca los elementos táctiles en la pantalla.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">Mostrar notificación</translation>
<translation id="2482878487686419369">Notificaciones</translation>
<translation id="2497284189126895209">Todos los archivos</translation>
<translation id="2522350507219695259">Se ha completado la calibración</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">abrir</translation>
<translation id="9038489124413477075">Carpeta sin nombre</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 s}other{# s}}</translation>
+<translation id="9059834730836941392">Ocultar notificación</translation>
<translation id="9150735707954472829">Pestaña </translation>
<translation id="9161053988251441839">APLICACIONES SUGERIDAS</translation>
<translation id="9170848237812810038">&amp;Deshacer</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_et.xtb b/chromium/ui/strings/translations/ui_strings_et.xtb
index da3a070fb27..3d0fe97bad2 100644
--- a/chromium/ui/strings/translations/ui_strings_et.xtb
+++ b/chromium/ui/strings/translations/ui_strings_et.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(tühi)</translation>
<translation id="2289052229480071835">Puudutage ekraanil puutesihtmärke.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">Laienda märguannet</translation>
<translation id="2482878487686419369">Märguanded</translation>
<translation id="2497284189126895209">Kõik failid</translation>
<translation id="2522350507219695259">Kalibreerimine on lõpetatud</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">avage</translation>
<translation id="9038489124413477075">Nimeta kaust</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 s}other{# s}}</translation>
+<translation id="9059834730836941392">Ahenda märguannet</translation>
<translation id="9150735707954472829">Vahekaart</translation>
<translation id="9161053988251441839">SOOVITATUD RAKENDUSED</translation>
<translation id="9170848237812810038">&amp;Võta tagasi</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_fa.xtb b/chromium/ui/strings/translations/ui_strings_fa.xtb
index e0465029c22..24f21bd3e16 100644
--- a/chromium/ui/strings/translations/ui_strings_fa.xtb
+++ b/chromium/ui/strings/translations/ui_strings_fa.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(خالی)</translation>
<translation id="2289052229480071835">روی اهداف لمسی در صفحه‌تان ضربه بزنید.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> ترابایت/ثانیه</translation>
+<translation id="24452542372838207">بزرگ کردن اعلان</translation>
<translation id="2482878487686419369">اعلان‌ها</translation>
<translation id="2497284189126895209">همه فایل‌ها</translation>
<translation id="2522350507219695259">کالیبراسیون تمام شد</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">باز کنید</translation>
<translation id="9038489124413477075">پوشه بدون نام</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{۱ ثانیه}one{# ثانیه}other{# ثانیه}}</translation>
+<translation id="9059834730836941392">کوچک کردن اعلان</translation>
<translation id="9150735707954472829">Tab</translation>
<translation id="9161053988251441839">برنامه‌های پیشنهادشده</translation>
<translation id="9170848237812810038">&amp;واگرد</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_fi.xtb b/chromium/ui/strings/translations/ui_strings_fi.xtb
index 6129d4f1a2f..80fc6acc914 100644
--- a/chromium/ui/strings/translations/ui_strings_fi.xtb
+++ b/chromium/ui/strings/translations/ui_strings_fi.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(tyhjä)</translation>
<translation id="2289052229480071835">Napauta näytölläsi olevia kosketettavia kohteita.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> Tt/s</translation>
+<translation id="24452542372838207">Laajenna ilmoitus</translation>
<translation id="2482878487686419369">Ilmoitukset</translation>
<translation id="2497284189126895209">Kaikki tiedostot</translation>
<translation id="2522350507219695259">Kalibrointi on valmis.</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">avata</translation>
<translation id="9038489124413477075">Nimetön kansio</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 s}other{# s}}</translation>
+<translation id="9059834730836941392">Tiivistä ilmoitus</translation>
<translation id="9150735707954472829">Välilehti</translation>
<translation id="9161053988251441839">SOVELLUSEHDOTUKSET</translation>
<translation id="9170848237812810038">K&amp;umoa</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_fil.xtb b/chromium/ui/strings/translations/ui_strings_fil.xtb
index 5f7ee547b6d..50666148610 100644
--- a/chromium/ui/strings/translations/ui_strings_fil.xtb
+++ b/chromium/ui/strings/translations/ui_strings_fil.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(walang laman)</translation>
<translation id="2289052229480071835">I-tap ang mga target sa pagpindot sa iyong screen.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> (na) TB/s</translation>
+<translation id="24452542372838207">Palawakin ang notification</translation>
<translation id="2482878487686419369">Mga Abiso</translation>
<translation id="2497284189126895209">Lahat ng Mga File</translation>
<translation id="2522350507219695259">Nakumpleto na ang pag-calibrate</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">buksan</translation>
<translation id="9038489124413477075">Walang Pangalan na Folder</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 segundo}one{# segundo}other{# na segundo}}</translation>
+<translation id="9059834730836941392">I-collapse ang notification</translation>
<translation id="9150735707954472829">Tab</translation>
<translation id="9161053988251441839">MGA IMINUMUNGKAHING APP</translation>
<translation id="9170848237812810038">&amp;I-undo</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_fr.xtb b/chromium/ui/strings/translations/ui_strings_fr.xtb
index 67662ffc7cd..934de20b85f 100644
--- a/chromium/ui/strings/translations/ui_strings_fr.xtb
+++ b/chromium/ui/strings/translations/ui_strings_fr.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(vide)</translation>
<translation id="2289052229480071835">Appuyez sur les cibles tactiles affichées à l'écran.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> To/s</translation>
+<translation id="24452542372838207">Développer la notification</translation>
<translation id="2482878487686419369">Notifications</translation>
<translation id="2497284189126895209">Tous les fichiers</translation>
<translation id="2522350507219695259">Calibrage terminé</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">ouvrir</translation>
<translation id="9038489124413477075">Dossier sans nom</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 s}one{# s}other{# s}}</translation>
+<translation id="9059834730836941392">Réduire la notification</translation>
<translation id="9150735707954472829">Onglet</translation>
<translation id="9161053988251441839">APPLICATIONS SUGGÉRÉES</translation>
<translation id="9170848237812810038">Ann&amp;uler</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_gu.xtb b/chromium/ui/strings/translations/ui_strings_gu.xtb
index 6d20644fa95..bd1ad668090 100644
--- a/chromium/ui/strings/translations/ui_strings_gu.xtb
+++ b/chromium/ui/strings/translations/ui_strings_gu.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(ખાલી)</translation>
<translation id="2289052229480071835">તમારી સ્ક્રીન પર ટચ કરવાના લક્ષ્યોને ટૅપ કરો.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">નોટિફિકેશન વિસ્તૃત કરો</translation>
<translation id="2482878487686419369">સૂચનાઓ</translation>
<translation id="2497284189126895209">બધી ફાઇલો</translation>
<translation id="2522350507219695259">કૅલિબ્રેશન પૂર્ણ થયું</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">ખોલો</translation>
<translation id="9038489124413477075">અનામાંકિત ફોલ્ડર</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 સે}one{# સે}other{# સે}}</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_hi.xtb b/chromium/ui/strings/translations/ui_strings_hi.xtb
index 8548fffe023..6da68dee230 100644
--- a/chromium/ui/strings/translations/ui_strings_hi.xtb
+++ b/chromium/ui/strings/translations/ui_strings_hi.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(खाली)</translation>
<translation id="2289052229480071835">अपनी स्क्रीन पर स्पर्श लक्ष्य पर टैप करें.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">सूचना को विस्तृत करें</translation>
<translation id="2482878487686419369">अधिसूचनाएं</translation>
<translation id="2497284189126895209">सभी फ़ाइलें</translation>
<translation id="2522350507219695259">कैलिब्रेशन पूरा हो गया</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">खोलें</translation>
<translation id="9038489124413477075">अनाम फ़ोल्डर</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 सेकंड}one{# सेकंड}other{# सेकंड}}</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_hr.xtb b/chromium/ui/strings/translations/ui_strings_hr.xtb
index 36d412b3f20..12223437030 100644
--- a/chromium/ui/strings/translations/ui_strings_hr.xtb
+++ b/chromium/ui/strings/translations/ui_strings_hr.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(prazno)</translation>
<translation id="2289052229480071835">Dodirnite ciljeve dodira na zaslonu.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">Proširi obavijest</translation>
<translation id="2482878487686419369">Obavijesti</translation>
<translation id="2497284189126895209">Sve datoteke</translation>
<translation id="2522350507219695259">Kalibracija je gotova</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">otvaranje</translation>
<translation id="9038489124413477075">Neimenovana mapa</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 s}one{# s}few{# s}other{# s}}</translation>
+<translation id="9059834730836941392">Sažmi obavijest</translation>
<translation id="9150735707954472829">Kartica</translation>
<translation id="9161053988251441839">PREDLOŽENE APLIKACIJE</translation>
<translation id="9170848237812810038">&amp;Poništi</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_hu.xtb b/chromium/ui/strings/translations/ui_strings_hu.xtb
index 6fe7fa69e42..54496d27f6a 100644
--- a/chromium/ui/strings/translations/ui_strings_hu.xtb
+++ b/chromium/ui/strings/translations/ui_strings_hu.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(üres)</translation>
<translation id="2289052229480071835">Koppintson a képernyőn az érintési célpontokra.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">Értesítés kibontása</translation>
<translation id="2482878487686419369">Értesítések</translation>
<translation id="2497284189126895209">Minden fájl</translation>
<translation id="2522350507219695259">A kalibrálás befejeződött</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">megnyitás</translation>
<translation id="9038489124413477075">Név nélküli mappa</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 mp}other{# mp}}</translation>
+<translation id="9059834730836941392">Értesítés összecsukása</translation>
<translation id="9150735707954472829">Lap</translation>
<translation id="9161053988251441839">JAVASOLT ALKALMAZÁSOK</translation>
<translation id="9170848237812810038">&amp;Visszavonás</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_id.xtb b/chromium/ui/strings/translations/ui_strings_id.xtb
index 7d6a33a1f27..042b7d6f7df 100644
--- a/chromium/ui/strings/translations/ui_strings_id.xtb
+++ b/chromium/ui/strings/translations/ui_strings_id.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(kosong)</translation>
<translation id="2289052229480071835">Tap target sentuh di layar.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/dtk</translation>
+<translation id="24452542372838207">Luaskan notifikasi</translation>
<translation id="2482878487686419369">Notifikasi</translation>
<translation id="2497284189126895209">Semua Jenis File</translation>
<translation id="2522350507219695259">Kalibrasi selesai</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">buka</translation>
<translation id="9038489124413477075">Folder Tanpa Nama</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 dtk}other{# dtk}}</translation>
+<translation id="9059834730836941392">Ciutkan notifikasi</translation>
<translation id="9150735707954472829">Tab</translation>
<translation id="9161053988251441839">APLIKASI YANG DISARANKAN</translation>
<translation id="9170848237812810038">&amp;Urung</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_it.xtb b/chromium/ui/strings/translations/ui_strings_it.xtb
index cca8990bf87..df43db55d5a 100644
--- a/chromium/ui/strings/translations/ui_strings_it.xtb
+++ b/chromium/ui/strings/translations/ui_strings_it.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(vuoto)</translation>
<translation id="2289052229480071835">Tocca i touch target sul tuo schermo.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">Espandi la notifica</translation>
<translation id="2482878487686419369">Notifiche</translation>
<translation id="2497284189126895209">Tutti i file</translation>
<translation id="2522350507219695259">Calibrazione completata</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">apri</translation>
<translation id="9038489124413477075">Cartella senza nome</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 sec}other{# sec}}</translation>
+<translation id="9059834730836941392">Comprimi la notifica</translation>
<translation id="9150735707954472829">Scheda</translation>
<translation id="9161053988251441839">APP CONSIGLIATE</translation>
<translation id="9170848237812810038">&amp;Annulla</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_iw.xtb b/chromium/ui/strings/translations/ui_strings_iw.xtb
index 693fdc92b3d..bcf0b8cd732 100644
--- a/chromium/ui/strings/translations/ui_strings_iw.xtb
+++ b/chromium/ui/strings/translations/ui_strings_iw.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(ריק)</translation>
<translation id="2289052229480071835">הקש על יעדי המגע במסך.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">הרחבת ההודעה</translation>
<translation id="2482878487686419369">התראות</translation>
<translation id="2497284189126895209">כל הקבצים</translation>
<translation id="2522350507219695259">הכיול הושלם</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">פתח</translation>
<translation id="9038489124413477075">תיקייה ללא שם</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{שנ‘ אחת}two{# שנ‘}many{# שנ‘}other{# שנ‘}}</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_ja.xtb b/chromium/ui/strings/translations/ui_strings_ja.xtb
index 49661fdb37b..cc70393aa70 100644
--- a/chromium/ui/strings/translations/ui_strings_ja.xtb
+++ b/chromium/ui/strings/translations/ui_strings_ja.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(なし)</translation>
<translation id="2289052229480071835">画面に表示されるタップ ターゲットをタップします。</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/秒</translation>
+<translation id="24452542372838207">通知を展開</translation>
<translation id="2482878487686419369">通知</translation>
<translation id="2497284189126895209">すべてのファイル</translation>
<translation id="2522350507219695259">キャリブレーションが完了しました</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">開く</translation>
<translation id="9038489124413477075">名前のないフォルダ</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 秒}other{# 秒}}</translation>
+<translation id="9059834730836941392">通知を折りたたむ</translation>
<translation id="9150735707954472829">タブ</translation>
<translation id="9161053988251441839">おすすめのアプリ</translation>
<translation id="9170848237812810038">取消(&amp;U)</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_kn.xtb b/chromium/ui/strings/translations/ui_strings_kn.xtb
index 7ee5b07443b..c4a5a372e98 100644
--- a/chromium/ui/strings/translations/ui_strings_kn.xtb
+++ b/chromium/ui/strings/translations/ui_strings_kn.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(ಖಾಲಿ)</translation>
<translation id="2289052229480071835">ನಿಮ್ಮ ಪರದೆಯಲ್ಲಿ ಸ್ಪರ್ಶ ಟಾರ್ಗೆಟ್‌ಗಳನ್ನು ಟ್ಯಾಪ್ ಮಾಡಿ.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">ವಿಸ್ತರಿಸುವ ಅಧಿಸೂಚನೆ</translation>
<translation id="2482878487686419369">ಸೂಚನೆಗಳು</translation>
<translation id="2497284189126895209">ಎಲ್ಲ ಫೈಲ್‌ಗಳು</translation>
<translation id="2522350507219695259">ಮಾಪನಾಂಕವು ಪೂರ್ಣಗೊಂಡಿದೆ</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">ತೆರೆ</translation>
<translation id="9038489124413477075">ಹೆಸರಿಸದ ಫೋಲ್ಡರ್</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 ಸೆಕೆಂಡ್}one{# ಸೆಕೆಂಡುಗಳು}other{# ಸೆಕೆಂಡುಗಳು}}</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_ko.xtb b/chromium/ui/strings/translations/ui_strings_ko.xtb
index 6a5cd3edbbd..424831f7169 100644
--- a/chromium/ui/strings/translations/ui_strings_ko.xtb
+++ b/chromium/ui/strings/translations/ui_strings_ko.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(비어있음)</translation>
<translation id="2289052229480071835">화면에서 터치 대상을 탭하세요.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" />TB/s</translation>
+<translation id="24452542372838207">알림 펼치기</translation>
<translation id="2482878487686419369">알림</translation>
<translation id="2497284189126895209">모든 파일</translation>
<translation id="2522350507219695259">보정이 완료되었습니다.</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">열기</translation>
<translation id="9038489124413477075">이름이 없는 폴더</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1초}other{#초}}</translation>
+<translation id="9059834730836941392">알림 접기</translation>
<translation id="9150735707954472829">탭</translation>
<translation id="9161053988251441839">추천 앱</translation>
<translation id="9170848237812810038">실행 취소(&amp;U)</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_lt.xtb b/chromium/ui/strings/translations/ui_strings_lt.xtb
index 0b9d3867840..85ccb38b9e5 100644
--- a/chromium/ui/strings/translations/ui_strings_lt.xtb
+++ b/chromium/ui/strings/translations/ui_strings_lt.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(tuščias)</translation>
<translation id="2289052229480071835">Palieskite jutiklines sritis ekrane.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">Išskleisti pranešimą</translation>
<translation id="2482878487686419369">Pranešimai</translation>
<translation id="2497284189126895209">Visi failai</translation>
<translation id="2522350507219695259">Kalibravimas baigtas</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">atidaryti</translation>
<translation id="9038489124413477075">Aplankas be pavadinimo</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 sek.}one{# sek.}few{# sek.}many{# sek.}other{# sek.}}</translation>
+<translation id="9059834730836941392">Sutraukti pranešimą</translation>
<translation id="9150735707954472829">Skirtukas</translation>
<translation id="9161053988251441839">SIŪLOMOS PROGRAMOS</translation>
<translation id="9170848237812810038">&amp;Atšaukti</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_lv.xtb b/chromium/ui/strings/translations/ui_strings_lv.xtb
index 6cd54539ce9..b444f2bff3e 100644
--- a/chromium/ui/strings/translations/ui_strings_lv.xtb
+++ b/chromium/ui/strings/translations/ui_strings_lv.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(tukšs)</translation>
<translation id="2289052229480071835">Pieskarieties ekrānā redzamajiem pieskāriena mērķiem.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">Izvērst paziņojumu</translation>
<translation id="2482878487686419369">Paziņojumi</translation>
<translation id="2497284189126895209">Visi faili</translation>
<translation id="2522350507219695259">Kalibrēšana ir pabeigta.</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">atvērt</translation>
<translation id="9038489124413477075">Mape bez nosaukuma</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 s}zero{# s}one{# s}other{# s}}</translation>
+<translation id="9059834730836941392">Sakļaut paziņojumu</translation>
<translation id="9150735707954472829">Cilne</translation>
<translation id="9161053988251441839">IETEIKTĀS LIETOTNES</translation>
<translation id="9170848237812810038">&amp;Atsaukt</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_ml.xtb b/chromium/ui/strings/translations/ui_strings_ml.xtb
index 99051d762b7..667fbed983f 100644
--- a/chromium/ui/strings/translations/ui_strings_ml.xtb
+++ b/chromium/ui/strings/translations/ui_strings_ml.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(ശൂന്യം)</translation>
<translation id="2289052229480071835">സ്‌ക്രീനിലുള്ള 'ടാർഗെറ്റുകൾ സ്‌പർശിക്കുക' ടാപ്പുചെയ്യുക.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">അറിയിപ്പ് വികസിപ്പിക്കുക</translation>
<translation id="2482878487686419369">വിജ്ഞാപനങ്ങള്‍‌</translation>
<translation id="2497284189126895209">എല്ലാ ഫയലുകളും</translation>
<translation id="2522350507219695259">കാലിബറേഷൻ പൂർത്തിയായി</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">തുറക്കുക</translation>
<translation id="9038489124413477075">പേരിടാത്ത ഫോൾഡർ</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{ഒരു സെക്കൻഡ്}other{# സെക്കൻഡ്}}</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_mr.xtb b/chromium/ui/strings/translations/ui_strings_mr.xtb
index 15799be80c4..3e3a09a3d20 100644
--- a/chromium/ui/strings/translations/ui_strings_mr.xtb
+++ b/chromium/ui/strings/translations/ui_strings_mr.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(रिक्त)</translation>
<translation id="2289052229480071835">आपल्या स्क्रीनवरील लक्ष्यांना स्पर्श करा टॅप करा.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">सूचना विस्तृत करा</translation>
<translation id="2482878487686419369">सूचना</translation>
<translation id="2497284189126895209">सर्व फाइल</translation>
<translation id="2522350507219695259">कॅलिब्रेशन पूर्ण झाले</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">उघडा</translation>
<translation id="9038489124413477075">अनामित फोल्डर</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 से}one{# से}other{# से}}</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_ms.xtb b/chromium/ui/strings/translations/ui_strings_ms.xtb
index 21b6a456df6..a14ce96f241 100644
--- a/chromium/ui/strings/translations/ui_strings_ms.xtb
+++ b/chromium/ui/strings/translations/ui_strings_ms.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(kosong)</translation>
<translation id="2289052229480071835">Ketik sasaran sentuhan pada skrin anda.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">Kembangkan pemberitahuan</translation>
<translation id="2482878487686419369">Pemberitahuan</translation>
<translation id="2497284189126895209">Semua Fail</translation>
<translation id="2522350507219695259">Penentukuran telah selesai</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">buka</translation>
<translation id="9038489124413477075">Folder Tanpa Nama</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 saat}other{# saat}}</translation>
+<translation id="9059834730836941392">Runtuhkan pemberitahuan</translation>
<translation id="9150735707954472829">Tab</translation>
<translation id="9161053988251441839">APL DISYORKAN</translation>
<translation id="9170848237812810038">&amp;Buat asal</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_nl.xtb b/chromium/ui/strings/translations/ui_strings_nl.xtb
index 5b25b062e4b..5c19318ec2b 100644
--- a/chromium/ui/strings/translations/ui_strings_nl.xtb
+++ b/chromium/ui/strings/translations/ui_strings_nl.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(leeg)</translation>
<translation id="2289052229480071835">Tik op de tikdoelen op je scherm.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">Melding uitvouwen</translation>
<translation id="2482878487686419369">Meldingen</translation>
<translation id="2497284189126895209">Alle bestanden</translation>
<translation id="2522350507219695259">Kalibratie is voltooid</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">openen</translation>
<translation id="9038489124413477075">Naamloze map</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 sec.}other{# sec.}}</translation>
+<translation id="9059834730836941392">Melding samenvouwen</translation>
<translation id="9150735707954472829">Tabblad</translation>
<translation id="9161053988251441839">VOORGESTELDE APPS</translation>
<translation id="9170848237812810038">&amp;Ongedaan maken</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_no.xtb b/chromium/ui/strings/translations/ui_strings_no.xtb
index d4aca96af68..60d8d3653a8 100644
--- a/chromium/ui/strings/translations/ui_strings_no.xtb
+++ b/chromium/ui/strings/translations/ui_strings_no.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(tom)</translation>
<translation id="2289052229480071835">Trykk på berøringsmålene på skjermen.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB per sek</translation>
+<translation id="24452542372838207">Vis varselet</translation>
<translation id="2482878487686419369">Varsler</translation>
<translation id="2497284189126895209">Alle filer</translation>
<translation id="2522350507219695259">Kalibreringen er ferdig</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">åpne</translation>
<translation id="9038489124413477075">Mappe uten navn</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 sek}other{# sek}}</translation>
+<translation id="9059834730836941392">Skjul varselet</translation>
<translation id="9150735707954472829">Fane</translation>
<translation id="9161053988251441839">FORESLÅTTE APPER</translation>
<translation id="9170848237812810038">&amp;Angre</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_pl.xtb b/chromium/ui/strings/translations/ui_strings_pl.xtb
index a0aa3514f97..3c71b17d470 100644
--- a/chromium/ui/strings/translations/ui_strings_pl.xtb
+++ b/chromium/ui/strings/translations/ui_strings_pl.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(puste)</translation>
<translation id="2289052229480071835">Kliknij docelowe obszary kliknięcia na ekranie.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">Rozwiń powiadomienie</translation>
<translation id="2482878487686419369">Powiadomienia</translation>
<translation id="2497284189126895209">Wszystkie pliki</translation>
<translation id="2522350507219695259">Kalibracja została ukończona</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">otwórz</translation>
<translation id="9038489124413477075">Folder bez nazwy</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 s}few{# s}many{# s}other{# s}}</translation>
+<translation id="9059834730836941392">Zwiń powiadomienie</translation>
<translation id="9150735707954472829">Karta</translation>
<translation id="9161053988251441839">SUGEROWANE APLIKACJE</translation>
<translation id="9170848237812810038">&amp;Cofnij</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_pt-BR.xtb b/chromium/ui/strings/translations/ui_strings_pt-BR.xtb
index c3e19d18cd8..f1610776240 100644
--- a/chromium/ui/strings/translations/ui_strings_pt-BR.xtb
+++ b/chromium/ui/strings/translations/ui_strings_pt-BR.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(vazio)</translation>
<translation id="2289052229480071835">Toque nas áreas de toque da tela.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">Expandir notificação</translation>
<translation id="2482878487686419369">Notificações</translation>
<translation id="2497284189126895209">Todos os arquivos</translation>
<translation id="2522350507219695259">A calibração está concluída</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">abrir</translation>
<translation id="9038489124413477075">Pasta sem nome</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 s}one{# s}other{# s}}</translation>
+<translation id="9059834730836941392">Recolher notificação</translation>
<translation id="9150735707954472829">Guia</translation>
<translation id="9161053988251441839">APPS SUGERIDOS</translation>
<translation id="9170848237812810038">&amp;Desfazer</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_pt-PT.xtb b/chromium/ui/strings/translations/ui_strings_pt-PT.xtb
index 7660857fc1a..10a29e211a6 100644
--- a/chromium/ui/strings/translations/ui_strings_pt-PT.xtb
+++ b/chromium/ui/strings/translations/ui_strings_pt-PT.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(vazio)</translation>
<translation id="2289052229480071835">Toque nos alvos de toque no ecrã.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">Expandir notificação</translation>
<translation id="2482878487686419369">Notificações</translation>
<translation id="2497284189126895209">Todos os ficheiros</translation>
<translation id="2522350507219695259">A calibração foi concluída</translation>
@@ -110,14 +111,14 @@
<translation id="6699343763173986273">Faixa seguinte de multimédia</translation>
<translation id="6786750046913594791">Fechar pasta</translation>
<translation id="6808150112686056157">Parar multimédia</translation>
-<translation id="6845383723252244143">Seleccionar pasta</translation>
+<translation id="6845383723252244143">Selecionar pasta</translation>
<translation id="6845533974506654842">premir</translation>
<translation id="6863590663815976734">{HOURS,plural, =1{Falta 1 hora}one{# hours left}other{Faltam # horas}}</translation>
<translation id="688711909580084195">Página Web Sem Nome</translation>
<translation id="6907759265145635167"><ph name="QUANTITY" /> PB/s</translation>
<translation id="6917971086528278418">{YEARS,plural, =1{Falta 1 ano}one{# years left}other{Faltam # anos}}</translation>
<translation id="6918245111648057970">Permitir as seguintes notificações para cada utilizador:</translation>
-<translation id="6945221475159498467">Seleccionar</translation>
+<translation id="6945221475159498467">Selecionar</translation>
<translation id="6965382102122355670">OK</translation>
<translation id="7052633198403197513">F1</translation>
<translation id="7130207228079676353">MUITO PROVAVELMENTE</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">abrir</translation>
<translation id="9038489124413477075">Pasta sem nome</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 seg}one{# secs}other{# seg}}</translation>
+<translation id="9059834730836941392">Reduzir notificação</translation>
<translation id="9150735707954472829">Tabulação</translation>
<translation id="9161053988251441839">APLICAÇÕES SUGERIDAS</translation>
<translation id="9170848237812810038">An&amp;ular</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_ro.xtb b/chromium/ui/strings/translations/ui_strings_ro.xtb
index 24dd4de1ad1..f53c0b1896a 100644
--- a/chromium/ui/strings/translations/ui_strings_ro.xtb
+++ b/chromium/ui/strings/translations/ui_strings_ro.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(gol)</translation>
<translation id="2289052229480071835">Atinge țintele de atingere de pe ecran.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">Extinde notificarea</translation>
<translation id="2482878487686419369">Notificări</translation>
<translation id="2497284189126895209">Toate fișierele</translation>
<translation id="2522350507219695259">Calibrarea este finalizată</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">deschide</translation>
<translation id="9038489124413477075">Dosar fără nume</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{O sec.}few{# sec.}other{# sec.}}</translation>
+<translation id="9059834730836941392">Restrânge notificarea</translation>
<translation id="9150735707954472829">Filă</translation>
<translation id="9161053988251441839">APLICAȚII SUGERATE</translation>
<translation id="9170848237812810038">&amp;Anulează</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_ru.xtb b/chromium/ui/strings/translations/ui_strings_ru.xtb
index 4169660ebbc..dfc0806c04d 100644
--- a/chromium/ui/strings/translations/ui_strings_ru.xtb
+++ b/chromium/ui/strings/translations/ui_strings_ru.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(пусто)</translation>
<translation id="2289052229480071835">Коснитесь интерактивных элементов на экране.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> ТБ/с</translation>
+<translation id="24452542372838207">Развернуть уведомление</translation>
<translation id="2482878487686419369">Оповещения</translation>
<translation id="2497284189126895209">Все файлы</translation>
<translation id="2522350507219695259">Калибровка завершена</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">открыть</translation>
<translation id="9038489124413477075">Без названия</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 сек.}one{# сек.}few{# сек.}many{# сек.}other{# сек.}}</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_sk.xtb b/chromium/ui/strings/translations/ui_strings_sk.xtb
index c73ccddb1a3..01db9a46bb6 100644
--- a/chromium/ui/strings/translations/ui_strings_sk.xtb
+++ b/chromium/ui/strings/translations/ui_strings_sk.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(prázdne)</translation>
<translation id="2289052229480071835">Klepnite na dotykové ciele na obrazovke.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">Rozbaliť upozornenie</translation>
<translation id="2482878487686419369">Upozornenia</translation>
<translation id="2497284189126895209">Všetky súbory</translation>
<translation id="2522350507219695259">Kalibrácia je dokončená</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">otvorenie</translation>
<translation id="9038489124413477075">Priečinok bez názvu</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 s}few{# s}many{# s}other{# s}}</translation>
+<translation id="9059834730836941392">Zbaliť upozornenie</translation>
<translation id="9150735707954472829">Karta</translation>
<translation id="9161053988251441839">ODPORÚČANÉ APLIKÁCIE</translation>
<translation id="9170848237812810038">&amp;Naspäť</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_sl.xtb b/chromium/ui/strings/translations/ui_strings_sl.xtb
index c6862817420..ea8fa4ac1f5 100644
--- a/chromium/ui/strings/translations/ui_strings_sl.xtb
+++ b/chromium/ui/strings/translations/ui_strings_sl.xtb
@@ -28,6 +28,7 @@
<translation id="2190355936436201913">(prazno)</translation>
<translation id="2289052229480071835">Dotaknite se ciljev za dotik na zaslonu.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">Razširi obvestilo</translation>
<translation id="2482878487686419369">Obvestila</translation>
<translation id="2497284189126895209">Vse datoteke</translation>
<translation id="2522350507219695259">Umerjanje je končano</translation>
@@ -152,6 +153,7 @@
<translation id="9002566407876343676">odpreti</translation>
<translation id="9038489124413477075">Neimenovana mapa</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 s}one{# s}two{# s}few{# s}other{# s}}</translation>
+<translation id="9059834730836941392">Strni obvestilo</translation>
<translation id="9150735707954472829">Zavihek</translation>
<translation id="9161053988251441839">PREDLAGANE APLIKACIJE</translation>
<translation id="9170848237812810038">&amp;Razveljavi</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_sr.xtb b/chromium/ui/strings/translations/ui_strings_sr.xtb
index abc0228cae5..5240068d11d 100644
--- a/chromium/ui/strings/translations/ui_strings_sr.xtb
+++ b/chromium/ui/strings/translations/ui_strings_sr.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(празно)</translation>
<translation id="2289052229480071835">Додирните циљна поља за додир на екрану.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">Прошири обавештење</translation>
<translation id="2482878487686419369">Обавештења</translation>
<translation id="2497284189126895209">Све датотеке</translation>
<translation id="2522350507219695259">Калибрација је довршена</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">отварање</translation>
<translation id="9038489124413477075">Неименовани директоријум</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 сек}one{# сек}few{# сек}other{# сек}}</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_sv.xtb b/chromium/ui/strings/translations/ui_strings_sv.xtb
index c9de27633e8..c64dcfb5fb7 100644
--- a/chromium/ui/strings/translations/ui_strings_sv.xtb
+++ b/chromium/ui/strings/translations/ui_strings_sv.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(tom)</translation>
<translation id="2289052229480071835">Tryck på tryckområdena på skärmen.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/sek</translation>
+<translation id="24452542372838207">Utöka avisering</translation>
<translation id="2482878487686419369">Aviseringar</translation>
<translation id="2497284189126895209">Alla filer</translation>
<translation id="2522350507219695259">Kalibreringen är slutförd</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">öppna</translation>
<translation id="9038489124413477075">Namnlös mapp</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 sek}other{# sek}}</translation>
+<translation id="9059834730836941392">Komprimera avisering</translation>
<translation id="9150735707954472829">Flik</translation>
<translation id="9161053988251441839">FÖRESLAGNA APPAR</translation>
<translation id="9170848237812810038">&amp;Ångra</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_sw.xtb b/chromium/ui/strings/translations/ui_strings_sw.xtb
index e2c318c23e0..c285e3059f5 100644
--- a/chromium/ui/strings/translations/ui_strings_sw.xtb
+++ b/chromium/ui/strings/translations/ui_strings_sw.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(tupu)</translation>
<translation id="2289052229480071835">Gonga viashirio vya kugusa kwenye skrini yako.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">Panua arifa</translation>
<translation id="2482878487686419369">Arifa</translation>
<translation id="2497284189126895209">Faili zote</translation>
<translation id="2522350507219695259">Imemaliza kurekebisha usahihi</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">fungua</translation>
<translation id="9038489124413477075">Folda isiyo na jina</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{Sekunde 1}other{Sekunde #}}</translation>
+<translation id="9059834730836941392">Kunja arifa</translation>
<translation id="9150735707954472829">Kichupo</translation>
<translation id="9161053988251441839">PROGRAMU ZINAZOPENDEKEZWA</translation>
<translation id="9170848237812810038">&amp;Tendua</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_ta.xtb b/chromium/ui/strings/translations/ui_strings_ta.xtb
index 0ddb7cde10c..19457f4c5af 100644
--- a/chromium/ui/strings/translations/ui_strings_ta.xtb
+++ b/chromium/ui/strings/translations/ui_strings_ta.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(காலி)</translation>
<translation id="2289052229480071835">உங்கள் திரையில் இருக்கும் தொடுவதற்கான இலக்கிடங்களைத் தட்டவும்.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> டெ.பை/வி</translation>
+<translation id="24452542372838207">அறிவிப்பை விரிவாக்கு</translation>
<translation id="2482878487686419369">அறிவிப்புகள்</translation>
<translation id="2497284189126895209">அனைத்து கோப்புகளும்</translation>
<translation id="2522350507219695259">அளவுத்திருத்தம் முடிந்தது</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">திற</translation>
<translation id="9038489124413477075">பெயரிடப்படாதக் கோப்புறை</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 நொடி}other{# நொடிகள்}}</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_te.xtb b/chromium/ui/strings/translations/ui_strings_te.xtb
index 554cddcc884..6c8646b9b20 100644
--- a/chromium/ui/strings/translations/ui_strings_te.xtb
+++ b/chromium/ui/strings/translations/ui_strings_te.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(ఖాళీ)</translation>
<translation id="2289052229480071835">మీ స్క్రీన్‌పై ఉన్న స్పర్శ లక్ష్యాలను నొక్కండి.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">నోటిఫికేషన్‌ని విస్తరించు</translation>
<translation id="2482878487686419369">ప్రకటనలు</translation>
<translation id="2497284189126895209">మొత్తం ఫైళ్లు</translation>
<translation id="2522350507219695259">క్రమాంకనం పూర్తయింది</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">తెరువు</translation>
<translation id="9038489124413477075">పేరులేని ఫోల్డర్</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 సెక.}other{# సెక.}}</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 5fb90c761d3..ae7940bcf1c 100644
--- a/chromium/ui/strings/translations/ui_strings_th.xtb
+++ b/chromium/ui/strings/translations/ui_strings_th.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(ว่างเปล่า)</translation>
<translation id="2289052229480071835">แตะเป้าหมายการสัมผัสในหน้าจอ</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/วินาที</translation>
+<translation id="24452542372838207">ขยายการแจ้งเตือน</translation>
<translation id="2482878487686419369">การแจ้งเตือน</translation>
<translation id="2497284189126895209">ไฟล์ทั้งหมด</translation>
<translation id="2522350507219695259">การปรับเทียบเสร็จสมบูรณ์</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">เปิด</translation>
<translation id="9038489124413477075">โฟลเดอร์ที่ไม่มีชื่อ</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 วินาที}other{# วินาที}}</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_tr.xtb b/chromium/ui/strings/translations/ui_strings_tr.xtb
index dc33caa13a5..9992af5c08a 100644
--- a/chromium/ui/strings/translations/ui_strings_tr.xtb
+++ b/chromium/ui/strings/translations/ui_strings_tr.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(boş)</translation>
<translation id="2289052229480071835">Ekranınızda dokunma hedeflerine dokunun.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/sn</translation>
+<translation id="24452542372838207">Bildirimi genişlet</translation>
<translation id="2482878487686419369">Bildirimler</translation>
<translation id="2497284189126895209">Tüm Dosyalar</translation>
<translation id="2522350507219695259">Kalibrasyon tamamlandı</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">açma</translation>
<translation id="9038489124413477075">Adsız Klasör</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 sn.}other{# sn.}}</translation>
+<translation id="9059834730836941392">Bildirimi daralt</translation>
<translation id="9150735707954472829">Sekme</translation>
<translation id="9161053988251441839">ÖNERİLEN UYGULAMALAR</translation>
<translation id="9170848237812810038">&amp;Geri al</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_uk.xtb b/chromium/ui/strings/translations/ui_strings_uk.xtb
index 93f0c155963..d1ffc268540 100644
--- a/chromium/ui/strings/translations/ui_strings_uk.xtb
+++ b/chromium/ui/strings/translations/ui_strings_uk.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(пусто)</translation>
<translation id="2289052229480071835">Торкніться елементів для дотику на екрані.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> ТБ/сек.</translation>
+<translation id="24452542372838207">Розгорнути сповіщення</translation>
<translation id="2482878487686419369">Сповіщення</translation>
<translation id="2497284189126895209">Усі файли</translation>
<translation id="2522350507219695259">Калібрування завершено</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">відкрити</translation>
<translation id="9038489124413477075">Папка без назви</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 с}one{# с}few{# с}many{# с}other{# с}}</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_vi.xtb b/chromium/ui/strings/translations/ui_strings_vi.xtb
index 58c7ae0da5e..cb24dbeed75 100644
--- a/chromium/ui/strings/translations/ui_strings_vi.xtb
+++ b/chromium/ui/strings/translations/ui_strings_vi.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(trống)</translation>
<translation id="2289052229480071835">Nhấn vào các mục tiêu cảm ứng trên màn hình của bạn.</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/giây</translation>
+<translation id="24452542372838207">Mở rộng thông báo</translation>
<translation id="2482878487686419369">Thông báo</translation>
<translation id="2497284189126895209">Tất cả Tệp tin</translation>
<translation id="2522350507219695259">Hiệu chỉnh xong</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">mở</translation>
<translation id="9038489124413477075">Thư mục không có tên</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 giây}other{# giây}}</translation>
+<translation id="9059834730836941392">Thu gọn thông báo</translation>
<translation id="9150735707954472829">Tab</translation>
<translation id="9161053988251441839">ỨNG DỤNG ĐƯỢC ĐỀ XUẤT</translation>
<translation id="9170848237812810038">H&amp;oàn tác</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_zh-CN.xtb b/chromium/ui/strings/translations/ui_strings_zh-CN.xtb
index e71d3406e52..11056d3a7ec 100644
--- a/chromium/ui/strings/translations/ui_strings_zh-CN.xtb
+++ b/chromium/ui/strings/translations/ui_strings_zh-CN.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(空)</translation>
<translation id="2289052229480071835">点按您屏幕上的触摸目标。</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/s</translation>
+<translation id="24452542372838207">展开通知</translation>
<translation id="2482878487686419369">通知</translation>
<translation id="2497284189126895209">所有文件</translation>
<translation id="2522350507219695259">已完成校准</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">打开</translation>
<translation id="9038489124413477075">未命名的文件夹</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 秒}other{# 秒}}</translation>
+<translation id="9059834730836941392">收起通知</translation>
<translation id="9150735707954472829">标签</translation>
<translation id="9161053988251441839">推荐的应用</translation>
<translation id="9170848237812810038">撤消(&amp;U)</translation>
diff --git a/chromium/ui/strings/translations/ui_strings_zh-TW.xtb b/chromium/ui/strings/translations/ui_strings_zh-TW.xtb
index 4392f8050f9..0a48672dc18 100644
--- a/chromium/ui/strings/translations/ui_strings_zh-TW.xtb
+++ b/chromium/ui/strings/translations/ui_strings_zh-TW.xtb
@@ -32,6 +32,7 @@
<translation id="2190355936436201913">(空白)</translation>
<translation id="2289052229480071835">輕觸畫面上的觸控目標。</translation>
<translation id="2297836609126180313"><ph name="QUANTITY" /> TB/秒</translation>
+<translation id="24452542372838207">展開通知</translation>
<translation id="2482878487686419369">通知</translation>
<translation id="2497284189126895209">所有檔案</translation>
<translation id="2522350507219695259">校正完成</translation>
@@ -162,6 +163,7 @@
<translation id="9002566407876343676">開啟</translation>
<translation id="9038489124413477075">未命名的資料夾</translation>
<translation id="9044832324875206639">{SECONDS,plural, =1{1 秒}other{# 秒}}</translation>
+<translation id="9059834730836941392">收合通知</translation>
<translation id="9150735707954472829">分頁</translation>
<translation id="9161053988251441839">建議使用的應用程式</translation>
<translation id="9170848237812810038">取消(&amp;U)</translation>
diff --git a/chromium/ui/strings/ui_strings.grd b/chromium/ui/strings/ui_strings.grd
index 7ece91dd9d8..310e90a4ffc 100644
--- a/chromium/ui/strings/ui_strings.grd
+++ b/chromium/ui/strings/ui_strings.grd
@@ -634,6 +634,12 @@ need to be translated for each locale.-->
<message name="IDS_MESSAGE_CENTER_CLEAR_ALL" desc="The button for clearing all notifications.">
Clear All
</message>
+ <message name="IDS_MESSAGE_CENTER_EXPAND_NOTIFICATION" desc="The button for expanding the notification. By clicking this, the long message and the buttons of the notification are shown.">
+ Expand notification
+ </message>
+ <message name="IDS_MESSAGE_CENTER_COLLAPSE_NOTIFICATION" desc="The button for collapsing the notification. By clicking this, the long message and the buttons of the notification are hidden.">
+ Collapse notification
+ </message>
<message name="IDS_MESSAGE_CENTER_LIST_NOTIFICATION_MESSAGE_WITH_DIVIDER" desc="The divider symbol of the title and the message of a sub item in list notification. In English, the title is on the left of this text. In RTL languages, the title is on the right of this message.">
''' - <ph name="message">$1<ex>This is the message!</ex></ph>'''
</message>
diff --git a/chromium/ui/touch_selection/BUILD.gn b/chromium/ui/touch_selection/BUILD.gn
index 110a4e0626e..233dffad714 100644
--- a/chromium/ui/touch_selection/BUILD.gn
+++ b/chromium/ui/touch_selection/BUILD.gn
@@ -38,9 +38,10 @@ component("touch_selection") {
if (use_aura) {
deps += [
+ "//services/ui/public/interfaces",
"//skia:skia",
- "//ui/aura:aura",
- "//ui/aura_extra:aura_extra",
+ "//ui/aura",
+ "//ui/aura_extra",
"//ui/compositor:compositor",
"//ui/gfx:gfx",
"//ui/resources",
diff --git a/chromium/ui/touch_selection/DEPS b/chromium/ui/touch_selection/DEPS
index 5b830344f32..e81e69afb83 100644
--- a/chromium/ui/touch_selection/DEPS
+++ b/chromium/ui/touch_selection/DEPS
@@ -1,4 +1,5 @@
include_rules = [
+ "+services/ui/public/interfaces",
"+ui/aura",
"+ui/aura_extra",
"+ui/base",
diff --git a/chromium/ui/touch_selection/touch_handle.cc b/chromium/ui/touch_selection/touch_handle.cc
index ad81711ac6b..ee1c765d17e 100644
--- a/chromium/ui/touch_selection/touch_handle.cc
+++ b/chromium/ui/touch_selection/touch_handle.cc
@@ -3,6 +3,7 @@
// found in the LICENSE file.
#include "ui/touch_selection/touch_handle.h"
+#include "base/metrics/histogram_macros.h"
#include <algorithm>
#include <cmath>
@@ -95,6 +96,7 @@ void TouchHandle::SetEnabled(bool enabled) {
if (enabled_ == enabled)
return;
if (!enabled) {
+ SetVisible(false, ANIMATION_NONE);
EndDrag();
EndFade();
}
@@ -262,7 +264,7 @@ void TouchHandle::UpdateHandleLayout() {
// Update mirror values only when dragging has stopped to prevent unwanted
// inversion while dragging of handles.
- if (client_->IsAdaptiveHandleOrientationEnabled() && !is_dragging_) {
+ if (!is_dragging_) {
gfx::RectF handle_bounds = drawable_->GetVisibleBounds();
bool mirror_horizontal = false;
bool mirror_vertical = false;
@@ -276,22 +278,52 @@ void TouchHandle::UpdateHandleLayout() {
const float top_y_mirrored =
focus_top_.y() - handle_height + viewport_rect_.y();
- // In case the viewport height is small, like webview, avoid inversion.
- if (bottom_y_unmirrored > viewport_rect_.bottom() &&
- top_y_mirrored > viewport_rect_.y()) {
- mirror_vertical = true;
+ const float bottom_y_clipped =
+ std::max(bottom_y_unmirrored - viewport_rect_.bottom(), 0.f);
+ const float top_y_clipped =
+ std::max(viewport_rect_.y() - top_y_mirrored, 0.f);
+
+ mirror_vertical = top_y_clipped < bottom_y_clipped;
+
+ const float best_y_clipped =
+ mirror_vertical ? top_y_clipped : bottom_y_clipped;
+
+ UMA_HISTOGRAM_PERCENTAGE(
+ "Event.TouchSelectionHandle.BottomHandleClippingPercentage",
+ static_cast<int>((bottom_y_clipped / handle_height) * 100));
+ UMA_HISTOGRAM_PERCENTAGE(
+ "Event.TouchSelectionHandle.BestVerticalClippingPercentage",
+ static_cast<int>((best_y_clipped / handle_height) * 100));
+ UMA_HISTOGRAM_BOOLEAN(
+ "Event.TouchSelectionHandle.ShouldFlipHandleVertically",
+ mirror_vertical);
+ UMA_HISTOGRAM_PERCENTAGE(
+ "Event.TouchSelectionHandle.FlippingImprovementPercentage",
+ static_cast<int>(((bottom_y_clipped - best_y_clipped) / handle_height) *
+ 100));
+
+ if (orientation_ == TouchHandleOrientation::LEFT) {
+ const float left_x_clipped = std::max(
+ viewport_rect_.x() - (focus_bottom_.x() - handle_width), 0.f);
+ UMA_HISTOGRAM_PERCENTAGE(
+ "Event.TouchSelectionHandle.LeftHandleClippingPercentage",
+ static_cast<int>((left_x_clipped / handle_height) * 100));
+ if (left_x_clipped > 0)
+ mirror_horizontal = true;
+ } else if (orientation_ == TouchHandleOrientation::RIGHT) {
+ const float right_x_clipped = std::max(
+ (focus_bottom_.x() + handle_width) - viewport_rect_.right(), 0.f);
+ UMA_HISTOGRAM_PERCENTAGE(
+ "Event.TouchSelectionHandle.RightHandleClippingPercentage",
+ static_cast<int>((right_x_clipped / handle_height) * 100));
+ if (right_x_clipped > 0)
+ mirror_horizontal = true;
}
- if (orientation_ == TouchHandleOrientation::LEFT &&
- focus_bottom_.x() - handle_width < viewport_rect_.x()) {
- mirror_horizontal = true;
- } else if (orientation_ == TouchHandleOrientation::RIGHT &&
- focus_bottom_.x() + handle_width > viewport_rect_.right()) {
- mirror_horizontal = true;
+ if (client_->IsAdaptiveHandleOrientationEnabled()) {
+ mirror_horizontal_ = mirror_horizontal;
+ mirror_vertical_ = mirror_vertical;
}
-
- mirror_horizontal_ = mirror_horizontal;
- mirror_vertical_ = mirror_vertical;
}
drawable_->SetOrientation(orientation_, mirror_vertical_, mirror_horizontal_);
diff --git a/chromium/ui/touch_selection/touch_handle.h b/chromium/ui/touch_selection/touch_handle.h
index 5d581e50034..3815fea5237 100644
--- a/chromium/ui/touch_selection/touch_handle.h
+++ b/chromium/ui/touch_selection/touch_handle.h
@@ -122,6 +122,7 @@ class UI_TOUCH_SELECTION_EXPORT TouchHandle : public TouchSelectionDraggable {
const gfx::PointF& focus_bottom() const { return focus_bottom_; }
TouchHandleOrientation orientation() const { return orientation_; }
+ float alpha() const { return alpha_; }
private:
gfx::PointF ComputeHandleOrigin() const;
diff --git a/chromium/ui/touch_selection/touch_handle_drawable_aura.cc b/chromium/ui/touch_selection/touch_handle_drawable_aura.cc
index d61ff09ac71..ed2914fef14 100644
--- a/chromium/ui/touch_selection/touch_handle_drawable_aura.cc
+++ b/chromium/ui/touch_selection/touch_handle_drawable_aura.cc
@@ -4,6 +4,7 @@
#include "ui/touch_selection/touch_handle_drawable_aura.h"
+#include "services/ui/public/interfaces/window_tree_constants.mojom.h"
#include "ui/aura/window.h"
#include "ui/aura/window_targeter.h"
#include "ui/aura_extra/image_window_delegate.h"
@@ -68,7 +69,7 @@ TouchHandleDrawableAura::TouchHandleDrawableAura(aura::Window* parent)
window_->SetTransparent(true);
window_->Init(LAYER_TEXTURED);
window_->set_owned_by_parent(false);
- window_->set_ignore_events(true);
+ window_->SetEventTargetingPolicy(ui::mojom::EventTargetingPolicy::NONE);
parent->AddChild(window_.get());
}
diff --git a/chromium/ui/touch_selection/touch_handle_unittest.cc b/chromium/ui/touch_selection/touch_handle_unittest.cc
index 7c07f4462bd..890e86d52e2 100644
--- a/chromium/ui/touch_selection/touch_handle_unittest.cc
+++ b/chromium/ui/touch_selection/touch_handle_unittest.cc
@@ -337,8 +337,11 @@ TEST_F(TouchHandleTest, Enabled) {
// Disabling mid-animation should cancel the animation.
handle.SetEnabled(true);
- UpdateHandleVisibility(handle, false, TouchHandle::ANIMATION_SMOOTH);
- EXPECT_TRUE(drawable().visible);
+ UpdateHandleVisibility(handle, true, TouchHandle::ANIMATION_SMOOTH);
+ EXPECT_TRUE(drawable().enabled);
+ EXPECT_EQ(0.f, drawable().alpha);
+ // Since alpha value is 0, visibility of drawable will be false.
+ EXPECT_FALSE(drawable().visible);
EXPECT_TRUE(GetAndResetNeedsAnimate());
handle.SetEnabled(false);
EXPECT_FALSE(drawable().enabled);
diff --git a/chromium/ui/touch_selection/touch_selection_controller_test_api.cc b/chromium/ui/touch_selection/touch_selection_controller_test_api.cc
index 17bdfa6691c..fe5a14306f1 100644
--- a/chromium/ui/touch_selection/touch_selection_controller_test_api.cc
+++ b/chromium/ui/touch_selection/touch_selection_controller_test_api.cc
@@ -20,6 +20,20 @@ bool TouchSelectionControllerTestApi::GetEndVisible() const {
return controller_->GetEndVisible();
}
+float TouchSelectionControllerTestApi::GetStartAlpha() const {
+ if (controller_->active_status_ == TouchSelectionController::SELECTION_ACTIVE)
+ return controller_->start_selection_handle_->alpha();
+
+ return 0.f;
+}
+
+float TouchSelectionControllerTestApi::GetEndAlpha() const {
+ if (controller_->active_status_ == TouchSelectionController::SELECTION_ACTIVE)
+ return controller_->end_selection_handle_->alpha();
+
+ return 0.f;
+}
+
TouchHandleOrientation
TouchSelectionControllerTestApi::GetStartHandleOrientation() const {
if (controller_->active_status_ != TouchSelectionController::SELECTION_ACTIVE)
diff --git a/chromium/ui/touch_selection/touch_selection_controller_test_api.h b/chromium/ui/touch_selection/touch_selection_controller_test_api.h
index 66ce6db027d..6454b9e8999 100644
--- a/chromium/ui/touch_selection/touch_selection_controller_test_api.h
+++ b/chromium/ui/touch_selection/touch_selection_controller_test_api.h
@@ -20,6 +20,8 @@ class TouchSelectionControllerTestApi {
bool GetStartVisible() const;
bool GetEndVisible() const;
+ float GetStartAlpha() const;
+ float GetEndAlpha() const;
TouchHandleOrientation GetStartHandleOrientation() const;
TouchHandleOrientation GetEndHandleOrientation() const;
diff --git a/chromium/ui/touch_selection/touch_selection_controller_unittest.cc b/chromium/ui/touch_selection/touch_selection_controller_unittest.cc
index 9d59383729c..a9089df1fd6 100644
--- a/chromium/ui/touch_selection/touch_selection_controller_unittest.cc
+++ b/chromium/ui/touch_selection/touch_selection_controller_unittest.cc
@@ -876,15 +876,20 @@ TEST_F(TouchSelectionControllerTest, TemporarilyHidden) {
EXPECT_FALSE(test_controller.GetStartVisible());
EXPECT_FALSE(test_controller.GetEndVisible());
+ EXPECT_EQ(0.f, test_controller.GetStartAlpha());
+ EXPECT_EQ(0.f, test_controller.GetEndAlpha());
+
visible = false;
ChangeInsertion(insertion_rect, visible);
EXPECT_FALSE(GetAndResetNeedsAnimate());
EXPECT_FALSE(test_controller.GetStartVisible());
+ EXPECT_EQ(0.f, test_controller.GetStartAlpha());
visible = true;
ChangeInsertion(insertion_rect, visible);
EXPECT_FALSE(GetAndResetNeedsAnimate());
EXPECT_FALSE(test_controller.GetStartVisible());
+ EXPECT_EQ(0.f, test_controller.GetStartAlpha());
controller().SetTemporarilyHidden(false);
EXPECT_TRUE(GetAndResetNeedsAnimate());
@@ -935,6 +940,8 @@ TEST_F(TouchSelectionControllerTest, LongPressDrag) {
// drag gesture are pending.
EXPECT_FALSE(test_controller.GetStartVisible());
EXPECT_FALSE(test_controller.GetEndVisible());
+ EXPECT_EQ(0.f, test_controller.GetStartAlpha());
+ EXPECT_EQ(0.f, test_controller.GetEndAlpha());
// The selection coordinates should reflect the drag movement.
gfx::PointF fixed_offset = start_rect.CenterPoint();
@@ -970,6 +977,8 @@ TEST_F(TouchSelectionControllerTest, LongPressDrag) {
// The handles should still be hidden.
EXPECT_FALSE(test_controller.GetStartVisible());
EXPECT_FALSE(test_controller.GetEndVisible());
+ EXPECT_EQ(0.f, test_controller.GetStartAlpha());
+ EXPECT_EQ(0.f, test_controller.GetEndAlpha());
// Releasing the touch sequence should end the drag and show the handles.
EXPECT_FALSE(controller().WillHandleTouchEvent(event.ReleasePoint()));
@@ -1002,6 +1011,9 @@ TEST_F(TouchSelectionControllerTest, LongPressNoDrag) {
EXPECT_FALSE(test_controller.GetStartVisible());
EXPECT_FALSE(test_controller.GetEndVisible());
+ EXPECT_EQ(0.f, test_controller.GetStartAlpha());
+ EXPECT_EQ(0.f, test_controller.GetEndAlpha());
+
// If no drag movement occurs, the handles should reappear after the touch
// is released.
EXPECT_FALSE(controller().WillHandleTouchEvent(event.ReleasePoint()));
@@ -1031,6 +1043,9 @@ TEST_F(TouchSelectionControllerTest, NoLongPressDragIfDisabled) {
EXPECT_TRUE(test_controller.GetStartVisible());
EXPECT_TRUE(test_controller.GetEndVisible());
+ EXPECT_EQ(1.f, test_controller.GetStartAlpha());
+ EXPECT_EQ(1.f, test_controller.GetEndAlpha());
+
// Subsequent motion of the same touch sequence after longpress shouldn't
// trigger drag selection.
EXPECT_FALSE(controller().WillHandleTouchEvent(event.MovePoint(0, 0, 0)));
@@ -1045,6 +1060,9 @@ TEST_F(TouchSelectionControllerTest, NoLongPressDragIfDisabled) {
EXPECT_THAT(GetAndResetEvents(), IsEmpty());
EXPECT_TRUE(test_controller.GetStartVisible());
EXPECT_TRUE(test_controller.GetEndVisible());
+
+ EXPECT_EQ(1.f, test_controller.GetStartAlpha());
+ EXPECT_EQ(1.f, test_controller.GetEndAlpha());
}
TEST_F(TouchSelectionControllerTest, RectBetweenBounds) {
diff --git a/chromium/ui/views/BUILD.gn b/chromium/ui/views/BUILD.gn
index f08e2b91ef5..6a7ad0283d3 100644
--- a/chromium/ui/views/BUILD.gn
+++ b/chromium/ui/views/BUILD.gn
@@ -53,6 +53,7 @@ component("views") {
"animation/ink_drop_ripple_observer.h",
"animation/ink_drop_state.h",
"animation/ink_drop_stub.h",
+ "animation/ink_drop_util.h",
"animation/scroll_animator.h",
"animation/square_ink_drop_ripple.h",
"background.h",
@@ -82,7 +83,6 @@ component("views") {
"controls/button/blue_button.h",
"controls/button/button.h",
"controls/button/checkbox.h",
- "controls/button/custom_button.h",
"controls/button/image_button.h",
"controls/button/image_button_factory.h",
"controls/button/label_button.h",
@@ -185,6 +185,7 @@ component("views") {
"native_cursor.h",
"native_theme_delegate.h",
"painter.h",
+ "paint_info.h",
"pointer_watcher.h",
"rect_based_targeting_utils.h",
"repeat_controller.h",
@@ -229,6 +230,7 @@ component("views") {
"window/frame_background.h",
"window/frame_buttons.h",
"window/native_frame_view.h",
+ "window/nav_button_provider.h",
"window/non_client_view.h",
"window/window_button_order_provider.h",
"window/window_resources.h",
@@ -250,6 +252,7 @@ component("views") {
"animation/ink_drop_ripple.cc",
"animation/ink_drop_state.cc",
"animation/ink_drop_stub.cc",
+ "animation/ink_drop_util.cc",
"animation/scroll_animator.cc",
"animation/square_ink_drop_ripple.cc",
"background.cc",
@@ -276,7 +279,6 @@ component("views") {
"controls/button/blue_button.cc",
"controls/button/button.cc",
"controls/button/checkbox.cc",
- "controls/button/custom_button.cc",
"controls/button/image_button.cc",
"controls/button/image_button_factory.cc",
"controls/button/label_button.cc",
@@ -364,6 +366,7 @@ component("views") {
"mouse_watcher.cc",
"mouse_watcher_view_host.cc",
"native_cursor_mac.mm",
+ "paint_info.cc",
"painter.cc",
"rect_based_targeting_utils.cc",
"repeat_controller.cc",
@@ -462,7 +465,7 @@ component("views") {
"//ui/views/resources",
]
- if (use_x11 && !is_chromeos) {
+ if (use_x11) {
deps += [ "//ui/display/util" ]
}
if (is_linux && !is_chromeos) {
@@ -495,6 +498,7 @@ component("views") {
"win/hwnd_message_handler.h",
"win/hwnd_message_handler_delegate.h",
"win/hwnd_util.h",
+ "win/pen_event_processor.h",
"win/scoped_fullscreen_visibility.h",
"win/windows_session_change_observer.h",
]
@@ -503,6 +507,7 @@ component("views") {
"win/fullscreen_handler.cc",
"win/hwnd_message_handler.cc",
"win/hwnd_util_aurawin.cc",
+ "win/pen_event_processor.cc",
"win/scoped_fullscreen_visibility.cc",
"win/windows_session_change_observer.cc",
]
@@ -542,7 +547,6 @@ component("views") {
"accessibility/ax_view_obj_wrapper.h",
"accessibility/ax_widget_obj_wrapper.h",
"accessibility/ax_window_obj_wrapper.h",
- "bubble/bubble_window_targeter.h",
"bubble/tray_bubble_view.h",
"controls/menu/menu_pre_target_handler.h",
"controls/native/native_view_host_aura.h",
@@ -575,7 +579,6 @@ component("views") {
"accessibility/ax_view_obj_wrapper.cc",
"accessibility/ax_widget_obj_wrapper.cc",
"accessibility/ax_window_obj_wrapper.cc",
- "bubble/bubble_window_targeter.cc",
"bubble/tray_bubble_view.cc",
"controls/menu/display_change_listener_aura.cc",
"controls/menu/menu_pre_target_handler.cc",
@@ -824,7 +827,7 @@ static_library("test_support_internal") {
"//ui/wm",
"//ui/wm/public",
]
- if (use_x11 && !is_chromeos) {
+ if (use_x11) {
sources += [
"test/desktop_screen_x11_test_api.cc",
"test/desktop_screen_x11_test_api.h",
@@ -889,17 +892,17 @@ source_set("views_unittests_sources") {
"bubble/bubble_border_unittest.cc",
"bubble/bubble_dialog_delegate_unittest.cc",
"bubble/bubble_frame_view_unittest.cc",
- "bubble/bubble_window_targeter_unittest.cc",
"cocoa/bridged_native_widget_unittest.mm",
"cocoa/cocoa_mouse_capture_unittest.mm",
"cocoa/drag_drop_client_mac_unittest.mm",
"controls/button/blue_button_unittest.cc",
- "controls/button/custom_button_unittest.cc",
+ "controls/button/button_unittest.cc",
"controls/button/image_button_factory_unittest.cc",
"controls/button/image_button_unittest.cc",
"controls/button/label_button_label_unittest.cc",
"controls/button/label_button_unittest.cc",
"controls/button/menu_button_unittest.cc",
+ "controls/button/radio_button_unittest.cc",
"controls/button/toggle_button_unittest.cc",
"controls/combobox/combobox_unittest.cc",
"controls/label_unittest.cc",
@@ -933,6 +936,7 @@ source_set("views_unittests_sources") {
"layout/box_layout_unittest.cc",
"layout/fill_layout_unittest.cc",
"layout/grid_layout_unittest.cc",
+ "paint_info_unittest.cc",
"rect_based_targeting_utils_unittest.cc",
"test/widget_test_unittest.cc",
"view_model_unittest.cc",
@@ -1002,6 +1006,7 @@ source_set("views_unittests_sources") {
"oleacc.lib",
"comctl32.lib",
]
+ sources += [ "win/pen_event_processor_unittest.cc" ]
}
if (has_native_accessibility) {
@@ -1038,10 +1043,7 @@ source_set("views_unittests_sources") {
if (is_mac) {
# views_unittests not yet compiling on Mac. http://crbug.com/378134
- sources -= [
- "bubble/bubble_window_targeter_unittest.cc",
- "controls/native/native_view_host_unittest.cc",
- ]
+ sources -= [ "controls/native/native_view_host_unittest.cc" ]
public_deps += [ "//ui/accelerated_widget_mac" ]
}
}
diff --git a/chromium/ui/views/DEPS b/chromium/ui/views/DEPS
index ee243276fc5..edc6d257814 100644
--- a/chromium/ui/views/DEPS
+++ b/chromium/ui/views/DEPS
@@ -36,5 +36,8 @@ specific_include_rules = {
],
"views_test_suite\.cc": [
"+gpu/ipc/service",
+ ],
+ "paint_info_unittest\.cc": [
+ "+cc/base",
]
}
diff --git a/chromium/ui/views/accessibility/OWNERS b/chromium/ui/views/accessibility/OWNERS
index bdb9178c0a6..2c85844e32c 100644
--- a/chromium/ui/views/accessibility/OWNERS
+++ b/chromium/ui/views/accessibility/OWNERS
@@ -1,5 +1,4 @@
-dmazzoni@chromium.org
-dtseng@chromium.org
+file://ui/accessibility/OWNERS
# TEAM: chromium-accessibility@chromium.org
# COMPONENT: UI>Accessibility
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 b0898a68810..bad990722ed 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
@@ -88,7 +88,7 @@ TEST_F(AXSystemCaretWinTest, DISABLED_TestOnCaretBoundsChangeInTextField) {
textfield_test_api.ExecuteTextEditCommand(
ui::TextEditCommand::MOVE_TO_BEGINNING_OF_DOCUMENT);
- gfx::Point caret_position = textfield_test_api.GetCursorViewOrigin();
+ gfx::Point caret_position = textfield_test_api.GetCursorViewRect().origin();
LONG x, y, width, height;
EXPECT_EQ(S_OK,
caret_accessible->accLocation(&x, &y, &width, &height, self_));
@@ -98,7 +98,7 @@ TEST_F(AXSystemCaretWinTest, DISABLED_TestOnCaretBoundsChangeInTextField) {
textfield_test_api.ExecuteTextEditCommand(
ui::TextEditCommand::MOVE_TO_END_OF_DOCUMENT);
- gfx::Point caret_position2 = textfield_test_api.GetCursorViewOrigin();
+ gfx::Point caret_position2 = textfield_test_api.GetCursorViewRect().origin();
EXPECT_NE(caret_position, caret_position2);
EXPECT_EQ(S_OK,
caret_accessible->accLocation(&x, &y, &width, &height, self_));
diff --git a/chromium/ui/views/accessibility/native_view_accessibility_auralinux.cc b/chromium/ui/views/accessibility/native_view_accessibility_auralinux.cc
index e16ba4a95de..4c1afebdd43 100644
--- a/chromium/ui/views/accessibility/native_view_accessibility_auralinux.cc
+++ b/chromium/ui/views/accessibility/native_view_accessibility_auralinux.cc
@@ -131,12 +131,7 @@ class AuraLinuxApplication
}
ui::AXPlatformNodeAuraLinux::SetApplication(platform_node_);
if (ViewsDelegate::GetInstance()) {
- // This should be on the a blocking pool thread so that we can open
- // libatk-bridge.so without blocking this thread.
- scoped_refptr<base::TaskRunner> init_task_runner =
- ViewsDelegate::GetInstance()->GetBlockingPoolTaskRunner();
- if (init_task_runner)
- ui::AXPlatformNodeAuraLinux::StaticInitialize(init_task_runner);
+ ui::AXPlatformNodeAuraLinux::StaticInitialize();
}
}
diff --git a/chromium/ui/views/accessibility/native_view_accessibility_win.cc b/chromium/ui/views/accessibility/native_view_accessibility_win.cc
index 153e9281f9e..af44ab0c4c7 100644
--- a/chromium/ui/views/accessibility/native_view_accessibility_win.cc
+++ b/chromium/ui/views/accessibility/native_view_accessibility_win.cc
@@ -22,7 +22,7 @@
#include "ui/base/layout.h"
#include "ui/base/win/accessibility_misc_utils.h"
#include "ui/base/win/atl_module.h"
-#include "ui/views/controls/button/custom_button.h"
+#include "ui/views/controls/button/button.h"
#include "ui/views/focus/focus_manager.h"
#include "ui/views/widget/widget.h"
#include "ui/views/win/hwnd_util.h"
diff --git a/chromium/ui/views/animation/OWNERS b/chromium/ui/views/animation/OWNERS
index 9710b4e0f93..be29560c22a 100644
--- a/chromium/ui/views/animation/OWNERS
+++ b/chromium/ui/views/animation/OWNERS
@@ -1 +1 @@
-per-file *ink*=bruthig@chromium.org
+per-file *ink*=mohsen@chromium.org
diff --git a/chromium/ui/views/animation/flood_fill_ink_drop_ripple.cc b/chromium/ui/views/animation/flood_fill_ink_drop_ripple.cc
index 33b5c69b35c..849ee7dc85c 100644
--- a/chromium/ui/views/animation/flood_fill_ink_drop_ripple.cc
+++ b/chromium/ui/views/animation/flood_fill_ink_drop_ripple.cc
@@ -14,6 +14,7 @@
#include "ui/gfx/animation/animation.h"
#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/vector2d_f.h"
+#include "ui/views/animation/ink_drop_util.h"
namespace {
@@ -213,8 +214,10 @@ void FloodFillInkDropRipple::AnimateStateChange(
}
break;
case InkDropState::ACTION_PENDING: {
- DCHECK_EQ(InkDropState::HIDDEN, old_ink_drop_state)
- << " old_ink_drop_state=" << ToString(old_ink_drop_state);
+ DLOG_IF(WARNING, InkDropState::HIDDEN != old_ink_drop_state)
+ << "Invalid InkDropState transition. old_ink_drop_state="
+ << ToString(old_ink_drop_state)
+ << " new_ink_drop_state=" << ToString(new_ink_drop_state);
AnimateToOpacity(visible_opacity_,
GetAnimationDuration(ACTION_PENDING_FADE_IN),
@@ -232,9 +235,12 @@ void FloodFillInkDropRipple::AnimateStateChange(
break;
}
case InkDropState::ACTION_TRIGGERED: {
- DCHECK(old_ink_drop_state == InkDropState::HIDDEN ||
- old_ink_drop_state == InkDropState::ACTION_PENDING)
- << " old_ink_drop_state=" << ToString(old_ink_drop_state);
+ DLOG_IF(WARNING, old_ink_drop_state != InkDropState::HIDDEN &&
+ old_ink_drop_state != InkDropState::ACTION_PENDING)
+ << "Invalid InkDropState transition. old_ink_drop_state="
+ << ToString(old_ink_drop_state)
+ << " new_ink_drop_state=" << ToString(new_ink_drop_state);
+
if (old_ink_drop_state == InkDropState::HIDDEN) {
AnimateStateChange(old_ink_drop_state, InkDropState::ACTION_PENDING,
animation_observer);
@@ -246,8 +252,11 @@ void FloodFillInkDropRipple::AnimateStateChange(
break;
}
case InkDropState::ALTERNATE_ACTION_PENDING: {
- DCHECK_EQ(InkDropState::ACTION_PENDING, old_ink_drop_state)
- << " old_ink_drop_state=" << ToString(old_ink_drop_state);
+ DLOG_IF(WARNING, InkDropState::ACTION_PENDING != old_ink_drop_state)
+ << "Invalid InkDropState transition. old_ink_drop_state="
+ << ToString(old_ink_drop_state)
+ << " new_ink_drop_state=" << ToString(new_ink_drop_state);
+
AnimateToOpacity(visible_opacity_,
GetAnimationDuration(ALTERNATE_ACTION_PENDING),
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
@@ -259,8 +268,12 @@ void FloodFillInkDropRipple::AnimateStateChange(
break;
}
case InkDropState::ALTERNATE_ACTION_TRIGGERED:
- DCHECK_EQ(InkDropState::ALTERNATE_ACTION_PENDING, old_ink_drop_state)
- << " old_ink_drop_state=" << ToString(old_ink_drop_state);
+ DLOG_IF(WARNING,
+ InkDropState::ALTERNATE_ACTION_PENDING != old_ink_drop_state)
+ << "Invalid InkDropState transition. old_ink_drop_state="
+ << ToString(old_ink_drop_state)
+ << " new_ink_drop_state=" << ToString(new_ink_drop_state);
+
AnimateToOpacity(kHiddenOpacity, GetAnimationDuration(
ALTERNATE_ACTION_TRIGGERED_FADE_OUT),
ui::LayerAnimator::ENQUEUE_NEW_ANIMATION,
@@ -414,6 +427,10 @@ gfx::Transform FloodFillInkDropRipple::CalculateTransform(
circle_layer_delegate_.GetCenteringOffset();
transform.Translate(-drawn_center_offset.x(), -drawn_center_offset.y());
+ // Add subpixel correction to the transform.
+ transform.ConcatTransform(GetTransformSubpixelCorrection(
+ transform, painted_layer_.device_scale_factor()));
+
return transform;
}
diff --git a/chromium/ui/views/animation/flood_fill_ink_drop_ripple_unittest.cc b/chromium/ui/views/animation/flood_fill_ink_drop_ripple_unittest.cc
index 44ea59f9523..f61dae86e7d 100644
--- a/chromium/ui/views/animation/flood_fill_ink_drop_ripple_unittest.cc
+++ b/chromium/ui/views/animation/flood_fill_ink_drop_ripple_unittest.cc
@@ -7,6 +7,7 @@
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/point_conversions.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
#include "ui/views/animation/test/flood_fill_ink_drop_ripple_test_api.h"
@@ -29,10 +30,11 @@ TEST(FloodFillInkDropRippleTest, TransformedCenterPointForIrregularClipBounds) {
SK_ColorWHITE, 0.175f);
FloodFillInkDropRippleTestApi test_api(&ripple);
- gfx::Point actual_center = test_api.GetDrawnCenterPoint();
+ gfx::Point3F actual_center(gfx::PointF(test_api.GetDrawnCenterPoint()));
test_api.TransformPoint(10, &actual_center);
- EXPECT_EQ(expected_center_point, actual_center);
+ EXPECT_EQ(expected_center_point,
+ gfx::ToRoundedPoint(actual_center.AsPointF()));
}
TEST(FloodFillInkDropRippleTest, MaxDistanceToCorners) {
@@ -107,5 +109,40 @@ TEST(FloodFillInkDropRippleTest, ActivatedFinalState) {
activated_transform.ApproximatelyEqual(pending_activated_transform));
}
+TEST(FloodFillInkDropRippleTest, TransformIsPixelAligned) {
+ const float kEpsilon = 0.001f;
+
+ const gfx::Size host_size(11, 11);
+ // Keep the draw center different from the the host center to have a non zero
+ // offset in the transformation.
+ const gfx::Point center_point(host_size.width() / 3, host_size.height() / 3);
+ const SkColor color = SK_ColorYELLOW;
+ const float visible_opacity = 0.3f;
+
+ FloodFillInkDropRipple ripple(host_size, center_point, color,
+ visible_opacity);
+ FloodFillInkDropRippleTestApi test_api(&ripple);
+
+ for (auto dsf : {1.25, 1.33, 1.5, 1.6, 1.75, 1.8, 2.25}) {
+ SCOPED_TRACE(testing::Message()
+ << std::endl
+ << "Device Scale Factor: " << dsf << std::endl);
+ ripple.GetRootLayer()->OnDeviceScaleFactorChanged(dsf);
+ gfx::Point3F ripple_origin;
+
+ test_api.TransformPoint(host_size.width() / 2, &ripple_origin);
+
+ // Apply device scale factor to get the final offset.
+ gfx::Transform dsf_transform;
+ dsf_transform.Scale(dsf, dsf);
+ dsf_transform.TransformPoint(&ripple_origin);
+
+ EXPECT_NEAR(ripple_origin.x(), gfx::ToRoundedInt(ripple_origin.x()),
+ kEpsilon);
+ EXPECT_NEAR(ripple_origin.y(), gfx::ToRoundedInt(ripple_origin.y()),
+ kEpsilon);
+ }
+}
+
} // namespace test
} // namespace views
diff --git a/chromium/ui/views/animation/ink_drop_highlight.cc b/chromium/ui/views/animation/ink_drop_highlight.cc
index effde4973db..98c9030845e 100644
--- a/chromium/ui/views/animation/ink_drop_highlight.cc
+++ b/chromium/ui/views/animation/ink_drop_highlight.cc
@@ -17,6 +17,7 @@
#include "ui/gfx/geometry/insets.h"
#include "ui/views/animation/ink_drop_highlight_observer.h"
#include "ui/views/animation/ink_drop_painted_layer_delegates.h"
+#include "ui/views/animation/ink_drop_util.h"
namespace views {
@@ -161,6 +162,11 @@ gfx::Transform InkDropHighlight::CalculateTransform(
size_.height() == 0 ? 0 : size.height() / size_.height());
gfx::Vector2dF layer_offset = layer_delegate_->GetCenteringOffset();
transform.Translate(-layer_offset.x(), -layer_offset.y());
+
+ // Add subpixel correction to the transform.
+ transform.ConcatTransform(
+ GetTransformSubpixelCorrection(transform, layer_->device_scale_factor()));
+
return transform;
}
diff --git a/chromium/ui/views/animation/ink_drop_highlight_unittest.cc b/chromium/ui/views/animation/ink_drop_highlight_unittest.cc
index 94dc954bfb9..95380dba477 100644
--- a/chromium/ui/views/animation/ink_drop_highlight_unittest.cc
+++ b/chromium/ui/views/animation/ink_drop_highlight_unittest.cc
@@ -10,10 +10,12 @@
#include "base/memory/ptr_util.h"
#include "base/time/time.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/compositor/layer.h"
#include "ui/compositor/scoped_animation_duration_scale_mode.h"
#include "ui/gfx/animation/animation.h"
#include "ui/gfx/animation/animation_test_api.h"
#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/transform.h"
#include "ui/views/animation/test/ink_drop_highlight_test_api.h"
#include "ui/views/animation/test/test_ink_drop_highlight_observer.h"
@@ -206,5 +208,35 @@ TEST_F(InkDropHighlightTest, AnimatingAZeroSizeHighlight) {
false /* explode */);
}
+TEST_F(InkDropHighlightTest, TransformIsPixelAligned) {
+ const float kEpsilon = 0.001f;
+ gfx::Size highlight_size(10, 10);
+ InitHighlight(base::MakeUnique<InkDropHighlight>(
+ highlight_size, 3, gfx::PointF(3.5f, 3.5f), SK_ColorYELLOW));
+ const gfx::PointF layer_origin(
+ ink_drop_highlight()->layer()->bounds().origin());
+ for (auto dsf : {1.25, 1.33, 1.5, 1.6, 1.75, 1.8, 2.25}) {
+ SCOPED_TRACE(testing::Message()
+ << std::endl
+ << "Device Scale Factor: " << dsf << std::endl);
+ ink_drop_highlight()->layer()->OnDeviceScaleFactorChanged(dsf);
+
+ const gfx::SizeF size(highlight_size);
+ gfx::Transform transform = test_api()->CalculateTransform(size);
+ gfx::Point3F transformed_layer_origin(layer_origin.x(), layer_origin.y(),
+ 0);
+ transform.TransformPoint(&transformed_layer_origin);
+
+ // Apply device scale factor to get the final offset.
+ gfx::Transform dsf_transform;
+ dsf_transform.Scale(dsf, dsf);
+ dsf_transform.TransformPoint(&transformed_layer_origin);
+ EXPECT_NEAR(transformed_layer_origin.x(),
+ gfx::ToRoundedInt(transformed_layer_origin.x()), kEpsilon);
+ EXPECT_NEAR(transformed_layer_origin.y(),
+ gfx::ToRoundedInt(transformed_layer_origin.y()), kEpsilon);
+ }
+}
+
} // namespace test
} // 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 1856e89293e..3124f8266fc 100644
--- a/chromium/ui/views/animation/ink_drop_host_view.cc
+++ b/chromium/ui/views/animation/ink_drop_host_view.cc
@@ -118,7 +118,8 @@ gfx::Size InkDropHostView::CalculateLargeInkDropSize(
InkDropHostView::InkDropHostView()
: ink_drop_mode_(InkDropMode::OFF),
ink_drop_(nullptr),
- ink_drop_visible_opacity_(kInkDropVisibleOpacity),
+ ink_drop_visible_opacity_(
+ PlatformStyle::kUseRipples ? kInkDropVisibleOpacity : 0),
old_paint_to_layer_(false),
destroying_(false) {}
@@ -277,7 +278,7 @@ bool InkDropHostView::HasInkDrop() const {
InkDrop* InkDropHostView::GetInkDrop() {
if (!ink_drop_) {
- if (ink_drop_mode_ == InkDropMode::OFF || !PlatformStyle::kUseRipples)
+ if (ink_drop_mode_ == InkDropMode::OFF)
ink_drop_ = base::MakeUnique<InkDropStub>();
else
ink_drop_ = CreateInkDrop();
diff --git a/chromium/ui/views/animation/ink_drop_mask.cc b/chromium/ui/views/animation/ink_drop_mask.cc
index d95286d91c9..104c4b3389e 100644
--- a/chromium/ui/views/animation/ink_drop_mask.cc
+++ b/chromium/ui/views/animation/ink_drop_mask.cc
@@ -48,9 +48,15 @@ void RoundRectInkDropMask::OnPaintLayer(const ui::PaintContext& context) {
flags.setAntiAlias(true);
ui::PaintRecorder recorder(context, layer()->size());
- gfx::RectF bounds(layer()->bounds());
- bounds.Inset(mask_insets_);
- recorder.canvas()->DrawRoundRect(bounds, corner_radius_, flags);
+ const float dsf = recorder.canvas()->UndoDeviceScaleFactor();
+
+ gfx::RectF masking_bound(layer()->bounds());
+ masking_bound.Inset(mask_insets_);
+
+ const gfx::Rect masking_bound_scaled =
+ gfx::ScaleToRoundedRect(gfx::ToNearestRect(masking_bound), dsf);
+ recorder.canvas()->DrawRoundRect(masking_bound_scaled, corner_radius_ * dsf,
+ flags);
}
// CircleInkDropMask
diff --git a/chromium/ui/views/animation/ink_drop_ripple.cc b/chromium/ui/views/animation/ink_drop_ripple.cc
index 22306a933a9..f6360a80947 100644
--- a/chromium/ui/views/animation/ink_drop_ripple.cc
+++ b/chromium/ui/views/animation/ink_drop_ripple.cc
@@ -38,7 +38,8 @@ void InkDropRipple::AnimateToState(InkDropState ink_drop_state) {
// 1. The attached observers must be notified of all animations started and
// ended.
// 2. Not all state transitions is are valid, especially no-op transitions,
- // and these should be detected by DCHECKs in AnimateStateChange().
+ // and these invalid transitions will be logged as warnings in
+ // AnimateStateChange().
// |animation_observer| will be deleted when AnimationEndedCallback() returns
// true.
diff --git a/chromium/ui/views/animation/ink_drop_util.cc b/chromium/ui/views/animation/ink_drop_util.cc
new file mode 100644
index 00000000000..4344d479756
--- /dev/null
+++ b/chromium/ui/views/animation/ink_drop_util.cc
@@ -0,0 +1,54 @@
+// 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/views/animation/ink_drop_util.h"
+
+#include <math.h>
+
+#include "base/logging.h"
+#include "ui/gfx/geometry/point3_f.h"
+#include "ui/gfx/geometry/safe_integer_conversions.h"
+#include "ui/gfx/geometry/vector2d_f.h"
+#include "ui/gfx/transform.h"
+
+namespace views {
+
+gfx::Transform GetTransformSubpixelCorrection(const gfx::Transform& transform,
+ float device_scale_factor) {
+ gfx::Point3F origin;
+ transform.TransformPoint(&origin);
+
+ const gfx::Vector2dF offset_in_dip = origin.AsPointF().OffsetFromOrigin();
+
+ // Scale the origin to screen space
+ origin.Scale(device_scale_factor);
+
+ // Compute the rounded offset in screen space and finally unscale it back to
+ // DIP space.
+ gfx::Vector2dF aligned_offset_in_dip = origin.AsPointF().OffsetFromOrigin();
+ aligned_offset_in_dip.set_x(gfx::ToRoundedInt(aligned_offset_in_dip.x()));
+ aligned_offset_in_dip.set_y(gfx::ToRoundedInt(aligned_offset_in_dip.y()));
+ aligned_offset_in_dip.Scale(1.f / device_scale_factor);
+
+ // Compute the subpixel offset correction and apply it to the transform.
+ gfx::Transform subpixel_correction;
+ subpixel_correction.Translate(aligned_offset_in_dip - offset_in_dip);
+#if DCHECK_IS_ON()
+ const float kEpsilon = 0.0001f;
+ gfx::Point3F offset;
+
+ gfx::Transform transform_corrected(transform);
+ transform_corrected.ConcatTransform(subpixel_correction);
+ transform_corrected.TransformPoint(&offset);
+ offset.Scale(device_scale_factor);
+
+ if (!std::isnan(offset.x()))
+ DCHECK_LT(std::abs(gfx::ToRoundedInt(offset.x()) - offset.x()), kEpsilon);
+ if (!std::isnan(offset.y()))
+ DCHECK_LT(std::abs(gfx::ToRoundedInt(offset.y()) - offset.y()), kEpsilon);
+#endif
+ return subpixel_correction;
+}
+
+} // namespace views
diff --git a/chromium/ui/views/animation/ink_drop_util.h b/chromium/ui/views/animation/ink_drop_util.h
new file mode 100644
index 00000000000..883b78974ef
--- /dev/null
+++ b/chromium/ui/views/animation/ink_drop_util.h
@@ -0,0 +1,27 @@
+// 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_VIEWS_ANIMATION_INK_DROP_UTIL_H_
+#define UI_VIEWS_ANIMATION_INK_DROP_UTIL_H_
+
+#include "ui/views/views_export.h"
+
+namespace gfx {
+class Transform;
+} // namespace gfx
+
+namespace views {
+
+// A layer |transform| may add an offset to its layer relative to the parent
+// layer. This offset does not take into consideration the subpixel positioning.
+// A subpixel correction needs to be applied to make sure the layers are pixel
+// aligned after the transform is applied. Use this function to compute the
+// subpixel correction transform.
+VIEWS_EXPORT gfx::Transform GetTransformSubpixelCorrection(
+ const gfx::Transform& transform,
+ float device_scale_factor);
+
+} // namespace views
+
+#endif // UI_VIEWS_ANIMATION_INK_DROP_UTIL_H_
diff --git a/chromium/ui/views/animation/square_ink_drop_ripple.cc b/chromium/ui/views/animation/square_ink_drop_ripple.cc
index 7dd72be2dd4..276b5d5f732 100644
--- a/chromium/ui/views/animation/square_ink_drop_ripple.cc
+++ b/chromium/ui/views/animation/square_ink_drop_ripple.cc
@@ -238,8 +238,13 @@ void SquareInkDropRipple::AnimateStateChange(
}
break;
case InkDropState::ACTION_PENDING:
- DCHECK_EQ(InkDropState::HIDDEN, old_ink_drop_state)
- << " old_ink_drop_state=" << ToString(old_ink_drop_state);
+ if (old_ink_drop_state == new_ink_drop_state)
+ return;
+ DLOG_IF(WARNING, InkDropState::HIDDEN != old_ink_drop_state)
+ << "Invalid InkDropState transition. old_ink_drop_state="
+ << ToString(old_ink_drop_state)
+ << " new_ink_drop_state=" << ToString(new_ink_drop_state);
+
AnimateToOpacity(visible_opacity_,
GetAnimationDuration(ACTION_PENDING_FADE_IN),
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
@@ -255,9 +260,12 @@ void SquareInkDropRipple::AnimateStateChange(
gfx::Tween::EASE_IN_OUT, animation_observer);
break;
case InkDropState::ACTION_TRIGGERED: {
- DCHECK(old_ink_drop_state == InkDropState::HIDDEN ||
- old_ink_drop_state == InkDropState::ACTION_PENDING)
- << " old_ink_drop_state=" << ToString(old_ink_drop_state);
+ DLOG_IF(WARNING, old_ink_drop_state != InkDropState::HIDDEN &&
+ old_ink_drop_state != InkDropState::ACTION_PENDING)
+ << "Invalid InkDropState transition. old_ink_drop_state="
+ << ToString(old_ink_drop_state)
+ << " new_ink_drop_state=" << ToString(new_ink_drop_state);
+
if (old_ink_drop_state == InkDropState::HIDDEN) {
AnimateStateChange(old_ink_drop_state, InkDropState::ACTION_PENDING,
animation_observer);
@@ -275,8 +283,11 @@ void SquareInkDropRipple::AnimateStateChange(
break;
}
case InkDropState::ALTERNATE_ACTION_PENDING:
- DCHECK_EQ(InkDropState::ACTION_PENDING, old_ink_drop_state)
- << " old_ink_drop_state=" << ToString(old_ink_drop_state);
+ DLOG_IF(WARNING, InkDropState::ACTION_PENDING != old_ink_drop_state)
+ << "Invalid InkDropState transition. old_ink_drop_state="
+ << ToString(old_ink_drop_state)
+ << " new_ink_drop_state=" << ToString(new_ink_drop_state);
+
AnimateToOpacity(visible_opacity_,
GetAnimationDuration(ALTERNATE_ACTION_PENDING),
ui::LayerAnimator::IMMEDIATELY_ANIMATE_TO_NEW_TARGET,
@@ -288,8 +299,12 @@ void SquareInkDropRipple::AnimateStateChange(
gfx::Tween::EASE_IN_OUT, animation_observer);
break;
case InkDropState::ALTERNATE_ACTION_TRIGGERED: {
- DCHECK_EQ(InkDropState::ALTERNATE_ACTION_PENDING, old_ink_drop_state)
- << " old_ink_drop_state=" << ToString(old_ink_drop_state);
+ DLOG_IF(WARNING,
+ InkDropState::ALTERNATE_ACTION_PENDING != old_ink_drop_state)
+ << "Invalid InkDropState transition. old_ink_drop_state="
+ << ToString(old_ink_drop_state)
+ << " new_ink_drop_state=" << ToString(new_ink_drop_state);
+
base::TimeDelta visible_duration =
GetAnimationDuration(ALTERNATE_ACTION_TRIGGERED_TRANSFORM) -
GetAnimationDuration(ALTERNATE_ACTION_TRIGGERED_FADE_OUT);
diff --git a/chromium/ui/views/bubble/bubble_border_unittest.cc b/chromium/ui/views/bubble/bubble_border_unittest.cc
index 3c6245e14b0..0d2a89cc8fe 100644
--- a/chromium/ui/views/bubble/bubble_border_unittest.cc
+++ b/chromium/ui/views/bubble/bubble_border_unittest.cc
@@ -10,11 +10,19 @@
#include "base/macros.h"
#include "base/strings/stringprintf.h"
+#include "ui/base/material_design/material_design_controller.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/views/test/views_test_base.h"
namespace views {
+namespace {
+
+bool UseMd() {
+ return ui::MaterialDesignController::IsSecondaryUiMaterial();
+}
+
+} // namespace
typedef views::ViewsTestBase BubbleBorderTest;
@@ -216,6 +224,7 @@ TEST_F(BubbleBorderTest, GetSizeForContentsSizeTest) {
SK_ColorWHITE);
const views::internal::BorderImages* kImages = border.GetImagesForTest();
+ const gfx::Insets kInsets = border.GetInsets();
// kSmallSize is smaller than the minimum allowable size and does not
// contribute to the resulting size.
@@ -225,29 +234,39 @@ TEST_F(BubbleBorderTest, GetSizeForContentsSizeTest) {
const gfx::Size kMediumSize = gfx::Size(50, 60);
const gfx::Size kSmallHorizArrow(
- 2 * kImages->border_thickness + kImages->arrow_width,
- kImages->border_thickness + kImages->arrow_thickness +
- kImages->border_interior_thickness);
+ UseMd() ? kSmallSize.width() + kInsets.width()
+ : 2 * kImages->border_thickness + kImages->arrow_width,
+ UseMd() ? kSmallSize.height() + kInsets.height()
+ : kImages->border_thickness + kImages->arrow_thickness +
+ kImages->border_interior_thickness);
- const gfx::Size kSmallVertArrow(kSmallHorizArrow.height(),
- kSmallHorizArrow.width());
+ const gfx::Size kSmallVertArrow(
+ UseMd() ? kSmallHorizArrow.width() : kSmallHorizArrow.height(),
+ UseMd() ? kSmallHorizArrow.height() : kSmallHorizArrow.width());
- const gfx::Size kSmallNoArrow(2 * kImages->border_thickness,
- 2 * kImages->border_thickness);
+ const gfx::Size kSmallNoArrow(
+ UseMd() ? kSmallHorizArrow.width() : 2 * kImages->border_thickness,
+ UseMd() ? kSmallHorizArrow.height() : 2 * kImages->border_thickness);
const gfx::Size kMediumHorizArrow(
- kMediumSize.width() + 2 * border.GetBorderThickness(),
- kMediumSize.height() + border.GetBorderThickness() +
- kImages->arrow_thickness);
+ UseMd() ? kMediumSize.width() + kInsets.width()
+ : kMediumSize.width() + 2 * border.GetBorderThickness(),
+ UseMd() ? kMediumSize.height() + kInsets.height()
+ : kMediumSize.height() + border.GetBorderThickness() +
+ kImages->arrow_thickness);
const gfx::Size kMediumVertArrow(
- kMediumSize.width() + border.GetBorderThickness() +
- kImages->arrow_thickness,
- kMediumSize.height() + 2 * border.GetBorderThickness());
+ UseMd() ? kMediumHorizArrow.width()
+ : kMediumSize.width() + border.GetBorderThickness() +
+ kImages->arrow_thickness,
+ UseMd() ? kMediumHorizArrow.height()
+ : kMediumSize.height() + 2 * border.GetBorderThickness());
const gfx::Size kMediumNoArrow(
- kMediumSize.width() + 2 * border.GetBorderThickness(),
- kMediumSize.height() + 2 * border.GetBorderThickness());
+ UseMd() ? kMediumHorizArrow.width()
+ : kMediumSize.width() + 2 * border.GetBorderThickness(),
+ UseMd() ? kMediumHorizArrow.height()
+ : kMediumSize.height() + 2 * border.GetBorderThickness());
struct TestCase {
BubbleBorder::Arrow arrow;
@@ -334,6 +353,7 @@ TEST_F(BubbleBorderTest, GetBoundsOriginTest) {
const gfx::Rect kAnchor(100, 100, 20, 30);
const gfx::Size kContentSize(500, 600);
+ const gfx::Insets kInsets = border.GetInsets();
const views::internal::BorderImages* kImages = border.GetImagesForTest();
@@ -354,14 +374,14 @@ TEST_F(BubbleBorderTest, GetBoundsOriginTest) {
const int kArrowOffsetForHorizCenter = kTotalSizeWithHorizArrow.width() / 2;
const int kArrowOffsetForVertCenter = kTotalSizeWithVertArrow.height() / 2;
const int kArrowOffsetForNotCenter =
- kImages->border_thickness + (kImages->arrow_width / 2);
+ UseMd() ? 0 : kImages->border_thickness + (kImages->arrow_width / 2);
const int kStrokeWidth =
shadow == BubbleBorder::NO_ASSETS ? 0 : BubbleBorder::kStroke;
- const int kArrowThickness = kImages->arrow_interior_thickness;
+ const int kArrowThickness = UseMd() ? 0 : kImages->arrow_interior_thickness;
const int kArrowShift =
- kArrowThickness + kStrokeWidth - kImages->arrow_thickness;
+ UseMd() ? 0 : kArrowThickness + kStrokeWidth - kImages->arrow_thickness;
const int kHeightDifference =
kTotalSizeWithHorizArrow.height() - kTotalSizeWithNoArrow.height();
const int kWidthDifference =
@@ -371,19 +391,26 @@ TEST_F(BubbleBorderTest, GetBoundsOriginTest) {
// The arrow only makes a difference in height if it is longer than the
// shadow.
const int kExpectedHeightDifference =
- std::max(kImages->arrow_thickness + kImages->border_interior_thickness,
- kImages->border_thickness) -
- std::max(kImages->border_interior_thickness, kImages->border_thickness);
+ UseMd() ? 0
+ : std::max(kImages->arrow_thickness +
+ kImages->border_interior_thickness,
+ kImages->border_thickness) -
+ std::max(kImages->border_interior_thickness,
+ kImages->border_thickness);
EXPECT_EQ(kExpectedHeightDifference, kHeightDifference)
<< "Size with arrow: " << kTotalSizeWithHorizArrow.ToString()
<< " vs. size without arrow: " << kTotalSizeWithNoArrow.ToString();
- const int kTopHorizArrowY = kAnchor.y() + kAnchor.height() + kArrowShift;
+ const int kTopHorizArrowY =
+ UseMd() ? kAnchor.bottom() + kStrokeWidth - kInsets.top()
+ : kAnchor.bottom() + kArrowShift;
const int kBottomHorizArrowY =
- kAnchor.y() - kArrowShift - kTotalSizeWithHorizArrow.height();
+ UseMd() ? kAnchor.y() - kTotalSizeWithHorizArrow.height()
+ : kAnchor.y() - kArrowShift - kTotalSizeWithHorizArrow.height();
const int kLeftVertArrowX = kAnchor.x() + kAnchor.width() + kArrowShift;
const int kRightVertArrowX =
- kAnchor.x() - kArrowShift - kTotalSizeWithVertArrow.width();
+ UseMd() ? kAnchor.x() - kTotalSizeWithHorizArrow.width()
+ : kAnchor.x() - kArrowShift - kTotalSizeWithVertArrow.width();
struct TestCase {
BubbleBorder::Arrow arrow;
@@ -395,15 +422,21 @@ TEST_F(BubbleBorderTest, GetBoundsOriginTest) {
TestCase cases[] = {
// Horizontal arrow tests.
{BubbleBorder::TOP_LEFT, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR,
- kAnchor.CenterPoint().x() - kArrowOffsetForNotCenter, kTopHorizArrowY},
+ UseMd() ? kAnchor.x() + kStrokeWidth - kInsets.left()
+ : kAnchor.CenterPoint().x() - kArrowOffsetForNotCenter,
+ kTopHorizArrowY},
{BubbleBorder::TOP_LEFT, BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE,
- kAnchor.x() + kStrokeWidth - kBorderThickness, kTopHorizArrowY},
- {BubbleBorder::TOP_CENTER, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR,
- kAnchor.CenterPoint().x() - kArrowOffsetForHorizCenter,
+ UseMd() ? kAnchor.x() + kStrokeWidth - kInsets.left()
+ : kAnchor.x() + kStrokeWidth - kBorderThickness,
kTopHorizArrowY},
+ {BubbleBorder::TOP_CENTER, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR,
+ UseMd() ? kAnchor.CenterPoint().x()
+ : kAnchor.CenterPoint().x() - kArrowOffsetForHorizCenter,
+ kTopHorizArrowY + (UseMd() ? kInsets.top() - kStrokeWidth : 0)},
{BubbleBorder::BOTTOM_RIGHT, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR,
- kAnchor.CenterPoint().x() + kArrowOffsetForNotCenter -
- kTotalSizeWithHorizArrow.width(),
+ UseMd() ? kAnchor.CenterPoint().x() - kTotalSizeWithHorizArrow.width()
+ : kAnchor.CenterPoint().x() + kArrowOffsetForNotCenter -
+ kTotalSizeWithHorizArrow.width(),
kBottomHorizArrowY},
{BubbleBorder::BOTTOM_RIGHT, BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE,
kAnchor.x() + kAnchor.width() - kTotalSizeWithHorizArrow.width() +
@@ -416,8 +449,9 @@ TEST_F(BubbleBorderTest, GetBoundsOriginTest) {
{BubbleBorder::LEFT_TOP, BubbleBorder::ALIGN_EDGE_TO_ANCHOR_EDGE,
kLeftVertArrowX, kAnchor.y() + kStrokeWidth - kBorderThickness},
{BubbleBorder::LEFT_CENTER, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR,
- kLeftVertArrowX,
- kAnchor.CenterPoint().y() - kArrowOffsetForVertCenter},
+ kLeftVertArrowX - (UseMd() ? kInsets.right() - kStrokeWidth : 0),
+ kAnchor.CenterPoint().y() - kArrowOffsetForVertCenter +
+ (UseMd() ? 2 * kStrokeWidth : 0)},
{BubbleBorder::RIGHT_BOTTOM, BubbleBorder::ALIGN_ARROW_TO_MID_ANCHOR,
kRightVertArrowX,
kAnchor.CenterPoint().y() + kArrowOffsetForNotCenter -
@@ -485,6 +519,8 @@ TEST_F(BubbleBorderTest, GetBoundsOriginTest) {
// Ensure all the shadow types pass some size validation and paint sanely.
TEST_F(BubbleBorderTest, ShadowTypes) {
+ if (UseMd())
+ return; // This test doesn't mean anything in MD mode.
const gfx::Rect rect(0, 0, 320, 200);
View paint_view;
paint_view.SetBoundsRect(rect);
diff --git a/chromium/ui/views/bubble/bubble_dialog_delegate.cc b/chromium/ui/views/bubble/bubble_dialog_delegate.cc
index b335b5bfc5d..405ee89345e 100644
--- a/chromium/ui/views/bubble/bubble_dialog_delegate.cc
+++ b/chromium/ui/views/bubble/bubble_dialog_delegate.cc
@@ -98,18 +98,14 @@ bool BubbleDialogDelegateView::ShouldShowCloseButton() const {
ClientView* BubbleDialogDelegateView::CreateClientView(Widget* widget) {
DialogClientView* client = new DialogClientView(widget, GetContentsView());
- LayoutProvider* provider = LayoutProvider::Get();
- // The other three sides are taken care of by the |margins_| given to
- // BubbleFrameView in CreateNonClientFrameView().
- client->SetButtonRowInsets(gfx::Insets(
- provider->GetDistanceMetric(DISTANCE_BUBBLE_BUTTON_TOP_MARGIN), 0, 0, 0));
widget->non_client_view()->set_mirror_client_in_rtl(mirror_arrow_in_rtl_);
return client;
}
NonClientFrameView* BubbleDialogDelegateView::CreateNonClientFrameView(
Widget* widget) {
- BubbleFrameView* frame = new BubbleFrameView(title_margins_, margins_);
+ BubbleFrameView* frame = new BubbleFrameView(title_margins_, gfx::Insets());
+ frame->set_footnote_margins(margins());
frame->SetFootnoteView(CreateFootnoteView());
BubbleBorder::Arrow adjusted_arrow = arrow();
@@ -178,7 +174,7 @@ void BubbleDialogDelegateView::OnBeforeBubbleWidgetInit(
void BubbleDialogDelegateView::UseCompactMargins() {
const int kCompactMargin = 6;
- margins_.Set(kCompactMargin, kCompactMargin, kCompactMargin, kCompactMargin);
+ set_margins(gfx::Insets(kCompactMargin));
}
void BubbleDialogDelegateView::SetAlignment(
@@ -218,8 +214,8 @@ BubbleDialogDelegateView::BubbleDialogDelegateView(View* anchor_view,
adjust_if_offscreen_(true),
parent_window_(nullptr) {
LayoutProvider* provider = LayoutProvider::Get();
- margins_ = provider->GetInsetsMetric(INSETS_BUBBLE_CONTENTS);
- title_margins_ = provider->GetInsetsMetric(INSETS_BUBBLE_TITLE);
+ set_margins(provider->GetInsetsMetric(INSETS_DIALOG_CONTENTS));
+ title_margins_ = provider->GetInsetsMetric(INSETS_DIALOG_TITLE);
if (anchor_view)
SetAnchorView(anchor_view);
UpdateColorsFromTheme(GetNativeTheme());
diff --git a/chromium/ui/views/bubble/bubble_dialog_delegate.h b/chromium/ui/views/bubble/bubble_dialog_delegate.h
index c3fc547307f..07172f1c020 100644
--- a/chromium/ui/views/bubble/bubble_dialog_delegate.h
+++ b/chromium/ui/views/bubble/bubble_dialog_delegate.h
@@ -41,14 +41,14 @@ class VIEWS_EXPORT BubbleDialogDelegateView : public DialogDelegateView,
// Create and initialize the bubble Widget(s) with proper bounds.
static Widget* CreateBubble(BubbleDialogDelegateView* bubble_delegate);
- // WidgetDelegateView overrides:
+ // WidgetDelegateView:
BubbleDialogDelegateView* AsBubbleDialogDelegate() override;
bool ShouldShowCloseButton() const override;
ClientView* CreateClientView(Widget* widget) override;
NonClientFrameView* CreateNonClientFrameView(Widget* widget) override;
const char* GetClassName() const override;
- // WidgetObserver overrides:
+ // WidgetObserver:
void OnWidgetDestroying(Widget* widget) override;
void OnWidgetVisibilityChanging(Widget* widget, bool visible) override;
void OnWidgetVisibilityChanged(Widget* widget, bool visible) override;
@@ -79,8 +79,6 @@ class VIEWS_EXPORT BubbleDialogDelegateView : public DialogDelegateView,
color_explicitly_set_ = true;
}
- const gfx::Insets& margins() const { return margins_; }
- void set_margins(const gfx::Insets& margins) { margins_ = margins; }
void set_title_margins(const gfx::Insets& title_margins) {
title_margins_ = title_margins;
}
@@ -104,7 +102,7 @@ class VIEWS_EXPORT BubbleDialogDelegateView : public DialogDelegateView,
virtual void OnBeforeBubbleWidgetInit(Widget::InitParams* params,
Widget* widget) const;
- // Sets |margins_| to a default picked for smaller bubbles.
+ // Sets the content margins to a default picked for smaller bubbles.
void UseCompactMargins();
// Sets the bubble alignment relative to the anchor. This may only be called
@@ -185,9 +183,6 @@ class VIEWS_EXPORT BubbleDialogDelegateView : public DialogDelegateView,
SkColor color_;
bool color_explicitly_set_;
- // The margins between the content and the inside of the border.
- gfx::Insets margins_;
-
// The margins around the title.
// TODO(tapted): Investigate deleting this when MD is default.
gfx::Insets title_margins_;
diff --git a/chromium/ui/views/bubble/bubble_dialog_delegate_unittest.cc b/chromium/ui/views/bubble/bubble_dialog_delegate_unittest.cc
index a6c2b175532..f556302ca17 100644
--- a/chromium/ui/views/bubble/bubble_dialog_delegate_unittest.cc
+++ b/chromium/ui/views/bubble/bubble_dialog_delegate_unittest.cc
@@ -19,18 +19,19 @@
#include "ui/views/test/views_test_base.h"
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_observer.h"
+#include "ui/views/window/dialog_client_view.h"
namespace views {
namespace {
+constexpr int kContentHeight = 200;
+constexpr int kContentWidth = 200;
+
class TestBubbleDialogDelegateView : public BubbleDialogDelegateView {
public:
TestBubbleDialogDelegateView(View* anchor_view)
- : BubbleDialogDelegateView(anchor_view, BubbleBorder::TOP_LEFT),
- view_(new View()),
- title_view_(nullptr),
- should_show_close_button_(false) {
+ : BubbleDialogDelegateView(anchor_view, BubbleBorder::TOP_LEFT) {
view_->SetFocusBehavior(FocusBehavior::ALWAYS);
AddChildView(view_);
}
@@ -39,7 +40,7 @@ class TestBubbleDialogDelegateView : public BubbleDialogDelegateView {
// BubbleDialogDelegateView overrides:
View* GetInitiallyFocusedView() override { return view_; }
gfx::Size CalculatePreferredSize() const override {
- return gfx::Size(200, 200);
+ return gfx::Size(kContentWidth, kContentHeight);
}
void AddedToWidget() override {
if (title_view_)
@@ -50,21 +51,36 @@ class TestBubbleDialogDelegateView : public BubbleDialogDelegateView {
return base::ASCIIToUTF16("TITLE TITLE TITLE");
}
+ bool ShouldShowWindowTitle() const override {
+ return should_show_window_title_;
+ }
+
bool ShouldShowCloseButton() const override {
return should_show_close_button_;
}
+ int GetDialogButtons() const override { return buttons_; }
+
void set_title_view(View* title_view) { title_view_.reset(title_view); }
void show_close_button() { should_show_close_button_ = true; }
+ void hide_buttons() {
+ should_show_close_button_ = false;
+ buttons_ = ui::DIALOG_BUTTON_NONE;
+ }
+ void set_should_show_window_title(bool should_show_window_title) {
+ should_show_window_title_ = should_show_window_title;
+ }
using BubbleDialogDelegateView::SetAnchorRect;
using BubbleDialogDelegateView::GetBubbleFrameView;
using BubbleDialogDelegateView::SizeToContents;
private:
- View* view_;
+ View* view_ = new View;
std::unique_ptr<View> title_view_;
- bool should_show_close_button_;
+ int buttons_ = ui::DIALOG_BUTTON_OK | ui::DIALOG_BUTTON_CANCEL;
+ bool should_show_close_button_ = false;
+ bool should_show_window_title_ = true;
DISALLOW_COPY_AND_ASSIGN(TestBubbleDialogDelegateView);
};
@@ -360,8 +376,8 @@ TEST_F(BubbleDialogDelegateTest, CustomTitle) {
std::unique_ptr<Widget> anchor_widget(CreateTestWidget());
TestBubbleDialogDelegateView* bubble_delegate =
new TestBubbleDialogDelegateView(anchor_widget->GetContentsView());
- constexpr int kTitlePreferredHeight = 20;
- View* title_view = new StaticSizedView(gfx::Size(10, kTitlePreferredHeight));
+ constexpr int kTitleHeight = 20;
+ View* title_view = new StaticSizedView(gfx::Size(10, kTitleHeight));
bubble_delegate->set_title_view(title_view);
Widget* bubble_widget =
BubbleDialogDelegateView::CreateBubble(bubble_delegate);
@@ -373,7 +389,7 @@ TEST_F(BubbleDialogDelegateTest, CustomTitle) {
EXPECT_EQ(bubble_frame, title_view->parent());
// Title takes up the whole bubble width when there's no icon or close button.
EXPECT_EQ(bubble_delegate->width(), title_view->size().width());
- EXPECT_EQ(kTitlePreferredHeight, title_view->size().height());
+ EXPECT_EQ(kTitleHeight, title_view->size().height());
bubble_delegate->show_close_button();
bubble_frame->ResetWindowControls();
@@ -384,6 +400,50 @@ TEST_F(BubbleDialogDelegateTest, CustomTitle) {
EXPECT_EQ(close_button->x() - LayoutProvider::Get()->GetDistanceMetric(
DISTANCE_CLOSE_BUTTON_MARGIN),
title_view->bounds().right());
+
+ LayoutProvider* provider = LayoutProvider::Get();
+ const gfx::Insets content_margins =
+ provider->GetInsetsMetric(INSETS_DIALOG_CONTENTS);
+ const gfx::Insets title_margins =
+ provider->GetInsetsMetric(INSETS_DIALOG_TITLE);
+ EXPECT_EQ(content_margins, bubble_delegate->margins());
+ // Note there is no title_margins() accessor (it should not be customizable).
+
+ // To perform checks on the precise size, first hide the dialog buttons so the
+ // calculations are simpler (e.g. platform font discrepancies can be ignored).
+ DialogClientView* client_view =
+ static_cast<DialogClientView*>(bubble_widget->client_view());
+ bubble_delegate->hide_buttons();
+ bubble_frame->ResetWindowControls();
+ client_view->UpdateDialogButtons();
+ bubble_delegate->SizeToContents();
+
+ // Use GetContentsBounds() to exclude the bubble border, which can change per
+ // platform.
+ gfx::Rect frame_size = bubble_frame->GetContentsBounds();
+ EXPECT_EQ(content_margins.height() + kContentHeight + title_margins.height() +
+ kTitleHeight,
+ frame_size.height());
+ EXPECT_EQ(content_margins.width() + kContentWidth, frame_size.width());
+
+ // Set the title preferred size to 0. The bubble frame makes fewer assumptions
+ // about custom title views, so there should still be margins for it while the
+ // WidgetDelegate says it should be shown, even if its preferred size is zero.
+ title_view->SetPreferredSize(gfx::Size());
+ bubble_widget->UpdateWindowTitle();
+ bubble_delegate->SizeToContents();
+ frame_size = bubble_frame->GetContentsBounds();
+ EXPECT_EQ(content_margins.height() + kContentHeight + title_margins.height(),
+ frame_size.height());
+ EXPECT_EQ(content_margins.width() + kContentWidth, frame_size.width());
+
+ // Now hide the title properly. The margins should also disappear.
+ bubble_delegate->set_should_show_window_title(false);
+ bubble_widget->UpdateWindowTitle();
+ bubble_delegate->SizeToContents();
+ frame_size = bubble_frame->GetContentsBounds();
+ EXPECT_EQ(content_margins.height() + kContentHeight, frame_size.height());
+ EXPECT_EQ(content_margins.width() + kContentWidth, frame_size.width());
}
// Ensure the BubbleFrameView correctly resizes when the title is provided by a
diff --git a/chromium/ui/views/bubble/bubble_frame_view.cc b/chromium/ui/views/bubble/bubble_frame_view.cc
index a04b0982ebc..302bce50f87 100644
--- a/chromium/ui/views/bubble/bubble_frame_view.cc
+++ b/chromium/ui/views/bubble/bubble_frame_view.cc
@@ -14,7 +14,6 @@
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/material_design/material_design_controller.h"
#include "ui/base/resource/resource_bundle.h"
-#include "ui/compositor/paint_context.h"
#include "ui/compositor/paint_recorder.h"
#include "ui/display/display.h"
#include "ui/display/screen.h"
@@ -31,6 +30,7 @@
#include "ui/views/controls/image_view.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/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
@@ -72,6 +72,21 @@ int GetOffScreenLength(const gfx::Rect& available_bounds,
} // namespace
+// A container that changes visibility with its contents.
+class FootnoteContainerView : public View {
+ public:
+ FootnoteContainerView() {}
+
+ // View:
+ void ChildVisibilityChanged(View* child) override {
+ DCHECK_EQ(child_count(), 1);
+ SetVisible(child->visible());
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FootnoteContainerView);
+};
+
// static
const char BubbleFrameView::kViewClassName[] = "BubbleFrameView";
@@ -80,6 +95,7 @@ BubbleFrameView::BubbleFrameView(const gfx::Insets& title_margins,
: bubble_border_(nullptr),
title_margins_(title_margins),
content_margins_(content_margins),
+ footnote_margins_(content_margins_),
title_icon_(new views::ImageView()),
default_title_(CreateDefaultTitleLabel(base::string16()).release()),
custom_title_(nullptr),
@@ -122,13 +138,13 @@ Button* BubbleFrameView::CreateCloseButton(ButtonListener* listener) {
} else {
ui::ResourceBundle* rb = &ui::ResourceBundle::GetSharedInstance();
close_button = new ImageButton(listener);
- close_button->SetImage(CustomButton::STATE_NORMAL,
+ close_button->SetImage(Button::STATE_NORMAL,
*rb->GetImageNamed(IDR_CLOSE_DIALOG).ToImageSkia());
close_button->SetImage(
- CustomButton::STATE_HOVERED,
+ Button::STATE_HOVERED,
*rb->GetImageNamed(IDR_CLOSE_DIALOG_H).ToImageSkia());
close_button->SetImage(
- CustomButton::STATE_PRESSED,
+ Button::STATE_PRESSED,
*rb->GetImageNamed(IDR_CLOSE_DIALOG_P).ToImageSkia());
}
close_button->SetTooltipText(l10n_util::GetStringUTF16(IDS_APP_CLOSE));
@@ -147,7 +163,9 @@ gfx::Rect BubbleFrameView::GetBoundsForClientView() const {
// (i.e. |this|), but not the client view bounds.
gfx::Rect client_bounds = GetContentsBounds();
client_bounds.Inset(GetClientInsetsForFrameWidth(client_bounds.width()));
- if (footnote_container_) {
+ // Only account for footnote_container_'s height if it's visible, because
+ // content_margins_ adds extra padding even if all child views are invisible.
+ if (footnote_container_ && footnote_container_->visible()) {
client_bounds.set_height(client_bounds.height() -
footnote_container_->height());
}
@@ -364,12 +382,14 @@ void BubbleFrameView::Layout() {
std::max(title_icon_pref_size.height(), title_preferred_height);
title()->SetBounds(title_label_x,
bounds.y() + (title_height - title_preferred_height) / 2,
- title_available_width, title_height);
+ title_available_width, title_preferred_height);
title_icon_->SetBounds(bounds.x(), bounds.y(), title_icon_pref_size.width(),
title_height);
- if (footnote_container_) {
+ // Only account for footnote_container_'s height if it's visible, because
+ // content_margins_ adds extra padding even if all child views are invisible.
+ if (footnote_container_ && footnote_container_->visible()) {
const int width = contents_bounds.width();
const int height = footnote_container_->GetHeightForWidth(width);
footnote_container_->SetBounds(
@@ -409,11 +429,14 @@ void BubbleFrameView::OnPaint(gfx::Canvas* canvas) {
// Border comes after children.
}
-void BubbleFrameView::PaintChildren(const ui::PaintContext& context) {
- NonClientFrameView::PaintChildren(context);
+void BubbleFrameView::PaintChildren(const PaintInfo& paint_info) {
+ NonClientFrameView::PaintChildren(paint_info);
ui::PaintCache paint_cache;
- ui::PaintRecorder recorder(context, size(), &paint_cache);
+ ui::PaintRecorder recorder(
+ paint_info.context(), paint_info.paint_recording_size(),
+ paint_info.paint_recording_scale_x(),
+ paint_info.paint_recording_scale_y(), &paint_cache);
OnPaintBorder(recorder.canvas());
}
@@ -437,14 +460,15 @@ void BubbleFrameView::SetFootnoteView(View* view) {
return;
DCHECK(!footnote_container_);
- footnote_container_ = new views::View();
+ footnote_container_ = new FootnoteContainerView();
footnote_container_->SetLayoutManager(
- new BoxLayout(BoxLayout::kVertical, content_margins_, 0));
+ new BoxLayout(BoxLayout::kVertical, footnote_margins_, 0));
footnote_container_->SetBackground(
CreateSolidBackground(kFootnoteBackgroundColor));
footnote_container_->SetBorder(
CreateSolidSidedBorder(1, 0, 0, 0, kFootnoteBorderColor));
footnote_container_->AddChildView(view);
+ footnote_container_->SetVisible(view->visible());
AddChildView(footnote_container_);
}
@@ -573,15 +597,19 @@ gfx::Size BubbleFrameView::GetFrameSizeForClientSize(
DCHECK_GE(frame_width, client_size.width());
gfx::Size size(frame_width, client_size.height() + client_insets.height());
- if (footnote_container_)
+ // Only account for footnote_container_'s height if it's visible, because
+ // content_margins_ adds extra padding even if all child views are invisible.
+ if (footnote_container_ && footnote_container_->visible())
size.Enlarge(0, footnote_container_->GetHeightForWidth(size.width()));
return size;
}
bool BubbleFrameView::HasTitle() const {
- return custom_title_ != nullptr ||
- default_title_->GetPreferredSize().height() > 0 ||
+ return (custom_title_ != nullptr &&
+ GetWidget()->widget_delegate()->ShouldShowWindowTitle()) ||
+ (default_title_ != nullptr &&
+ default_title_->GetPreferredSize().height() > 0) ||
title_icon_->GetPreferredSize().height() > 0;
}
diff --git a/chromium/ui/views/bubble/bubble_frame_view.h b/chromium/ui/views/bubble/bubble_frame_view.h
index 1b72b8d80e4..1369874c91c 100644
--- a/chromium/ui/views/bubble/bubble_frame_view.h
+++ b/chromium/ui/views/bubble/bubble_frame_view.h
@@ -60,7 +60,7 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView,
gfx::Size GetMaximumSize() const override;
void Layout() override;
void OnPaint(gfx::Canvas* canvas) override;
- void PaintChildren(const ui::PaintContext& context) override;
+ void PaintChildren(const PaintInfo& paint_info) override;
void OnThemeChanged() override;
void OnNativeThemeChanged(const ui::NativeTheme* theme) override;
void ViewHierarchyChanged(
@@ -84,6 +84,9 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView,
gfx::Insets content_margins() const { return content_margins_; }
void SetFootnoteView(View* view);
+ void set_footnote_margins(const gfx::Insets& footnote_margins) {
+ footnote_margins_ = footnote_margins;
+ }
// Given the size of the contents and the rect to point at, returns the bounds
// of the bubble window. The bubble's arrow location may change if the bubble
@@ -106,6 +109,7 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView,
private:
FRIEND_TEST_ALL_PREFIXES(BubbleFrameViewTest, GetBoundsForClientView);
FRIEND_TEST_ALL_PREFIXES(BubbleFrameViewTest, RemoveFootnoteView);
+ FRIEND_TEST_ALL_PREFIXES(BubbleFrameViewTest, LayoutWithIcon);
FRIEND_TEST_ALL_PREFIXES(BubbleDelegateTest, CloseReasons);
FRIEND_TEST_ALL_PREFIXES(BubbleDialogDelegateTest, CloseMethods);
@@ -150,6 +154,9 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView,
// Margins between the content and the inside of the border, in pixels.
gfx::Insets content_margins_;
+ // Margins between the footnote view and the footnote container.
+ gfx::Insets footnote_margins_;
+
// The optional title icon.
views::ImageView* title_icon_;
diff --git a/chromium/ui/views/bubble/bubble_frame_view_unittest.cc b/chromium/ui/views/bubble/bubble_frame_view_unittest.cc
index c2ebde257a0..583c4a8082f 100644
--- a/chromium/ui/views/bubble/bubble_frame_view_unittest.cc
+++ b/chromium/ui/views/bubble/bubble_frame_view_unittest.cc
@@ -7,7 +7,9 @@
#include <memory>
#include "base/macros.h"
+#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
+#include "ui/base/material_design/material_design_controller.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
@@ -26,6 +28,10 @@ typedef ViewsTestBase BubbleFrameViewTest;
namespace {
+bool UseMd() {
+ return ui::MaterialDesignController::IsSecondaryUiMaterial();
+}
+
const BubbleBorder::Arrow kArrow = BubbleBorder::TOP_LEFT;
const SkColor kColor = SK_ColorRED;
const int kMargin = 6;
@@ -168,6 +174,20 @@ TEST_F(BubbleFrameViewTest, GetBoundsForClientViewWithClose) {
frame.GetBoundsForClientView().y());
}
+TEST_F(BubbleFrameViewTest,
+ FootnoteContainerViewShouldMatchVisibilityOfFirstChild) {
+ TestBubbleFrameView frame(this);
+ View* footnote_dummy_view = new StaticSizedView(gfx::Size(200, 200));
+ footnote_dummy_view->SetVisible(false);
+ frame.SetFootnoteView(footnote_dummy_view);
+ View* footnote_container_view = footnote_dummy_view->parent();
+ EXPECT_FALSE(footnote_container_view->visible());
+ footnote_dummy_view->SetVisible(true);
+ EXPECT_TRUE(footnote_container_view->visible());
+ footnote_dummy_view->SetVisible(false);
+ EXPECT_FALSE(footnote_container_view->visible());
+}
+
// Tests that the arrow is mirrored as needed to better fit the screen.
TEST_F(BubbleFrameViewTest, GetUpdatedWindowBounds) {
TestBubbleFrameView frame(this);
@@ -345,15 +365,25 @@ TEST_F(BubbleFrameViewTest, GetUpdatedWindowBoundsDontTryMirror) {
TEST_F(BubbleFrameViewTest, GetUpdatedWindowBoundsCenterArrows) {
TestBubbleFrameView frame(this);
gfx::Rect window_bounds;
+ // Bubbles have a thicker shadow on the bottom in MD.
+ // Match definition of kLargeShadowVerticalOffset in bubble_border.cc.
+ const int kLargeShadowVerticalOffset = UseMd() ? 2 : 0;
+
+ // Some of these tests may go away once --secondary-ui-md becomes the
+ // default. Under Material Design mode, the BubbleBorder doesn't support all
+ // "arrow" positions. If this changes, then the tests should be updated or
+ // added for MD mode.
// Test that the bubble displays normally when it fits.
- frame.bubble_border()->set_arrow(BubbleBorder::TOP_CENTER);
- window_bounds = frame.GetUpdatedWindowBounds(
- gfx::Rect(500, 100, 50, 50), // |anchor_rect|
- gfx::Size(500, 500), // |client_size|
- true); // |adjust_if_offscreen|
- EXPECT_EQ(BubbleBorder::TOP_CENTER, frame.bubble_border()->arrow());
- EXPECT_EQ(window_bounds.x() + window_bounds.width() / 2, 525);
+ if (!UseMd()) { // TOP_CENTER isn't supported by the bubble_border() in MD.
+ frame.bubble_border()->set_arrow(BubbleBorder::TOP_CENTER);
+ window_bounds = frame.GetUpdatedWindowBounds(
+ gfx::Rect(500, 100, 50, 50), // |anchor_rect|
+ gfx::Size(500, 500), // |client_size|
+ true); // |adjust_if_offscreen|
+ EXPECT_EQ(BubbleBorder::TOP_CENTER, frame.bubble_border()->arrow());
+ EXPECT_EQ(window_bounds.x() + window_bounds.width() / 2, 525);
+ }
frame.bubble_border()->set_arrow(BubbleBorder::BOTTOM_CENTER);
window_bounds = frame.GetUpdatedWindowBounds(
@@ -369,7 +399,8 @@ TEST_F(BubbleFrameViewTest, GetUpdatedWindowBoundsCenterArrows) {
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::LEFT_CENTER, frame.bubble_border()->arrow());
- EXPECT_EQ(window_bounds.y() + window_bounds.height() / 2, 425);
+ EXPECT_EQ(window_bounds.y() + window_bounds.height() / 2,
+ 425 + kLargeShadowVerticalOffset);
frame.bubble_border()->set_arrow(BubbleBorder::RIGHT_CENTER);
window_bounds = frame.GetUpdatedWindowBounds(
@@ -377,18 +408,22 @@ TEST_F(BubbleFrameViewTest, GetUpdatedWindowBoundsCenterArrows) {
gfx::Size(500, 500), // |client_size|
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::RIGHT_CENTER, frame.bubble_border()->arrow());
- EXPECT_EQ(window_bounds.y() + window_bounds.height() / 2, 425);
+ EXPECT_EQ(window_bounds.y() + window_bounds.height() / 2,
+ 425 + kLargeShadowVerticalOffset);
// Test bubble not fitting left screen edge.
- frame.bubble_border()->set_arrow(BubbleBorder::TOP_CENTER);
- window_bounds = frame.GetUpdatedWindowBounds(
- gfx::Rect(100, 100, 50, 50), // |anchor_rect|
- gfx::Size(500, 500), // |client_size|
- true); // |adjust_if_offscreen|
- EXPECT_EQ(BubbleBorder::TOP_CENTER, frame.bubble_border()->arrow());
- EXPECT_EQ(window_bounds.x(), 0);
- EXPECT_EQ(window_bounds.x() +
- frame.bubble_border()->GetArrowOffset(window_bounds.size()), 125);
+ if (!UseMd()) { // TOP_CENTER isn't supported by the bubble_border() in MD.
+ frame.bubble_border()->set_arrow(BubbleBorder::TOP_CENTER);
+ window_bounds = frame.GetUpdatedWindowBounds(
+ gfx::Rect(100, 100, 50, 50), // |anchor_rect|
+ gfx::Size(500, 500), // |client_size|
+ true); // |adjust_if_offscreen|
+ EXPECT_EQ(BubbleBorder::TOP_CENTER, frame.bubble_border()->arrow());
+ EXPECT_EQ(window_bounds.x(), 0);
+ EXPECT_EQ(window_bounds.x() +
+ frame.bubble_border()->GetArrowOffset(window_bounds.size()),
+ 125);
+ }
frame.bubble_border()->set_arrow(BubbleBorder::BOTTOM_CENTER);
window_bounds = frame.GetUpdatedWindowBounds(
@@ -397,19 +432,25 @@ TEST_F(BubbleFrameViewTest, GetUpdatedWindowBoundsCenterArrows) {
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::BOTTOM_CENTER, frame.bubble_border()->arrow());
EXPECT_EQ(window_bounds.x(), 0);
- EXPECT_EQ(window_bounds.x() +
- frame.bubble_border()->GetArrowOffset(window_bounds.size()), 125);
+ if (!UseMd()) { // There is no arrow offset in MD mode.
+ EXPECT_EQ(window_bounds.x() +
+ frame.bubble_border()->GetArrowOffset(window_bounds.size()),
+ 125);
+ }
// Test bubble not fitting right screen edge.
- frame.bubble_border()->set_arrow(BubbleBorder::TOP_CENTER);
- window_bounds = frame.GetUpdatedWindowBounds(
- gfx::Rect(900, 100, 50, 50), // |anchor_rect|
- gfx::Size(500, 500), // |client_size|
- true); // |adjust_if_offscreen|
- EXPECT_EQ(BubbleBorder::TOP_CENTER, frame.bubble_border()->arrow());
- EXPECT_EQ(window_bounds.right(), 1000);
- EXPECT_EQ(window_bounds.x() +
- frame.bubble_border()->GetArrowOffset(window_bounds.size()), 925);
+ if (!UseMd()) { // TOP_CENTER isn't supported by the bubble_border() in MD.
+ frame.bubble_border()->set_arrow(BubbleBorder::TOP_CENTER);
+ window_bounds = frame.GetUpdatedWindowBounds(
+ gfx::Rect(900, 100, 50, 50), // |anchor_rect|
+ gfx::Size(500, 500), // |client_size|
+ true); // |adjust_if_offscreen|
+ EXPECT_EQ(BubbleBorder::TOP_CENTER, frame.bubble_border()->arrow());
+ EXPECT_EQ(window_bounds.right(), 1000);
+ EXPECT_EQ(window_bounds.x() +
+ frame.bubble_border()->GetArrowOffset(window_bounds.size()),
+ 925);
+ }
frame.bubble_border()->set_arrow(BubbleBorder::BOTTOM_CENTER);
window_bounds = frame.GetUpdatedWindowBounds(
@@ -418,53 +459,64 @@ TEST_F(BubbleFrameViewTest, GetUpdatedWindowBoundsCenterArrows) {
true); // |adjust_if_offscreen|
EXPECT_EQ(BubbleBorder::BOTTOM_CENTER, frame.bubble_border()->arrow());
EXPECT_EQ(window_bounds.right(), 1000);
- EXPECT_EQ(window_bounds.x() +
- frame.bubble_border()->GetArrowOffset(window_bounds.size()), 925);
+ if (!UseMd()) { // There is no arrow offset in MD mode.
+ EXPECT_EQ(window_bounds.x() +
+ frame.bubble_border()->GetArrowOffset(window_bounds.size()),
+ 925);
+ }
// Test bubble not fitting top screen edge.
- frame.bubble_border()->set_arrow(BubbleBorder::LEFT_CENTER);
- window_bounds = frame.GetUpdatedWindowBounds(
- gfx::Rect(100, 100, 50, 50), // |anchor_rect|
- gfx::Size(500, 500), // |client_size|
- true); // |adjust_if_offscreen|
- EXPECT_EQ(BubbleBorder::LEFT_CENTER, frame.bubble_border()->arrow());
- EXPECT_EQ(window_bounds.y(), 0);
- EXPECT_EQ(window_bounds.y() +
- frame.bubble_border()->GetArrowOffset(window_bounds.size()), 125);
-
- frame.bubble_border()->set_arrow(BubbleBorder::RIGHT_CENTER);
- window_bounds = frame.GetUpdatedWindowBounds(
- gfx::Rect(900, 100, 50, 50), // |anchor_rect|
- gfx::Size(500, 500), // |client_size|
- true); // |adjust_if_offscreen|
- EXPECT_EQ(BubbleBorder::RIGHT_CENTER, frame.bubble_border()->arrow());
- EXPECT_EQ(window_bounds.y(), 0);
- EXPECT_EQ(window_bounds.y() +
- frame.bubble_border()->GetArrowOffset(window_bounds.size()), 125);
-
- // Test bubble not fitting bottom screen edge.
- frame.bubble_border()->set_arrow(BubbleBorder::LEFT_CENTER);
- window_bounds = frame.GetUpdatedWindowBounds(
- gfx::Rect(100, 900, 50, 50), // |anchor_rect|
- gfx::Size(500, 500), // |client_size|
- true); // |adjust_if_offscreen|
- EXPECT_EQ(BubbleBorder::LEFT_CENTER, frame.bubble_border()->arrow());
- EXPECT_EQ(window_bounds.bottom(), 1000);
- EXPECT_EQ(window_bounds.y() +
- frame.bubble_border()->GetArrowOffset(window_bounds.size()), 925);
-
- frame.bubble_border()->set_arrow(BubbleBorder::RIGHT_CENTER);
- window_bounds = frame.GetUpdatedWindowBounds(
- gfx::Rect(900, 900, 50, 50), // |anchor_rect|
- gfx::Size(500, 500), // |client_size|
- true); // |adjust_if_offscreen|
- EXPECT_EQ(BubbleBorder::RIGHT_CENTER, frame.bubble_border()->arrow());
- EXPECT_EQ(window_bounds.bottom(), 1000);
- EXPECT_EQ(window_bounds.y() +
- frame.bubble_border()->GetArrowOffset(window_bounds.size()), 925);
+ if (!UseMd()) { // Moving the bubble by setting the arrow offset doesn't work
+ // in MD mode since there is no arrow displayed.
+ frame.bubble_border()->set_arrow(BubbleBorder::LEFT_CENTER);
+ window_bounds = frame.GetUpdatedWindowBounds(
+ gfx::Rect(100, 100, 50, 50), // |anchor_rect|
+ gfx::Size(500, 500), // |client_size|
+ true); // |adjust_if_offscreen|
+ EXPECT_EQ(BubbleBorder::LEFT_CENTER, frame.bubble_border()->arrow());
+ EXPECT_EQ(window_bounds.y(), 0);
+ EXPECT_EQ(window_bounds.y() +
+ frame.bubble_border()->GetArrowOffset(window_bounds.size()),
+ 125);
+
+ frame.bubble_border()->set_arrow(BubbleBorder::RIGHT_CENTER);
+ window_bounds = frame.GetUpdatedWindowBounds(
+ gfx::Rect(900, 100, 50, 50), // |anchor_rect|
+ gfx::Size(500, 500), // |client_size|
+ true); // |adjust_if_offscreen|
+ EXPECT_EQ(BubbleBorder::RIGHT_CENTER, frame.bubble_border()->arrow());
+ EXPECT_EQ(window_bounds.y(), 0);
+ EXPECT_EQ(window_bounds.y() +
+ frame.bubble_border()->GetArrowOffset(window_bounds.size()),
+ 125);
+
+ // Test bubble not fitting bottom screen edge.
+ frame.bubble_border()->set_arrow(BubbleBorder::LEFT_CENTER);
+ window_bounds = frame.GetUpdatedWindowBounds(
+ gfx::Rect(100, 900, 50, 50), // |anchor_rect|
+ gfx::Size(500, 500), // |client_size|
+ true); // |adjust_if_offscreen|
+ EXPECT_EQ(BubbleBorder::LEFT_CENTER, frame.bubble_border()->arrow());
+ EXPECT_EQ(window_bounds.bottom(), 1000);
+ EXPECT_EQ(window_bounds.y() +
+ frame.bubble_border()->GetArrowOffset(window_bounds.size()),
+ 925);
+
+ frame.bubble_border()->set_arrow(BubbleBorder::RIGHT_CENTER);
+ window_bounds = frame.GetUpdatedWindowBounds(
+ gfx::Rect(900, 900, 50, 50), // |anchor_rect|
+ gfx::Size(500, 500), // |client_size|
+ true); // |adjust_if_offscreen|
+ EXPECT_EQ(BubbleBorder::RIGHT_CENTER, frame.bubble_border()->arrow());
+ EXPECT_EQ(window_bounds.bottom(), 1000);
+ EXPECT_EQ(window_bounds.y() +
+ frame.bubble_border()->GetArrowOffset(window_bounds.size()),
+ 925);
+ }
}
TEST_F(BubbleFrameViewTest, GetPreferredSize) {
+ // Test border/insets.
TestBubbleFrameView frame(this);
gfx::Rect preferred_rect(frame.GetPreferredSize());
// Expect that a border has been added to the preferred size.
@@ -475,6 +527,29 @@ TEST_F(BubbleFrameViewTest, GetPreferredSize) {
EXPECT_EQ(expected_size, preferred_rect.size());
}
+TEST_F(BubbleFrameViewTest, GetPreferredSizeWithFootnote) {
+ // Test footnote view: adding a footnote should increase the preferred size,
+ // but only when the footnote is visible.
+ TestBubbleFrameView frame(this);
+
+ constexpr int kFootnoteHeight = 20;
+ const gfx::Size no_footnote_size = frame.GetPreferredSize();
+ View* footnote = new StaticSizedView(gfx::Size(10, kFootnoteHeight));
+ footnote->SetVisible(false);
+ frame.SetFootnoteView(footnote);
+ EXPECT_EQ(no_footnote_size, frame.GetPreferredSize()); // No change.
+
+ footnote->SetVisible(true);
+ gfx::Size with_footnote_size = no_footnote_size;
+ constexpr int kFootnoteTopBorderThickness = 1;
+ with_footnote_size.Enlarge(0, kFootnoteHeight + kFootnoteTopBorderThickness +
+ frame.content_margins().height());
+ EXPECT_EQ(with_footnote_size, frame.GetPreferredSize());
+
+ footnote->SetVisible(false);
+ EXPECT_EQ(no_footnote_size, frame.GetPreferredSize());
+}
+
TEST_F(BubbleFrameViewTest, GetMinimumSize) {
TestBubbleFrameView frame(this);
gfx::Rect minimum_rect(frame.GetMinimumSize());
@@ -524,10 +599,13 @@ class TestBubbleDialogDelegateView : public BubbleDialogDelegateView {
}
void set_override_snap(bool value) { override_snap_ = value; }
+ void set_icon(const gfx::ImageSkia& icon) { icon_ = icon; }
// BubbleDialogDelegateView:
using BubbleDialogDelegateView::SetAnchorView;
using BubbleDialogDelegateView::SizeToContents;
+ gfx::ImageSkia GetWindowIcon() override { return icon_; }
+ bool ShouldShowWindowIcon() const override { return !icon_.isNull(); }
base::string16 GetWindowTitle() const override { return title_; }
bool ShouldShowWindowTitle() const override { return !title_.empty(); }
@@ -545,7 +623,13 @@ class TestBubbleDialogDelegateView : public BubbleDialogDelegateView {
return gfx::Size(200, 200);
}
+ BubbleFrameView* GetBubbleFrameView() const {
+ return static_cast<BubbleFrameView*>(
+ GetWidget()->non_client_view()->frame_view());
+ }
+
private:
+ gfx::ImageSkia icon_;
base::string16 title_;
base::Optional<bool> override_snap_;
@@ -684,4 +768,29 @@ TEST_F(BubbleFrameViewTest, LayoutEdgeCases) {
// When |anchor| goes out of scope it should take |bubble| with it.
}
+TEST_F(BubbleFrameViewTest, LayoutWithIcon) {
+ TestBubbleDialogDelegateView delegate;
+ TestAnchor anchor(CreateParams(Widget::InitParams::TYPE_WINDOW));
+ delegate.SetAnchorView(anchor.widget().GetContentsView());
+ SkBitmap bitmap;
+ bitmap.allocN32Pixels(20, 80);
+ delegate.set_icon(gfx::ImageSkia::CreateFrom1xBitmap(bitmap));
+
+ Widget* widget = BubbleDialogDelegateView::CreateBubble(&delegate);
+ widget->Show();
+
+ delegate.ChangeTitle(base::ASCIIToUTF16("test title"));
+ BubbleFrameView* frame = delegate.GetBubbleFrameView();
+ View* icon = frame->title_icon_;
+ View* title = frame->title();
+
+ // There should be equal amounts of space on the left and right of the icon.
+ EXPECT_EQ(icon->x() * 2 + icon->width(), title->x());
+
+ // The title should be vertically centered relative to the icon.
+ EXPECT_LT(title->height(), icon->height());
+ const int title_offset_y = (icon->height() - title->height()) / 2;
+ EXPECT_EQ(icon->y() + title_offset_y, title->y());
+}
+
} // namespace views
diff --git a/chromium/ui/views/bubble/bubble_window_targeter.cc b/chromium/ui/views/bubble/bubble_window_targeter.cc
deleted file mode 100644
index 8fa0da81c94..00000000000
--- a/chromium/ui/views/bubble/bubble_window_targeter.cc
+++ /dev/null
@@ -1,29 +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/views/bubble/bubble_window_targeter.h"
-
-#include "ui/aura/window.h"
-#include "ui/gfx/path.h"
-#include "ui/gfx/skia_util.h"
-#include "ui/views/bubble/bubble_dialog_delegate.h"
-#include "ui/views/bubble/bubble_frame_view.h"
-
-namespace views {
-
-BubbleWindowTargeter::BubbleWindowTargeter(BubbleDialogDelegateView* bubble)
- : wm::MaskedWindowTargeter(bubble->GetWidget()->GetNativeView()),
- bubble_(bubble) {}
-
-BubbleWindowTargeter::~BubbleWindowTargeter() {
-}
-
-bool BubbleWindowTargeter::GetHitTestMask(aura::Window* window,
- gfx::Path* mask) const {
- mask->addRect(
- gfx::RectToSkRect(bubble_->GetBubbleFrameView()->GetContentsBounds()));
- return true;
-}
-
-} // namespace views
diff --git a/chromium/ui/views/bubble/bubble_window_targeter.h b/chromium/ui/views/bubble/bubble_window_targeter.h
deleted file mode 100644
index 7b7f87b5f76..00000000000
--- a/chromium/ui/views/bubble/bubble_window_targeter.h
+++ /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 "base/macros.h"
-#include "ui/views/views_export.h"
-#include "ui/wm/core/masked_window_targeter.h"
-
-namespace aura {
-class Window;
-}
-
-namespace views {
-
-class BubbleDialogDelegateView;
-
-// A convenient window-targeter that uses a mask based on the content-bounds of
-// the bubble-frame.
-class VIEWS_EXPORT BubbleWindowTargeter
- : public NON_EXPORTED_BASE(wm::MaskedWindowTargeter) {
- public:
- explicit BubbleWindowTargeter(BubbleDialogDelegateView* bubble);
- ~BubbleWindowTargeter() override;
-
- private:
- // wm::MaskedWindowTargeter:
- bool GetHitTestMask(aura::Window* window, gfx::Path* mask) const override;
-
- views::BubbleDialogDelegateView* bubble_;
-
- DISALLOW_COPY_AND_ASSIGN(BubbleWindowTargeter);
-};
-
-} // namespace views
diff --git a/chromium/ui/views/bubble/bubble_window_targeter_unittest.cc b/chromium/ui/views/bubble/bubble_window_targeter_unittest.cc
deleted file mode 100644
index 975d68e82db..00000000000
--- a/chromium/ui/views/bubble/bubble_window_targeter_unittest.cc
+++ /dev/null
@@ -1,123 +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/views/bubble/bubble_window_targeter.h"
-
-#include "base/macros.h"
-#include "ui/aura/window.h"
-#include "ui/aura/window_event_dispatcher.h"
-#include "ui/aura/window_tree_host.h"
-#include "ui/events/event_utils.h"
-#include "ui/views/bubble/bubble_border.h"
-#include "ui/views/bubble/bubble_dialog_delegate.h"
-#include "ui/views/test/views_test_base.h"
-#include "ui/views/widget/widget.h"
-
-namespace views {
-
-namespace {
-
-class WidgetOwnsNativeBubble : public BubbleDialogDelegateView {
- public:
- WidgetOwnsNativeBubble(View* content, BubbleBorder::Arrow arrow)
- : BubbleDialogDelegateView(content, arrow) {}
-
- ~WidgetOwnsNativeBubble() override {}
-
- private:
- // BubbleDialogDelegateView:
- void OnBeforeBubbleWidgetInit(Widget::InitParams* params,
- Widget* widget) const override {
- params->ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- }
-
- DISALLOW_COPY_AND_ASSIGN(WidgetOwnsNativeBubble);
-};
-
-} // namespace
-
-class BubbleWindowTargeterTest : public ViewsTestBase {
- public:
- BubbleWindowTargeterTest()
- : bubble_delegate_(NULL) {
- }
- ~BubbleWindowTargeterTest() override {}
-
- void SetUp() override {
- ViewsTestBase::SetUp();
- CreateAnchorWidget();
- CreateBubbleWidget();
-
- anchor_widget()->Show();
- bubble_widget()->Show();
- }
-
- void TearDown() override {
- bubble_delegate_ = NULL;
- bubble_widget_.reset();
- anchor_.reset();
- ViewsTestBase::TearDown();
- }
-
- Widget* anchor_widget() { return anchor_.get(); }
- Widget* bubble_widget() { return bubble_widget_.get(); }
- BubbleDialogDelegateView* bubble_delegate() { return bubble_delegate_; }
-
- private:
- void CreateAnchorWidget() {
- anchor_.reset(new Widget());
- Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_WINDOW);
- params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
- anchor_->Init(params);
- }
-
- void CreateBubbleWidget() {
- bubble_delegate_ = new WidgetOwnsNativeBubble(
- anchor_->GetContentsView(), BubbleBorder::NONE);
- bubble_delegate_->set_color(SK_ColorGREEN);
- bubble_widget_.reset(
- BubbleDialogDelegateView::CreateBubble(bubble_delegate_));
- }
-
- std::unique_ptr<Widget> anchor_;
- std::unique_ptr<Widget> bubble_widget_;
- BubbleDialogDelegateView* bubble_delegate_;
-
- DISALLOW_COPY_AND_ASSIGN(BubbleWindowTargeterTest);
-};
-
-TEST_F(BubbleWindowTargeterTest, HitTest) {
- aura::Window* root = bubble_widget()->GetNativeWindow()->GetRootWindow();
- ui::EventTargeter* targeter =
- root->GetHost()->dispatcher()->GetDefaultEventTargeter();
- aura::Window* bubble_window = bubble_widget()->GetNativeWindow();
- gfx::Rect bubble_bounds = bubble_window->GetBoundsInRootWindow();
-
- {
- bubble_delegate()->set_margins(gfx::Insets());
- ui::MouseEvent move1(ui::ET_MOUSE_MOVED, bubble_bounds.origin(),
- bubble_bounds.origin(), ui::EventTimeForNow(),
- ui::EF_NONE, ui::EF_NONE);
- EXPECT_EQ(bubble_window, targeter->FindTargetForEvent(root, &move1));
- }
- {
- bubble_delegate()->set_margins(gfx::Insets(20));
- ui::MouseEvent move1(ui::ET_MOUSE_MOVED, bubble_bounds.origin(),
- bubble_bounds.origin(), ui::EventTimeForNow(),
- ui::EF_NONE, ui::EF_NONE);
- EXPECT_EQ(bubble_window, targeter->FindTargetForEvent(root, &move1));
- }
-
- bubble_window->SetEventTargeter(std::unique_ptr<ui::EventTargeter>(
- new BubbleWindowTargeter(bubble_delegate())));
- {
- bubble_delegate()->set_margins(gfx::Insets(20));
- ui::MouseEvent move1(ui::ET_MOUSE_MOVED, bubble_bounds.origin(),
- bubble_bounds.origin(), ui::EventTimeForNow(),
- ui::EF_NONE, ui::EF_NONE);
- EXPECT_NE(bubble_window, targeter->FindTargetForEvent(root, &move1));
- }
-}
-
-} // namespace views
diff --git a/chromium/ui/views/bubble/tray_bubble_view.cc b/chromium/ui/views/bubble/tray_bubble_view.cc
index 165a07eb45d..305aaebb2a5 100644
--- a/chromium/ui/views/bubble/tray_bubble_view.cc
+++ b/chromium/ui/views/bubble/tray_bubble_view.cc
@@ -16,8 +16,7 @@
#include "ui/aura/env.h"
#include "ui/aura/window.h"
#include "ui/compositor/layer.h"
-#include "ui/compositor/layer_delegate.h"
-#include "ui/compositor/paint_recorder.h"
+#include "ui/compositor/layer_owner.h"
#include "ui/events/event.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/color_palette.h"
@@ -26,8 +25,8 @@
#include "ui/gfx/path.h"
#include "ui/gfx/skia_util.h"
#include "ui/views/bubble/bubble_frame_view.h"
-#include "ui/views/bubble/bubble_window_targeter.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"
@@ -83,54 +82,6 @@ bool MouseMoveDetectorHost::Contains(const gfx::Point& screen_point,
return false;
}
-// This mask layer clips the bubble's content so that it does not overwrite the
-// rounded bubble corners.
-// TODO(miket): This does not work on Windows. Implement layer masking or
-// alternate solutions if the TrayBubbleView is needed there in the future.
-class TrayBubbleContentMask : public ui::LayerDelegate {
- public:
- explicit TrayBubbleContentMask(int corner_radius);
- ~TrayBubbleContentMask() override;
-
- ui::Layer* layer() { return &layer_; }
-
- // Overridden from LayerDelegate.
- void OnPaintLayer(const ui::PaintContext& context) override;
- void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override {}
- void OnDeviceScaleFactorChanged(float device_scale_factor) override;
-
- private:
- ui::Layer layer_;
- int corner_radius_;
-
- DISALLOW_COPY_AND_ASSIGN(TrayBubbleContentMask);
-};
-
-TrayBubbleContentMask::TrayBubbleContentMask(int corner_radius)
- : layer_(ui::LAYER_TEXTURED),
- corner_radius_(corner_radius) {
- layer_.set_delegate(this);
- layer_.SetFillsBoundsOpaquely(false);
-}
-
-TrayBubbleContentMask::~TrayBubbleContentMask() {
- layer_.set_delegate(NULL);
-}
-
-void TrayBubbleContentMask::OnPaintLayer(const ui::PaintContext& context) {
- ui::PaintRecorder recorder(context, layer()->size());
- cc::PaintFlags flags;
- flags.setAlpha(255);
- flags.setStyle(cc::PaintFlags::kFill_Style);
- gfx::Rect rect(layer()->bounds().size());
- recorder.canvas()->DrawRoundRect(rect, corner_radius_, flags);
-}
-
-void TrayBubbleContentMask::OnDeviceScaleFactorChanged(
- float device_scale_factor) {
- // Redrawing will take care of scale factor change.
-}
-
// 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 {
@@ -168,7 +119,6 @@ class BottomAlignedBoxLayout : public BoxLayout {
} // namespace internal
-using internal::TrayBubbleContentMask;
using internal::BottomAlignedBoxLayout;
TrayBubbleView::Delegate::~Delegate() {}
@@ -266,8 +216,9 @@ TrayBubbleView::TrayBubbleView(const InitParams& init_params)
set_margins(gfx::Insets());
SetPaintToLayer();
- bubble_content_mask_.reset(
- new TrayBubbleContentMask(bubble_border_->GetBorderCornerRadius()));
+ bubble_content_mask_ = views::Painter::CreatePaintedLayer(
+ views::Painter::CreateSolidRoundRectPainter(
+ SK_ColorBLACK, bubble_border_->GetBorderCornerRadius()));
layout_->SetDefaultFlex(1);
SetLayoutManager(layout_);
@@ -291,8 +242,6 @@ void TrayBubbleView::InitializeAndShowBubble() {
layer()->parent()->SetMaskLayer(bubble_content_mask_->layer());
GetWidget()->Show();
- GetWidget()->GetNativeWindow()->SetEventTargeter(
- std::unique_ptr<ui::EventTargeter>(new BubbleWindowTargeter(this)));
UpdateBubble();
++g_current_tray_bubble_showing_count_;
diff --git a/chromium/ui/views/bubble/tray_bubble_view.h b/chromium/ui/views/bubble/tray_bubble_view.h
index 51928ad75ce..aeff9a874a0 100644
--- a/chromium/ui/views/bubble/tray_bubble_view.h
+++ b/chromium/ui/views/bubble/tray_bubble_view.h
@@ -15,6 +15,10 @@
#include "ui/views/mouse_watcher.h"
#include "ui/views/views_export.h"
+namespace ui {
+class LayerOwner;
+}
+
namespace views {
class BoxLayout;
class View;
@@ -23,10 +27,6 @@ class Widget;
namespace views {
-namespace internal {
-class TrayBubbleContentMask;
-}
-
// 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
@@ -202,7 +202,7 @@ class VIEWS_EXPORT TrayBubbleView : public BubbleDialogDelegateView,
// 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<internal::TrayBubbleContentMask> bubble_content_mask_;
+ 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.
diff --git a/chromium/ui/views/button_drag_utils.cc b/chromium/ui/views/button_drag_utils.cc
index 064a133d269..c898239ead0 100644
--- a/chromium/ui/views/button_drag_utils.cc
+++ b/chromium/ui/views/button_drag_utils.cc
@@ -18,6 +18,7 @@
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/button/label_button_border.h"
#include "ui/views/drag_utils.h"
+#include "ui/views/paint_info.h"
#include "ui/views/widget/widget.h"
#include "url/gurl.h"
@@ -83,7 +84,11 @@ void SetDragImage(const GURL& url,
SkBitmap bitmap;
float raster_scale = ScaleFactorForDragFromWidget(&widget);
SkColor color = SK_ColorTRANSPARENT;
- button.Paint(ui::CanvasPainter(&bitmap, size, raster_scale, color).context());
+ button.Paint(views::PaintInfo::CreateRootPaintInfo(
+ ui::CanvasPainter(&bitmap, size, raster_scale, color,
+ widget.GetCompositor()->is_pixel_canvas())
+ .context(),
+ size));
gfx::ImageSkia image(gfx::ImageSkiaRep(bitmap, raster_scale));
data->provider().SetDragImage(image, press_point);
}
diff --git a/chromium/ui/views/cocoa/bridged_content_view.mm b/chromium/ui/views/cocoa/bridged_content_view.mm
index e300b7e245c..a06eed11e58 100644
--- a/chromium/ui/views/cocoa/bridged_content_view.mm
+++ b/chromium/ui/views/cocoa/bridged_content_view.mm
@@ -466,6 +466,12 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
if (!hostedView_)
return;
+ // Always propagate the shift modifier if present. Shift doesn't always alter
+ // the command selector, but should always be passed along. Control and Alt
+ // have different meanings on Mac, so they do not propagate automatically.
+ if ([keyDownEvent_ modifierFlags] & NSShiftKeyMask)
+ eventFlags |= ui::EF_SHIFT_DOWN;
+
// Generate a synthetic event with the keycode toolkit-views expects.
ui::KeyEvent event(ui::ET_KEY_PRESSED, keyCode, domCode, eventFlags);
@@ -622,6 +628,13 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
ui::MouseEvent event(theEvent);
+ // ui::EventLocationFromNative() assumes the event hit the contentView.
+ // Adjust if that's not the case (e.g. for reparented views).
+ if ([theEvent window] && [[self window] contentView] != self) {
+ NSPoint p = [self convertPoint:[theEvent locationInWindow] fromView:nil];
+ event.set_location(gfx::Point(p.x, NSHeight([self frame]) - p.y));
+ }
+
// Aura updates tooltips with the help of aura::Window::AddPreTargetHandler().
// Mac hooks in here.
[self updateTooltipIfRequiredAt:event.location()];
@@ -669,7 +682,7 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
// window containing it, since AppKit requires a titlebar to give frameless
// windows correct shadows and rounded corners.
NSWindow* window = [self window];
- if (window)
+ if (window && [window contentView] == self)
newSize = [window contentRectForFrameRect:[window frame]].size;
[super setFrameSize:newSize];
@@ -1449,8 +1462,9 @@ ui::TextEditCommand GetTextEditCommandForMenuAction(SEL action) {
// the Chrome renderer. Add code to extract underlines from |text| once our
// render text implementation supports thick underlines and discontinous
// underlines for consecutive characters. See http://crbug.com/612675.
- composition.underlines.push_back(ui::CompositionUnderline(
- 0, [text length], SK_ColorBLACK, false, SK_ColorTRANSPARENT));
+ composition.ime_text_spans.push_back(
+ ui::ImeTextSpan(ui::ImeTextSpan::Type::kComposition, 0, [text length],
+ SK_ColorBLACK, false, SK_ColorTRANSPARENT));
textInputClient_->SetCompositionText(composition);
hasUnhandledKeyDownEvent_ = NO;
}
diff --git a/chromium/ui/views/cocoa/bridged_native_widget.h b/chromium/ui/views/cocoa/bridged_native_widget.h
index ac529290b78..bf322525d2e 100644
--- a/chromium/ui/views/cocoa/bridged_native_widget.h
+++ b/chromium/ui/views/cocoa/bridged_native_widget.h
@@ -201,6 +201,13 @@ class VIEWS_EXPORT BridgedNativeWidget
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_; }
@@ -247,6 +254,9 @@ class VIEWS_EXPORT BridgedNativeWidget
// update its draggable region.
void SetDraggable(bool draggable);
+ // Called by |mouse_down_monitor_| to close a bubble.
+ void OnRightMouseDownWithBubble(NSEvent* event);
+
// Overridden from CocoaMouseCaptureDelegate:
void PostCapturedEvent(NSEvent* event) override;
void OnMouseCaptureLost() override;
@@ -328,6 +338,9 @@ class VIEWS_EXPORT BridgedNativeWidget
// the compositor arrives to avoid "blinking".
bool initial_visibility_suppressed_ = false;
+ // Right mouse down monitor for bubble widget.
+ id mouse_down_monitor_;
+
AssociatedViews associated_views_;
DISALLOW_COPY_AND_ASSIGN(BridgedNativeWidget);
diff --git a/chromium/ui/views/cocoa/bridged_native_widget.mm b/chromium/ui/views/cocoa/bridged_native_widget.mm
index b4a4de3018c..132ca1e4e20 100644
--- a/chromium/ui/views/cocoa/bridged_native_widget.mm
+++ b/chromium/ui/views/cocoa/bridged_native_widget.mm
@@ -21,6 +21,7 @@
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/input_method_factory.h"
#include "ui/base/layout.h"
+#include "ui/compositor/compositor_switches.h"
#include "ui/gfx/geometry/dip_util.h"
#import "ui/gfx/mac/coordinate_conversion.h"
#import "ui/gfx/mac/nswindow_frame_controls.h"
@@ -126,6 +127,20 @@ bool PositionWindowInScreenCoordinates(views::Widget* widget,
return widget && widget->is_top_level();
}
+// Returns true if the content_view is reparented.
+bool PositionWindowInNativeViewParent(NSView* content_view) {
+ return [[content_view window] contentView] != content_view;
+}
+
+// Return the offset of the parent native view from the window.
+gfx::Vector2d GetNativeViewParentOffset(NSView* content_view) {
+ NSWindow* window = [content_view window];
+ NSView* parent_view = [content_view superview];
+ NSPoint p = NSMakePoint(0, NSHeight([parent_view frame]));
+ p = [parent_view convertPoint:p toView:nil];
+ return gfx::Vector2d(p.x, NSHeight([window frame]) - p.y);
+}
+
// Return the content size for a minimum or maximum widget size.
gfx::Size GetClientSizeForWindowSize(NSWindow* window,
const gfx::Size& window_size) {
@@ -358,7 +373,8 @@ BridgedNativeWidget::BridgedNativeWidget(NativeWidgetMac* parent)
target_fullscreen_state_(false),
in_fullscreen_transition_(false),
window_visible_(false),
- wants_to_be_visible_(false) {
+ wants_to_be_visible_(false),
+ mouse_down_monitor_(nullptr) {
if (BridgedNativeWidget::ShouldUseDragEventMonitor())
SetupDragEventMonitor();
@@ -406,6 +422,17 @@ void BridgedNativeWidget::Init(base::scoped_nsobject<NSWindow> window,
name:NSControlTintDidChangeNotification
object:nil];
+ // Right-clicks outside a bubble should dismiss them, but that doesn't cause
+ // loss of focus on Mac, so add an event monitor to detect.
+ if (params.type == Widget::InitParams::TYPE_BUBBLE) {
+ mouse_down_monitor_ = [NSEvent
+ addLocalMonitorForEventsMatchingMask:NSRightMouseDownMask
+ handler:^NSEvent* (NSEvent* event) {
+ OnRightMouseDownWithBubble(event);
+ return event;
+ }];
+ }
+
// Validate the window's initial state, otherwise the bridge's initial
// tracking state will be incorrect.
DCHECK(![window_ isVisible]);
@@ -520,6 +547,9 @@ void BridgedNativeWidget::SetBounds(const gfx::Rect& new_bounds) {
if (parent_ && !PositionWindowInScreenCoordinates(widget, widget_type_))
actual_new_bounds.Offset(parent_->GetChildWindowOffset());
+ if (PositionWindowInNativeViewParent(bridged_view_))
+ actual_new_bounds.Offset(GetNativeViewParentOffset(bridged_view_));
+
[window_ setFrame:gfx::ScreenRectToNSRect(actual_new_bounds)
display:YES
animate:NO];
@@ -643,7 +673,7 @@ void BridgedNativeWidget::AcquireCapture() {
// will reset the mouse cursor to an arrow. Asking the window for an update
// here will restore what we want. However, it can sometimes cause the cursor
// to flicker, once, on the initial mouseDown.
- // TOOD(tapted): Make this unnecessary by only asking for global mouse capture
+ // TODO(tapted): Make this unnecessary by only asking for global mouse capture
// for the cases that need it (e.g. menus, but not drag and drop).
[window_ cursorUpdate:[NSApp currentEvent]];
}
@@ -725,6 +755,10 @@ void BridgedNativeWidget::OnWindowWillClose() {
parent_ = nullptr;
}
[[NSNotificationCenter defaultCenter] removeObserver:window_delegate_];
+ if (mouse_down_monitor_) {
+ [NSEvent removeMonitor:mouse_down_monitor_];
+ mouse_down_monitor_ = nullptr;
+ }
[window_ setDelegate:nil];
native_widget_mac_->OnWindowDestroyed();
// Note: |this| is deleted here.
@@ -1064,6 +1098,42 @@ void BridgedNativeWidget::ReorderChildViews() {
[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_) {
+ if (parent_)
+ parent_->RemoveChildWindow(this);
+
+ if (parent_bridge) {
+ parent_ = parent_bridge;
+ parent_bridge->child_windows_.push_back(this);
+ } else {
+ parent_ = new WidgetOwnerNSWindowAdapter(this, new_parent);
+ }
+
+ [[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];
+ }
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
// BridgedNativeWidget, internal::InputMethodDelegate:
@@ -1275,7 +1345,8 @@ void BridgedNativeWidget::CreateCompositor() {
compositor_.reset(new ui::Compositor(
context_factory_private->AllocateFrameSinkId(), context_factory,
context_factory_private, GetCompositorTaskRunner(),
- false /* enable_surface_synchronization */));
+ false /* enable_surface_synchronization */,
+ ui::IsPixelCanvasRecordingEnabled()));
compositor_->SetAcceleratedWidget(compositor_widget_->accelerated_widget());
compositor_widget_->SetNSView(this);
}
@@ -1435,4 +1506,26 @@ void BridgedNativeWidget::SetDraggable(bool draggable) {
[window_ setMovableByWindowBackground:YES];
}
+void BridgedNativeWidget::OnRightMouseDownWithBubble(NSEvent* event) {
+ NSWindow* target = [event window];
+ if ([target isSheet])
+ return;
+
+ // Do not close the bubble if the event happened on a window with a higher
+ // level. For example, the content of a browser action bubble opens a
+ // calendar picker window with NSPopUpMenuWindowLevel, and a date selection
+ // closes the picker window, but it should not close the bubble.
+ if ([target level] > [window_ level])
+ return;
+
+ // If the event is in |window_|'s hierarchy, do not close the bubble.
+ while (target) {
+ if (target == window_.get())
+ return;
+ target = [target parentWindow];
+ }
+
+ OnWindowKeyStatusChangedTo(false);
+}
+
} // namespace views
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 c7dfd87266b..a959ac0fa4d 100644
--- a/chromium/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm
+++ b/chromium/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm
@@ -9,6 +9,7 @@
#import "base/mac/mac_util.h"
#import "base/mac/sdk_forward_declarations.h"
#include "base/macros.h"
+#include "base/run_loop.h"
#include "ui/base/hit_test.h"
#import "ui/base/test/nswindow_fullscreen_notification_waiter.h"
#include "ui/base/test/ui_controls.h"
diff --git a/chromium/ui/views/cocoa/bridged_native_widget_unittest.mm b/chromium/ui/views/cocoa/bridged_native_widget_unittest.mm
index a500e998e22..733bd508122 100644
--- a/chromium/ui/views/cocoa/bridged_native_widget_unittest.mm
+++ b/chromium/ui/views/cocoa/bridged_native_widget_unittest.mm
@@ -40,6 +40,7 @@ using base::ASCIIToUTF16;
using base::SysNSStringToUTF8;
using base::SysNSStringToUTF16;
using base::SysUTF8ToNSString;
+using base::SysUTF16ToNSString;
#define EXPECT_EQ_RANGE(a, b) \
EXPECT_EQ(a.location, b.location); \
diff --git a/chromium/ui/views/cocoa/native_widget_mac_nswindow.mm b/chromium/ui/views/cocoa/native_widget_mac_nswindow.mm
index af19ce7c26e..a61d582b79c 100644
--- a/chromium/ui/views/cocoa/native_widget_mac_nswindow.mm
+++ b/chromium/ui/views/cocoa/native_widget_mac_nswindow.mm
@@ -21,6 +21,7 @@
- (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.
@@ -74,6 +75,11 @@
return menuController && menuController->owner() == [self viewsWidget];
}
+- (id)rootAccessibilityObject {
+ views::Widget* widget = [self viewsWidget];
+ return widget ? widget->GetRootView()->GetNativeViewAccessible() : nil;
+}
+
// NSWindow overrides.
- (BOOL)_isTitleHidden {
@@ -222,4 +228,39 @@
forHandler:commandHandler_];
}
+// NSWindow overrides (NSAccessibility informal protocol implementation).
+
+- (id)accessibilityFocusedUIElement {
+ // The SDK documents this as "The deepest descendant of the accessibility
+ // hierarchy that has the focus" and says "if a child element does not have
+ // the focus, either return self or, if available, invoke the superclass's
+ // implementation."
+ // The behavior of NSWindow is usually to return null, except when the window
+ // is first shown, when it returns self. But in the second case, we can
+ // provide richer a11y information by reporting the views::RootView instead.
+ // 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)
+ return superFocus;
+
+ return widget->GetRootView()->GetNativeViewAccessible();
+}
+
+- (id)accessibilityAttributeValue:(NSString*)attribute {
+ // Check when NSWindow is asked for its title to provide the title given by
+ // the views::RootView (and WidgetDelegate::GetAccessibleWindowTitle()). For
+ // all other attributes, use what NSWindow provides by default since diverging
+ // from NSWindow's behavior can easily break VoiceOver integration.
+ if (![attribute isEqualToString:NSAccessibilityTitleAttribute])
+ return [super accessibilityAttributeValue:attribute];
+
+ id viewsValue =
+ [[self rootAccessibilityObject] accessibilityAttributeValue:attribute];
+ return viewsValue ? viewsValue
+ : [super accessibilityAttributeValue:attribute];
+}
+
@end
diff --git a/chromium/ui/views/cocoa/views_nswindow_delegate.mm b/chromium/ui/views/cocoa/views_nswindow_delegate.mm
index d0d50a0eada..96acf216de7 100644
--- a/chromium/ui/views/cocoa/views_nswindow_delegate.mm
+++ b/chromium/ui/views/cocoa/views_nswindow_delegate.mm
@@ -92,6 +92,12 @@
parent_->OnWindowKeyStatusChangedTo(false);
}
+- (BOOL)windowShouldClose:(id)sender {
+ views::NonClientView* nonClientView =
+ [self nativeWidgetMac]->GetWidget()->non_client_view();
+ return !nonClientView || nonClientView->CanClose();
+}
+
- (void)windowWillClose:(NSNotification*)notification {
// Retain |self|. |parent_| should be cleared. OnWindowWillClose() may delete
// |parent_|, but it may also dealloc |self| before returning. However, the
diff --git a/chromium/ui/views/controls/button/button.cc b/chromium/ui/views/controls/button/button.cc
index 14aa0bb4d8b..0291ab49358 100644
--- a/chromium/ui/views/controls/button/button.cc
+++ b/chromium/ui/views/controls/button/button.cc
@@ -7,12 +7,71 @@
#include "base/strings/utf_string_conversions.h"
#include "ui/accessibility/ax_node_data.h"
+#include "ui/accessibility/ax_node_data.h"
+#include "ui/base/class_property.h"
+#include "ui/events/event.h"
+#include "ui/events/event_utils.h"
+#include "ui/events/keycodes/keyboard_codes.h"
+#include "ui/gfx/animation/throb_animation.h"
+#include "ui/gfx/color_palette.h"
+#include "ui/native_theme/native_theme.h"
+#include "ui/views/animation/ink_drop_highlight.h"
+#include "ui/views/animation/ink_drop_impl.h"
+#include "ui/views/controls/button/blue_button.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/controls/button/menu_button.h"
+#include "ui/views/controls/button/radio_button.h"
+#include "ui/views/controls/button/toggle_button.h"
+#include "ui/views/painter.h"
+#include "ui/views/style/platform_style.h"
+#include "ui/views/widget/widget.h"
+
+#if defined(USE_AURA)
+#include "ui/aura/client/capture_client.h"
+#include "ui/aura/window.h"
+#endif
+
namespace views {
+namespace {
+
+DEFINE_LOCAL_UI_CLASS_PROPERTY_KEY(bool, kIsButtonProperty, false);
+
+// How long the hover animation takes if uninterrupted.
+const int kHoverFadeDurationMs = 150;
+
+Button::KeyClickAction GetKeyClickActionForEvent(const ui::KeyEvent& event) {
+ if (event.key_code() == ui::VKEY_SPACE)
+ return PlatformStyle::kKeyClickActionOnSpace;
+ if (event.key_code() == ui::VKEY_RETURN &&
+ PlatformStyle::kReturnClicksFocusedControl)
+ return Button::CLICK_ON_KEY_PRESS;
+ return Button::CLICK_NONE;
+}
+
+} // namespace
+
////////////////////////////////////////////////////////////////////////////////
// Button, static public:
// static
+const char Button::kViewClassName[] = "Button";
+
+// static
+const Button* Button::AsButton(const views::View* view) {
+ return AsButton(const_cast<View*>(view));
+}
+
+// static
+Button* Button::AsButton(views::View* view) {
+ if (view && view->GetProperty(kIsButtonProperty))
+ return static_cast<Button*>(view);
+ return nullptr;
+}
+
+// static
Button::ButtonState Button::GetButtonStateFrom(ui::NativeTheme::State state) {
switch (state) {
case ui::NativeTheme::kDisabled: return Button::STATE_DISABLED;
@@ -27,8 +86,7 @@ Button::ButtonState Button::GetButtonStateFrom(ui::NativeTheme::State state) {
////////////////////////////////////////////////////////////////////////////////
// Button, public:
-Button::~Button() {
-}
+Button::~Button() {}
void Button::SetFocusForPlatform() {
#if defined(OS_MACOSX)
@@ -49,10 +107,253 @@ void Button::SetTooltipText(const base::string16& tooltip_text) {
void Button::SetAccessibleName(const base::string16& name) {
accessible_name_ = name;
}
+void Button::SetState(ButtonState state) {
+ if (state == state_)
+ return;
+
+ if (animate_on_state_change_ &&
+ (!is_throbbing_ || !hover_animation_.is_animating())) {
+ is_throbbing_ = false;
+ if ((state_ == STATE_HOVERED) && (state == STATE_NORMAL)) {
+ // For HOVERED -> NORMAL, animate from hovered (1) to not hovered (0).
+ hover_animation_.Hide();
+ } else if (state != STATE_HOVERED) {
+ // For HOVERED -> PRESSED/DISABLED, or any transition not involving
+ // HOVERED at all, simply set the state to not hovered (0).
+ hover_animation_.Reset();
+ } else if (state_ == STATE_NORMAL) {
+ // For NORMAL -> HOVERED, animate from not hovered (0) to hovered (1).
+ hover_animation_.Show();
+ } else {
+ // For PRESSED/DISABLED -> HOVERED, simply set the state to hovered (1).
+ hover_animation_.Reset(1);
+ }
+ }
+
+ ButtonState old_state = state_;
+ state_ = state;
+ StateChanged(old_state);
+ SchedulePaint();
+}
+
+void Button::StartThrobbing(int cycles_til_stop) {
+ if (!animate_on_state_change_)
+ return;
+ is_throbbing_ = true;
+ hover_animation_.StartThrobbing(cycles_til_stop);
+}
+
+void Button::StopThrobbing() {
+ if (hover_animation_.is_animating()) {
+ hover_animation_.Stop();
+ SchedulePaint();
+ }
+}
+
+void Button::SetAnimationDuration(int duration) {
+ hover_animation_.SetSlideDuration(duration);
+}
+
+void Button::SetHotTracked(bool is_hot_tracked) {
+ if (state_ != STATE_DISABLED)
+ SetState(is_hot_tracked ? STATE_HOVERED : STATE_NORMAL);
+
+ if (is_hot_tracked)
+ NotifyAccessibilityEvent(ui::AX_EVENT_HOVER, true);
+}
+
+bool Button::IsHotTracked() const {
+ return state_ == STATE_HOVERED;
+}
+
+void Button::SetFocusPainter(std::unique_ptr<Painter> focus_painter) {
+ focus_painter_ = std::move(focus_painter);
+}
////////////////////////////////////////////////////////////////////////////////
// Button, View overrides:
+void Button::OnEnabledChanged() {
+ if (enabled() ? (state_ != STATE_DISABLED) : (state_ == STATE_DISABLED))
+ return;
+
+ if (enabled()) {
+ bool should_enter_hover_state = ShouldEnterHoveredState();
+ SetState(should_enter_hover_state ? STATE_HOVERED : STATE_NORMAL);
+ GetInkDrop()->SetHovered(should_enter_hover_state);
+ } else {
+ SetState(STATE_DISABLED);
+ GetInkDrop()->SetHovered(false);
+ }
+}
+
+const char* Button::GetClassName() const {
+ return kViewClassName;
+}
+
+bool Button::OnMousePressed(const ui::MouseEvent& event) {
+ if (state_ == STATE_DISABLED)
+ return true;
+ if (state_ != STATE_PRESSED && ShouldEnterPushedState(event) &&
+ HitTestPoint(event.location())) {
+ SetState(STATE_PRESSED);
+ AnimateInkDrop(views::InkDropState::ACTION_PENDING, &event);
+ }
+ if (request_focus_on_press_)
+ RequestFocus();
+ if (IsTriggerableEvent(event) && notify_action_ == NOTIFY_ON_PRESS) {
+ NotifyClick(event);
+ // NOTE: We may be deleted at this point (by the listener's notification
+ // handler).
+ }
+ return true;
+}
+
+bool Button::OnMouseDragged(const ui::MouseEvent& event) {
+ if (state_ != STATE_DISABLED) {
+ const bool should_enter_pushed = ShouldEnterPushedState(event);
+ const bool should_show_pending =
+ should_enter_pushed && notify_action_ == NOTIFY_ON_RELEASE && !InDrag();
+ if (HitTestPoint(event.location())) {
+ SetState(should_enter_pushed ? STATE_PRESSED : STATE_HOVERED);
+ if (should_show_pending && GetInkDrop()->GetTargetInkDropState() ==
+ views::InkDropState::HIDDEN) {
+ AnimateInkDrop(views::InkDropState::ACTION_PENDING, &event);
+ }
+ } else {
+ SetState(STATE_NORMAL);
+ if (should_show_pending && GetInkDrop()->GetTargetInkDropState() ==
+ views::InkDropState::ACTION_PENDING) {
+ AnimateInkDrop(views::InkDropState::HIDDEN, &event);
+ }
+ }
+ }
+ return true;
+}
+
+void Button::OnMouseReleased(const ui::MouseEvent& event) {
+ if (state_ != STATE_DISABLED) {
+ if (!HitTestPoint(event.location())) {
+ SetState(STATE_NORMAL);
+ } else {
+ SetState(STATE_HOVERED);
+ if (IsTriggerableEvent(event) && notify_action_ == NOTIFY_ON_RELEASE) {
+ NotifyClick(event);
+ // NOTE: We may be deleted at this point (by the listener's notification
+ // handler).
+ return;
+ }
+ }
+ }
+ if (notify_action_ == NOTIFY_ON_RELEASE)
+ OnClickCanceled(event);
+}
+
+void Button::OnMouseCaptureLost() {
+ // Starting a drag results in a MouseCaptureLost. Reset button state.
+ // TODO(varkha): Reset the state even while in drag. The same logic may
+ // applies everywhere so gather any feedback and update.
+ if (state_ != STATE_DISABLED)
+ SetState(STATE_NORMAL);
+ AnimateInkDrop(views::InkDropState::HIDDEN, nullptr /* event */);
+ GetInkDrop()->SetHovered(false);
+ InkDropHostView::OnMouseCaptureLost();
+}
+
+void Button::OnMouseEntered(const ui::MouseEvent& event) {
+ if (state_ != STATE_DISABLED)
+ SetState(STATE_HOVERED);
+}
+
+void Button::OnMouseExited(const ui::MouseEvent& event) {
+ // Starting a drag results in a MouseExited, we need to ignore it.
+ if (state_ != STATE_DISABLED && !InDrag())
+ SetState(STATE_NORMAL);
+}
+
+void Button::OnMouseMoved(const ui::MouseEvent& event) {
+ if (state_ != STATE_DISABLED)
+ SetState(HitTestPoint(event.location()) ? STATE_HOVERED : STATE_NORMAL);
+}
+
+bool Button::OnKeyPressed(const ui::KeyEvent& event) {
+ if (state_ == STATE_DISABLED)
+ return false;
+
+ switch (GetKeyClickActionForEvent(event)) {
+ case KeyClickAction::CLICK_ON_KEY_RELEASE:
+ SetState(STATE_PRESSED);
+ if (GetInkDrop()->GetTargetInkDropState() !=
+ InkDropState::ACTION_PENDING) {
+ AnimateInkDrop(InkDropState::ACTION_PENDING, nullptr /* event */);
+ }
+ return true;
+ case KeyClickAction::CLICK_ON_KEY_PRESS:
+ SetState(STATE_NORMAL);
+ NotifyClick(event);
+ return true;
+ case KeyClickAction::CLICK_NONE:
+ return false;
+ }
+
+ NOTREACHED();
+ return false;
+}
+
+bool Button::OnKeyReleased(const ui::KeyEvent& event) {
+ const bool click_button =
+ state_ == STATE_PRESSED &&
+ GetKeyClickActionForEvent(event) == KeyClickAction::CLICK_ON_KEY_RELEASE;
+ if (!click_button)
+ return false;
+
+ SetState(STATE_NORMAL);
+ NotifyClick(event);
+ return true;
+}
+
+void Button::OnGestureEvent(ui::GestureEvent* event) {
+ if (state_ == STATE_DISABLED) {
+ InkDropHostView::OnGestureEvent(event);
+ return;
+ }
+
+ if (event->type() == ui::ET_GESTURE_TAP && IsTriggerableEvent(*event)) {
+ // Set the button state to hot and start the animation fully faded in. The
+ // GESTURE_END event issued immediately after will set the state to
+ // STATE_NORMAL beginning the fade out animation. See
+ // http://crbug.com/131184.
+ SetState(STATE_HOVERED);
+ hover_animation_.Reset(1.0);
+ NotifyClick(*event);
+ event->StopPropagation();
+ } else if (event->type() == ui::ET_GESTURE_TAP_DOWN &&
+ ShouldEnterPushedState(*event)) {
+ SetState(STATE_PRESSED);
+ if (request_focus_on_press_)
+ RequestFocus();
+ event->StopPropagation();
+ } else if (event->type() == ui::ET_GESTURE_TAP_CANCEL ||
+ event->type() == ui::ET_GESTURE_END) {
+ SetState(STATE_NORMAL);
+ }
+ if (!event->handled())
+ InkDropHostView::OnGestureEvent(event);
+}
+
+bool Button::AcceleratorPressed(const ui::Accelerator& accelerator) {
+ SetState(STATE_NORMAL);
+ NotifyClick(accelerator.ToKeyEvent());
+ return true;
+}
+
+bool Button::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) {
+ // If this button is focused and the user presses space or enter, don't let
+ // that be treated as an accelerator if there is a key click action
+ // corresponding to it.
+ return GetKeyClickActionForEvent(event) != KeyClickAction::CLICK_NONE;
+}
+
bool Button::GetTooltipText(const gfx::Point& p,
base::string16* tooltip) const {
if (tooltip_text_.empty())
@@ -62,6 +363,36 @@ bool Button::GetTooltipText(const gfx::Point& p,
return true;
}
+void Button::ShowContextMenu(const gfx::Point& p,
+ ui::MenuSourceType source_type) {
+ if (!context_menu_controller())
+ return;
+
+ // We're about to show the context menu. Showing the context menu likely means
+ // we won't get a mouse exited and reset state. Reset it now to be sure.
+ if (state_ != STATE_DISABLED)
+ SetState(STATE_NORMAL);
+ if (hide_ink_drop_when_showing_context_menu_) {
+ GetInkDrop()->SetHovered(false);
+ AnimateInkDrop(InkDropState::HIDDEN, nullptr /* event */);
+ }
+ InkDropHostView::ShowContextMenu(p, source_type);
+}
+
+void Button::OnDragDone() {
+ // Only reset the state to normal if the button isn't currently disabled
+ // (since disabled buttons may still be able to be dragged).
+ if (state_ != STATE_DISABLED)
+ SetState(STATE_NORMAL);
+ AnimateInkDrop(InkDropState::HIDDEN, nullptr /* event */);
+}
+
+void Button::OnPaint(gfx::Canvas* canvas) {
+ InkDropHostView::OnPaint(canvas);
+ PaintButtonContents(canvas);
+ Painter::PaintFocusPainter(this, canvas, focus_painter_.get());
+}
+
void Button::GetAccessibleNodeData(ui::AXNodeData* node_data) {
node_data->role = ui::AX_ROLE_BUTTON;
node_data->SetName(accessible_name_);
@@ -69,24 +400,154 @@ void Button::GetAccessibleNodeData(ui::AXNodeData* node_data) {
node_data->AddIntAttribute(ui::AX_ATTR_RESTRICTION,
ui::AX_RESTRICTION_DISABLED);
}
+
+ switch (state_) {
+ case STATE_HOVERED:
+ node_data->AddState(ui::AX_STATE_HOVERED);
+ break;
+ case STATE_PRESSED:
+ node_data->AddIntAttribute(ui::AX_ATTR_CHECKED_STATE,
+ ui::AX_CHECKED_STATE_TRUE);
+ break;
+ case STATE_DISABLED:
+ node_data->AddIntAttribute(ui::AX_ATTR_RESTRICTION,
+ ui::AX_RESTRICTION_DISABLED);
+ break;
+ case STATE_NORMAL:
+ case STATE_COUNT:
+ // No additional accessibility node_data set for this button node_data.
+ break;
+ }
+ if (enabled()) {
+ node_data->AddIntAttribute(ui::AX_ATTR_DEFAULT_ACTION_VERB,
+ ui::AX_DEFAULT_ACTION_VERB_PRESS);
+ }
+}
+
+void Button::VisibilityChanged(View* starting_from, bool visible) {
+ InkDropHostView::VisibilityChanged(starting_from, visible);
+ if (state_ == STATE_DISABLED)
+ return;
+ SetState(visible && ShouldEnterHoveredState() ? STATE_HOVERED : STATE_NORMAL);
+}
+
+void Button::ViewHierarchyChanged(const ViewHierarchyChangedDetails& details) {
+ if (!details.is_add && state_ != STATE_DISABLED)
+ SetState(STATE_NORMAL);
+}
+
+void Button::OnFocus() {
+ InkDropHostView::OnFocus();
+ if (focus_painter_)
+ SchedulePaint();
+}
+
+void Button::OnBlur() {
+ InkDropHostView::OnBlur();
+ if (IsHotTracked() || state_ == STATE_PRESSED) {
+ SetState(STATE_NORMAL);
+ if (GetInkDrop()->GetTargetInkDropState() != views::InkDropState::HIDDEN)
+ AnimateInkDrop(views::InkDropState::HIDDEN, nullptr /* event */);
+ // TODO(bruthig) : Fix Buttons to work well when multiple input
+ // methods are interacting with a button. e.g. By animating to HIDDEN here
+ // it is possible for a Mouse Release to trigger an action however there
+ // would be no visual cue to the user that this will occur.
+ }
+ if (focus_painter_)
+ SchedulePaint();
+}
+
+std::unique_ptr<InkDrop> Button::CreateInkDrop() {
+ std::unique_ptr<views::InkDropImpl> ink_drop = CreateDefaultInkDropImpl();
+ ink_drop->SetShowHighlightOnFocus(true);
+ return std::move(ink_drop);
+}
+
+SkColor Button::GetInkDropBaseColor() const {
+ return ink_drop_base_color_;
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// Button, gfx::AnimationDelegate implementation:
+
+void Button::AnimationProgressed(const gfx::Animation* animation) {
+ SchedulePaint();
}
////////////////////////////////////////////////////////////////////////////////
// Button, protected:
Button::Button(ButtonListener* listener)
- : listener_(listener),
- tag_(-1) {
+ : listener_(listener), ink_drop_base_color_(gfx::kPlaceholderColor) {
SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY);
+ SetProperty(kIsButtonProperty, true);
+ hover_animation_.SetSlideDuration(kHoverFadeDurationMs);
}
void Button::NotifyClick(const ui::Event& event) {
+ if (has_ink_drop_action_on_click_) {
+ AnimateInkDrop(InkDropState::ACTION_TRIGGERED,
+ ui::LocatedEvent::FromIfValid(&event));
+ }
// We can be called when there is no listener, in cases like double clicks on
// menu buttons etc.
if (listener_)
listener_->ButtonPressed(this, event);
}
-void Button::OnClickCanceled(const ui::Event& event) {}
+void Button::OnClickCanceled(const ui::Event& event) {
+ if (ShouldUpdateInkDropOnClickCanceled()) {
+ if (GetInkDrop()->GetTargetInkDropState() ==
+ views::InkDropState::ACTION_PENDING ||
+ GetInkDrop()->GetTargetInkDropState() ==
+ views::InkDropState::ALTERNATE_ACTION_PENDING) {
+ AnimateInkDrop(views::InkDropState::HIDDEN,
+ ui::LocatedEvent::FromIfValid(&event));
+ }
+ }
+}
+
+void Button::StateChanged(ButtonState old_state) {}
+
+bool Button::IsTriggerableEvent(const ui::Event& event) {
+ return event.type() == ui::ET_GESTURE_TAP_DOWN ||
+ event.type() == ui::ET_GESTURE_TAP ||
+ (event.IsMouseEvent() &&
+ (triggerable_event_flags_ & event.flags()) != 0);
+}
+
+bool Button::ShouldUpdateInkDropOnClickCanceled() const {
+ return true;
+}
+
+bool Button::ShouldEnterPushedState(const ui::Event& event) {
+ return IsTriggerableEvent(event);
+}
+
+void Button::PaintButtonContents(gfx::Canvas* canvas) {}
+
+bool Button::ShouldEnterHoveredState() {
+ if (!visible())
+ return false;
+
+ bool check_mouse_position = true;
+#if defined(USE_AURA)
+ // If another window has capture, we shouldn't check the current mouse
+ // position because the button won't receive any mouse events - so if the
+ // mouse was hovered, the button would be stuck in a hovered state (since it
+ // would never receive OnMouseExited).
+ const Widget* widget = GetWidget();
+ if (widget && widget->GetNativeWindow()) {
+ aura::Window* root_window = widget->GetNativeWindow()->GetRootWindow();
+ aura::client::CaptureClient* capture_client =
+ aura::client::GetCaptureClient(root_window);
+ aura::Window* capture_window =
+ capture_client ? capture_client->GetGlobalCaptureWindow() : nullptr;
+ check_mouse_position = !capture_window || capture_window == root_window;
+ }
+#endif
+
+ return check_mouse_position && IsMouseHovered();
+}
} // namespace views
diff --git a/chromium/ui/views/controls/button/button.h b/chromium/ui/views/controls/button/button.h
index 62aecd7734e..26c852d8717 100644
--- a/chromium/ui/views/controls/button/button.h
+++ b/chromium/ui/views/controls/button/button.h
@@ -6,8 +6,14 @@
#define UI_VIEWS_CONTROLS_BUTTON_BUTTON_H_
#include "base/macros.h"
+#include "build/build_config.h"
+#include "ui/events/event_constants.h"
+#include "ui/gfx/animation/animation_delegate.h"
+#include "ui/gfx/animation/throb_animation.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/animation/ink_drop_host_view.h"
+#include "ui/views/animation/ink_drop_state.h"
+#include "ui/views/painter.h"
namespace views {
@@ -24,9 +30,11 @@ class VIEWS_EXPORT ButtonListener {
virtual ~ButtonListener() {}
};
-// A View representing a button. Depending on the specific type, the button
-// could be implemented by a native control or custom rendered.
-class VIEWS_EXPORT Button : public InkDropHostView {
+// A View representing a button. A Button is not focusable by default and will
+// not be part of the focus chain, unless in accessibility mode (see
+// SetFocusForPlatform()).
+class VIEWS_EXPORT Button : public InkDropHostView,
+ public gfx::AnimationDelegate {
public:
~Button() override;
@@ -47,6 +55,26 @@ class VIEWS_EXPORT Button : public InkDropHostView {
STYLE_COUNT,
};
+ // An enum describing the events on which a button should notify its listener.
+ enum NotifyAction {
+ NOTIFY_ON_PRESS,
+ NOTIFY_ON_RELEASE,
+ };
+
+ // An enum describing the events on which a button should be clicked for a
+ // given key event.
+ enum KeyClickAction {
+ CLICK_ON_KEY_PRESS,
+ CLICK_ON_KEY_RELEASE,
+ CLICK_NONE,
+ };
+
+ // The menu button's class name.
+ static const char kViewClassName[];
+
+ static const Button* AsButton(const View* view);
+ static Button* AsButton(View* view);
+
static ButtonState GetButtonStateFrom(ui::NativeTheme::State state);
// Make the button focusable as per the platform.
@@ -59,13 +87,106 @@ class VIEWS_EXPORT Button : public InkDropHostView {
void SetAccessibleName(const base::string16& name);
+ // Get/sets the current display state of the button.
+ ButtonState state() const { return state_; }
+ // Clients passing in STATE_DISABLED should consider calling
+ // SetEnabled(false) instead because the enabled flag can affect other things
+ // like event dispatching, focus traversals, etc. Calling SetEnabled(false)
+ // will also set the state of |this| to STATE_DISABLED.
+ void SetState(ButtonState state);
+
+ // Starts throbbing. See HoverAnimation for a description of cycles_til_stop.
+ // This method does nothing if |animate_on_state_change_| is false.
+ void StartThrobbing(int cycles_til_stop);
+
+ // Stops throbbing immediately.
+ void StopThrobbing();
+
+ // Set how long the hover animation will last for.
+ void SetAnimationDuration(int duration);
+
+ void set_triggerable_event_flags(int triggerable_event_flags) {
+ triggerable_event_flags_ = triggerable_event_flags;
+ }
+ int triggerable_event_flags() const { return triggerable_event_flags_; }
+
+ // Sets whether |RequestFocus| should be invoked on a mouse press. The default
+ // is false.
+ void set_request_focus_on_press(bool value) {
+// On Mac, buttons should not request focus on a mouse press. Hence keep the
+// default value i.e. false.
+#if !defined(OS_MACOSX)
+ request_focus_on_press_ = value;
+#endif
+ }
+
+ bool request_focus_on_press() const { return request_focus_on_press_; }
+
+ // See description above field.
+ void set_animate_on_state_change(bool value) {
+ animate_on_state_change_ = value;
+ }
+
+ // Sets the event on which the button should notify its listener.
+ void set_notify_action(NotifyAction notify_action) {
+ notify_action_ = notify_action;
+ }
+
+ void set_hide_ink_drop_when_showing_context_menu(
+ bool hide_ink_drop_when_showing_context_menu) {
+ hide_ink_drop_when_showing_context_menu_ =
+ hide_ink_drop_when_showing_context_menu;
+ }
+
+ void set_ink_drop_base_color(SkColor color) { ink_drop_base_color_ = color; }
+ void set_has_ink_drop_action_on_click(bool has_ink_drop_action_on_click) {
+ has_ink_drop_action_on_click_ = has_ink_drop_action_on_click;
+ }
+
+ void SetHotTracked(bool is_hot_tracked);
+ bool IsHotTracked() const;
+
+ void SetFocusPainter(std::unique_ptr<Painter> focus_painter);
+
// Overridden from View:
+ void OnEnabledChanged() override;
+ const char* GetClassName() const override;
+ bool OnMousePressed(const ui::MouseEvent& event) override;
+ bool OnMouseDragged(const ui::MouseEvent& event) override;
+ void OnMouseReleased(const ui::MouseEvent& event) override;
+ void OnMouseCaptureLost() override;
+ void OnMouseEntered(const ui::MouseEvent& event) override;
+ void OnMouseExited(const ui::MouseEvent& event) override;
+ void OnMouseMoved(const ui::MouseEvent& event) override;
+ bool OnKeyPressed(const ui::KeyEvent& event) override;
+ bool OnKeyReleased(const ui::KeyEvent& event) override;
+ void OnGestureEvent(ui::GestureEvent* event) override;
+ bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
+ bool SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) override;
bool GetTooltipText(const gfx::Point& p,
base::string16* tooltip) const override;
+ void ShowContextMenu(const gfx::Point& p,
+ ui::MenuSourceType source_type) override;
+ void OnDragDone() override;
+ // Instead of overriding this, subclasses that want custom painting should use
+ // PaintButtonContents.
+ void OnPaint(gfx::Canvas* canvas) final;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
+ void VisibilityChanged(View* starting_from, bool is_visible) override;
+ void ViewHierarchyChanged(
+ const ViewHierarchyChangedDetails& details) override;
+ void OnFocus() override;
+ void OnBlur() override;
+
+ // Overridden from InkDropHostView:
+ std::unique_ptr<InkDrop> CreateInkDrop() override;
+ SkColor GetInkDropBaseColor() const override;
+
+ // Overridden from gfx::AnimationDelegate:
+ void AnimationProgressed(const gfx::Animation* animation) override;
protected:
- // Construct the Button with a Listener. The listener can be NULL. This can be
+ // Construct the Button with a Listener. The listener can be null. This can be
// true of buttons that don't have a listener - e.g. menubuttons where there's
// no default action and checkboxes.
explicit Button(ButtonListener* listener);
@@ -78,10 +199,48 @@ class VIEWS_EXPORT Button : public InkDropHostView {
// events.
virtual void OnClickCanceled(const ui::Event& event);
+ // Invoked from SetState() when SetState() is passed a value that differs from
+ // the current node_data. Button's implementation of StateChanged() does
+ // nothing; this method is provided for subclasses that wish to do something
+ // on state changes.
+ virtual void StateChanged(ButtonState old_state);
+
+ // Returns true if the event is one that can trigger notifying the listener.
+ // This implementation returns true if the left mouse button is down.
+ virtual bool IsTriggerableEvent(const ui::Event& event);
+
+ // Returns true if the ink drop should be updated by Button when
+ // OnClickCanceled() is called. This method is provided for subclasses.
+ // If the method is overriden and returns false, the subclass is responsible
+ // will be responsible for updating the ink drop.
+ virtual bool ShouldUpdateInkDropOnClickCanceled() const;
+
+ // Returns true if the button should become pressed when the user
+ // holds the mouse down over the button. For this implementation,
+ // we simply return IsTriggerableEvent(event).
+ virtual bool ShouldEnterPushedState(const ui::Event& event);
+
+ // Override to paint custom button contents. Any background or border set on
+ // the view will be painted before this is called and |focus_painter_| will be
+ // painted afterwards.
+ virtual void PaintButtonContents(gfx::Canvas* canvas);
+
+ // Returns true if the button should enter hovered state; that is, if the
+ // mouse is over the button, and no other window has capture (which would
+ // prevent the button from receiving MouseExited events and updating its
+ // node_data). This does not take into account enabled node_data.
+ bool ShouldEnterHoveredState();
+
+ const gfx::ThrobAnimation& hover_animation() const {
+ return hover_animation_;
+ }
+
// The button's listener. Notified when clicked.
ButtonListener* listener_;
private:
+ FRIEND_TEST_ALL_PREFIXES(BlueButtonTest, Border);
+
// The text shown in a tooltip.
base::string16 tooltip_text_;
@@ -90,7 +249,39 @@ class VIEWS_EXPORT Button : public InkDropHostView {
// The id tag associated with this button. Used to disambiguate buttons in
// the ButtonListener implementation.
- int tag_;
+ int tag_ = -1;
+
+ ButtonState state_ = STATE_NORMAL;
+
+ gfx::ThrobAnimation hover_animation_{this};
+
+ // Should we animate when the state changes?
+ bool animate_on_state_change_ = false;
+
+ // Is the hover animation running because StartThrob was invoked?
+ bool is_throbbing_ = false;
+
+ // Mouse event flags which can trigger button actions.
+ int triggerable_event_flags_ = ui::EF_LEFT_MOUSE_BUTTON;
+
+ // See description above setter.
+ bool request_focus_on_press_ = false;
+
+ // The event on which the button should notify its listener.
+ NotifyAction notify_action_ = NOTIFY_ON_RELEASE;
+
+ // True when a button click should trigger an animation action on
+ // ink_drop_delegate().
+ bool has_ink_drop_action_on_click_ = false;
+
+ // When true, the ink drop ripple and hover will be hidden prior to showing
+ // the context menu.
+ bool hide_ink_drop_when_showing_context_menu_ = true;
+
+ // The color of the ripple and hover.
+ SkColor ink_drop_base_color_;
+
+ std::unique_ptr<Painter> focus_painter_;
DISALLOW_COPY_AND_ASSIGN(Button);
};
diff --git a/chromium/ui/views/controls/button/custom_button_unittest.cc b/chromium/ui/views/controls/button/button_unittest.cc
index b9406604a13..ec700c8a9d0 100644
--- a/chromium/ui/views/controls/button/custom_button_unittest.cc
+++ b/chromium/ui/views/controls/button/button_unittest.cc
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/views/controls/button/custom_button.h"
+#include "ui/views/controls/button/button.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
@@ -58,31 +58,28 @@ class TestContextMenuController : public ContextMenuController {
DISALLOW_COPY_AND_ASSIGN(TestContextMenuController);
};
-class TestCustomButton : public CustomButton, public ButtonListener {
+class TestButton : public Button, public ButtonListener {
public:
- explicit TestCustomButton(bool has_ink_drop_action_on_click)
- : CustomButton(this) {
+ explicit TestButton(bool has_ink_drop_action_on_click) : Button(this) {
set_has_ink_drop_action_on_click(has_ink_drop_action_on_click);
}
- ~TestCustomButton() override {}
+ ~TestButton() override {}
void ButtonPressed(Button* sender, const ui::Event& event) override {
pressed_ = true;
}
- void OnClickCanceled(const ui::Event& event) override {
- canceled_ = true;
- }
+ void OnClickCanceled(const ui::Event& event) override { canceled_ = true; }
// InkDropHostView:
void AddInkDropLayer(ui::Layer* ink_drop_layer) override {
++ink_drop_layer_add_count_;
- CustomButton::AddInkDropLayer(ink_drop_layer);
+ Button::AddInkDropLayer(ink_drop_layer);
}
void RemoveInkDropLayer(ui::Layer* ink_drop_layer) override {
++ink_drop_layer_remove_count_;
- CustomButton::RemoveInkDropLayer(ink_drop_layer);
+ Button::RemoveInkDropLayer(ink_drop_layer);
}
bool pressed() { return pressed_; }
@@ -96,7 +93,7 @@ class TestCustomButton : public CustomButton, public ButtonListener {
}
// Raised visibility of OnFocus() to public
- void OnFocus() override { CustomButton::OnFocus(); }
+ void OnFocus() override { Button::OnFocus(); }
private:
bool pressed_ = false;
@@ -105,20 +102,20 @@ class TestCustomButton : public CustomButton, public ButtonListener {
int ink_drop_layer_add_count_ = 0;
int ink_drop_layer_remove_count_ = 0;
- DISALLOW_COPY_AND_ASSIGN(TestCustomButton);
+ DISALLOW_COPY_AND_ASSIGN(TestButton);
};
} // namespace
-class CustomButtonTest : public ViewsTestBase {
+class ButtonTest : public ViewsTestBase {
public:
- CustomButtonTest() {}
- ~CustomButtonTest() override {}
+ ButtonTest() {}
+ ~ButtonTest() override {}
void SetUp() override {
ViewsTestBase::SetUp();
- // Create a widget so that the CustomButton can query the hover state
+ // Create a widget so that the Button can query the hover state
// correctly.
widget_.reset(new Widget);
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
@@ -127,7 +124,7 @@ class CustomButtonTest : public ViewsTestBase {
widget_->Init(params);
widget_->Show();
- button_ = new TestCustomButton(false);
+ button_ = new TestButton(false);
widget_->SetContentsView(button_);
}
@@ -139,14 +136,14 @@ class CustomButtonTest : public ViewsTestBase {
void CreateButtonWithInkDrop(std::unique_ptr<InkDrop> ink_drop,
bool has_ink_drop_action_on_click) {
delete button_;
- button_ = new TestCustomButton(has_ink_drop_action_on_click);
+ button_ = new TestButton(has_ink_drop_action_on_click);
InkDropHostViewTestApi(button_).SetInkDrop(std::move(ink_drop));
widget_->SetContentsView(button_);
}
void CreateButtonWithRealInkDrop() {
delete button_;
- button_ = new TestCustomButton(false);
+ button_ = new TestButton(false);
InkDropHostViewTestApi(button_).SetInkDrop(
base::MakeUnique<InkDropImpl>(button_, button_->size()));
widget_->SetContentsView(button_);
@@ -154,39 +151,39 @@ class CustomButtonTest : public ViewsTestBase {
protected:
Widget* widget() { return widget_.get(); }
- TestCustomButton* button() { return button_; }
+ TestButton* button() { return button_; }
void SetDraggedView(View* dragged_view) {
widget_->dragged_view_ = dragged_view;
}
private:
std::unique_ptr<Widget> widget_;
- TestCustomButton* button_ = nullptr;
+ TestButton* button_ = nullptr;
- DISALLOW_COPY_AND_ASSIGN(CustomButtonTest);
+ DISALLOW_COPY_AND_ASSIGN(ButtonTest);
};
// Tests that hover state changes correctly when visiblity/enableness changes.
-TEST_F(CustomButtonTest, HoverStateOnVisibilityChange) {
+TEST_F(ButtonTest, HoverStateOnVisibilityChange) {
ui::test::EventGenerator generator(widget()->GetNativeWindow());
generator.PressLeftButton();
- EXPECT_EQ(CustomButton::STATE_PRESSED, button()->state());
+ EXPECT_EQ(Button::STATE_PRESSED, button()->state());
generator.ReleaseLeftButton();
- EXPECT_EQ(CustomButton::STATE_HOVERED, button()->state());
+ EXPECT_EQ(Button::STATE_HOVERED, button()->state());
button()->SetEnabled(false);
- EXPECT_EQ(CustomButton::STATE_DISABLED, button()->state());
+ EXPECT_EQ(Button::STATE_DISABLED, button()->state());
button()->SetEnabled(true);
- EXPECT_EQ(CustomButton::STATE_HOVERED, button()->state());
+ EXPECT_EQ(Button::STATE_HOVERED, button()->state());
button()->SetVisible(false);
- EXPECT_EQ(CustomButton::STATE_NORMAL, button()->state());
+ EXPECT_EQ(Button::STATE_NORMAL, button()->state());
button()->SetVisible(true);
- EXPECT_EQ(CustomButton::STATE_HOVERED, button()->state());
+ EXPECT_EQ(Button::STATE_HOVERED, button()->state());
#if defined(USE_AURA)
{
@@ -201,16 +198,16 @@ TEST_F(CustomButtonTest, HoverStateOnVisibilityChange) {
second_widget.GetNativeWindow()->SetCapture();
button()->SetEnabled(false);
- EXPECT_EQ(CustomButton::STATE_DISABLED, button()->state());
+ EXPECT_EQ(Button::STATE_DISABLED, button()->state());
button()->SetEnabled(true);
- EXPECT_EQ(CustomButton::STATE_NORMAL, button()->state());
+ EXPECT_EQ(Button::STATE_NORMAL, button()->state());
button()->SetVisible(false);
- EXPECT_EQ(CustomButton::STATE_NORMAL, button()->state());
+ EXPECT_EQ(Button::STATE_NORMAL, button()->state());
button()->SetVisible(true);
- EXPECT_EQ(CustomButton::STATE_NORMAL, button()->state());
+ EXPECT_EQ(Button::STATE_NORMAL, button()->state());
}
#endif
@@ -225,43 +222,43 @@ TEST_F(CustomButtonTest, HoverStateOnVisibilityChange) {
cursor_client.DisableMouseEvents();
button()->SetEnabled(false);
- EXPECT_EQ(CustomButton::STATE_DISABLED, button()->state());
+ EXPECT_EQ(Button::STATE_DISABLED, button()->state());
button()->SetEnabled(true);
- EXPECT_EQ(CustomButton::STATE_NORMAL, button()->state());
+ EXPECT_EQ(Button::STATE_NORMAL, button()->state());
button()->SetVisible(false);
- EXPECT_EQ(CustomButton::STATE_NORMAL, button()->state());
+ EXPECT_EQ(Button::STATE_NORMAL, button()->state());
button()->SetVisible(true);
- EXPECT_EQ(CustomButton::STATE_NORMAL, button()->state());
+ EXPECT_EQ(Button::STATE_NORMAL, button()->state());
#endif // !defined(OS_MACOSX) || defined(USE_AURA)
}
// Tests the different types of NotifyActions.
-TEST_F(CustomButtonTest, NotifyAction) {
+TEST_F(ButtonTest, NotifyAction) {
gfx::Point center(10, 10);
// By default the button should notify its listener on mouse release.
button()->OnMousePressed(ui::MouseEvent(
ui::ET_MOUSE_PRESSED, center, center, ui::EventTimeForNow(),
ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
- EXPECT_EQ(CustomButton::STATE_PRESSED, button()->state());
+ EXPECT_EQ(Button::STATE_PRESSED, button()->state());
EXPECT_FALSE(button()->pressed());
button()->OnMouseReleased(ui::MouseEvent(
ui::ET_MOUSE_RELEASED, center, center, ui::EventTimeForNow(),
ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
- EXPECT_EQ(CustomButton::STATE_HOVERED, button()->state());
+ EXPECT_EQ(Button::STATE_HOVERED, button()->state());
EXPECT_TRUE(button()->pressed());
// Set the notify action to its listener on mouse press.
button()->Reset();
- button()->set_notify_action(CustomButton::NOTIFY_ON_PRESS);
+ button()->set_notify_action(Button::NOTIFY_ON_PRESS);
button()->OnMousePressed(ui::MouseEvent(
ui::ET_MOUSE_PRESSED, center, center, ui::EventTimeForNow(),
ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
- EXPECT_EQ(CustomButton::STATE_PRESSED, button()->state());
+ EXPECT_EQ(Button::STATE_PRESSED, button()->state());
EXPECT_TRUE(button()->pressed());
// The button should no longer notify on mouse release.
@@ -269,13 +266,13 @@ TEST_F(CustomButtonTest, NotifyAction) {
button()->OnMouseReleased(ui::MouseEvent(
ui::ET_MOUSE_RELEASED, center, center, ui::EventTimeForNow(),
ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
- EXPECT_EQ(CustomButton::STATE_HOVERED, button()->state());
+ EXPECT_EQ(Button::STATE_HOVERED, button()->state());
EXPECT_FALSE(button()->pressed());
}
// Tests that OnClickCanceled gets called when NotifyClick is not expected
// anymore.
-TEST_F(CustomButtonTest, NotifyActionNoClick) {
+TEST_F(ButtonTest, NotifyActionNoClick) {
gfx::Point center(10, 10);
// By default the button should notify its listener on mouse release.
@@ -291,7 +288,7 @@ TEST_F(CustomButtonTest, NotifyActionNoClick) {
// Set the notify action to its listener on mouse press.
button()->Reset();
- button()->set_notify_action(CustomButton::NOTIFY_ON_PRESS);
+ button()->set_notify_action(Button::NOTIFY_ON_PRESS);
button()->OnMousePressed(ui::MouseEvent(
ui::ET_MOUSE_PRESSED, center, center, ui::EventTimeForNow(),
ui::EF_RIGHT_MOUSE_BUTTON, ui::EF_RIGHT_MOUSE_BUTTON));
@@ -311,7 +308,7 @@ TEST_F(CustomButtonTest, NotifyActionNoClick) {
namespace {
-void PerformGesture(CustomButton* button, ui::EventType event_type) {
+void PerformGesture(Button* button, ui::EventType event_type) {
ui::GestureEventDetails gesture_details(event_type);
ui::GestureEvent gesture_event(0, 0, 0, base::TimeTicks(), gesture_details);
button->OnGestureEvent(&gesture_event);
@@ -320,61 +317,61 @@ void PerformGesture(CustomButton* button, ui::EventType event_type) {
} // namespace
// Tests that gesture events correctly change the button state.
-TEST_F(CustomButtonTest, GestureEventsSetState) {
+TEST_F(ButtonTest, GestureEventsSetState) {
aura::test::TestCursorClient cursor_client(
widget()->GetNativeView()->GetRootWindow());
- EXPECT_EQ(CustomButton::STATE_NORMAL, button()->state());
+ EXPECT_EQ(Button::STATE_NORMAL, button()->state());
PerformGesture(button(), ui::ET_GESTURE_TAP_DOWN);
- EXPECT_EQ(CustomButton::STATE_PRESSED, button()->state());
+ EXPECT_EQ(Button::STATE_PRESSED, button()->state());
PerformGesture(button(), ui::ET_GESTURE_SHOW_PRESS);
- EXPECT_EQ(CustomButton::STATE_PRESSED, button()->state());
+ EXPECT_EQ(Button::STATE_PRESSED, button()->state());
PerformGesture(button(), ui::ET_GESTURE_TAP_CANCEL);
- EXPECT_EQ(CustomButton::STATE_NORMAL, button()->state());
+ EXPECT_EQ(Button::STATE_NORMAL, button()->state());
}
#endif // !defined(OS_MACOSX) || defined(USE_AURA)
-// Ensure subclasses of CustomButton are correctly recognized as CustomButton.
-TEST_F(CustomButtonTest, AsCustomButton) {
+// Ensure subclasses of Button are correctly recognized as Button.
+TEST_F(ButtonTest, AsButton) {
base::string16 text;
LabelButton label_button(NULL, text);
- EXPECT_TRUE(CustomButton::AsCustomButton(&label_button));
+ EXPECT_TRUE(Button::AsButton(&label_button));
ImageButton image_button(NULL);
- EXPECT_TRUE(CustomButton::AsCustomButton(&image_button));
+ EXPECT_TRUE(Button::AsButton(&image_button));
Checkbox checkbox(text);
- EXPECT_TRUE(CustomButton::AsCustomButton(&checkbox));
+ EXPECT_TRUE(Button::AsButton(&checkbox));
RadioButton radio_button(text, 0);
- EXPECT_TRUE(CustomButton::AsCustomButton(&radio_button));
+ EXPECT_TRUE(Button::AsButton(&radio_button));
MenuButton menu_button(text, NULL, false);
- EXPECT_TRUE(CustomButton::AsCustomButton(&menu_button));
+ EXPECT_TRUE(Button::AsButton(&menu_button));
ToggleButton toggle_button(NULL);
- EXPECT_TRUE(CustomButton::AsCustomButton(&toggle_button));
+ EXPECT_TRUE(Button::AsButton(&toggle_button));
Label label;
- EXPECT_FALSE(CustomButton::AsCustomButton(&label));
+ EXPECT_FALSE(Button::AsButton(&label));
Link link(text);
- EXPECT_FALSE(CustomButton::AsCustomButton(&link));
+ EXPECT_FALSE(Button::AsButton(&link));
Textfield textfield;
- EXPECT_FALSE(CustomButton::AsCustomButton(&textfield));
+ EXPECT_FALSE(Button::AsButton(&textfield));
}
// Tests that pressing a button shows the ink drop and releasing the button
// does not hide the ink drop.
-// Note: Ink drop is not hidden upon release because CustomButton descendants
+// Note: Ink drop is not hidden upon release because Button descendants
// may enter a different ink drop state.
-TEST_F(CustomButtonTest, ButtonClickTogglesInkDrop) {
+TEST_F(ButtonTest, ButtonClickTogglesInkDrop) {
TestInkDrop* ink_drop = new TestInkDrop();
CreateButtonWithInkDrop(base::WrapUnique(ink_drop), false);
@@ -389,7 +386,7 @@ TEST_F(CustomButtonTest, ButtonClickTogglesInkDrop) {
// Tests that pressing a button shows and releasing capture hides ink drop.
// Releasing capture should also reset PRESSED button state to NORMAL.
-TEST_F(CustomButtonTest, CaptureLossHidesInkDrop) {
+TEST_F(ButtonTest, CaptureLossHidesInkDrop) {
TestInkDrop* ink_drop = new TestInkDrop();
CreateButtonWithInkDrop(base::WrapUnique(ink_drop), false);
@@ -407,7 +404,7 @@ TEST_F(CustomButtonTest, CaptureLossHidesInkDrop) {
EXPECT_EQ(Button::ButtonState::STATE_NORMAL, button()->state());
}
-TEST_F(CustomButtonTest, HideInkDropWhenShowingContextMenu) {
+TEST_F(ButtonTest, HideInkDropWhenShowingContextMenu) {
TestInkDrop* ink_drop = new TestInkDrop();
CreateButtonWithInkDrop(base::WrapUnique(ink_drop), false);
TestContextMenuController context_menu_controller;
@@ -423,7 +420,7 @@ TEST_F(CustomButtonTest, HideInkDropWhenShowingContextMenu) {
EXPECT_EQ(InkDropState::HIDDEN, ink_drop->GetTargetInkDropState());
}
-TEST_F(CustomButtonTest, DontHideInkDropWhenShowingContextMenu) {
+TEST_F(ButtonTest, DontHideInkDropWhenShowingContextMenu) {
TestInkDrop* ink_drop = new TestInkDrop();
CreateButtonWithInkDrop(base::WrapUnique(ink_drop), false);
TestContextMenuController context_menu_controller;
@@ -439,7 +436,7 @@ TEST_F(CustomButtonTest, DontHideInkDropWhenShowingContextMenu) {
EXPECT_EQ(InkDropState::ACTION_PENDING, ink_drop->GetTargetInkDropState());
}
-TEST_F(CustomButtonTest, HideInkDropOnBlur) {
+TEST_F(ButtonTest, HideInkDropOnBlur) {
gfx::Point center(10, 10);
TestInkDrop* ink_drop = new TestInkDrop();
@@ -461,7 +458,7 @@ TEST_F(CustomButtonTest, HideInkDropOnBlur) {
EXPECT_TRUE(button()->pressed());
}
-TEST_F(CustomButtonTest, HideInkDropHighlightOnDisable) {
+TEST_F(ButtonTest, HideInkDropHighlightOnDisable) {
TestInkDrop* ink_drop = new TestInkDrop();
CreateButtonWithInkDrop(base::WrapUnique(ink_drop), false);
@@ -474,7 +471,7 @@ TEST_F(CustomButtonTest, HideInkDropHighlightOnDisable) {
EXPECT_TRUE(ink_drop->is_hovered());
}
-TEST_F(CustomButtonTest, InkDropAfterTryingToShowContextMenu) {
+TEST_F(ButtonTest, InkDropAfterTryingToShowContextMenu) {
TestInkDrop* ink_drop = new TestInkDrop();
CreateButtonWithInkDrop(base::WrapUnique(ink_drop), false);
button()->set_context_menu_controller(nullptr);
@@ -490,13 +487,13 @@ TEST_F(CustomButtonTest, InkDropAfterTryingToShowContextMenu) {
// Tests that when button is set to notify on release, dragging mouse out and
// back transitions ink drop states correctly.
-TEST_F(CustomButtonTest, InkDropShowHideOnMouseDraggedNotifyOnRelease) {
+TEST_F(ButtonTest, InkDropShowHideOnMouseDraggedNotifyOnRelease) {
gfx::Point center(10, 10);
gfx::Point oob(-1, -1);
TestInkDrop* ink_drop = new TestInkDrop();
CreateButtonWithInkDrop(base::WrapUnique(ink_drop), false);
- button()->set_notify_action(CustomButton::NOTIFY_ON_RELEASE);
+ button()->set_notify_action(Button::NOTIFY_ON_RELEASE);
button()->OnMousePressed(ui::MouseEvent(
ui::ET_MOUSE_PRESSED, center, center, ui::EventTimeForNow(),
@@ -531,13 +528,13 @@ TEST_F(CustomButtonTest, InkDropShowHideOnMouseDraggedNotifyOnRelease) {
// Tests that when button is set to notify on press, dragging mouse out and back
// does not change the ink drop state.
-TEST_F(CustomButtonTest, InkDropShowHideOnMouseDraggedNotifyOnPress) {
+TEST_F(ButtonTest, InkDropShowHideOnMouseDraggedNotifyOnPress) {
gfx::Point center(10, 10);
gfx::Point oob(-1, -1);
TestInkDrop* ink_drop = new TestInkDrop();
CreateButtonWithInkDrop(base::WrapUnique(ink_drop), true);
- button()->set_notify_action(CustomButton::NOTIFY_ON_PRESS);
+ button()->set_notify_action(Button::NOTIFY_ON_PRESS);
button()->OnMousePressed(ui::MouseEvent(
ui::ET_MOUSE_PRESSED, center, center, ui::EventTimeForNow(),
@@ -571,7 +568,7 @@ TEST_F(CustomButtonTest, InkDropShowHideOnMouseDraggedNotifyOnPress) {
EXPECT_EQ(InkDropState::ACTION_TRIGGERED, ink_drop->GetTargetInkDropState());
}
-TEST_F(CustomButtonTest, InkDropStaysHiddenWhileDragging) {
+TEST_F(ButtonTest, InkDropStaysHiddenWhileDragging) {
gfx::Point center(10, 10);
gfx::Point oob(-1, -1);
@@ -607,7 +604,7 @@ TEST_F(CustomButtonTest, InkDropStaysHiddenWhileDragging) {
// Test that hiding or closing a Widget doesn't attempt to add a layer due to
// changed visibility states.
-TEST_F(CustomButtonTest, NoLayerAddedForWidgetVisibilityChanges) {
+TEST_F(ButtonTest, NoLayerAddedForWidgetVisibilityChanges) {
CreateButtonWithRealInkDrop();
EXPECT_TRUE(button()->visible());
@@ -640,7 +637,7 @@ TEST_F(CustomButtonTest, NoLayerAddedForWidgetVisibilityChanges) {
// Verify that the Space key clicks the button on key-press on Mac, and
// key-release on other platforms.
-TEST_F(CustomButtonTest, ActionOnSpace) {
+TEST_F(ButtonTest, ActionOnSpace) {
// Give focus to the button.
button()->SetFocusForPlatform();
button()->RequestFocus();
@@ -650,10 +647,10 @@ TEST_F(CustomButtonTest, ActionOnSpace) {
EXPECT_TRUE(button()->OnKeyPressed(space_press));
#if defined(OS_MACOSX)
- EXPECT_EQ(CustomButton::STATE_NORMAL, button()->state());
+ EXPECT_EQ(Button::STATE_NORMAL, button()->state());
EXPECT_TRUE(button()->pressed());
#else
- EXPECT_EQ(CustomButton::STATE_PRESSED, button()->state());
+ EXPECT_EQ(Button::STATE_PRESSED, button()->state());
EXPECT_FALSE(button()->pressed());
#endif
@@ -665,14 +662,14 @@ TEST_F(CustomButtonTest, ActionOnSpace) {
EXPECT_TRUE(button()->OnKeyReleased(space_release));
#endif
- EXPECT_EQ(CustomButton::STATE_NORMAL, button()->state());
+ EXPECT_EQ(Button::STATE_NORMAL, button()->state());
EXPECT_TRUE(button()->pressed());
}
// Verify that the Return key clicks the button on key-press on all platforms
// except Mac. On Mac, the Return key performs the default action associated
// with a dialog, even if a button has focus.
-TEST_F(CustomButtonTest, ActionOnReturn) {
+TEST_F(ButtonTest, ActionOnReturn) {
// Give focus to the button.
button()->SetFocusForPlatform();
button()->RequestFocus();
@@ -682,11 +679,11 @@ TEST_F(CustomButtonTest, ActionOnReturn) {
#if defined(OS_MACOSX)
EXPECT_FALSE(button()->OnKeyPressed(return_press));
- EXPECT_EQ(CustomButton::STATE_NORMAL, button()->state());
+ EXPECT_EQ(Button::STATE_NORMAL, button()->state());
EXPECT_FALSE(button()->pressed());
#else
EXPECT_TRUE(button()->OnKeyPressed(return_press));
- EXPECT_EQ(CustomButton::STATE_NORMAL, button()->state());
+ EXPECT_EQ(Button::STATE_NORMAL, button()->state());
EXPECT_TRUE(button()->pressed());
#endif
diff --git a/chromium/ui/views/controls/button/checkbox.cc b/chromium/ui/views/controls/button/checkbox.cc
index d3535f0f548..14dc8b31154 100644
--- a/chromium/ui/views/controls/button/checkbox.cc
+++ b/chromium/ui/views/controls/button/checkbox.cc
@@ -23,10 +23,13 @@
#include "ui/views/painter.h"
#include "ui/views/resources/grit/views_resources.h"
#include "ui/views/style/platform_style.h"
+#include "ui/views/style/typography.h"
#include "ui/views/vector_icons.h"
namespace views {
+constexpr int kFocusRingThicknessDip = 2;
+
// View used to paint the focus ring around the Checkbox icon.
// The icon is painted separately.
class IconFocusRing : public View {
@@ -50,7 +53,7 @@ IconFocusRing::IconFocusRing(Checkbox* checkbox) : checkbox_(checkbox) {
void IconFocusRing::Layout() {
gfx::Rect focus_bounds = checkbox_->image()->bounds();
- focus_bounds.Inset(gfx::Insets(-2.f));
+ focus_bounds.Inset(-kFocusRingThicknessDip, -kFocusRingThicknessDip);
SetBoundsRect(focus_bounds);
}
@@ -205,18 +208,15 @@ std::unique_ptr<InkDropRipple> Checkbox::CreateInkDropRipple() const {
}
SkColor Checkbox::GetInkDropBaseColor() const {
- return GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_LabelEnabledColor);
+ // Usually ink drop ripples match the text color. Checkboxes use the color of
+ // the unchecked icon.
+ return GetIconImageColor(false);
}
gfx::ImageSkia Checkbox::GetImage(ButtonState for_state) const {
if (UseMd()) {
- return gfx::CreateVectorIcon(
- GetVectorIcon(), 16,
- // When not checked, the icon color matches the button text color.
- GetNativeTheme()->GetSystemColor(
- checked_ ? ui::NativeTheme::kColorId_FocusedBorderColor
- : ui::NativeTheme::kColorId_LabelEnabledColor));
+ return gfx::CreateVectorIcon(GetVectorIcon(), 16,
+ GetIconImageColor(checked_));
}
const size_t checked_index = checked_ ? 1 : 0;
@@ -248,13 +248,26 @@ void Checkbox::SetCustomImage(bool checked,
void Checkbox::PaintFocusRing(View* view,
gfx::Canvas* canvas,
const cc::PaintFlags& flags) {
- canvas->DrawRoundRect(view->GetLocalBounds(), 2.f, flags);
+ gfx::RectF bounds(view->GetLocalBounds());
+ bounds.Inset(kFocusRingThicknessDip, kFocusRingThicknessDip);
+ canvas->DrawRoundRect(bounds, kFocusRingThicknessDip, flags);
}
const gfx::VectorIcon& Checkbox::GetVectorIcon() const {
return checked() ? kCheckboxActiveIcon : kCheckboxNormalIcon;
}
+SkColor Checkbox::GetIconImageColor(bool checked) const {
+ DCHECK(UseMd());
+ const ui::NativeTheme* theme = GetNativeTheme();
+ return checked
+ ? theme->GetSystemColor(
+ ui::NativeTheme::kColorId_FocusedBorderColor)
+ // When unchecked, the icon color matches push button text color.
+ : style::GetColor(style::CONTEXT_BUTTON_MD, style::STYLE_PRIMARY,
+ theme);
+}
+
void Checkbox::NotifyClick(const ui::Event& event) {
SetChecked(!checked());
LabelButton::NotifyClick(event);
diff --git a/chromium/ui/views/controls/button/checkbox.h b/chromium/ui/views/controls/button/checkbox.h
index deb26a213f8..d260a8692ba 100644
--- a/chromium/ui/views/controls/button/checkbox.h
+++ b/chromium/ui/views/controls/button/checkbox.h
@@ -70,6 +70,8 @@ class VIEWS_EXPORT Checkbox : public LabelButton {
private:
friend class IconFocusRing;
+ SkColor GetIconImageColor(bool checked) const;
+
// Button:
void NotifyClick(const ui::Event& event) override;
diff --git a/chromium/ui/views/controls/button/custom_button.cc b/chromium/ui/views/controls/button/custom_button.cc
deleted file mode 100644
index 95e8aad340b..00000000000
--- a/chromium/ui/views/controls/button/custom_button.cc
+++ /dev/null
@@ -1,525 +0,0 @@
-// Copyright (c) 2012 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/controls/button/custom_button.h"
-
-#include "ui/accessibility/ax_node_data.h"
-#include "ui/events/event.h"
-#include "ui/events/event_utils.h"
-#include "ui/events/keycodes/keyboard_codes.h"
-#include "ui/gfx/animation/throb_animation.h"
-#include "ui/gfx/color_palette.h"
-#include "ui/native_theme/native_theme.h"
-#include "ui/views/animation/ink_drop_highlight.h"
-#include "ui/views/animation/ink_drop_impl.h"
-#include "ui/views/controls/button/blue_button.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/controls/button/menu_button.h"
-#include "ui/views/controls/button/radio_button.h"
-#include "ui/views/controls/button/toggle_button.h"
-#include "ui/views/painter.h"
-#include "ui/views/style/platform_style.h"
-#include "ui/views/widget/widget.h"
-
-#if defined(USE_AURA)
-#include "ui/aura/client/capture_client.h"
-#include "ui/aura/window.h"
-#endif
-
-namespace views {
-
-namespace {
-
-// How long the hover animation takes if uninterrupted.
-const int kHoverFadeDurationMs = 150;
-
-CustomButton::KeyClickAction GetKeyClickActionForEvent(
- const ui::KeyEvent& event) {
- if (event.key_code() == ui::VKEY_SPACE)
- return PlatformStyle::kKeyClickActionOnSpace;
- if (event.key_code() == ui::VKEY_RETURN &&
- PlatformStyle::kReturnClicksFocusedControl)
- return CustomButton::CLICK_ON_KEY_PRESS;
- return CustomButton::CLICK_NONE;
-}
-
-} // namespace
-
-////////////////////////////////////////////////////////////////////////////////
-// CustomButton, public:
-
-// static
-const char CustomButton::kViewClassName[] = "CustomButton";
-
-// static
-const CustomButton* CustomButton::AsCustomButton(const views::View* view) {
- return AsCustomButton(const_cast<View*>(view));
-}
-
-// static
-CustomButton* CustomButton::AsCustomButton(views::View* view) {
- if (view) {
- const char* classname = view->GetClassName();
- if (!strcmp(classname, Checkbox::kViewClassName) ||
- !strcmp(classname, CustomButton::kViewClassName) ||
- !strcmp(classname, ImageButton::kViewClassName) ||
- !strcmp(classname, LabelButton::kViewClassName) ||
- !strcmp(classname, RadioButton::kViewClassName) ||
- !strcmp(classname, ToggleButton::kViewClassName) ||
- !strcmp(classname, MenuButton::kViewClassName)) {
- return static_cast<CustomButton*>(view);
- }
- }
- return NULL;
-}
-
-CustomButton::~CustomButton() {}
-
-void CustomButton::SetState(ButtonState state) {
- if (state == state_)
- return;
-
- if (animate_on_state_change_ &&
- (!is_throbbing_ || !hover_animation_.is_animating())) {
- is_throbbing_ = false;
- if ((state_ == STATE_HOVERED) && (state == STATE_NORMAL)) {
- // For HOVERED -> NORMAL, animate from hovered (1) to not hovered (0).
- hover_animation_.Hide();
- } else if (state != STATE_HOVERED) {
- // For HOVERED -> PRESSED/DISABLED, or any transition not involving
- // HOVERED at all, simply set the state to not hovered (0).
- hover_animation_.Reset();
- } else if (state_ == STATE_NORMAL) {
- // For NORMAL -> HOVERED, animate from not hovered (0) to hovered (1).
- hover_animation_.Show();
- } else {
- // For PRESSED/DISABLED -> HOVERED, simply set the state to hovered (1).
- hover_animation_.Reset(1);
- }
- }
-
- ButtonState old_state = state_;
- state_ = state;
- StateChanged(old_state);
- SchedulePaint();
-}
-
-void CustomButton::StartThrobbing(int cycles_til_stop) {
- if (!animate_on_state_change_)
- return;
- is_throbbing_ = true;
- hover_animation_.StartThrobbing(cycles_til_stop);
-}
-
-void CustomButton::StopThrobbing() {
- if (hover_animation_.is_animating()) {
- hover_animation_.Stop();
- SchedulePaint();
- }
-}
-
-void CustomButton::SetAnimationDuration(int duration) {
- hover_animation_.SetSlideDuration(duration);
-}
-
-void CustomButton::SetHotTracked(bool is_hot_tracked) {
- if (state_ != STATE_DISABLED)
- SetState(is_hot_tracked ? STATE_HOVERED : STATE_NORMAL);
-
- if (is_hot_tracked)
- NotifyAccessibilityEvent(ui::AX_EVENT_HOVER, true);
-}
-
-bool CustomButton::IsHotTracked() const {
- return state_ == STATE_HOVERED;
-}
-
-void CustomButton::SetFocusPainter(std::unique_ptr<Painter> focus_painter) {
- focus_painter_ = std::move(focus_painter);
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// CustomButton, View overrides:
-
-void CustomButton::OnEnabledChanged() {
- // TODO(bruthig): Is there any reason we are not calling
- // Button::OnEnabledChanged() here?
- if (enabled() ? (state_ != STATE_DISABLED) : (state_ == STATE_DISABLED))
- return;
-
- if (enabled()) {
- bool should_enter_hover_state = ShouldEnterHoveredState();
- SetState(should_enter_hover_state ? STATE_HOVERED : STATE_NORMAL);
- GetInkDrop()->SetHovered(should_enter_hover_state);
- } else {
- SetState(STATE_DISABLED);
- GetInkDrop()->SetHovered(false);
- }
-}
-
-const char* CustomButton::GetClassName() const {
- return kViewClassName;
-}
-
-bool CustomButton::OnMousePressed(const ui::MouseEvent& event) {
- if (state_ == STATE_DISABLED)
- return true;
- if (state_ != STATE_PRESSED && ShouldEnterPushedState(event) &&
- HitTestPoint(event.location())) {
- SetState(STATE_PRESSED);
- AnimateInkDrop(views::InkDropState::ACTION_PENDING, &event);
- }
- if (request_focus_on_press_)
- RequestFocus();
- if (IsTriggerableEvent(event) && notify_action_ == NOTIFY_ON_PRESS) {
- NotifyClick(event);
- // NOTE: We may be deleted at this point (by the listener's notification
- // handler).
- }
- return true;
-}
-
-bool CustomButton::OnMouseDragged(const ui::MouseEvent& event) {
- if (state_ != STATE_DISABLED) {
- const bool should_enter_pushed = ShouldEnterPushedState(event);
- const bool should_show_pending =
- should_enter_pushed && notify_action_ == NOTIFY_ON_RELEASE && !InDrag();
- if (HitTestPoint(event.location())) {
- SetState(should_enter_pushed ? STATE_PRESSED : STATE_HOVERED);
- if (should_show_pending &&
- GetInkDrop()->GetTargetInkDropState() ==
- views::InkDropState::HIDDEN) {
- AnimateInkDrop(views::InkDropState::ACTION_PENDING, &event);
- }
- } else {
- SetState(STATE_NORMAL);
- if (should_show_pending &&
- GetInkDrop()->GetTargetInkDropState() ==
- views::InkDropState::ACTION_PENDING) {
- AnimateInkDrop(views::InkDropState::HIDDEN, &event);
- }
- }
- }
- return true;
-}
-
-void CustomButton::OnMouseReleased(const ui::MouseEvent& event) {
- if (state_ != STATE_DISABLED) {
- if (!HitTestPoint(event.location())) {
- SetState(STATE_NORMAL);
- } else {
- SetState(STATE_HOVERED);
- if (IsTriggerableEvent(event) && notify_action_ == NOTIFY_ON_RELEASE) {
- NotifyClick(event);
- // NOTE: We may be deleted at this point (by the listener's notification
- // handler).
- return;
- }
- }
- }
- if (notify_action_ == NOTIFY_ON_RELEASE)
- OnClickCanceled(event);
-}
-
-void CustomButton::OnMouseCaptureLost() {
- // Starting a drag results in a MouseCaptureLost. Reset button state.
- // TODO(varkha): Reset the state even while in drag. The same logic may
- // applies everywhere so gather any feedback and update.
- if (state_ != STATE_DISABLED)
- SetState(STATE_NORMAL);
- AnimateInkDrop(views::InkDropState::HIDDEN, nullptr /* event */);
- GetInkDrop()->SetHovered(false);
- Button::OnMouseCaptureLost();
-}
-
-void CustomButton::OnMouseEntered(const ui::MouseEvent& event) {
- if (state_ != STATE_DISABLED)
- SetState(STATE_HOVERED);
-}
-
-void CustomButton::OnMouseExited(const ui::MouseEvent& event) {
- // Starting a drag results in a MouseExited, we need to ignore it.
- if (state_ != STATE_DISABLED && !InDrag())
- SetState(STATE_NORMAL);
-}
-
-void CustomButton::OnMouseMoved(const ui::MouseEvent& event) {
- if (state_ != STATE_DISABLED)
- SetState(HitTestPoint(event.location()) ? STATE_HOVERED : STATE_NORMAL);
-}
-
-bool CustomButton::OnKeyPressed(const ui::KeyEvent& event) {
- if (state_ == STATE_DISABLED)
- return false;
-
- switch (GetKeyClickActionForEvent(event)) {
- case KeyClickAction::CLICK_ON_KEY_RELEASE:
- SetState(STATE_PRESSED);
- if (GetInkDrop()->GetTargetInkDropState() !=
- InkDropState::ACTION_PENDING) {
- AnimateInkDrop(InkDropState::ACTION_PENDING, nullptr /* event */);
- }
- return true;
- case KeyClickAction::CLICK_ON_KEY_PRESS:
- SetState(STATE_NORMAL);
- NotifyClick(event);
- return true;
- case KeyClickAction::CLICK_NONE:
- return false;
- }
-
- NOTREACHED();
- return false;
-}
-
-bool CustomButton::OnKeyReleased(const ui::KeyEvent& event) {
- const bool click_button =
- state_ == STATE_PRESSED &&
- GetKeyClickActionForEvent(event) == KeyClickAction::CLICK_ON_KEY_RELEASE;
- if (!click_button)
- return false;
-
- SetState(STATE_NORMAL);
- NotifyClick(event);
- return true;
-}
-
-void CustomButton::OnGestureEvent(ui::GestureEvent* event) {
- if (state_ == STATE_DISABLED) {
- Button::OnGestureEvent(event);
- return;
- }
-
- if (event->type() == ui::ET_GESTURE_TAP && IsTriggerableEvent(*event)) {
- // Set the button state to hot and start the animation fully faded in. The
- // GESTURE_END event issued immediately after will set the state to
- // STATE_NORMAL beginning the fade out animation. See
- // http://crbug.com/131184.
- SetState(STATE_HOVERED);
- hover_animation_.Reset(1.0);
- NotifyClick(*event);
- event->StopPropagation();
- } else if (event->type() == ui::ET_GESTURE_TAP_DOWN &&
- ShouldEnterPushedState(*event)) {
- SetState(STATE_PRESSED);
- if (request_focus_on_press_)
- RequestFocus();
- event->StopPropagation();
- } else if (event->type() == ui::ET_GESTURE_TAP_CANCEL ||
- event->type() == ui::ET_GESTURE_END) {
- SetState(STATE_NORMAL);
- }
- if (!event->handled())
- Button::OnGestureEvent(event);
-}
-
-bool CustomButton::AcceleratorPressed(const ui::Accelerator& accelerator) {
- SetState(STATE_NORMAL);
- NotifyClick(accelerator.ToKeyEvent());
- return true;
-}
-
-bool CustomButton::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) {
- // If this button is focused and the user presses space or enter, don't let
- // that be treated as an accelerator if there is a key click action
- // corresponding to it.
- return GetKeyClickActionForEvent(event) != KeyClickAction::CLICK_NONE;
-}
-
-void CustomButton::ShowContextMenu(const gfx::Point& p,
- ui::MenuSourceType source_type) {
- if (!context_menu_controller())
- return;
-
- // We're about to show the context menu. Showing the context menu likely means
- // we won't get a mouse exited and reset state. Reset it now to be sure.
- if (state_ != STATE_DISABLED)
- SetState(STATE_NORMAL);
- if (hide_ink_drop_when_showing_context_menu_) {
- GetInkDrop()->SetHovered(false);
- AnimateInkDrop(InkDropState::HIDDEN, nullptr /* event */);
- }
- View::ShowContextMenu(p, source_type);
-}
-
-void CustomButton::OnDragDone() {
- // Only reset the state to normal if the button isn't currently disabled
- // (since disabled buttons may still be able to be dragged).
- if (state_ != STATE_DISABLED)
- SetState(STATE_NORMAL);
- AnimateInkDrop(InkDropState::HIDDEN, nullptr /* event */);
-}
-
-void CustomButton::OnPaint(gfx::Canvas* canvas) {
- Button::OnPaint(canvas);
- PaintButtonContents(canvas);
- Painter::PaintFocusPainter(this, canvas, focus_painter_.get());
-}
-
-void CustomButton::GetAccessibleNodeData(ui::AXNodeData* node_data) {
- Button::GetAccessibleNodeData(node_data);
- switch (state_) {
- case STATE_HOVERED:
- node_data->AddState(ui::AX_STATE_HOVERED);
- break;
- case STATE_PRESSED:
- node_data->AddIntAttribute(ui::AX_ATTR_CHECKED_STATE,
- ui::AX_CHECKED_STATE_TRUE);
- break;
- case STATE_DISABLED:
- node_data->AddIntAttribute(ui::AX_ATTR_RESTRICTION,
- ui::AX_RESTRICTION_DISABLED);
- break;
- case STATE_NORMAL:
- case STATE_COUNT:
- // No additional accessibility node_data set for this button node_data.
- break;
- }
- if (enabled()) {
- node_data->AddIntAttribute(ui::AX_ATTR_DEFAULT_ACTION_VERB,
- ui::AX_DEFAULT_ACTION_VERB_PRESS);
- }
-}
-
-void CustomButton::VisibilityChanged(View* starting_from, bool visible) {
- Button::VisibilityChanged(starting_from, visible);
- if (state_ == STATE_DISABLED)
- return;
- SetState(visible && ShouldEnterHoveredState() ? STATE_HOVERED : STATE_NORMAL);
-}
-
-std::unique_ptr<InkDrop> CustomButton::CreateInkDrop() {
- std::unique_ptr<views::InkDropImpl> ink_drop = CreateDefaultInkDropImpl();
- ink_drop->SetShowHighlightOnFocus(true);
- return std::move(ink_drop);
-}
-
-SkColor CustomButton::GetInkDropBaseColor() const {
- return ink_drop_base_color_;
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// CustomButton, gfx::AnimationDelegate implementation:
-
-void CustomButton::AnimationProgressed(const gfx::Animation* animation) {
- SchedulePaint();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// CustomButton, View overrides (public):
-
-void CustomButton::ViewHierarchyChanged(
- const ViewHierarchyChangedDetails& details) {
- if (!details.is_add && state_ != STATE_DISABLED)
- SetState(STATE_NORMAL);
-}
-
-void CustomButton::OnFocus() {
- Button::OnFocus();
- if (focus_painter_)
- SchedulePaint();
-}
-
-void CustomButton::OnBlur() {
- Button::OnBlur();
- if (IsHotTracked() || state_ == STATE_PRESSED) {
- SetState(STATE_NORMAL);
- if (GetInkDrop()->GetTargetInkDropState() != views::InkDropState::HIDDEN)
- AnimateInkDrop(views::InkDropState::HIDDEN, nullptr /* event */);
- // TODO(bruthig) : Fix CustomButtons to work well when multiple input
- // methods are interacting with a button. e.g. By animating to HIDDEN here
- // it is possible for a Mouse Release to trigger an action however there
- // would be no visual cue to the user that this will occur.
- }
- if (focus_painter_)
- SchedulePaint();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// CustomButton, protected:
-
-CustomButton::CustomButton(ButtonListener* listener)
- : Button(listener),
- state_(STATE_NORMAL),
- hover_animation_(this),
- is_throbbing_(false),
- triggerable_event_flags_(ui::EF_LEFT_MOUSE_BUTTON),
- request_focus_on_press_(false),
- notify_action_(NOTIFY_ON_RELEASE),
- has_ink_drop_action_on_click_(false),
- hide_ink_drop_when_showing_context_menu_(true),
- ink_drop_base_color_(gfx::kPlaceholderColor) {
- hover_animation_.SetSlideDuration(kHoverFadeDurationMs);
-}
-
-void CustomButton::StateChanged(ButtonState old_state) {}
-
-bool CustomButton::IsTriggerableEvent(const ui::Event& event) {
- return event.type() == ui::ET_GESTURE_TAP_DOWN ||
- event.type() == ui::ET_GESTURE_TAP ||
- (event.IsMouseEvent() &&
- (triggerable_event_flags_ & event.flags()) != 0);
-}
-
-bool CustomButton::ShouldUpdateInkDropOnClickCanceled() const {
- return true;
-}
-
-bool CustomButton::ShouldEnterPushedState(const ui::Event& event) {
- return IsTriggerableEvent(event);
-}
-
-void CustomButton::PaintButtonContents(gfx::Canvas* canvas) {}
-
-bool CustomButton::ShouldEnterHoveredState() {
- if (!visible())
- return false;
-
- bool check_mouse_position = true;
-#if defined(USE_AURA)
- // If another window has capture, we shouldn't check the current mouse
- // position because the button won't receive any mouse events - so if the
- // mouse was hovered, the button would be stuck in a hovered state (since it
- // would never receive OnMouseExited).
- const Widget* widget = GetWidget();
- if (widget && widget->GetNativeWindow()) {
- aura::Window* root_window = widget->GetNativeWindow()->GetRootWindow();
- aura::client::CaptureClient* capture_client =
- aura::client::GetCaptureClient(root_window);
- aura::Window* capture_window =
- capture_client ? capture_client->GetGlobalCaptureWindow() : nullptr;
- check_mouse_position = !capture_window || capture_window == root_window;
- }
-#endif
-
- return check_mouse_position && IsMouseHovered();
-}
-
-////////////////////////////////////////////////////////////////////////////////
-// CustomButton, Button overrides (protected):
-
-void CustomButton::NotifyClick(const ui::Event& event) {
- if (has_ink_drop_action_on_click_) {
- AnimateInkDrop(InkDropState::ACTION_TRIGGERED,
- ui::LocatedEvent::FromIfValid(&event));
- }
- Button::NotifyClick(event);
-}
-
-void CustomButton::OnClickCanceled(const ui::Event& event) {
- if (ShouldUpdateInkDropOnClickCanceled()) {
- if (GetInkDrop()->GetTargetInkDropState() ==
- views::InkDropState::ACTION_PENDING ||
- GetInkDrop()->GetTargetInkDropState() ==
- views::InkDropState::ALTERNATE_ACTION_PENDING) {
- AnimateInkDrop(views::InkDropState::HIDDEN,
- ui::LocatedEvent::FromIfValid(&event));
- }
- }
- Button::OnClickCanceled(event);
-}
-
-} // namespace views
diff --git a/chromium/ui/views/controls/button/custom_button.h b/chromium/ui/views/controls/button/custom_button.h
deleted file mode 100644
index b76b2f87a54..00000000000
--- a/chromium/ui/views/controls/button/custom_button.h
+++ /dev/null
@@ -1,232 +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_CONTROLS_BUTTON_CUSTOM_BUTTON_H_
-#define UI_VIEWS_CONTROLS_BUTTON_CUSTOM_BUTTON_H_
-
-#include <memory>
-
-#include "base/macros.h"
-#include "build/build_config.h"
-#include "ui/events/event_constants.h"
-#include "ui/gfx/animation/animation_delegate.h"
-#include "ui/gfx/animation/throb_animation.h"
-#include "ui/views/animation/ink_drop_state.h"
-#include "ui/views/controls/button/button.h"
-
-namespace views {
-
-class Painter;
-
-// A button with custom rendering. The base of ImageButton and LabelButton.
-// Note that this type of button is not focusable by default and will not be
-// part of the focus chain, unless in accessibility mode. Call
-// SetFocusForPlatform() to make it part of the focus chain.
-class VIEWS_EXPORT CustomButton : public Button, public gfx::AnimationDelegate {
- public:
- // An enum describing the events on which a button should notify its listener.
- enum NotifyAction {
- NOTIFY_ON_PRESS,
- NOTIFY_ON_RELEASE,
- };
-
- // An enum describing the events on which a button should be clicked for a
- // given key event.
- enum KeyClickAction {
- CLICK_ON_KEY_PRESS,
- CLICK_ON_KEY_RELEASE,
- CLICK_NONE,
- };
-
- // The menu button's class name.
- static const char kViewClassName[];
-
- static const CustomButton* AsCustomButton(const View* view);
- static CustomButton* AsCustomButton(View* view);
-
- ~CustomButton() override;
-
- // Get/sets the current display state of the button.
- ButtonState state() const { return state_; }
- // Clients passing in STATE_DISABLED should consider calling
- // SetEnabled(false) instead because the enabled flag can affect other things
- // like event dispatching, focus traversals, etc. Calling SetEnabled(false)
- // will also set the state of |this| to STATE_DISABLED.
- void SetState(ButtonState state);
-
- // Starts throbbing. See HoverAnimation for a description of cycles_til_stop.
- // This method does nothing if |animate_on_state_change_| is false.
- void StartThrobbing(int cycles_til_stop);
-
- // Stops throbbing immediately.
- void StopThrobbing();
-
- // Set how long the hover animation will last for.
- void SetAnimationDuration(int duration);
-
- void set_triggerable_event_flags(int triggerable_event_flags) {
- triggerable_event_flags_ = triggerable_event_flags;
- }
- int triggerable_event_flags() const { return triggerable_event_flags_; }
-
- // Sets whether |RequestFocus| should be invoked on a mouse press. The default
- // is false.
- void set_request_focus_on_press(bool value) {
-// On Mac, buttons should not request focus on a mouse press. Hence keep the
-// default value i.e. false.
-#if !defined(OS_MACOSX)
- request_focus_on_press_ = value;
-#endif
- }
-
- bool request_focus_on_press() const { return request_focus_on_press_; }
-
- // See description above field.
- void set_animate_on_state_change(bool value) {
- animate_on_state_change_ = value;
- }
-
- // Sets the event on which the button should notify its listener.
- void set_notify_action(NotifyAction notify_action) {
- notify_action_ = notify_action;
- }
-
- void set_hide_ink_drop_when_showing_context_menu(
- bool hide_ink_drop_when_showing_context_menu) {
- hide_ink_drop_when_showing_context_menu_ =
- hide_ink_drop_when_showing_context_menu;
- }
-
- void set_ink_drop_base_color(SkColor color) { ink_drop_base_color_ = color; }
- void set_has_ink_drop_action_on_click(bool has_ink_drop_action_on_click) {
- has_ink_drop_action_on_click_ = has_ink_drop_action_on_click;
- }
-
- void SetHotTracked(bool is_hot_tracked);
- bool IsHotTracked() const;
-
- void SetFocusPainter(std::unique_ptr<Painter> focus_painter);
-
- // Overridden from View:
- void OnEnabledChanged() override;
- const char* GetClassName() const override;
- bool OnMousePressed(const ui::MouseEvent& event) override;
- bool OnMouseDragged(const ui::MouseEvent& event) override;
- void OnMouseReleased(const ui::MouseEvent& event) override;
- void OnMouseCaptureLost() override;
- void OnMouseEntered(const ui::MouseEvent& event) override;
- void OnMouseExited(const ui::MouseEvent& event) override;
- void OnMouseMoved(const ui::MouseEvent& event) override;
- bool OnKeyPressed(const ui::KeyEvent& event) override;
- bool OnKeyReleased(const ui::KeyEvent& event) override;
- void OnGestureEvent(ui::GestureEvent* event) override;
- bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
- bool SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) override;
- void ShowContextMenu(const gfx::Point& p,
- ui::MenuSourceType source_type) override;
- void OnDragDone() override;
- // Instead of overriding this, subclasses that want custom painting should use
- // PaintButtonContents.
- void OnPaint(gfx::Canvas* canvas) final;
- void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
- void VisibilityChanged(View* starting_from, bool is_visible) override;
-
- // Overridden from InkDropHostView:
- std::unique_ptr<InkDrop> CreateInkDrop() override;
- SkColor GetInkDropBaseColor() const override;
-
- // Overridden from gfx::AnimationDelegate:
- void AnimationProgressed(const gfx::Animation* animation) override;
-
- // Overridden from View:
- void ViewHierarchyChanged(
- const ViewHierarchyChangedDetails& details) override;
- void OnFocus() override;
- void OnBlur() override;
-
- protected:
- // Construct the Button with a Listener. See comment for Button's ctor.
- explicit CustomButton(ButtonListener* listener);
-
- // Invoked from SetState() when SetState() is passed a value that differs from
- // the current node_data. CustomButton's implementation of StateChanged() does
- // nothing; this method is provided for subclasses that wish to do something
- // on state changes.
- virtual void StateChanged(ButtonState old_state);
-
- // Returns true if the event is one that can trigger notifying the listener.
- // This implementation returns true if the left mouse button is down.
- virtual bool IsTriggerableEvent(const ui::Event& event);
-
- // Returns true if the ink drop should be updated by CustomButton when
- // OnClickCanceled() is called. This method is provided for subclasses.
- // If the method is overriden and returns false, the subclass is responsible
- // will be responsible for updating the ink drop.
- virtual bool ShouldUpdateInkDropOnClickCanceled() const;
-
- // Returns true if the button should become pressed when the user
- // holds the mouse down over the button. For this implementation,
- // we simply return IsTriggerableEvent(event).
- virtual bool ShouldEnterPushedState(const ui::Event& event);
-
- // Override to paint custom button contents. Any background or border set on
- // the view will be painted before this is called and |focus_painter_| will be
- // painted afterwards.
- virtual void PaintButtonContents(gfx::Canvas* canvas);
-
- // Returns true if the button should enter hovered state; that is, if the
- // mouse is over the button, and no other window has capture (which would
- // prevent the button from receiving MouseExited events and updating its
- // node_data). This does not take into account enabled node_data.
- bool ShouldEnterHoveredState();
-
- // Overridden from Button:
- void NotifyClick(const ui::Event& event) override;
- void OnClickCanceled(const ui::Event& event) override;
-
- const gfx::ThrobAnimation& hover_animation() const {
- return hover_animation_;
- }
-
- private:
- FRIEND_TEST_ALL_PREFIXES(BlueButtonTest, Border);
-
- ButtonState state_;
-
- gfx::ThrobAnimation hover_animation_;
-
- // Should we animate when the state changes?
- bool animate_on_state_change_ = false;
-
- // Is the hover animation running because StartThrob was invoked?
- bool is_throbbing_;
-
- // Mouse event flags which can trigger button actions.
- int triggerable_event_flags_;
-
- // See description above setter.
- bool request_focus_on_press_;
-
- // The event on which the button should notify its listener.
- NotifyAction notify_action_;
-
- // True when a button click should trigger an animation action on
- // ink_drop_delegate().
- bool has_ink_drop_action_on_click_;
-
- // When true, the ink drop ripple and hover will be hidden prior to showing
- // the context menu.
- bool hide_ink_drop_when_showing_context_menu_;
-
- // The color of the ripple and hover.
- SkColor ink_drop_base_color_;
-
- std::unique_ptr<Painter> focus_painter_;
-
- DISALLOW_COPY_AND_ASSIGN(CustomButton);
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_CONTROLS_BUTTON_CUSTOM_BUTTON_H_
diff --git a/chromium/ui/views/controls/button/image_button.cc b/chromium/ui/views/controls/button/image_button.cc
index 49e6d5fcf23..86da89c1729 100644
--- a/chromium/ui/views/controls/button/image_button.cc
+++ b/chromium/ui/views/controls/button/image_button.cc
@@ -29,7 +29,7 @@ const char ImageButton::kViewClassName[] = "ImageButton";
// ImageButton, public:
ImageButton::ImageButton(ButtonListener* listener)
- : CustomButton(listener),
+ : Button(listener),
h_alignment_(ALIGN_LEFT),
v_alignment_(ALIGN_TOP),
draw_image_mirrored_(false) {
@@ -112,6 +112,19 @@ gfx::Size ImageButton::CalculatePreferredSize() const {
return size;
}
+views::PaintInfo::ScaleType ImageButton::GetPaintScaleType() const {
+ // ImageButton contains an image which is rastered at the device scale factor.
+ // By default, the paint commands are recorded at a scale factor slighlty
+ // 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 and 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 ImageButton::PaintButtonContents(gfx::Canvas* canvas) {
// TODO(estade|tdanderson|bruthig): The ink drop layer should be positioned
// behind the button's image which means the image needs to be painted to its
diff --git a/chromium/ui/views/controls/button/image_button.h b/chromium/ui/views/controls/button/image_button.h
index 419a5176eb0..61c0ca338c1 100644
--- a/chromium/ui/views/controls/button/image_button.h
+++ b/chromium/ui/views/controls/button/image_button.h
@@ -11,7 +11,7 @@
#include "base/macros.h"
#include "ui/base/layout.h"
#include "ui/gfx/image/image_skia.h"
-#include "ui/views/controls/button/custom_button.h"
+#include "ui/views/controls/button/button.h"
namespace views {
@@ -19,7 +19,7 @@ namespace views {
// Note that this type of button is not focusable by default and will not be
// part of the focus chain, unless in accessibility mode. Call
// SetFocusForPlatform() to make it part of the focus chain.
-class VIEWS_EXPORT ImageButton : public CustomButton {
+class VIEWS_EXPORT ImageButton : public Button {
public:
static const char kViewClassName[];
@@ -72,9 +72,10 @@ class VIEWS_EXPORT ImageButton : public CustomButton {
// Overridden from View:
const char* GetClassName() const override;
gfx::Size CalculatePreferredSize() const override;
+ views::PaintInfo::ScaleType GetPaintScaleType() const override;
protected:
- // Overridden from CustomButton:
+ // Overridden from Button:
void PaintButtonContents(gfx::Canvas* canvas) override;
// Returns the image to paint. This is invoked from paint and returns a value
diff --git a/chromium/ui/views/controls/button/image_button_factory.cc b/chromium/ui/views/controls/button/image_button_factory.cc
index e1cafa904e0..6e7ddda2763 100644
--- a/chromium/ui/views/controls/button/image_button_factory.cc
+++ b/chromium/ui/views/controls/button/image_button_factory.cc
@@ -8,7 +8,7 @@
#include "ui/gfx/paint_vector_icon.h"
#include "ui/gfx/vector_icon_types.h"
#include "ui/views/border.h"
-#include "ui/views/controls/button/custom_button.h"
+#include "ui/views/controls/button/button.h"
#include "ui/views/controls/button/image_button.h"
#include "ui/views/layout/layout_provider.h"
#include "ui/views/painter.h"
@@ -17,7 +17,7 @@ namespace views {
ImageButton* CreateVectorImageButton(ButtonListener* listener) {
ImageButton* button = new ImageButton(listener);
- button->SetInkDropMode(CustomButton::InkDropMode::ON);
+ button->SetInkDropMode(Button::InkDropMode::ON);
button->set_has_ink_drop_action_on_click(true);
button->SetImageAlignment(ImageButton::ALIGN_CENTER,
ImageButton::ALIGN_MIDDLE);
@@ -33,9 +33,9 @@ void SetImageFromVectorIcon(ImageButton* button,
const SkColor icon_color =
color_utils::DeriveDefaultIconColor(related_text_color);
const SkColor disabled_color = SkColorSetA(icon_color, 0xff / 2);
- button->SetImage(CustomButton::STATE_NORMAL,
+ button->SetImage(Button::STATE_NORMAL,
gfx::CreateVectorIcon(icon, icon_color));
- button->SetImage(CustomButton::STATE_DISABLED,
+ button->SetImage(Button::STATE_DISABLED,
gfx::CreateVectorIcon(icon, disabled_color));
button->set_ink_drop_base_color(icon_color);
}
diff --git a/chromium/ui/views/controls/button/image_button_factory_unittest.cc b/chromium/ui/views/controls/button/image_button_factory_unittest.cc
index f1e4ec7136f..21700f67388 100644
--- a/chromium/ui/views/controls/button/image_button_factory_unittest.cc
+++ b/chromium/ui/views/controls/button/image_button_factory_unittest.cc
@@ -26,8 +26,8 @@ TEST_F(ImageButtonFactoryTest, CreateVectorImageButton) {
TEST_F(ImageButtonFactoryTest, SetImageFromVectorIcon) {
ImageButton* button = CreateVectorImageButton(nullptr);
SetImageFromVectorIcon(button, vector_icons::kCloseIcon, SK_ColorRED);
- EXPECT_FALSE(button->GetImage(CustomButton::STATE_NORMAL).isNull());
- EXPECT_FALSE(button->GetImage(CustomButton::STATE_DISABLED).isNull());
+ EXPECT_FALSE(button->GetImage(Button::STATE_NORMAL).isNull());
+ EXPECT_FALSE(button->GetImage(Button::STATE_DISABLED).isNull());
EXPECT_EQ(color_utils::DeriveDefaultIconColor(SK_ColorRED),
button->GetInkDropBaseColor());
diff --git a/chromium/ui/views/controls/button/image_button_unittest.cc b/chromium/ui/views/controls/button/image_button_unittest.cc
index ccd62cef046..baf9a75d18b 100644
--- a/chromium/ui/views/controls/button/image_button_unittest.cc
+++ b/chromium/ui/views/controls/button/image_button_unittest.cc
@@ -57,7 +57,7 @@ TEST_F(ImageButtonTest, Basics) {
// Set a normal image.
gfx::ImageSkia normal_image = CreateTestImage(10, 20);
- button.SetImage(CustomButton::STATE_NORMAL, &normal_image);
+ button.SetImage(Button::STATE_NORMAL, &normal_image);
// Image uses normal image for painting.
EXPECT_FALSE(button.GetImageToPaint().isNull());
@@ -69,7 +69,7 @@ TEST_F(ImageButtonTest, Basics) {
// Set a pushed image.
gfx::ImageSkia pushed_image = CreateTestImage(11, 21);
- button.SetImage(CustomButton::STATE_PRESSED, &pushed_image);
+ button.SetImage(Button::STATE_PRESSED, &pushed_image);
// By convention, preferred size doesn't change, even though pushed image
// is bigger.
@@ -118,7 +118,7 @@ TEST_F(ImageButtonTest, SetAndGetImage) {
TEST_F(ImageButtonTest, ImagePositionWithBorder) {
ImageButton button(NULL);
gfx::ImageSkia image = CreateTestImage(20, 30);
- button.SetImage(CustomButton::STATE_NORMAL, &image);
+ button.SetImage(Button::STATE_NORMAL, &image);
// The image should be painted at the top-left corner.
EXPECT_EQ(gfx::Point().ToString(),
@@ -152,7 +152,7 @@ TEST_F(ImageButtonTest, ImagePositionWithBorder) {
TEST_F(ImageButtonTest, LeftAlignedMirrored) {
ImageButton button(NULL);
gfx::ImageSkia image = CreateTestImage(20, 30);
- button.SetImage(CustomButton::STATE_NORMAL, &image);
+ button.SetImage(Button::STATE_NORMAL, &image);
button.SetBounds(0, 0, 50, 30);
button.SetImageAlignment(ImageButton::ALIGN_LEFT,
ImageButton::ALIGN_BOTTOM);
@@ -167,7 +167,7 @@ TEST_F(ImageButtonTest, LeftAlignedMirrored) {
TEST_F(ImageButtonTest, RightAlignedMirrored) {
ImageButton button(NULL);
gfx::ImageSkia image = CreateTestImage(20, 30);
- button.SetImage(CustomButton::STATE_NORMAL, &image);
+ button.SetImage(Button::STATE_NORMAL, &image);
button.SetBounds(0, 0, 50, 30);
button.SetImageAlignment(ImageButton::ALIGN_RIGHT,
ImageButton::ALIGN_BOTTOM);
@@ -184,18 +184,18 @@ TEST_F(ImageButtonTest, PreferredSizeInvalidation) {
ImageButton button(nullptr);
gfx::ImageSkia first_image = CreateTestImage(20, 30);
gfx::ImageSkia second_image = CreateTestImage(50, 50);
- button.SetImage(CustomButton::STATE_NORMAL, &first_image);
+ button.SetImage(Button::STATE_NORMAL, &first_image);
parent.AddChildView(&button);
ASSERT_EQ(0, parent.pref_size_changed_calls());
- button.SetImage(CustomButton::STATE_NORMAL, &first_image);
+ button.SetImage(Button::STATE_NORMAL, &first_image);
EXPECT_EQ(0, parent.pref_size_changed_calls());
- button.SetImage(CustomButton::STATE_HOVERED, &second_image);
+ button.SetImage(Button::STATE_HOVERED, &second_image);
EXPECT_EQ(0, parent.pref_size_changed_calls());
// Changing normal state image size leads to a change in preferred size.
- button.SetImage(CustomButton::STATE_NORMAL, &second_image);
+ button.SetImage(Button::STATE_NORMAL, &second_image);
EXPECT_EQ(1, parent.pref_size_changed_calls());
}
diff --git a/chromium/ui/views/controls/button/label_button.cc b/chromium/ui/views/controls/button/label_button.cc
index 1d9e7b82cd5..68be16e39a1 100644
--- a/chromium/ui/views/controls/button/label_button.cc
+++ b/chromium/ui/views/controls/button/label_button.cc
@@ -40,7 +40,7 @@ const char LabelButton::kViewClassName[] = "LabelButton";
LabelButton::LabelButton(ButtonListener* listener,
const base::string16& text,
int button_context)
- : CustomButton(listener),
+ : Button(listener),
image_(new ImageView()),
label_(new LabelButtonLabel(text, button_context)),
ink_drop_container_(new InkDropContainerView()),
@@ -298,7 +298,7 @@ void LabelButton::Layout() {
}
label_->SetBoundsRect(label_bounds);
- CustomButton::Layout();
+ Button::Layout();
}
const char* LabelButton::GetClassName() const {
@@ -306,7 +306,7 @@ const char* LabelButton::GetClassName() const {
}
void LabelButton::EnableCanvasFlippingForRTLUI(bool flip) {
- CustomButton::EnableCanvasFlippingForRTLUI(flip);
+ Button::EnableCanvasFlippingForRTLUI(flip);
image_->EnableCanvasFlippingForRTLUI(flip);
}
@@ -339,13 +339,13 @@ bool LabelButton::ShouldUseFloodFillInkDrop() const {
}
void LabelButton::OnFocus() {
- CustomButton::OnFocus();
+ Button::OnFocus();
// Typically the border renders differently when focused.
SchedulePaint();
}
void LabelButton::OnBlur() {
- CustomButton::OnBlur();
+ Button::OnBlur();
// Typically the border renders differently when focused.
SchedulePaint();
}
@@ -376,7 +376,7 @@ void LabelButton::RemoveInkDropLayer(ui::Layer* ink_drop_layer) {
std::unique_ptr<InkDrop> LabelButton::CreateInkDrop() {
return ShouldUseFloodFillInkDrop() ? CreateDefaultFloodFillInkDropImpl()
- : CustomButton::CreateInkDrop();
+ : Button::CreateInkDrop();
}
std::unique_ptr<views::InkDropRipple> LabelButton::CreateInkDropRipple() const {
diff --git a/chromium/ui/views/controls/button/label_button.h b/chromium/ui/views/controls/button/label_button.h
index 0fb03378c74..bc5190a4bc7 100644
--- a/chromium/ui/views/controls/button/label_button.h
+++ b/chromium/ui/views/controls/button/label_button.h
@@ -13,7 +13,7 @@
#include "base/macros.h"
#include "third_party/skia/include/core/SkColor.h"
#include "ui/gfx/image/image_skia.h"
-#include "ui/views/controls/button/custom_button.h"
+#include "ui/views/controls/button/button.h"
#include "ui/views/controls/image_view.h"
#include "ui/views/controls/label.h"
#include "ui/views/native_theme_delegate.h"
@@ -26,8 +26,7 @@ class LabelButtonBorder;
class LabelButtonLabel;
// LabelButton is a button with text and an icon, it's not focusable by default.
-class VIEWS_EXPORT LabelButton : public CustomButton,
- public NativeThemeDelegate {
+class VIEWS_EXPORT LabelButton : public Button, public NativeThemeDelegate {
public:
// The length of the hover fade animation.
static const int kHoverAnimationDurationMs;
@@ -130,7 +129,7 @@ class VIEWS_EXPORT LabelButton : public CustomButton,
void OnBlur() override;
void OnNativeThemeChanged(const ui::NativeTheme* theme) override;
- // CustomButton:
+ // Button:
void StateChanged(ButtonState old_state) override;
// Fills |params| with information about the button.
@@ -181,7 +180,7 @@ class VIEWS_EXPORT LabelButton : public CustomButton,
void ResetCachedPreferredSize();
// Updates additional state related to focus or default status, rather than
- // merely the CustomButton::state(). E.g. ensures the label text color is
+ // merely the Button::state(). E.g. ensures the label text color is
// correct for the current background.
void ResetLabelEnabledColor();
diff --git a/chromium/ui/views/controls/button/label_button_unittest.cc b/chromium/ui/views/controls/button/label_button_unittest.cc
index 9ba1771edde..74b34b038a5 100644
--- a/chromium/ui/views/controls/button/label_button_unittest.cc
+++ b/chromium/ui/views/controls/button/label_button_unittest.cc
@@ -64,7 +64,7 @@ class LabelButtonTest : public test::WidgetTest {
TestLabelButton* AddStyledButton(const char* label, bool is_default) {
TestLabelButton* button = new TestLabelButton;
button->SetText(ASCIIToUTF16(label));
- button->SetStyleDeprecated(CustomButton::STYLE_BUTTON);
+ button->SetStyleDeprecated(Button::STYLE_BUTTON);
if (is_default)
button->SetIsDefault(true);
button_->GetWidget()->GetContentsView()->AddChildView(button);
@@ -474,7 +474,7 @@ class InkDropLabelButtonTest : public ViewsTestBase {
switches::kTopChromeMD, switches::kTopChromeMDMaterial);
ViewsTestBase::SetUp();
- // Create a widget so that the CustomButton can query the hover state
+ // Create a widget so that the Button can query the hover state
// correctly.
widget_.reset(new Widget);
Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
diff --git a/chromium/ui/views/controls/button/md_text_button.cc b/chromium/ui/views/controls/button/md_text_button.cc
index 114cbe5dae1..5657285f45d 100644
--- a/chromium/ui/views/controls/button/md_text_button.cc
+++ b/chromium/ui/views/controls/button/md_text_button.cc
@@ -6,6 +6,7 @@
#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"
@@ -43,7 +44,7 @@ LabelButton* CreateButton(ButtonListener* listener,
return MdTextButton::Create(listener, text, style::CONTEXT_BUTTON_MD);
LabelButton* button = new LabelButton(listener, text, style::CONTEXT_BUTTON);
- button->SetStyleDeprecated(CustomButton::STYLE_BUTTON);
+ button->SetStyleDeprecated(Button::STYLE_BUTTON);
return button;
}
@@ -243,6 +244,7 @@ void MdTextButton::UpdatePadding() {
void MdTextButton::UpdateColors() {
ui::NativeTheme* theme = GetNativeTheme();
+ bool is_disabled = state() == STATE_DISABLED;
SkColor enabled_text_color = style::GetColor(
label()->text_context(),
is_prominent_ ? style::STYLE_DIALOG_BUTTON_DEFAULT : style::STYLE_PRIMARY,
@@ -250,6 +252,15 @@ void MdTextButton::UpdateColors() {
if (!explicitly_set_normal_color()) {
const auto colors = explicitly_set_colors();
LabelButton::SetEnabledTextColors(enabled_text_color);
+ // Non-prominent, disabled buttons need the disabled color explicitly set.
+ // This ensures that label()->enabled_color() returns the correct color as
+ // the basis for calculating the stroke color. enabled_text_color isn't used
+ // since a descendant could have overridden the label enabled color.
+ if (is_disabled && !is_prominent_) {
+ LabelButton::SetTextColor(STATE_DISABLED,
+ style::GetColor(label()->text_context(),
+ style::STYLE_DISABLED, theme));
+ }
set_explicitly_set_colors(colors);
}
@@ -267,9 +278,10 @@ void MdTextButton::UpdateColors() {
} else if (is_prominent_) {
bg_color = theme->GetSystemColor(
ui::NativeTheme::kColorId_ProminentButtonColor);
- if (state() == STATE_DISABLED)
+ if (is_disabled) {
bg_color = color_utils::BlendTowardOppositeLuma(
bg_color, gfx::kDisabledControlAlpha);
+ }
}
if (state() == STATE_PRESSED) {
@@ -278,19 +290,41 @@ void MdTextButton::UpdateColors() {
bg_color = color_utils::GetResultingPaintColor(shade, bg_color);
}
- // Specified text color: 5a5a5a @ 1.0 alpha
- // Specified stroke color: 000000 @ 0.2 alpha
- // 000000 @ 0.2 is very close to 5a5a5a @ 0.308 (== 0x4e); both are cccccc @
- // 1.0, and this way if NativeTheme changes the button color, the button
- // stroke will also change colors to match.
- SkColor stroke_color =
- is_prominent_ ? SK_ColorTRANSPARENT : SkColorSetA(text_color, 0x4e);
-
- // Disabled, non-prominent buttons need their stroke lightened. Prominent
- // buttons need it left at SK_ColorTRANSPARENT from above.
- if (state() == STATE_DISABLED && !is_prominent_) {
- stroke_color = color_utils::BlendTowardOppositeLuma(
- stroke_color, gfx::kDisabledControlAlpha);
+ SkColor stroke_color;
+ if (is_prominent_) {
+ stroke_color = SK_ColorTRANSPARENT;
+ } else {
+ int stroke_alpha;
+ if (is_disabled) {
+ // Disabled, non-prominent buttons need a lighter stroke. This alpha
+ // value will take the disabled button colors, a1a192 @ 1.0 alpha for
+ // non-Harmony, 9e9e9e @ 1.0 alpha for Harmony and turn it into
+ // e6e6e6 @ 1.0 alpha (or very close to it) or an effective 000000 @ 0.1
+ // alpha for the stroke color. The same alpha value will work with both
+ // Harmony and non-Harmony colors.
+ stroke_alpha = 0x43;
+ } else {
+ // These alpha values will take the enabled button colors, 5a5a5a @ 1.0
+ // alpha for non-Harmony, 757575 @ 1.0 alpha for Harmony and turn it into
+ // an effective b2b2b2 @ 1.0 alpha or 000000 @ 0.3 for the stroke_color.
+ stroke_alpha = UseMaterialSecondaryButtons() ? 0x8f : 0x77;
+#if defined(OS_MACOSX)
+ // Without full secondary UI MD support, the text color is solid black,
+ // and so the border is too dark on Mac. On Retina it looks OK, so
+ // heuristically determine the scale factor as well.
+ if (!ui::MaterialDesignController::IsSecondaryUiMaterial()) {
+ // The Compositor may only be set when attached to a Widget. But, since
+ // that also determines the theme, UpdateColors() will always be called
+ // after attaching to a Widget.
+ // TODO(tapted): Move this into SolidRoundRectPainter if we like this
+ // logic for Harmony.
+ auto* compositor = layer()->GetCompositor();
+ if (compositor && compositor->device_scale_factor() == 1)
+ stroke_alpha = 0x4d; // Chosen to match full secondary UI MD (0.3).
+ }
+#endif
+ }
+ stroke_color = SkColorSetA(text_color, stroke_alpha);
}
DCHECK_EQ(SK_AlphaOPAQUE, static_cast<int>(SkColorGetA(bg_color)));
diff --git a/chromium/ui/views/controls/button/menu_button.cc b/chromium/ui/views/controls/button/menu_button.cc
index 0e4194e4625..8a823199304 100644
--- a/chromium/ui/views/controls/button/menu_button.cc
+++ b/chromium/ui/views/controls/button/menu_button.cc
@@ -282,14 +282,14 @@ bool MenuButton::OnKeyPressed(const ui::KeyEvent& event) {
}
bool MenuButton::OnKeyReleased(const ui::KeyEvent& event) {
- // Override CustomButton's implementation, which presses the button when
+ // Override Button's implementation, which presses the button when
// you press space and clicks it when you release space. For a MenuButton
// we always activate the menu on key press.
return false;
}
void MenuButton::GetAccessibleNodeData(ui::AXNodeData* node_data) {
- CustomButton::GetAccessibleNodeData(node_data);
+ Button::GetAccessibleNodeData(node_data);
node_data->role = ui::AX_ROLE_POP_UP_BUTTON;
node_data->AddState(ui::AX_STATE_HASPOPUP);
if (enabled()) {
diff --git a/chromium/ui/views/controls/button/menu_button.h b/chromium/ui/views/controls/button/menu_button.h
index 9adbee93848..e38200b8a43 100644
--- a/chromium/ui/views/controls/button/menu_button.h
+++ b/chromium/ui/views/controls/button/menu_button.h
@@ -95,7 +95,7 @@ class VIEWS_EXPORT MenuButton : public LabelButton {
// Overridden from LabelButton:
gfx::Rect GetChildAreaBounds() override;
- // Overridden from CustomButton:
+ // Overridden from Button:
bool IsTriggerableEvent(const ui::Event& event) override;
bool ShouldEnterPushedState(const ui::Event& event) override;
void StateChanged(ButtonState old_state) override;
diff --git a/chromium/ui/views/controls/button/menu_button_unittest.cc b/chromium/ui/views/controls/button/menu_button_unittest.cc
index 21eb775c6e5..500bbc91a5d 100644
--- a/chromium/ui/views/controls/button/menu_button_unittest.cc
+++ b/chromium/ui/views/controls/button/menu_button_unittest.cc
@@ -21,6 +21,7 @@
#if defined(USE_AURA)
#include "ui/aura/client/drag_drop_client.h"
+#include "ui/aura/client/drag_drop_client_observer.h"
#include "ui/events/event.h"
#include "ui/events/event_handler.h"
#endif
@@ -134,9 +135,9 @@ class TestButtonListener : public ButtonListener {
void ButtonPressed(Button* sender, const ui::Event& event) override {
last_sender_ = sender;
- CustomButton* custom_button = CustomButton::AsCustomButton(sender);
- DCHECK(custom_button);
- last_sender_state_ = custom_button->state();
+ Button* button = Button::AsButton(sender);
+ DCHECK(button);
+ last_sender_state_ = button->state();
last_event_type_ = event.type();
}
@@ -162,9 +163,9 @@ class TestMenuButtonListener : public MenuButtonListener {
const gfx::Point& point,
const ui::Event* event) override {
last_source_ = source;
- CustomButton* custom_button = CustomButton::AsCustomButton(source);
- DCHECK(custom_button);
- last_source_state_ = custom_button->state();
+ Button* button = Button::AsButton(source);
+ DCHECK(button);
+ last_source_state_ = button->state();
}
View* last_source() { return last_source_; }
@@ -253,6 +254,9 @@ class TestDragDropClient : public aura::client::DragDropClient,
ui::DragDropTypes::DragEventSource source) override;
void DragCancel() override;
bool IsDragDropInProgress() override;
+ void AddObserver(aura::client::DragDropClientObserver* observer) override {}
+ void RemoveObserver(aura::client::DragDropClientObserver* observer) override {
+ }
// ui::EventHandler:
void OnMouseEvent(ui::MouseEvent* event) override;
diff --git a/chromium/ui/views/controls/button/radio_button_unittest.cc b/chromium/ui/views/controls/button/radio_button_unittest.cc
new file mode 100644
index 00000000000..c68b6ad15ec
--- /dev/null
+++ b/chromium/ui/views/controls/button/radio_button_unittest.cc
@@ -0,0 +1,96 @@
+// 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/views/controls/button/radio_button.h"
+
+#include "base/strings/utf_string_conversions.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/views/test/views_test_base.h"
+
+namespace {
+// Group ID of the test radio buttons.
+constexpr int kGroup = 1;
+} // namespace
+
+namespace views {
+
+class RadioButtonTest : public ViewsTestBase {
+ public:
+ RadioButtonTest() : button_container_(nullptr) {}
+
+ void SetUp() override {
+ ViewsTestBase::SetUp();
+
+ // Create a Widget so the radio buttons can find their group siblings.
+ widget_ = base::MakeUnique<Widget>();
+ Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+ params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ widget_->Init(params);
+ widget_->Show();
+
+ button_container_ = new View();
+ widget_->SetContentsView(button_container_);
+ }
+
+ void TearDown() override {
+ button_container_ = nullptr;
+ widget_.reset();
+ ViewsTestBase::TearDown();
+ }
+
+ protected:
+ View& button_container() { return *button_container_; }
+
+ private:
+ View* button_container_;
+ std::unique_ptr<Widget> widget_;
+
+ DISALLOW_COPY_AND_ASSIGN(RadioButtonTest);
+};
+
+TEST_F(RadioButtonTest, Basics) {
+ RadioButton* button1 = new RadioButton(base::ASCIIToUTF16("Blah"), kGroup);
+ button_container().AddChildView(button1);
+ RadioButton* button2 = new RadioButton(base::ASCIIToUTF16("Blah"), kGroup);
+ button_container().AddChildView(button2);
+
+ button1->SetChecked(true);
+ EXPECT_TRUE(button1->checked());
+ EXPECT_FALSE(button2->checked());
+
+ button2->SetChecked(true);
+ EXPECT_FALSE(button1->checked());
+ EXPECT_TRUE(button2->checked());
+}
+
+TEST_F(RadioButtonTest, Focus) {
+ RadioButton* button1 = new RadioButton(base::ASCIIToUTF16("Blah"), kGroup);
+ button_container().AddChildView(button1);
+ RadioButton* button2 = new RadioButton(base::ASCIIToUTF16("Blah"), kGroup);
+ button_container().AddChildView(button2);
+
+ // Tabbing through only focuses the checked button.
+ button1->SetChecked(true);
+ auto* focus_manager = button_container().GetFocusManager();
+ ui::KeyEvent pressed_tab(ui::ET_KEY_PRESSED, ui::VKEY_TAB, ui::EF_NONE);
+ focus_manager->OnKeyEvent(pressed_tab);
+ EXPECT_EQ(button1, focus_manager->GetFocusedView());
+ focus_manager->OnKeyEvent(pressed_tab);
+ EXPECT_EQ(button1, focus_manager->GetFocusedView());
+
+ // The checked button can be moved using arrow keys.
+ focus_manager->OnKeyEvent(
+ ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_DOWN, ui::EF_NONE));
+ EXPECT_EQ(button2, focus_manager->GetFocusedView());
+ EXPECT_FALSE(button1->checked());
+ EXPECT_TRUE(button2->checked());
+
+ focus_manager->OnKeyEvent(
+ ui::KeyEvent(ui::ET_KEY_PRESSED, ui::VKEY_UP, ui::EF_NONE));
+ EXPECT_EQ(button1, focus_manager->GetFocusedView());
+ EXPECT_TRUE(button1->checked());
+ EXPECT_FALSE(button2->checked());
+}
+
+} // namespace views
diff --git a/chromium/ui/views/controls/button/toggle_button.cc b/chromium/ui/views/controls/button/toggle_button.cc
index 5585524516d..b62c2de33e0 100644
--- a/chromium/ui/views/controls/button/toggle_button.cc
+++ b/chromium/ui/views/controls/button/toggle_button.cc
@@ -110,10 +110,7 @@ class ToggleButton::ThumbView : public InkDropHostView {
const char ToggleButton::kViewClassName[] = "ToggleButton";
ToggleButton::ToggleButton(ButtonListener* listener)
- : CustomButton(listener),
- is_on_(false),
- slide_animation_(this),
- thumb_view_(new ThumbView()) {
+ : Button(listener), thumb_view_(new ThumbView()) {
slide_animation_.SetSlideDuration(80 /* ms */);
slide_animation_.SetTweenType(gfx::Tween::LINEAR);
AddChildView(thumb_view_);
@@ -185,6 +182,10 @@ const char* ToggleButton::GetClassName() const {
return kViewClassName;
}
+bool ToggleButton::CanAcceptEvent(const ui::Event& event) {
+ return accepts_events_ && Button::CanAcceptEvent(event);
+}
+
void ToggleButton::OnBoundsChanged(const gfx::Rect& previous_bounds) {
UpdateThumb();
}
@@ -194,7 +195,7 @@ void ToggleButton::OnNativeThemeChanged(const ui::NativeTheme* theme) {
}
void ToggleButton::GetAccessibleNodeData(ui::AXNodeData* node_data) {
- CustomButton::GetAccessibleNodeData(node_data);
+ Button::GetAccessibleNodeData(node_data);
node_data->role = ui::AX_ROLE_SWITCH;
const ui::AXCheckedState checked_state =
@@ -202,9 +203,32 @@ void ToggleButton::GetAccessibleNodeData(ui::AXNodeData* node_data) {
node_data->AddIntAttribute(ui::AX_ATTR_CHECKED_STATE, checked_state);
}
+void ToggleButton::OnFocus() {
+ Button::OnFocus();
+ AnimateInkDrop(views::InkDropState::ACTION_PENDING, nullptr);
+}
+
+void ToggleButton::OnBlur() {
+ Button::OnBlur();
+
+ // The ink drop may have already gone away if the user clicked after focusing.
+ if (GetInkDrop()->GetTargetInkDropState() ==
+ views::InkDropState::ACTION_PENDING) {
+ AnimateInkDrop(views::InkDropState::ACTION_TRIGGERED, nullptr);
+ }
+}
+
void ToggleButton::NotifyClick(const ui::Event& event) {
SetIsOn(!is_on(), true);
- CustomButton::NotifyClick(event);
+
+ // Skip over Button::NotifyClick, to customize the ink drop animation.
+ // Leave the ripple in place when the button is activated via the keyboard.
+ if (!event.IsKeyEvent()) {
+ AnimateInkDrop(InkDropState::ACTION_TRIGGERED,
+ ui::LocatedEvent::FromIfValid(&event));
+ }
+
+ Button::NotifyClick(event);
}
void ToggleButton::PaintButtonContents(gfx::Canvas* canvas) {
@@ -234,8 +258,7 @@ void ToggleButton::RemoveInkDropLayer(ui::Layer* ink_drop_layer) {
}
std::unique_ptr<InkDrop> ToggleButton::CreateInkDrop() {
- std::unique_ptr<InkDropImpl> ink_drop =
- CustomButton::CreateDefaultInkDropImpl();
+ std::unique_ptr<InkDropImpl> ink_drop = Button::CreateDefaultInkDropImpl();
ink_drop->SetShowHighlightOnHover(false);
return std::move(ink_drop);
}
@@ -247,7 +270,7 @@ std::unique_ptr<InkDropRipple> ToggleButton::CreateInkDropRipple() const {
}
SkColor ToggleButton::GetInkDropBaseColor() const {
- return GetTrackColor(is_on());
+ return GetTrackColor(is_on() || HasFocus());
}
void ToggleButton::AnimationProgressed(const gfx::Animation* animation) {
@@ -258,7 +281,7 @@ void ToggleButton::AnimationProgressed(const gfx::Animation* animation) {
SchedulePaint();
return;
}
- CustomButton::AnimationProgressed(animation);
+ Button::AnimationProgressed(animation);
}
} // namespace views
diff --git a/chromium/ui/views/controls/button/toggle_button.h b/chromium/ui/views/controls/button/toggle_button.h
index 7b356885031..87b97add21f 100644
--- a/chromium/ui/views/controls/button/toggle_button.h
+++ b/chromium/ui/views/controls/button/toggle_button.h
@@ -6,14 +6,14 @@
#define UI_VIEWS_CONTROLS_BUTTON_TOGGLE_BUTTON_H_
#include "ui/gfx/animation/slide_animation.h"
-#include "ui/views/controls/button/custom_button.h"
+#include "ui/views/controls/button/button.h"
namespace views {
// This view presents a button that has two states: on and off. This is similar
// to a checkbox but has no text and looks more like a two-state horizontal
// slider.
-class VIEWS_EXPORT ToggleButton : public CustomButton {
+class VIEWS_EXPORT ToggleButton : public Button {
public:
static const char kViewClassName[];
@@ -23,6 +23,10 @@ class VIEWS_EXPORT ToggleButton : public CustomButton {
void SetIsOn(bool is_on, bool animate);
bool is_on() const { return is_on_; }
+ void set_accepts_events(bool accepts_events) {
+ accepts_events_ = accepts_events;
+ }
+
// views::View:
gfx::Size CalculatePreferredSize() const override;
@@ -43,11 +47,14 @@ class VIEWS_EXPORT ToggleButton : public CustomButton {
// views::View:
const char* GetClassName() const override;
+ bool CanAcceptEvent(const ui::Event& event) override;
void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
void OnNativeThemeChanged(const ui::NativeTheme* theme) override;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
+ void OnFocus() override;
+ void OnBlur() override;
- // CustomButton:
+ // Button:
void NotifyClick(const ui::Event& event) override;
void PaintButtonContents(gfx::Canvas* canvas) override;
void AddInkDropLayer(ui::Layer* ink_drop_layer) override;
@@ -59,10 +66,14 @@ class VIEWS_EXPORT ToggleButton : public CustomButton {
// gfx::AnimationDelegate:
void AnimationProgressed(const gfx::Animation* animation) override;
- bool is_on_;
- gfx::SlideAnimation slide_animation_;
+ bool is_on_ = false;
+ gfx::SlideAnimation slide_animation_{this};
ThumbView* thumb_view_;
+ // When false, this button won't accept input. Different from View::SetEnabled
+ // in that the view retains focus when this is false but not when disabled.
+ bool accepts_events_ = true;
+
DISALLOW_COPY_AND_ASSIGN(ToggleButton);
};
diff --git a/chromium/ui/views/controls/button/toggle_button_unittest.cc b/chromium/ui/views/controls/button/toggle_button_unittest.cc
index 8ea3f033795..ac6191418b0 100644
--- a/chromium/ui/views/controls/button/toggle_button_unittest.cc
+++ b/chromium/ui/views/controls/button/toggle_button_unittest.cc
@@ -9,7 +9,7 @@
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
#include "ui/events/event_utils.h"
-#include "ui/views/style/platform_style.h"
+#include "ui/events/test/event_generator.h"
#include "ui/views/test/views_test_base.h"
namespace views {
@@ -25,6 +25,8 @@ class TestToggleButton : public ToggleButton {
SetInkDropMode(InkDropMode::OFF);
}
+ using View::Focus;
+
protected:
// ToggleButton:
void AddInkDropLayer(ui::Layer* ink_drop_layer) override {
@@ -54,7 +56,8 @@ class ToggleButtonTest : public ViewsTestBase {
// Create a widget so that the ToggleButton can query the hover state
// correctly.
widget_.reset(new Widget);
- Widget::InitParams params = CreateParams(Widget::InitParams::TYPE_POPUP);
+ Widget::InitParams params =
+ CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
params.bounds = gfx::Rect(0, 0, 650, 650);
widget_->Init(params);
@@ -91,13 +94,55 @@ TEST_F(ToggleButtonTest, ToggleButtonDestroyed) {
button()->OnMousePressed(ui::MouseEvent(
ui::ET_MOUSE_PRESSED, center, center, ui::EventTimeForNow(),
ui::EF_LEFT_MOUSE_BUTTON, ui::EF_LEFT_MOUSE_BUTTON));
- // On platforms with no ripples, there should never be an ink drop layer.
- if (PlatformStyle::kUseRipples)
- EXPECT_EQ(1, counter());
- else
- EXPECT_EQ(0, counter());
+ EXPECT_EQ(1, counter());
delete button();
EXPECT_EQ(0, counter());
}
+// Make sure nothing bad happens when the widget is destroyed while the
+// ToggleButton has focus (and is showing a ripple).
+TEST_F(ToggleButtonTest, ShutdownWithFocus) {
+ button()->RequestFocus();
+ EXPECT_EQ(1, counter());
+}
+
+// Verify that ToggleButton::accepts_events_ works as expected.
+TEST_F(ToggleButtonTest, AcceptEvents) {
+ EXPECT_FALSE(button()->is_on());
+ ui::test::EventGenerator generator(widget()->GetNativeWindow());
+
+ // Clicking toggles.
+ generator.ClickLeftButton();
+ EXPECT_TRUE(button()->is_on());
+ generator.ClickLeftButton();
+ EXPECT_FALSE(button()->is_on());
+
+ // Spacebar toggles.
+ button()->RequestFocus();
+ generator.PressKey(ui::VKEY_SPACE, ui::EF_NONE);
+ generator.ReleaseKey(ui::VKEY_SPACE, ui::EF_NONE);
+ EXPECT_TRUE(button()->is_on());
+ generator.PressKey(ui::VKEY_SPACE, ui::EF_NONE);
+ generator.ReleaseKey(ui::VKEY_SPACE, ui::EF_NONE);
+ EXPECT_FALSE(button()->is_on());
+
+ // Spacebar and clicking do nothing when not accepting events, but focus is
+ // not affected.
+ button()->set_accepts_events(false);
+ EXPECT_TRUE(button()->HasFocus());
+ generator.PressKey(ui::VKEY_SPACE, ui::EF_NONE);
+ generator.ReleaseKey(ui::VKEY_SPACE, ui::EF_NONE);
+ EXPECT_FALSE(button()->is_on());
+ generator.ClickLeftButton();
+ EXPECT_FALSE(button()->is_on());
+
+ // Re-enable events and clicking and spacebar resume working.
+ button()->set_accepts_events(true);
+ generator.PressKey(ui::VKEY_SPACE, ui::EF_NONE);
+ generator.ReleaseKey(ui::VKEY_SPACE, ui::EF_NONE);
+ EXPECT_TRUE(button()->is_on());
+ generator.ClickLeftButton();
+ EXPECT_FALSE(button()->is_on());
+}
+
} // namespace views
diff --git a/chromium/ui/views/controls/combobox/combobox.cc b/chromium/ui/views/controls/combobox/combobox.cc
index 195114dc2d6..b489f9722d3 100644
--- a/chromium/ui/views/controls/combobox/combobox.cc
+++ b/chromium/ui/views/controls/combobox/combobox.cc
@@ -32,7 +32,7 @@
#include "ui/views/animation/ink_drop_highlight.h"
#include "ui/views/animation/ink_drop_impl.h"
#include "ui/views/background.h"
-#include "ui/views/controls/button/custom_button.h"
+#include "ui/views/controls/button/button.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/combobox/combobox_listener.h"
#include "ui/views/controls/focus_ring.h"
@@ -119,10 +119,10 @@ gfx::Rect PositionArrowWithinContainer(const gfx::Rect& container_bounds,
}
// The transparent button which holds a button state but is not rendered.
-class TransparentButton : public CustomButton {
+class TransparentButton : public Button {
public:
TransparentButton(ButtonListener* listener, bool animate_state_change)
- : CustomButton(listener) {
+ : Button(listener) {
set_animate_on_state_change(animate_state_change);
if (animate_state_change)
SetAnimationDuration(LabelButton::kHoverAnimationDurationMs);
@@ -142,7 +142,7 @@ class TransparentButton : public CustomButton {
// platforms they do.
parent()->RequestFocus();
#endif
- return CustomButton::OnMousePressed(mouse_event);
+ return Button::OnMousePressed(mouse_event);
}
double GetAnimationValue() const {
diff --git a/chromium/ui/views/controls/combobox/combobox.h b/chromium/ui/views/controls/combobox/combobox.h
index 42a2051fdf8..511cad8bece 100644
--- a/chromium/ui/views/controls/combobox/combobox.h
+++ b/chromium/ui/views/controls/combobox/combobox.h
@@ -27,7 +27,7 @@ class ComboboxTestApi;
}
class ComboboxListener;
-class CustomButton;
+class Button;
class MenuRunner;
class Painter;
class PrefixSelector;
@@ -214,8 +214,8 @@ class VIEWS_EXPORT Combobox : public View,
// STYLE_NOTIFY_ON_CLICK, a Combobox renders the button images according to
// these button states.
// The base View takes the ownerships of these as child views.
- CustomButton* text_button_;
- CustomButton* arrow_button_;
+ Button* text_button_;
+ Button* arrow_button_;
// Set while the dropdown is showing. Ensures the menu is closed if |this| is
// destroyed.
diff --git a/chromium/ui/views/controls/focusable_border.cc b/chromium/ui/views/controls/focusable_border.cc
index e96914d5697..61166088b75 100644
--- a/chromium/ui/views/controls/focusable_border.cc
+++ b/chromium/ui/views/controls/focusable_border.cc
@@ -36,10 +36,6 @@ void FocusableBorder::SetColorId(
}
void FocusableBorder::Paint(const View& view, gfx::Canvas* canvas) {
- // In harmony, the focus indicator is a FocusRing.
- if (ui::MaterialDesignController::IsSecondaryUiMaterial() && view.HasFocus())
- return;
-
cc::PaintFlags flags;
flags.setStyle(cc::PaintFlags::kStroke_Style);
flags.setColor(GetCurrentColor(view));
@@ -85,10 +81,14 @@ void FocusableBorder::SetInsets(int top, int left, int bottom, int right) {
SkColor FocusableBorder::GetCurrentColor(const View& view) const {
ui::NativeTheme::ColorId color_id =
ui::NativeTheme::kColorId_UnfocusedBorderColor;
- if (override_color_id_)
+ if (override_color_id_) {
color_id = *override_color_id_;
- else if (view.HasFocus())
+ } else if (view.HasFocus() &&
+ !ui::MaterialDesignController::IsSecondaryUiMaterial()) {
+ // Note with --secondary-ui-md there is a FocusRing indicator, so the border
+ // retains its unfocused color.
color_id = ui::NativeTheme::kColorId_FocusedBorderColor;
+ }
SkColor color = view.GetNativeTheme()->GetSystemColor(color_id);
if (ui::MaterialDesignController::IsSecondaryUiMaterial() &&
diff --git a/chromium/ui/views/controls/image_view.cc b/chromium/ui/views/controls/image_view.cc
index a1ca6ee4433..bc748e3552d 100644
--- a/chromium/ui/views/controls/image_view.cc
+++ b/chromium/ui/views/controls/image_view.cc
@@ -180,6 +180,19 @@ gfx::Size ImageView::CalculatePreferredSize() const {
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 slighlty
+ // 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_ = NULL;
diff --git a/chromium/ui/views/controls/image_view.h b/chromium/ui/views/controls/image_view.h
index 393b934592a..e850c033cb2 100644
--- a/chromium/ui/views/controls/image_view.h
+++ b/chromium/ui/views/controls/image_view.h
@@ -79,6 +79,7 @@ class VIEWS_EXPORT ImageView : public View {
bool GetTooltipText(const gfx::Point& p,
base::string16* tooltip) const override;
gfx::Size CalculatePreferredSize() const override;
+ views::PaintInfo::ScaleType GetPaintScaleType() const override;
private:
void OnPaintImage(gfx::Canvas* canvas);
diff --git a/chromium/ui/views/controls/label.cc b/chromium/ui/views/controls/label.cc
index 05c933848e5..16aec515d72 100644
--- a/chromium/ui/views/controls/label.cc
+++ b/chromium/ui/views/controls/label.cc
@@ -187,6 +187,14 @@ void Label::SetMultiLine(bool multi_line) {
ResetLayout();
}
+void Label::SetMaxLines(int max_lines) {
+ if (max_lines_ == max_lines)
+ return;
+ is_first_paint_text_ = true;
+ max_lines_ = max_lines;
+ ResetLayout();
+}
+
void Label::SetObscured(bool obscured) {
if (this->obscured() == obscured)
return;
@@ -329,6 +337,8 @@ gfx::Size Label::CalculatePreferredSize() const {
if (multi_line() && max_width_ != 0 && max_width_ < size.width())
return gfx::Size(max_width_, GetHeightForWidth(max_width_));
+ if (multi_line() && max_lines() > 0)
+ return gfx::Size(size.width(), GetHeightForWidth(size.width()));
return size;
}
@@ -356,8 +366,9 @@ int Label::GetHeightForWidth(int w) const {
w -= GetInsets().width();
int height = 0;
+ int base_line_height = std::max(line_height(), font_list().GetHeight());
if (!multi_line() || text().empty() || w <= 0) {
- height = std::max(line_height(), font_list().GetHeight());
+ height = base_line_height;
} else if (render_text_->MultilineSupported()) {
// SetDisplayRect() has a side effect for later calls of GetStringSize().
// Be careful to invoke |render_text_->SetDisplayRect(gfx::Rect())| to
@@ -366,7 +377,12 @@ int Label::GetHeightForWidth(int w) const {
// managers invoke GetHeightForWidth() for the same width multiple times
// and |render_text_| can cache the height.
render_text_->SetDisplayRect(gfx::Rect(0, 0, w, 0));
- height = render_text_->GetStringSize().height();
+ int string_height = render_text_->GetStringSize().height();
+ // Cap the number of lines to |max_lines()| if multi-line and non-zero
+ // |max_lines()|.
+ height = multi_line() && max_lines() > 0
+ ? std::min(max_lines() * base_line_height, string_height)
+ : string_height;
} else {
std::vector<base::string16> lines = GetLinesForWidth(w);
height = lines.size() * std::max(line_height(), font_list().GetHeight());
@@ -819,6 +835,7 @@ void Label::Init(const base::string16& text, const gfx::FontList& font_list) {
subpixel_rendering_enabled_ = true;
auto_color_readability_ = true;
multi_line_ = false;
+ max_lines_ = 0;
UpdateColorsFromTheme(GetNativeTheme());
handles_tooltips_ = true;
collapse_when_hidden_ = false;
@@ -867,15 +884,17 @@ void Label::MaybeBuildRenderTextLines() const {
rtl ? gfx::DIRECTIONALITY_FORCE_RTL : gfx::DIRECTIONALITY_FORCE_LTR;
}
- // Text eliding is not supported for multi-lined Labels.
- // TODO(mukai): Add multi-lined elided text support.
+ // Multi-line labels only support NO_ELIDE and ELIDE_TAIL for now.
+ // TODO(warx): Investigate more elide text support.
gfx::ElideBehavior elide_behavior =
- multi_line() ? gfx::NO_ELIDE : elide_behavior_;
+ multi_line() && (elide_behavior_ != gfx::NO_ELIDE) ? gfx::ELIDE_TAIL
+ : elide_behavior_;
if (!multi_line() || render_text_->MultilineSupported()) {
std::unique_ptr<gfx::RenderText> render_text =
CreateRenderText(text(), alignment, directionality, elide_behavior);
render_text->SetDisplayRect(rect);
render_text->SetMultiline(multi_line());
+ render_text->SetMaxLines(multi_line() ? max_lines() : 0);
render_text->SetWordWrapBehavior(render_text_->word_wrap_behavior());
// Setup render text for selection controller.
@@ -887,6 +906,8 @@ void Label::MaybeBuildRenderTextLines() const {
lines_.push_back(std::move(render_text));
} else {
+ // TODO(warx): Apply max_lines property when RenderText doesn't support
+ // multi-line (crbug.com/758720).
std::vector<base::string16> lines = GetLinesForWidth(rect.width());
if (lines.size() > 1)
rect.set_height(std::max(line_height(), font_list().GetHeight()));
diff --git a/chromium/ui/views/controls/label.h b/chromium/ui/views/controls/label.h
index 38eb5f3cd2b..7cae587453c 100644
--- a/chromium/ui/views/controls/label.h
+++ b/chromium/ui/views/controls/label.h
@@ -132,6 +132,11 @@ class VIEWS_EXPORT Label : public View,
bool multi_line() const { return multi_line_; }
void SetMultiLine(bool multi_line);
+ // If multi-line, a non-zero value will cap the number of lines rendered, and
+ // elide the rest (currently only ELIDE_TAIL supported). See gfx::RenderText.
+ int max_lines() const { return max_lines_; }
+ void SetMaxLines(int max_lines);
+
// Get or set if the label text should be obscured before rendering (e.g.
// should "Password!" display as "*********"); default is false.
bool obscured() const { return render_text_->obscured(); }
@@ -359,6 +364,7 @@ class VIEWS_EXPORT Label : public View,
bool auto_color_readability_;
// TODO(mukai): remove |multi_line_| when all RenderText can render multiline.
bool multi_line_;
+ int max_lines_;
base::string16 tooltip_text_;
bool handles_tooltips_;
// Whether to collapse the label when it's not visible.
diff --git a/chromium/ui/views/controls/label_unittest.cc b/chromium/ui/views/controls/label_unittest.cc
index b2cf18f40af..820567cc99e 100644
--- a/chromium/ui/views/controls/label_unittest.cc
+++ b/chromium/ui/views/controls/label_unittest.cc
@@ -56,7 +56,10 @@ class TestLabel : public Label {
void SimulatePaint() {
SkBitmap bitmap;
SkColor color = SK_ColorTRANSPARENT;
- Paint(ui::CanvasPainter(&bitmap, bounds().size(), 1.f, color).context());
+ Paint(PaintInfo::CreateRootPaintInfo(
+ ui::CanvasPainter(&bitmap, bounds().size(), 1.f, color, false)
+ .context(),
+ bounds().size()));
}
// View:
@@ -569,8 +572,7 @@ TEST_F(LabelTest, SingleLineSizing) {
EXPECT_EQ(size, label()->GetPreferredSize());
const gfx::Insets border(10, 20, 30, 40);
- label()->SetBorder(CreateEmptyBorder(border.top(), border.left(),
- border.bottom(), border.right()));
+ label()->SetBorder(CreateEmptyBorder(border));
const gfx::Size size_with_border = label()->GetPreferredSize();
EXPECT_EQ(size_with_border.height(), size.height() + border.height());
EXPECT_EQ(size_with_border.width(), size.width() + border.width());
@@ -649,8 +651,7 @@ TEST_F(LabelTest, MultiLineSizing) {
// Test everything with borders.
gfx::Insets border(10, 20, 30, 40);
- label()->SetBorder(CreateEmptyBorder(border.top(), border.left(),
- border.bottom(), border.right()));
+ label()->SetBorder(CreateEmptyBorder(border));
// SizeToFit and borders.
label()->SizeToFit(0);
@@ -682,6 +683,52 @@ TEST_F(LabelTest, MultiLineSizing) {
required_size.width() + border.width());
}
+#if !defined(OS_MACOSX)
+// TODO(warx): Remove !defined(OS_MACOSX) once SetMaxLines() is applied to MAC
+// (crbug.com/758720).
+TEST_F(LabelTest, MultiLineSetMaxLines) {
+ // Ensure SetMaxLines clamps the line count of a string with returns.
+ label()->SetText(ASCIIToUTF16("first line\nsecond line\nthird line"));
+ label()->SetMultiLine(true);
+ gfx::Size string_size = label()->GetPreferredSize();
+ label()->SetMaxLines(2);
+ gfx::Size two_line_size = label()->GetPreferredSize();
+ EXPECT_EQ(string_size.width(), two_line_size.width());
+ EXPECT_GT(string_size.height(), two_line_size.height());
+
+ // Ensure GetHeightForWidth also respects SetMaxLines.
+ int height = label()->GetHeightForWidth(string_size.width() / 2);
+ EXPECT_EQ(height, two_line_size.height());
+
+ // Ensure SetMaxLines also works with line wrapping for SizeToFit.
+ label()->SetText(ASCIIToUTF16("A long string that will be wrapped"));
+ label()->SetMaxLines(0); // Used to get the uncapped height.
+ label()->SizeToFit(0); // Used to get the uncapped width.
+ label()->SizeToFit(label()->GetPreferredSize().width() / 4);
+ string_size = label()->GetPreferredSize();
+ label()->SetMaxLines(2);
+ two_line_size = label()->GetPreferredSize();
+ EXPECT_EQ(string_size.width(), two_line_size.width());
+ EXPECT_GT(string_size.height(), two_line_size.height());
+
+ // Ensure SetMaxLines also works with line wrapping for SetMaximumWidth.
+ label()->SetMaxLines(0); // Used to get the uncapped height.
+ label()->SizeToFit(0); // Used to get the uncapped width.
+ label()->SetMaximumWidth(label()->GetPreferredSize().width() / 4);
+ string_size = label()->GetPreferredSize();
+ label()->SetMaxLines(2);
+ two_line_size = label()->GetPreferredSize();
+ EXPECT_EQ(string_size.width(), two_line_size.width());
+ EXPECT_GT(string_size.height(), two_line_size.height());
+
+ // Ensure SetMaxLines respects the requested inset height.
+ const gfx::Insets border(1, 2, 3, 4);
+ label()->SetBorder(CreateEmptyBorder(border));
+ EXPECT_EQ(two_line_size.height() + border.height(),
+ label()->GetPreferredSize().height());
+}
+#endif
+
// Verifies if the combination of text eliding and multiline doesn't cause
// any side effects of size / layout calculation.
TEST_F(LabelTest, MultiLineSizingWithElide) {
@@ -696,7 +743,7 @@ TEST_F(LabelTest, MultiLineSizingWithElide) {
label()->SetBoundsRect(gfx::Rect(required_size));
label()->SetElideBehavior(gfx::ELIDE_TAIL);
- EXPECT_EQ(required_size.ToString(), label()->GetPreferredSize().ToString());
+ EXPECT_EQ(required_size, label()->GetPreferredSize());
EXPECT_EQ(text, label()->GetDisplayTextForTesting());
label()->SizeToFit(required_size.width() - 1);
@@ -706,12 +753,12 @@ TEST_F(LabelTest, MultiLineSizingWithElide) {
// SetBounds() doesn't change the preferred size.
label()->SetBounds(0, 0, narrow_size.width() - 1, narrow_size.height());
- EXPECT_EQ(narrow_size.ToString(), label()->GetPreferredSize().ToString());
+ EXPECT_EQ(narrow_size, label()->GetPreferredSize());
// Paint() doesn't change the preferred size.
gfx::Canvas canvas;
label()->OnPaint(&canvas);
- EXPECT_EQ(narrow_size.ToString(), label()->GetPreferredSize().ToString());
+ EXPECT_EQ(narrow_size, label()->GetPreferredSize());
}
// Check that labels support GetTooltipHandlerForPoint.
@@ -766,7 +813,7 @@ TEST_F(LabelTest, ResetRenderTextData) {
label()->SizeToPreferredSize();
gfx::Size preferred_size = label()->GetPreferredSize();
- EXPECT_NE(gfx::Size().ToString(), preferred_size.ToString());
+ EXPECT_NE(gfx::Size(), preferred_size);
EXPECT_EQ(0u, label()->lines_.size());
gfx::Canvas canvas(preferred_size, 1.0f, true);
@@ -783,7 +830,7 @@ TEST_F(LabelTest, ResetRenderTextData) {
EXPECT_EQ(ASCIIToUTF16("Example"), label()->text());
EXPECT_EQ(0u, label()->lines_.size());
- EXPECT_EQ(preferred_size.ToString(), label()->GetPreferredSize().ToString());
+ EXPECT_EQ(preferred_size, label()->GetPreferredSize());
EXPECT_EQ(0u, label()->lines_.size());
// RenderText data should be back when it's necessary.
@@ -893,7 +940,7 @@ TEST_P(MDLabelTest, FocusBounds) {
label()->SizeToPreferredSize();
gfx::Rect focus_bounds = label()->GetFocusRingBounds();
- EXPECT_EQ(label()->GetLocalBounds().ToString(), focus_bounds.ToString());
+ EXPECT_EQ(label()->GetLocalBounds(), focus_bounds);
gfx::Size focusable_size = normal_label_size;
label()->SetBounds(
@@ -903,7 +950,7 @@ TEST_P(MDLabelTest, FocusBounds) {
EXPECT_EQ(0, focus_bounds.x());
EXPECT_LT(0, focus_bounds.y());
EXPECT_GT(label()->bounds().bottom(), focus_bounds.bottom());
- EXPECT_EQ(focusable_size.ToString(), focus_bounds.size().ToString());
+ EXPECT_EQ(focusable_size, focus_bounds.size());
label()->SetHorizontalAlignment(gfx::ALIGN_RIGHT);
focus_bounds = label()->GetFocusRingBounds();
@@ -911,7 +958,7 @@ TEST_P(MDLabelTest, FocusBounds) {
EXPECT_EQ(label()->bounds().right(), focus_bounds.right());
EXPECT_LT(0, focus_bounds.y());
EXPECT_GT(label()->bounds().bottom(), focus_bounds.bottom());
- EXPECT_EQ(focusable_size.ToString(), focus_bounds.size().ToString());
+ EXPECT_EQ(focusable_size, focus_bounds.size());
label()->SetHorizontalAlignment(gfx::ALIGN_LEFT);
label()->SetElideBehavior(gfx::FADE_TAIL);
diff --git a/chromium/ui/views/controls/menu/menu_controller.cc b/chromium/ui/views/controls/menu/menu_controller.cc
index e9125d68fbd..9c0a30130cd 100644
--- a/chromium/ui/views/controls/menu/menu_controller.cc
+++ b/chromium/ui/views/controls/menu/menu_controller.cc
@@ -103,15 +103,15 @@ bool TitleMatchesMnemonic(MenuItemView* menu, base::char16 key) {
}
// Returns the first descendant of |view| that is hot tracked.
-CustomButton* GetFirstHotTrackedView(View* view) {
+Button* GetFirstHotTrackedView(View* view) {
if (!view)
return NULL;
- CustomButton* button = CustomButton::AsCustomButton(view);
+ Button* button = Button::AsButton(view);
if (button && button->IsHotTracked())
return button;
for (int i = 0; i < view->child_count(); ++i) {
- CustomButton* hot_view = GetFirstHotTrackedView(view->child_at(i));
+ Button* hot_view = GetFirstHotTrackedView(view->child_at(i));
if (hot_view)
return hot_view;
}
@@ -570,7 +570,7 @@ bool MenuController::OnMousePressed(SubmenuView* source,
ConvertLocatedEventForRootView(source, forward_to_root, &event_for_root);
View* view =
forward_to_root->GetEventHandlerForPoint(event_for_root.location());
- CustomButton* button = CustomButton::AsCustomButton(view);
+ Button* button = Button::AsButton(view);
if (hot_button_ != button)
SetHotTrackedButton(button);
@@ -756,7 +756,7 @@ void MenuController::OnMouseMoved(SubmenuView* source,
ConvertLocatedEventForRootView(source, root_view, &event_for_root);
View* view =
root_view->GetEventHandlerForPoint(event_for_root.location());
- CustomButton* button = CustomButton::AsCustomButton(view);
+ Button* button = Button::AsButton(view);
if (button && button->IsHotTracked())
SetHotTrackedButton(button);
}
@@ -785,7 +785,7 @@ void MenuController::OnGestureEvent(SubmenuView* source,
ConvertLocatedEventForRootView(source, root_view, &event_for_root);
View* view =
root_view->GetEventHandlerForPoint(event_for_root.location());
- CustomButton* button = CustomButton::AsCustomButton(view);
+ Button* button = Button::AsButton(view);
if (hot_button_ && hot_button_ != button)
SetHotTrackedButton(nullptr);
}
@@ -1350,7 +1350,7 @@ void MenuController::OnKeyDown(ui::KeyboardCode key_code) {
break;
case ui::VKEY_APPS: {
- CustomButton* hot_view = GetFirstHotTrackedView(pending_state_.item);
+ Button* hot_view = GetFirstHotTrackedView(pending_state_.item);
if (hot_view) {
hot_view->ShowContextMenu(hot_view->GetKeyboardContextMenuLocation(),
ui::MENU_SOURCE_KEYBOARD);
@@ -1422,7 +1422,7 @@ MenuController::~MenuController() {
}
bool MenuController::SendAcceleratorToHotTrackedView() {
- CustomButton* hot_view = GetFirstHotTrackedView(pending_state_.item);
+ Button* hot_view = GetFirstHotTrackedView(pending_state_.item);
if (!hot_view)
return false;
@@ -1431,7 +1431,7 @@ bool MenuController::SendAcceleratorToHotTrackedView() {
hot_view->AcceleratorPressed(accelerator);
// An accelerator may have canceled the menu after activation.
if (this_ref) {
- CustomButton* button = static_cast<CustomButton*>(hot_view);
+ Button* button = static_cast<Button*>(hot_view);
SetHotTrackedButton(button);
}
return true;
@@ -2203,7 +2203,7 @@ void MenuController::IncrementSelection(
}
if (item->has_children()) {
- CustomButton* button = GetFirstHotTrackedView(item);
+ Button* button = GetFirstHotTrackedView(item);
if (button) {
DCHECK_EQ(hot_button_, button);
SetHotTrackedButton(nullptr);
@@ -2212,7 +2212,7 @@ void MenuController::IncrementSelection(
View* to_make_hot = button
? GetNextFocusableView(item, button, direction_is_down)
: GetInitialFocusableView(item, direction_is_down);
- CustomButton* hot_button = CustomButton::AsCustomButton(to_make_hot);
+ Button* hot_button = Button::AsButton(to_make_hot);
if (hot_button) {
SetHotTrackedButton(hot_button);
return;
@@ -2695,10 +2695,10 @@ void MenuController::SetInitialHotTrackedView(
SetSelection(item, SELECTION_DEFAULT);
View* hot_view =
GetInitialFocusableView(item, direction == INCREMENT_SELECTION_DOWN);
- SetHotTrackedButton(CustomButton::AsCustomButton(hot_view));
+ SetHotTrackedButton(Button::AsButton(hot_view));
}
-void MenuController::SetHotTrackedButton(CustomButton* hot_button) {
+void MenuController::SetHotTrackedButton(Button* hot_button) {
if (hot_button == hot_button_) {
// Hot-tracked state may change outside of the MenuController. Correct it.
if (hot_button && !hot_button->IsHotTracked()) {
diff --git a/chromium/ui/views/controls/menu/menu_controller.h b/chromium/ui/views/controls/menu/menu_controller.h
index 06fc19b5c90..2a58d296567 100644
--- a/chromium/ui/views/controls/menu/menu_controller.h
+++ b/chromium/ui/views/controls/menu/menu_controller.h
@@ -238,7 +238,7 @@ class VIEWS_EXPORT MenuController
// Used to capture a hot tracked child button when a nested menu is opened
// and to restore the hot tracked state when exiting a nested menu.
- CustomButton* hot_button;
+ Button* hot_button;
// If item has a submenu this indicates if the submenu is showing.
bool submenu_open;
@@ -545,7 +545,7 @@ class VIEWS_EXPORT MenuController
SelectionIncrementDirectionType direction);
// Updates the current |hot_button_| and its hot tracked state.
- void SetHotTrackedButton(CustomButton* hot_button);
+ void SetHotTrackedButton(Button* hot_button);
// The active instance.
static MenuController* active_instance_;
@@ -646,7 +646,7 @@ class VIEWS_EXPORT MenuController
std::unique_ptr<ViewTracker> active_mouse_view_tracker_;
// Current hot tracked child button if any.
- CustomButton* hot_button_;
+ Button* hot_button_;
internal::MenuControllerDelegate* delegate_;
diff --git a/chromium/ui/views/controls/menu/menu_controller_unittest.cc b/chromium/ui/views/controls/menu/menu_controller_unittest.cc
index c5aa7abc00d..32668272f71 100644
--- a/chromium/ui/views/controls/menu/menu_controller_unittest.cc
+++ b/chromium/ui/views/controls/menu/menu_controller_unittest.cc
@@ -36,6 +36,7 @@
#if defined(USE_AURA)
#include "ui/aura/client/drag_drop_client.h"
+#include "ui/aura/client/drag_drop_client_observer.h"
#include "ui/aura/scoped_window_targeter.h"
#include "ui/aura/window.h"
#include "ui/views/controls/menu/menu_pre_target_handler.h"
@@ -172,6 +173,10 @@ class TestDragDropClient : public aura::client::DragDropClient {
void DragCancel() override;
bool IsDragDropInProgress() override;
+ void AddObserver(aura::client::DragDropClientObserver* observer) override {}
+ void RemoveObserver(aura::client::DragDropClientObserver* observer) override {
+ }
+
private:
base::Closure start_drag_and_drop_callback_;
bool drag_in_progress_;
@@ -489,11 +494,9 @@ class MenuControllerTest : public ViewsTestBase {
void DestroyMenuItem() { menu_item_.reset(); }
- CustomButton* GetHotButton() {
- return menu_controller_->hot_button_;
- }
+ Button* GetHotButton() { return menu_controller_->hot_button_; }
- void SetHotTrackedButton(CustomButton* hot_button) {
+ void SetHotTrackedButton(Button* hot_button) {
menu_controller_->SetHotTrackedButton(hot_button);
}
@@ -770,14 +773,11 @@ TEST_F(MenuControllerTest, SelectChildButtonView) {
AddButtonMenuItems();
View* buttons_view = menu_item()->GetSubmenu()->child_at(4);
ASSERT_NE(nullptr, buttons_view);
- CustomButton* button1 =
- CustomButton::AsCustomButton(buttons_view->child_at(0));
+ Button* button1 = Button::AsButton(buttons_view->child_at(0));
ASSERT_NE(nullptr, button1);
- CustomButton* button2 =
- CustomButton::AsCustomButton(buttons_view->child_at(1));
+ Button* button2 = Button::AsButton(buttons_view->child_at(1));
ASSERT_NE(nullptr, button2);
- CustomButton* button3 =
- CustomButton::AsCustomButton(buttons_view->child_at(2));
+ Button* button3 = Button::AsButton(buttons_view->child_at(2));
ASSERT_NE(nullptr, button2);
// Handle searching for 'f'; should find "Four".
@@ -843,14 +843,11 @@ TEST_F(MenuControllerTest, DeleteChildButtonView) {
View* buttons_view = menu_item()->GetSubmenu()->child_at(4);
ASSERT_NE(nullptr, buttons_view);
- CustomButton* button1 =
- CustomButton::AsCustomButton(buttons_view->child_at(0));
+ Button* button1 = Button::AsButton(buttons_view->child_at(0));
ASSERT_NE(nullptr, button1);
- CustomButton* button2 =
- CustomButton::AsCustomButton(buttons_view->child_at(1));
+ Button* button2 = Button::AsButton(buttons_view->child_at(1));
ASSERT_NE(nullptr, button2);
- CustomButton* button3 =
- CustomButton::AsCustomButton(buttons_view->child_at(2));
+ Button* button3 = Button::AsButton(buttons_view->child_at(2));
ASSERT_NE(nullptr, button2);
EXPECT_FALSE(button1->IsHotTracked());
EXPECT_FALSE(button2->IsHotTracked());
@@ -877,7 +874,7 @@ TEST_F(MenuControllerTest, DeleteChildButtonView) {
EXPECT_FALSE(button3->IsHotTracked());
}
-// Creates a menu with CustomButton child views, simulates running a nested
+// Creates a menu with Button child views, simulates running a nested
// menu and tests that existing the nested run restores hot-tracked child view.
TEST_F(MenuControllerTest, ChildButtonHotTrackedWhenNested) {
AddButtonMenuItems();
@@ -888,14 +885,11 @@ TEST_F(MenuControllerTest, ChildButtonHotTrackedWhenNested) {
View* buttons_view = menu_item()->GetSubmenu()->child_at(4);
ASSERT_NE(nullptr, buttons_view);
- CustomButton* button1 =
- CustomButton::AsCustomButton(buttons_view->child_at(0));
+ Button* button1 = Button::AsButton(buttons_view->child_at(0));
ASSERT_NE(nullptr, button1);
- CustomButton* button2 =
- CustomButton::AsCustomButton(buttons_view->child_at(1));
+ Button* button2 = Button::AsButton(buttons_view->child_at(1));
ASSERT_NE(nullptr, button2);
- CustomButton* button3 =
- CustomButton::AsCustomButton(buttons_view->child_at(2));
+ Button* button3 = Button::AsButton(buttons_view->child_at(2));
ASSERT_NE(nullptr, button2);
EXPECT_FALSE(button1->IsHotTracked());
EXPECT_FALSE(button2->IsHotTracked());
diff --git a/chromium/ui/views/controls/menu/menu_item_view.cc b/chromium/ui/views/controls/menu/menu_item_view.cc
index 905690f8d40..fcf1e9aa0b7 100644
--- a/chromium/ui/views/controls/menu/menu_item_view.cc
+++ b/chromium/ui/views/controls/menu/menu_item_view.cc
@@ -184,6 +184,13 @@ void MenuItemView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
// No additional accessibility states currently for these menu states.
break;
}
+
+ base::char16 mnemonic = GetMnemonic();
+ if (mnemonic != '\0') {
+ node_data->AddStringAttribute(
+ ui::AX_ATTR_KEY_SHORTCUTS,
+ base::UTF16ToUTF8(base::string16(1, mnemonic)));
+ }
}
// static
@@ -334,8 +341,14 @@ MenuItemView* MenuItemView::AppendMenuItemImpl(
}
SubmenuView* MenuItemView::CreateSubmenu() {
- if (!submenu_)
+ if (!submenu_) {
submenu_ = new SubmenuView(this);
+
+ // Initialize the submenu indicator icon (arrow).
+ submenu_arrow_image_view_ = new ImageView();
+ AddChildView(submenu_arrow_image_view_);
+ }
+
return submenu_;
}
@@ -547,7 +560,11 @@ void MenuItemView::Layout() {
int x = width() - (use_right_margin_ ? item_right_margin_ : 0);
for (int i = child_count() - 1; i >= 0; --i) {
View* child = child_at(i);
- if (icon_view_ && (icon_view_ == child))
+ if (icon_view_ == child)
+ continue;
+ if (radio_check_image_view_ == child)
+ continue;
+ if (submenu_arrow_image_view_ == child)
continue;
int width = child->GetPreferredSize().width();
child->SetBounds(x - width, 0, width, height());
@@ -566,6 +583,22 @@ void MenuItemView::Layout() {
(height() + GetTopMargin() - GetBottomMargin() - size.height()) / 2;
icon_view_->SetPosition(gfx::Point(x, y));
}
+
+ if (radio_check_image_view_) {
+ int x = config.item_left_margin + left_icon_margin_;
+ int y =
+ (height() + GetTopMargin() - GetBottomMargin() - kMenuCheckSize) / 2;
+ radio_check_image_view_->SetBounds(x, y, kMenuCheckSize, kMenuCheckSize);
+ }
+
+ if (submenu_arrow_image_view_) {
+ int x = this->width() - config.arrow_width - config.arrow_to_edge_padding;
+ int y =
+ (height() + GetTopMargin() - GetBottomMargin() - kSubmenuArrowSize) /
+ 2;
+ submenu_arrow_image_view_->SetBounds(x, y, config.arrow_width,
+ kSubmenuArrowSize);
+ }
}
}
@@ -650,11 +683,25 @@ void MenuItemView::Init(MenuItemView* parent,
selected_ = false;
command_ = command;
submenu_ = NULL;
+ radio_check_image_view_ = nullptr;
+ submenu_arrow_image_view_ = nullptr;
show_mnemonics_ = false;
// Assign our ID, this allows SubmenuItemView to find MenuItemViews.
set_id(kMenuItemViewID);
has_icons_ = false;
+ if (type_ == CHECKBOX || type_ == RADIO) {
+ radio_check_image_view_ = new ImageView();
+ bool show_check_radio_icon =
+ type_ == RADIO ||
+ (type_ == CHECKBOX && GetDelegate()->IsItemChecked(GetCommand()));
+ radio_check_image_view_->SetVisible(show_check_radio_icon);
+ AddChildView(radio_check_image_view_);
+ }
+
+ if (submenu_arrow_image_view_)
+ submenu_arrow_image_view_->SetVisible(HasSubmenu());
+
// Don't request enabled status from the root menu item as it is just
// a container for real items. EMPTY items will be disabled.
MenuDelegate* root_delegate = GetDelegate();
@@ -715,7 +762,7 @@ const gfx::FontList& MenuItemView::GetFontList() const {
void MenuItemView::AddEmptyMenus() {
DCHECK(HasSubmenu());
- if (!submenu_->has_children()) {
+ if (!submenu_->HasVisibleChildren()) {
submenu_->AddChildViewAt(new EmptyMenuMenuItem(this), 0);
} else {
for (int i = 0, item_count = submenu_->GetMenuItemCount(); i < item_count;
@@ -774,7 +821,6 @@ void MenuItemView::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) {
ui::NativeTheme::ExtraParams());
}
- const int icon_x = config.item_left_margin + left_icon_margin_;
const int top_margin = GetTopMargin();
const int bottom_margin = GetBottomMargin();
const int available_height = height() - top_margin - bottom_margin;
@@ -785,24 +831,10 @@ void MenuItemView::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) {
// Render the check.
if (type_ == CHECKBOX && delegate->IsItemChecked(GetCommand())) {
- gfx::ImageSkia check = GetMenuCheckImage(icon_color);
- // Don't use config.check_width here as it's padded
- // to force more padding (AURA).
- gfx::Rect check_bounds(icon_x,
- top_margin + (available_height - check.height()) / 2,
- check.width(),
- check.height());
- AdjustBoundsForRTLUI(&check_bounds);
- canvas->DrawImageInt(check, check_bounds.x(), check_bounds.y());
+ radio_check_image_view_->SetImage(GetMenuCheckImage(icon_color));
} else if (type_ == RADIO) {
- gfx::ImageSkia image = GetRadioButtonImage(
- delegate->IsItemChecked(GetCommand()), render_selection, icon_color);
- gfx::Rect radio_bounds(icon_x,
- top_margin + (available_height - image.height()) / 2,
- image.width(),
- image.height());
- AdjustBoundsForRTLUI(&radio_bounds);
- canvas->DrawImageInt(image, radio_bounds.x(), radio_bounds.y());
+ radio_check_image_view_->SetImage(GetRadioButtonImage(
+ delegate->IsItemChecked(GetCommand()), render_selection, icon_color));
}
// Render the foreground.
@@ -835,17 +867,9 @@ void MenuItemView::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) {
PaintMinorText(canvas, GetTextColor(true, render_selection, emphasized));
- // Render the submenu indicator (arrow).
- if (HasSubmenu()) {
- gfx::ImageSkia arrow = GetSubmenuArrowImage(icon_color);
- gfx::Rect arrow_bounds(this->width() - config.arrow_width -
- config.arrow_to_edge_padding,
- top_margin + (available_height - arrow.height()) / 2,
- config.arrow_width,
- arrow.height());
- AdjustBoundsForRTLUI(&arrow_bounds);
- canvas->DrawImageInt(arrow, arrow_bounds.x(), arrow_bounds.y());
- }
+ // Set the submenu indicator (arrow) image and color.
+ if (HasSubmenu())
+ submenu_arrow_image_view_->SetImage(GetSubmenuArrowImage(icon_color));
}
void MenuItemView::PaintMinorText(gfx::Canvas* canvas, SkColor color) {
@@ -929,7 +953,11 @@ gfx::Size MenuItemView::GetChildPreferredSize() const {
int width = 0;
for (int i = 0; i < child_count(); ++i) {
const View* child = child_at(i);
- if (icon_view_ && (icon_view_ == child))
+ if (icon_view_ == child)
+ continue;
+ if (radio_check_image_view_ == child)
+ continue;
+ if (submenu_arrow_image_view_ == child)
continue;
if (i)
width += kChildXPadding;
@@ -1037,7 +1065,9 @@ bool MenuItemView::IsContainer() const {
int MenuItemView::NonIconChildViewsCount() const {
// Note that what child_count() returns is the number of children,
// not the number of menu items.
- return child_count() - (icon_view_ ? 1 : 0);
+ return child_count() - (icon_view_ ? 1 : 0) -
+ (radio_check_image_view_ ? 1 : 0) -
+ (submenu_arrow_image_view_ ? 1 : 0);
}
int MenuItemView::GetMaxIconViewWidth() const {
diff --git a/chromium/ui/views/controls/menu/menu_item_view.h b/chromium/ui/views/controls/menu/menu_item_view.h
index a23101c16a3..f474f6f9dac 100644
--- a/chromium/ui/views/controls/menu/menu_item_view.h
+++ b/chromium/ui/views/controls/menu/menu_item_view.h
@@ -43,6 +43,7 @@ class TestMenuItemViewShown;
class MenuController;
class MenuDelegate;
+class TestMenuItemView;
class SubmenuView;
// MenuItemView --------------------------------------------------------------
@@ -351,6 +352,7 @@ class VIEWS_EXPORT MenuItemView : public View {
private:
friend class internal::MenuRunnerImpl; // For access to ~MenuItemView.
friend class test::TestMenuItemViewShown; // for access to |submenu_|;
+ friend class TestMenuItemView; // For access to AddEmptyMenus();
enum PaintButtonMode { PB_NORMAL, PB_FOR_DRAG };
@@ -536,6 +538,12 @@ class VIEWS_EXPORT MenuItemView : public View {
// containing other elements.
bool use_right_margin_;
+ // Contains an image for the checkbox or radio icon.
+ ImageView* radio_check_image_view_;
+
+ // The submenu indicator arrow icon in case the menu item has a Submenu.
+ ImageView* submenu_arrow_image_view_;
+
DISALLOW_COPY_AND_ASSIGN(MenuItemView);
};
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 7c9151f6625..ab5f10ec455 100644
--- a/chromium/ui/views/controls/menu/menu_item_view_unittest.cc
+++ b/chromium/ui/views/controls/menu/menu_item_view_unittest.cc
@@ -7,8 +7,11 @@
#include "base/strings/string16.h"
#include "base/strings/utf_string_conversions.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/base/l10n/l10n_util.h"
+#include "ui/strings/grit/ui_strings.h"
#include "ui/views/controls/menu/submenu_view.h"
-#include "ui/views/view.h"
+
+namespace views {
namespace {
@@ -23,15 +26,20 @@ class SquareView : public views::View {
int GetHeightForWidth(int width) const override { return width; }
};
+} // namespace
+
// A MenuItemView implementation with a public destructor (so we can clean up
// in tests).
-class TestMenuItemView : public views::MenuItemView {
+class TestMenuItemView : public MenuItemView {
public:
- TestMenuItemView() : views::MenuItemView(NULL) {}
+ TestMenuItemView() : MenuItemView(NULL) {}
~TestMenuItemView() override {}
-};
-} // namespace
+ void AddEmptyMenus() { MenuItemView::AddEmptyMenus(); }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestMenuItemView);
+};
TEST(MenuItemViewUnitTest, TestMenuItemViewWithFlexibleWidthChild) {
TestMenuItemView root_menu;
@@ -70,3 +78,69 @@ TEST(MenuItemViewUnitTest, TestMenuItemViewWithFlexibleWidthChild) {
EXPECT_EQ(label_size.height() + flex_height,
submenu->GetPreferredSize().height());
}
+
+// Tests that the top-level menu item with hidden children should contain the
+// "(empty)" menu item to display.
+TEST(MenuItemViewUnitTest, TestEmptyTopLevelWhenAllItemsAreHidden) {
+ TestMenuItemView root_menu;
+ views::MenuItemView* item1 =
+ root_menu.AppendMenuItemWithLabel(1, base::ASCIIToUTF16("item 1"));
+ views::MenuItemView* item2 =
+ root_menu.AppendMenuItemWithLabel(2, base::ASCIIToUTF16("item 2"));
+
+ // Set menu items to hidden.
+ item1->SetVisible(false);
+ item2->SetVisible(false);
+
+ SubmenuView* submenu = root_menu.GetSubmenu();
+ ASSERT_TRUE(submenu);
+
+ EXPECT_EQ(2, submenu->child_count());
+
+ // Adds any empty menu items to the menu, if needed.
+ root_menu.AddEmptyMenus();
+
+ // 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);
+ ASSERT_EQ(MenuItemView::kEmptyMenuItemViewID, empty_item->id());
+ EXPECT_EQ(l10n_util::GetStringUTF16(IDS_APP_MENU_EMPTY_SUBMENU),
+ empty_item->title());
+}
+
+// Tests that submenu with hidden children should contain the "(empty)" menu
+// item to display.
+TEST(MenuItemViewUnitTest, TestEmptySubmenuWhenAllChildItemsAreHidden) {
+ TestMenuItemView root_menu;
+ MenuItemView* submenu_item =
+ root_menu.AppendSubMenu(1, base::ASCIIToUTF16("My Submenu"));
+ MenuItemView* child1 = submenu_item->AppendMenuItemWithLabel(
+ 1, base::ASCIIToUTF16("submenu item 1"));
+ MenuItemView* child2 = submenu_item->AppendMenuItemWithLabel(
+ 2, base::ASCIIToUTF16("submenu item 2"));
+
+ // Set submenu children to hidden.
+ child1->SetVisible(false);
+ child2->SetVisible(false);
+
+ SubmenuView* submenu = submenu_item->GetSubmenu();
+ ASSERT_TRUE(submenu);
+
+ EXPECT_EQ(2, submenu->child_count());
+
+ // Adds any empty menu items to the menu, if needed.
+ root_menu.AddEmptyMenus();
+
+ // 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);
+ ASSERT_EQ(MenuItemView::kEmptyMenuItemViewID, empty_item->id());
+ EXPECT_EQ(l10n_util::GetStringUTF16(IDS_APP_MENU_EMPTY_SUBMENU),
+ empty_item->title());
+}
+
+} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu_runner_impl.h b/chromium/ui/views/controls/menu/menu_runner_impl.h
index 78fcff7d482..22e490a1af5 100644
--- a/chromium/ui/views/controls/menu/menu_runner_impl.h
+++ b/chromium/ui/views/controls/menu/menu_runner_impl.h
@@ -32,9 +32,8 @@ class MenuRunnerDestructionTest;
namespace internal {
// A menu runner implementation that uses views::MenuItemView to show a menu.
-class VIEWS_EXPORT MenuRunnerImpl
- : NON_EXPORTED_BASE(public MenuRunnerImplInterface),
- NON_EXPORTED_BASE(public MenuControllerDelegate) {
+class VIEWS_EXPORT MenuRunnerImpl : public MenuRunnerImplInterface,
+ public MenuControllerDelegate {
public:
explicit MenuRunnerImpl(MenuItemView* menu);
diff --git a/chromium/ui/views/controls/menu/menu_runner_impl_adapter.h b/chromium/ui/views/controls/menu/menu_runner_impl_adapter.h
index bcb31cf102b..e70d7b60168 100644
--- a/chromium/ui/views/controls/menu/menu_runner_impl_adapter.h
+++ b/chromium/ui/views/controls/menu/menu_runner_impl_adapter.h
@@ -20,8 +20,7 @@ namespace internal {
class MenuRunnerImpl;
// Given a MenuModel, adapts MenuRunnerImpl which expects a MenuItemView.
-class VIEWS_EXPORT MenuRunnerImplAdapter
- : public NON_EXPORTED_BASE(MenuRunnerImplInterface) {
+class VIEWS_EXPORT MenuRunnerImplAdapter : public MenuRunnerImplInterface {
public:
MenuRunnerImplAdapter(ui::MenuModel* menu_model,
const base::Closure& on_menu_closed_callback);
diff --git a/chromium/ui/views/controls/menu/submenu_view.cc b/chromium/ui/views/controls/menu/submenu_view.cc
index 77795b98d52..f7a75314ec4 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::HasVisibleChildren() {
+ for (int i = 0, item_count = GetMenuItemCount(); i < item_count; i++) {
+ if (GetMenuItemAt(i)->visible())
+ return true;
+ }
+ return false;
+}
+
int SubmenuView::GetMenuItemCount() {
int count = 0;
for (int i = 0; i < child_count(); ++i) {
@@ -191,8 +199,8 @@ void SubmenuView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
node_data->AddState(ui::AX_STATE_VERTICAL);
}
-void SubmenuView::PaintChildren(const ui::PaintContext& context) {
- View::PaintChildren(context);
+void SubmenuView::PaintChildren(const PaintInfo& paint_info) {
+ View::PaintChildren(paint_info);
bool paint_drop_indicator = false;
if (drop_item_) {
@@ -210,7 +218,7 @@ void SubmenuView::PaintChildren(const ui::PaintContext& context) {
if (paint_drop_indicator) {
gfx::Rect bounds = CalculateDropIndicatorBounds(drop_item_, drop_position_);
- ui::PaintRecorder recorder(context, size());
+ ui::PaintRecorder recorder(paint_info.context(), size());
recorder.canvas()->FillRect(bounds, kDropIndicatorColor);
}
}
diff --git a/chromium/ui/views/controls/menu/submenu_view.h b/chromium/ui/views/controls/menu/submenu_view.h
index 6bfacac7e51..c17c94449e8 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 visible child item.
+ bool HasVisibleChildren();
+
// Returns the number of child views that are MenuItemViews.
// MenuItemViews are identified by ID.
int GetMenuItemCount();
@@ -69,7 +72,7 @@ class VIEWS_EXPORT SubmenuView : public View,
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
// Painting.
- void PaintChildren(const ui::PaintContext& context) override;
+ void PaintChildren(const PaintInfo& paint_info) override;
// Drag and drop methods. These are forwarded to the MenuController.
bool GetDropFormats(
diff --git a/chromium/ui/views/controls/native/native_view_host.cc b/chromium/ui/views/controls/native/native_view_host.cc
index e926db1b5e4..64160a2f008 100644
--- a/chromium/ui/views/controls/native/native_view_host.cc
+++ b/chromium/ui/views/controls/native/native_view_host.cc
@@ -54,6 +54,10 @@ void NativeViewHost::SetPreferredSize(const gfx::Size& size) {
PreferredSizeChanged();
}
+bool NativeViewHost::SetCornerRadius(int corner_radius) {
+ return native_wrapper_->SetCornerRadius(corner_radius);
+}
+
void NativeViewHost::NativeViewDestroyed() {
// Detach so we can clear our state and notify the native_wrapper_ to release
// ref on the native view.
diff --git a/chromium/ui/views/controls/native/native_view_host.h b/chromium/ui/views/controls/native/native_view_host.h
index 5b0183717b8..d838192ecc4 100644
--- a/chromium/ui/views/controls/native/native_view_host.h
+++ b/chromium/ui/views/controls/native/native_view_host.h
@@ -50,6 +50,11 @@ class VIEWS_EXPORT NativeViewHost : public View {
// Sets a preferred size for the native view attached to this View.
void SetPreferredSize(const gfx::Size& size);
+ // Sets the corner radius for clipping gfx::NativeView. Returns true on
+ // success or false if the platform doesn't support the operation.
+ // NB: This does not interact nicely with fast_resize.
+ bool SetCornerRadius(int corner_radius);
+
// 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
@@ -70,7 +75,6 @@ class VIEWS_EXPORT NativeViewHost : public View {
return fast_resize_at_last_layout_;
}
- // Accessor for |native_view_|.
gfx::NativeView native_view() const { return native_view_; }
void NativeViewDestroyed();
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 1bb47710a2d..40b01d9c3c4 100644
--- a/chromium/ui/views/controls/native/native_view_host_aura.cc
+++ b/chromium/ui/views/controls/native/native_view_host_aura.cc
@@ -5,13 +5,16 @@
#include "ui/views/controls/native/native_view_host_aura.h"
#include "base/logging.h"
+#include "build/build_config.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/window.h"
#include "ui/aura/window_delegate.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/hit_test.h"
+#include "ui/compositor/paint_recorder.h"
#include "ui/views/controls/native/native_view_host.h"
+#include "ui/views/painter.h"
#include "ui/views/view_constants_aura.h"
#include "ui/views/widget/widget.h"
@@ -95,6 +98,7 @@ void NativeViewHostAura::AttachNativeView() {
host_->native_view()->SetProperty(views::kHostViewKey,
static_cast<View*>(host_));
AddClippingWindow();
+ InstallMask();
}
void NativeViewHostAura::NativeViewDetaching(bool destroyed) {
@@ -132,6 +136,20 @@ void NativeViewHostAura::RemovedFromWidget() {
}
}
+bool NativeViewHostAura::SetCornerRadius(int corner_radius) {
+#if defined(OS_WIN)
+ // Layer masks don't work on Windows. See crbug.com/713359
+ return false;
+#else
+ mask_ = views::Painter::CreatePaintedLayer(
+ views::Painter::CreateSolidRoundRectPainter(SK_ColorBLACK,
+ corner_radius));
+ mask_->layer()->SetFillsBoundsOpaquely(false);
+ InstallMask();
+ return true;
+#endif
+}
+
void NativeViewHostAura::InstallClip(int x, int y, int w, int h) {
clip_rect_.reset(
new gfx::Rect(host_->ConvertRectToWidget(gfx::Rect(x, y, w, h))));
@@ -187,6 +205,13 @@ gfx::NativeCursor NativeViewHostAura::GetCursor(int x, int y) {
return gfx::kNullCursor;
}
+void NativeViewHostAura::OnWindowBoundsChanged(aura::Window* window,
+ const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) {
+ if (mask_)
+ mask_->layer()->SetBounds(gfx::Rect(host_->native_view()->bounds().size()));
+}
+
void NativeViewHostAura::OnWindowDestroying(aura::Window* window) {
DCHECK(window == host_->native_view());
clipping_window_delegate_->set_native_view(NULL);
@@ -234,4 +259,13 @@ void NativeViewHostAura::RemoveClippingWindow() {
clipping_window_.parent()->RemoveChild(&clipping_window_);
}
+void NativeViewHostAura::InstallMask() {
+ if (!mask_)
+ return;
+ if (host_->native_view()) {
+ mask_->layer()->SetBounds(gfx::Rect(host_->native_view()->bounds().size()));
+ host_->native_view()->layer()->SetMaskLayer(mask_->layer());
+ }
+}
+
} // namespace views
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 45e859082eb..86770c341bf 100644
--- a/chromium/ui/views/controls/native/native_view_host_aura.h
+++ b/chromium/ui/views/controls/native/native_view_host_aura.h
@@ -9,6 +9,7 @@
#include "base/macros.h"
#include "ui/aura/window.h"
#include "ui/aura/window_observer.h"
+#include "ui/compositor/layer_owner.h"
#include "ui/views/controls/native/native_view_host_wrapper.h"
#include "ui/views/views_export.h"
@@ -17,8 +18,8 @@ namespace views {
class NativeViewHost;
// Aura implementation of NativeViewHostWrapper.
-class VIEWS_EXPORT NativeViewHostAura : public NativeViewHostWrapper,
- public aura::WindowObserver {
+class NativeViewHostAura : public NativeViewHostWrapper,
+ public aura::WindowObserver {
public:
explicit NativeViewHostAura(NativeViewHost* host);
~NativeViewHostAura() override;
@@ -28,6 +29,7 @@ class VIEWS_EXPORT NativeViewHostAura : public NativeViewHostWrapper,
void NativeViewDetaching(bool destroyed) override;
void AddedToWidget() override;
void RemovedFromWidget() override;
+ bool SetCornerRadius(int corner_radius) override;
void InstallClip(int x, int y, int w, int h) override;
bool HasInstalledClip() override;
void UninstallClip() override;
@@ -39,12 +41,14 @@ class VIEWS_EXPORT NativeViewHostAura : public NativeViewHostWrapper,
private:
friend class NativeViewHostAuraTest;
-
class ClippingWindowDelegate;
// Overridden from aura::WindowObserver:
void OnWindowDestroying(aura::Window* window) override;
void OnWindowDestroyed(aura::Window* window) override;
+ void OnWindowBoundsChanged(aura::Window* window,
+ const gfx::Rect& old_bounds,
+ const gfx::Rect& new_bounds) override;
// Reparents the native view with the clipping window existing between it and
// its old parent, so that the fast resize path works.
@@ -54,6 +58,9 @@ class VIEWS_EXPORT NativeViewHostAura : public NativeViewHostWrapper,
// undoes it.
void RemoveClippingWindow();
+ // Sets or updates the mask layer on the native view's layer.
+ void InstallMask();
+
// Our associated NativeViewHost.
NativeViewHost* host_;
@@ -65,6 +72,9 @@ class VIEWS_EXPORT NativeViewHostAura : public NativeViewHostWrapper,
aura::Window clipping_window_;
std::unique_ptr<gfx::Rect> clip_rect_;
+ // This mask exists for the sake of SetCornerRadius().
+ std::unique_ptr<ui::LayerOwner> mask_;
+
DISALLOW_COPY_AND_ASSIGN(NativeViewHostAura);
};
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 b47d1c2d441..74039d869f0 100644
--- a/chromium/ui/views/controls/native/native_view_host_mac.h
+++ b/chromium/ui/views/controls/native/native_view_host_mac.h
@@ -15,7 +15,7 @@ namespace views {
class NativeViewHost;
// Mac implementation of NativeViewHostWrapper.
-class VIEWS_EXPORT NativeViewHostMac : public NativeViewHostWrapper {
+class NativeViewHostMac : public NativeViewHostWrapper {
public:
explicit NativeViewHostMac(NativeViewHost* host);
~NativeViewHostMac() override;
@@ -25,6 +25,7 @@ class VIEWS_EXPORT NativeViewHostMac : public NativeViewHostWrapper {
void NativeViewDetaching(bool destroyed) override;
void AddedToWidget() override;
void RemovedFromWidget() override;
+ bool SetCornerRadius(int corner_radius) override;
void InstallClip(int x, int y, int w, int h) override;
bool HasInstalledClip() override;
void UninstallClip() override;
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 45a315736a4..cb5553b6634 100644
--- a/chromium/ui/views/controls/native/native_view_host_mac.mm
+++ b/chromium/ui/views/controls/native/native_view_host_mac.mm
@@ -96,6 +96,11 @@ void NativeViewHostMac::RemovedFromWidget() {
NativeViewDetaching(false);
}
+bool NativeViewHostMac::SetCornerRadius(int corner_radius) {
+ NOTIMPLEMENTED();
+ return false;
+}
+
void NativeViewHostMac::InstallClip(int x, int y, int w, int h) {
NOTIMPLEMENTED();
}
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 1f9330b6cfc..d6c58dd4c62 100644
--- a/chromium/ui/views/controls/native/native_view_host_wrapper.h
+++ b/chromium/ui/views/controls/native/native_view_host_wrapper.h
@@ -15,7 +15,7 @@ class NativeViewHost;
// An interface that implemented by an object that wraps a gfx::NativeView on
// a specific platform, used to perform platform specific operations on that
// native view when attached, detached, moved and sized.
-class VIEWS_EXPORT NativeViewHostWrapper {
+class NativeViewHostWrapper {
public:
virtual ~NativeViewHostWrapper() {}
@@ -38,6 +38,10 @@ class VIEWS_EXPORT NativeViewHostWrapper {
// rooted at a valid Widget.
virtual void RemovedFromWidget() = 0;
+ // Sets the corner radius for clipping gfx::NativeView. Returns true on
+ // success or false if the platform doesn't support the operation.
+ virtual bool SetCornerRadius(int corner_radius) = 0;
+
// Installs a clip on the gfx::NativeView. These values are in the coordinate
// space of the Widget, so if this method is called from ShowWidget
// then the values need to be translated.
diff --git a/chromium/ui/views/controls/scroll_view.cc b/chromium/ui/views/controls/scroll_view.cc
index 61f853fe56d..95f4acca864 100644
--- a/chromium/ui/views/controls/scroll_view.cc
+++ b/chromium/ui/views/controls/scroll_view.cc
@@ -763,7 +763,7 @@ void ScrollView::ScrollToOffset(const gfx::ScrollOffset& offset) {
// but will only be invoked (asynchronously) when a Compositor is present
// and commits a frame, which isn't true in some tests.
// See http://crbug.com/637521.
- OnLayerScrolled(offset);
+ OnLayerScrolled(offset, contents_->layer()->element_id());
} else {
contents_->SetPosition(gfx::Point(-offset.x(), -offset.y()));
ScrollHeader();
@@ -787,7 +787,8 @@ void ScrollView::EnableViewPortLayer() {
UpdateBackground();
}
-void ScrollView::OnLayerScrolled(const gfx::ScrollOffset&) {
+void ScrollView::OnLayerScrolled(const gfx::ScrollOffset&,
+ const cc::ElementId&) {
UpdateScrollBarPositions();
ScrollHeader();
}
diff --git a/chromium/ui/views/controls/scroll_view.h b/chromium/ui/views/controls/scroll_view.h
index a39fbbd002b..dfb8f1e1aeb 100644
--- a/chromium/ui/views/controls/scroll_view.h
+++ b/chromium/ui/views/controls/scroll_view.h
@@ -172,7 +172,7 @@ class VIEWS_EXPORT ScrollView : public View, public ScrollBarController {
bool ScrollsWithLayers() const;
// Callback entrypoint when hosted Layers are scrolled by the Compositor.
- void OnLayerScrolled(const gfx::ScrollOffset& offset);
+ void OnLayerScrolled(const gfx::ScrollOffset&, const cc::ElementId&);
// Horizontally scrolls the header (if any) to match the contents.
void ScrollHeader();
diff --git a/chromium/ui/views/controls/scrollbar/base_scroll_bar.h b/chromium/ui/views/controls/scrollbar/base_scroll_bar.h
index 5d077737cfa..7c89c6f2580 100644
--- a/chromium/ui/views/controls/scrollbar/base_scroll_bar.h
+++ b/chromium/ui/views/controls/scrollbar/base_scroll_bar.h
@@ -139,7 +139,7 @@ class VIEWS_EXPORT BaseScrollBar : public ScrollBar,
// Called when the state of the thumb track changes (e.g. by the user
// pressing the mouse button down in it).
- void SetThumbTrackState(CustomButton::ButtonState state);
+ void SetThumbTrackState(Button::ButtonState state);
BaseScrollBarThumb* thumb_;
diff --git a/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.cc b/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.cc
index e2befaee43a..9d8b1a92ae6 100644
--- a/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.cc
+++ b/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.cc
@@ -12,10 +12,9 @@
namespace views {
BaseScrollBarButton::BaseScrollBarButton(ButtonListener* listener)
- : CustomButton(listener),
+ : Button(listener),
repeater_(base::Bind(&BaseScrollBarButton::RepeaterNotifyClick,
- base::Unretained(this))) {
-}
+ base::Unretained(this))) {}
BaseScrollBarButton::~BaseScrollBarButton() {
}
diff --git a/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.h b/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.h
index 6e8716bebb5..245d60f0861 100644
--- a/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.h
+++ b/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.h
@@ -5,7 +5,7 @@
#ifndef UI_VIEWS_CONTROLS_SCROLLBAR_BASE_SCROLL_BAR_BUTTON_H_
#define UI_VIEWS_CONTROLS_SCROLLBAR_BASE_SCROLL_BAR_BUTTON_H_
-#include "ui/views/controls/button/custom_button.h"
+#include "ui/views/controls/button/button.h"
#include "base/macros.h"
#include "build/build_config.h"
@@ -22,7 +22,7 @@ namespace views {
// down on the button.
//
///////////////////////////////////////////////////////////////////////////////
-class VIEWS_EXPORT BaseScrollBarButton : public CustomButton {
+class VIEWS_EXPORT BaseScrollBarButton : public Button {
public:
explicit BaseScrollBarButton(ButtonListener* listener);
~BaseScrollBarButton() override;
diff --git a/chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc b/chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc
index 2cf40e66d18..007df324cc4 100644
--- a/chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc
+++ b/chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc
@@ -20,8 +20,7 @@ BaseScrollBarThumb::BaseScrollBarThumb(BaseScrollBar* scroll_bar)
: scroll_bar_(scroll_bar),
drag_start_position_(-1),
mouse_offset_(-1),
- state_(CustomButton::STATE_NORMAL) {
-}
+ state_(Button::STATE_NORMAL) {}
BaseScrollBarThumb::~BaseScrollBarThumb() {
}
@@ -60,17 +59,17 @@ int BaseScrollBarThumb::GetPosition() const {
}
void BaseScrollBarThumb::OnMouseEntered(const ui::MouseEvent& event) {
- SetState(CustomButton::STATE_HOVERED);
+ SetState(Button::STATE_HOVERED);
}
void BaseScrollBarThumb::OnMouseExited(const ui::MouseEvent& event) {
- SetState(CustomButton::STATE_NORMAL);
+ SetState(Button::STATE_NORMAL);
}
bool BaseScrollBarThumb::OnMousePressed(const ui::MouseEvent& event) {
mouse_offset_ = IsHorizontal() ? event.x() : event.y();
drag_start_position_ = GetPosition();
- SetState(CustomButton::STATE_PRESSED);
+ SetState(Button::STATE_PRESSED);
return true;
}
@@ -104,19 +103,19 @@ bool BaseScrollBarThumb::OnMouseDragged(const ui::MouseEvent& event) {
}
void BaseScrollBarThumb::OnMouseReleased(const ui::MouseEvent& event) {
- SetState(HitTestPoint(event.location()) ?
- CustomButton::STATE_HOVERED : CustomButton::STATE_NORMAL);
+ SetState(HitTestPoint(event.location()) ? Button::STATE_HOVERED
+ : Button::STATE_NORMAL);
}
void BaseScrollBarThumb::OnMouseCaptureLost() {
- SetState(CustomButton::STATE_HOVERED);
+ SetState(Button::STATE_HOVERED);
}
-CustomButton::ButtonState BaseScrollBarThumb::GetState() const {
+Button::ButtonState BaseScrollBarThumb::GetState() const {
return state_;
}
-void BaseScrollBarThumb::SetState(CustomButton::ButtonState state) {
+void BaseScrollBarThumb::SetState(Button::ButtonState state) {
if (state_ == state)
return;
diff --git a/chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.h b/chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.h
index 023b87ee4a8..bf4fccc9329 100644
--- a/chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.h
+++ b/chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.h
@@ -7,7 +7,7 @@
#include "base/macros.h"
#include "ui/gfx/geometry/size.h"
-#include "ui/views/controls/button/custom_button.h"
+#include "ui/views/controls/button/button.h"
#include "ui/views/controls/scrollbar/scroll_bar.h"
#include "ui/views/view.h"
@@ -57,9 +57,9 @@ class VIEWS_EXPORT BaseScrollBarThumb : public View {
void OnMouseReleased(const ui::MouseEvent& event) override;
void OnMouseCaptureLost() override;
- CustomButton::ButtonState GetState() const;
+ Button::ButtonState GetState() const;
// Update our state and schedule a repaint when the mouse moves over us.
- void SetState(CustomButton::ButtonState state);
+ void SetState(Button::ButtonState state);
virtual void OnStateChanged();
bool IsHorizontal() const;
@@ -77,7 +77,7 @@ class VIEWS_EXPORT BaseScrollBarThumb : public View {
int mouse_offset_;
// The current state of the thumb button.
- CustomButton::ButtonState state_;
+ Button::ButtonState state_;
DISALLOW_COPY_AND_ASSIGN(BaseScrollBarThumb);
};
diff --git a/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.mm b/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
index c7e4cd4ac57..6cab3ad1f39 100644
--- a/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
+++ b/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
@@ -103,11 +103,11 @@ CocoaScrollBarThumb::CocoaScrollBarThumb(CocoaScrollBar* scroll_bar)
CocoaScrollBarThumb::~CocoaScrollBarThumb() {}
bool CocoaScrollBarThumb::IsStateHovered() const {
- return GetState() == CustomButton::STATE_HOVERED;
+ return GetState() == Button::STATE_HOVERED;
}
bool CocoaScrollBarThumb::IsStatePressed() const {
- return GetState() == CustomButton::STATE_PRESSED;
+ return GetState() == Button::STATE_PRESSED;
}
gfx::Size CocoaScrollBarThumb::CalculatePreferredSize() const {
@@ -154,8 +154,8 @@ void CocoaScrollBarThumb::OnMouseExited(const ui::MouseEvent& event) {
// The thumb should remain pressed when dragged, even if the mouse leaves
// the scrollview. The thumb will be set back to its hover or normal state
// when the mouse is released.
- if (GetState() != CustomButton::STATE_PRESSED)
- SetState(CustomButton::STATE_NORMAL);
+ if (GetState() != Button::STATE_PRESSED)
+ SetState(Button::STATE_NORMAL);
}
//////////////////////////////////////////////////////////////////
diff --git a/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc b/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc
index 10d1d04e1d8..e62c0c84a1b 100644
--- a/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc
+++ b/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc
@@ -101,12 +101,12 @@ void OverlayScrollBar::Thumb::OnBoundsChanged(
const gfx::Rect& previous_bounds) {
scroll_bar_->Show();
// Don't start the hide countdown if the thumb is still hovered or pressed.
- if (GetState() == CustomButton::STATE_NORMAL)
+ if (GetState() == Button::STATE_NORMAL)
scroll_bar_->StartHideCountdown();
}
void OverlayScrollBar::Thumb::OnStateChanged() {
- if (GetState() == CustomButton::STATE_NORMAL) {
+ if (GetState() == Button::STATE_NORMAL) {
gfx::Transform translation;
const int direction = base::i18n::IsRTL() ? -1 : 1;
translation.Translate(
diff --git a/chromium/ui/views/controls/scrollbar/scroll_bar_views.cc b/chromium/ui/views/controls/scrollbar/scroll_bar_views.cc
index 3dc0527f771..667eee0e1e1 100644
--- a/chromium/ui/views/controls/scrollbar/scroll_bar_views.cc
+++ b/chromium/ui/views/controls/scrollbar/scroll_bar_views.cc
@@ -8,7 +8,7 @@
#include "ui/events/keycodes/keyboard_codes.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/path.h"
-#include "ui/views/controls/button/custom_button.h"
+#include "ui/views/controls/button/button.h"
#include "ui/views/controls/focusable_border.h"
#include "ui/views/controls/scrollbar/base_scroll_bar_button.h"
#include "ui/views/controls/scrollbar/base_scroll_bar_thumb.h"
@@ -91,7 +91,7 @@ ui::NativeTheme::ExtraParams ScrollBarButton::GetNativeThemeParams() const {
ui::NativeTheme::ExtraParams params;
switch (state()) {
- case CustomButton::STATE_HOVERED:
+ case Button::STATE_HOVERED:
params.scrollbar_arrow.is_hovering = true;
break;
default:
@@ -120,15 +120,15 @@ ui::NativeTheme::Part ScrollBarButton::GetNativeThemePart() const {
ui::NativeTheme::State ScrollBarButton::GetNativeThemeState() const {
switch (state()) {
- case CustomButton::STATE_HOVERED:
+ case Button::STATE_HOVERED:
return ui::NativeTheme::kHovered;
- case CustomButton::STATE_PRESSED:
+ case Button::STATE_PRESSED:
return ui::NativeTheme::kPressed;
- case CustomButton::STATE_DISABLED:
+ case Button::STATE_DISABLED:
return ui::NativeTheme::kDisabled;
- case CustomButton::STATE_NORMAL:
+ case Button::STATE_NORMAL:
return ui::NativeTheme::kNormal;
- case CustomButton::STATE_COUNT:
+ case Button::STATE_COUNT:
break;
}
@@ -165,8 +165,7 @@ void ScrollBarThumb::OnPaint(gfx::Canvas* canvas) {
ui::NativeTheme::ExtraParams ScrollBarThumb::GetNativeThemeParams() const {
// This gives the behavior we want.
ui::NativeTheme::ExtraParams params;
- params.scrollbar_thumb.is_hovering =
- (GetState() != CustomButton::STATE_HOVERED);
+ params.scrollbar_thumb.is_hovering = (GetState() != Button::STATE_HOVERED);
return params;
}
@@ -178,15 +177,15 @@ ui::NativeTheme::Part ScrollBarThumb::GetNativeThemePart() const {
ui::NativeTheme::State ScrollBarThumb::GetNativeThemeState() const {
switch (GetState()) {
- case CustomButton::STATE_HOVERED:
+ case Button::STATE_HOVERED:
return ui::NativeTheme::kHovered;
- case CustomButton::STATE_PRESSED:
+ case Button::STATE_PRESSED:
return ui::NativeTheme::kPressed;
- case CustomButton::STATE_DISABLED:
+ case Button::STATE_DISABLED:
return ui::NativeTheme::kDisabled;
- case CustomButton::STATE_NORMAL:
+ case Button::STATE_NORMAL:
return ui::NativeTheme::kNormal;
- case CustomButton::STATE_COUNT:
+ case Button::STATE_COUNT:
break;
}
diff --git a/chromium/ui/views/controls/slider.cc b/chromium/ui/views/controls/slider.cc
index eaa903cb64c..8af93e64099 100644
--- a/chromium/ui/views/controls/slider.cc
+++ b/chromium/ui/views/controls/slider.cc
@@ -20,7 +20,6 @@
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
-#include "ui/native_theme/native_theme.h"
#include "ui/views/widget/widget.h"
namespace {
@@ -184,21 +183,6 @@ void Slider::MoveButtonTo(const gfx::Point& point) {
VALUE_CHANGED_BY_USER);
}
-void Slider::OnPaintFocus(gfx::Canvas* canvas) {
- if (!HasFocus())
- return;
-
- // TODO(estade): make this a glow effect instead: crbug.com/658783
- gfx::Rect focus_bounds = GetLocalBounds();
- focus_bounds.Inset(gfx::Insets(1));
- canvas->DrawSolidFocusRect(
- gfx::RectF(focus_bounds),
- SkColorSetA(GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_FocusedBorderColor),
- 0x99),
- 2);
-}
-
void Slider::OnSliderDragStarted() {
SetHighlighted(true);
if (listener_)
@@ -321,8 +305,6 @@ void Slider::OnPaint(gfx::Canvas* canvas) {
canvas->DrawCircle(
thumb_center,
is_active_ ? kThumbRadius : (kThumbRadius - kThumbStroke / 2), flags);
-
- OnPaintFocus(canvas);
}
void Slider::OnFocus() {
diff --git a/chromium/ui/views/controls/slider.h b/chromium/ui/views/controls/slider.h
index f2dace01954..096b1401836 100644
--- a/chromium/ui/views/controls/slider.h
+++ b/chromium/ui/views/controls/slider.h
@@ -87,8 +87,6 @@ class VIEWS_EXPORT Slider : public View, public gfx::AnimationDelegate {
// Moves the button to the specified point and updates the value accordingly.
void MoveButtonTo(const gfx::Point& point);
- void OnPaintFocus(gfx::Canvas* canvas);
-
// Notify the listener_, if not NULL, that dragging started.
void OnSliderDragStarted();
diff --git a/chromium/ui/views/controls/table/table_view.cc b/chromium/ui/views/controls/table/table_view.cc
index 60657e6988e..e14dd9e9025 100644
--- a/chromium/ui/views/controls/table/table_view.cc
+++ b/chromium/ui/views/controls/table/table_view.cc
@@ -28,10 +28,8 @@
#include "ui/views/controls/table/table_header.h"
#include "ui/views/controls/table/table_utils.h"
#include "ui/views/controls/table/table_view_observer.h"
-
-// Padding around the text (on each side).
-static const int kTextVerticalPadding = 3;
-static const int kTextHorizontalPadding = 6;
+#include "ui/views/layout/layout_provider.h"
+#include "ui/views/style/typography.h"
// Size of images.
static const int kImageSize = 16;
@@ -145,11 +143,16 @@ TableView::TableView(ui::TableModel* model,
single_selection_(single_selection),
select_on_remove_(true),
observer_(NULL),
- row_height_(font_list_.GetHeight() + kTextVerticalPadding * 2),
last_parent_width_(0),
layout_width_(0),
grouper_(NULL),
in_set_visible_column_width_(false) {
+ constexpr int kTextContext = style::CONTEXT_TABLE_ROW;
+ constexpr int kTextStyle = style::STYLE_PRIMARY;
+ font_list_ = style::GetFont(kTextContext, kTextStyle);
+ row_height_ = LayoutProvider::GetControlHeightForFont(kTextContext,
+ kTextStyle, font_list_);
+
for (size_t i = 0; i < columns.size(); ++i) {
VisibleColumn visible_column;
visible_column.column = columns[i];
@@ -551,6 +554,8 @@ void TableView::OnPaint(gfx::Canvas* canvas) {
ui::NativeTheme::kColorId_TableText);
const SkColor selected_fg_color = GetNativeTheme()->GetSystemColor(
selected_text_color_id(HasFocus()));
+ const int cell_margin = GetCellMargin();
+ const int cell_element_spacing = GetCellElementSpacing();
for (int i = region.min_row; i < region.max_row; ++i) {
const int model_index = ViewToModel(i);
const bool is_selected = selection_model_.IsSelected(model_index);
@@ -558,11 +563,11 @@ void TableView::OnPaint(gfx::Canvas* canvas) {
canvas->FillRect(GetRowBounds(i), selected_bg_color);
for (int j = region.min_column; j < region.max_column; ++j) {
const gfx::Rect cell_bounds(GetCellBounds(i, j));
- int text_x = kTextHorizontalPadding + cell_bounds.x();
+ int text_x = cell_margin + cell_bounds.x();
// Provide space for the grouping indicator, but draw it separately.
if (j == 0 && grouper_)
- text_x += kGroupingIndicatorSize + kTextHorizontalPadding;
+ text_x += kGroupingIndicatorSize + cell_element_spacing;
// Always paint the icon in the first visible column.
if (j == 0 && table_type_ == ICON_AND_TEXT) {
@@ -575,17 +580,16 @@ void TableView::OnPaint(gfx::Canvas* canvas) {
cell_bounds.y() + (cell_bounds.height() - kImageSize) / 2,
kImageSize, kImageSize, true);
}
- text_x += kImageSize + kTextHorizontalPadding;
+ text_x += kImageSize + cell_element_spacing;
}
- if (text_x < cell_bounds.right() - kTextHorizontalPadding) {
+ if (text_x < cell_bounds.right() - cell_margin) {
canvas->DrawStringRectWithFlags(
model_->GetText(model_index, visible_columns_[j].column.id),
font_list_, is_selected ? selected_fg_color : fg_color,
gfx::Rect(GetMirroredXWithWidthInView(
- text_x, cell_bounds.right() - text_x - kTextHorizontalPadding),
- cell_bounds.y() + kTextVerticalPadding,
- cell_bounds.right() - text_x,
- cell_bounds.height() - kTextVerticalPadding * 2),
+ text_x, cell_bounds.right() - text_x - cell_margin),
+ cell_bounds.y(), cell_bounds.right() - text_x,
+ row_height_),
TableColumnAlignmentToCanvasAlignment(
visible_columns_[j].column.alignment));
}
@@ -601,8 +605,8 @@ void TableView::OnPaint(gfx::Canvas* canvas) {
grouping_flags.setColor(grouping_color);
grouping_flags.setStyle(cc::PaintFlags::kFill_Style);
grouping_flags.setAntiAlias(true);
- const int group_indicator_x = GetMirroredXInView(GetCellBounds(0, 0).x() +
- kTextHorizontalPadding + kGroupingIndicatorSize / 2);
+ const int group_indicator_x = GetMirroredXInView(
+ GetCellBounds(0, 0).x() + cell_margin + kGroupingIndicatorSize / 2);
for (int i = region.min_row; i < region.max_row; ) {
const int model_index = ViewToModel(i);
GroupRange range;
@@ -648,6 +652,16 @@ void TableView::OnBlur() {
SchedulePaintForSelection();
}
+int TableView::GetCellMargin() const {
+ return LayoutProvider::Get()->GetDistanceMetric(
+ DISTANCE_TABLE_CELL_HORIZONTAL_MARGIN);
+}
+
+int TableView::GetCellElementSpacing() const {
+ return LayoutProvider::Get()->GetDistanceMetric(
+ DISTANCE_RELATED_LABEL_HORIZONTAL);
+}
+
void TableView::NumRowsChanged() {
SortItemsAndUpdateMapping();
PreferredSizeChanged();
@@ -707,16 +721,17 @@ gfx::Rect TableView::GetCellBounds(int row, int visible_column_index) const {
void TableView::AdjustCellBoundsForText(int visible_column_index,
gfx::Rect* bounds) const {
- int text_x = kTextHorizontalPadding + bounds->x();
+ const int cell_margin = GetCellMargin();
+ const int cell_element_spacing = GetCellElementSpacing();
+ int text_x = cell_margin + bounds->x();
if (visible_column_index == 0) {
if (grouper_)
- text_x += kGroupingIndicatorSize + kTextHorizontalPadding;
+ text_x += kGroupingIndicatorSize + cell_element_spacing;
if (table_type_ == ICON_AND_TEXT)
- text_x += kImageSize + kTextHorizontalPadding;
+ text_x += kImageSize + cell_element_spacing;
}
bounds->set_x(text_x);
- bounds->set_width(
- std::max(0, bounds->right() - kTextHorizontalPadding - text_x));
+ bounds->set_width(std::max(0, bounds->right() - cell_margin - text_x));
}
void TableView::CreateHeaderIfNecessary() {
@@ -736,15 +751,17 @@ void TableView::UpdateVisibleColumnSizes() {
for (size_t i = 0; i < visible_columns_.size(); ++i)
columns.push_back(visible_columns_[i].column);
+ const int cell_margin = GetCellMargin();
+ const int cell_element_spacing = GetCellElementSpacing();
int first_column_padding = 0;
if (table_type_ == ICON_AND_TEXT && header_)
- first_column_padding += kImageSize + kTextHorizontalPadding;
+ first_column_padding += kImageSize + cell_element_spacing;
if (grouper_)
- first_column_padding += kGroupingIndicatorSize + kTextHorizontalPadding;
+ first_column_padding += kGroupingIndicatorSize + cell_element_spacing;
std::vector<int> sizes = views::CalculateTableColumnSizes(
layout_width_, first_column_padding, header_->font_list(), font_list_,
- std::max(kTextHorizontalPadding, TableHeader::kHorizontalPadding) * 2,
+ std::max(cell_margin, TableHeader::kHorizontalPadding) * 2,
TableHeader::kSortIndicatorWidth, columns, model_);
DCHECK_EQ(visible_columns_.size(), sizes.size());
int x = 0;
@@ -958,8 +975,9 @@ bool TableView::GetTooltipImpl(const gfx::Point& location,
if (tooltip)
*tooltip = text;
if (tooltip_origin) {
- tooltip_origin->SetPoint(cell_bounds.x(),
- cell_bounds.y() + kTextVerticalPadding);
+ tooltip_origin->SetPoint(
+ cell_bounds.x(),
+ cell_bounds.y() + (row_height_ - font_list_.GetHeight()) / 2);
}
return true;
}
diff --git a/chromium/ui/views/controls/table/table_view.h b/chromium/ui/views/controls/table/table_view.h
index 10d9bd8f11a..c8d3ad23f91 100644
--- a/chromium/ui/views/controls/table/table_view.h
+++ b/chromium/ui/views/controls/table/table_view.h
@@ -219,6 +219,14 @@ class VIEWS_EXPORT TableView
ADVANCE_INCREMENT,
};
+ // Returns the horizontal margin between the bounds of a cell and its
+ // contents.
+ int GetCellMargin() const;
+
+ // Returns the horizontal spacing between elements (grouper, icon, and text)
+ // in a cell.
+ int GetCellElementSpacing() const;
+
// Invoked when the number of rows changes in some way.
void NumRowsChanged();
diff --git a/chromium/ui/views/controls/textfield/textfield.cc b/chromium/ui/views/controls/textfield/textfield.cc
index 5c562f17a37..94be6ec5ba2 100644
--- a/chromium/ui/views/controls/textfield/textfield.cc
+++ b/chromium/ui/views/controls/textfield/textfield.cc
@@ -803,7 +803,7 @@ bool Textfield::CanHandleAccelerators() const {
}
void Textfield::AboutToRequestFocusFromTabTraversal(bool reverse) {
- SelectAll(false);
+ SelectAll(PlatformStyle::kTextfieldScrollsToStartOnFocusChange);
}
bool Textfield::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) {
@@ -1036,6 +1036,11 @@ void Textfield::OnFocus() {
void Textfield::OnBlur() {
gfx::RenderText* render_text = GetRenderText();
render_text->set_focused(false);
+
+ // If necessary, yank the cursor to the logical start of the textfield.
+ if (PlatformStyle::kTextfieldScrollsToStartOnFocusChange)
+ model_->MoveCursorTo(gfx::SelectionModel(0, gfx::CURSOR_FORWARD));
+
if (GetInputMethod()) {
GetInputMethod()->DetachTextInputClient(this);
#if defined(OS_CHROMEOS)
@@ -1115,8 +1120,11 @@ void Textfield::WriteDragDataForView(View* sender,
if (!ui::XVisualManager::GetInstance()->ArgbVisualAvailable())
color = GetBackgroundColor();
#endif
- label.Paint(
- ui::CanvasPainter(&bitmap, label.size(), raster_scale, color).context());
+ label.Paint(PaintInfo::CreateRootPaintInfo(
+ ui::CanvasPainter(&bitmap, label.size(), raster_scale, color,
+ GetWidget()->GetCompositor()->is_pixel_canvas())
+ .context(),
+ label.size()));
const gfx::Vector2d kOffset(-15, 0);
gfx::ImageSkia image(gfx::ImageSkiaRep(bitmap, raster_scale));
data->provider().SetDragImage(image, kOffset);
@@ -1974,6 +1982,9 @@ void Textfield::UpdateCursorVisibility() {
void Textfield::UpdateCursorViewPosition() {
gfx::Rect location(GetRenderText()->GetUpdatedCursorBounds());
location.set_x(GetMirroredXForRect(location));
+ location.set_height(
+ std::min(location.height(),
+ GetContentsBounds().height() - location.y() - location.y()));
cursor_view_.SetBoundsRect(location);
}
diff --git a/chromium/ui/views/controls/textfield/textfield_model.cc b/chromium/ui/views/controls/textfield/textfield_model.cc
index f4d2282c55a..39b56544d3c 100644
--- a/chromium/ui/views/controls/textfield/textfield_model.cc
+++ b/chromium/ui/views/controls/textfield/textfield_model.cc
@@ -256,8 +256,8 @@ namespace {
// representing the target clause (on Windows). Returns an invalid range if
// there is no such a range.
gfx::Range GetFirstEmphasizedRange(const ui::CompositionText& composition) {
- for (size_t i = 0; i < composition.underlines.size(); ++i) {
- const ui::CompositionUnderline& underline = composition.underlines[i];
+ for (size_t i = 0; i < composition.ime_text_spans.size(); ++i) {
+ const ui::ImeTextSpan& underline = composition.ime_text_spans[i];
if (underline.thick)
return gfx::Range(underline.start_offset, underline.end_offset);
}
@@ -659,8 +659,9 @@ void TextfieldModel::SetCompositionText(
base::string16 new_text = text();
render_text_->SetText(new_text.insert(cursor, composition.text));
composition_range_ = gfx::Range(cursor, cursor + composition.text.length());
- // Don't render transparent composition underlines.
- if (composition.underlines.size() > 0 && composition.underlines[0].color != 0)
+ // Don't render transparent IME spans.
+ if (composition.ime_text_spans.size() > 0 &&
+ composition.ime_text_spans[0].underline_color != 0)
render_text_->SetCompositionRange(composition_range_);
else
render_text_->SetCompositionRange(gfx::Range::InvalidRange());
diff --git a/chromium/ui/views/controls/textfield/textfield_model_unittest.cc b/chromium/ui/views/controls/textfield/textfield_model_unittest.cc
index d3722bb15e4..a28fb1e30a9 100644
--- a/chromium/ui/views/controls/textfield/textfield_model_unittest.cc
+++ b/chromium/ui/views/controls/textfield/textfield_model_unittest.cc
@@ -867,7 +867,7 @@ TEST_F(TextfieldModelTest, CompositionTextTest) {
ui::CompositionText composition;
composition.text = base::ASCIIToUTF16("678");
- composition.underlines.push_back(ui::CompositionUnderline(0, 3, 0, false));
+ composition.ime_text_spans.push_back(ui::ImeTextSpan(0, 3, 0, false));
// Cursor should be at the end of composition when characters are just typed.
composition.selection = gfx::Range(3, 3);
@@ -881,15 +881,15 @@ TEST_F(TextfieldModelTest, CompositionTextTest) {
// Restart composition with targeting "67" in "678".
composition.selection = gfx::Range(1, 3);
- composition.underlines.clear();
- composition.underlines.push_back(ui::CompositionUnderline(0, 2, 0, true));
- composition.underlines.push_back(ui::CompositionUnderline(2, 3, 0, false));
+ composition.ime_text_spans.clear();
+ composition.ime_text_spans.push_back(ui::ImeTextSpan(0, 2, 0, true));
+ composition.ime_text_spans.push_back(ui::ImeTextSpan(2, 3, 0, false));
model.SetCompositionText(composition);
EXPECT_TRUE(model.HasCompositionText());
EXPECT_TRUE(model.HasSelection());
#if !defined(OS_CHROMEOS)
// |composition.selection| is ignored because SetCompositionText checks
- // if a bold underline exists first.
+ // if a thick underline exists first.
EXPECT_EQ(gfx::Range(5, 7), model.render_text()->selection());
EXPECT_EQ(7U, model.render_text()->cursor_position());
#else
@@ -922,9 +922,9 @@ TEST_F(TextfieldModelTest, CompositionTextTest) {
composition_text_confirmed_or_cleared_ = false;
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_NONE);
- // Also test the case where a selection exists but a bold underline doesn't.
+ // Also test the case where a selection exists but a thick underline doesn't.
composition.selection = gfx::Range(0, 1);
- composition.underlines.clear();
+ composition.ime_text_spans.clear();
model.SetCompositionText(composition);
EXPECT_STR_EQ("1234567890678", model.text());
EXPECT_TRUE(model.HasSelection());
@@ -1475,7 +1475,7 @@ TEST_F(TextfieldModelTest, UndoRedo_CompositionText) {
ui::CompositionText composition;
composition.text = base::ASCIIToUTF16("abc");
- composition.underlines.push_back(ui::CompositionUnderline(0, 3, 0, false));
+ composition.ime_text_spans.push_back(ui::ImeTextSpan(0, 3, 0, false));
composition.selection = gfx::Range(2, 3);
model.SetText(base::ASCIIToUTF16("ABCDE"));
diff --git a/chromium/ui/views/controls/textfield/textfield_test_api.cc b/chromium/ui/views/controls/textfield/textfield_test_api.cc
index be45d24cc42..bef918aea45 100644
--- a/chromium/ui/views/controls/textfield/textfield_test_api.cc
+++ b/chromium/ui/views/controls/textfield/textfield_test_api.cc
@@ -4,6 +4,8 @@
#include "ui/views/controls/textfield/textfield_test_api.h"
+#include "ui/gfx/geometry/rect.h"
+
namespace views {
TextfieldTestApi::TextfieldTestApi(Textfield* textfield)
@@ -27,4 +29,8 @@ void TextfieldTestApi::ResetTouchSelectionController() {
textfield_->touch_selection_controller_.reset();
}
+void TextfieldTestApi::SetCursorViewRect(gfx::Rect bounds) {
+ textfield_->cursor_view_.SetBoundsRect(bounds);
+}
+
} // namespace views
diff --git a/chromium/ui/views/controls/textfield/textfield_test_api.h b/chromium/ui/views/controls/textfield/textfield_test_api.h
index 8fbc740e73a..8b898715afd 100644
--- a/chromium/ui/views/controls/textfield/textfield_test_api.h
+++ b/chromium/ui/views/controls/textfield/textfield_test_api.h
@@ -45,7 +45,8 @@ class TextfieldTestApi {
return textfield_->cursor_blink_timer_.IsRunning();
}
- gfx::Point GetCursorViewOrigin() { return textfield_->cursor_view_.origin(); }
+ gfx::Rect GetCursorViewRect() { return textfield_->cursor_view_.bounds(); }
+ void SetCursorViewRect(gfx::Rect bounds);
bool IsCursorVisible() const { return textfield_->cursor_view_.visible(); }
diff --git a/chromium/ui/views/controls/textfield/textfield_unittest.cc b/chromium/ui/views/controls/textfield/textfield_unittest.cc
index 40eb7975d50..a58d14fec5f 100644
--- a/chromium/ui/views/controls/textfield/textfield_unittest.cc
+++ b/chromium/ui/views/controls/textfield/textfield_unittest.cc
@@ -258,18 +258,14 @@ bool MockInputMethod::HasComposition() {
}
void MockInputMethod::ClearComposition() {
- composition_.Clear();
+ composition_ = ui::CompositionText();
result_text_.clear();
}
// A Textfield wrapper to intercept OnKey[Pressed|Released]() results.
class TestTextfield : public views::Textfield {
public:
- TestTextfield()
- : Textfield(),
- key_handled_(false),
- key_received_(false),
- weak_ptr_factory_(this) {}
+ TestTextfield() = default;
// ui::TextInputClient overrides:
void InsertChar(const ui::KeyEvent& e) override {
@@ -283,13 +279,18 @@ class TestTextfield : public views::Textfield {
bool key_handled() const { return key_handled_; }
bool key_received() const { return key_received_; }
+ int event_flags() const { return event_flags_; }
- void clear() { key_received_ = key_handled_ = false; }
+ void clear() {
+ key_received_ = key_handled_ = false;
+ event_flags_ = 0;
+ }
private:
// views::View override:
void OnKeyEvent(ui::KeyEvent* event) override {
key_received_ = true;
+ event_flags_ = event->flags();
// Since Textfield::OnKeyPressed() might destroy |this|, get a weak pointer
// and verify it isn't null before writing the bool value to key_handled_.
@@ -306,10 +307,11 @@ class TestTextfield : public views::Textfield {
EXPECT_FALSE(key_handled_);
}
- bool key_handled_;
- bool key_received_;
+ bool key_handled_ = false;
+ bool key_received_ = false;
+ int event_flags_ = 0;
- base::WeakPtrFactory<TestTextfield> weak_ptr_factory_;
+ base::WeakPtrFactory<TestTextfield> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(TestTextfield);
};
@@ -2430,11 +2432,11 @@ TEST_F(TextfieldTest, TextCursorPositionInRTLTest) {
InitTextfield();
// LTR-RTL string in RTL context.
- int text_cursor_position_prev = test_api_->GetCursorViewOrigin().x();
+ int text_cursor_position_prev = test_api_->GetCursorViewRect().x();
SendKeyEvent('a');
SendKeyEvent('b');
EXPECT_STR_EQ("ab", textfield_->text());
- int text_cursor_position_new = test_api_->GetCursorViewOrigin().x();
+ int text_cursor_position_new = test_api_->GetCursorViewRect().x();
// Text cursor stays at same place after inserting new charactors in RTL mode.
EXPECT_EQ(text_cursor_position_prev, text_cursor_position_new);
@@ -2446,11 +2448,11 @@ TEST_F(TextfieldTest, TextCursorPositionInLTRTest) {
InitTextfield();
// LTR-RTL string in LTR context.
- int text_cursor_position_prev = test_api_->GetCursorViewOrigin().x();
+ int text_cursor_position_prev = test_api_->GetCursorViewRect().x();
SendKeyEvent('a');
SendKeyEvent('b');
EXPECT_STR_EQ("ab", textfield_->text());
- int text_cursor_position_new = test_api_->GetCursorViewOrigin().x();
+ int text_cursor_position_new = test_api_->GetCursorViewRect().x();
// Text cursor moves to right after inserting new charactors in LTR mode.
EXPECT_LT(text_cursor_position_prev, text_cursor_position_new);
}
@@ -3191,6 +3193,47 @@ TEST_F(TextfieldTest, CursorVisibility) {
EXPECT_TRUE(test_api_->IsCursorVisible());
}
+// Verify that cursor view height does not exceed the textfield height.
+TEST_F(TextfieldTest, CursorViewHeight) {
+ InitTextfield();
+ textfield_->SetBounds(0, 0, 100, 100);
+ textfield_->SetCursorEnabled(true);
+ SendKeyEvent('a');
+ EXPECT_TRUE(test_api_->IsCursorVisible());
+ EXPECT_GT(textfield_->GetVisibleBounds().height(),
+ test_api_->GetCursorViewRect().height());
+ EXPECT_LE(test_api_->GetCursorViewRect().height(),
+ GetCursorBounds().height());
+
+ // set the cursor height to be higher than the textfield height, verify that
+ // UpdateCursorViewPosition update cursor view height currectly.
+ gfx::Rect cursor_bound(test_api_->GetCursorViewRect());
+ cursor_bound.set_height(150);
+ test_api_->SetCursorViewRect(cursor_bound);
+ SendKeyEvent('b');
+ EXPECT_GT(textfield_->GetVisibleBounds().height(),
+ test_api_->GetCursorViewRect().height());
+ EXPECT_LE(test_api_->GetCursorViewRect().height(),
+ GetCursorBounds().height());
+}
+
+// Verify that cursor view height is independent of its parent view height.
+TEST_F(TextfieldTest, CursorViewHeightAtDiffDSF) {
+ InitTextfield();
+ textfield_->SetBounds(0, 0, 100, 100);
+ textfield_->SetCursorEnabled(true);
+ SendKeyEvent('a');
+ EXPECT_TRUE(test_api_->IsCursorVisible());
+ int height = test_api_->GetCursorViewRect().height();
+
+ // update the size of its parent view size and verify that the height of the
+ // cursor view stays the same.
+ View* parent = textfield_->parent();
+ parent->SetBounds(0, 0, 50, height - 2);
+ SendKeyEvent('b');
+ EXPECT_EQ(height, test_api_->GetCursorViewRect().height());
+}
+
// Check if the text cursor is always at the end of the textfield after the
// text overflows from the textfield. If the textfield size changes, check if
// the text cursor's location is updated accordingly.
@@ -3270,4 +3313,40 @@ TEST_F(TextfieldTest, SwitchFocusInKeyDown) {
EXPECT_EQ(base::ASCIIToUTF16(" "), textfield_->text());
}
+TEST_F(TextfieldTest, FocusChangesScrollToStart) {
+ const std::string& kText = "abcdef";
+ InitTextfield();
+ textfield_->SetText(ASCIIToUTF16(kText));
+ EXPECT_EQ(base::ASCIIToUTF16(std::string()), textfield_->GetSelectedText());
+ textfield_->AboutToRequestFocusFromTabTraversal(false);
+ EXPECT_EQ(base::ASCIIToUTF16(kText), textfield_->GetSelectedText());
+ if (PlatformStyle::kTextfieldScrollsToStartOnFocusChange)
+ EXPECT_EQ(0U, textfield_->GetCursorPosition());
+ else
+ EXPECT_EQ(kText.size(), textfield_->GetCursorPosition());
+
+ // The OnBlur() behavior below is only meaningful on platforms where textfield
+ // focus moves on focus change.
+ if (!PlatformStyle::kTextfieldScrollsToStartOnFocusChange)
+ return;
+
+ SendKeyEvent(ui::VKEY_RIGHT, true, false);
+ EXPECT_EQ(1U, textfield_->GetCursorPosition());
+ textfield_->OnBlur();
+ EXPECT_EQ(0U, textfield_->GetCursorPosition());
+}
+
+TEST_F(TextfieldTest, SendingDeletePreservesShiftFlag) {
+ InitTextfield();
+ SendKeyPress(ui::VKEY_DELETE, 0);
+ EXPECT_EQ(0, textfield_->event_flags());
+ textfield_->clear();
+
+ // Ensure the shift modifier propagates for keys that may be subject to native
+ // key mappings. E.g., on Mac, Delete and Shift+Delete are both
+ // deleteForward:, but the shift modifier should propagate.
+ SendKeyPress(ui::VKEY_DELETE, ui::EF_SHIFT_DOWN);
+ EXPECT_EQ(ui::EF_SHIFT_DOWN, textfield_->event_flags());
+}
+
} // namespace views
diff --git a/chromium/ui/views/corewm/tooltip_controller_unittest.cc b/chromium/ui/views/corewm/tooltip_controller_unittest.cc
index 7603750f987..357e7a3809a 100644
--- a/chromium/ui/views/corewm/tooltip_controller_unittest.cc
+++ b/chromium/ui/views/corewm/tooltip_controller_unittest.cc
@@ -580,7 +580,7 @@ TEST_F(TooltipControllerCaptureTest, DISABLED_CloseOnCaptureLost) {
// Disabled on X11 as DesktopScreenX11::GetWindowAtScreenPoint() doesn't
// consider z-order.
// Disabled on Windows due to failing bots. http://crbug.com/604479
-#if (defined(USE_X11) && !defined(OS_CHROMEOS)) || defined(OS_WIN)
+#if defined(USE_X11) || defined(OS_WIN)
#define MAYBE_Capture DISABLED_Capture
#else
#define MAYBE_Capture Capture
diff --git a/chromium/ui/views/examples/box_layout_example.h b/chromium/ui/views/examples/box_layout_example.h
index 76950459ece..a11fc9e6a80 100644
--- a/chromium/ui/views/examples/box_layout_example.h
+++ b/chromium/ui/views/examples/box_layout_example.h
@@ -38,7 +38,7 @@ class VIEWS_EXAMPLES_EXPORT BoxLayoutExample : public ExampleBase,
void CreateExampleView(View* container) override;
private:
- friend class ChildPanel;
+ friend views::examples::ChildPanel;
// ButtonListener
void ButtonPressed(Button* sender, const ui::Event& event) override;
diff --git a/chromium/ui/views/examples/button_example.cc b/chromium/ui/views/examples/button_example.cc
index a13bb25eb9e..5a0f96989ec 100644
--- a/chromium/ui/views/examples/button_example.cc
+++ b/chromium/ui/views/examples/button_example.cc
@@ -127,7 +127,7 @@ void ButtonExample::ButtonPressed(Button* sender, const ui::Event& event) {
else if (sender == disabled_button_)
LabelButtonPressed(disabled_button_, event);
else if (sender == md_button_ || sender == md_default_button_)
- static_cast<CustomButton*>(sender)->StartThrobbing(5);
+ static_cast<Button*>(sender)->StartThrobbing(5);
else
PrintStatus("Image Button Pressed! count: %d", ++count_);
}
diff --git a/chromium/ui/views/examples/examples_main.cc b/chromium/ui/views/examples/examples_main.cc
index aca55f27e86..15765edf282 100644
--- a/chromium/ui/views/examples/examples_main.cc
+++ b/chromium/ui/views/examples/examples_main.cc
@@ -9,11 +9,11 @@
#include "base/files/file_path.h"
#include "base/i18n/icu_util.h"
#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
#include "base/path_service.h"
#include "base/power_monitor/power_monitor.h"
#include "base/power_monitor/power_monitor_device_source.h"
#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
#include "base/test/test_discardable_memory_allocator.h"
#include "build/build_config.h"
#include "components/viz/host/host_frame_sink_manager.h"
@@ -73,7 +73,8 @@ int main(int argc, char** argv) {
&host_frame_sink_manager_, &frame_sink_manager_);
context_factory->set_use_test_surface(false);
- base::MessageLoopForUI message_loop;
+ base::test::ScopedTaskEnvironment scoped_task_environment(
+ base::test::ScopedTaskEnvironment::MainThreadType::UI);
base::i18n::InitializeICU();
diff --git a/chromium/ui/views/examples/examples_window.cc b/chromium/ui/views/examples/examples_window.cc
index f3b3d0a39fe..ae5e2ab998c 100644
--- a/chromium/ui/views/examples/examples_window.cc
+++ b/chromium/ui/views/examples/examples_window.cc
@@ -11,7 +11,7 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
-#include "base/message_loop/message_loop.h"
+#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/base/models/combobox_model.h"
@@ -190,7 +190,7 @@ class ExamplesWindowContents : public WidgetDelegateView,
void WindowClosing() override {
instance_ = NULL;
if (operation_ == QUIT_ON_CLOSE)
- base::MessageLoop::current()->QuitWhenIdle();
+ base::RunLoop::QuitCurrentWhenIdleDeprecated();
}
gfx::Size CalculatePreferredSize() const override {
return gfx::Size(800, 300);
diff --git a/chromium/ui/views/layout/layout_provider.cc b/chromium/ui/views/layout/layout_provider.cc
index fd7c9c39604..b467de5fdf8 100644
--- a/chromium/ui/views/layout/layout_provider.cc
+++ b/chromium/ui/views/layout/layout_provider.cc
@@ -7,6 +7,8 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
#include "ui/base/material_design/material_design_controller.h"
+#include "ui/gfx/font_list.h"
+#include "ui/views/style/typography.h"
#include "ui/views/views_delegate.h"
namespace views {
@@ -31,35 +33,39 @@ LayoutProvider* LayoutProvider::Get() {
return g_layout_delegate;
}
+// static
+int LayoutProvider::GetControlHeightForFont(int context,
+ int style,
+ const gfx::FontList& font) {
+ return std::max(views::style::GetLineHeight(context, style),
+ font.GetHeight()) +
+ Get()->GetDistanceMetric(DISTANCE_CONTROL_TOTAL_VERTICAL_TEXT_PADDING);
+}
+
gfx::Insets LayoutProvider::GetInsetsMetric(int metric) const {
DCHECK_LT(metric, VIEWS_INSETS_MAX);
switch (metric) {
- case InsetsMetric::INSETS_BUBBLE_CONTENTS:
+ case InsetsMetric::INSETS_DIALOG:
return gfx::Insets(13, 13);
- case InsetsMetric::INSETS_BUBBLE_TITLE: {
- const gfx::Insets bubble_contents =
- GetInsetsMetric(INSETS_BUBBLE_CONTENTS);
- return gfx::Insets(bubble_contents.top(), bubble_contents.left(), 0,
- bubble_contents.right());
- }
- case InsetsMetric::INSETS_CHECKBOX_RADIO_BUTTON:
- return gfx::Insets(5, 6);
case InsetsMetric::INSETS_DIALOG_BUTTON_ROW: {
- const gfx::Insets dialog_contents =
- GetInsetsMetric(INSETS_DIALOG_CONTENTS);
- return gfx::Insets(
- 0, dialog_contents.left(),
- GetDistanceMetric(DISTANCE_DIALOG_BUTTON_BOTTOM_MARGIN),
- dialog_contents.right());
+ const gfx::Insets dialog_insets = GetInsetsMetric(INSETS_DIALOG);
+ return gfx::Insets(0, dialog_insets.left(), dialog_insets.bottom(),
+ dialog_insets.right());
+ }
+ case InsetsMetric::INSETS_DIALOG_CONTENTS: {
+ const gfx::Insets dialog_insets = GetInsetsMetric(INSETS_DIALOG);
+ return gfx::Insets(GetDistanceMetric(DISTANCE_DIALOG_TITLE_TO_CONTENT),
+ dialog_insets.left(),
+ GetDistanceMetric(DISTANCE_DIALOG_CONTENT_TO_BUTTONS),
+ dialog_insets.right());
}
- case InsetsMetric::INSETS_DIALOG_CONTENTS:
- return gfx::Insets(13, 20);
case InsetsMetric::INSETS_DIALOG_TITLE: {
- const gfx::Insets dialog_contents =
- GetInsetsMetric(INSETS_DIALOG_CONTENTS);
- return gfx::Insets(dialog_contents.top(), dialog_contents.left(), 0,
- dialog_contents.right());
+ const gfx::Insets dialog_insets = GetInsetsMetric(INSETS_DIALOG);
+ return gfx::Insets(dialog_insets.top(), dialog_insets.left(), 0,
+ dialog_insets.right());
}
+ case InsetsMetric::INSETS_CHECKBOX_RADIO_BUTTON:
+ return gfx::Insets(5, 6);
case InsetsMetric::INSETS_VECTOR_IMAGE_BUTTON:
return gfx::Insets(4);
}
@@ -76,18 +82,25 @@ int LayoutProvider::GetDistanceMetric(int metric) const {
return 0;
case DistanceMetric::DISTANCE_CLOSE_BUTTON_MARGIN:
return 7;
+ case DistanceMetric::DISTANCE_CONTROL_TOTAL_VERTICAL_TEXT_PADDING:
+ return 6;
+ case DistanceMetric::DISTANCE_DIALOG_CONTENT_TO_BUTTONS:
+ return 13;
+ case DistanceMetric::DISTANCE_DIALOG_TITLE_TO_CONTENT:
+ return 13;
case DistanceMetric::DISTANCE_RELATED_BUTTON_HORIZONTAL:
return 6;
case DistanceMetric::DISTANCE_RELATED_CONTROL_HORIZONTAL:
return 8;
- case DistanceMetric::DISTANCE_BUBBLE_BUTTON_TOP_MARGIN:
case DistanceMetric::DISTANCE_RELATED_CONTROL_VERTICAL:
return 8;
- case DISTANCE_DIALOG_BUTTON_BOTTOM_MARGIN:
- return 20;
case DistanceMetric::DISTANCE_DIALOG_BUTTON_MINIMUM_WIDTH:
return 75;
- case DISTANCE_UNRELATED_CONTROL_VERTICAL:
+ case DistanceMetric::DISTANCE_RELATED_LABEL_HORIZONTAL:
+ return 10;
+ case DistanceMetric::DISTANCE_TABLE_CELL_HORIZONTAL_MARGIN:
+ return 10;
+ case DistanceMetric::DISTANCE_UNRELATED_CONTROL_VERTICAL:
return 20;
}
NOTREACHED();
diff --git a/chromium/ui/views/layout/layout_provider.h b/chromium/ui/views/layout/layout_provider.h
index a5d938668e0..5d76dfd32d5 100644
--- a/chromium/ui/views/layout/layout_provider.h
+++ b/chromium/ui/views/layout/layout_provider.h
@@ -19,20 +19,18 @@ enum InsetsMetric {
// actual Insets: the rest are markers.
VIEWS_INSETS_START = 0,
- // The margins around the contents of a bubble (popover)-style dialog.
- INSETS_BUBBLE_CONTENTS = VIEWS_INSETS_START,
- // The margins around the title of a bubble (popover)-style dialog. The bottom
- // margin is implied by the content insets.
- INSETS_BUBBLE_TITLE,
// Internal border around checkboxes and radio buttons.
- INSETS_CHECKBOX_RADIO_BUTTON,
+ INSETS_CHECKBOX_RADIO_BUTTON = VIEWS_INSETS_START,
+ // The margins around the edges of the dialog.
+ INSETS_DIALOG,
// The margins around the button row of a dialog. The top margin is implied
- // by the content insets.
+ // by the content insets and the other margins overlap with INSETS_DIALOG.
INSETS_DIALOG_BUTTON_ROW,
- // The margins that should be applied around the contents of a dialog.
+ // The margins around the contents of a dialog. The left and right margins
+ // overlap with INSETS_DIALOG.
INSETS_DIALOG_CONTENTS,
// The margins around the icon/title of a dialog. The bottom margin is implied
- // by the content insets.
+ // by the content insets and the other margins overlap with INSETS_DIALOG.
INSETS_DIALOG_TITLE,
// Padding to add to vector image buttons to increase their click and touch
// target size.
@@ -51,11 +49,8 @@ enum DistanceMetric {
// two types have not been interchanged.
VIEWS_DISTANCE_START = VIEWS_INSETS_MAX,
- // If a bubble has buttons, this is the margin between them and the rest of
- // the content.
- DISTANCE_BUBBLE_BUTTON_TOP_MARGIN = VIEWS_DISTANCE_START,
// The default padding to add on each side of a button's label.
- DISTANCE_BUTTON_HORIZONTAL_PADDING,
+ DISTANCE_BUTTON_HORIZONTAL_PADDING = VIEWS_DISTANCE_START,
// The maximum width a button can have and still influence the sizes of
// other linked buttons. This allows short buttons to have linked widths
// without long buttons making things overly wide.
@@ -63,10 +58,16 @@ enum DistanceMetric {
// The distance between a dialog's edge and the close button in the upper
// trailing corner.
DISTANCE_CLOSE_BUTTON_MARGIN,
- // Margin between the bottom edge of a dialog and a contained button.
- DISTANCE_DIALOG_BUTTON_BOTTOM_MARGIN,
+ // The combined vertical padding applied to text in a control.
+ DISTANCE_CONTROL_TOTAL_VERTICAL_TEXT_PADDING,
+ // The distance between the bottom of a dialog's content and the top of the
+ // dialog's button row.
+ DISTANCE_DIALOG_CONTENT_TO_BUTTONS,
// The default minimum width of a dialog button.
DISTANCE_DIALOG_BUTTON_MINIMUM_WIDTH,
+ // The distance between the bottom of a dialog's title and the top of the
+ // dialog's content.
+ DISTANCE_DIALOG_TITLE_TO_CONTENT,
// The spacing between a pair of related horizontal buttons, used for
// dialog layout.
DISTANCE_RELATED_BUTTON_HORIZONTAL,
@@ -75,6 +76,11 @@ enum DistanceMetric {
// The spacing between a pair of related vertical controls, used for
// dialog layout.
DISTANCE_RELATED_CONTROL_VERTICAL,
+ // Horizontal spacing between an item such as an icon or checkbox and a
+ // label related to it.
+ DISTANCE_RELATED_LABEL_HORIZONTAL,
+ // Horizontal margin between a table cell and its contents.
+ DISTANCE_TABLE_CELL_HORIZONTAL_MARGIN,
// Vertical spacing between controls that are logically unrelated.
DISTANCE_UNRELATED_CONTROL_VERTICAL,
@@ -90,6 +96,12 @@ class VIEWS_EXPORT LayoutProvider {
// This should never return nullptr.
static LayoutProvider* Get();
+ // Calculates the control height based on the |font|'s reported glyph height,
+ // the default line spacing and DISTANCE_CONTROL_TOTAL_VERTICAL_TEXT_PADDING.
+ static int GetControlHeightForFont(int context,
+ int style,
+ const gfx::FontList& font);
+
// Returns the insets metric according to the given enumeration element.
virtual gfx::Insets GetInsetsMetric(int metric) const;
diff --git a/chromium/ui/views/linux_ui/linux_ui.h b/chromium/ui/views/linux_ui/linux_ui.h
index bc831d80f8f..844b8a7d62b 100644
--- a/chromium/ui/views/linux_ui/linux_ui.h
+++ b/chromium/ui/views/linux_ui/linux_ui.h
@@ -41,6 +41,7 @@ class Border;
class DeviceScaleFactorObserver;
class LabelButton;
class LabelButtonBorder;
+class NavButtonProvider;
class WindowButtonOrderObserver;
// Adapter class with targets to render like different toolkits. Set by any
@@ -168,6 +169,10 @@ class VIEWS_EXPORT LinuxUI : public ui::LinuxInputMethodContextFactory,
// factor.
virtual void RemoveDeviceScaleFactorObserver(
DeviceScaleFactorObserver* observer) = 0;
+
+ // Returns a new NavButtonProvider, or nullptr if the underlying
+ // toolkit does not support drawing client-side navigation buttons.
+ virtual std::unique_ptr<NavButtonProvider> CreateNavButtonProvider() = 0;
};
} // namespace views
diff --git a/chromium/ui/views/mus/BUILD.gn b/chromium/ui/views/mus/BUILD.gn
index d9242d59cdc..8e836fda997 100644
--- a/chromium/ui/views/mus/BUILD.gn
+++ b/chromium/ui/views/mus/BUILD.gn
@@ -48,7 +48,6 @@ component("mus") {
"//base:i18n",
"//base/third_party/dynamic_annotations",
"//cc",
- "//cc/surfaces",
"//mojo/common",
"//mojo/public/cpp/bindings",
"//net",
diff --git a/chromium/ui/views/mus/OWNERS b/chromium/ui/views/mus/OWNERS
new file mode 100644
index 00000000000..e2906750656
--- /dev/null
+++ b/chromium/ui/views/mus/OWNERS
@@ -0,0 +1,5 @@
+per-file interactive_ui_tests_manifest.json=set noparent
+per-file interactive_ui_tests_manifest.json=file://ipc/SECURITY_OWNERS
+
+per-file unittests_manifest.json=set noparent
+per-file unittests_manifest.json=file://ipc/SECURITY_OWNERS
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 e7d67121103..b1dd981c66d 100644
--- a/chromium/ui/views/mus/desktop_window_tree_host_mus.cc
+++ b/chromium/ui/views/mus/desktop_window_tree_host_mus.cc
@@ -321,8 +321,7 @@ void DesktopWindowTreeHostMus::Init(aura::Window* content_window,
}
if (!params.accept_events) {
- aura::WindowPortMus::Get(window())->SetEventTargetingPolicy(
- ui::mojom::EventTargetingPolicy::NONE);
+ window()->SetEventTargetingPolicy(ui::mojom::EventTargetingPolicy::NONE);
} else {
aura::WindowPortMus::Get(content_window)->SetCanAcceptDrops(true);
}
@@ -540,7 +539,7 @@ gfx::Rect DesktopWindowTreeHostMus::GetWorkAreaBoundsInScreen() const {
}
void DesktopWindowTreeHostMus::SetShape(
- std::unique_ptr<SkRegion> native_region) {
+ std::unique_ptr<Widget::ShapeRects> native_shape) {
NOTIMPLEMENTED();
}
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 d9c5620a0f2..149a66cf9c5 100644
--- a/chromium/ui/views/mus/desktop_window_tree_host_mus.h
+++ b/chromium/ui/views/mus/desktop_window_tree_host_mus.h
@@ -84,7 +84,7 @@ class VIEWS_MUS_EXPORT DesktopWindowTreeHostMus
gfx::Rect GetRestoredBounds() const override;
std::string GetWorkspace() const override;
gfx::Rect GetWorkAreaBoundsInScreen() const override;
- void SetShape(std::unique_ptr<SkRegion> native_region) override;
+ void SetShape(std::unique_ptr<Widget::ShapeRects> native_shape) override;
void Activate() override;
void Deactivate() override;
bool IsActive() const override;
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 ad0db4ba5fe..a8e1fe126a5 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
@@ -5,6 +5,7 @@
#include "ui/views/mus/desktop_window_tree_host_mus.h"
#include "base/debug/stack_trace.h"
+#include "base/run_loop.h"
#include "base/memory/ptr_util.h"
#include "ui/aura/client/cursor_client.h"
diff --git a/chromium/ui/views/mus/drag_interactive_uitest.cc b/chromium/ui/views/mus/drag_interactive_uitest.cc
index a16c1d5b7d6..59a66d4ec21 100644
--- a/chromium/ui/views/mus/drag_interactive_uitest.cc
+++ b/chromium/ui/views/mus/drag_interactive_uitest.cc
@@ -2,6 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
+#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "services/ui/public/interfaces/window_server_test.mojom.h"
#include "services/ui/public/interfaces/window_tree_constants.mojom.h"
@@ -153,7 +154,7 @@ TEST_F(DragTestInteractive, DragTest) {
aura::test::ChangeCompletionWaiter source_waiter(
MusClient::Get()->window_tree_client(), aura::ChangeType::BOUNDS, false);
source_widget->SetBounds(gfx::Rect(0, 0, 20, 20));
- source_waiter.Wait();
+ ASSERT_TRUE(source_waiter.Wait());
Widget* target_widget = CreateTopLevelFramelessPlatformWidget();
TargetView* target_view = new TargetView;
@@ -163,7 +164,7 @@ TEST_F(DragTestInteractive, DragTest) {
aura::test::ChangeCompletionWaiter target_waiter(
MusClient::Get()->window_tree_client(), aura::ChangeType::BOUNDS, false);
target_widget->SetBounds(gfx::Rect(20, 20, 20, 20));
- target_waiter.Wait();
+ ASSERT_TRUE(target_waiter.Wait());
auto* dnwa =
static_cast<DesktopNativeWidgetAura*>(source_widget->native_widget());
diff --git a/chromium/ui/views/mus/screen_mus.h b/chromium/ui/views/mus/screen_mus.h
index a1eae31511d..4987b07edaa 100644
--- a/chromium/ui/views/mus/screen_mus.h
+++ b/chromium/ui/views/mus/screen_mus.h
@@ -19,9 +19,8 @@ namespace views {
class ScreenMusDelegate;
// Screen implementation backed by ui::mojom::DisplayManager.
-class VIEWS_MUS_EXPORT ScreenMus
- : public display::ScreenBase,
- public NON_EXPORTED_BASE(ui::mojom::DisplayManagerObserver) {
+class VIEWS_MUS_EXPORT ScreenMus : public display::ScreenBase,
+ public ui::mojom::DisplayManagerObserver {
public:
explicit ScreenMus(ScreenMusDelegate* delegate);
~ScreenMus() override;
diff --git a/chromium/ui/views/paint_info.cc b/chromium/ui/views/paint_info.cc
new file mode 100644
index 00000000000..fd749599f49
--- /dev/null
+++ b/chromium/ui/views/paint_info.cc
@@ -0,0 +1,127 @@
+// 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/views/paint_info.h"
+
+namespace views {
+
+// static
+PaintInfo PaintInfo::CreateRootPaintInfo(const ui::PaintContext& root_context,
+ const gfx::Size& size) {
+ return PaintInfo(root_context, size);
+}
+
+// static
+PaintInfo PaintInfo::CreateChildPaintInfo(const PaintInfo& parent_paint_info,
+ const gfx::Rect& bounds,
+ const gfx::Size& parent_size,
+ ScaleType scale_type) {
+ return PaintInfo(parent_paint_info, bounds, parent_size, scale_type);
+}
+
+// static
+PaintInfo PaintInfo::ClonePaintInfo(const PaintInfo& parent_paint_info) {
+ return PaintInfo(parent_paint_info,
+ ui::PaintContext::CLONE_WITHOUT_INVALIDATION);
+}
+
+PaintInfo::PaintInfo(const PaintInfo& other,
+ ui::PaintContext::CloneWithoutInvalidation c)
+ : paint_recording_scale_x_(other.paint_recording_scale_x_),
+ paint_recording_scale_y_(other.paint_recording_scale_y_),
+ paint_recording_bounds_(other.paint_recording_bounds_),
+ offset_from_parent_(other.offset_from_parent_),
+ context_(other.context(), c),
+ root_context_(nullptr) {}
+
+PaintInfo::~PaintInfo() {}
+
+bool PaintInfo::IsPixelCanvas() const {
+ return context().is_pixel_canvas();
+}
+
+PaintInfo::PaintInfo(const PaintInfo& other)
+ : paint_recording_scale_x_(other.paint_recording_scale_x_),
+ paint_recording_scale_y_(other.paint_recording_scale_y_),
+ paint_recording_bounds_(other.paint_recording_bounds_),
+ offset_from_parent_(other.offset_from_parent_),
+ context_(other.context(), gfx::Vector2d()),
+ root_context_(nullptr) {}
+
+PaintInfo::PaintInfo(const ui::PaintContext& root_context,
+ const gfx::Size& size)
+ : paint_recording_scale_x_(root_context.is_pixel_canvas()
+ ? root_context.device_scale_factor()
+ : 1.f),
+ paint_recording_scale_y_(paint_recording_scale_x_),
+ paint_recording_bounds_(
+ gfx::ScaleToRoundedRect(gfx::Rect(size), paint_recording_scale_x_)),
+ context_(root_context, gfx::Vector2d()),
+ root_context_(&root_context) {}
+
+PaintInfo::PaintInfo(const PaintInfo& parent_paint_info,
+ const gfx::Rect& bounds,
+ const gfx::Size& parent_size,
+ ScaleType scale_type)
+ : paint_recording_scale_x_(1.f),
+ paint_recording_scale_y_(1.f),
+ paint_recording_bounds_(
+ parent_paint_info.GetSnappedRecordingBounds(parent_size, bounds)),
+ offset_from_parent_(
+ paint_recording_bounds_.OffsetFromOrigin() -
+ parent_paint_info.paint_recording_bounds_.OffsetFromOrigin()),
+ context_(parent_paint_info.context(), offset_from_parent_),
+ root_context_(nullptr) {
+ if (IsPixelCanvas()) {
+ if (scale_type == ScaleType::kUniformScaling) {
+ paint_recording_scale_x_ = paint_recording_scale_y_ =
+ context().device_scale_factor();
+ } else if (scale_type == ScaleType::kScaleWithEdgeSnapping) {
+ if (bounds.size().width() > 0) {
+ paint_recording_scale_x_ =
+ static_cast<float>(paint_recording_bounds_.width()) /
+ static_cast<float>(bounds.size().width());
+ }
+ if (bounds.size().height() > 0) {
+ paint_recording_scale_y_ =
+ static_cast<float>(paint_recording_bounds_.height()) /
+ static_cast<float>(bounds.size().height());
+ }
+ }
+ }
+}
+
+gfx::Rect PaintInfo::GetSnappedRecordingBounds(
+ const gfx::Size& parent_size,
+ const gfx::Rect& child_bounds) const {
+ if (!IsPixelCanvas())
+ return (child_bounds + paint_recording_bounds_.OffsetFromOrigin());
+
+ const gfx::Vector2d& child_origin = child_bounds.OffsetFromOrigin();
+
+ int right = child_origin.x() + child_bounds.width();
+ int bottom = child_origin.y() + child_bounds.height();
+
+ int new_x = std::round(child_origin.x() * context().device_scale_factor());
+ int new_y = std::round(child_origin.y() * context().device_scale_factor());
+
+ int new_right;
+ int new_bottom;
+
+ if (right == parent_size.width())
+ new_right = paint_recording_bounds_.width();
+ else
+ new_right = std::round(right * context().device_scale_factor());
+
+ if (bottom == parent_size.height())
+ new_bottom = paint_recording_bounds_.height();
+ else
+ new_bottom = std::round(bottom * context().device_scale_factor());
+
+ return gfx::Rect(new_x + paint_recording_bounds_.x(),
+ new_y + paint_recording_bounds_.y(), new_right - new_x,
+ new_bottom - new_y);
+}
+
+} // namespace views
diff --git a/chromium/ui/views/paint_info.h b/chromium/ui/views/paint_info.h
new file mode 100644
index 00000000000..7e38d374d5a
--- /dev/null
+++ b/chromium/ui/views/paint_info.h
@@ -0,0 +1,122 @@
+// 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_VIEWS_PAINT_INFO_H_
+#define UI_VIEWS_PAINT_INFO_H_
+
+#include "ui/compositor/paint_context.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/views/views_export.h"
+
+namespace views {
+
+// This class manages the context required during View::Paint(). It is
+// responsible for setting the paint recording size and the paint recording
+// scale factors for an individual View.
+// Each PaintInfo instance has paint recording offset relative to a root
+// PaintInfo.
+// All coordinates are in paint recording space. If pixel canvas is enabled this
+// essentially becomes pixel coordinate space.
+class VIEWS_EXPORT PaintInfo {
+ public:
+ enum class ScaleType {
+ // Scale the recordings by the default device scale factor while maintaining
+ // the aspect ratio. Use this when a view contains an image or icon that
+ // should not get distorted due to scaling.
+ kUniformScaling = 0,
+
+ // Scale the recordings based on the device scale factor but snap to the
+ // parent's bottom or right edge whenever possible. This may lead to minor
+ // distortion and is not recommended to be used with views that contain
+ // images.
+ kScaleWithEdgeSnapping
+ };
+
+ // Instantiates a root PaintInfo. This should only be initialized at the Paint
+ // root, ie., a layer or the root of a widget.
+ static PaintInfo CreateRootPaintInfo(const ui::PaintContext& root_context,
+ const gfx::Size& size);
+
+ // Instantiate a child PaintInfo instance. All bounds for this object are
+ // relative to its root PaintInfo.
+ static PaintInfo CreateChildPaintInfo(const PaintInfo& parent_paint_info,
+ const gfx::Rect& bounds,
+ const gfx::Size& parent_size,
+ ScaleType scale_type);
+
+ // Clones a given paint info, |other|, without the invalidation from its
+ // PaintContext.
+ static PaintInfo ClonePaintInfo(const PaintInfo& other);
+
+ PaintInfo(const PaintInfo& other);
+ ~PaintInfo();
+
+ // Returns true if all paint commands are recorded at pixel size.
+ bool IsPixelCanvas() const;
+
+ const ui::PaintContext& context() const {
+ return root_context_ ? *root_context_ : context_;
+ }
+
+ gfx::Vector2d offset_from_root() const {
+ return paint_recording_bounds_.OffsetFromOrigin();
+ }
+
+ const gfx::Vector2d& offset_from_parent() const {
+ return offset_from_parent_;
+ }
+
+ float paint_recording_scale_x() const { return paint_recording_scale_x_; }
+
+ float paint_recording_scale_y() const { return paint_recording_scale_y_; }
+
+ const gfx::Size& paint_recording_size() const {
+ return paint_recording_bounds_.size();
+ }
+
+ const gfx::Rect& paint_recording_bounds() const {
+ return paint_recording_bounds_;
+ }
+
+ private:
+ friend class PaintInfoTest;
+
+ PaintInfo(const ui::PaintContext& root_context, const gfx::Size& size);
+ PaintInfo(const PaintInfo& parent_paint_info,
+ const gfx::Rect& bounds,
+ const gfx::Size& parent_size,
+ ScaleType scale_type);
+ PaintInfo(const PaintInfo& other,
+ ui::PaintContext::CloneWithoutInvalidation c);
+
+ // Scales the |child_bounds| to its recording bounds based on the
+ // |context.device_scale_factor()|. The recording bounds are snapped to the
+ // parent's right and/or bottom edge if required.
+ // If pixel canvas is disabled, this function returns |child_bounds| as is.
+ gfx::Rect GetSnappedRecordingBounds(const gfx::Size& parent_size,
+ const gfx::Rect& child_bounds) const;
+
+ // The scale at which the paint commands are recorded at. Due to the decimal
+ // rounding and snapping to edges during the scale operation, the effective
+ // paint recording scale may end up being slightly different between the x and
+ // y axis.
+ float paint_recording_scale_x_;
+ float paint_recording_scale_y_;
+
+ // Paint Recording bounds of the view. The offset is relative to the root
+ // PaintInfo.
+ const gfx::Rect paint_recording_bounds_;
+
+ // Offset relative to the parent view's paint recording bounds. Returns 0
+ // offset if this is the root.
+ gfx::Vector2d offset_from_parent_;
+
+ // Compositor PaintContext associated with the view this object belongs to.
+ ui::PaintContext context_;
+ const ui::PaintContext* root_context_;
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_PAINT_INFO_H_
diff --git a/chromium/ui/views/paint_info_unittest.cc b/chromium/ui/views/paint_info_unittest.cc
new file mode 100644
index 00000000000..b0f75630885
--- /dev/null
+++ b/chromium/ui/views/paint_info_unittest.cc
@@ -0,0 +1,254 @@
+// 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/views/paint_info.h"
+
+#include <vector>
+
+#include "base/macros.h"
+#include "base/memory/ref_counted.h"
+#include "cc/base/region.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/compositor/compositor_switches.h"
+#include "ui/compositor/paint_context.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace views {
+namespace {
+
+using PaintInfos = std::vector<std::unique_ptr<PaintInfo>>;
+
+// Device scale factors
+constexpr float DSF100 = 1.f;
+constexpr float DSF125 = 1.25f;
+constexpr float DSF150 = 1.5f;
+constexpr float DSF160 = 1.6f;
+constexpr float DSF166 = 1.66f;
+
+const std::vector<float> kDsfList = {DSF100, DSF125, DSF150, DSF160, DSF166};
+
+constexpr gfx::Size kLayerSize(123, 456);
+
+// ___________
+// | 1 |
+// |___________|
+// | 3 | 4 | 5 | <-- 2 (encapsulates 3, 4 and 5)
+// |___|___|___|
+// | 7 | 8 | <-- 6 (encapsulates 7 and 8)
+// |_______|___|
+//
+// |r_0| encapsulates 1, 2 and 6.
+const gfx::Rect r_0(kLayerSize);
+
+constexpr gfx::Rect r_1(0, 0, 123, 152);
+
+constexpr gfx::Rect r_2(0, 152, 123, 152);
+constexpr gfx::Rect r_3(0, 0, 41, 152);
+constexpr gfx::Rect r_4(41, 0, 41, 152);
+constexpr gfx::Rect r_5(82, 0, 41, 152);
+
+constexpr gfx::Rect r_6(0, 304, 123, 152);
+constexpr gfx::Rect r_7(0, 0, 82, 152);
+constexpr gfx::Rect r_8(82, 0, 41, 152);
+
+// Verifies that the child recording bounds completely cover the parent
+// recording bounds.
+void VerifyChildBoundsCoversParent(const PaintInfo* parent_paint_info,
+ const std::vector<PaintInfo*>& info_list) {
+ cc::Region remaining(gfx::Rect(parent_paint_info->paint_recording_size()));
+ int times_empty = 0;
+ for (auto* const paint_info : info_list) {
+ const gfx::Rect& child_recording_bounds =
+ paint_info->paint_recording_bounds() -
+ parent_paint_info->paint_recording_bounds().OffsetFromOrigin();
+ EXPECT_TRUE(remaining.Contains(child_recording_bounds))
+ << "Remaining: " << remaining.ToString()
+ << " paint recording bounds: " << child_recording_bounds.ToString();
+ remaining.Subtract(child_recording_bounds);
+ times_empty += remaining.IsEmpty();
+ }
+ EXPECT_EQ(times_empty, 1);
+}
+
+void VerifyPixelCanvasCornerScaling(const PaintInfos& info_list) {
+ // child 1, child 2 and child 6 should completely cover child 0.
+ std::vector<PaintInfo*> child_info_list;
+ child_info_list.push_back(info_list[1].get());
+ child_info_list.push_back(info_list[2].get());
+ child_info_list.push_back(info_list[6].get());
+ VerifyChildBoundsCoversParent(info_list[0].get(), child_info_list);
+ child_info_list.clear();
+
+ // Child 3,4 and 5 should completely cover child 2.
+ child_info_list.push_back(info_list[3].get());
+ child_info_list.push_back(info_list[4].get());
+ child_info_list.push_back(info_list[5].get());
+ VerifyChildBoundsCoversParent(info_list[2].get(), child_info_list);
+ child_info_list.clear();
+
+ // Child 7 and 8 should completely cover child 6.
+ child_info_list.push_back(info_list[7].get());
+ child_info_list.push_back(info_list[8].get());
+ VerifyChildBoundsCoversParent(info_list[6].get(), child_info_list);
+ child_info_list.clear();
+}
+
+void VerifyPixelSizesAreSameAsDIPSize(const PaintInfos& info_list) {
+ EXPECT_EQ(info_list[0]->paint_recording_size(), r_0.size());
+
+ EXPECT_EQ(info_list[1]->paint_recording_size(), r_1.size());
+
+ EXPECT_EQ(info_list[2]->paint_recording_size(), r_2.size());
+ EXPECT_EQ(info_list[3]->paint_recording_size(), r_3.size());
+ EXPECT_EQ(info_list[4]->paint_recording_size(), r_4.size());
+ EXPECT_EQ(info_list[5]->paint_recording_size(), r_5.size());
+
+ EXPECT_EQ(info_list[6]->paint_recording_size(), r_6.size());
+ EXPECT_EQ(info_list[7]->paint_recording_size(), r_7.size());
+ EXPECT_EQ(info_list[8]->paint_recording_size(), r_8.size());
+}
+
+} // namespace
+
+class PaintInfoTest : public ::testing::Test {
+ public:
+ PaintInfoTest() {}
+
+ ~PaintInfoTest() override {}
+
+ // ___________
+ // | 1 |
+ // |___________|
+ // | 3 | 4 | 5 | <-- 2 (encapsulates 3, 4 and 5)
+ // |___|___|___|
+ // | 7 | 8 | <-- 6 (encapsulates 7 and 8)
+ // |_______|___|
+ //
+ // |r_0| encapsulates 1, 2 and 6.
+ //
+ // Returns the following arrangement of paint recording bounds for the given
+ // |dsf|
+ PaintInfos GetPaintInfoSetup(const ui::PaintContext& context) {
+ PaintInfos info_list(9);
+
+ info_list[0].reset(new PaintInfo(context, kLayerSize));
+
+ info_list[1].reset(
+ new PaintInfo(*info_list[0], r_1, r_0.size(),
+ PaintInfo::ScaleType::kScaleWithEdgeSnapping));
+
+ info_list[2].reset(
+ new PaintInfo(*info_list[0], r_2, r_0.size(),
+ PaintInfo::ScaleType::kScaleWithEdgeSnapping));
+ info_list[3].reset(
+ new PaintInfo(*info_list[2], r_3, r_2.size(),
+ PaintInfo::ScaleType::kScaleWithEdgeSnapping));
+ info_list[4].reset(
+ new PaintInfo(*info_list[2], r_4, r_2.size(),
+ PaintInfo::ScaleType::kScaleWithEdgeSnapping));
+ info_list[5].reset(
+ new PaintInfo(*info_list[2], r_5, r_2.size(),
+ PaintInfo::ScaleType::kScaleWithEdgeSnapping));
+
+ info_list[6].reset(
+ new PaintInfo(*info_list[0], r_6, r_0.size(),
+ PaintInfo::ScaleType::kScaleWithEdgeSnapping));
+ info_list[7].reset(
+ new PaintInfo(*info_list[6], r_7, r_6.size(),
+ PaintInfo::ScaleType::kScaleWithEdgeSnapping));
+ info_list[8].reset(
+ new PaintInfo(*info_list[6], r_8, r_6.size(),
+ PaintInfo::ScaleType::kScaleWithEdgeSnapping));
+
+ return info_list;
+ }
+
+ void VerifyInvalidationRects(float dsf, bool pixel_canvas_enabled) {
+ std::vector<gfx::Rect> invalidation_rects = {
+ gfx::Rect(0, 0, 123, 41), // Intersects with 0 & 1.
+ gfx::Rect(0, 76, 60, 152), // Intersects 0, 1, 2, 3 & 4.
+ gfx::Rect(41, 152, 41, 152), // Intersects with 0, 2 & 4.
+ gfx::Rect(80, 320, 4, 4), // Intersects with 0, 6, 7 & 8.
+ gfx::Rect(40, 151, 43, 154), // Intersects all
+ gfx::Rect(82, 304, 1, 1), // Intersects with 0, 6 & 8.
+ gfx::Rect(81, 303, 2, 2) // Intersects with 0, 2, 4, 5, 6, 7, 8
+ };
+
+ std::vector<std::vector<int>> repaint_indices = {
+ std::vector<int>{0, 1},
+ std::vector<int>{0, 1, 2, 3, 4},
+ std::vector<int>{0, 2, 4},
+ std::vector<int>{0, 6, 7, 8},
+ std::vector<int>{0, 1, 2, 3, 4, 5, 6, 7, 8},
+ std::vector<int>{0, 6, 8},
+ std::vector<int>{0, 2, 4, 5, 6, 7, 8}};
+
+ PaintInfos info_list;
+
+ EXPECT_EQ(repaint_indices.size(), invalidation_rects.size());
+ for (size_t i = 0; i < invalidation_rects.size(); i++) {
+ ui::PaintContext context(nullptr, dsf, invalidation_rects[i],
+ pixel_canvas_enabled);
+ info_list = GetPaintInfoSetup(context);
+ for (size_t j = 0; j < repaint_indices[i].size(); j++) {
+ EXPECT_TRUE(
+ info_list[repaint_indices[i][j]]->context().IsRectInvalid(gfx::Rect(
+ info_list[repaint_indices[i][j]]->paint_recording_size())));
+ }
+ info_list.clear();
+ }
+ }
+};
+
+TEST_F(PaintInfoTest, CornerScalingPixelCanvasEnabled) {
+ PaintInfos info_list;
+ for (float dsf : kDsfList) {
+ ui::PaintContext context(nullptr, dsf, gfx::Rect(), true);
+ info_list = GetPaintInfoSetup(context);
+ VerifyPixelCanvasCornerScaling(info_list);
+ info_list.clear();
+ }
+
+ // More accurate testing for 1.25 dsf
+ ui::PaintContext context(nullptr, DSF125, gfx::Rect(), true);
+ info_list = GetPaintInfoSetup(context);
+ VerifyPixelCanvasCornerScaling(info_list);
+ EXPECT_EQ(info_list[0]->paint_recording_size(), gfx::Size(154, 570));
+
+ EXPECT_EQ(info_list[1]->paint_recording_size(), gfx::Size(154, 190));
+
+ EXPECT_EQ(info_list[2]->paint_recording_bounds(),
+ gfx::Rect(0, 190, 154, 190));
+ EXPECT_EQ(info_list[3]->paint_recording_size(), gfx::Size(51, 190));
+ EXPECT_EQ(info_list[4]->paint_recording_bounds(),
+ gfx::Rect(51, 190, 52, 190));
+ EXPECT_EQ(info_list[5]->paint_recording_bounds(),
+ gfx::Rect(103, 190, 51, 190));
+
+ EXPECT_EQ(info_list[6]->paint_recording_bounds(),
+ gfx::Rect(0, 380, 154, 190));
+ EXPECT_EQ(info_list[7]->paint_recording_size(), gfx::Size(103, 190));
+ EXPECT_EQ(info_list[8]->paint_recording_bounds(),
+ gfx::Rect(103, 380, 51, 190));
+}
+
+TEST_F(PaintInfoTest, ScalingWithPixelCanvasDisabled) {
+ for (float dsf : kDsfList) {
+ ui::PaintContext context(nullptr, dsf, gfx::Rect(), false);
+ PaintInfos info_list = GetPaintInfoSetup(context);
+ VerifyPixelCanvasCornerScaling(info_list);
+ VerifyPixelSizesAreSameAsDIPSize(info_list);
+ info_list.clear();
+ }
+}
+
+TEST_F(PaintInfoTest, Invalidation) {
+ for (float dsf : kDsfList) {
+ VerifyInvalidationRects(dsf, false);
+ VerifyInvalidationRects(dsf, true);
+ }
+}
+
+} // namespace views
diff --git a/chromium/ui/views/painter.cc b/chromium/ui/views/painter.cc
index d9b9aee168f..d50ef9202bb 100644
--- a/chromium/ui/views/painter.cc
+++ b/chromium/ui/views/painter.cc
@@ -6,6 +6,10 @@
#include "base/logging.h"
#include "base/memory/ptr_util.h"
+#include "ui/compositor/layer.h"
+#include "ui/compositor/layer_delegate.h"
+#include "ui/compositor/layer_owner.h"
+#include "ui/compositor/paint_recorder.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/insets_f.h"
@@ -186,6 +190,40 @@ void ImagePainter::Paint(gfx::Canvas* canvas, const gfx::Size& size) {
nine_painter_->Paint(canvas, gfx::Rect(size));
}
+class PaintedLayer : public ui::LayerOwner, public ui::LayerDelegate {
+ public:
+ explicit PaintedLayer(std::unique_ptr<Painter> painter);
+ ~PaintedLayer() override;
+
+ // LayerDelegate:
+ void OnPaintLayer(const ui::PaintContext& context) override;
+ void OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) override;
+ void OnDeviceScaleFactorChanged(float device_scale_factor) override;
+
+ private:
+ std::unique_ptr<Painter> painter_;
+
+ DISALLOW_COPY_AND_ASSIGN(PaintedLayer);
+};
+
+PaintedLayer::PaintedLayer(std::unique_ptr<Painter> painter)
+ : painter_(std::move(painter)) {
+ SetLayer(base::MakeUnique<ui::Layer>(ui::LAYER_TEXTURED));
+ layer()->set_delegate(this);
+}
+
+PaintedLayer::~PaintedLayer() {}
+
+void PaintedLayer::OnPaintLayer(const ui::PaintContext& context) {
+ ui::PaintRecorder recorder(context, layer()->size());
+ painter_->Paint(recorder.canvas(), layer()->size());
+}
+
+void PaintedLayer::OnDelegatedFrameDamage(const gfx::Rect& damage_rect_in_dip) {
+}
+
+void PaintedLayer::OnDeviceScaleFactorChanged(float device_scale_factor) {}
+
} // namespace
@@ -277,4 +315,10 @@ std::unique_ptr<Painter> Painter::CreateSolidFocusPainter(
return base::MakeUnique<SolidFocusPainter>(color, thickness, insets);
}
+// static
+std::unique_ptr<ui::LayerOwner> Painter::CreatePaintedLayer(
+ std::unique_ptr<Painter> painter) {
+ return base::MakeUnique<PaintedLayer>(std::move(painter));
+}
+
} // namespace views
diff --git a/chromium/ui/views/painter.h b/chromium/ui/views/painter.h
index 57b4fb0a132..cd9672304d8 100644
--- a/chromium/ui/views/painter.h
+++ b/chromium/ui/views/painter.h
@@ -24,6 +24,10 @@ class Rect;
class Size;
}
+namespace ui {
+class LayerOwner;
+}
+
namespace views {
class View;
@@ -89,6 +93,10 @@ class VIEWS_EXPORT Painter {
int thickness,
const gfx::InsetsF& insets);
+ // Creates and returns a texture layer that is painted by |painter|.
+ static std::unique_ptr<ui::LayerOwner> CreatePaintedLayer(
+ std::unique_ptr<Painter> painter);
+
// Returns the minimum size this painter can paint without obvious graphical
// problems (e.g. overlapping images).
virtual gfx::Size GetMinimumSize() const = 0;
diff --git a/chromium/ui/views/style/platform_style.cc b/chromium/ui/views/style/platform_style.cc
index 0b7ed2f41b5..3f7970d6bf1 100644
--- a/chromium/ui/views/style/platform_style.cc
+++ b/chromium/ui/views/style/platform_style.cc
@@ -41,15 +41,16 @@ const bool PlatformStyle::kDefaultLabelButtonHasBoldFont = true;
const bool PlatformStyle::kDialogDefaultButtonCanBeCancel = true;
const bool PlatformStyle::kSelectWordOnRightClick = false;
const bool PlatformStyle::kSelectAllOnRightClickWhenUnfocused = false;
-const CustomButton::NotifyAction PlatformStyle::kMenuNotifyActivationAction =
- CustomButton::NOTIFY_ON_RELEASE;
-const CustomButton::KeyClickAction PlatformStyle::kKeyClickActionOnSpace =
- CustomButton::CLICK_ON_KEY_RELEASE;
+const Button::NotifyAction PlatformStyle::kMenuNotifyActivationAction =
+ Button::NOTIFY_ON_RELEASE;
+const Button::KeyClickAction PlatformStyle::kKeyClickActionOnSpace =
+ Button::CLICK_ON_KEY_RELEASE;
const bool PlatformStyle::kReturnClicksFocusedControl = true;
const bool PlatformStyle::kTreeViewSelectionPaintsEntireRow = false;
const bool PlatformStyle::kTreeViewUsesOpenIcon = true;
const bool PlatformStyle::kUseRipples = true;
const bool PlatformStyle::kMirrorBubbleArrowInRTLByDefault = true;
+const bool PlatformStyle::kTextfieldScrollsToStartOnFocusChange = false;
// static
std::unique_ptr<ScrollBar> PlatformStyle::CreateScrollBar(bool is_horizontal) {
diff --git a/chromium/ui/views/style/platform_style.h b/chromium/ui/views/style/platform_style.h
index ce396891725..025c6743782 100644
--- a/chromium/ui/views/style/platform_style.h
+++ b/chromium/ui/views/style/platform_style.h
@@ -9,7 +9,6 @@
#include "base/macros.h"
#include "ui/views/controls/button/button.h"
-#include "ui/views/controls/button/custom_button.h"
#include "ui/views/views_export.h"
namespace views {
@@ -42,10 +41,10 @@ class VIEWS_EXPORT PlatformStyle {
static const bool kSelectAllOnRightClickWhenUnfocused;
// The menu button's action to show the menu.
- static const CustomButton::NotifyAction kMenuNotifyActivationAction;
+ static const Button::NotifyAction kMenuNotifyActivationAction;
// Whether the Space key clicks a button on key press or key release.
- static const CustomButton::KeyClickAction kKeyClickActionOnSpace;
+ static const Button::KeyClickAction kKeyClickActionOnSpace;
// Whether the Return key clicks the focused control (on key press).
// Otherwise, Return does nothing unless it is handled by an accelerator.
@@ -66,6 +65,10 @@ class VIEWS_EXPORT PlatformStyle {
// opens in the opposite direction.
static const bool kMirrorBubbleArrowInRTLByDefault;
+ // Whether to scroll text fields to the beginning when they gain or lose
+ // focus.
+ static const bool kTextfieldScrollsToStartOnFocusChange;
+
// Creates the default scrollbar for the given orientation.
static std::unique_ptr<ScrollBar> CreateScrollBar(bool is_horizontal);
diff --git a/chromium/ui/views/style/platform_style_mac.mm b/chromium/ui/views/style/platform_style_mac.mm
index e18282bc17f..ab628d6b2c1 100644
--- a/chromium/ui/views/style/platform_style_mac.mm
+++ b/chromium/ui/views/style/platform_style_mac.mm
@@ -20,6 +20,7 @@ const bool PlatformStyle::kDefaultLabelButtonHasBoldFont = false;
const bool PlatformStyle::kDialogDefaultButtonCanBeCancel = false;
const bool PlatformStyle::kSelectWordOnRightClick = true;
const bool PlatformStyle::kSelectAllOnRightClickWhenUnfocused = true;
+const bool PlatformStyle::kTextfieldScrollsToStartOnFocusChange = true;
const bool PlatformStyle::kTreeViewSelectionPaintsEntireRow = true;
const bool PlatformStyle::kTreeViewUsesOpenIcon = false;
const bool PlatformStyle::kUseRipples = false;
@@ -30,11 +31,11 @@ const bool PlatformStyle::kUseRipples = false;
const bool PlatformStyle::kMirrorBubbleArrowInRTLByDefault =
BUILDFLAG(MAC_VIEWS_BROWSER);
-const CustomButton::NotifyAction PlatformStyle::kMenuNotifyActivationAction =
- CustomButton::NOTIFY_ON_PRESS;
+const Button::NotifyAction PlatformStyle::kMenuNotifyActivationAction =
+ Button::NOTIFY_ON_PRESS;
-const CustomButton::KeyClickAction PlatformStyle::kKeyClickActionOnSpace =
- CustomButton::CLICK_ON_KEY_PRESS;
+const Button::KeyClickAction PlatformStyle::kKeyClickActionOnSpace =
+ Button::CLICK_ON_KEY_PRESS;
// On Mac, the Return key is used to perform the default action even when a
// control is focused.
diff --git a/chromium/ui/views/style/typography.h b/chromium/ui/views/style/typography.h
index 29295a41583..36ee1230bfa 100644
--- a/chromium/ui/views/style/typography.h
+++ b/chromium/ui/views/style/typography.h
@@ -41,6 +41,9 @@ enum TextContext {
// Text to label a control, usually next to it. "Body 2". Usually 12pt.
CONTEXT_LABEL,
+ // Text in a table row.
+ CONTEXT_TABLE_ROW,
+
// An editable text field. Usually matches CONTROL_LABEL.
CONTEXT_TEXTFIELD,
diff --git a/chromium/ui/views/style/typography_provider.cc b/chromium/ui/views/style/typography_provider.cc
index f8f7f3774c4..4fd2cd72b08 100644
--- a/chromium/ui/views/style/typography_provider.cc
+++ b/chromium/ui/views/style/typography_provider.cc
@@ -5,11 +5,16 @@
#include "ui/views/style/typography_provider.h"
#include "base/logging.h"
+#include "build/build_config.h"
#include "ui/base/default_style.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/native_theme/native_theme.h"
#include "ui/views/style/typography.h"
+#if defined(OS_MACOSX)
+#include "base/mac/mac_util.h"
+#endif
+
using gfx::Font;
namespace views {
@@ -30,13 +35,27 @@ Font::Weight GetValueBolderThan(Font::Weight weight) {
} // namespace
// static
-Font::Weight TypographyProvider::WeightNotLighterThanNormal(
- Font::Weight weight) {
+Font::Weight TypographyProvider::MediumWeightForUI() {
+#if defined(OS_MACOSX)
+ // System fonts are not user-configurable on Mac, so there's a simpler check.
+ // However, 10.9 and 10.11 do not ship with a MEDIUM weight system font. In
+ // that case, trying to use MEDIUM there will give a bold font, which will
+ // look worse with the surrounding NORMAL text than just using NORMAL.
+ return (base::mac::IsOS10_9() || base::mac::IsOS10_11())
+ ? Font::Weight::NORMAL
+ : Font::Weight::MEDIUM;
+#else
+ // NORMAL may already have at least MEDIUM weight. Return NORMAL in that case
+ // since trying to return MEDIUM would actually make the font lighter-weight
+ // than the surrounding text. For example, Windows can be configured to use a
+ // BOLD font for dialog text; deriving MEDIUM from that would replace the BOLD
+ // attribute with something lighter.
if (ResourceBundle::GetSharedInstance()
.GetFontListWithDelta(0, Font::NORMAL, Font::Weight::NORMAL)
- .GetFontWeight() < weight)
- return weight;
+ .GetFontWeight() < Font::Weight::MEDIUM)
+ return Font::Weight::MEDIUM;
return Font::Weight::NORMAL;
+#endif
}
const gfx::FontList& DefaultTypographyProvider::GetFont(int context,
@@ -90,7 +109,7 @@ void DefaultTypographyProvider::GetDefaultFont(int context,
switch (context) {
case style::CONTEXT_BUTTON_MD:
*size_delta = ui::kLabelFontSizeDelta;
- *font_weight = WeightNotLighterThanNormal(Font::Weight::MEDIUM);
+ *font_weight = MediumWeightForUI();
break;
case style::CONTEXT_DIALOG_TITLE:
*size_delta = ui::kTitleFontSizeDelta;
diff --git a/chromium/ui/views/style/typography_provider.h b/chromium/ui/views/style/typography_provider.h
index 978df456f44..ac67e9890bc 100644
--- a/chromium/ui/views/style/typography_provider.h
+++ b/chromium/ui/views/style/typography_provider.h
@@ -37,13 +37,12 @@ class VIEWS_EXPORT TypographyProvider {
// Gets the line spacing, or 0 if it should be provided by gfx::FontList.
virtual int GetLineHeight(int context, int style) const = 0;
- // The system may indicate a "bold" UI font is preferred (e.g. by selecting
- // the "Bold" checkbox in Windows under "Change only the text size" in
- // Control Panel). In this case, a user's gfx::Weight::NORMAL font will
- // already be bold, and requesting a MEDIUM font will result in a font that is
- // less bold. So this method returns NORMAL, if the NORMAL font is at least as
- // bold as |weight|.
- static gfx::Font::Weight WeightNotLighterThanNormal(gfx::Font::Weight weight);
+ // Returns the weight that will result in the ResourceBundle returning an
+ // appropriate "medium" weight for UI. This caters for systems that are known
+ // to be unable to provide a system font with weight other than NORMAL or BOLD
+ // and for user configurations where the NORMAL font is already BOLD. In both
+ // of these cases, NORMAL is returned instead.
+ static gfx::Font::Weight MediumWeightForUI();
protected:
TypographyProvider() = default;
diff --git a/chromium/ui/views/touchui/touch_selection_controller_impl.cc b/chromium/ui/views/touchui/touch_selection_controller_impl.cc
index 0846f6a0c50..4fa1a8a98e8 100644
--- a/chromium/ui/views/touchui/touch_selection_controller_impl.cc
+++ b/chromium/ui/views/touchui/touch_selection_controller_impl.cc
@@ -10,6 +10,7 @@
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/env.h"
#include "ui/aura/window.h"
+#include "ui/aura/window_targeter.h"
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/geometry/rect.h"
@@ -20,7 +21,6 @@
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/wm/core/coordinate_conversion.h"
-#include "ui/wm/core/masked_window_targeter.h"
namespace {
@@ -206,19 +206,19 @@ namespace views {
typedef TouchSelectionControllerImpl::EditingHandleView EditingHandleView;
-class TouchHandleWindowTargeter : public wm::MaskedWindowTargeter {
+// A WindowTargeter that shifts the hit-test target down - away from the text
+// cursor and expanding the hit-test area just below the visible drag handle.
+class TouchHandleWindowTargeter : public aura::WindowTargeter {
public:
- TouchHandleWindowTargeter(aura::Window* window,
- EditingHandleView* handle_view);
+ TouchHandleWindowTargeter() = default;
+ ~TouchHandleWindowTargeter() override = default;
- ~TouchHandleWindowTargeter() override {}
+ void SetHitTestOffset(int offset) {
+ const gfx::Insets insets(offset, 0, -offset, 0);
+ SetInsets(insets, insets);
+ }
private:
- // wm::MaskedWindowTargeter:
- bool GetHitTestMask(aura::Window* window, gfx::Path* mask) const override;
-
- EditingHandleView* handle_view_;
-
DISALLOW_COPY_AND_ASSIGN(TouchHandleWindowTargeter);
};
@@ -237,8 +237,8 @@ class TouchSelectionControllerImpl::EditingHandleView
widget_.reset(CreateTouchSelectionPopupWidget(context, this));
aura::Window* window = widget_->GetNativeWindow();
- window->SetEventTargeter(std::unique_ptr<ui::EventTargeter>(
- new TouchHandleWindowTargeter(window, this)));
+ targeter_ = new TouchHandleWindowTargeter();
+ window->SetEventTargeter(std::unique_ptr<ui::EventTargeter>(targeter_));
// We are owned by the TouchSelectionControllerImpl.
set_owned_by_client();
@@ -251,20 +251,6 @@ class TouchSelectionControllerImpl::EditingHandleView
}
// Overridden from views::WidgetDelegateView:
- bool WidgetHasHitTestMask() const override { return true; }
-
- void GetWidgetHitTestMask(gfx::Path* mask) const override {
- gfx::Size image_size = image_->Size();
- mask->addRect(
- SkIntToScalar(0),
- SkIntToScalar(selection_bound_.GetHeight() +
- kSelectionHandleVerticalVisualOffset),
- SkIntToScalar(image_size.width()) + 2 * kSelectionHandleHorizPadding,
- SkIntToScalar(selection_bound_.GetHeight() +
- kSelectionHandleVerticalVisualOffset +
- image_size.height() + kSelectionHandleVertPadding));
- }
-
void DeleteDelegate() override {
// We are owned and deleted by TouchSelectionControllerImpl.
}
@@ -366,19 +352,20 @@ class TouchSelectionControllerImpl::EditingHandleView
SchedulePaint();
}
- if (!is_visible)
- return;
-
- selection_bound_.SetEdge(bound.edge_top(), bound.edge_bottom());
+ if (is_visible) {
+ selection_bound_.SetEdge(bound.edge_top(), bound.edge_bottom());
- widget_->SetBounds(GetSelectionWidgetBounds(selection_bound_));
+ widget_->SetBounds(GetSelectionWidgetBounds(selection_bound_));
- aura::Window* window = widget_->GetNativeView();
- gfx::Point edge_top = selection_bound_.edge_top_rounded();
- gfx::Point edge_bottom = selection_bound_.edge_bottom_rounded();
- wm::ConvertPointFromScreen(window, &edge_top);
- wm::ConvertPointFromScreen(window, &edge_bottom);
- selection_bound_.SetEdge(gfx::PointF(edge_top), gfx::PointF(edge_bottom));
+ aura::Window* window = widget_->GetNativeView();
+ gfx::Point edge_top = selection_bound_.edge_top_rounded();
+ gfx::Point edge_bottom = selection_bound_.edge_bottom_rounded();
+ wm::ConvertPointFromScreen(window, &edge_top);
+ wm::ConvertPointFromScreen(window, &edge_bottom);
+ selection_bound_.SetEdge(gfx::PointF(edge_top), gfx::PointF(edge_bottom));
+ }
+ targeter_->SetHitTestOffset(selection_bound_.GetHeight() +
+ kSelectionHandleVerticalVisualOffset);
}
void SetDrawInvisible(bool draw_invisible) {
@@ -392,6 +379,12 @@ class TouchSelectionControllerImpl::EditingHandleView
std::unique_ptr<Widget> widget_;
TouchSelectionControllerImpl* controller_;
+ // A custom targeter 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_;
+
// In local coordinates
gfx::SelectionBound selection_bound_;
gfx::Image* image_;
@@ -416,19 +409,6 @@ class TouchSelectionControllerImpl::EditingHandleView
DISALLOW_COPY_AND_ASSIGN(EditingHandleView);
};
-TouchHandleWindowTargeter::TouchHandleWindowTargeter(
- aura::Window* window,
- EditingHandleView* handle_view)
- : wm::MaskedWindowTargeter(window),
- handle_view_(handle_view) {
-}
-
-bool TouchHandleWindowTargeter::GetHitTestMask(aura::Window* window,
- gfx::Path* mask) const {
- handle_view_->GetWidgetHitTestMask(mask);
- return true;
-}
-
TouchSelectionControllerImpl::TouchSelectionControllerImpl(
ui::TouchEditable* client_view)
: client_view_(client_view),
diff --git a/chromium/ui/views/view.cc b/chromium/ui/views/view.cc
index 19b9a6d98a5..db50dc0720c 100644
--- a/chromium/ui/views/view.cc
+++ b/chromium/ui/views/view.cc
@@ -642,19 +642,6 @@ void View::SetLayoutManager(LayoutManager* layout_manager) {
layout_manager_->Installed(this);
}
-void View::SnapLayerToPixelBoundary() {
- if (!layer())
- return;
-
- if (snap_layer_to_pixel_boundary_ && layer()->parent() &&
- layer()->GetCompositor()) {
- ui::SnapLayerToPhysicalPixelBoundary(layer()->parent(), layer());
- } else {
- // Reset the offset.
- layer()->SetSubpixelPositionOffset(gfx::Vector2dF());
- }
-}
-
// Attributes ------------------------------------------------------------------
const char* View::GetClassName() const {
@@ -845,36 +832,46 @@ void View::SchedulePaintInRect(const gfx::Rect& rect) {
}
}
-void View::Paint(const ui::PaintContext& parent_context) {
+void View::Paint(const PaintInfo& parent_paint_info) {
if (!ShouldPaint())
return;
- ui::PaintContext context(parent_context, GetPaintContextOffset());
+ const gfx::Rect& parent_bounds = !parent()
+ ? GetPaintRecordingBounds()
+ : parent()->GetPaintRecordingBounds();
+
+ PaintInfo paint_info = PaintInfo::CreateChildPaintInfo(
+ parent_paint_info, GetPaintRecordingBounds(), parent_bounds.size(),
+ GetPaintScaleType());
+ const ui::PaintContext& context = paint_info.context();
bool is_invalidated = true;
- if (context.CanCheckInvalid()) {
+ if (paint_info.context().CanCheckInvalid()) {
#if DCHECK_IS_ON()
- gfx::Vector2d offset;
- context.Visited(this);
- View* view = this;
- while (view->parent() && !view->layer()) {
- DCHECK(view->GetTransform().IsIdentity());
- offset += view->GetMirroredPosition().OffsetFromOrigin();
- view = view->parent();
+ if (!context.is_pixel_canvas()) {
+ gfx::Vector2d offset;
+ context.Visited(this);
+ View* view = this;
+ while (view->parent() && !view->layer()) {
+ DCHECK(view->GetTransform().IsIdentity());
+ offset += view->GetMirroredPosition().OffsetFromOrigin();
+ view = view->parent();
+ }
+ // The offset in the PaintContext should be the offset up to the paint
+ // root, which we compute and verify here.
+ DCHECK_EQ(context.PaintOffset().x(), offset.x());
+ DCHECK_EQ(context.PaintOffset().y(), offset.y());
+ // The above loop will stop when |view| is the paint root, which should be
+ // the root of the current paint walk, as verified by storing the root in
+ // the PaintContext.
+ DCHECK_EQ(context.RootVisited(), view);
}
- // The offset in the PaintContext should be the offset up to the paint root,
- // which we compute and verify here.
- DCHECK_EQ(context.PaintOffset().x(), offset.x());
- DCHECK_EQ(context.PaintOffset().y(), offset.y());
- // The above loop will stop when |view| is the paint root, which should be
- // the root of the current paint walk, as verified by storing the root in
- // the PaintContext.
- DCHECK_EQ(context.RootVisited(), view);
#endif
// If the View wasn't invalidated, don't waste time painting it, the output
// would be culled.
- is_invalidated = context.IsRectInvalid(GetLocalBounds());
+ is_invalidated =
+ context.IsRectInvalid(gfx::Rect(paint_info.paint_recording_size()));
}
TRACE_EVENT1("views", "View::Paint", "class", GetClassName());
@@ -883,29 +880,44 @@ void View::Paint(const ui::PaintContext& parent_context) {
// rather than relative to its parent.
// TODO(danakj): Rework clip and transform recorder usage here to use
// std::optional once we can do so.
- ui::ClipRecorder clip_recorder(parent_context);
+ ui::ClipRecorder clip_recorder(parent_paint_info.context());
if (!layer()) {
// Set the clip rect to the bounds of this View, or |clip_path_| if it's
// been set. Note that the X (or left) position we pass to ClipRect takes
// into consideration whether or not the View uses a right-to-left layout so
// that we paint the View in its mirrored position if need be.
if (clip_path_.isEmpty()) {
- clip_recorder.ClipRect(GetMirroredBounds());
+ clip_recorder.ClipRect(gfx::Rect(paint_info.paint_recording_size()) +
+ paint_info.offset_from_parent());
} else {
gfx::Path clip_path_in_parent = clip_path_;
- clip_path_in_parent.offset(GetMirroredX(), y());
+
+ // Transform |clip_path_| from local space to parent recording space.
+ gfx::Transform to_parent_recording_space;
+
+ to_parent_recording_space.Translate(paint_info.offset_from_parent());
+ to_parent_recording_space.Scale(
+ SkFloatToScalar(paint_info.paint_recording_scale_x()),
+ SkFloatToScalar(paint_info.paint_recording_scale_y()));
+
+ clip_path_in_parent.transform(to_parent_recording_space.matrix());
clip_recorder.ClipPathWithAntiAliasing(clip_path_in_parent);
}
}
ui::TransformRecorder transform_recorder(context);
- SetupTransformRecorderForPainting(&transform_recorder);
+ SetupTransformRecorderForPainting(paint_info.offset_from_parent(),
+ &transform_recorder);
// Note that the cache is not aware of the offset of the view
// relative to the parent since painting is always done relative to
// the top left of the individual view.
- if (is_invalidated || !paint_cache_.UseCache(context, size())) {
- ui::PaintRecorder recorder(context, size(), &paint_cache_);
+ if (is_invalidated ||
+ !paint_cache_.UseCache(context, paint_info.paint_recording_size())) {
+ ui::PaintRecorder recorder(context, paint_info.paint_recording_size(),
+ paint_info.paint_recording_scale_x(),
+ paint_info.paint_recording_scale_y(),
+ &paint_cache_);
gfx::Canvas* canvas = recorder.canvas();
gfx::ScopedRTLFlipCanvas scoped_canvas(canvas, width(),
flip_canvas_on_paint_for_rtl_ui_);
@@ -915,7 +927,7 @@ void View::Paint(const ui::PaintContext& parent_context) {
}
// View::Paint() recursion over the subtree.
- PaintChildren(context);
+ PaintChildren(paint_info);
}
void View::SetBackground(std::unique_ptr<Background> b) {
@@ -1543,9 +1555,9 @@ void View::RemovedFromWidget() {}
// Painting --------------------------------------------------------------------
-void View::PaintChildren(const ui::PaintContext& context) {
+void View::PaintChildren(const PaintInfo& paint_info) {
TRACE_EVENT1("views", "View::PaintChildren", "class", GetClassName());
- RecursivePaintHelper(&View::Paint, context);
+ RecursivePaintHelper(&View::Paint, paint_info);
}
void View::OnPaint(gfx::Canvas* canvas) {
@@ -1570,18 +1582,20 @@ void View::OnPaintBorder(gfx::Canvas* canvas) {
// Accelerated Painting --------------------------------------------------------
-gfx::Vector2d View::CalculateOffsetToAncestorWithLayer(
+View::LayerOffsetData View::CalculateOffsetToAncestorWithLayer(
ui::Layer** layer_parent) {
if (layer()) {
if (layer_parent)
*layer_parent = layer();
- return gfx::Vector2d();
+ return LayerOffsetData(layer()->device_scale_factor());
}
if (!parent_)
- return gfx::Vector2d();
+ return LayerOffsetData();
- return gfx::Vector2d(GetMirroredX(), y()) +
+ LayerOffsetData offset_data =
parent_->CalculateOffsetToAncestorWithLayer(layer_parent);
+
+ return offset_data + GetMirroredPosition().OffsetFromOrigin();
}
void View::UpdateParentLayer() {
@@ -1591,25 +1605,27 @@ void View::UpdateParentLayer() {
ui::Layer* parent_layer = NULL;
gfx::Vector2d offset(GetMirroredX(), y());
- if (parent_)
- offset += parent_->CalculateOffsetToAncestorWithLayer(&parent_layer);
+ if (parent_) {
+ offset +=
+ parent_->CalculateOffsetToAncestorWithLayer(&parent_layer).offset();
+ }
ReparentLayer(offset, parent_layer);
}
void View::MoveLayerToParent(ui::Layer* parent_layer,
- const gfx::Point& point) {
- gfx::Point local_point(point);
+ const LayerOffsetData& offset_data) {
+ LayerOffsetData local_offset_data(offset_data);
if (parent_layer != layer())
- local_point.Offset(GetMirroredX(), y());
+ local_offset_data += GetMirroredPosition().OffsetFromOrigin();
+
if (layer() && parent_layer != layer()) {
parent_layer->Add(layer());
- SetLayerBounds(gfx::Rect(local_point.x(), local_point.y(),
- width(), height()));
+ SetLayerBounds(size(), local_offset_data);
} else {
internal::ScopedChildrenLock lock(this);
for (auto* child : children_)
- child->MoveLayerToParent(parent_layer, local_point);
+ child->MoveLayerToParent(parent_layer, local_offset_data);
}
}
@@ -1674,14 +1690,14 @@ void View::NotifyParentsOfLayerChange() {
}
}
-void View::UpdateChildLayerBounds(const gfx::Vector2d& offset) {
+void View::UpdateChildLayerBounds(const LayerOffsetData& offset_data) {
if (layer()) {
- SetLayerBounds(GetLocalBounds() + offset);
+ SetLayerBounds(size(), offset_data);
} else {
internal::ScopedChildrenLock lock(this);
for (auto* child : children_) {
child->UpdateChildLayerBounds(
- offset + gfx::Vector2d(child->GetMirroredX(), child->y()));
+ offset_data + child->GetMirroredPosition().OffsetFromOrigin());
}
}
}
@@ -1697,8 +1713,23 @@ void View::OnDelegatedFrameDamage(
void View::OnDeviceScaleFactorChanged(float device_scale_factor) {
snap_layer_to_pixel_boundary_ =
(device_scale_factor - std::floor(device_scale_factor)) != 0.0f;
- SnapLayerToPixelBoundary();
- // Repainting with new scale factor will paint the content at the right scale.
+
+ if (!layer())
+ return;
+
+ // There can be no subpixel offset if the layer has no parent.
+ if (!parent() || !layer()->parent())
+ return;
+
+ if (layer()->parent() && layer()->GetCompositor() &&
+ layer()->GetCompositor()->is_pixel_canvas()) {
+ LayerOffsetData offset_data(
+ parent()->CalculateOffsetToAncestorWithLayer(nullptr));
+ offset_data += GetMirroredPosition().OffsetFromOrigin();
+ SnapLayerToPixelBoundary(offset_data);
+ } else {
+ SnapLayerToPixelBoundary(LayerOffsetData());
+ }
}
void View::ReorderLayers() {
@@ -1817,6 +1848,10 @@ int View::GetVerticalDragThreshold() {
return kDefaultVerticalDragThreshold;
}
+PaintInfo::ScaleType View::GetPaintScaleType() const {
+ return PaintInfo::ScaleType::kScaleWithEdgeSnapping;
+}
+
// Debugging -------------------------------------------------------------------
#if !defined(NDEBUG)
@@ -1969,14 +2004,16 @@ bool View::ShouldPaint() const {
return visible_ && !size().IsEmpty();
}
-gfx::Vector2d View::GetPaintContextOffset() const {
- // If the View has a layer() then it is a paint root. Otherwise, we need to
- // add the offset from the parent into the total offset from the paint root.
+gfx::Rect View::GetPaintRecordingBounds() const {
+ // If the View has a layer() then it is a paint root and no offset information
+ // is needed. Otherwise, we need bounds that includes an offset from the
+ // parent to add to the total offset from the paint root.
DCHECK(layer() || parent() || origin() == gfx::Point());
- return layer() ? gfx::Vector2d() : GetMirroredPosition().OffsetFromOrigin();
+ return layer() ? GetLocalBounds() : GetMirroredBounds();
}
void View::SetupTransformRecorderForPainting(
+ const gfx::Vector2d& offset_from_parent,
ui::TransformRecorder* recorder) const {
// If the view is backed by a layer, it should paint with itself as the origin
// rather than relative to its parent.
@@ -1986,42 +2023,54 @@ void View::SetupTransformRecorderForPainting(
// Translate the graphics such that 0,0 corresponds to where this View is
// located relative to its parent.
gfx::Transform transform_from_parent;
- gfx::Vector2d offset_from_parent = GetMirroredPosition().OffsetFromOrigin();
transform_from_parent.Translate(offset_from_parent.x(),
offset_from_parent.y());
- transform_from_parent.PreconcatTransform(GetTransform());
recorder->Transform(transform_from_parent);
}
-void View::RecursivePaintHelper(void (View::*func)(const ui::PaintContext&),
- const ui::PaintContext& context) {
+void View::RecursivePaintHelper(void (View::*func)(const PaintInfo&),
+ const PaintInfo& info) {
View::Views children = GetChildrenInZOrder();
DCHECK_EQ(child_count(), static_cast<int>(children.size()));
for (auto* child : children) {
if (!child->layer())
- (child->*func)(context);
+ (child->*func)(info);
}
}
void View::PaintFromPaintRoot(const ui::PaintContext& parent_context) {
- Paint(parent_context);
+ PaintInfo paint_info = PaintInfo::CreateRootPaintInfo(
+ parent_context, layer() ? layer()->size() : size());
+ Paint(paint_info);
if (base::CommandLine::ForCurrentProcess()->HasSwitch(
switches::kDrawViewBoundsRects))
- PaintDebugRects(parent_context);
+ PaintDebugRects(paint_info);
}
-void View::PaintDebugRects(const ui::PaintContext& parent_context) {
+void View::PaintDebugRects(const PaintInfo& parent_paint_info) {
if (!ShouldPaint())
return;
- ui::PaintContext context(parent_context, GetPaintContextOffset());
+ const gfx::Rect& parent_bounds = (layer() || !parent())
+ ? GetPaintRecordingBounds()
+ : parent()->GetPaintRecordingBounds();
+ PaintInfo paint_info = PaintInfo::CreateChildPaintInfo(
+ parent_paint_info, GetPaintRecordingBounds(), parent_bounds.size(),
+ GetPaintScaleType());
+
+ const ui::PaintContext& context = paint_info.context();
+
ui::TransformRecorder transform_recorder(context);
- SetupTransformRecorderForPainting(&transform_recorder);
+ SetupTransformRecorderForPainting(paint_info.offset_from_parent(),
+ &transform_recorder);
- RecursivePaintHelper(&View::PaintDebugRects, context);
+ RecursivePaintHelper(&View::PaintDebugRects, paint_info);
// Draw outline rects for debugging.
- ui::PaintRecorder recorder(context, size());
+ ui::PaintRecorder recorder(context, paint_info.paint_recording_size(),
+ paint_info.paint_recording_scale_x(),
+ paint_info.paint_recording_scale_y(),
+ &paint_cache_);
gfx::Canvas* canvas = recorder.canvas();
const float scale = canvas->UndoDeviceScaleFactor();
gfx::RectF outline_rect(ScaleToEnclosedRect(GetLocalBounds(), scale));
@@ -2180,6 +2229,23 @@ void View::VisibilityChangedImpl(View* starting_from, bool is_visible) {
VisibilityChanged(starting_from, is_visible);
}
+void View::SnapLayerToPixelBoundary(const LayerOffsetData& offset_data) {
+ if (!layer())
+ return;
+
+ if (snap_layer_to_pixel_boundary_ && layer()->parent() &&
+ layer()->GetCompositor()) {
+ if (layer()->GetCompositor()->is_pixel_canvas()) {
+ layer()->SetSubpixelPositionOffset(offset_data.GetSubpixelOffset());
+ } else {
+ ui::SnapLayerToPhysicalPixelBoundary(layer()->parent(), layer());
+ }
+ } else {
+ // Reset the offset.
+ layer()->SetSubpixelPositionOffset(gfx::Vector2dF());
+ }
+}
+
void View::BoundsChanged(const gfx::Rect& previous_bounds) {
if (visible_) {
// Paint the new bounds.
@@ -2190,11 +2256,13 @@ void View::BoundsChanged(const gfx::Rect& previous_bounds) {
if (layer()) {
if (parent_) {
- SetLayerBounds(GetLocalBounds() +
- gfx::Vector2d(GetMirroredX(), y()) +
- parent_->CalculateOffsetToAncestorWithLayer(NULL));
+ LayerOffsetData offset_data(
+ parent_->CalculateOffsetToAncestorWithLayer(nullptr));
+ offset_data += GetMirroredPosition().OffsetFromOrigin();
+ SetLayerBounds(size(), offset_data);
} else {
- SetLayerBounds(bounds_);
+ SetLayerBounds(bounds_.size(),
+ LayerOffsetData() + bounds_.OffsetFromOrigin());
}
// In RTL mode, if our width has changed, our children's mirrored bounds
@@ -2204,7 +2272,8 @@ void View::BoundsChanged(const gfx::Rect& previous_bounds) {
for (int i = 0; i < child_count(); ++i) {
View* child = child_at(i);
child->UpdateChildLayerBounds(
- gfx::Vector2d(child->GetMirroredX(), child->y()));
+ LayerOffsetData(layer()->device_scale_factor(),
+ child->GetMirroredPosition().OffsetFromOrigin()));
}
}
} else {
@@ -2284,9 +2353,10 @@ void View::RemoveDescendantToNotify(View* view) {
descendants_to_notify_.reset();
}
-void View::SetLayerBounds(const gfx::Rect& bounds) {
- layer()->SetBounds(bounds);
- SnapLayerToPixelBoundary();
+void View::SetLayerBounds(const gfx::Size& size,
+ const LayerOffsetData& offset_data) {
+ layer()->SetBounds(gfx::Rect(size) + offset_data.offset());
+ SnapLayerToPixelBoundary(offset_data);
}
// Transformations -------------------------------------------------------------
@@ -2423,7 +2493,7 @@ void View::ReparentLayer(const gfx::Vector2d& offset, ui::Layer* parent_layer) {
if (parent_layer)
parent_layer->Add(layer());
layer()->SchedulePaint(GetLocalBounds());
- MoveLayerToParent(layer(), gfx::Point());
+ MoveLayerToParent(layer(), LayerOffsetData(layer()->device_scale_factor()));
}
// Input -----------------------------------------------------------------------
@@ -2620,15 +2690,6 @@ void View::PropagateThemeChanged() {
OnThemeChanged();
}
-void View::PropagateLocaleChanged() {
- {
- internal::ScopedChildrenLock lock(this);
- for (auto* child : base::Reversed(children_))
- child->PropagateLocaleChanged();
- }
- OnLocaleChanged();
-}
-
void View::PropagateDeviceScaleFactorChanged(float device_scale_factor) {
{
internal::ScopedChildrenLock lock(this);
diff --git a/chromium/ui/views/view.h b/chromium/ui/views/view.h
index 7a8a7b327eb..33f393275cb 100644
--- a/chromium/ui/views/view.h
+++ b/chromium/ui/views/view.h
@@ -37,6 +37,7 @@
#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/path.h"
+#include "ui/views/paint_info.h"
#include "ui/views/view_targeter.h"
#include "ui/views/views_export.h"
@@ -165,6 +166,96 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
View* move_view;
};
+ // During paint, the origin of each view in physical pixel is calculated by
+ // view_origin_pixel = ROUND(view.origin() * device_scale_factor)
+ //
+ // Thus in a view hierarchy, the offset between two views, view_i and view_j,
+ // is calculated by:
+ // view_offset_ij_pixel = SUM [view_origin_pixel.OffsetFromOrigin()]
+ // {For all views along the path from view_i to view_j}
+ //
+ // But the offset between the two layers, the layer in view_i and the layer in
+ // view_j, is computed by
+ // view_offset_ij_dip = SUM [view.origin().OffsetFromOrigin()]
+ // {For all views along the path from view_i to view_j}
+ //
+ // layer_offset_ij_pixel = ROUND (view_offset_ij_dip * device_scale_factor)
+ //
+ // Due to this difference in the logic for computation of offset, the values
+ // view_offset_ij_pixel and layer_offset_ij_pixel may not always be equal.
+ // They will differ by some subpixel_offset. This leads to bugs like
+ // crbug.com/734787.
+ // The subpixel offset needs to be applied to the layer to get the correct
+ // output during paint.
+ //
+ // This class manages the computation of subpixel offset internally when
+ // working with offsets.
+ class LayerOffsetData {
+ public:
+ LayerOffsetData(float device_scale_factor = 1.f,
+ const gfx::Vector2d& offset = gfx::Vector2d())
+ : device_scale_factor_(device_scale_factor) {
+ AddOffset(offset);
+ }
+
+ const gfx::Vector2d& offset() const { return offset_; }
+
+ const gfx::Vector2dF GetSubpixelOffset() const {
+ // |rounded_pixel_offset_| is stored in physical pixel space. Convert it
+ // into DIP space before returning.
+ gfx::Vector2dF subpixel_offset(rounded_pixel_offset_);
+ subpixel_offset.Scale(1.f / device_scale_factor_);
+ return subpixel_offset;
+ }
+
+ LayerOffsetData& operator+=(const gfx::Vector2d& offset) {
+ AddOffset(offset);
+ return *this;
+ }
+
+ LayerOffsetData operator+(const gfx::Vector2d& offset) const {
+ LayerOffsetData offset_data(*this);
+ offset_data.AddOffset(offset);
+ return offset_data;
+ }
+
+ private:
+ // Adds the |offset_to_parent| to the total |offset_| and updates the
+ // |rounded_pixel_offset_| value.
+ void AddOffset(const gfx::Vector2d& offset_to_parent) {
+ // Add the DIP |offset_to_parent| amount to the total offset.
+ offset_ += offset_to_parent;
+
+ // Convert |offset_to_parent| to physical pixel coordinates.
+ gfx::Vector2dF fractional_pixel_offset(
+ offset_to_parent.x() * device_scale_factor_,
+ offset_to_parent.y() * device_scale_factor_);
+
+ // Since pixels cannot be fractional, we need to round the offset to get
+ // the correct physical pixel coordinate.
+ gfx::Vector2dF integral_pixel_offset(
+ gfx::ToRoundedInt(fractional_pixel_offset.x()),
+ gfx::ToRoundedInt(fractional_pixel_offset.y()));
+
+ // |integral_pixel_offset - fractional_pixel_offset| gives the subpixel
+ // offset amount for |offset_to_parent|. This is added to
+ // |rounded_pixel_offset_| to update the total subpixel offset.
+ rounded_pixel_offset_ += integral_pixel_offset - fractional_pixel_offset;
+ }
+
+ // Total offset so far. This stores the offset between two nodes in the view
+ // hierarchy.
+ gfx::Vector2d offset_;
+
+ // This stores the value such that if added to
+ // |offset_ * device_scale_factor| will give the correct aligned offset in
+ // physical pixels.
+ gfx::Vector2dF rounded_pixel_offset_;
+
+ // The device scale factor at which the subpixel offset is being computed.
+ float device_scale_factor_;
+ };
+
// Creation and lifetime -----------------------------------------------------
View();
@@ -424,10 +515,6 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
LayoutManager* GetLayoutManager() const;
void SetLayoutManager(LayoutManager* layout);
- // Adjust the layer's offset so that it snaps to the physical pixel boundary.
- // This has no effect if the view does not have an associated layer.
- void SnapLayerToPixelBoundary();
-
// Attributes ----------------------------------------------------------------
// The view class name.
@@ -543,7 +630,7 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// for View coordinates and language direction as required, allows the View
// to paint itself via the various OnPaint*() event handlers and then paints
// the hierarchy beneath it.
- void Paint(const ui::PaintContext& parent_context);
+ void Paint(const PaintInfo& parent_paint_info);
// The background object may be null.
void SetBackground(std::unique_ptr<Background> b);
@@ -1152,7 +1239,7 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Responsible for calling Paint() on child Views. Override to control the
// order child Views are painted.
- virtual void PaintChildren(const ui::PaintContext& context);
+ virtual void PaintChildren(const PaintInfo& info);
// Override to provide rendering in any part of the View's bounds. Typically
// this is the "contents" of the view. If you override this method you will
@@ -1167,11 +1254,18 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Override to paint a border not specified by SetBorder().
virtual void OnPaintBorder(gfx::Canvas* canvas);
+ // Returns the type of scaling to be done for this View. Override this to
+ // change the default scaling type from |kScaleToFit|. You would want to
+ // override this for a view and return |kScaleToScaleFactor| in cases where
+ // scaling should cause no distortion. Such as in the case of an image or
+ // an icon.
+ virtual PaintInfo::ScaleType GetPaintScaleType() const;
+
// Accelerated painting ------------------------------------------------------
// Returns the offset from this view to the nearest ancestor with a layer. If
// |layer_parent| is non-NULL it is set to the nearest ancestor with a layer.
- virtual gfx::Vector2d CalculateOffsetToAncestorWithLayer(
+ virtual LayerOffsetData CalculateOffsetToAncestorWithLayer(
ui::Layer** layer_parent);
// Updates the view's layer's parent. Called when a view is added to a view
@@ -1184,11 +1278,12 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// recurses through all children. This is used when adding a layer to an
// existing view to make sure all descendants that have layers are parented to
// the right layer.
- void MoveLayerToParent(ui::Layer* parent_layer, const gfx::Point& point);
+ void MoveLayerToParent(ui::Layer* parent_layer,
+ const LayerOffsetData& offset_data);
// Called to update the bounds of any child layers within this View's
// hierarchy when something happens to the hierarchy.
- void UpdateChildLayerBounds(const gfx::Vector2d& offset);
+ void UpdateChildLayerBounds(const LayerOffsetData& offset_data);
// Overridden from ui::LayerDelegate:
void OnPaintLayer(const ui::PaintContext& context) override;
@@ -1235,11 +1330,6 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Widget::ThemeChanged().
virtual void OnThemeChanged() {}
- // Called when the locale has changed, overriding allows individual Views to
- // update locale-dependent strings.
- // To dispatch a locale changed notification, call Widget::LocaleChanged().
- virtual void OnLocaleChanged() {}
-
// Tooltips ------------------------------------------------------------------
// Views must invoke this when the tooltip text they are to display changes.
@@ -1296,6 +1386,10 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
friend class ViewLayerTest;
friend class Widget;
+ FRIEND_TEST_ALL_PREFIXES(ViewTest, PaintWithMovedViewUsesCache);
+ FRIEND_TEST_ALL_PREFIXES(ViewTest, PaintWithMovedViewUsesCacheInRTL);
+ FRIEND_TEST_ALL_PREFIXES(ViewTest, PaintWithUnknownInvalidation);
+
// Painting -----------------------------------------------------------------
enum SchedulePaintType {
@@ -1319,17 +1413,19 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// during painting.
bool ShouldPaint() const;
- // Returns the offset that should be used when constructing the paint context
+ // Returns the bounds that should be used when constructing the |PaintInfo|
// for this view.
- gfx::Vector2d GetPaintContextOffset() const;
+ gfx::Rect GetPaintRecordingBounds() const;
// Adjusts the transform of |recorder| in advance of painting.
- void SetupTransformRecorderForPainting(ui::TransformRecorder* recorder) const;
+ void SetupTransformRecorderForPainting(
+ const gfx::Vector2d& offset_from_parent,
+ ui::TransformRecorder* recorder) const;
// Recursively calls the painting method |func| on all non-layered children,
// in Z order.
- void RecursivePaintHelper(void (View::*func)(const ui::PaintContext&),
- const ui::PaintContext& context);
+ void RecursivePaintHelper(void (View::*func)(const PaintInfo&),
+ const PaintInfo& info);
// Invokes Paint() and, if necessary, PaintDebugRects(). Should be called
// only on the root of a widget/layer. PaintDebugRects() is invoked as a
@@ -1340,7 +1436,7 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Draws a semitransparent rect to indicate the bounds of this view.
// Recursively does the same for all children. Invoked only with
// --draw-view-bounds-rects.
- void PaintDebugRects(const ui::PaintContext& parent_context);
+ void PaintDebugRects(const PaintInfo& paint_info);
// Tree operations -----------------------------------------------------------
@@ -1412,9 +1508,6 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
void AddDescendantToNotify(View* view);
void RemoveDescendantToNotify(View* view);
- // Sets the layer's bounds given in DIP coordinates.
- void SetLayerBounds(const gfx::Rect& bounds_in_dip);
-
// Transformations -----------------------------------------------------------
// Returns in |transform| the transform to get from coordinates of |ancestor|
@@ -1492,6 +1585,14 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// this subtree.
void OrphanLayers();
+ // Adjust the layer's offset so that it snaps to the physical pixel boundary.
+ // This has no effect if the view does not have an associated layer.
+ void SnapLayerToPixelBoundary(const LayerOffsetData& offset_data);
+
+ // Sets the layer's bounds given in DIP coordinates.
+ void SetLayerBounds(const gfx::Size& size_in_dip,
+ const LayerOffsetData& layer_offset_data);
+
// Input ---------------------------------------------------------------------
bool ProcessMousePressed(const ui::MouseEvent& event);
@@ -1525,10 +1626,6 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// views in the hierarchy.
void PropagateThemeChanged();
- // Used to propagate locale changed notifications from the root view to all
- // views in the hierarchy.
- void PropagateLocaleChanged();
-
// Used to propagate device scale factor changed notifications from the root
// view to all views in the hierarchy.
void PropagateDeviceScaleFactorChanged(float device_scale_factor);
diff --git a/chromium/ui/views/view_properties.cc b/chromium/ui/views/view_properties.cc
index 3f5d1c3539a..7fe9d82e504 100644
--- a/chromium/ui/views/view_properties.cc
+++ b/chromium/ui/views/view_properties.cc
@@ -6,6 +6,11 @@
#include "ui/gfx/geometry/insets.h"
+#if !defined(USE_AURA)
+// aura_constants.cc also declared the bool ClassProperty type.
+DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT, bool);
+#endif
+
DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT, gfx::Insets*);
namespace views {
diff --git a/chromium/ui/views/view_tracker.cc b/chromium/ui/views/view_tracker.cc
index c1391ab2936..4d2032a8eb1 100644
--- a/chromium/ui/views/view_tracker.cc
+++ b/chromium/ui/views/view_tracker.cc
@@ -8,7 +8,7 @@
namespace views {
-ViewTracker::ViewTracker(View* view) : view_(view) {
+ViewTracker::ViewTracker(View* view) : view_(nullptr) {
SetView(view);
}
diff --git a/chromium/ui/views/view_tracker_unittest.cc b/chromium/ui/views/view_tracker_unittest.cc
index 34f48cf0ac9..998d234e5b9 100644
--- a/chromium/ui/views/view_tracker_unittest.cc
+++ b/chromium/ui/views/view_tracker_unittest.cc
@@ -4,6 +4,7 @@
#include "ui/views/view_tracker.h"
+#include "base/memory/ptr_util.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/view.h"
@@ -21,4 +22,14 @@ TEST_F(ViewTrackerTest, RemovedOnDelete) {
EXPECT_EQ(nullptr, tracker.view());
}
+TEST_F(ViewTrackerTest, ObservedAtConstruction) {
+ std::unique_ptr<ViewTracker> tracker;
+ {
+ View view;
+ tracker = base::MakeUnique<ViewTracker>(&view);
+ EXPECT_EQ(&view, tracker->view());
+ }
+ EXPECT_EQ(nullptr, tracker->view());
+}
+
} // namespace views
diff --git a/chromium/ui/views/view_unittest.cc b/chromium/ui/views/view_unittest.cc
index 1dbb59e20cc..3dcb6b01b5f 100644
--- a/chromium/ui/views/view_unittest.cc
+++ b/chromium/ui/views/view_unittest.cc
@@ -9,10 +9,12 @@
#include <map>
#include <memory>
+#include "base/command_line.h"
#include "base/i18n/rtl.h"
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "base/rand_util.h"
+#include "base/run_loop.h"
#include "base/strings/string_util.h"
#include "base/strings/stringprintf.h"
#include "base/strings/utf_string_conversions.h"
@@ -22,6 +24,7 @@
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/l10n/l10n_util.h"
#include "ui/compositor/compositor.h"
+#include "ui/compositor/compositor_switches.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animator.h"
#include "ui/compositor/paint_context.h"
@@ -40,6 +43,7 @@
#include "ui/views/controls/native/native_view_host.h"
#include "ui/views/controls/scroll_view.h"
#include "ui/views/controls/textfield/textfield.h"
+#include "ui/views/paint_info.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/view_observer.h"
#include "ui/views/widget/native_widget.h"
@@ -527,7 +531,9 @@ TEST_F(ViewTest, PaintEmptyView) {
// Paint "everything".
gfx::Rect first_paint(1, 1);
auto list = base::MakeRefCounted<cc::DisplayItemList>();
- root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, first_paint, false),
+ first_paint.size()));
// The empty view has nothing to paint so it doesn't try build a cache, nor do
// its children which would be clipped by its (empty) self.
@@ -548,8 +554,8 @@ TEST_F(ViewTest, PaintWithMovedViewUsesCache) {
gfx::Rect pixel_rect = gfx::Rect(1, 1);
float device_scale_factor = 1.f;
auto list = base::MakeRefCounted<cc::DisplayItemList>();
- root_view->Paint(
- ui::PaintContext(list.get(), device_scale_factor, pixel_rect));
+ root_view->PaintFromPaintRoot(
+ ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false));
EXPECT_TRUE(v1->did_paint_);
v1->Reset();
// The visual rects for (clip, drawing, transform) should be in layer space.
@@ -564,15 +570,15 @@ TEST_F(ViewTest, PaintWithMovedViewUsesCache) {
// If invalidation doesn't intersect v1, we paint with the cache.
list = base::MakeRefCounted<cc::DisplayItemList>();
- root_view->Paint(
- ui::PaintContext(list.get(), device_scale_factor, pixel_rect));
+ root_view->PaintFromPaintRoot(
+ ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false));
EXPECT_FALSE(v1->did_paint_);
v1->Reset();
// If invalidation does intersect v1, we don't paint with the cache.
list = base::MakeRefCounted<cc::DisplayItemList>();
- root_view->Paint(
- ui::PaintContext(list.get(), device_scale_factor, v1->bounds()));
+ root_view->PaintFromPaintRoot(
+ ui::PaintContext(list.get(), device_scale_factor, v1->bounds(), false));
EXPECT_TRUE(v1->did_paint_);
v1->Reset();
@@ -580,8 +586,8 @@ TEST_F(ViewTest, PaintWithMovedViewUsesCache) {
// intersect v1.
list = base::MakeRefCounted<cc::DisplayItemList>();
v1->SetX(9);
- root_view->Paint(
- ui::PaintContext(list.get(), device_scale_factor, pixel_rect));
+ root_view->PaintFromPaintRoot(
+ ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false));
EXPECT_FALSE(v1->did_paint_);
v1->Reset();
item_index = 3;
@@ -597,8 +603,8 @@ TEST_F(ViewTest, PaintWithMovedViewUsesCache) {
// invalidation.
list = base::MakeRefCounted<cc::DisplayItemList>();
v1->SetX(8);
- root_view->Paint(ui::PaintContext(
- ui::PaintContext(list.get(), device_scale_factor, pixel_rect),
+ root_view->PaintFromPaintRoot(ui::PaintContext(
+ ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false),
ui::PaintContext::CLONE_WITHOUT_INVALIDATION));
EXPECT_TRUE(v1->did_paint_);
v1->Reset();
@@ -625,8 +631,8 @@ TEST_F(ViewTest, PaintWithMovedViewUsesCacheInRTL) {
gfx::Rect pixel_rect = gfx::Rect(1, 1);
float device_scale_factor = 1.f;
auto list = base::MakeRefCounted<cc::DisplayItemList>();
- root_view->Paint(
- ui::PaintContext(list.get(), device_scale_factor, pixel_rect));
+ root_view->PaintFromPaintRoot(
+ ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false));
EXPECT_TRUE(v1->did_paint_);
v1->Reset();
// The visual rects for (clip, drawing, transform) should be in layer space.
@@ -642,15 +648,15 @@ TEST_F(ViewTest, PaintWithMovedViewUsesCacheInRTL) {
// If invalidation doesn't intersect v1, we paint with the cache.
list = base::MakeRefCounted<cc::DisplayItemList>();
- root_view->Paint(
- ui::PaintContext(list.get(), device_scale_factor, pixel_rect));
+ root_view->PaintFromPaintRoot(
+ ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false));
EXPECT_FALSE(v1->did_paint_);
v1->Reset();
// If invalidation does intersect v1, we don't paint with the cache.
list = base::MakeRefCounted<cc::DisplayItemList>();
- root_view->Paint(
- ui::PaintContext(list.get(), device_scale_factor, v1->bounds()));
+ root_view->PaintFromPaintRoot(
+ ui::PaintContext(list.get(), device_scale_factor, v1->bounds(), false));
EXPECT_TRUE(v1->did_paint_);
v1->Reset();
@@ -658,8 +664,8 @@ TEST_F(ViewTest, PaintWithMovedViewUsesCacheInRTL) {
// intersect v1.
list = base::MakeRefCounted<cc::DisplayItemList>();
v1->SetX(9);
- root_view->Paint(
- ui::PaintContext(list.get(), device_scale_factor, pixel_rect));
+ root_view->PaintFromPaintRoot(
+ ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false));
EXPECT_FALSE(v1->did_paint_);
v1->Reset();
item_index = 3;
@@ -676,8 +682,8 @@ TEST_F(ViewTest, PaintWithMovedViewUsesCacheInRTL) {
// invalidation.
list = base::MakeRefCounted<cc::DisplayItemList>();
v1->SetX(8);
- root_view->Paint(ui::PaintContext(
- ui::PaintContext(list.get(), device_scale_factor, pixel_rect),
+ root_view->PaintFromPaintRoot(ui::PaintContext(
+ ui::PaintContext(list.get(), device_scale_factor, pixel_rect, false),
ui::PaintContext::CLONE_WITHOUT_INVALIDATION));
EXPECT_TRUE(v1->did_paint_);
v1->Reset();
@@ -708,7 +714,8 @@ TEST_F(ViewTest, PaintWithUnknownInvalidation) {
// invalidation.
gfx::Rect first_paint(1, 1);
auto list = base::MakeRefCounted<cc::DisplayItemList>();
- root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+ root_view->PaintFromPaintRoot(
+ ui::PaintContext(list.get(), 1.f, first_paint, false));
v1->Reset();
v2->Reset();
@@ -719,13 +726,14 @@ TEST_F(ViewTest, PaintWithUnknownInvalidation) {
// With a known invalidation, v1 and v2 are not painted.
EXPECT_FALSE(v1->did_paint_);
EXPECT_FALSE(v2->did_paint_);
- root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+ root_view->PaintFromPaintRoot(
+ ui::PaintContext(list.get(), 1.f, paint_area, false));
EXPECT_FALSE(v1->did_paint_);
EXPECT_FALSE(v2->did_paint_);
// With unknown invalidation, v1 and v2 are painted.
- root_view->Paint(
- ui::PaintContext(ui::PaintContext(list.get(), 1.f, paint_area),
+ root_view->PaintFromPaintRoot(
+ ui::PaintContext(ui::PaintContext(list.get(), 1.f, paint_area, false),
ui::PaintContext::CLONE_WITHOUT_INVALIDATION));
EXPECT_TRUE(v1->did_paint_);
EXPECT_TRUE(v2->did_paint_);
@@ -747,7 +755,9 @@ TEST_F(ViewTest, PaintContainsChildren) {
// invalidation.
gfx::Rect first_paint(1, 1);
auto list = base::MakeRefCounted<cc::DisplayItemList>();
- root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, first_paint, false),
+ root_view->size()));
v1->Reset();
v2->Reset();
@@ -757,7 +767,8 @@ TEST_F(ViewTest, PaintContainsChildren) {
EXPECT_FALSE(v1->did_paint_);
EXPECT_FALSE(v2->did_paint_);
- root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
EXPECT_TRUE(v1->did_paint_);
EXPECT_TRUE(v2->did_paint_);
}
@@ -790,7 +801,9 @@ TEST_F(ViewTest, PaintContainsChildrenInRTL) {
// invalidation.
gfx::Rect first_paint(1, 1);
auto list = base::MakeRefCounted<cc::DisplayItemList>();
- root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, first_paint, false),
+ root_view->size()));
v1->Reset();
v2->Reset();
@@ -800,7 +813,8 @@ TEST_F(ViewTest, PaintContainsChildrenInRTL) {
EXPECT_FALSE(v1->did_paint_);
EXPECT_FALSE(v2->did_paint_);
- root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
EXPECT_TRUE(v1->did_paint_);
EXPECT_TRUE(v2->did_paint_);
}
@@ -821,7 +835,9 @@ TEST_F(ViewTest, PaintIntersectsChildren) {
// invalidation.
gfx::Rect first_paint(1, 1);
auto list = base::MakeRefCounted<cc::DisplayItemList>();
- root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, first_paint, false),
+ root_view->size()));
v1->Reset();
v2->Reset();
@@ -831,7 +847,8 @@ TEST_F(ViewTest, PaintIntersectsChildren) {
EXPECT_FALSE(v1->did_paint_);
EXPECT_FALSE(v2->did_paint_);
- root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
EXPECT_TRUE(v1->did_paint_);
EXPECT_TRUE(v2->did_paint_);
}
@@ -864,7 +881,9 @@ TEST_F(ViewTest, PaintIntersectsChildrenInRTL) {
// invalidation.
gfx::Rect first_paint(1, 1);
auto list = base::MakeRefCounted<cc::DisplayItemList>();
- root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, first_paint, false),
+ root_view->size()));
v1->Reset();
v2->Reset();
@@ -874,7 +893,8 @@ TEST_F(ViewTest, PaintIntersectsChildrenInRTL) {
EXPECT_FALSE(v1->did_paint_);
EXPECT_FALSE(v2->did_paint_);
- root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
EXPECT_TRUE(v1->did_paint_);
EXPECT_TRUE(v2->did_paint_);
}
@@ -895,7 +915,9 @@ TEST_F(ViewTest, PaintIntersectsChildButNotGrandChild) {
// invalidation.
gfx::Rect first_paint(1, 1);
auto list = base::MakeRefCounted<cc::DisplayItemList>();
- root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, first_paint, false),
+ root_view->size()));
v1->Reset();
v2->Reset();
@@ -905,7 +927,8 @@ TEST_F(ViewTest, PaintIntersectsChildButNotGrandChild) {
EXPECT_FALSE(v1->did_paint_);
EXPECT_FALSE(v2->did_paint_);
- root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
EXPECT_TRUE(v1->did_paint_);
EXPECT_FALSE(v2->did_paint_);
}
@@ -938,7 +961,9 @@ TEST_F(ViewTest, PaintIntersectsChildButNotGrandChildInRTL) {
// invalidation.
gfx::Rect first_paint(1, 1);
auto list = base::MakeRefCounted<cc::DisplayItemList>();
- root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, first_paint, false),
+ root_view->size()));
v1->Reset();
v2->Reset();
@@ -948,7 +973,8 @@ TEST_F(ViewTest, PaintIntersectsChildButNotGrandChildInRTL) {
EXPECT_FALSE(v1->did_paint_);
EXPECT_FALSE(v2->did_paint_);
- root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
EXPECT_TRUE(v1->did_paint_);
EXPECT_FALSE(v2->did_paint_);
}
@@ -969,7 +995,9 @@ TEST_F(ViewTest, PaintIntersectsNoChildren) {
// invalidation.
gfx::Rect first_paint(1, 1);
auto list = base::MakeRefCounted<cc::DisplayItemList>();
- root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, first_paint, false),
+ root_view->size()));
v1->Reset();
v2->Reset();
@@ -979,7 +1007,8 @@ TEST_F(ViewTest, PaintIntersectsNoChildren) {
EXPECT_FALSE(v1->did_paint_);
EXPECT_FALSE(v2->did_paint_);
- root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
EXPECT_FALSE(v1->did_paint_);
EXPECT_FALSE(v2->did_paint_);
}
@@ -1012,7 +1041,9 @@ TEST_F(ViewTest, PaintIntersectsNoChildrenInRTL) {
// invalidation.
gfx::Rect first_paint(1, 1);
auto list = base::MakeRefCounted<cc::DisplayItemList>();
- root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, first_paint, false),
+ root_view->size()));
v1->Reset();
v2->Reset();
@@ -1022,7 +1053,8 @@ TEST_F(ViewTest, PaintIntersectsNoChildrenInRTL) {
EXPECT_FALSE(v1->did_paint_);
EXPECT_FALSE(v2->did_paint_);
- root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
EXPECT_FALSE(v1->did_paint_);
EXPECT_FALSE(v2->did_paint_);
}
@@ -1043,7 +1075,9 @@ TEST_F(ViewTest, PaintIntersectsOneChild) {
// invalidation.
gfx::Rect first_paint(1, 1);
auto list = base::MakeRefCounted<cc::DisplayItemList>();
- root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, first_paint, false),
+ root_view->size()));
v1->Reset();
v2->Reset();
@@ -1054,7 +1088,8 @@ TEST_F(ViewTest, PaintIntersectsOneChild) {
EXPECT_FALSE(v1->did_paint_);
EXPECT_FALSE(v2->did_paint_);
- root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
EXPECT_FALSE(v1->did_paint_);
EXPECT_TRUE(v2->did_paint_);
@@ -1065,7 +1100,8 @@ TEST_F(ViewTest, PaintIntersectsOneChild) {
v2->Reset();
EXPECT_FALSE(v1->did_paint_);
EXPECT_FALSE(v2->did_paint_);
- root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
EXPECT_TRUE(v1->did_paint_);
EXPECT_FALSE(v2->did_paint_);
}
@@ -1098,7 +1134,9 @@ TEST_F(ViewTest, PaintIntersectsOneChildInRTL) {
// invalidation.
gfx::Rect first_paint(1, 1);
auto list = base::MakeRefCounted<cc::DisplayItemList>();
- root_view->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, first_paint, false),
+ root_view->size()));
v1->Reset();
v2->Reset();
@@ -1109,7 +1147,8 @@ TEST_F(ViewTest, PaintIntersectsOneChildInRTL) {
EXPECT_FALSE(v1->did_paint_);
EXPECT_FALSE(v2->did_paint_);
- root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
EXPECT_TRUE(v1->did_paint_);
EXPECT_FALSE(v2->did_paint_);
@@ -1120,7 +1159,8 @@ TEST_F(ViewTest, PaintIntersectsOneChildInRTL) {
v2->Reset();
EXPECT_FALSE(v1->did_paint_);
EXPECT_FALSE(v2->did_paint_);
- root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, paint_area, false), root_view->size()));
EXPECT_FALSE(v1->did_paint_);
EXPECT_TRUE(v2->did_paint_);
}
@@ -1142,7 +1182,8 @@ TEST_F(ViewTest, PaintInPromotedToLayer) {
// invalidation.
gfx::Rect first_paint(1, 1);
auto list = base::MakeRefCounted<cc::DisplayItemList>();
- v1->Paint(ui::PaintContext(list.get(), 1.f, first_paint));
+ v1->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, first_paint, false), v1->size()));
v1->Reset();
v2->Reset();
@@ -1152,7 +1193,9 @@ TEST_F(ViewTest, PaintInPromotedToLayer) {
auto list = base::MakeRefCounted<cc::DisplayItemList>();
// The promoted views are not painted as they are separate paint roots.
- root_view->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+ root_view->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, paint_area, false),
+ root_view->size()));
EXPECT_FALSE(v1->did_paint_);
EXPECT_FALSE(v2->did_paint_);
}
@@ -1164,7 +1207,8 @@ TEST_F(ViewTest, PaintInPromotedToLayer) {
// The |v1| view is painted. If it used its offset incorrect, it would think
// its at (10,11) instead of at (0,0) since it is the paint root.
- v1->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+ v1->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, paint_area, false), v1->size()));
EXPECT_TRUE(v1->did_paint_);
EXPECT_FALSE(v2->did_paint_);
}
@@ -1178,7 +1222,8 @@ TEST_F(ViewTest, PaintInPromotedToLayer) {
// The |v2| view is painted also. If it used its offset incorrect, it would
// think its at (13,15) instead of at (3,4) since |v1| is the paint root.
- v1->Paint(ui::PaintContext(list.get(), 1.f, paint_area));
+ v1->Paint(PaintInfo::CreateRootPaintInfo(
+ ui::PaintContext(list.get(), 1.f, paint_area, false), v1->size()));
EXPECT_TRUE(v1->did_paint_);
EXPECT_TRUE(v2->did_paint_);
}
@@ -1221,9 +1266,9 @@ TEST_F(ViewTest, PaintLocalBounds) {
EXPECT_EQ(gfx::Rect(0, 1000, 100, 100), v1->GetVisibleBounds());
auto list = base::MakeRefCounted<cc::DisplayItemList>();
- ui::PaintContext context(list.get(), 1.f, gfx::Rect());
+ ui::PaintContext context(list.get(), 1.f, gfx::Rect(), false);
- v1->Paint(context);
+ v1->Paint(PaintInfo::CreateRootPaintInfo(context, gfx::Size()));
EXPECT_TRUE(v1->did_paint_);
// Check that the canvas produced by |v1| for paint contains all of |v1|'s
@@ -2353,16 +2398,9 @@ class ToplevelWidgetObserverView : public View {
DISALLOW_COPY_AND_ASSIGN(ToplevelWidgetObserverView);
};
-// No ReparentNativeView on Mac. See http://crbug.com/514920.
-#if defined(OS_MACOSX) && !defined(USE_AURA)
-#define MAYBE_NativeViewHierarchyChanged DISABLED_NativeViewHierarchyChanged
-#else
-#define MAYBE_NativeViewHierarchyChanged NativeViewHierarchyChanged
-#endif
-
// Test that a view can track the current top level widget by overriding
// View::ViewHierarchyChanged() and View::NativeViewHierarchyChanged().
-TEST_F(ViewTest, MAYBE_NativeViewHierarchyChanged) {
+TEST_F(ViewTest, NativeViewHierarchyChanged) {
std::unique_ptr<Widget> toplevel1(new Widget);
Widget::InitParams toplevel1_params =
CreateParams(Widget::InitParams::TYPE_POPUP);
@@ -4440,6 +4478,67 @@ TEST_F(ViewLayerTest, SnapLayerToPixel) {
EXPECT_EQ("0.00 0.00", ToString(v11->layer()->subpixel_position_offset()));
}
+class ViewLayerPixelCanvasTest : public ViewLayerTest {
+ public:
+ ViewLayerPixelCanvasTest() {}
+
+ ~ViewLayerPixelCanvasTest() override {}
+
+ void SetUp() override {
+ // Enable pixel canvas
+ base::CommandLine* cmd_line = base::CommandLine::ForCurrentProcess();
+ cmd_line->AppendSwitch(switches::kEnablePixelCanvasRecording);
+
+ ViewLayerTest::SetUp();
+ }
+};
+
+TEST_F(ViewLayerPixelCanvasTest, SnapLayerToPixel) {
+ View* v1 = new View;
+ View* v2 = new View;
+ View* v3 = new View;
+ v1->AddChildView(v2);
+ v2->AddChildView(v3);
+
+ widget()->SetContentsView(v1);
+
+ const gfx::Size& size = GetRootLayer()->GetCompositor()->size();
+ GetRootLayer()->GetCompositor()->SetScaleAndSize(1.6f, size);
+
+ v3->SetBoundsRect(gfx::Rect(4, 4, 20, 20));
+ v2->SetBoundsRect(gfx::Rect(7, 7, 50, 50));
+ v1->SetBoundsRect(gfx::Rect(9, 9, 100, 100));
+ v3->SetPaintToLayer();
+
+ EXPECT_EQ("-0.63 -0.63", ToString(v3->layer()->subpixel_position_offset()));
+
+ // Creating a layer in parent should update the child view's layer offset.
+ v1->SetPaintToLayer();
+ EXPECT_EQ("-0.25 -0.25", ToString(v1->layer()->subpixel_position_offset()));
+ EXPECT_EQ("-0.37 -0.37", ToString(v3->layer()->subpixel_position_offset()));
+
+ // DSF change should get propagated and update offsets.
+ GetRootLayer()->GetCompositor()->SetScaleAndSize(1.5f, size);
+ EXPECT_EQ("0.33 0.33", ToString(v1->layer()->subpixel_position_offset()));
+ EXPECT_EQ("0.33 0.33", ToString(v3->layer()->subpixel_position_offset()));
+
+ GetRootLayer()->GetCompositor()->SetScaleAndSize(1.33f, size);
+ EXPECT_EQ("0.02 0.02", ToString(v1->layer()->subpixel_position_offset()));
+ EXPECT_EQ("-0.47 -0.47", ToString(v3->layer()->subpixel_position_offset()));
+
+ // Deleting parent's layer should update the child view's layer's offset.
+ v1->DestroyLayer();
+ EXPECT_EQ("-0.45 -0.45", ToString(v3->layer()->subpixel_position_offset()));
+
+ // Setting parent view should update the child view's layer's offset.
+ v1->SetBoundsRect(gfx::Rect(3, 3, 10, 10));
+ EXPECT_EQ("-0.47 -0.47", ToString(v3->layer()->subpixel_position_offset()));
+
+ // Setting integral DSF should reset the offset.
+ GetRootLayer()->GetCompositor()->SetScaleAndSize(2.0f, size);
+ EXPECT_EQ("0.00 0.00", ToString(v3->layer()->subpixel_position_offset()));
+}
+
TEST_F(ViewTest, FocusableAssertions) {
// View subclasses may change insets based on whether they are focusable,
// which effects the preferred size. To avoid preferred size changing around
diff --git a/chromium/ui/views/views_delegate.cc b/chromium/ui/views/views_delegate.cc
index 862d3c3eb1c..cd3ffb17d51 100644
--- a/chromium/ui/views/views_delegate.cc
+++ b/chromium/ui/views/views_delegate.cc
@@ -136,8 +136,4 @@ int ViewsDelegate::GetAppbarAutohideEdges(HMONITOR monitor,
}
#endif
-scoped_refptr<base::TaskRunner> ViewsDelegate::GetBlockingPoolTaskRunner() {
- return nullptr;
-}
-
} // namespace views
diff --git a/chromium/ui/views/views_delegate.h b/chromium/ui/views/views_delegate.h
index b869e7b3fb3..ec2f61cb056 100644
--- a/chromium/ui/views/views_delegate.h
+++ b/chromium/ui/views/views_delegate.h
@@ -24,7 +24,6 @@
#include "ui/views/widget/widget.h"
namespace base {
-class TaskRunner;
class TimeDelta;
}
@@ -213,9 +212,6 @@ class VIEWS_EXPORT ViewsDelegate {
const base::Closure& callback);
#endif
- // Returns a blocking pool task runner given a TaskRunnerType.
- virtual scoped_refptr<base::TaskRunner> GetBlockingPoolTaskRunner();
-
protected:
ViewsDelegate();
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 d53d9c72cc6..5df66d73019 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
@@ -836,6 +836,16 @@ bool DesktopDragDropClientAuraX11::IsDragDropInProgress() {
return !!g_current_drag_drop_client;
}
+void DesktopDragDropClientAuraX11::AddObserver(
+ aura::client::DragDropClientObserver* observer) {
+ NOTIMPLEMENTED();
+}
+
+void DesktopDragDropClientAuraX11::RemoveObserver(
+ aura::client::DragDropClientObserver* observer) {
+ NOTIMPLEMENTED();
+}
+
void DesktopDragDropClientAuraX11::OnWindowDestroyed(aura::Window* window) {
DCHECK_EQ(target_window_, window);
target_window_ = NULL;
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h
index b8792c2d855..53a8f237e0f 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h
@@ -26,6 +26,7 @@
namespace aura {
namespace client {
+class DragDropClientObserver;
class DragDropDelegate;
}
}
@@ -89,6 +90,8 @@ class VIEWS_EXPORT DesktopDragDropClientAuraX11
ui::DragDropTypes::DragEventSource source) override;
void DragCancel() override;
bool IsDragDropInProgress() override;
+ void AddObserver(aura::client::DragDropClientObserver* observer) override;
+ void RemoveObserver(aura::client::DragDropClientObserver* observer) override;
// Overridden from aura::WindowObserver:
void OnWindowDestroyed(aura::Window* window) override;
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc
index 67fd2faa13f..1267b568a30 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc
@@ -84,6 +84,16 @@ bool DesktopDragDropClientWin::IsDragDropInProgress() {
return drag_drop_in_progress_;
}
+void DesktopDragDropClientWin::AddObserver(
+ aura::client::DragDropClientObserver* observer) {
+ NOTIMPLEMENTED();
+}
+
+void DesktopDragDropClientWin::RemoveObserver(
+ aura::client::DragDropClientObserver* observer) {
+ NOTIMPLEMENTED();
+}
+
void DesktopDragDropClientWin::OnNativeWidgetDestroying(HWND window) {
if (drop_target_.get()) {
RevokeDragDrop(window);
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h
index 44c28416eea..25845e08f22 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h
@@ -14,6 +14,12 @@
#include "ui/aura/client/drag_drop_client.h"
#include "ui/views/views_export.h"
+namespace aura {
+namespace client {
+class DragDropClientObserver;
+}
+} // namespace aura
+
namespace ui {
class DragSourceWin;
}
@@ -36,6 +42,8 @@ class VIEWS_EXPORT DesktopDragDropClientWin
ui::DragDropTypes::DragEventSource source) override;
void DragCancel() override;
bool IsDragDropInProgress() override;
+ void AddObserver(aura::client::DragDropClientObserver* observer) override;
+ void RemoveObserver(aura::client::DragDropClientObserver* observer) override;
void OnNativeWidgetDestroying(HWND window);
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 a9fdec6c525..aed089087f9 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
@@ -710,7 +710,8 @@ void DesktopNativeWidgetAura::StackAtTop() {
desktop_window_tree_host_->StackAtTop();
}
-void DesktopNativeWidgetAura::SetShape(std::unique_ptr<SkRegion> shape) {
+void DesktopNativeWidgetAura::SetShape(
+ std::unique_ptr<Widget::ShapeRects> shape) {
if (content_window_)
desktop_window_tree_host_->SetShape(std::move(shape));
}
@@ -1150,12 +1151,11 @@ int DesktopNativeWidgetAura::OnPerformDrop(const ui::DropTargetEvent& event) {
////////////////////////////////////////////////////////////////////////////////
// DesktopNativeWidgetAura, aura::WindowTreeHostObserver implementation:
-void DesktopNativeWidgetAura::OnHostCloseRequested(
- const aura::WindowTreeHost* host) {
+void DesktopNativeWidgetAura::OnHostCloseRequested(aura::WindowTreeHost* host) {
GetWidget()->Close();
}
-void DesktopNativeWidgetAura::OnHostResized(const aura::WindowTreeHost* host) {
+void DesktopNativeWidgetAura::OnHostResized(aura::WindowTreeHost* host) {
// Don't update the bounds of the child layers when animating closed. If we
// did it would force a paint, which we don't want. We don't want the paint
// as we can't assume any of the children are valid.
@@ -1168,12 +1168,12 @@ void DesktopNativeWidgetAura::OnHostResized(const aura::WindowTreeHost* host) {
}
void DesktopNativeWidgetAura::OnHostWorkspaceChanged(
- const aura::WindowTreeHost* host) {
+ aura::WindowTreeHost* host) {
native_widget_delegate_->OnNativeWidgetWorkspaceChanged();
}
void DesktopNativeWidgetAura::OnHostMovedInPixels(
- const aura::WindowTreeHost* host,
+ aura::WindowTreeHost* host,
const gfx::Point& new_origin_in_pixels) {
TRACE_EVENT1("views", "DesktopNativeWidgetAura::OnHostMovedInPixels",
"new_origin_in_pixels", new_origin_in_pixels.ToString());
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
index 01faa59fc6b..cdb96b1b2d3 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h
@@ -138,7 +138,7 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
void SetSize(const gfx::Size& size) override;
void StackAbove(gfx::NativeView native_view) override;
void StackAtTop() override;
- void SetShape(std::unique_ptr<SkRegion> shape) override;
+ void SetShape(std::unique_ptr<Widget::ShapeRects> shape) override;
void Close() override;
void CloseNow() override;
void Show() override;
@@ -231,10 +231,10 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
int OnPerformDrop(const ui::DropTargetEvent& event) override;
// Overridden from aura::WindowTreeHostObserver:
- void OnHostCloseRequested(const aura::WindowTreeHost* host) override;
- void OnHostResized(const aura::WindowTreeHost* host) override;
- void OnHostWorkspaceChanged(const aura::WindowTreeHost* host) override;
- void OnHostMovedInPixels(const aura::WindowTreeHost* host,
+ void OnHostCloseRequested(aura::WindowTreeHost* host) override;
+ void OnHostResized(aura::WindowTreeHost* host) override;
+ void OnHostWorkspaceChanged(aura::WindowTreeHost* host) override;
+ void OnHostMovedInPixels(aura::WindowTreeHost* host,
const gfx::Point& new_origin_in_pixels) override;
private:
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 c31728ca1b4..df8884e7de4 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc
@@ -377,8 +377,9 @@ std::vector<display::Display> DesktopScreenX11::BuildDisplaysFromXRandRInfo() {
// TODO(ccameron): Populate this based on this specific display.
// http://crbug.com/735613
if (!display::Display::HasForceColorProfile()) {
- display.set_color_space(
- gfx::ICCProfile::FromBestMonitor().GetColorSpace());
+ gfx::ICCProfile icc_profile = gfx::ICCProfile::FromBestMonitor();
+ icc_profile.HistogramDisplay(display.id());
+ display.set_color_space(icc_profile.GetColorSpace());
}
displays.push_back(display);
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.h b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.h
index c8633b68fad..a1cf57dc46e 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.h
@@ -94,9 +94,9 @@ class VIEWS_EXPORT DesktopWindowTreeHost {
virtual gfx::Rect GetWorkAreaBoundsInScreen() const = 0;
- // Sets the shape of the root window. If |native_region| is NULL then the
+ // Sets the shape of the root window. If |native_shape| is nullptr then the
// window reverts to rectangular.
- virtual void SetShape(std::unique_ptr<SkRegion> native_region) = 0;
+ virtual void SetShape(std::unique_ptr<Widget::ShapeRects> native_shape) = 0;
virtual void Activate() = 0;
virtual void Deactivate() = 0;
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
index 4d0dfbe80e5..e5b007cd0a4 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc
@@ -15,7 +15,6 @@
#include "ui/base/cursor/cursor_loader_win.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/win/shell.h"
-#include "ui/compositor/compositor_constants.h"
#include "ui/compositor/paint_context.h"
#include "ui/display/win/dpi.h"
#include "ui/display/win/screen_win.h"
@@ -133,12 +132,7 @@ void DesktopWindowTreeHostWin::Init(aura::Window* content_window,
gfx::Rect pixel_bounds =
display::win::ScreenWin::DIPToScreenRect(nullptr, params.bounds);
message_handler_->Init(parent_hwnd, pixel_bounds);
- if (params.force_software_compositing) {
- ::SetProp(GetAcceleratedWidget(),
- kForceSoftwareCompositor,
- reinterpret_cast<HANDLE>(true));
- }
- CreateCompositor();
+ CreateCompositor(viz::FrameSinkId(), params.force_software_compositing);
OnAcceleratedWidgetAvailable();
InitHost();
window()->Show();
@@ -298,34 +292,34 @@ gfx::Rect DesktopWindowTreeHostWin::GetWorkAreaBoundsInScreen() const {
}
void DesktopWindowTreeHostWin::SetShape(
- std::unique_ptr<SkRegion> native_region) {
- if (!native_region) {
+ std::unique_ptr<Widget::ShapeRects> native_shape) {
+ if (!native_shape || native_shape->empty()) {
message_handler_->SetRegion(nullptr);
return;
}
// TODO(wez): This would be a lot simpler if we were passed an SkPath.
// See crbug.com/410593.
- SkRegion* shape = native_region.get();
- SkRegion device_region;
+ SkRegion shape;
const float scale = display::win::ScreenWin::GetScaleFactorForHWND(GetHWND());
if (scale > 1.0) {
- shape = &device_region;
- std::vector<SkIRect> rects;
- for (SkRegion::Iterator it(*native_region); !it.done(); it.next()) {
- const SkIRect& rect = it.rect();
+ std::vector<SkIRect> sk_rects;
+ for (const gfx::Rect& rect : *native_shape) {
+ const SkIRect sk_rect = gfx::RectToSkIRect(rect);
SkRect scaled_rect =
- SkRect::MakeLTRB(rect.left() * scale, rect.top() * scale,
- rect.right() * scale, rect.bottom() * scale);
+ SkRect::MakeLTRB(sk_rect.left() * scale, sk_rect.top() * scale,
+ sk_rect.right() * scale, sk_rect.bottom() * scale);
SkIRect rounded_scaled_rect;
scaled_rect.roundOut(&rounded_scaled_rect);
- rects.push_back(rounded_scaled_rect);
+ sk_rects.push_back(rounded_scaled_rect);
}
- if (!rects.empty())
- device_region.setRects(&rects[0], rects.size());
+ shape.setRects(&sk_rects[0], sk_rects.size());
+ } else {
+ for (const gfx::Rect& rect : *native_shape)
+ shape.op(gfx::RectToSkIRect(rect), SkRegion::kUnion_Op);
}
- message_handler_->SetRegion(gfx::CreateHRGNFromSkRegion(*shape));
+ message_handler_->SetRegion(gfx::CreateHRGNFromSkRegion(shape));
}
void DesktopWindowTreeHostWin::Activate() {
@@ -802,11 +796,13 @@ void DesktopWindowTreeHostWin::HandleEndWMSizeMove() {
}
void DesktopWindowTreeHostWin::HandleMove() {
+ CheckForMonitorChange();
native_widget_delegate_->OnNativeWidgetMove();
OnHostMovedInPixels(GetBoundsInPixels().origin());
}
void DesktopWindowTreeHostWin::HandleWorkAreaChanged() {
+ CheckForMonitorChange();
GetWidget()->widget_delegate()->OnWorkAreaChanged();
}
@@ -820,11 +816,13 @@ void DesktopWindowTreeHostWin::HandleVisibilityChanged(bool visible) {
void DesktopWindowTreeHostWin::HandleClientSizeChanged(
const gfx::Size& new_size) {
+ CheckForMonitorChange();
if (dispatcher())
OnHostResizedInPixels(new_size);
}
void DesktopWindowTreeHostWin::HandleFrameChanged() {
+ CheckForMonitorChange();
SetWindowTransparency();
// Replace the frame and layout the contents.
GetWidget()->non_client_view()->UpdateFrame();
@@ -843,6 +841,11 @@ bool DesktopWindowTreeHostWin::HandleMouseEvent(const ui::MouseEvent& event) {
return event.handled();
}
+bool DesktopWindowTreeHostWin::HandlePointerEvent(ui::PointerEvent* event) {
+ SendEventToSink(event);
+ return event->handled();
+}
+
void DesktopWindowTreeHostWin::HandleKeyEvent(ui::KeyEvent* event) {
SendEventToSink(event);
}
@@ -997,6 +1000,15 @@ bool DesktopWindowTreeHostWin::IsModalWindowActive() const {
return false;
}
+void DesktopWindowTreeHostWin::CheckForMonitorChange() {
+ HMONITOR monitor_from_window =
+ ::MonitorFromWindow(GetHWND(), MONITOR_DEFAULTTOPRIMARY);
+ if (monitor_from_window == last_monitor_from_window_)
+ return;
+ last_monitor_from_window_ = monitor_from_window;
+ OnHostDisplayChanged();
+}
+
////////////////////////////////////////////////////////////////////////////////
// DesktopWindowTreeHost, public:
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
index 3f1c7bffb61..eb1205ee6a5 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h
@@ -77,7 +77,7 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin
gfx::Rect GetRestoredBounds() const override;
std::string GetWorkspace() const override;
gfx::Rect GetWorkAreaBoundsInScreen() const override;
- void SetShape(std::unique_ptr<SkRegion> native_region) override;
+ void SetShape(std::unique_ptr<Widget::ShapeRects> native_shape) override;
void Activate() override;
void Deactivate() override;
bool IsActive() const override;
@@ -188,6 +188,7 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin
void HandleNativeFocus(HWND last_focused_window) override;
void HandleNativeBlur(HWND focused_window) override;
bool HandleMouseEvent(const ui::MouseEvent& event) override;
+ bool HandlePointerEvent(ui::PointerEvent* event) override;
void HandleKeyEvent(ui::KeyEvent* event) override;
void HandleTouchEvent(const ui::TouchEvent& event) override;
bool HandleIMEMessage(UINT message,
@@ -221,6 +222,12 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin
// Returns true if a modal window is active in the current root window chain.
bool IsModalWindowActive() const;
+ // Called whenever the HWND resizes or moves, to see if the nearest HMONITOR
+ // has changed, and, if so, inform the aura::WindowTreeHost.
+ void CheckForMonitorChange();
+
+ HMONITOR last_monitor_from_window_ = nullptr;
+
std::unique_ptr<HWNDMessageHandler> message_handler_;
std::unique_ptr<aura::client::FocusClient> focus_client_;
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 e8a7a79c534..316cf855f7c 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
@@ -166,8 +166,7 @@ DesktopWindowTreeHostX11::DesktopWindowTreeHostX11(
has_pointer_focus_(false),
modal_dialog_counter_(0),
close_widget_factory_(this),
- weak_factory_(this) {
-}
+ weak_factory_(this) {}
DesktopWindowTreeHostX11::~DesktopWindowTreeHostX11() {
window()->ClearProperty(kHostForRootWindow);
@@ -701,15 +700,18 @@ gfx::Rect DesktopWindowTreeHostX11::GetWorkAreaBoundsInScreen() const {
}
void DesktopWindowTreeHostX11::SetShape(
- std::unique_ptr<SkRegion> native_region) {
+ std::unique_ptr<Widget::ShapeRects> native_shape) {
custom_window_shape_ = false;
window_shape_.reset();
- if (native_region) {
+ if (native_shape) {
+ SkRegion native_region;
+ for (const gfx::Rect& rect : *native_shape)
+ native_region.op(gfx::RectToSkIRect(rect), SkRegion::kUnion_Op);
gfx::Transform transform = GetRootTransform();
- if (!transform.IsIdentity() && !native_region->isEmpty()) {
+ if (!transform.IsIdentity() && !native_region.isEmpty()) {
SkPath path_in_dip;
- if (native_region->getBoundaryPath(&path_in_dip)) {
+ if (native_region.getBoundaryPath(&path_in_dip)) {
SkPath path_in_pixels;
path_in_dip.transform(transform.matrix(), &path_in_pixels);
window_shape_.reset(gfx::CreateRegionFromSkPath(path_in_pixels));
@@ -717,7 +719,7 @@ void DesktopWindowTreeHostX11::SetShape(
window_shape_.reset(XCreateRegion());
}
} else {
- window_shape_.reset(gfx::CreateRegionFromSkRegion(*native_region));
+ window_shape_.reset(gfx::CreateRegionFromSkRegion(native_region));
}
custom_window_shape_ = true;
@@ -1321,6 +1323,8 @@ void DesktopWindowTreeHostX11::OnDisplayMetricsChanged(
}
}
+void DesktopWindowTreeHostX11::OnMaximizedStateChanged() {}
+
////////////////////////////////////////////////////////////////////////////////
// DesktopWindowTreeHostX11, private:
@@ -1530,7 +1534,10 @@ void DesktopWindowTreeHostX11::InitX11Window(
if (window_icon) {
SetWindowIcons(gfx::ImageSkia(), *window_icon);
}
- CreateCompositor();
+ // Disable compositing on tooltips as a workaround for
+ // https://crbug.com/442111.
+ CreateCompositor(viz::FrameSinkId(),
+ params.type == Widget::InitParams::TYPE_TOOLTIP);
OnAcceleratedWidgetAvailable();
}
@@ -1560,11 +1567,15 @@ void DesktopWindowTreeHostX11::OnWMStateUpdated() {
ui::GetAtomArrayProperty(xwindow_, "_NET_WM_STATE", &atom_list);
bool was_minimized = IsMinimized();
+ bool was_maximized = IsMaximized();
window_properties_.clear();
std::copy(atom_list.begin(), atom_list.end(),
inserter(window_properties_, window_properties_.begin()));
+ 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
// called by PropertyNofify event from DispatchEvent() when the browser is
@@ -1577,7 +1588,6 @@ void DesktopWindowTreeHostX11::OnWMStateUpdated() {
// don't draw any 'blank' frames that could be noticed in applications such as
// window manager previews, which show content even when a window is
// minimized.
- bool is_minimized = IsMinimized();
if (is_minimized != was_minimized) {
if (is_minimized) {
compositor()->SetVisible(false);
@@ -1611,6 +1621,9 @@ void DesktopWindowTreeHostX11::OnWMStateUpdated() {
is_always_on_top_ = HasWMSpecProperty("_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.)
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 cb189675734..b72ec26d3ed 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
@@ -113,7 +113,7 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11
gfx::Rect GetRestoredBounds() const override;
std::string GetWorkspace() const override;
gfx::Rect GetWorkAreaBoundsInScreen() const override;
- void SetShape(std::unique_ptr<SkRegion> native_region) override;
+ void SetShape(std::unique_ptr<Widget::ShapeRects> native_shape) override;
void Activate() override;
void Deactivate() override;
bool IsActive() const override;
@@ -173,6 +173,9 @@ 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();
+
private:
friend class DesktopWindowTreeHostX11HighDPITest;
// Initializes our X11 surface to draw on. This method performs all
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 612b41f5939..32bcd039e1c 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
@@ -267,17 +267,10 @@ TEST_F(DesktopWindowTreeHostX11Test, Shape) {
}
// 2) Test setting the window shape via Widget::SetShape().
- gfx::Path shape2;
- shape2.moveTo(10, 0);
- shape2.lineTo(10, 10);
- shape2.lineTo(0, 10);
- shape2.lineTo(0, 100);
- shape2.lineTo(100, 100);
- shape2.lineTo(100, 0);
- shape2.close();
-
- auto shape_region = base::MakeUnique<SkRegion>();
- shape_region->setPath(shape2, SkRegion(shape2.getBounds().round()));
+ auto shape_region = base::MakeUnique<Widget::ShapeRects>();
+ shape_region->emplace_back(10, 0, 90, 10);
+ shape_region->emplace_back(0, 10, 10, 90);
+ shape_region->emplace_back(10, 10, 90, 90);
std::unique_ptr<Widget> widget2(CreateWidget(nullptr));
widget2->Show();
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 d94a8789cbf..18fac097875 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
@@ -20,7 +20,6 @@
#include "base/macros.h"
#include "base/memory/ptr_util.h"
#include "third_party/skia/include/core/SkRect.h"
-#include "third_party/skia/include/core/SkRegion.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/events/platform/x11/x11_event_source.h"
@@ -302,10 +301,10 @@ TEST_F(X11TopmostWindowFinderTest, NonRectangular) {
std::unique_ptr<Widget> widget1(
CreateAndShowWidget(gfx::Rect(100, 100, 100, 100)));
XID xid1 = widget1->GetNativeWindow()->GetHost()->GetAcceleratedWidget();
- auto skregion1 = base::MakeUnique<SkRegion>();
- skregion1->op(SkIRect::MakeXYWH(0, 10, 10, 90), SkRegion::kUnion_Op);
- skregion1->op(SkIRect::MakeXYWH(10, 0, 90, 100), SkRegion::kUnion_Op);
- widget1->SetShape(std::move(skregion1));
+ auto shape1 = base::MakeUnique<Widget::ShapeRects>();
+ shape1->emplace_back(0, 10, 10, 90);
+ shape1->emplace_back(10, 0, 90, 100);
+ widget1->SetShape(std::move(shape1));
SkRegion skregion2;
skregion2.op(SkIRect::MakeXYWH(0, 10, 10, 90), SkRegion::kUnion_Op);
@@ -341,10 +340,10 @@ TEST_F(X11TopmostWindowFinderTest, NonRectangularEmptyShape) {
std::unique_ptr<Widget> widget1(
CreateAndShowWidget(gfx::Rect(100, 100, 100, 100)));
XID xid1 = widget1->GetNativeWindow()->GetHost()->GetAcceleratedWidget();
- auto skregion1 = base::MakeUnique<SkRegion>();
- skregion1->op(SkIRect::MakeXYWH(0, 0, 0, 0), SkRegion::kUnion_Op);
- // Widget takes ownership of |skregion1|.
- widget1->SetShape(std::move(skregion1));
+ auto shape1 = base::MakeUnique<Widget::ShapeRects>();
+ shape1->emplace_back();
+ // Widget takes ownership of |shape1|.
+ widget1->SetShape(std::move(shape1));
XID xids[] = { xid1 };
StackingClientListWaiter stack_waiter(xids, arraysize(xids));
@@ -362,9 +361,9 @@ TEST_F(X11TopmostWindowFinderTest, NonRectangularNullShape) {
std::unique_ptr<Widget> widget1(
CreateAndShowWidget(gfx::Rect(100, 100, 100, 100)));
XID xid1 = widget1->GetNativeWindow()->GetHost()->GetAcceleratedWidget();
- auto skregion1 = base::MakeUnique<SkRegion>();
- skregion1->op(SkIRect::MakeXYWH(0, 0, 0, 0), SkRegion::kUnion_Op);
- widget1->SetShape(std::move(skregion1));
+ auto shape1 = base::MakeUnique<Widget::ShapeRects>();
+ shape1->emplace_back();
+ widget1->SetShape(std::move(shape1));
// Remove the shape - this is now just a normal window.
widget1->SetShape(nullptr);
diff --git a/chromium/ui/views/widget/native_widget_aura.cc b/chromium/ui/views/widget/native_widget_aura.cc
index 90cd8ab604d..af6022f14ec 100644
--- a/chromium/ui/views/widget/native_widget_aura.cc
+++ b/chromium/ui/views/widget/native_widget_aura.cc
@@ -13,7 +13,7 @@
#include "build/build_config.h"
#include "services/ui/public/interfaces/window_manager.mojom.h"
#include "services/ui/public/interfaces/window_manager_constants.mojom.h"
-#include "third_party/skia/include/core/SkRegion.h"
+#include "services/ui/public/interfaces/window_tree_constants.mojom.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/capture_client.h"
#include "ui/aura/client/cursor_client.h"
@@ -62,7 +62,7 @@
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h"
#endif
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#if defined(USE_X11)
#include "ui/views/linux_ui/linux_ui.h"
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
#endif
@@ -226,7 +226,10 @@ void NativeWidgetAura::InitNativeWidget(const Widget::InitParams& params) {
SetRestoreBounds(window_, window_bounds);
else
SetBounds(window_bounds);
- window_->set_ignore_events(!params.accept_events);
+ window_->SetEventTargetingPolicy(
+ params.accept_events
+ ? ui::mojom::EventTargetingPolicy::TARGET_AND_DESCENDANTS
+ : ui::mojom::EventTargetingPolicy::NONE);
DCHECK(GetWidget()->GetRootView());
if (params.type != Widget::InitParams::TYPE_TOOLTIP)
tooltip_manager_.reset(new views::TooltipManagerAura(GetWidget()));
@@ -490,9 +493,9 @@ void NativeWidgetAura::StackAtTop() {
window_->parent()->StackChildAtTop(window_);
}
-void NativeWidgetAura::SetShape(std::unique_ptr<SkRegion> region) {
+void NativeWidgetAura::SetShape(std::unique_ptr<Widget::ShapeRects> shape) {
if (window_)
- window_->layer()->SetAlphaShape(std::move(region));
+ window_->layer()->SetAlphaShape(std::move(shape));
}
void NativeWidgetAura::Close() {
@@ -1000,7 +1003,7 @@ void NativeWidgetAura::SetInitialFocus(ui::WindowShowState show_state) {
// Widget, public:
namespace {
-#if defined(OS_WIN) || (defined(USE_X11) && !defined(OS_CHROMEOS))
+#if defined(OS_WIN) || defined(USE_X11)
void CloseWindow(aura::Window* window) {
if (window) {
Widget* widget = Widget::GetWidgetForNativeView(window);
@@ -1030,7 +1033,7 @@ void Widget::CloseAllSecondaryWidgets() {
EnumThreadWindows(GetCurrentThreadId(), WindowCallbackProc, 0);
#endif
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#if defined(USE_X11)
DesktopWindowTreeHostX11::CleanUpWindowList(CloseWindow);
#endif
}
@@ -1042,7 +1045,7 @@ bool Widget::ConvertRect(const Widget* source,
}
const ui::NativeTheme* Widget::GetNativeTheme() const {
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#if defined(USE_X11)
const LinuxUI* linux_ui = LinuxUI::instance();
if (linux_ui) {
ui::NativeTheme* native_theme =
diff --git a/chromium/ui/views/widget/native_widget_aura.h b/chromium/ui/views/widget/native_widget_aura.h
index f556bcc14d1..87fc9372272 100644
--- a/chromium/ui/views/widget/native_widget_aura.h
+++ b/chromium/ui/views/widget/native_widget_aura.h
@@ -99,7 +99,7 @@ class VIEWS_EXPORT NativeWidgetAura : public internal::NativeWidgetPrivate,
void SetSize(const gfx::Size& size) override;
void StackAbove(gfx::NativeView native_view) override;
void StackAtTop() override;
- void SetShape(std::unique_ptr<SkRegion> shape) override;
+ void SetShape(std::unique_ptr<Widget::ShapeRects> shape) override;
void Close() override;
void CloseNow() override;
void Show() override;
diff --git a/chromium/ui/views/widget/native_widget_mac.h b/chromium/ui/views/widget/native_widget_mac.h
index 25e52d78ab3..74e3f333e57 100644
--- a/chromium/ui/views/widget/native_widget_mac.h
+++ b/chromium/ui/views/widget/native_widget_mac.h
@@ -84,7 +84,7 @@ class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate {
void SetSize(const gfx::Size& size) override;
void StackAbove(gfx::NativeView native_view) override;
void StackAtTop() override;
- void SetShape(std::unique_ptr<SkRegion> shape) override;
+ void SetShape(std::unique_ptr<Widget::ShapeRects> shape) override;
void Close() override;
void CloseNow() override;
void Show() override;
diff --git a/chromium/ui/views/widget/native_widget_mac.mm b/chromium/ui/views/widget/native_widget_mac.mm
index 398ea45f1f2..284c7fb7e1e 100644
--- a/chromium/ui/views/widget/native_widget_mac.mm
+++ b/chromium/ui/views/widget/native_widget_mac.mm
@@ -268,7 +268,7 @@ void NativeWidgetMac::GetWindowPlacement(
bool NativeWidgetMac::SetWindowTitle(const base::string16& title) {
NSWindow* window = GetNativeWindow();
NSString* current_title = [window title];
- NSString* new_title = SysUTF16ToNSString(title);
+ NSString* new_title = base::SysUTF16ToNSString(title);
if ([current_title isEqualToString:new_title])
return false;
@@ -333,7 +333,7 @@ void NativeWidgetMac::StackAtTop() {
NOTIMPLEMENTED();
}
-void NativeWidgetMac::SetShape(std::unique_ptr<SkRegion> shape) {
+void NativeWidgetMac::SetShape(std::unique_ptr<Widget::ShapeRects> shape) {
NOTIMPLEMENTED();
}
@@ -742,14 +742,34 @@ void NativeWidgetPrivate::GetAllOwnedWidgets(gfx::NativeView native_view,
// static
void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView native_view,
gfx::NativeView new_parent) {
+ DCHECK_NE(native_view, new_parent);
+ if (!new_parent || [native_view superview] == new_parent) {
+ NOTREACHED();
+ return;
+ }
+
BridgedNativeWidget* bridge =
NativeWidgetMac::GetBridgeForNativeWindow([native_view window]);
- if (bridge && bridge->parent() &&
- bridge->parent()->GetNSWindow() == [new_parent window])
- return; // Nothing to do.
+ BridgedNativeWidget* parent_bridge =
+ NativeWidgetMac::GetBridgeForNativeWindow([new_parent window]);
+ DCHECK(bridge);
+ if (Widget::GetWidgetForNativeView(native_view)->is_top_level() &&
+ bridge->parent() == parent_bridge)
+ return;
+
+ 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);
- // Not supported. See http://crbug.com/514920.
- NOTREACHED();
+ // And now, notify them that they have a brand new parent.
+ for (auto* child : widgets)
+ child->NotifyNativeViewHierarchyChanged();
}
// static
diff --git a/chromium/ui/views/widget/native_widget_mac_accessibility_unittest.mm b/chromium/ui/views/widget/native_widget_mac_accessibility_unittest.mm
index 357897b4fc7..a9debe71bcc 100644
--- a/chromium/ui/views/widget/native_widget_mac_accessibility_unittest.mm
+++ b/chromium/ui/views/widget/native_widget_mac_accessibility_unittest.mm
@@ -24,19 +24,6 @@
#include "ui/views/test/widget_test.h"
#include "ui/views/widget/widget.h"
-// Expose some methods from AXPlatformNodeCocoa for testing purposes only.
-@interface AXPlatformNodeCocoa (Testing)
-- (NSString*)AXRole;
-- (id)AXValue;
-
-// Text attributes.
-- (NSString*)AXSelectedText;
-- (NSValue*)AXSelectedTextRange;
-- (NSNumber*)AXNumberOfCharacters;
-- (NSValue*)AXVisibleCharacterRange;
-- (NSNumber*)AXInsertionPointLineNumber;
-@end
-
namespace views {
namespace {
@@ -92,28 +79,44 @@ class TestLabelButton : public LabelButton {
DISALLOW_COPY_AND_ASSIGN(TestLabelButton);
};
+class TestWidgetDelegate : public test::TestDesktopWidgetDelegate {
+ public:
+ TestWidgetDelegate() = default;
+
+ static constexpr char kAccessibleWindowTitle[] = "My Accessible Window";
+
+ // WidgetDelegate:
+ base::string16 GetAccessibleWindowTitle() const override {
+ return base::ASCIIToUTF16(kAccessibleWindowTitle);
+ }
+
+ private:
+ DISALLOW_COPY_AND_ASSIGN(TestWidgetDelegate);
+};
+
+constexpr char TestWidgetDelegate::kAccessibleWindowTitle[];
+
class NativeWidgetMacAccessibilityTest : public test::WidgetTest {
public:
NativeWidgetMacAccessibilityTest() {}
void SetUp() override {
test::WidgetTest::SetUp();
- widget_ = CreateTopLevelPlatformWidget();
- widget_->SetBounds(gfx::Rect(50, 50, 100, 100));
+ widget_delegate_.InitWidget(CreateParams(Widget::InitParams::TYPE_WINDOW));
widget()->Show();
}
void TearDown() override {
- widget_->CloseNow();
+ widget()->CloseNow();
test::WidgetTest::TearDown();
}
id A11yElementAtMidpoint() {
// Accessibility hit tests come in Cocoa screen coordinates.
NSPoint midpoint_in_screen_ = gfx::ScreenPointToNSPoint(
- widget_->GetWindowBoundsInScreen().CenterPoint());
+ widget()->GetWindowBoundsInScreen().CenterPoint());
return
- [widget_->GetNativeWindow() accessibilityHitTest:midpoint_in_screen_];
+ [widget()->GetNativeWindow() accessibilityHitTest:midpoint_in_screen_];
}
id AttributeValueAtMidpoint(NSString* attribute) {
@@ -129,11 +132,71 @@ class NativeWidgetMacAccessibilityTest : public test::WidgetTest {
return textfield;
}
- Widget* widget() { return widget_; }
- gfx::Rect GetWidgetBounds() { return widget_->GetClientAreaBoundsInScreen(); }
+ // Shorthand helpers to get a11y properties from A11yElementAtMidpoint().
+ NSString* AXRole() {
+ return AttributeValueAtMidpoint(NSAccessibilityRoleAttribute);
+ }
+ id AXParent() {
+ return AttributeValueAtMidpoint(NSAccessibilityParentAttribute);
+ }
+ id AXValue() {
+ return AttributeValueAtMidpoint(NSAccessibilityValueAttribute);
+ }
+ NSString* AXTitle() {
+ return AttributeValueAtMidpoint(NSAccessibilityTitleAttribute);
+ }
+ NSString* AXDescription() {
+ return AttributeValueAtMidpoint(NSAccessibilityDescriptionAttribute);
+ }
+ NSString* AXSelectedText() {
+ return AttributeValueAtMidpoint(NSAccessibilitySelectedTextAttribute);
+ }
+ NSValue* AXSelectedTextRange() {
+ return AttributeValueAtMidpoint(NSAccessibilitySelectedTextRangeAttribute);
+ }
+ NSNumber* AXNumberOfCharacters() {
+ return AttributeValueAtMidpoint(NSAccessibilityNumberOfCharactersAttribute);
+ }
+ NSValue* AXVisibleCharacterRange() {
+ return AttributeValueAtMidpoint(
+ NSAccessibilityVisibleCharacterRangeAttribute);
+ }
+ NSNumber* AXInsertionPointLineNumber() {
+ return AttributeValueAtMidpoint(
+ NSAccessibilityInsertionPointLineNumberAttribute);
+ }
+ NSNumber* AXLineForIndex(id parameter) {
+ return [A11yElementAtMidpoint()
+ accessibilityAttributeValue:
+ NSAccessibilityLineForIndexParameterizedAttribute
+ forParameter:parameter];
+ }
+ NSValue* AXRangeForLine(id parameter) {
+ return [A11yElementAtMidpoint()
+ accessibilityAttributeValue:
+ NSAccessibilityRangeForLineParameterizedAttribute
+ forParameter:parameter];
+ }
+ NSString* AXStringForRange(id parameter) {
+ return [A11yElementAtMidpoint()
+ accessibilityAttributeValue:
+ NSAccessibilityStringForRangeParameterizedAttribute
+ forParameter:parameter];
+ }
+ NSAttributedString* AXAttributedStringForRange(id parameter) {
+ return [A11yElementAtMidpoint()
+ accessibilityAttributeValue:
+ NSAccessibilityAttributedStringForRangeParameterizedAttribute
+ forParameter:parameter];
+ }
+
+ Widget* widget() { return widget_delegate_.GetWidget(); }
+ gfx::Rect GetWidgetBounds() {
+ return widget()->GetClientAreaBoundsInScreen();
+ }
private:
- Widget* widget_ = nullptr;
+ TestWidgetDelegate widget_delegate_;
DISALLOW_COPY_AND_ASSIGN(NativeWidgetMacAccessibilityTest);
};
@@ -229,8 +292,7 @@ TEST_F(NativeWidgetMacAccessibilityTest, FocusableElementsAreLeafNodes) {
TestLabelButton* button = new TestLabelButton();
button->SetSize(widget()->GetContentsView()->size());
widget()->GetContentsView()->AddChildView(button);
- EXPECT_NSEQ(NSAccessibilityButtonRole,
- AttributeValueAtMidpoint(NSAccessibilityRoleAttribute));
+ EXPECT_NSEQ(NSAccessibilityButtonRole, AXRole());
EXPECT_EQ(
0u,
[[button->GetNativeViewAccessible()
@@ -290,7 +352,7 @@ TEST_F(NativeWidgetMacAccessibilityTest, ParentAttribute) {
// Views with Widget parents will have a NSWindow parent.
EXPECT_NSEQ(
NSAccessibilityWindowRole,
- [AttributeValueAtMidpoint(NSAccessibilityParentAttribute) AXRole]);
+ [AXParent() accessibilityAttributeValue:NSAccessibilityRoleAttribute]);
// Views with non-Widget parents will have the role of the parent view.
widget()->GetContentsView()->RemoveChildView(child);
@@ -299,13 +361,13 @@ TEST_F(NativeWidgetMacAccessibilityTest, ParentAttribute) {
widget()->GetContentsView()->AddChildView(parent);
EXPECT_NSEQ(
NSAccessibilityGroupRole,
- [AttributeValueAtMidpoint(NSAccessibilityParentAttribute) AXRole]);
+ [AXParent() accessibilityAttributeValue:NSAccessibilityRoleAttribute]);
// Test an ignored role parent is skipped in favor of the grandparent.
parent->set_role(ui::AX_ROLE_IGNORED);
EXPECT_NSEQ(
NSAccessibilityWindowRole,
- [AttributeValueAtMidpoint(NSAccessibilityParentAttribute) AXRole]);
+ [AXParent() accessibilityAttributeValue:NSAccessibilityRoleAttribute]);
}
// Test for NSAccessibilityPositionAttribute, including on Widget movement
@@ -337,20 +399,22 @@ TEST_F(NativeWidgetMacAccessibilityTest, HelpAttribute) {
AttributeValueAtMidpoint(NSAccessibilityHelpAttribute));
}
-// Test for NSAccessibilityWindowAttribute and
-// NSAccessibilityTopLevelUIElementAttribute.
-TEST_F(NativeWidgetMacAccessibilityTest, WindowAndTopLevelUIElementAttributes) {
+// Test view properties that should report the native NSWindow, and test
+// specific properties on that NSWindow.
+TEST_F(NativeWidgetMacAccessibilityTest, NativeWindowProperties) {
FlexibleRoleTestView* view = new FlexibleRoleTestView(ui::AX_ROLE_GROUP);
view->SetSize(GetWidgetBounds().size());
widget()->GetContentsView()->AddChildView(view);
// Make sure it's |view| in the hit test by checking its accessibility role.
- EXPECT_EQ(NSAccessibilityGroupRole,
- AttributeValueAtMidpoint(NSAccessibilityRoleAttribute));
- EXPECT_NSEQ(widget()->GetNativeWindow(),
- AttributeValueAtMidpoint(NSAccessibilityWindowAttribute));
+ EXPECT_EQ(NSAccessibilityGroupRole, AXRole());
+
+ NSWindow* window = widget()->GetNativeWindow();
+ EXPECT_NSEQ(window, AttributeValueAtMidpoint(NSAccessibilityWindowAttribute));
+ EXPECT_NSEQ(window, AttributeValueAtMidpoint(
+ NSAccessibilityTopLevelUIElementAttribute));
EXPECT_NSEQ(
- widget()->GetNativeWindow(),
- AttributeValueAtMidpoint(NSAccessibilityTopLevelUIElementAttribute));
+ base::SysUTF8ToNSString(TestWidgetDelegate::kAccessibleWindowTitle),
+ [window accessibilityAttributeValue:NSAccessibilityTitleAttribute]);
}
// Tests for accessibility attributes on a views::Textfield.
@@ -375,16 +439,9 @@ TEST_F(NativeWidgetMacAccessibilityTest, TextfieldGenericAttributes) {
boolValue]);
// NSAccessibilityTitleAttribute.
- EXPECT_NSEQ(kTestTitle,
- AttributeValueAtMidpoint(NSAccessibilityTitleAttribute));
-
- // NSAccessibilityValueAttribute.
- EXPECT_NSEQ(kTestStringValue,
- AttributeValueAtMidpoint(NSAccessibilityValueAttribute));
-
- // NSAccessibilityRoleAttribute.
- EXPECT_NSEQ(NSAccessibilityTextFieldRole,
- AttributeValueAtMidpoint(NSAccessibilityRoleAttribute));
+ EXPECT_NSEQ(NSAccessibilityTextFieldRole, AXRole());
+ EXPECT_NSEQ(kTestTitle, AXTitle());
+ EXPECT_NSEQ(kTestStringValue, AXValue());
// NSAccessibilitySubroleAttribute and
// NSAccessibilityRoleDescriptionAttribute.
@@ -431,10 +488,8 @@ TEST_F(NativeWidgetMacAccessibilityTest, TextfieldEditableAttributes) {
NSAccessibilityInsertionPointLineNumberAttribute) intValue]);
// NSAccessibilityNumberOfCharactersAttribute.
- EXPECT_EQ(
- kTestStringValue.length,
- [AttributeValueAtMidpoint(NSAccessibilityNumberOfCharactersAttribute)
- unsignedIntegerValue]);
+ EXPECT_EQ(kTestStringValue.length,
+ [AXNumberOfCharacters() unsignedIntegerValue]);
// NSAccessibilityPlaceholderAttribute.
EXPECT_NSEQ(
@@ -443,54 +498,41 @@ TEST_F(NativeWidgetMacAccessibilityTest, TextfieldEditableAttributes) {
// NSAccessibilitySelectedTextAttribute and
// NSAccessibilitySelectedTextRangeAttribute.
- EXPECT_NSEQ(@"",
- AttributeValueAtMidpoint(NSAccessibilitySelectedTextAttribute));
+ EXPECT_NSEQ(@"", AXSelectedText());
// The cursor will be at the end of the textfield, so the selection range will
// span 0 characters and be located at the index after the last character.
EXPECT_EQ(gfx::Range(kTestStringValue.length, kTestStringValue.length),
- gfx::Range([AttributeValueAtMidpoint(
- NSAccessibilitySelectedTextRangeAttribute) rangeValue]));
+ gfx::Range([AXSelectedTextRange() rangeValue]));
// Select some text in the middle of the textfield.
const gfx::Range forward_range(2, 6);
const NSRange ns_range = forward_range.ToNSRange();
textfield->SelectRange(forward_range);
- EXPECT_NSEQ([kTestStringValue substringWithRange:ns_range],
- AttributeValueAtMidpoint(NSAccessibilitySelectedTextAttribute));
+ EXPECT_NSEQ([kTestStringValue substringWithRange:ns_range], AXSelectedText());
EXPECT_EQ(textfield->GetSelectedText(),
- base::SysNSStringToUTF16(AttributeValueAtMidpoint(
- NSAccessibilitySelectedTextAttribute)));
- EXPECT_EQ(forward_range,
- gfx::Range([AttributeValueAtMidpoint(
- NSAccessibilitySelectedTextRangeAttribute) rangeValue]));
+ base::SysNSStringToUTF16(AXSelectedText()));
+ EXPECT_EQ(forward_range, gfx::Range([AXSelectedTextRange() rangeValue]));
const gfx::Range reversed_range(6, 2);
textfield->SelectRange(reversed_range);
// NSRange has no direction, so these are unchanged from the forward range.
- EXPECT_NSEQ([kTestStringValue substringWithRange:ns_range],
- AttributeValueAtMidpoint(NSAccessibilitySelectedTextAttribute));
+ EXPECT_NSEQ([kTestStringValue substringWithRange:ns_range], AXSelectedText());
EXPECT_EQ(textfield->GetSelectedText(),
- base::SysNSStringToUTF16(AttributeValueAtMidpoint(
- NSAccessibilitySelectedTextAttribute)));
- EXPECT_EQ(forward_range,
- gfx::Range([AttributeValueAtMidpoint(
- NSAccessibilitySelectedTextRangeAttribute) rangeValue]));
+ base::SysNSStringToUTF16(AXSelectedText()));
+ EXPECT_EQ(forward_range, gfx::Range([AXSelectedTextRange() rangeValue]));
// NSAccessibilityVisibleCharacterRangeAttribute.
EXPECT_EQ(gfx::Range(0, kTestStringValue.length),
- gfx::Range([AttributeValueAtMidpoint(
- NSAccessibilityVisibleCharacterRangeAttribute) rangeValue]));
+ gfx::Range([AXVisibleCharacterRange() rangeValue]));
// Test an RTL string.
textfield->SetText(base::SysNSStringToUTF16(kTestRTLStringValue));
textfield->SelectRange(forward_range);
EXPECT_EQ(textfield->GetSelectedText(),
- base::SysNSStringToUTF16(AttributeValueAtMidpoint(
- NSAccessibilitySelectedTextAttribute)));
+ base::SysNSStringToUTF16(AXSelectedText()));
textfield->SelectRange(reversed_range);
EXPECT_EQ(textfield->GetSelectedText(),
- base::SysNSStringToUTF16(AttributeValueAtMidpoint(
- NSAccessibilitySelectedTextAttribute)));
+ base::SysNSStringToUTF16(AXSelectedText()));
}
// Test writing accessibility attributes via an accessibility client for normal
@@ -503,8 +545,7 @@ TEST_F(NativeWidgetMacAccessibilityTest, ViewWritableAttributes) {
// Make sure the accessibility object tested is the correct one.
id ax_node = A11yElementAtMidpoint();
EXPECT_TRUE(ax_node);
- EXPECT_NSEQ(NSAccessibilityGroupRole,
- AttributeValueAtMidpoint(NSAccessibilityRoleAttribute));
+ EXPECT_NSEQ(NSAccessibilityGroupRole, AXRole());
// Make sure |view| is focusable, then focus/unfocus it.
view->SetFocusBehavior(View::FocusBehavior::ALWAYS);
@@ -530,17 +571,14 @@ TEST_F(NativeWidgetMacAccessibilityTest, TextfieldWritableAttributes) {
EXPECT_TRUE(ax_node);
// Make sure it's the correct accessibility object.
- id value =
- [ax_node accessibilityAttributeValue:NSAccessibilityValueAttribute];
- EXPECT_NSEQ(kTestStringValue, value);
+ EXPECT_NSEQ(kTestStringValue, AXValue());
// Write a new NSAccessibilityValueAttribute.
EXPECT_TRUE(
[ax_node accessibilityIsAttributeSettable:NSAccessibilityValueAttribute]);
[ax_node accessibilitySetValue:kTestPlaceholderText
forAttribute:NSAccessibilityValueAttribute];
- EXPECT_NSEQ(kTestPlaceholderText,
- AttributeValueAtMidpoint(NSAccessibilityValueAttribute));
+ EXPECT_NSEQ(kTestPlaceholderText, AXValue());
EXPECT_EQ(base::SysNSStringToUTF16(kTestPlaceholderText), textfield->text());
// Test a read-only textfield.
@@ -549,8 +587,7 @@ TEST_F(NativeWidgetMacAccessibilityTest, TextfieldWritableAttributes) {
[ax_node accessibilityIsAttributeSettable:NSAccessibilityValueAttribute]);
[ax_node accessibilitySetValue:kTestStringValue
forAttribute:NSAccessibilityValueAttribute];
- EXPECT_NSEQ(kTestPlaceholderText,
- AttributeValueAtMidpoint(NSAccessibilityValueAttribute));
+ EXPECT_NSEQ(kTestPlaceholderText, AXValue());
EXPECT_EQ(base::SysNSStringToUTF16(kTestPlaceholderText), textfield->text());
textfield->SetReadOnly(false);
@@ -563,8 +600,7 @@ TEST_F(NativeWidgetMacAccessibilityTest, TextfieldWritableAttributes) {
[kTestStringValue stringByAppendingString:kTestPlaceholderText];
[ax_node accessibilitySetValue:kTestStringValue
forAttribute:NSAccessibilitySelectedTextAttribute];
- EXPECT_NSEQ(new_string,
- AttributeValueAtMidpoint(NSAccessibilityValueAttribute));
+ EXPECT_NSEQ(new_string, AXValue());
EXPECT_EQ(base::SysNSStringToUTF16(new_string), textfield->text());
// Replace entire selection.
@@ -572,8 +608,7 @@ TEST_F(NativeWidgetMacAccessibilityTest, TextfieldWritableAttributes) {
textfield->SelectRange(test_range);
[ax_node accessibilitySetValue:kTestStringValue
forAttribute:NSAccessibilitySelectedTextAttribute];
- EXPECT_NSEQ(kTestStringValue,
- AttributeValueAtMidpoint(NSAccessibilityValueAttribute));
+ EXPECT_NSEQ(kTestStringValue, AXValue());
EXPECT_EQ(base::SysNSStringToUTF16(kTestStringValue), textfield->text());
// Make sure the cursor is at the end of the Textfield.
EXPECT_EQ(gfx::Range([kTestStringValue length]),
@@ -590,8 +625,7 @@ TEST_F(NativeWidgetMacAccessibilityTest, TextfieldWritableAttributes) {
textfield->SelectRange(test_range);
[ax_node accessibilitySetValue:base::SysUTF16ToNSString(replacement)
forAttribute:NSAccessibilitySelectedTextAttribute];
- EXPECT_NSEQ(new_string,
- AttributeValueAtMidpoint(NSAccessibilityValueAttribute));
+ EXPECT_NSEQ(new_string, AXValue());
EXPECT_EQ(base::SysNSStringToUTF16(new_string), textfield->text());
// Make sure the cursor is at the end of the replacement.
EXPECT_EQ(gfx::Range(front.length() + replacement.length()),
@@ -645,30 +679,17 @@ TEST_F(NativeWidgetMacAccessibilityTest, TextParameterizedAttributes) {
EXPECT_TRUE([ax_node respondsToSelector:sel]);
}
- NSNumber* line =
- [ax_node accessibilityAttributeValue:
- NSAccessibilityLineForIndexParameterizedAttribute
- forParameter:@5];
+ NSNumber* line = AXLineForIndex(@5);
EXPECT_TRUE(line);
EXPECT_EQ(0, [line intValue]);
EXPECT_NSEQ([NSValue valueWithRange:NSMakeRange(0, kTestStringLength)],
- [ax_node accessibilityAttributeValue:
- NSAccessibilityRangeForLineParameterizedAttribute
- forParameter:line]);
+ AXRangeForLine(line));
// The substring "est st" of kTestStringValue.
NSValue* test_range = [NSValue valueWithRange:NSMakeRange(1, 6)];
- EXPECT_NSEQ(@"est st",
- [ax_node accessibilityAttributeValue:
- NSAccessibilityStringForRangeParameterizedAttribute
- forParameter:test_range]);
- EXPECT_NSEQ(
- @"est st",
- [[ax_node
- accessibilityAttributeValue:
- NSAccessibilityAttributedStringForRangeParameterizedAttribute
- forParameter:test_range] string]);
+ EXPECT_NSEQ(@"est st", AXStringForRange(test_range));
+ EXPECT_NSEQ(@"est st", [AXAttributedStringForRange(test_range) string]);
// Not implemented yet. Update these tests when they are.
EXPECT_NSEQ(nil,
@@ -705,8 +726,7 @@ TEST_F(NativeWidgetMacAccessibilityTest, PressAction) {
view->SetSize(GetWidgetBounds().size());
id ax_node = A11yElementAtMidpoint();
- EXPECT_NSEQ(NSAccessibilityButtonRole,
- AttributeValueAtMidpoint(NSAccessibilityRoleAttribute));
+ EXPECT_NSEQ(NSAccessibilityButtonRole, AXRole());
EXPECT_TRUE([[ax_node accessibilityActionNames]
containsObject:NSAccessibilityPressAction]);
@@ -769,35 +789,35 @@ TEST_F(NativeWidgetMacAccessibilityTest, ProtectedTextfields) {
// Explicit checks done without comparing to NSTextField.
EXPECT_TRUE(
[ax_node accessibilityIsAttributeSettable:NSAccessibilityValueAttribute]);
- EXPECT_NSEQ(NSAccessibilityTextFieldRole, [ax_node AXRole]);
+ EXPECT_NSEQ(NSAccessibilityTextFieldRole, AXRole());
NSString* kShownValue = @"•"
@"••••••••••••••••";
// Sanity check.
EXPECT_EQ(kTestStringLength, static_cast<int>([kShownValue length]));
- EXPECT_NSEQ(kShownValue, [ax_node AXValue]);
+ EXPECT_NSEQ(kShownValue, AXValue());
// Cursor currently at the end of input.
- EXPECT_NSEQ(@"", [ax_node AXSelectedText]);
+ EXPECT_NSEQ(@"", AXSelectedText());
EXPECT_NSEQ([NSValue valueWithRange:NSMakeRange(kTestStringLength, 0)],
- [ax_node AXSelectedTextRange]);
+ AXSelectedTextRange());
- EXPECT_EQ(kTestStringLength, [[ax_node AXNumberOfCharacters] intValue]);
+ EXPECT_EQ(kTestStringLength, [AXNumberOfCharacters() intValue]);
EXPECT_NSEQ(([NSValue valueWithRange:{0, kTestStringLength}]),
- [ax_node AXVisibleCharacterRange]);
- EXPECT_EQ(0, [[ax_node AXInsertionPointLineNumber] intValue]);
+ AXVisibleCharacterRange());
+ EXPECT_EQ(0, [AXInsertionPointLineNumber() intValue]);
// Test replacing text.
textfield->SetText(base::ASCIIToUTF16("123"));
- EXPECT_NSEQ(@"•••", [ax_node AXValue]);
- EXPECT_EQ(3, [[ax_node AXNumberOfCharacters] intValue]);
+ EXPECT_NSEQ(@"•••", AXValue());
+ EXPECT_EQ(3, [AXNumberOfCharacters() intValue]);
textfield->SelectRange(gfx::Range(2, 3)); // Selects "3".
[ax_node accessibilitySetValue:@"ab"
forAttribute:NSAccessibilitySelectedTextAttribute];
EXPECT_EQ(base::ASCIIToUTF16("12ab"), textfield->text());
- EXPECT_NSEQ(@"••••", [ax_node AXValue]);
- EXPECT_EQ(4, [[ax_node AXNumberOfCharacters] intValue]);
+ EXPECT_NSEQ(@"••••", AXValue());
+ EXPECT_EQ(4, [AXNumberOfCharacters() intValue]);
}
// Test text-specific attributes of Labels.
@@ -811,20 +831,40 @@ TEST_F(NativeWidgetMacAccessibilityTest, Label) {
id ax_node = A11yElementAtMidpoint();
EXPECT_TRUE(ax_node);
- EXPECT_NSEQ(NSAccessibilityStaticTextRole, [ax_node AXRole]);
- EXPECT_NSEQ(kTestStringValue, [ax_node AXValue]);
+ EXPECT_NSEQ(NSAccessibilityStaticTextRole, AXRole());
+ EXPECT_NSEQ(kTestStringValue, AXValue());
+
+ // Title and description for StaticTextRole should always be empty.
+ EXPECT_NSEQ(@"", AXTitle());
+
+ // The description is "The purpose of the element, not including the role.".
+ // BrowserAccessibility returns an empty string instead of nil. Either should
+ // be OK.
+ EXPECT_EQ(nil, AXDescription());
// No selection by default. TODO(tapted): Test selection when views::Label
// uses RenderTextHarfBuzz on Mac. See http://crbug.com/454835.
// For now, this tests that the codepaths are valid for views::Label.
- EXPECT_NSEQ(@"", [ax_node AXSelectedText]);
+ EXPECT_NSEQ(@"", AXSelectedText());
EXPECT_NSEQ([NSValue valueWithRange:NSMakeRange(0, 0)],
- [ax_node AXSelectedTextRange]);
+ AXSelectedTextRange());
- EXPECT_EQ(kTestStringLength, [[ax_node AXNumberOfCharacters] intValue]);
+ EXPECT_EQ(kTestStringLength, [AXNumberOfCharacters() intValue]);
EXPECT_NSEQ(([NSValue valueWithRange:{0, kTestStringLength}]),
- [ax_node AXVisibleCharacterRange]);
- EXPECT_EQ(0, [[ax_node AXInsertionPointLineNumber] intValue]);
+ AXVisibleCharacterRange());
+ EXPECT_EQ(0, [AXInsertionPointLineNumber() intValue]);
+
+ // Test parameterized attributes for Static Text.
+ NSNumber* line = AXLineForIndex(@5);
+ EXPECT_TRUE(line);
+ EXPECT_EQ(0, [line intValue]);
+ EXPECT_NSEQ([NSValue valueWithRange:NSMakeRange(0, kTestStringLength)],
+ AXRangeForLine(line));
+ NSValue* test_range = [NSValue valueWithRange:NSMakeRange(1, 6)];
+ EXPECT_NSEQ(@"est st", AXStringForRange(test_range));
+ EXPECT_NSEQ(@"est st", [AXAttributedStringForRange(test_range) string]);
+
+ // TODO(tapted): Add a test for multiline Labels (currently not supported).
}
class TestComboboxModel : public ui::ComboboxModel {
@@ -851,12 +891,12 @@ TEST_F(NativeWidgetMacAccessibilityTest, Combobox) {
id ax_node = A11yElementAtMidpoint();
EXPECT_TRUE(ax_node);
- EXPECT_NSEQ(NSAccessibilityPopUpButtonRole, [ax_node AXRole]);
+ EXPECT_NSEQ(NSAccessibilityPopUpButtonRole, AXRole());
// The initial value should be the first item in the menu.
- EXPECT_NSEQ(kTestStringValue, [ax_node AXValue]);
+ EXPECT_NSEQ(kTestStringValue, AXValue());
combobox->SetSelectedIndex(1);
- EXPECT_NSEQ(@"Second Item", [ax_node AXValue]);
+ EXPECT_NSEQ(@"Second Item", AXValue());
// Expect to see both a press action and a show menu action. This matches
// Cocoa behavior.
diff --git a/chromium/ui/views/widget/native_widget_mac_interactive_uitest.mm b/chromium/ui/views/widget/native_widget_mac_interactive_uitest.mm
index c29fe0464ff..4e8cf2b6c67 100644
--- a/chromium/ui/views/widget/native_widget_mac_interactive_uitest.mm
+++ b/chromium/ui/views/widget/native_widget_mac_interactive_uitest.mm
@@ -11,6 +11,7 @@
#include "base/macros.h"
#include "ui/base/test/ui_controls.h"
#import "ui/base/test/windowed_nsnotification_observer.h"
+#import "ui/events/test/cocoa_test_event_utils.h"
#include "ui/views/bubble/bubble_dialog_delegate.h"
#include "ui/views/test/test_widget_observer.h"
#include "ui/views/test/widget_test.h"
@@ -221,6 +222,57 @@ TEST_F(NativeWidgetMacInteractiveUITest, ParentWindowTrafficLights) {
parent_widget->CloseNow();
}
+// Test that bubble widgets are dismissed on right mouse down.
+TEST_F(NativeWidgetMacInteractiveUITest, BubbleDismiss) {
+ Widget* parent_widget = CreateTopLevelPlatformWidget();
+ parent_widget->SetBounds(gfx::Rect(100, 100, 100, 100));
+ ShowKeyWindow(parent_widget);
+
+ Widget* bubble_widget =
+ BubbleDialogDelegateView::CreateBubble(new TestBubbleView(parent_widget));
+ ShowKeyWindow(bubble_widget);
+
+ // First, test with LeftMouseDown in the parent window.
+ NSEvent* mouse_down = cocoa_test_event_utils::LeftMouseDownAtPointInWindow(
+ NSMakePoint(50, 50), parent_widget->GetNativeWindow());
+ [NSApp sendEvent:mouse_down];
+ EXPECT_TRUE(bubble_widget->IsClosed());
+
+ bubble_widget =
+ BubbleDialogDelegateView::CreateBubble(new TestBubbleView(parent_widget));
+ ShowKeyWindow(bubble_widget);
+
+ // Test with RightMouseDown in the parent window.
+ mouse_down = cocoa_test_event_utils::RightMouseDownAtPointInWindow(
+ NSMakePoint(50, 50), parent_widget->GetNativeWindow());
+ [NSApp sendEvent:mouse_down];
+ EXPECT_TRUE(bubble_widget->IsClosed());
+
+ bubble_widget =
+ BubbleDialogDelegateView::CreateBubble(new TestBubbleView(parent_widget));
+ ShowKeyWindow(bubble_widget);
+
+ // Test with RightMouseDown in the bubble (bubble should stay open).
+ mouse_down = cocoa_test_event_utils::RightMouseDownAtPointInWindow(
+ NSMakePoint(50, 50), bubble_widget->GetNativeWindow());
+ [NSApp sendEvent:mouse_down];
+ EXPECT_FALSE(bubble_widget->IsClosed());
+ bubble_widget->CloseNow();
+
+ // Test with RightMouseDown when set_close_on_deactivate(false).
+ TestBubbleView* bubble_view = new TestBubbleView(parent_widget);
+ bubble_view->set_close_on_deactivate(false);
+ bubble_widget = BubbleDialogDelegateView::CreateBubble(bubble_view);
+ ShowKeyWindow(bubble_widget);
+
+ mouse_down = cocoa_test_event_utils::RightMouseDownAtPointInWindow(
+ NSMakePoint(50, 50), parent_widget->GetNativeWindow());
+ [NSApp sendEvent:mouse_down];
+ EXPECT_FALSE(bubble_widget->IsClosed());
+
+ parent_widget->CloseNow();
+}
+
INSTANTIATE_TEST_CASE_P(NativeWidgetMacInteractiveUITestInstance,
NativeWidgetMacInteractiveUITest,
::testing::Bool());
diff --git a/chromium/ui/views/widget/native_widget_mac_unittest.mm b/chromium/ui/views/widget/native_widget_mac_unittest.mm
index edd51fb6a44..5a2188cb882 100644
--- a/chromium/ui/views/widget/native_widget_mac_unittest.mm
+++ b/chromium/ui/views/widget/native_widget_mac_unittest.mm
@@ -664,7 +664,7 @@ TEST_F(NativeWidgetMacTest, AccessibilityIntegration) {
NSPoint midpoint = NSMakePoint(NSMidX(nsrect), NSMidY(nsrect));
id hit = [widget->GetNativeWindow() accessibilityHitTest:midpoint];
- id title = [hit accessibilityAttributeValue:NSAccessibilityTitleAttribute];
+ id title = [hit accessibilityAttributeValue:NSAccessibilityValueAttribute];
EXPECT_NSEQ(title, @"Green");
widget->CloseNow();
@@ -915,11 +915,17 @@ class ModalDialogDelegate : public DialogDelegateView {
explicit ModalDialogDelegate(ui::ModalType modal_type)
: modal_type_(modal_type) {}
+ void set_can_close(bool value) { can_close_ = value; }
+
// WidgetDelegate:
ui::ModalType GetModalType() const override { return modal_type_; }
+ // DialogDelegate:
+ bool Close() override { return can_close_; }
+
private:
const ui::ModalType modal_type_;
+ bool can_close_ = true;
DISALLOW_COPY_AND_ASSIGN(ModalDialogDelegate);
};
@@ -1697,6 +1703,80 @@ TEST_F(NativeWidgetMacTest, ChangeFocusOnChangeFirstResponder) {
widget->CloseNow();
}
+// Ensure reparented native view has correct bounds.
+TEST_F(NativeWidgetMacTest, ReparentNativeViewBounds) {
+ Widget* parent = CreateTopLevelFramelessPlatformWidget();
+ gfx::Rect parent_rect(100, 100, 300, 200);
+ parent->SetBounds(parent_rect);
+
+ Widget::InitParams params(Widget::InitParams::TYPE_CONTROL);
+ params.parent = parent->GetNativeView();
+ Widget* widget = new Widget;
+ widget->Init(params);
+ widget->SetContentsView(new View);
+
+ NSView* child_view = widget->GetNativeView();
+ Widget::ReparentNativeView(child_view, parent->GetNativeView());
+
+ // Reparented content view has the size of the Widget that created it.
+ gfx::Rect widget_rect(0, 0, 200, 100);
+ widget->SetBounds(widget_rect);
+ EXPECT_EQ(200, NSWidth([child_view frame]));
+ EXPECT_EQ(100, NSHeight([child_view frame]));
+
+ // Reparented widget has bounds relative to the native parent
+ NSRect native_parent_rect = NSMakeRect(50, 100, 200, 70);
+ base::scoped_nsobject<NSView> native_parent(
+ [[NSView alloc] initWithFrame:native_parent_rect]);
+ [parent->GetNativeView() addSubview:native_parent];
+
+ gfx::Rect screen_rect = widget->GetWindowBoundsInScreen();
+ EXPECT_EQ(100, screen_rect.x());
+ EXPECT_EQ(100, screen_rect.y());
+
+ Widget::ReparentNativeView(child_view, native_parent);
+ widget->SetBounds(widget_rect);
+ screen_rect = widget->GetWindowBoundsInScreen();
+ EXPECT_EQ(150, screen_rect.x());
+ EXPECT_EQ(130, screen_rect.y());
+
+ parent->CloseNow();
+}
+
+// Test two kinds of widgets to re-parent.
+TEST_F(NativeWidgetMacTest, ReparentNativeViewTypes) {
+ std::unique_ptr<Widget> toplevel1(new Widget);
+ Widget::InitParams toplevel_params =
+ CreateParams(Widget::InitParams::TYPE_POPUP);
+ toplevel_params.ownership = Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ toplevel1->Init(toplevel_params);
+
+ std::unique_ptr<Widget> toplevel2(new Widget);
+ toplevel2->Init(toplevel_params);
+
+ Widget* child = new Widget;
+ Widget::InitParams child_params(Widget::InitParams::TYPE_CONTROL);
+ child->Init(child_params);
+
+ Widget::ReparentNativeView(child->GetNativeView(),
+ toplevel1->GetNativeView());
+ EXPECT_EQ([child->GetNativeView() window],
+ [toplevel1->GetNativeView() window]);
+ EXPECT_EQ(0, [child->GetNativeWindow() alphaValue]);
+
+ Widget::ReparentNativeView(child->GetNativeView(),
+ toplevel2->GetNativeView());
+ EXPECT_EQ([child->GetNativeView() window],
+ [toplevel2->GetNativeView() window]);
+ EXPECT_EQ(0, [child->GetNativeWindow() alphaValue]);
+ EXPECT_NE(0, [toplevel1->GetNativeWindow() alphaValue]);
+
+ Widget::ReparentNativeView(toplevel2->GetNativeView(),
+ toplevel1->GetNativeView());
+ EXPECT_EQ([toplevel2->GetNativeWindow() parentWindow],
+ [toplevel1->GetNativeView() window]);
+}
+
// Test class for Full Keyboard Access related tests.
class NativeWidgetMacFullKeyboardAccessTest : public NativeWidgetMacTest {
public:
@@ -1877,6 +1957,19 @@ TEST_F(NativeWidgetMacViewsOrderTest, UnassociatedViewsIsAbove) {
]]));
}
+// Test -[NSWindowDelegate windowShouldClose:].
+TEST_F(NativeWidgetMacTest, CanClose) {
+ ModalDialogDelegate* delegate = new ModalDialogDelegate(ui::MODAL_TYPE_NONE);
+ Widget* widget =
+ views::DialogDelegate::CreateDialogWidget(delegate, nullptr, nullptr);
+ NSWindow* window = widget->GetNativeWindow();
+ delegate->set_can_close(false);
+ EXPECT_FALSE([[window delegate] windowShouldClose:window]);
+ delegate->set_can_close(true);
+ EXPECT_TRUE([[window delegate] windowShouldClose:window]);
+ widget->CloseNow();
+}
+
} // namespace test
} // namespace views
diff --git a/chromium/ui/views/widget/native_widget_private.h b/chromium/ui/views/widget/native_widget_private.h
index dfe37828b68..ebeb4e377b9 100644
--- a/chromium/ui/views/widget/native_widget_private.h
+++ b/chromium/ui/views/widget/native_widget_private.h
@@ -176,7 +176,7 @@ class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget {
virtual void SetSize(const gfx::Size& size) = 0;
virtual void StackAbove(gfx::NativeView native_view) = 0;
virtual void StackAtTop() = 0;
- virtual void SetShape(std::unique_ptr<SkRegion> shape) = 0;
+ virtual void SetShape(std::unique_ptr<Widget::ShapeRects> shape) = 0;
virtual void Close() = 0;
virtual void CloseNow() = 0;
virtual void Show() = 0;
diff --git a/chromium/ui/views/widget/root_view.cc b/chromium/ui/views/widget/root_view.cc
index 37e54bdf2d7..acc2aaf61d0 100644
--- a/chromium/ui/views/widget/root_view.cc
+++ b/chromium/ui/views/widget/root_view.cc
@@ -219,10 +219,6 @@ void RootView::ThemeChanged() {
View::PropagateThemeChanged();
}
-void RootView::LocaleChanged() {
- View::PropagateLocaleChanged();
-}
-
void RootView::DeviceScaleFactorChanged(float device_scale_factor) {
View::PropagateDeviceScaleFactorChanged(device_scale_factor);
}
@@ -644,12 +640,13 @@ void RootView::OnPaint(gfx::Canvas* canvas) {
View::OnPaint(canvas);
}
-gfx::Vector2d RootView::CalculateOffsetToAncestorWithLayer(
+View::LayerOffsetData RootView::CalculateOffsetToAncestorWithLayer(
ui::Layer** layer_parent) {
- gfx::Vector2d offset(View::CalculateOffsetToAncestorWithLayer(layer_parent));
- if (!layer() && layer_parent)
+ if (layer() || !widget_->GetLayer())
+ return View::CalculateOffsetToAncestorWithLayer(layer_parent);
+ if (layer_parent)
*layer_parent = widget_->GetLayer();
- return offset;
+ return LayerOffsetData(widget_->GetLayer()->device_scale_factor());
}
View::DragInfo* RootView::GetDragInfo() {
diff --git a/chromium/ui/views/widget/root_view.h b/chromium/ui/views/widget/root_view.h
index d8212a24d78..17ae8112718 100644
--- a/chromium/ui/views/widget/root_view.h
+++ b/chromium/ui/views/widget/root_view.h
@@ -83,10 +83,6 @@ class VIEWS_EXPORT RootView : public View,
// hierarchy.
void ThemeChanged();
- // Public API for broadcasting locale change notifications to this View
- // hierarchy.
- void LocaleChanged();
-
// Public API for broadcasting device scale factor change notifications to
// this View hierarchy.
void DeviceScaleFactorChanged(float device_scale_factor);
@@ -125,7 +121,7 @@ class VIEWS_EXPORT RootView : public View,
const ViewHierarchyChangedDetails& details) override;
void VisibilityChanged(View* starting_from, bool is_visible) override;
void OnPaint(gfx::Canvas* canvas) override;
- gfx::Vector2d CalculateOffsetToAncestorWithLayer(
+ View::LayerOffsetData CalculateOffsetToAncestorWithLayer(
ui::Layer** layer_parent) override;
View::DragInfo* GetDragInfo() override;
diff --git a/chromium/ui/views/widget/widget.cc b/chromium/ui/views/widget/widget.cc
index 32a50e8860a..d37585c6fa3 100644
--- a/chromium/ui/views/widget/widget.cc
+++ b/chromium/ui/views/widget/widget.cc
@@ -567,7 +567,7 @@ void Widget::StackAtTop() {
native_widget_->StackAtTop();
}
-void Widget::SetShape(std::unique_ptr<SkRegion> shape) {
+void Widget::SetShape(std::unique_ptr<ShapeRects> shape) {
native_widget_->SetShape(std::move(shape));
}
@@ -857,10 +857,6 @@ void Widget::ThemeChanged() {
root_view_->ThemeChanged();
}
-void Widget::LocaleChanged() {
- root_view_->LocaleChanged();
-}
-
void Widget::DeviceScaleFactorChanged(float device_scale_factor) {
root_view_->DeviceScaleFactorChanged(device_scale_factor);
}
diff --git a/chromium/ui/views/widget/widget.h b/chromium/ui/views/widget/widget.h
index 63fcb9d611e..6590ea90b80 100644
--- a/chromium/ui/views/widget/widget.h
+++ b/chromium/ui/views/widget/widget.h
@@ -109,7 +109,8 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
public FocusTraversable,
public ui::NativeThemeObserver {
public:
- typedef std::set<Widget*> Widgets;
+ using Widgets = std::set<Widget*>;
+ using ShapeRects = std::vector<gfx::Rect>;
enum FrameType {
FRAME_TYPE_DEFAULT, // Use whatever the default would be.
@@ -484,7 +485,7 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// Sets a shape on the widget. Passing a NULL |shape| reverts the widget to
// be rectangular.
- void SetShape(std::unique_ptr<SkRegion> shape);
+ void SetShape(std::unique_ptr<ShapeRects> shape);
// Hides the widget then closes it after a return to the message loop.
virtual void Close();
@@ -641,10 +642,6 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// changed.
void ThemeChanged();
- // Notifies the view hierarchy contained in this widget that locale resources
- // changed.
- void LocaleChanged();
-
// Notifies the view hierarchy contained in this widget that the device scale
// factor changed.
void DeviceScaleFactorChanged(float device_scale_factor);
@@ -859,7 +856,7 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
private:
friend class ComboboxTest;
- friend class CustomButtonTest;
+ friend class ButtonTest;
friend class TextfieldTest;
friend class ViewAuraTest;
diff --git a/chromium/ui/views/widget/widget_interactive_uitest.cc b/chromium/ui/views/widget/widget_interactive_uitest.cc
index 75aba4f70ef..fd641827713 100644
--- a/chromium/ui/views/widget/widget_interactive_uitest.cc
+++ b/chromium/ui/views/widget/widget_interactive_uitest.cc
@@ -62,7 +62,7 @@ class ExitLoopOnRelease : public View {
// View:
void OnMouseReleased(const ui::MouseEvent& event) override {
GetWidget()->Close();
- base::MessageLoop::current()->QuitNow();
+ base::RunLoop::QuitCurrentDeprecated();
}
DISALLOW_COPY_AND_ASSIGN(ExitLoopOnRelease);
diff --git a/chromium/ui/views/widget/widget_unittest.cc b/chromium/ui/views/widget/widget_unittest.cc
index e321d91b9a0..9cddacbcda9 100644
--- a/chromium/ui/views/widget/widget_unittest.cc
+++ b/chromium/ui/views/widget/widget_unittest.cc
@@ -8,7 +8,6 @@
#include "base/bind.h"
#include "base/macros.h"
-#include "base/message_loop/message_loop.h"
#include "base/run_loop.h"
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
@@ -1059,7 +1058,7 @@ TEST_F(WidgetTest, GetWindowPlacement) {
#endif
WidgetAutoclosePtr widget;
-#if defined(USE_X11) && !defined(OS_CHROMEOS)
+#if defined(USE_X11)
// On desktop-Linux cheat and use non-desktop widgets. On X11, minimize is
// asynchronous. Also (harder) showing a window doesn't activate it without
// user interaction (or extra steps only done for interactive ui tests).
@@ -2096,7 +2095,7 @@ class CloseDestroysWidget : public Widget {
~CloseDestroysWidget() override {
if (destroyed_) {
*destroyed_ = true;
- base::MessageLoop::current()->QuitNow();
+ base::RunLoop::QuitCurrentDeprecated();
}
}
diff --git a/chromium/ui/views/win/hwnd_message_handler.cc b/chromium/ui/views/win/hwnd_message_handler.cc
index d8086d862d5..9664c746279 100644
--- a/chromium/ui/views/win/hwnd_message_handler.cc
+++ b/chromium/ui/views/win/hwnd_message_handler.cc
@@ -29,6 +29,7 @@
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/ime/text_input_type.h"
+#include "ui/base/ui_base_switches.h"
#include "ui/base/view_prop.h"
#include "ui/base/win/internal_constants.h"
#include "ui/base/win/lock_state.h"
@@ -241,12 +242,12 @@ ui::EventType GetTouchEventType(POINTER_FLAGS pointer_flags) {
const int kTouchDownContextResetTimeout = 500;
-// Windows does not flag synthesized mouse messages from touch in all cases.
-// This causes us grief as we don't want to process touch and mouse messages
-// concurrently. Hack as per msdn is to check if the time difference between
-// the touch message and the mouse move is within 500 ms and at the same
-// location as the cursor.
-const int kSynthesizedMouseTouchMessagesTimeDifference = 500;
+// Windows does not flag synthesized mouse messages from touch or pen in all
+// cases. This causes us grief as we don't want to process touch and mouse
+// messages concurrently. Hack as per msdn is to check if the time difference
+// between the touch/pen message and the mouse move is within 500 ms and at the
+// same location as the cursor.
+const int kSynthesizedMouseMessagesTimeDifference = 500;
// Currently this flag is always false - see http://crbug.com/763223
const bool kUsePointerEventsForTouch = false;
@@ -339,7 +340,7 @@ base::LazyInstance<HWNDMessageHandler::FullscreenWindowMonitorMap>::
////////////////////////////////////////////////////////////////////////////////
// HWNDMessageHandler, public:
-long HWNDMessageHandler::last_touch_message_time_ = 0;
+long HWNDMessageHandler::last_touch_or_pen_message_time_ = 0;
HWNDMessageHandler::HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate)
: msg_handled_(FALSE),
@@ -360,6 +361,9 @@ HWNDMessageHandler::HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate)
is_first_nccalc_(true),
menu_depth_(0),
id_generator_(0),
+ pen_processor_(
+ &id_generator_,
+ base::FeatureList::IsEnabled(features::kDirectManipulationStylus)),
in_size_loop_(false),
touch_down_contexts_(0),
last_mouse_hwheel_time_(0),
@@ -2322,7 +2326,7 @@ LRESULT HWNDMessageHandler::OnTouchEvent(UINT message,
ScreenToClient(hwnd(), &point);
- last_touch_message_time_ = ::GetMessageTime();
+ last_touch_or_pen_message_time_ = ::GetMessageTime();
gfx::Point touch_point(point.x, point.y);
unsigned int touch_id = id_generator_.GetGeneratedID(input[i].dwID);
@@ -2346,7 +2350,7 @@ LRESULT HWNDMessageHandler::OnTouchEvent(UINT message,
touch_ids_.erase(input[i].dwID);
GenerateTouchEvent(ui::ET_TOUCH_RELEASED, touch_point, touch_id,
event_time, &touch_events);
- id_generator_.ReleaseNumber(input[i].dwID);
+ id_generator_.MaybeReleaseNumber(input[i].dwID);
}
}
}
@@ -2715,8 +2719,16 @@ LRESULT HWNDMessageHandler::HandlePointerEventTypeTouch(UINT message,
return -1;
}
- POINTER_INFO pointer_info = pointer_touch_info.pointerInfo;
+ // Ignore enter/leave events, otherwise they will be converted in
+ // |GetTouchEventType| to ET_TOUCH_PRESSED/ET_TOUCH_RELEASED events, which
+ // is not correct.
+ if (message == WM_POINTERENTER || message == WM_POINTERLEAVE) {
+ SetMsgHandled(TRUE);
+ return 0;
+ }
+ unsigned int mapped_pointer_id = id_generator_.GetGeneratedID(pointer_id);
+ POINTER_INFO pointer_info = pointer_touch_info.pointerInfo;
POINT client_point = pointer_info.ptPixelLocationRaw;
ScreenToClient(hwnd(), &client_point);
gfx::Point touch_point = gfx::Point(client_point.x, client_point.y);
@@ -2741,9 +2753,9 @@ LRESULT HWNDMessageHandler::HandlePointerEventTypeTouch(UINT message,
ui::TouchEvent event(
event_type, touch_point, event_time,
- ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH, pointer_id,
- radius_x, radius_y, pressure, 0.0f, 0.0f, 0.0f,
- pointer_touch_info.orientation),
+ ui::PointerDetails(ui::EventPointerType::POINTER_TYPE_TOUCH,
+ mapped_pointer_id, radius_x, radius_y, pressure, 0.0f,
+ 0.0f, 0.0f, pointer_touch_info.orientation),
ui::GetModifiersFromKeyState(), rotation_angle);
event.latency()->AddLatencyNumberWithTimestamp(
@@ -2754,6 +2766,8 @@ LRESULT HWNDMessageHandler::HandlePointerEventTypeTouch(UINT message,
base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr());
delegate_->HandleTouchEvent(event);
+ if (event_type == ui::ET_TOUCH_RELEASED)
+ id_generator_.MaybeReleaseNumber(pointer_id);
if (ref)
SetMsgHandled(TRUE);
return 0;
@@ -2774,82 +2788,31 @@ LRESULT HWNDMessageHandler::HandlePointerEventTypePen(UINT message,
return -1;
}
- // We are now creating a fake mouse event with pointer type of pen from
- // the WM_POINTER message and then setting up an associated pointer
- // details in the MouseEvent which contains the pen's information.
- ui::EventPointerType input_type = ui::EventPointerType::POINTER_TYPE_PEN;
- // TODO(lanwei): penFlags of PEN_FLAG_INVERTED may also indicate we are using
- // an eraser, but it is under debate. Please see
- // https://github.com/w3c/pointerevents/issues/134/.
- if (pointer_pen_info.penFlags & PEN_FLAG_ERASER)
- input_type = ui::EventPointerType::POINTER_TYPE_ERASER;
-
- float pressure = static_cast<float>(pointer_pen_info.pressure) / 1024;
- float rotation = pointer_pen_info.rotation;
- int tilt_x = pointer_pen_info.tiltX;
- int tilt_y = pointer_pen_info.tiltY;
POINT client_point = pointer_pen_info.pointerInfo.ptPixelLocationRaw;
ScreenToClient(hwnd(), &client_point);
gfx::Point point = gfx::Point(client_point.x, client_point.y);
- ui::EventType event_type = ui::ET_MOUSE_MOVED;
- int flag = 0;
- int click_count = 0;
- switch (message) {
- case WM_POINTERDOWN:
- event_type = ui::ET_MOUSE_PRESSED;
- if (pointer_pen_info.pointerInfo.ButtonChangeType ==
- POINTER_CHANGE_SECONDBUTTON_DOWN) {
- flag = ui::EF_RIGHT_MOUSE_BUTTON;
- } else {
- flag = ui::EF_LEFT_MOUSE_BUTTON;
- }
- click_count = 1;
- break;
- case WM_POINTERUP:
- event_type = ui::ET_MOUSE_RELEASED;
- if (pointer_pen_info.pointerInfo.ButtonChangeType ==
- POINTER_CHANGE_SECONDBUTTON_UP) {
- flag = ui::EF_RIGHT_MOUSE_BUTTON;
- } else {
- flag = ui::EF_LEFT_MOUSE_BUTTON;
- }
- click_count = 1;
- break;
- case WM_POINTERUPDATE:
- event_type = ui::ET_MOUSE_DRAGGED;
- if (pointer_pen_info.pointerInfo.pointerFlags &
- POINTER_FLAG_FIRSTBUTTON) {
- flag = ui::EF_LEFT_MOUSE_BUTTON;
- } else if (pointer_pen_info.pointerInfo.pointerFlags &
- POINTER_FLAG_SECONDBUTTON) {
- flag = ui::EF_RIGHT_MOUSE_BUTTON;
- } else {
- event_type = ui::ET_MOUSE_MOVED;
- }
- break;
- case WM_POINTERENTER:
- event_type = ui::ET_MOUSE_ENTERED;
- break;
- case WM_POINTERLEAVE:
- event_type = ui::ET_MOUSE_EXITED;
- break;
- default:
- NOTREACHED();
- }
- ui::PointerDetails pointer_details(
- input_type, pointer_id, /* radius_x */ 0.0f, /* radius_y */ 0.0f,
- pressure, tilt_x, tilt_y, /* tangential_pressure */ 0.0f, rotation);
- ui::MouseEvent event(event_type, point, point, base::TimeTicks::Now(), flag,
- flag, pointer_details);
- event.SetClickCount(click_count);
+
+ std::unique_ptr<ui::Event> event = pen_processor_.GenerateEvent(
+ message, pointer_id, pointer_pen_info, point);
// There are cases where the code handling the message destroys the
// window, so use the weak ptr to check if destruction occured or not.
base::WeakPtr<HWNDMessageHandler> ref(weak_factory_.GetWeakPtr());
- bool handled = delegate_->HandleMouseEvent(event);
+ if (event) {
+ if (event->IsTouchEvent()) {
+ delegate_->HandleTouchEvent(*event->AsTouchEvent());
+ } else if (event->IsMouseEvent()) {
+ delegate_->HandleMouseEvent(*event->AsMouseEvent());
+ } else {
+ NOTREACHED();
+ }
+ last_touch_or_pen_message_time_ = ::GetMessageTime();
+ }
+ // Always mark as handled as we don't want to generate WM_MOUSE compatiblity
+ // events.
if (ref)
- SetMsgHandled(handled);
+ SetMsgHandled(TRUE);
return 0;
}
@@ -2861,9 +2824,10 @@ bool HWNDMessageHandler::IsSynthesizedMouseMessage(unsigned int message,
// Ignore mouse messages which occur at the same location as the current
// cursor position and within a time difference of 500 ms from the last
// touch message.
- if (last_touch_message_time_ && message_time >= last_touch_message_time_ &&
- ((message_time - last_touch_message_time_) <=
- kSynthesizedMouseTouchMessagesTimeDifference)) {
+ if (last_touch_or_pen_message_time_ &&
+ message_time >= last_touch_or_pen_message_time_ &&
+ ((message_time - last_touch_or_pen_message_time_) <=
+ kSynthesizedMouseMessagesTimeDifference)) {
POINT mouse_location = CR_POINT_INITIALIZER_FROM_LPARAM(l_param);
::ClientToScreen(hwnd(), &mouse_location);
POINT cursor_pos = {0};
diff --git a/chromium/ui/views/win/hwnd_message_handler.h b/chromium/ui/views/win/hwnd_message_handler.h
index 51f399a202f..ad432b4d9ac 100644
--- a/chromium/ui/views/win/hwnd_message_handler.h
+++ b/chromium/ui/views/win/hwnd_message_handler.h
@@ -29,6 +29,7 @@
#include "ui/gfx/sequential_id_generator.h"
#include "ui/gfx/win/window_impl.h"
#include "ui/views/views_export.h"
+#include "ui/views/win/pen_event_processor.h"
namespace gfx {
class ImageSkia;
@@ -543,6 +544,19 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl,
WPARAM w_param,
LPARAM l_param);
+ LRESULT GenerateMouseEventFromPointerEvent(
+ UINT message,
+ UINT32 pointer_id,
+ const POINTER_INFO& pointer_info,
+ const gfx::Point& point,
+ const ui::PointerDetails& pointer_details);
+ LRESULT GenerateTouchEventFromPointerEvent(
+ UINT message,
+ UINT32 pointer_id,
+ const POINTER_INFO& pointer_info,
+ const gfx::Point& point,
+ const ui::PointerDetails& pointer_details);
+
// Returns true if the mouse message passed in is an OS synthesized mouse
// message.
// |message| identifies the mouse message.
@@ -671,6 +685,8 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl,
// Generates touch-ids for touch-events.
ui::SequentialIDGenerator id_generator_;
+ PenEventProcessor pen_processor_;
+
// Set to true if we are in the context of a sizing operation.
bool in_size_loop_;
@@ -685,11 +701,11 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl,
// native SetFocus calls invoked in the views code.
int touch_down_contexts_;
- // Time the last touch message was received. Used to flag mouse messages
- // synthesized by Windows for touch which are not flagged by the OS as
- // synthesized mouse messages. For more information please refer to
- // the IsMouseEventFromTouch function.
- static long last_touch_message_time_;
+ // Time the last touch or pen message was received. Used to flag mouse
+ // messages synthesized by Windows for touch which are not flagged by the OS
+ // as synthesized mouse messages. For more information please refer to the
+ // IsMouseEventFromTouch function.
+ static long last_touch_or_pen_message_time_;
// Time the last WM_MOUSEHWHEEL message is received. Please refer to the
// HandleMouseEventInternal function as to why this is needed.
diff --git a/chromium/ui/views/win/hwnd_message_handler_delegate.h b/chromium/ui/views/win/hwnd_message_handler_delegate.h
index 72d3213945d..2168aedea4b 100644
--- a/chromium/ui/views/win/hwnd_message_handler_delegate.h
+++ b/chromium/ui/views/win/hwnd_message_handler_delegate.h
@@ -188,6 +188,10 @@ class VIEWS_EXPORT HWNDMessageHandlerDelegate {
// handled by the delegate.
virtual bool HandleMouseEvent(const ui::MouseEvent& event) = 0;
+ // Called when a pointer event is received. Returns true if the event was
+ // handled by the delegate.
+ virtual bool HandlePointerEvent(ui::PointerEvent* event) = 0;
+
// Called when an untranslated key event is received (i.e. pre-IME
// translation).
virtual void HandleKeyEvent(ui::KeyEvent* event) = 0;
diff --git a/chromium/ui/views/win/pen_event_processor.cc b/chromium/ui/views/win/pen_event_processor.cc
new file mode 100644
index 00000000000..d42fe1eff3c
--- /dev/null
+++ b/chromium/ui/views/win/pen_event_processor.cc
@@ -0,0 +1,197 @@
+// 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 "pen_event_processor.h"
+
+#include "base/memory/ptr_util.h"
+#include "base/time/time.h"
+#include "ui/events/event_utils.h"
+
+namespace views {
+namespace {
+
+int GetFlagsFromPointerMessage(UINT message, const POINTER_INFO& pointer_info) {
+ int flags = ui::EF_NONE;
+ if (pointer_info.pointerFlags & POINTER_FLAG_FIRSTBUTTON)
+ flags |= ui::EF_LEFT_MOUSE_BUTTON;
+
+ if (pointer_info.pointerFlags & POINTER_FLAG_SECONDBUTTON)
+ flags |= ui::EF_RIGHT_MOUSE_BUTTON;
+
+ if (message == WM_POINTERUP) {
+ if (pointer_info.ButtonChangeType == POINTER_CHANGE_SECONDBUTTON_UP)
+ flags |= ui::EF_RIGHT_MOUSE_BUTTON;
+ else
+ flags |= ui::EF_LEFT_MOUSE_BUTTON;
+ }
+ return flags;
+}
+
+} // namespace
+
+PenEventProcessor::PenEventProcessor(ui::SequentialIDGenerator* id_generator,
+ bool direct_manipulation_enabled)
+ : id_generator_(id_generator),
+ direct_manipulation_enabled_(direct_manipulation_enabled) {}
+
+PenEventProcessor::~PenEventProcessor() {}
+
+std::unique_ptr<ui::Event> PenEventProcessor::GenerateEvent(
+ UINT message,
+ UINT32 pointer_id,
+ const POINTER_PEN_INFO& pointer_pen_info,
+ const gfx::Point& point) {
+ unsigned int mapped_pointer_id = id_generator_->GetGeneratedID(pointer_id);
+
+ // We are now creating a fake mouse event with pointer type of pen from
+ // the WM_POINTER message and then setting up an associated pointer
+ // details in the MouseEvent which contains the pen's information.
+ ui::EventPointerType input_type = ui::EventPointerType::POINTER_TYPE_PEN;
+ // TODO(lanwei): penFlags of PEN_FLAG_INVERTED may also indicate we are using
+ // an eraser, but it is under debate. Please see
+ // https://github.com/w3c/pointerevents/issues/134/.
+ if (pointer_pen_info.penFlags & PEN_FLAG_ERASER)
+ input_type = ui::EventPointerType::POINTER_TYPE_ERASER;
+
+ // 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 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, tilt_x, tilt_y, /* tangential_pressure */ 0.0f, rotation);
+
+ // If the flag is disabled, we send mouse events for all pen inputs.
+ if (!direct_manipulation_enabled_) {
+ return GenerateMouseEvent(message, pointer_id, pointer_pen_info.pointerInfo,
+ point, pointer_details);
+ }
+ bool is_pointer_event =
+ message == WM_POINTERENTER || message == WM_POINTERLEAVE;
+
+ // Send MouseEvents when the pen is hovering or any buttons (other than the
+ // tip) are depressed when the stylus makes contact with the digitizer. Ensure
+ // we read |send_touch_for_pen_| before we process the event as we want to
+ // ensure a TouchRelease is sent appropriately at the end when the stylus is
+ // no longer in contact with the digitizer.
+ bool send_touch = send_touch_for_pen_;
+ if (pointer_pen_info.pointerInfo.pointerFlags & POINTER_FLAG_INCONTACT) {
+ if (!pen_in_contact_) {
+ send_touch = send_touch_for_pen_ =
+ (pointer_pen_info.pointerInfo.pointerFlags &
+ (POINTER_FLAG_SECONDBUTTON | POINTER_FLAG_THIRDBUTTON |
+ POINTER_FLAG_FOURTHBUTTON | POINTER_FLAG_FIFTHBUTTON)) == 0;
+ }
+ pen_in_contact_ = true;
+ } else {
+ pen_in_contact_ = false;
+ send_touch_for_pen_ = false;
+ }
+
+ if (is_pointer_event || !send_touch) {
+ return GenerateMouseEvent(message, pointer_id, pointer_pen_info.pointerInfo,
+ point, pointer_details);
+ }
+
+ return GenerateTouchEvent(message, pointer_id, pointer_pen_info.pointerInfo,
+ point, pointer_details);
+}
+
+std::unique_ptr<ui::Event> PenEventProcessor::GenerateMouseEvent(
+ UINT message,
+ UINT32 pointer_id,
+ const POINTER_INFO& pointer_info,
+ const gfx::Point& point,
+ const ui::PointerDetails& pointer_details) {
+ ui::EventType event_type = ui::ET_MOUSE_MOVED;
+ int flag = GetFlagsFromPointerMessage(message, pointer_info);
+ int changed_flag = ui::EF_NONE;
+ int click_count = 0;
+ switch (message) {
+ case WM_POINTERDOWN:
+ event_type = ui::ET_MOUSE_PRESSED;
+ if (pointer_info.ButtonChangeType == POINTER_CHANGE_FIRSTBUTTON_DOWN)
+ changed_flag = ui::EF_LEFT_MOUSE_BUTTON;
+ else
+ changed_flag = ui::EF_RIGHT_MOUSE_BUTTON;
+ click_count = 1;
+ sent_mouse_down_ = true;
+ break;
+ case WM_POINTERUP:
+ event_type = ui::ET_MOUSE_RELEASED;
+ if (pointer_info.ButtonChangeType == POINTER_CHANGE_FIRSTBUTTON_UP)
+ changed_flag = ui::EF_LEFT_MOUSE_BUTTON;
+ else
+ changed_flag = ui::EF_RIGHT_MOUSE_BUTTON;
+ id_generator_->MaybeReleaseNumber(pointer_id);
+ click_count = 1;
+ if (!sent_mouse_down_)
+ return nullptr;
+ sent_mouse_down_ = false;
+ break;
+ case WM_POINTERUPDATE:
+ event_type = ui::ET_MOUSE_DRAGGED;
+ if (flag == ui::EF_NONE)
+ event_type = ui::ET_MOUSE_MOVED;
+ break;
+ case WM_POINTERENTER:
+ event_type = ui::ET_MOUSE_ENTERED;
+ break;
+ case WM_POINTERLEAVE:
+ event_type = ui::ET_MOUSE_EXITED;
+ id_generator_->MaybeReleaseNumber(pointer_id);
+ break;
+ default:
+ NOTREACHED();
+ }
+ std::unique_ptr<ui::Event> event = base::MakeUnique<ui::MouseEvent>(
+ event_type, point, point, ui::EventTimeForNow(), flag, changed_flag,
+ pointer_details);
+ event->AsMouseEvent()->SetClickCount(click_count);
+ return event;
+}
+
+std::unique_ptr<ui::Event> PenEventProcessor::GenerateTouchEvent(
+ UINT message,
+ UINT32 pointer_id,
+ const POINTER_INFO& pointer_info,
+ const gfx::Point& point,
+ const ui::PointerDetails& pointer_details) {
+ int flags = GetFlagsFromPointerMessage(message, pointer_info);
+
+ ui::EventType event_type = ui::ET_TOUCH_MOVED;
+ switch (message) {
+ case WM_POINTERDOWN:
+ event_type = ui::ET_TOUCH_PRESSED;
+ sent_touch_start_ = true;
+ break;
+ case WM_POINTERUP:
+ event_type = ui::ET_TOUCH_RELEASED;
+ id_generator_->MaybeReleaseNumber(pointer_id);
+ if (!sent_touch_start_)
+ return nullptr;
+ sent_touch_start_ = false;
+ break;
+ case WM_POINTERUPDATE:
+ event_type = ui::ET_TOUCH_MOVED;
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ 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::Event> event = base::MakeUnique<ui::TouchEvent>(
+ event_type, point, event_time, pointer_details, flags, rotation_angle);
+ event->latency()->AddLatencyNumberWithTimestamp(
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, 0, 0, event_time, 1);
+ return event;
+}
+
+} // namespace views
diff --git a/chromium/ui/views/win/pen_event_processor.h b/chromium/ui/views/win/pen_event_processor.h
new file mode 100644
index 00000000000..60d55489d5e
--- /dev/null
+++ b/chromium/ui/views/win/pen_event_processor.h
@@ -0,0 +1,63 @@
+// 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_VIEWS_WIN_PEN_EVENT_PROCESSOR_H_
+#define UI_VIEWS_WIN_PEN_EVENT_PROCESSOR_H_
+
+#include <windows.h>
+
+#include <memory>
+
+#include "ui/events/event.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/sequential_id_generator.h"
+#include "ui/views/views_export.h"
+
+namespace views {
+
+// This class handles the processing pen event state information
+// from native Windows events and returning appropriate
+// ui::Events for the current state.
+class VIEWS_EXPORT PenEventProcessor {
+ public:
+ // |id_generator| must outlive this object's lifecycle.
+ PenEventProcessor(ui::SequentialIDGenerator* id_generator,
+ bool direct_manipulation_enabled);
+ ~PenEventProcessor();
+
+ // Generate an appropriate ui::Event for a given pen pointer.
+ // May return nullptr if no event should be dispatched.
+ std::unique_ptr<ui::Event> GenerateEvent(
+ UINT message,
+ UINT32 pointer_id,
+ const POINTER_PEN_INFO& pen_pointer_info,
+ const gfx::Point& point);
+
+ private:
+ std::unique_ptr<ui::Event> GenerateMouseEvent(
+ UINT message,
+ UINT32 pointer_id,
+ const POINTER_INFO& pointer_info,
+ const gfx::Point& point,
+ const ui::PointerDetails& pointer_details);
+ std::unique_ptr<ui::Event> GenerateTouchEvent(
+ UINT message,
+ UINT32 pointer_id,
+ const POINTER_INFO& pointer_info,
+ const gfx::Point& point,
+ const ui::PointerDetails& pointer_details);
+
+ ui::SequentialIDGenerator* id_generator_;
+ bool direct_manipulation_enabled_;
+ bool pen_in_contact_ = false;
+ bool send_touch_for_pen_ = false;
+ bool sent_mouse_down_ = false;
+ bool sent_touch_start_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(PenEventProcessor);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_WIN_PEN_EVENT_PROCESSOR_H_
diff --git a/chromium/ui/views/win/pen_event_processor_unittest.cc b/chromium/ui/views/win/pen_event_processor_unittest.cc
new file mode 100644
index 00000000000..228d2453b67
--- /dev/null
+++ b/chromium/ui/views/win/pen_event_processor_unittest.cc
@@ -0,0 +1,151 @@
+// 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/views/win/pen_event_processor.h"
+
+#include <gtest/gtest.h>
+
+#include "ui/gfx/sequential_id_generator.h"
+
+namespace views {
+
+TEST(PenProcessorTest, TypicalCaseDMDisabled) {
+ ui::SequentialIDGenerator id_generator(0);
+ PenEventProcessor processor(&id_generator,
+ /*direct_manipulation_enabled*/ false);
+
+ POINTER_PEN_INFO pen_info;
+ memset(&pen_info, 0, sizeof(POINTER_PEN_INFO));
+ gfx::Point point(100, 100);
+
+ std::unique_ptr<ui::Event> event =
+ processor.GenerateEvent(WM_POINTERENTER, 0, pen_info, point);
+ ASSERT_TRUE(event);
+ ASSERT_TRUE(event->IsMouseEvent());
+ EXPECT_EQ(ui::ET_MOUSE_ENTERED, event->AsMouseEvent()->type());
+
+ pen_info.pointerInfo.pointerFlags =
+ POINTER_FLAG_INCONTACT | POINTER_FLAG_FIRSTBUTTON;
+ pen_info.pointerInfo.ButtonChangeType = POINTER_CHANGE_FIRSTBUTTON_DOWN;
+
+ event = processor.GenerateEvent(WM_POINTERDOWN, 0, pen_info, point);
+ ASSERT_TRUE(event);
+ ASSERT_TRUE(event->IsMouseEvent());
+ EXPECT_EQ(ui::ET_MOUSE_PRESSED, event->AsMouseEvent()->type());
+ EXPECT_EQ(1, event->AsMouseEvent()->GetClickCount());
+ EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON,
+ event->AsMouseEvent()->changed_button_flags());
+
+ pen_info.pointerInfo.ButtonChangeType = POINTER_CHANGE_NONE;
+ event = processor.GenerateEvent(WM_POINTERUPDATE, 0, pen_info, point);
+ ASSERT_TRUE(event);
+ ASSERT_TRUE(event->IsMouseEvent());
+ EXPECT_EQ(ui::ET_MOUSE_DRAGGED, event->AsMouseEvent()->type());
+
+ pen_info.pointerInfo.pointerFlags = POINTER_FLAG_INCONTACT;
+ pen_info.pointerInfo.ButtonChangeType = POINTER_CHANGE_FIRSTBUTTON_UP;
+ event = processor.GenerateEvent(WM_POINTERUP, 0, pen_info, point);
+ ASSERT_TRUE(event);
+ ASSERT_TRUE(event->IsMouseEvent());
+ EXPECT_EQ(ui::ET_MOUSE_RELEASED, event->AsMouseEvent()->type());
+ EXPECT_EQ(ui::EF_LEFT_MOUSE_BUTTON,
+ event->AsMouseEvent()->changed_button_flags());
+
+ pen_info.pointerInfo.pointerFlags = POINTER_FLAG_NONE;
+ event = processor.GenerateEvent(WM_POINTERUPDATE, 0, pen_info, point);
+ ASSERT_TRUE(event);
+ ASSERT_TRUE(event->IsMouseEvent());
+ EXPECT_EQ(ui::ET_MOUSE_MOVED, event->AsMouseEvent()->type());
+
+ event = processor.GenerateEvent(WM_POINTERLEAVE, 0, pen_info, point);
+ ASSERT_TRUE(event);
+ ASSERT_TRUE(event->IsMouseEvent());
+ EXPECT_EQ(ui::ET_MOUSE_EXITED, event->AsMouseEvent()->type());
+}
+
+TEST(PenProcessorTest, TypicalCaseDMEnabled) {
+ ui::SequentialIDGenerator id_generator(0);
+ PenEventProcessor processor(&id_generator,
+ /*direct_manipulation_enabled*/ true);
+
+ POINTER_PEN_INFO pen_info;
+ memset(&pen_info, 0, sizeof(POINTER_PEN_INFO));
+ gfx::Point point(100, 100);
+
+ std::unique_ptr<ui::Event> event =
+ processor.GenerateEvent(WM_POINTERENTER, 0, pen_info, point);
+ ASSERT_TRUE(event);
+ ASSERT_TRUE(event->IsMouseEvent());
+ EXPECT_EQ(ui::ET_MOUSE_ENTERED, event->AsMouseEvent()->type());
+
+ pen_info.pointerInfo.pointerFlags =
+ POINTER_FLAG_INCONTACT | POINTER_FLAG_FIRSTBUTTON;
+ pen_info.pointerInfo.ButtonChangeType = POINTER_CHANGE_FIRSTBUTTON_DOWN;
+
+ event = processor.GenerateEvent(WM_POINTERDOWN, 0, pen_info, point);
+ ASSERT_TRUE(event);
+ ASSERT_TRUE(event->IsTouchEvent());
+ EXPECT_EQ(ui::ET_TOUCH_PRESSED, event->AsTouchEvent()->type());
+
+ pen_info.pointerInfo.ButtonChangeType = POINTER_CHANGE_NONE;
+ event = processor.GenerateEvent(WM_POINTERUPDATE, 0, pen_info, point);
+ ASSERT_TRUE(event);
+ ASSERT_TRUE(event->IsTouchEvent());
+ EXPECT_EQ(ui::ET_TOUCH_MOVED, event->AsTouchEvent()->type());
+
+ pen_info.pointerInfo.pointerFlags = POINTER_FLAG_NONE;
+ pen_info.pointerInfo.ButtonChangeType = POINTER_CHANGE_FIRSTBUTTON_UP;
+ event = processor.GenerateEvent(WM_POINTERUP, 0, pen_info, point);
+ ASSERT_TRUE(event);
+ ASSERT_TRUE(event->IsTouchEvent());
+ EXPECT_EQ(ui::ET_TOUCH_RELEASED, event->AsTouchEvent()->type());
+
+ pen_info.pointerInfo.ButtonChangeType = POINTER_CHANGE_NONE;
+ event = processor.GenerateEvent(WM_POINTERUPDATE, 0, pen_info, point);
+ ASSERT_TRUE(event);
+ ASSERT_TRUE(event->IsMouseEvent());
+ EXPECT_EQ(ui::ET_MOUSE_MOVED, event->type());
+
+ event = processor.GenerateEvent(WM_POINTERLEAVE, 0, pen_info, point);
+ ASSERT_TRUE(event);
+ ASSERT_TRUE(event->IsMouseEvent());
+ EXPECT_EQ(ui::ET_MOUSE_EXITED, event->AsMouseEvent()->type());
+}
+
+TEST(PenProcessorTest, UnpairedPointerDownTouchDMEnabled) {
+ ui::SequentialIDGenerator id_generator(0);
+ PenEventProcessor processor(&id_generator,
+ /*direct_manipulation_enabled*/ true);
+
+ POINTER_PEN_INFO pen_info;
+ memset(&pen_info, 0, sizeof(POINTER_PEN_INFO));
+ gfx::Point point(100, 100);
+
+ pen_info.pointerInfo.pointerFlags =
+ POINTER_FLAG_INCONTACT | POINTER_FLAG_FIRSTBUTTON;
+ pen_info.pointerInfo.ButtonChangeType = POINTER_CHANGE_FIRSTBUTTON_UP;
+
+ std::unique_ptr<ui::Event> event =
+ processor.GenerateEvent(WM_POINTERUP, 0, pen_info, point);
+ EXPECT_EQ(nullptr, event.get());
+}
+
+TEST(PenProcessorTest, UnpairedPointerDownMouseDMEnabled) {
+ ui::SequentialIDGenerator id_generator(0);
+ PenEventProcessor processor(&id_generator,
+ /*direct_manipulation_enabled*/ true);
+
+ POINTER_PEN_INFO pen_info;
+ memset(&pen_info, 0, sizeof(POINTER_PEN_INFO));
+ gfx::Point point(100, 100);
+
+ pen_info.pointerInfo.pointerFlags = POINTER_FLAG_FIRSTBUTTON;
+ pen_info.pointerInfo.ButtonChangeType = POINTER_CHANGE_FIRSTBUTTON_UP;
+
+ std::unique_ptr<ui::Event> event =
+ processor.GenerateEvent(WM_POINTERUP, 0, pen_info, point);
+ EXPECT_EQ(nullptr, event.get());
+}
+
+} // namespace views
diff --git a/chromium/ui/views/win/windows_session_change_observer.cc b/chromium/ui/views/win/windows_session_change_observer.cc
index d3663e5cc22..e2021dbcdc3 100644
--- a/chromium/ui/views/win/windows_session_change_observer.cc
+++ b/chromium/ui/views/win/windows_session_change_observer.cc
@@ -13,10 +13,9 @@
#include "base/callback.h"
#include "base/location.h"
#include "base/macros.h"
-#include "base/memory/ref_counted.h"
#include "base/memory/singleton.h"
#include "base/observer_list.h"
-#include "base/task_runner.h"
+#include "base/task_scheduler/post_task.h"
#include "ui/gfx/win/singleton_hwnd.h"
#include "ui/gfx/win/singleton_hwnd_observer.h"
#include "ui/views/views_delegate.h"
@@ -67,19 +66,19 @@ class WindowsSessionChangeObserver::WtsRegistrationNotificationManager {
singleton_hwnd_observer_.reset(new gfx::SingletonHwndObserver(
base::Bind(&WtsRegistrationNotificationManager::OnWndProc,
base::Unretained(this))));
- scoped_refptr<base::TaskRunner> task_runner;
- if (ViewsDelegate::GetInstance()) {
- task_runner = ViewsDelegate::GetInstance()->GetBlockingPoolTaskRunner();
- }
- base::Closure wts_register =
- base::Bind(base::IgnoreResult(&WTSRegisterSessionNotification),
- gfx::SingletonHwnd::GetInstance()->hwnd(),
- NOTIFY_FOR_THIS_SESSION);
- if (task_runner) {
- task_runner->PostTask(FROM_HERE, wts_register);
+ base::OnceClosure wts_register = base::BindOnce(
+ base::IgnoreResult(&WTSRegisterSessionNotification),
+ gfx::SingletonHwnd::GetInstance()->hwnd(), NOTIFY_FOR_THIS_SESSION);
+
+ // This should probably always be async but it wasn't async in the absence
+ // of a ViewsDelegate prior to the migration to TaskScheduler and making it
+ // async breaks many unrelated views unittests.
+ if (ViewsDelegate::GetInstance()) {
+ base::CreateCOMSTATaskRunnerWithTraits({})->PostTask(
+ FROM_HERE, std::move(wts_register));
} else {
- wts_register.Run();
+ std::move(wts_register).Run();
}
}
diff --git a/chromium/ui/views/window/custom_frame_view.cc b/chromium/ui/views/window/custom_frame_view.cc
index a2eaafc2fbb..22d0bed6be8 100644
--- a/chromium/ui/views/window/custom_frame_view.cc
+++ b/chromium/ui/views/window/custom_frame_view.cc
@@ -185,9 +185,9 @@ void CustomFrameView::GetWindowMask(const gfx::Size& size,
}
void CustomFrameView::ResetWindowControls() {
- restore_button_->SetState(CustomButton::STATE_NORMAL);
- minimize_button_->SetState(CustomButton::STATE_NORMAL);
- maximize_button_->SetState(CustomButton::STATE_NORMAL);
+ restore_button_->SetState(Button::STATE_NORMAL);
+ minimize_button_->SetState(Button::STATE_NORMAL);
+ maximize_button_->SetState(Button::STATE_NORMAL);
// The close button isn't affected by this constraint.
}
@@ -598,11 +598,11 @@ ImageButton* CustomFrameView::InitWindowCaptionButton(
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
ImageButton* button = new ImageButton(this);
button->SetAccessibleName(l10n_util::GetStringUTF16(accessibility_string_id));
- button->SetImage(CustomButton::STATE_NORMAL,
+ button->SetImage(Button::STATE_NORMAL,
rb.GetImageNamed(normal_image_id).ToImageSkia());
- button->SetImage(CustomButton::STATE_HOVERED,
+ button->SetImage(Button::STATE_HOVERED,
rb.GetImageNamed(hot_image_id).ToImageSkia());
- button->SetImage(CustomButton::STATE_PRESSED,
+ button->SetImage(Button::STATE_PRESSED,
rb.GetImageNamed(pushed_image_id).ToImageSkia());
AddChildView(button);
return button;
diff --git a/chromium/ui/views/window/dialog_client_view.cc b/chromium/ui/views/window/dialog_client_view.cc
index 7d62cadf15e..256ba5dcc0d 100644
--- a/chromium/ui/views/window/dialog_client_view.cc
+++ b/chromium/ui/views/window/dialog_client_view.cc
@@ -12,8 +12,8 @@
#include "ui/views/background.h"
#include "ui/views/border.h"
#include "ui/views/controls/button/blue_button.h"
+#include "ui/views/controls/button/button.h"
#include "ui/views/controls/button/checkbox.h"
-#include "ui/views/controls/button/custom_button.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/button/md_text_button.h"
#include "ui/views/layout/grid_layout.h"
@@ -139,9 +139,11 @@ const DialogClientView* DialogClientView::AsDialogClientView() const {
// DialogClientView, View overrides:
gfx::Size DialogClientView::CalculatePreferredSize() const {
+ gfx::Size contents_size = ClientView::CalculatePreferredSize();
+ const gfx::Insets& content_margins = GetDialogDelegate()->margins();
+ contents_size.Enlarge(content_margins.width(), content_margins.height());
return GetBoundingSizeForVerticalStack(
- ClientView::CalculatePreferredSize(),
- button_row_container_->GetPreferredSize());
+ contents_size, button_row_container_->GetPreferredSize());
}
gfx::Size DialogClientView::GetMinimumSize() const {
@@ -172,8 +174,11 @@ void DialogClientView::Layout() {
button_row_container_->SetSize(
gfx::Size(width(), button_row_container_->GetHeightForWidth(width())));
button_row_container_->SetY(height() - button_row_container_->height());
- if (contents_view())
- contents_view()->SetSize(gfx::Size(width(), button_row_container_->y()));
+ if (contents_view()) {
+ gfx::Rect contents_bounds(width(), button_row_container_->y());
+ contents_bounds.Inset(GetDialogDelegate()->margins());
+ contents_view()->SetBoundsRect(contents_bounds);
+ }
}
bool DialogClientView::AcceleratorPressed(const ui::Accelerator& accelerator) {
@@ -395,7 +400,7 @@ void DialogClientView::SetupLayout() {
// will be in |link[0]|. Skip that if it is not a button, or if it is a
// Checkbox (which extends LabelButton). Otherwise, link everything.
bool skip_first_link =
- views[0] && (!CustomButton::AsCustomButton(views[0]) ||
+ views[0] && (!Button::AsButton(views[0]) ||
views[0]->GetClassName() == Checkbox::kViewClassName);
if (skip_first_link)
column_set->LinkColumnSizes(link[1], link[2], -1);
diff --git a/chromium/ui/views/window/dialog_client_view_unittest.cc b/chromium/ui/views/window/dialog_client_view_unittest.cc
index a143aa95082..4192b0ee039 100644
--- a/chromium/ui/views/window/dialog_client_view_unittest.cc
+++ b/chromium/ui/views/window/dialog_client_view_unittest.cc
@@ -465,4 +465,18 @@ TEST_F(DialogClientViewTest, FocusMultipleButtons) {
EXPECT_TRUE(client_view()->cancel_button()->HasFocus());
}
+// Ensures that the focus persistence works correctly when buttons are removed.
+TEST_F(DialogClientViewTest, FocusChangingButtons) {
+ // Start with ok and cancel buttons.
+ widget()->Show();
+ SetDialogButtons(ui::DIALOG_BUTTON_CANCEL | ui::DIALOG_BUTTON_OK);
+ client_view()->cancel_button()->RequestFocus(); // Set focus.
+ FocusManager* focus_manager = GetFocusManager();
+ EXPECT_EQ(client_view()->cancel_button(), focus_manager->GetFocusedView());
+
+ // Remove buttons.
+ SetDialogButtons(ui::DIALOG_BUTTON_NONE);
+ EXPECT_EQ(nullptr, focus_manager->GetFocusedView());
+}
+
} // namespace views
diff --git a/chromium/ui/views/window/dialog_delegate.cc b/chromium/ui/views/window/dialog_delegate.cc
index 0484d5d06fd..ee398d8077f 100644
--- a/chromium/ui/views/window/dialog_delegate.cc
+++ b/chromium/ui/views/window/dialog_delegate.cc
@@ -31,11 +31,20 @@ namespace views {
////////////////////////////////////////////////////////////////////////////////
// DialogDelegate:
-DialogDelegate::DialogDelegate() : supports_custom_frame_(true) {
+DialogDelegate::DialogDelegate()
+ : supports_custom_frame_(true),
+ // TODO(crbug.com/733040): Most subclasses assume they must set their own
+ // margins explicitly, so we set them to 0 here for now to avoid doubled
+ // margins.
+ margins_(0) {
UMA_HISTOGRAM_BOOLEAN("Dialog.DialogDelegate.Create", true);
+ creation_time_ = base::TimeTicks::Now();
}
-DialogDelegate::~DialogDelegate() {}
+DialogDelegate::~DialogDelegate() {
+ UMA_HISTOGRAM_LONG_TIMES("Dialog.DialogDelegate.Duration",
+ base::TimeTicks::Now() - creation_time_);
+}
// static
Widget* DialogDelegate::CreateDialogWidget(WidgetDelegate* delegate,
diff --git a/chromium/ui/views/window/dialog_delegate.h b/chromium/ui/views/window/dialog_delegate.h
index 8d2205b4462..598e8bae52e 100644
--- a/chromium/ui/views/window/dialog_delegate.h
+++ b/chromium/ui/views/window/dialog_delegate.h
@@ -8,6 +8,7 @@
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/strings/string16.h"
+#include "base/time/time.h"
#include "ui/accessibility/ax_enums.h"
#include "ui/base/models/dialog_model.h"
#include "ui/base/ui_base_types.h"
@@ -111,6 +112,9 @@ class VIEWS_EXPORT DialogDelegate : public ui::DialogModel,
// frame.
virtual bool ShouldUseCustomFrame() const;
+ const gfx::Insets& margins() const { return margins_; }
+ void set_margins(const gfx::Insets& margins) { margins_ = margins; }
+
// A helper for accessing the DialogClientView object contained by this
// delegate's Window.
const DialogClientView* GetDialogClientView() const;
@@ -124,6 +128,14 @@ class VIEWS_EXPORT DialogDelegate : public ui::DialogModel,
// A flag indicating whether this dialog is able to use the custom frame
// style for dialogs.
bool supports_custom_frame_;
+
+ // The margins between the content and the inside of the border.
+ gfx::Insets margins_;
+
+ // The time the dialog is created.
+ base::TimeTicks creation_time_;
+
+ DISALLOW_COPY_AND_ASSIGN(DialogDelegate);
};
// A DialogDelegate implementation that is-a View. Used to override GetWidget()
diff --git a/chromium/ui/views/window/nav_button_provider.h b/chromium/ui/views/window/nav_button_provider.h
new file mode 100644
index 00000000000..499563328f0
--- /dev/null
+++ b/chromium/ui/views/window/nav_button_provider.h
@@ -0,0 +1,54 @@
+// 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_VIEWS_NAV_BUTTON_PROVIDER_H_
+#define UI_VIEWS_NAV_BUTTON_PROVIDER_H_
+
+#include "ui/views/controls/button/button.h"
+
+namespace chrome {
+enum class FrameButtonDisplayType;
+}
+
+namespace gfx {
+class ImageSkia;
+class Insets;
+} // namespace gfx
+
+namespace views {
+
+class NavButtonProvider {
+ public:
+ virtual ~NavButtonProvider() {}
+
+ // Redraws all images and updates all size state. |top_area_height|
+ // is the total available height to render the buttons, and buttons
+ // may be drawn larger when more height is available. |active|
+ // indicates if the window the buttons reside in has activation.
+ virtual void RedrawImages(int top_area_height,
+ bool maximized,
+ bool active) = 0;
+
+ // Gets the cached button image corresponding to |type| and |state|.
+ virtual gfx::ImageSkia GetImage(chrome::FrameButtonDisplayType type,
+ views::Button::ButtonState state) const = 0;
+
+ // Gets the external margin around each button. The left inset
+ // represents the leading margin, and the right inset represents the
+ // trailing margin.
+ virtual gfx::Insets GetNavButtonMargin(
+ chrome::FrameButtonDisplayType type) const = 0;
+
+ // Gets the internal spacing (padding + border) of the top area.
+ // The left inset represents the leading spacing, and the right
+ // inset represents the trailing spacing.
+ virtual gfx::Insets GetTopAreaSpacing() const = 0;
+
+ // Gets the spacing to be used to separate buttons.
+ virtual int GetInterNavButtonSpacing() const = 0;
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_NAV_BUTTON_PROVIDER_H_
diff --git a/chromium/ui/webui/PLATFORM_OWNERS b/chromium/ui/webui/PLATFORM_OWNERS
index 249ebb89100..a4e5de4c6f9 100644
--- a/chromium/ui/webui/PLATFORM_OWNERS
+++ b/chromium/ui/webui/PLATFORM_OWNERS
@@ -1,8 +1,8 @@
# Please use more specific OWNERS when possible.
bauerb@chromium.org
calamity@chromium.org
-dbeam@chromium.org
dpapad@chromium.org
+dschuyler@chromium.org
michaelpg@chromium.org
pam@chromium.org
tommycli@chromium.org
diff --git a/chromium/ui/webui/resources/PRESUBMIT.py b/chromium/ui/webui/resources/PRESUBMIT.py
index 2b24710521a..26bc5ec895e 100644
--- a/chromium/ui/webui/resources/PRESUBMIT.py
+++ b/chromium/ui/webui/resources/PRESUBMIT.py
@@ -28,9 +28,12 @@ def _CheckForTranslations(input_api, output_api):
for f in input_api.AffectedFiles():
local_path = f.LocalPath()
+ # Allow translation in i18n_behavior.js.
if local_path.endswith('i18n_behavior.js'):
continue
-
+ # Allow translation in the cr_components directory.
+ if 'cr_components' in local_path:
+ continue
keywords = None
if local_path.endswith('.js'):
keywords = js_keywords
diff --git a/chromium/ui/webui/resources/cr_components/OWNERS b/chromium/ui/webui/resources/cr_components/OWNERS
new file mode 100644
index 00000000000..ae9d7fbf6f8
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/OWNERS
@@ -0,0 +1,2 @@
+stevenjb@chromium.org
+dpapad@chromium.org
diff --git a/chromium/ui/webui/resources/cr_components/README.md b/chromium/ui/webui/resources/cr_components/README.md
new file mode 100644
index 00000000000..a4ea0138a7d
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/README.md
@@ -0,0 +1,12 @@
+This directory contains complex Polymer web components for Web UI. They may be
+shared between Settings, login, stand alone dialogs, etc.
+
+These components are allowed to use I18nBehavior. The Web UI hosting these
+components is expected to provide loadTimeData with any necessary strings.
+TODO(stevenjb/dschuyler): Add support for i18n{} substitution.
+
+These components may also use chrome and extension APIs, e.g. chrome.send
+(through a browser proxy) or chrome.settingsPrivate. The C++ code hosting the
+component is expected to handle these calls.
+
+For simpler components with no I18n or chrome dependencies, see cr_elements.
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/ca_trust_edit_dialog.html b/chromium/ui/webui/resources/cr_components/certificate_manager/ca_trust_edit_dialog.html
new file mode 100644
index 00000000000..82be73ab885
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/ca_trust_edit_dialog.html
@@ -0,0 +1,57 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
+<link rel="import" href="chrome://resources/cr_elements/paper_button_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/paper_checkbox_style_css.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">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-checkbox/paper-checkbox.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-spinner/paper-spinner.html">
+<link rel="import" href="certificate_shared_css.html">
+<link rel="import" href="certificates_browser_proxy.html">
+
+<dom-module id="ca-trust-edit-dialog">
+ <template>
+ <style include="certificate-shared paper-button-style paper-checkbox-style">
+ paper-checkbox {
+ display: block;
+ }
+
+ paper-checkbox,
+ #description {
+ margin: 15px 0;
+ }
+ </style>
+
+ <dialog is="cr-dialog" id="dialog" close-text="[[i18n('close')]]">
+ <div slot="title">
+ [[i18n('certificateManagerCaTrustEditDialogTitle')]]
+ </div>
+ <div slot="body">
+ <div>[[explanationText_]]</div>
+ <div id="description">
+ [[i18n('certificateManagerCaTrustEditDialogDescription')]]
+ </div>
+ <paper-checkbox id="ssl" checked="[[trustInfo_.ssl]]">
+ [[i18n('certificateManagerCaTrustEditDialogSsl')]]
+ </paper-checkbox>
+ <paper-checkbox id="email" checked="[[trustInfo_.email]]">
+ [[i18n('certificateManagerCaTrustEditDialogEmail')]]
+ </paper-checkbox>
+ <paper-checkbox id="objSign" checked="[[trustInfo_.objSign]]">
+ [[i18n('certificateManagerCaTrustEditDialogObjSign')]]
+ </paper-checkbox>
+ </div>
+ <div slot="button-container">
+ <paper-spinner id="spinner"></paper-spinner>
+ <paper-button class="cancel-button" on-tap="onCancelTap_">
+ [[i18n('cancel')]]
+ </paper-button>
+ <paper-button id="ok" class="action-button" on-tap="onOkTap_">
+ [[i18n('ok')]]
+ </paper-button>
+ </div>
+ </dialog>
+ </template>
+ <script src="ca_trust_edit_dialog.js"></script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/ca_trust_edit_dialog.js b/chromium/ui/webui/resources/cr_components/certificate_manager/ca_trust_edit_dialog.js
new file mode 100644
index 00000000000..c33d5558efa
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/ca_trust_edit_dialog.js
@@ -0,0 +1,80 @@
+// 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 'ca-trust-edit-dialog' allows the user to:
+ * - specify the trust level of a certificate authority that is being
+ * imported.
+ * - edit the trust level of an already existing certificate authority.
+ */
+Polymer({
+ is: 'ca-trust-edit-dialog',
+
+ behaviors: [I18nBehavior],
+
+ properties: {
+ /** @type {!CertificateSubnode|!NewCertificateSubNode} */
+ model: Object,
+
+ /** @private {?CaTrustInfo} */
+ trustInfo_: Object,
+
+ /** @private {string} */
+ explanationText_: String,
+ },
+
+ /** @private {?certificate_manager.CertificatesBrowserProxy} */
+ browserProxy_: null,
+
+ /** @override */
+ ready: function() {
+ this.browserProxy_ =
+ certificate_manager.CertificatesBrowserProxyImpl.getInstance();
+ },
+
+ /** @override */
+ attached: function() {
+ this.explanationText_ = loadTimeData.getStringF(
+ 'certificateManagerCaTrustEditDialogExplanation', this.model.name);
+
+ // A non existing |model.id| indicates that a new certificate is being
+ // imported, otherwise an existing certificate is being edited.
+ if (this.model.id) {
+ this.browserProxy_.getCaCertificateTrust(this.model.id)
+ .then(trustInfo => {
+ this.trustInfo_ = trustInfo;
+ this.$.dialog.showModal();
+ });
+ } else {
+ /** @type {!CrDialogElement} */ (this.$.dialog).showModal();
+ }
+ },
+
+ /** @private */
+ onCancelTap_: function() {
+ /** @type {!CrDialogElement} */ (this.$.dialog).close();
+ },
+
+ /** @private */
+ onOkTap_: function() {
+ this.$.spinner.active = true;
+
+ var whenDone = this.model.id ?
+ this.browserProxy_.editCaCertificateTrust(
+ this.model.id, this.$.ssl.checked, this.$.email.checked,
+ this.$.objSign.checked) :
+ this.browserProxy_.importCaCertificateTrustSelected(
+ this.$.ssl.checked, this.$.email.checked, this.$.objSign.checked);
+
+ whenDone.then(
+ () => {
+ this.$.spinner.active = false;
+ /** @type {!CrDialogElement} */ (this.$.dialog).close();
+ },
+ error => {
+ /** @type {!CrDialogElement} */ (this.$.dialog).close();
+ this.fire('certificates-error', {error: error, anchor: null});
+ });
+ },
+});
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_delete_confirmation_dialog.html b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_delete_confirmation_dialog.html
new file mode 100644
index 00000000000..fbf253c3a5d
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_delete_confirmation_dialog.html
@@ -0,0 +1,30 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.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">
+<link rel="import" href="certificate_shared_css.html">
+<link rel="import" href="certificates_browser_proxy.html">
+
+<dom-module id="certificate-delete-confirmation-dialog">
+ <template>
+ <style include="certificate-shared"></style>
+ <dialog is="cr-dialog" id="dialog" close-text="[[i18n('close')]]">
+ <div slot="title">
+ [[getTitleText_(model, certificateType)]]
+ </div>
+ <div slot="body">
+ <div>[[getDescriptionText_(model, certificateType)]]</div>
+ </div>
+ <div slot="button-container">
+ <paper-button class="cancel-button" on-tap="onCancelTap_">
+ [[i18n('cancel')]]
+ </paper-button>
+ <paper-button id="ok" class="action-button" on-tap="onOkTap_">
+ [[i18n('ok')]]
+ </paper-button>
+ </div>
+ </dialog>
+ </template>
+ <script src="certificate_delete_confirmation_dialog.js"></script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_delete_confirmation_dialog.js b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_delete_confirmation_dialog.js
new file mode 100644
index 00000000000..f914b0865ad
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_delete_confirmation_dialog.js
@@ -0,0 +1,97 @@
+// 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 A confirmation dialog allowing the user to delete various types
+ * of certificates.
+ */
+Polymer({
+ is: 'certificate-delete-confirmation-dialog',
+
+ behaviors: [I18nBehavior],
+
+ properties: {
+ /** @type {!CertificateSubnode} */
+ model: Object,
+
+ /** @type {!CertificateType} */
+ certificateType: String,
+ },
+
+ /** @private {?certificate_manager.CertificatesBrowserProxy} */
+ browserProxy_: null,
+
+ /** @override */
+ ready: function() {
+ this.browserProxy_ =
+ certificate_manager.CertificatesBrowserProxyImpl.getInstance();
+ },
+
+ /** @override */
+ attached: function() {
+ /** @type {!CrDialogElement} */ (this.$.dialog).showModal();
+ },
+
+ /**
+ * @private
+ * @return {string}
+ */
+ getTitleText_: function() {
+ /**
+ * @param {string} localizedMessageId
+ * @return {string}
+ */
+ var getString = localizedMessageId =>
+ loadTimeData.getStringF(localizedMessageId, this.model.name);
+
+ switch (this.certificateType) {
+ case CertificateType.PERSONAL:
+ return getString('certificateManagerDeleteUserTitle');
+ case CertificateType.SERVER:
+ return getString('certificateManagerDeleteServerTitle');
+ case CertificateType.CA:
+ return getString('certificateManagerDeleteCaTitle');
+ case CertificateType.OTHER:
+ return getString('certificateManagerDeleteOtherTitle');
+ }
+ assertNotReached();
+ },
+
+ /**
+ * @private
+ * @return {string}
+ */
+ getDescriptionText_: function() {
+ var getString = loadTimeData.getString.bind(loadTimeData);
+ switch (this.certificateType) {
+ case CertificateType.PERSONAL:
+ return getString('certificateManagerDeleteUserDescription');
+ case CertificateType.SERVER:
+ return getString('certificateManagerDeleteServerDescription');
+ case CertificateType.CA:
+ return getString('certificateManagerDeleteCaDescription');
+ case CertificateType.OTHER:
+ return '';
+ }
+ assertNotReached();
+ },
+
+ /** @private */
+ onCancelTap_: function() {
+ /** @type {!CrDialogElement} */ (this.$.dialog).close();
+ },
+
+ /** @private */
+ onOkTap_: function() {
+ this.browserProxy_.deleteCertificate(this.model.id)
+ .then(
+ () => {
+ /** @type {!CrDialogElement} */ (this.$.dialog).close();
+ },
+ error => {
+ /** @type {!CrDialogElement} */ (this.$.dialog).close();
+ this.fire('certificates-error', {error: error, anchor: null});
+ });
+ },
+});
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_entry.html b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_entry.html
new file mode 100644
index 00000000000..8dcb44091d0
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_entry.html
@@ -0,0 +1,39 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/cr_expand_button/cr_expand_button.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
+<link rel="import" href="certificate_shared_css.html">
+<link rel="import" href="certificate_subentry.html">
+<link rel="import" href="certificates_browser_proxy.html">
+
+<dom-module id="certificate-entry">
+ <template>
+ <style include="certificate-shared iron-flex">
+ .expand-box {
+ align-items: center;
+ border-top: var(--cr-separator-line);
+ display: flex;
+ min-height: 48px;
+ padding: 0 20px;
+ }
+ </style>
+ <div class="expand-box">
+ <div class="flex">[[model.id]]</div>
+ <cr-expand-button expanded="{{expanded_}}"
+ alt="[[i18n('certificateManagerExpandA11yLabel')]]">
+ </cr-expand-button>
+ </div>
+ <template is="dom-if" if="[[expanded_]]">
+ <div class="list-frame">
+ <template is="dom-repeat" items="[[model.subnodes]]">
+ <certificate-subentry model="[[item]]"
+ certificate-type="[[certificateType]]"
+ is-last$="[[isLast_(index, model)]]">
+ </certificate-subentry>
+ </template>
+ </div>
+ </template>
+ </template>
+ <script src="certificate_entry.js"></script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_entry.js b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_entry.js
new file mode 100644
index 00000000000..bcd900e48c1
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_entry.js
@@ -0,0 +1,29 @@
+// 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 An element that represents an SSL certificate entry.
+ */
+Polymer({
+ is: 'certificate-entry',
+
+ behaviors: [I18nBehavior],
+
+ properties: {
+ /** @type {!Certificate} */
+ model: Object,
+
+ /** @type {!CertificateType} */
+ certificateType: String,
+ },
+
+ /**
+ * @param {number} index
+ * @return {boolean} Whether the given index corresponds to the last sub-node.
+ * @private
+ */
+ isLast_: function(index) {
+ return index == this.model.subnodes.length - 1;
+ },
+});
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_list.html b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_list.html
new file mode 100644
index 00000000000..55396b5f371
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_list.html
@@ -0,0 +1,41 @@
+<link rel="import" href="chrome://resources/html/polymer.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/iron-flex-layout/iron-flex-layout-classes.html">
+<link rel="import" href="certificate_entry.html">
+<link rel="import" href="certificate_manager_types.html">
+<link rel="import" href="certificate_shared_css.html">
+<link rel="import" href="certificates_browser_proxy.html">
+
+<dom-module id="certificate-list">
+ <template>
+ <style include="certificate-shared iron-flex">
+ .button-box {
+ align-items: center;
+ display: flex;
+ margin-bottom: 24px;
+ min-height: 48px;
+ padding: 0 20px;
+ }
+ </style>
+ <div class="button-box">
+ <span class="flex">
+ [[getDescription_(certificateType, certificates)]]</span>
+ <paper-button id="import" on-tap="onImportTap_"
+ hidden="[[!canImport_(certificateType)]]">
+ [[i18n('certificateManagerImport')]]</paper-button>
+<if expr="chromeos">
+ <paper-button id="importAndBind" on-tap="onImportAndBindTap_"
+ hidden="[[!canImportAndBind_(certificateType, isGuest_)]]">
+ [[i18n('certificateManagerImportAndBind')]]</paper-button>
+</if>
+ </div>
+ <template is="dom-repeat" items="[[certificates]]">
+ <certificate-entry model="[[item]]"
+ certificate-type="[[certificateType]]">
+ </certificate-entry>
+ </template>
+ </template>
+ <script src="certificate_list.js"></script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_list.js b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_list.js
new file mode 100644
index 00000000000..d24361fdeee
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_list.js
@@ -0,0 +1,158 @@
+// 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 'certificate-list' is an element that displays a list of
+ * certificates.
+ */
+Polymer({
+ is: 'certificate-list',
+
+ properties: {
+ /** @type {!Array<!Certificate>} */
+ certificates: {
+ type: Array,
+ value: function() {
+ return [];
+ },
+ },
+
+ /** @type {!CertificateType} */
+ certificateType: String,
+
+ // 'if expr="chromeos"' here is breaking vulcanize. TODO(stevenjb/dpapad):
+ // Restore after migrating to polymer-bundler, crbug.com/731881.
+ /** @private */
+ isGuest_: {
+ type: Boolean,
+ value: function() {
+ return loadTimeData.valueExists('isGuest') &&
+ loadTimeData.getBoolean('isGuest');
+ },
+ },
+ },
+
+ behaviors: [I18nBehavior],
+
+ /**
+ * @return {string}
+ * @private
+ */
+ getDescription_: function() {
+ if (this.certificates.length == 0)
+ return this.i18n('certificateManagerNoCertificates');
+
+ switch (this.certificateType) {
+ case CertificateType.PERSONAL:
+ return this.i18n('certificateManagerYourCertificatesDescription');
+ case CertificateType.SERVER:
+ return this.i18n('certificateManagerServersDescription');
+ case CertificateType.CA:
+ return this.i18n('certificateManagerAuthoritiesDescription');
+ case CertificateType.OTHER:
+ return this.i18n('certificateManagerOthersDescription');
+ }
+
+ assertNotReached();
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ canImport_: function() {
+ return this.certificateType != CertificateType.OTHER;
+ },
+
+ // <if expr="chromeos">
+ /**
+ * @return {boolean}
+ * @private
+ */
+ canImportAndBind_: function() {
+ return !this.isGuest_ && this.certificateType == CertificateType.PERSONAL;
+ },
+ // </if>
+
+ /**
+ * Handles a rejected Promise returned from |browserProxy_|.
+ * @param {!HTMLElement} anchor
+ * @param {*} error Expects {!CertificatesError|!CertificatesImportError}.
+ * @private
+ */
+ onRejected_: function(anchor, error) {
+ if (error === null) {
+ // Nothing to do here. Null indicates that the user clicked "cancel" on
+ // a native file chooser dialog.
+ return;
+ }
+
+ // Otherwise propagate the error to the parents, such that a dialog
+ // displaying the error will be shown.
+ this.fire('certificates-error', {error: error, anchor: anchor});
+ },
+
+
+ /**
+ * @param {?NewCertificateSubNode} subnode
+ * @param {!HTMLElement} anchor
+ * @private
+ */
+ dispatchImportActionEvent_: function(subnode, anchor) {
+ this.fire(
+ CertificateActionEvent,
+ /** @type {!CertificateActionEventDetail} */ ({
+ action: CertificateAction.IMPORT,
+ subnode: subnode,
+ certificateType: this.certificateType,
+ anchor: anchor,
+ }));
+ },
+
+ /**
+ * @param {!Event} e
+ * @private
+ */
+ onImportTap_: function(e) {
+ this.handleImport_(
+ false, /** @type {!HTMLElement} */ (Polymer.dom(e).localTarget));
+ },
+
+ // <if expr="chromeos">
+ /**
+ * @private
+ * @param {!Event} e
+ */
+ onImportAndBindTap_: function(e) {
+ this.handleImport_(
+ true, /** @type {!HTMLElement} */ (Polymer.dom(e).localTarget));
+ },
+ // </if>
+
+ /**
+ * @param {boolean} useHardwareBacked
+ * @param {!HTMLElement} anchor
+ * @private
+ */
+ handleImport_: function(useHardwareBacked, anchor) {
+ var browserProxy =
+ certificate_manager.CertificatesBrowserProxyImpl.getInstance();
+ if (this.certificateType == CertificateType.PERSONAL) {
+ browserProxy.importPersonalCertificate(useHardwareBacked)
+ .then(showPasswordPrompt => {
+ if (showPasswordPrompt)
+ this.dispatchImportActionEvent_(null, anchor);
+ }, this.onRejected_.bind(this, anchor));
+ } else if (this.certificateType == CertificateType.CA) {
+ browserProxy.importCaCertificate().then(certificateName => {
+ this.dispatchImportActionEvent_({name: certificateName}, anchor);
+ }, this.onRejected_.bind(this, anchor));
+ } else if (this.certificateType == CertificateType.SERVER) {
+ browserProxy.importServerCertificate().catch(
+ this.onRejected_.bind(this, anchor));
+ } else {
+ assertNotReached();
+ }
+ },
+});
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_manager.html b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_manager.html
new file mode 100644
index 00000000000..9c9ebcb86c3
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_manager.html
@@ -0,0 +1,106 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/html/assert.html">
+<link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.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-pages/iron-pages.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-tabs/paper-tabs.html">
+<link rel="import" href="ca_trust_edit_dialog.html">
+<link rel="import" href="certificate_delete_confirmation_dialog.html">
+<link rel="import" href="certificate_list.html">
+<link rel="import" href="certificate_manager_types.html">
+<link rel="import" href="certificate_password_decryption_dialog.html">
+<link rel="import" href="certificate_password_encryption_dialog.html">
+<link rel="import" href="certificates_browser_proxy.html">
+<link rel="import" href="certificates_error_dialog.html">
+
+<dom-module id="certificate-manager">
+ <template>
+ <style>
+ :host {
+ --paper-tabs-selection-bar-color: var(--paper-blue-500);
+ }
+
+ paper-tabs {
+ font-size: inherit;
+ height: 40px;
+ margin-bottom: 24px;
+ }
+
+ paper-tab {
+ --paper-tab-content: {
+ color: var(--paper-grey-800);
+ };
+ --paper-tab-content-unselected: {
+ color: var(--paper-grey-600);
+ };
+ text-transform: uppercase;
+ }
+ </style>
+
+ <template is="dom-if" if="[[showCaTrustEditDialog_]]" restamp>
+ <ca-trust-edit-dialog model="[[dialogModel_]]">
+ </ca-trust-edit-dialog>
+ </template>
+ <template is="dom-if" if="[[showDeleteConfirmationDialog_]]" restamp>
+ <certificate-delete-confirmation-dialog
+ model="[[dialogModel_]]"
+ certificate-type="[[dialogModelCertificateType_]]">
+ </certificate-delete-confirmation-dialog>
+ </template>
+ <template is="dom-if" if="[[showPasswordEncryptionDialog_]]" restamp>
+ <certificate-password-encryption-dialog
+ model="[[dialogModel_]]">
+ </certificate-password-encryption-dialog>
+ </template>
+ <template is="dom-if" if="[[showPasswordDecryptionDialog_]]" restamp>
+ <certificate-password-decryption-dialog>
+ </certificate-password-decryption-dialog>
+ </template>
+ <template is="dom-if" if="[[showErrorDialog_]]" restamp>
+ <certificates-error-dialog model="[[errorDialogModel_]]">
+ </certificates-error-dialog>
+ </template>
+
+ <paper-tabs noink selected="{{selected}}">
+ <paper-tab>[[i18n('certificateManagerYourCertificates')]]</paper-tab>
+ <paper-tab>[[i18n('certificateManagerServers')]]</paper-tab>
+ <paper-tab>[[i18n('certificateManagerAuthorities')]]</paper-tab>
+ <paper-tab>[[i18n('certificateManagerOthers')]]</paper-tab>
+ </paper-tabs>
+ <iron-pages selected="[[selected]]">
+ <div>
+ <certificate-list id="personalCerts"
+ certificates="[[personalCerts]]"
+ certificate-type="[[certificateTypeEnum_.PERSONAL]]">
+ </certificate-list>
+ </div>
+ <div>
+ <template is="dom-if" if="[[isTabSelected_(selected, 1)]]">
+ <certificate-list id="serverCerts"
+ certificates="[[serverCerts]]"
+ certificate-type="[[certificateTypeEnum_.SERVER]]">
+ </certificate-list>
+ </template>
+ </div>
+ <div>
+ <template is="dom-if" if="[[isTabSelected_(selected, 2)]]">
+ <certificate-list id="caCerts"
+ certificates="[[caCerts]]"
+ certificate-type="[[certificateTypeEnum_.CA]]">
+ </certificate-list>
+ </template>
+ </div>
+ <div>
+ <template is="dom-if" if="[[isTabSelected_(selected, 3)]]">
+ <certificate-list id="otherCerts"
+ certificates="[[otherCerts]]"
+ certificate-type="[[certificateTypeEnum_.OTHER]]">
+ </certificate-list>
+ </template>
+ </div>
+ </iron-pages>
+ </template>
+ <script src="certificate_manager.js"></script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_manager.js b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_manager.js
new file mode 100644
index 00000000000..0b1049d56df
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_manager.js
@@ -0,0 +1,189 @@
+// 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.
+
+/**
+ * @fileoverview The 'certificate-manager' component manages SSL certificates.
+ */
+Polymer({
+ is: 'certificate-manager',
+
+ behaviors: [I18nBehavior, WebUIListenerBehavior],
+
+ properties: {
+ /** @type {number} */
+ selected: {
+ type: Number,
+ value: 0,
+ },
+
+ /** @type {!Array<!Certificate>} */
+ personalCerts: {
+ type: Array,
+ value: function() {
+ return [];
+ },
+ },
+
+ /** @type {!Array<!Certificate>} */
+ serverCerts: {
+ type: Array,
+ value: function() {
+ return [];
+ },
+ },
+
+ /** @type {!Array<!Certificate>} */
+ caCerts: {
+ type: Array,
+ value: function() {
+ return [];
+ },
+ },
+
+ /** @type {!Array<!Certificate>} */
+ otherCerts: {
+ type: Array,
+ value: function() {
+ return [];
+ },
+ },
+
+ /** @private */
+ certificateTypeEnum_: {
+ type: Object,
+ value: CertificateType,
+ readOnly: true,
+ },
+
+ /** @private */
+ showCaTrustEditDialog_: Boolean,
+
+ /** @private */
+ showDeleteConfirmationDialog_: Boolean,
+
+ /** @private */
+ showPasswordEncryptionDialog_: Boolean,
+
+ /** @private */
+ showPasswordDecryptionDialog_: Boolean,
+
+ /** @private */
+ showErrorDialog_: Boolean,
+
+ /**
+ * The model to be passed to dialogs that refer to a given certificate.
+ * @private {?CertificateSubnode}
+ */
+ dialogModel_: Object,
+
+ /**
+ * The certificate type to be passed to dialogs that refer to a given
+ * certificate.
+ * @private {?CertificateType}
+ */
+ dialogModelCertificateType_: String,
+
+ /**
+ * The model to be passed to the error dialog.
+ * @private {null|!CertificatesError|!CertificatesImportError}
+ */
+ errorDialogModel_: Object,
+
+ /**
+ * The element to return focus to, when the currently shown dialog is
+ * closed.
+ * @private {?HTMLElement}
+ */
+ activeDialogAnchor_: Object,
+ },
+
+ /** @override */
+ attached: function() {
+ this.addWebUIListener('certificates-changed', this.set.bind(this));
+ certificate_manager.CertificatesBrowserProxyImpl.getInstance()
+ .refreshCertificates();
+ },
+
+ /**
+ * @param {number} selectedIndex
+ * @param {number} tabIndex
+ * @return {boolean} Whether to show tab at |tabIndex|.
+ * @private
+ */
+ isTabSelected_: function(selectedIndex, tabIndex) {
+ return selectedIndex == tabIndex;
+ },
+
+ /** @override */
+ ready: function() {
+ this.addEventListener(CertificateActionEvent, event => {
+ this.dialogModel_ = event.detail.subnode;
+ this.dialogModelCertificateType_ = event.detail.certificateType;
+
+ if (event.detail.action == CertificateAction.IMPORT) {
+ if (event.detail.certificateType == CertificateType.PERSONAL) {
+ this.openDialog_(
+ 'certificate-password-decryption-dialog',
+ 'showPasswordDecryptionDialog_', event.detail.anchor);
+ } else if (event.detail.certificateType == CertificateType.CA) {
+ this.openDialog_(
+ 'ca-trust-edit-dialog', 'showCaTrustEditDialog_',
+ event.detail.anchor);
+ }
+ } else {
+ if (event.detail.action == CertificateAction.EDIT) {
+ this.openDialog_(
+ 'ca-trust-edit-dialog', 'showCaTrustEditDialog_',
+ event.detail.anchor);
+ } else if (event.detail.action == CertificateAction.DELETE) {
+ this.openDialog_(
+ 'certificate-delete-confirmation-dialog',
+ 'showDeleteConfirmationDialog_', event.detail.anchor);
+ } else if (event.detail.action == CertificateAction.EXPORT_PERSONAL) {
+ this.openDialog_(
+ 'certificate-password-encryption-dialog',
+ 'showPasswordEncryptionDialog_', event.detail.anchor);
+ }
+ }
+
+ event.stopPropagation();
+ });
+
+ this.addEventListener('certificates-error', event => {
+ var detail = /** @type {!CertificatesErrorEventDetail} */ (event.detail);
+ this.errorDialogModel_ = detail.error;
+ this.openDialog_(
+ 'certificates-error-dialog', 'showErrorDialog_', detail.anchor);
+ event.stopPropagation();
+ });
+ },
+
+ /**
+ * Opens a dialog and registers a listener for removing the dialog from the
+ * DOM once is closed. The listener is destroyed when the dialog is removed
+ * (because of 'restamp').
+ *
+ * @param {string} dialogTagName The tag name of the dialog to be shown.
+ * @param {string} domIfBooleanName The name of the boolean variable
+ * corresponding to the dialog.
+ * @param {?HTMLElement} anchor The element to focus when the dialog is
+ * closed. If null, the previous anchor element should be reused. This
+ * happens when a 'certificates-error-dialog' is opened, which when closed
+ * should focus the anchor of the previous dialog (the one that generated
+ * the error).
+ * @private
+ */
+ openDialog_: function(dialogTagName, domIfBooleanName, anchor) {
+ if (anchor)
+ this.activeDialogAnchor_ = anchor;
+ this.set(domIfBooleanName, true);
+ this.async(() => {
+ var dialog = this.$$(dialogTagName);
+ dialog.addEventListener('close', () => {
+ this.set(domIfBooleanName, false);
+ cr.ui.focusWithoutInk(assert(this.activeDialogAnchor_));
+ });
+ });
+ },
+});
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_manager_types.html b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_manager_types.html
new file mode 100644
index 00000000000..271b2666939
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_manager_types.html
@@ -0,0 +1 @@
+<script src="certificate_manager_types.js"></script>
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_manager_types.js b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_manager_types.js
new file mode 100644
index 00000000000..76d448770cf
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_manager_types.js
@@ -0,0 +1,44 @@
+// 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 Closure compiler typedefs.
+ */
+
+/**
+ * The payload of the 'certificate-action' event.
+ * @typedef {{
+ * action: !CertificateAction,
+ * subnode: (null|CertificateSubnode|NewCertificateSubNode),
+ * certificateType: !CertificateType,
+ * anchor: !HTMLElement
+ * }}
+ */
+var CertificateActionEventDetail;
+
+/**
+ * The payload of the 'certificates-error' event.
+ * @typedef {{
+ * error: (null|CertificatesError|CertificatesImportError),
+ * anchor: ?HTMLElement
+ * }}
+ */
+var CertificatesErrorEventDetail;
+
+/**
+ * Enumeration of actions that require a popup menu to be shown to the user.
+ * @enum {number}
+ */
+var CertificateAction = {
+ DELETE: 0,
+ EDIT: 1,
+ EXPORT_PERSONAL: 2,
+ IMPORT: 3,
+};
+
+/**
+ * The name of the event fired when a certificate action is selected from the
+ * dropdown menu. CertificateActionEventDetail is passed as the event detail.
+ */
+var CertificateActionEvent = 'certificate-action';
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_password_decryption_dialog.html b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_password_decryption_dialog.html
new file mode 100644
index 00000000000..850da130e7f
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_password_decryption_dialog.html
@@ -0,0 +1,34 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.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">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
+<link rel="import" href="certificate_shared_css.html">
+<link rel="import" href="certificates_browser_proxy.html">
+
+<dom-module id="certificate-password-decryption-dialog">
+ <template>
+ <style include="certificate-shared"></style>
+ <dialog is="cr-dialog" id="dialog" close-text="[[i18n('close')]]">
+ <div slot="title">
+ [[i18n('certificateManagerDecryptPasswordTitle')]]
+ </div>
+ <div slot="body">
+ <paper-input type="password" id="password"
+ label="[[i18n('certificateManagerPassword')]]"
+ value="{{password_}}">
+ </paper-input>
+ </div>
+ <div slot="button-container">
+ <paper-button class="cancel-button" on-tap="onCancelTap_">
+ [[i18n('cancel')]]
+ </paper-button>
+ <paper-button id="ok" class="action-button" on-tap="onOkTap_">
+ [[i18n('ok')]]
+ </paper-button>
+ </div>
+ </dialog>
+ </template>
+ <script src="certificate_password_decryption_dialog.js"></script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_password_decryption_dialog.js b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_password_decryption_dialog.js
new file mode 100644
index 00000000000..0e502404c1b
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_password_decryption_dialog.js
@@ -0,0 +1,53 @@
+// 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 A dialog prompting the user for a decryption password such that
+ * a previously exported personal certificate can be imported.
+ */
+Polymer({
+ is: 'certificate-password-decryption-dialog',
+
+ behaviors: [I18nBehavior],
+
+ properties: {
+ /** @private */
+ password_: {
+ type: String,
+ value: '',
+ },
+ },
+
+ /** @private {?certificate_manager.CertificatesBrowserProxy} */
+ browserProxy_: null,
+
+ /** @override */
+ ready: function() {
+ this.browserProxy_ =
+ certificate_manager.CertificatesBrowserProxyImpl.getInstance();
+ },
+
+ /** @override */
+ attached: function() {
+ /** @type {!CrDialogElement} */ (this.$.dialog).showModal();
+ },
+
+ /** @private */
+ onCancelTap_: function() {
+ /** @type {!CrDialogElement} */ (this.$.dialog).close();
+ },
+
+ /** @private */
+ onOkTap_: function() {
+ this.browserProxy_.importPersonalCertificatePasswordSelected(this.password_)
+ .then(
+ () => {
+ /** @type {!CrDialogElement} */ (this.$.dialog).close();
+ },
+ error => {
+ /** @type {!CrDialogElement} */ (this.$.dialog).close();
+ this.fire('certificates-error', {error: error, anchor: null});
+ });
+ },
+});
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_password_encryption_dialog.html b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_password_encryption_dialog.html
new file mode 100644
index 00000000000..f17b2825fef
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_password_encryption_dialog.html
@@ -0,0 +1,44 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.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">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
+<link rel="import" href="certificate_shared_css.html">
+<link rel="import" href="certificates_browser_proxy.html">
+
+<dom-module id="certificate-password-encryption-dialog">
+ <template>
+ <style include="certificate-shared">
+ .password-buttons {
+ margin-bottom: 20px;
+ }
+ </style>
+ <dialog is="cr-dialog" id="dialog" close-text="[[i18n('close')]]">
+ <div slot="title">
+ [[i18n('certificateManagerEncryptPasswordTitle')]]
+ </div>
+ <div slot="body">
+ <div>[[i18n('certificateManagerEncryptPasswordDescription')]]</div>
+ <div class="password-buttons">
+ <paper-input type="password" value="{{password_}}" id="password"
+ label="[[i18n('certificateManagerPassword')]]"
+ on-input="validate_"></paper-input>
+ <paper-input type="password"
+ value="{{confirmPassword_}}" id="confirmPassword"
+ label="[[i18n('certificateManagerConfirmPassword')]]"
+ on-input="validate_"></paper-input>
+ </div>
+ </div>
+ <div slot="button-container">
+ <paper-button class="cancel-button" on-tap="onCancelTap_">
+ [[i18n('cancel')]]
+ </paper-button>
+ <paper-button id="ok" class="action-button" on-tap="onOkTap_" disabled>
+ [[i18n('ok')]]
+ </paper-button>
+ </div>
+ </dialog>
+ </template>
+ <script src="certificate_password_encryption_dialog.js"></script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_password_encryption_dialog.js b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_password_encryption_dialog.js
new file mode 100644
index 00000000000..b605ee7c22a
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_password_encryption_dialog.js
@@ -0,0 +1,69 @@
+// 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 A dialog prompting the user to encrypt a personal certificate
+ * before it is exported to disk.
+ */
+Polymer({
+ is: 'certificate-password-encryption-dialog',
+
+ behaviors: [I18nBehavior],
+
+ properties: {
+ /** @type {!CertificateSubnode} */
+ model: Object,
+
+ /** @private */
+ password_: {
+ type: String,
+ value: '',
+ },
+
+ /** @private */
+ confirmPassword_: {
+ type: String,
+ value: '',
+ },
+ },
+
+ /** @private {?certificate_manager.CertificatesBrowserProxy} */
+ browserProxy_: null,
+
+ /** @override */
+ ready: function() {
+ this.browserProxy_ =
+ certificate_manager.CertificatesBrowserProxyImpl.getInstance();
+ },
+
+ /** @override */
+ attached: function() {
+ /** @type {!CrDialogElement} */ (this.$.dialog).showModal();
+ },
+
+ /** @private */
+ onCancelTap_: function() {
+ /** @type {!CrDialogElement} */ (this.$.dialog).close();
+ },
+
+ /** @private */
+ onOkTap_: function() {
+ this.browserProxy_.exportPersonalCertificatePasswordSelected(this.password_)
+ .then(
+ () => {
+ this.$.dialog.close();
+ },
+ error => {
+ this.$.dialog.close();
+ this.fire('certificates-error', {error: error, anchor: null});
+ });
+ },
+
+ /** @private */
+ validate_: function() {
+ var isValid =
+ this.password_ != '' && this.password_ == this.confirmPassword_;
+ this.$.ok.disabled = !isValid;
+ },
+});
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_shared_css.html b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_shared_css.html
new file mode 100644
index 00000000000..88fbdb2e211
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_shared_css.html
@@ -0,0 +1,35 @@
+<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
+
+<!-- Common styles for certificate elements. -->
+
+<dom-module id="certificate-shared">
+ <template>
+ <style include="cr-shared-style">
+ /* .list-frame and .list-item match the styling in settings_shared_css. */
+ .list-frame {
+ -webkit-padding-end: 20px;
+ -webkit-padding-start: 60px;
+ align-items: center;
+ display: block;
+ }
+
+ .list-item {
+ align-items: center;
+ display: flex;
+ min-height: 48px;
+ }
+
+ .list-item.underbar {
+ border-bottom: var(--cr-separator-line);
+ }
+
+ .list-item.selected {
+ font-weight: 500;
+ }
+
+ .list-item > .start {
+ flex: 1;
+ }
+ </style>
+ </template>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_subentry.html b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_subentry.html
new file mode 100644
index 00000000000..691625fb095
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_subentry.html
@@ -0,0 +1,63 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/cr_action_menu/cr_action_menu.html">
+<link rel="import" href="chrome://resources/cr_elements/cr_lazy_render/cr_lazy_render.html">
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
+<link rel="import" href="certificate_manager_types.html">
+<link rel="import" href="certificate_shared_css.html">
+<link rel="import" href="certificates_browser_proxy.html">
+
+<dom-module id="certificate-subentry">
+ <template>
+ <style include="certificate-shared cr-icons">
+ .name {
+ flex: auto;
+ }
+
+ .untrusted {
+ -webkit-margin-end: 16px;
+ color: var(--paper-red-700);
+ font-weight: 500;
+ text-transform: uppercase;
+ }
+
+ :host([is-last]) .list-item {
+ border-bottom: none;
+ }
+ </style>
+ <div class="list-item underbar">
+ <div class="untrusted" hidden$="[[!model.untrusted]]">
+ [[i18n('certificateManagerUntrusted')]]
+ </div>
+ <div class="name">[[model.name]]</div>
+ <button is="paper-icon-button-light" class="icon-more-vert" id="dots"
+ title="[[i18n('moreActions')]]" on-tap="onDotsTap_"></button>
+ <template is="cr-lazy-render" id="menu">
+ <dialog is="cr-action-menu">
+ <button class="dropdown-item" id="view"
+ on-tap="onViewTap_">
+ [[i18n('certificateManagerView')]]
+ </button>
+ <button class="dropdown-item" id="edit"
+ hidden$="[[!canEdit_(certificateType, model)]]"
+ on-tap="onEditTap_">
+ [[i18n('edit')]]
+ </button>
+ <button class="dropdown-item" id="export"
+ hidden$="[[!canExport_(certificateType, model)]]"
+ on-tap="onExportTap_">
+ [[i18n('certificateManagerExport')]]
+ </button>
+ <button class="dropdown-item" id="delete"
+ hidden$="[[!canDelete_(model)]]"
+ on-tap="onDeleteTap_">
+ [[i18n('certificateManagerDelete')]]
+ </button>
+ </dialog>
+ </template>
+ <div>
+ </template>
+ <script src="certificate_subentry.js"></script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_subentry.js b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_subentry.js
new file mode 100644
index 00000000000..f2bc22e51fc
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/certificate_subentry.js
@@ -0,0 +1,150 @@
+// 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 certificate-subentry represents an SSL certificate sub-entry.
+ */
+
+Polymer({
+ is: 'certificate-subentry',
+
+ behaviors: [I18nBehavior],
+
+ properties: {
+ /** @type {!CertificateSubnode} */
+ model: Object,
+
+ /** @type {!CertificateType} */
+ certificateType: String,
+ },
+
+ /** @private {certificate_manager.CertificatesBrowserProxy} */
+ browserProxy_: null,
+
+ /** @override */
+ created: function() {
+ this.browserProxy_ =
+ certificate_manager.CertificatesBrowserProxyImpl.getInstance();
+ },
+
+ /**
+ * Dispatches an event indicating which certificate action was tapped. It is
+ * used by the parent of this element to display a modal dialog accordingly.
+ * @param {!CertificateAction} action
+ * @private
+ */
+ dispatchCertificateActionEvent_: function(action) {
+ this.fire(
+ CertificateActionEvent,
+ /** @type {!CertificateActionEventDetail} */ ({
+ action: action,
+ subnode: this.model,
+ certificateType: this.certificateType,
+ anchor: this.$.dots,
+ }));
+ },
+
+ /**
+ * Handles the case where a call to the browser resulted in a rejected
+ * promise.
+ * @param {*} error Expects {?CertificatesError}.
+ * @private
+ */
+ onRejected_: function(error) {
+ if (error === null) {
+ // Nothing to do here. Null indicates that the user clicked "cancel" on
+ // the native file chooser dialog.
+ return;
+ }
+
+ // Otherwise propagate the error to the parents, such that a dialog
+ // displaying the error will be shown.
+ this.fire('certificates-error', {error: error, anchor: this.$.dots});
+ },
+
+ /**
+ * @param {!Event} event
+ * @private
+ */
+ onViewTap_: function(event) {
+ this.closePopupMenu_();
+ this.browserProxy_.viewCertificate(this.model.id);
+ },
+
+ /**
+ * @param {!Event} event
+ * @private
+ */
+ onEditTap_: function(event) {
+ this.closePopupMenu_();
+ this.dispatchCertificateActionEvent_(CertificateAction.EDIT);
+ },
+
+ /**
+ * @param {!Event} event
+ * @private
+ */
+ onDeleteTap_: function(event) {
+ this.closePopupMenu_();
+ this.dispatchCertificateActionEvent_(CertificateAction.DELETE);
+ },
+
+ /**
+ * @param {!Event} event
+ * @private
+ */
+ onExportTap_: function(event) {
+ this.closePopupMenu_();
+ if (this.certificateType == CertificateType.PERSONAL) {
+ this.browserProxy_.exportPersonalCertificate(this.model.id).then(() => {
+ this.dispatchCertificateActionEvent_(CertificateAction.EXPORT_PERSONAL);
+ }, this.onRejected_.bind(this));
+ } else {
+ this.browserProxy_.exportCertificate(this.model.id);
+ }
+ },
+
+ /**
+ * @param {!CertificateType} certificateType
+ * @param {!CertificateSubnode} model
+ * @return {boolean} Whether the certificate can be edited.
+ * @private
+ */
+ canEdit_: function(certificateType, model) {
+ return certificateType == CertificateType.CA && !model.policy;
+ },
+
+ /**
+ * @param {!CertificateType} certificateType
+ * @param {!CertificateSubnode} model
+ * @return {boolean} Whether the certificate can be exported.
+ * @private
+ */
+ canExport_: function(certificateType, model) {
+ if (certificateType == CertificateType.PERSONAL) {
+ return model.extractable;
+ }
+ return true;
+ },
+
+ /**
+ * @param {!CertificateSubnode} model
+ * @return {boolean} Whether the certificate can be deleted.
+ * @private
+ */
+ canDelete_: function(model) {
+ return !model.readonly && !model.policy;
+ },
+
+ /** @private */
+ closePopupMenu_: function() {
+ this.$$('dialog[is=cr-action-menu]').close();
+ },
+
+ /** @private */
+ onDotsTap_: function() {
+ var actionMenu = /** @type {!CrActionMenuElement} */ (this.$.menu.get());
+ actionMenu.showAt(this.$.dots);
+ },
+});
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/certificates_browser_proxy.html b/chromium/ui/webui/resources/cr_components/certificate_manager/certificates_browser_proxy.html
new file mode 100644
index 00000000000..0dc7c572ff1
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/certificates_browser_proxy.html
@@ -0,0 +1 @@
+<script src="certificates_browser_proxy.js"></script>
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/certificates_browser_proxy.js b/chromium/ui/webui/resources/cr_components/certificate_manager/certificates_browser_proxy.js
new file mode 100644
index 00000000000..bbf1d73f17a
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/certificates_browser_proxy.js
@@ -0,0 +1,271 @@
+// 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 A helper object used from the "Manage certificates" section
+ * to interact with the browser.
+ */
+
+/**
+ * @typedef {{
+ * extractable: boolean,
+ * id: string,
+ * name: string,
+ * policy: boolean,
+ * readonly: boolean,
+ * untrusted: boolean,
+ * }}
+ * @see chrome/browser/ui/webui/settings/certificates_handler.cc
+ */
+var CertificateSubnode;
+
+/**
+ * A data structure describing a certificate that is currently being imported,
+ * therefore it has no ID yet, but it has a name. Used within JS only.
+ * @typedef {{
+ * name: string,
+ * }}
+ */
+var NewCertificateSubNode;
+
+/**
+ * @typedef {{
+ * id: string,
+ * name: string,
+ * subnodes: !Array<!CertificateSubnode>
+ * }}
+ * @see chrome/browser/ui/webui/settings/certificates_handler.cc
+ */
+var Certificate;
+
+/**
+ * @typedef {{
+ * ssl: boolean,
+ * email: boolean,
+ * objSign: boolean
+ * }}
+ */
+var CaTrustInfo;
+
+/**
+ * Generic error returned from C++ via a Promise reject callback.
+ * @typedef {{
+ * title: string,
+ * description: string
+ * }}
+ * @see chrome/browser/ui/webui/settings/certificates_handler.cc
+ */
+var CertificatesError;
+
+/**
+ * Enumeration of all possible certificate types.
+ * @enum {string}
+ */
+var CertificateType = {
+ CA: 'ca',
+ OTHER: 'other',
+ PERSONAL: 'personal',
+ SERVER: 'server',
+};
+
+
+/**
+ * Error returned from C++ via a Promise reject callback, when some certificates
+ * fail to be imported.
+ * @typedef {{
+ * title: string,
+ * description: string,
+ * certificateErrors: !Array<{name: string, error: string}>
+ * }}
+ * @see chrome/browser/ui/webui/settings/certificates_handler.cc
+ */
+var CertificatesImportError;
+
+cr.define('certificate_manager', function() {
+ /** @interface */
+ class CertificatesBrowserProxy {
+ /**
+ * Triggers 5 events in the following order
+ * 1x 'certificates-model-ready' event.
+ * 4x 'certificates-changed' event, one for each certificate category.
+ */
+ refreshCertificates() {}
+
+ /** @param {string} id */
+ viewCertificate(id) {}
+
+ /** @param {string} id */
+ exportCertificate(id) {}
+
+ /**
+ * @param {string} id
+ * @return {!Promise} A promise resolved when the certificate has been
+ * deleted successfully or rejected with a CertificatesError.
+ */
+ deleteCertificate(id) {}
+
+ /**
+ * @param {string} id
+ * @return {!Promise<!CaTrustInfo>}
+ */
+ getCaCertificateTrust(id) {}
+
+ /**
+ * @param {string} id
+ * @param {boolean} ssl
+ * @param {boolean} email
+ * @param {boolean} objSign
+ * @return {!Promise}
+ */
+ editCaCertificateTrust(id, ssl, email, objSign) {}
+
+ cancelImportExportCertificate() {}
+
+ /**
+ * @param {string} id
+ * @return {!Promise} A promise firing once the user has selected
+ * the export location. A prompt should be shown to asking for a
+ * password to use for encrypting the file. The password should be
+ * passed back via a call to
+ * exportPersonalCertificatePasswordSelected().
+ */
+ exportPersonalCertificate(id) {}
+
+ /**
+ * @param {string} password
+ * @return {!Promise}
+ */
+ exportPersonalCertificatePasswordSelected(password) {}
+
+ /**
+ * @param {boolean} useHardwareBacked
+ * @return {!Promise<boolean>} A promise firing once the user has selected
+ * the file to be imported. If true a password prompt should be shown to
+ * the user, and the password should be passed back via a call to
+ * importPersonalCertificatePasswordSelected().
+ */
+ importPersonalCertificate(useHardwareBacked) {}
+
+ /**
+ * @param {string} password
+ * @return {!Promise}
+ */
+ importPersonalCertificatePasswordSelected(password) {}
+
+ /**
+ * @return {!Promise} A promise firing once the user has selected
+ * the file to be imported, or failing with CertificatesError.
+ * Upon success, a prompt should be shown to the user to specify the
+ * trust levels, and that information should be passed back via a call
+ * to importCaCertificateTrustSelected().
+ */
+ importCaCertificate() {}
+
+ /**
+ * @param {boolean} ssl
+ * @param {boolean} email
+ * @param {boolean} objSign
+ * @return {!Promise} A promise firing once the trust level for the imported
+ * certificate has been successfully set. The promise is rejected if an
+ * error occurred with either a CertificatesError or
+ * CertificatesImportError.
+ */
+ importCaCertificateTrustSelected(ssl, email, objSign) {}
+
+ /**
+ * @return {!Promise} A promise firing once the certificate has been
+ * imported. The promise is rejected if an error occurred, with either
+ * a CertificatesError or CertificatesImportError.
+ */
+ importServerCertificate() {}
+ }
+
+ /**
+ * @implements {certificate_manager.CertificatesBrowserProxy}
+ */
+ class CertificatesBrowserProxyImpl {
+ /** @override */
+ refreshCertificates() {
+ chrome.send('refreshCertificates');
+ }
+
+ /** @override */
+ viewCertificate(id) {
+ chrome.send('viewCertificate', [id]);
+ }
+
+ /** @override */
+ exportCertificate(id) {
+ chrome.send('exportCertificate', [id]);
+ }
+
+ /** @override */
+ deleteCertificate(id) {
+ return cr.sendWithPromise('deleteCertificate', id);
+ }
+
+ /** @override */
+ exportPersonalCertificate(id) {
+ return cr.sendWithPromise('exportPersonalCertificate', id);
+ }
+
+ /** @override */
+ exportPersonalCertificatePasswordSelected(password) {
+ return cr.sendWithPromise(
+ 'exportPersonalCertificatePasswordSelected', password);
+ }
+
+ /** @override */
+ importPersonalCertificate(useHardwareBacked) {
+ return cr.sendWithPromise('importPersonalCertificate', useHardwareBacked);
+ }
+
+ /** @override */
+ importPersonalCertificatePasswordSelected(password) {
+ return cr.sendWithPromise(
+ 'importPersonalCertificatePasswordSelected', password);
+ }
+
+ /** @override */
+ getCaCertificateTrust(id) {
+ return cr.sendWithPromise('getCaCertificateTrust', id);
+ }
+
+ /** @override */
+ editCaCertificateTrust(id, ssl, email, objSign) {
+ return cr.sendWithPromise(
+ 'editCaCertificateTrust', id, ssl, email, objSign);
+ }
+
+ /** @override */
+ importCaCertificateTrustSelected(ssl, email, objSign) {
+ return cr.sendWithPromise(
+ 'importCaCertificateTrustSelected', ssl, email, objSign);
+ }
+
+ /** @override */
+ cancelImportExportCertificate() {
+ chrome.send('cancelImportExportCertificate');
+ }
+
+ /** @override */
+ importCaCertificate() {
+ return cr.sendWithPromise('importCaCertificate');
+ }
+
+ /** @override */
+ importServerCertificate() {
+ return cr.sendWithPromise('importServerCertificate');
+ }
+ }
+
+ // The singleton instance_ is replaced with a test version of this wrapper
+ // during testing.
+ cr.addSingletonGetter(CertificatesBrowserProxyImpl);
+
+ return {
+ CertificatesBrowserProxy: CertificatesBrowserProxy,
+ CertificatesBrowserProxyImpl: CertificatesBrowserProxyImpl,
+ };
+});
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/certificates_error_dialog.html b/chromium/ui/webui/resources/cr_components/certificate_manager/certificates_error_dialog.html
new file mode 100644
index 00000000000..2c0bb746765
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/certificates_error_dialog.html
@@ -0,0 +1,29 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.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">
+<link rel="import" href="certificate_shared_css.html">
+
+<dom-module id="certificates-error-dialog">
+ <template>
+ <style include="certificate-shared"></style>
+ <dialog is="cr-dialog" id="dialog" close-text="[[i18n('close')]]">
+ <div slot="title">[[model.title]]</div>
+ <div slot="body">
+ <div>[[model.description]]</div>
+ <template is="dom-if" if="[[model.certificateErrors]]">
+ <template is="dom-repeat" items="[[model.certificateErrors]]">
+ <div>[[getCertificateErrorText_(item)]]</div>
+ </template>
+ </template>
+ </div>
+ <div slot="button-container">
+ <paper-button id="ok" class="action-button" on-tap="onOkTap_">
+ [[i18n('ok')]]
+ </paper-button>
+ </div>
+ </dialog>
+ </template>
+ <script src="certificates_error_dialog.js"></script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/certificates_error_dialog.js b/chromium/ui/webui/resources/cr_components/certificate_manager/certificates_error_dialog.js
new file mode 100644
index 00000000000..2b3cd779653
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/certificates_error_dialog.js
@@ -0,0 +1,38 @@
+// 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 A dialog for showing SSL certificate related error messages.
+ * The user can only close the dialog, there is no other possible interaction.
+ */
+Polymer({
+ is: 'certificates-error-dialog',
+
+ behaviors: [I18nBehavior],
+
+ properties: {
+ /** @type {!CertificatesError|!CertificatesImportError} */
+ model: Object,
+ },
+
+ /** @override */
+ attached: function() {
+ /** @type {!CrDialogElement} */ (this.$.dialog).showModal();
+ },
+
+ /** @private */
+ onOkTap_: function() {
+ /** @type {!CrDialogElement} */ (this.$.dialog).close();
+ },
+
+ /**
+ * @param {{name: string, error: string}} importError
+ * @return {string}
+ * @private
+ */
+ getCertificateErrorText_: function(importError) {
+ return loadTimeData.getStringF(
+ 'certificateImportErrorFormat', importError.name, importError.error);
+ },
+});
diff --git a/chromium/ui/webui/resources/cr_components/certificate_manager/compiled_resources2.gyp b/chromium/ui/webui/resources/cr_components/certificate_manager/compiled_resources2.gyp
new file mode 100644
index 00000000000..fef217bee75
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/certificate_manager/compiled_resources2.gyp
@@ -0,0 +1,125 @@
+# 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.
+{
+ 'targets': [
+ {
+ 'target_name': 'ca_trust_edit_dialog',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_elements/cr_dialog/compiled_resources2.gyp:cr_dialog',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
+ 'certificate_manager_types',
+ 'certificates_browser_proxy',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'certificate_delete_confirmation_dialog',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_elements/cr_dialog/compiled_resources2.gyp:cr_dialog',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
+ 'certificate_manager_types',
+ 'certificates_browser_proxy',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'certificate_entry',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ 'certificate_manager_types',
+ 'certificates_browser_proxy',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'certificate_list',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ 'certificate_manager_types',
+ 'certificate_subentry',
+ 'certificates_browser_proxy',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'certificate_manager',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:web_ui_listener_behavior',
+ '<(DEPTH)/ui/webui/resources/js/cr/ui/compiled_resources2.gyp:focus_without_ink',
+ 'certificate_list',
+ 'certificate_manager_types',
+ 'certificates_browser_proxy',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'certificate_manager_types',
+ 'dependencies': [
+ 'certificates_browser_proxy',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'certificate_password_decryption_dialog',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_elements/cr_dialog/compiled_resources2.gyp:cr_dialog',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ 'certificate_manager_types',
+ 'certificates_browser_proxy',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'certificate_password_encryption_dialog',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_elements/cr_dialog/compiled_resources2.gyp:cr_dialog',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ 'certificate_manager_types',
+ 'certificates_browser_proxy',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'certificate_subentry',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_elements/cr_action_menu/compiled_resources2.gyp:cr_action_menu',
+ '<(DEPTH)/ui/webui/resources/cr_elements/cr_lazy_render/compiled_resources2.gyp:cr_lazy_render',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ 'certificate_manager_types',
+ 'certificates_browser_proxy',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'certificates_browser_proxy',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'certificates_error_dialog',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_elements/cr_dialog/compiled_resources2.gyp:cr_dialog',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:load_time_data',
+ 'certificate_manager_types',
+ 'certificates_browser_proxy',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ ],
+}
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/bluetooth_dialog.html b/chromium/ui/webui/resources/cr_components/chromeos/bluetooth_dialog.html
new file mode 100644
index 00000000000..a89ba4d5fde
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/bluetooth_dialog.html
@@ -0,0 +1,137 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/cr_dialog/cr_dialog.html">
+<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.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/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-list/iron-list.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
+
+<dom-module id="bluetooth-dialog">
+ <template>
+ <style include="cr-hidden-style iron-flex">
+ #pairing {
+ margin-bottom: 10px;
+ }
+
+ #pairing paper-input {
+ text-align: center;
+ }
+
+ #pinDiv {
+ margin-top: 10px;
+ }
+
+ .dialog-message {
+ margin-bottom: 10px;
+ }
+
+ div.contents {
+ height: 250px;
+ }
+
+ /* .display indicates a displayed pin code or passkey. */
+ span.display {
+ border: 1px solid #ccc;
+ border-radius: 4px;
+ box-shadow: 0 0 0 1px #222;
+ color: #222;
+ font-size: 123.08%; /* 16px / 13px */
+ height: 38px;
+ line-height: 38px;
+ margin: 0 5px;
+ padding: 0 15px;
+ text-align: center;
+ text-shadow: 0 1px 0 rgba(255, 255, 255, 0.5);
+ }
+
+ span.display.next {
+ background: rgb(77, 144, 254);
+ border: 2px solid rgb(77, 144, 254);
+ box-shadow: none;
+ color: #fff;
+ }
+
+ span.display.untyped {
+ border: 1px solid #d4d4d4;
+ box-shadow: 0 0 0 1px #888;
+ color: #666;
+ }
+
+ /* .confirm indicates a confirmation passkey. */
+ span.confirm {
+ color: #999;
+ font-size: 153.85%; /* 20px / 13px */
+ font-weight: 600; /* semibold */
+ margin: 0 20px;
+ }
+ </style>
+ <!-- TODO(stevenjb/dschuyler): Find a solution to support i18n{} here -->
+ <dialog is="cr-dialog" id="dialog" on-cancel="onDialogCanceled_"
+ close-text="[[i18n('close')]]" on-closed="onDialogCanceled_">
+ <div slot="title">[[title]]</div>
+ <div slot="body">
+ <div class="contents layout vertical center center-justified">
+ <template is="dom-if" if="[[!errorMessage_]]">
+ <div id="pairing" class="layout vertical center center-justified">
+ <div class="dialog-message">
+ [[getMessage_(pairingDevice, pairingEvent_)]]
+ </div>
+ <div hidden$="[[!showEnterPincode_(pairingEvent_)]]">
+ <paper-input id="pincode" minlength="1" maxlength="16"
+ type="text" auto-validate value="{{pinOrPass_}}">
+ </paper-input>
+ </div>
+ <div hidden$="[[!showEnterPasskey_(pairingEvent_)]]">
+ <paper-input id="passkey" minlength="6" maxlength="6"
+ type="text" auto-validate value="{{pinOrPass_}}">
+ </paper-input>
+ </div>
+ <div id="pinDiv" class="layout horizontal center center-justified"
+ hidden="[[!showDisplayPassOrPin_(pairingEvent_)]]">
+ <template is="dom-repeat" items="[[digits_]]">
+ <span class$="[[getPinClass_(index, pairingEvent_)]]">
+ [[getPinDigit_(index, pairingEvent_)]]
+ </span>
+ </template>
+ <span class$="[[getPinClass_(-1, pairingEvent_)]]"
+ hidden="[[showAcceptReject_(pairingEvent_)]]">
+ [[i18n('bluetoothEnterKey')]]
+ </span>
+ </div>
+ </div>
+ </template>
+ <template is="dom-if" if="[[errorMessage_]]">
+ <div class="layout vertical center center-justified">
+ <div class="dialog-message">[[errorMessage_]]</div>
+ </div>
+ </template>
+ </div>
+ </div>
+ <div slot="button-container">
+ <template is="dom-if" if="[[!errorMessage_]]">
+ <paper-button hidden$="[[!showAcceptReject_(pairingEvent_)]]"
+ on-tap="onAcceptTap_">[[i18n('bluetoothAccept')]]</paper-button>
+ <paper-button hidden$="[[!showAcceptReject_(pairingEvent_)]]"
+ on-tap="onRejectTap_">[[i18n('bluetoothReject')]]</paper-button>
+ <paper-button hidden$="[[!showConnect_(pairingEvent_)]]"
+ disabled="[[!enableConnect_(pairingEvent_, pinOrPass_)]]"
+ on-tap="onConnectTap_">[[i18n('bluetoothPair')]]</paper-button>
+ <paper-button
+ hidden$="[[!showDismiss_(pairingDevice, pairingEvent_)]]"
+ on-tap="close">[[i18n('ok')]]</paper-button>
+ <paper-button hidden$="[[showDismiss_(pairingDevice, pairingEvent_)]]"
+ on-tap="onCancelTap_">
+ [[i18n('cancel')]]
+ </paper-button>
+ </template>
+ <template is="dom-if" if="[[errorMessage_]]">
+ <paper-button on-tap="close">[[i18n('ok')]]</paper-button>
+ </template>
+ </div>
+ </dialog>
+ </template>
+ <script src="bluetooth_dialog.js"></script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/bluetooth_dialog.js b/chromium/ui/webui/resources/cr_components/chromeos/bluetooth_dialog.js
new file mode 100644
index 00000000000..b061349e266
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/bluetooth_dialog.js
@@ -0,0 +1,459 @@
+// 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
+ * Dialog used for pairing a provided |pairing-device|. Set |show-error| to
+ * show the error results from a pairing event instead of the pairing UI.
+ * NOTE: This module depends on I18nBehavior which depends on loadTimeData.
+ */
+
+var PairingEventType = chrome.bluetoothPrivate.PairingEventType;
+
+Polymer({
+ is: 'bluetooth-dialog',
+
+ behaviors: [I18nBehavior],
+
+ properties: {
+ /**
+ * Interface for bluetooth calls. Set in bluetooth-page.
+ * @type {Bluetooth}
+ * @private
+ */
+ bluetooth: {
+ type: Object,
+ value: chrome.bluetooth,
+ },
+
+ /**
+ * Interface for bluetoothPrivate calls.
+ * @type {BluetoothPrivate}
+ */
+ bluetoothPrivate: {
+ type: Object,
+ value: chrome.bluetoothPrivate,
+ },
+
+ /** Dialog title */
+ title: String,
+
+ /**
+ * Current Pairing device.
+ * @type {!chrome.bluetooth.Device|undefined}
+ */
+ pairingDevice: Object,
+
+ /**
+ * Current Pairing event.
+ * @private {?chrome.bluetoothPrivate.PairingEvent}
+ */
+ pairingEvent_: {
+ type: Object,
+ value: null,
+ },
+
+ /**
+ * May be set by the host to show a pairing error result, or may be
+ * set by the dialog if a pairing or connect error occured.
+ * @private
+ */
+ errorMessage_: String,
+
+ /**
+ * Pincode or passkey value, used to trigger connect enabled changes.
+ * @private
+ */
+ pinOrPass_: String,
+
+ /**
+ * @const {!Array<number>}
+ * @private
+ */
+ digits_: {
+ type: Array,
+ readOnly: true,
+ value: [0, 1, 2, 3, 4, 5],
+ },
+ },
+
+ observers: [
+ 'dialogUpdated_(errorMessage_, pairingEvent_)',
+ 'pairingChanged_(pairingDevice, pairingEvent_)',
+ ],
+
+ /**
+ * Listener for chrome.bluetoothPrivate.onPairing events.
+ * @private {?function(!chrome.bluetoothPrivate.PairingEvent)}
+ */
+ bluetoothPrivateOnPairingListener_: null,
+
+ /**
+ * Listener for chrome.bluetooth.onBluetoothDeviceChanged events.
+ * @private {?function(!chrome.bluetooth.Device)}
+ */
+ bluetoothDeviceChangedListener_: null,
+
+ open: function() {
+ this.startPairing();
+ this.pinOrPass_ = '';
+ this.getDialog_().showModal();
+ this.itemWasFocused_ = false;
+ },
+
+ close: function() {
+ this.endPairing();
+ var dialog = this.getDialog_();
+ if (dialog.open)
+ dialog.close();
+ },
+
+ /**
+ * Updates the dialog after a connect attempt.
+ * @param {!chrome.bluetooth.Device} device The device connected to
+ * @param {!{message: string}} lastError chrome.runtime.lastError
+ * @param {chrome.bluetoothPrivate.ConnectResultType} result The connect
+ * result
+ * @return {boolean}
+ */
+ handleError: function(device, lastError, result) {
+ var error;
+ if (lastError) {
+ error = lastError.message;
+ } else {
+ switch (result) {
+ case chrome.bluetoothPrivate.ConnectResultType.IN_PROGRESS:
+ case chrome.bluetoothPrivate.ConnectResultType.ALREADY_CONNECTED:
+ case chrome.bluetoothPrivate.ConnectResultType.AUTH_CANCELED:
+ case chrome.bluetoothPrivate.ConnectResultType.SUCCESS:
+ this.errorMessage_ = '';
+ return false;
+ default:
+ error = result;
+ }
+ }
+
+ var name = device.name || device.address;
+ var id = 'bluetooth_connect_' + error;
+ if (this.i18nExists(id)) {
+ this.errorMessage_ = this.i18n(id, name);
+ } else {
+ this.errorMessage_ = error;
+ console.error('Unexpected error connecting to: ' + name + ': ' + error);
+ }
+ return true;
+ },
+
+ /** @private */
+ dialogUpdated_: function() {
+ if (this.showEnterPincode_())
+ this.$$('#pincode').focus();
+ else if (this.showEnterPasskey_())
+ this.$$('#passkey').focus();
+ },
+
+ /**
+ * @return {!CrDialogElement}
+ * @private
+ */
+ getDialog_: function() {
+ return /** @type {!CrDialogElement} */ (this.$.dialog);
+ },
+
+ /** @private */
+ onCancelTap_: function() {
+ this.getDialog_().cancel();
+ },
+
+ /** @private */
+ onDialogCanceled_: function() {
+ if (!this.errorMessage_)
+ this.sendResponse_(chrome.bluetoothPrivate.PairingResponse.CANCEL);
+ this.endPairing();
+ },
+
+ /** Called when the dialog is opened. Starts listening for pairing events. */
+ startPairing: function() {
+ if (!this.bluetoothPrivateOnPairingListener_) {
+ this.bluetoothPrivateOnPairingListener_ =
+ this.onBluetoothPrivateOnPairing_.bind(this);
+ this.bluetoothPrivate.onPairing.addListener(
+ this.bluetoothPrivateOnPairingListener_);
+ }
+ if (!this.bluetoothDeviceChangedListener_) {
+ this.bluetoothDeviceChangedListener_ =
+ this.onBluetoothDeviceChanged_.bind(this);
+ this.bluetooth.onDeviceChanged.addListener(
+ this.bluetoothDeviceChangedListener_);
+ }
+ },
+
+ /** Called when the dialog is closed. */
+ endPairing: function() {
+ if (this.bluetoothPrivateOnPairingListener_) {
+ this.bluetoothPrivate.onPairing.removeListener(
+ this.bluetoothPrivateOnPairingListener_);
+ this.bluetoothPrivateOnPairingListener_ = null;
+ }
+ if (this.bluetoothDeviceChangedListener_) {
+ this.bluetooth.onDeviceChanged.removeListener(
+ this.bluetoothDeviceChangedListener_);
+ this.bluetoothDeviceChangedListener_ = null;
+ }
+ this.pairingEvent_ = null;
+ },
+
+ /**
+ * Process bluetoothPrivate.onPairing events.
+ * @param {!chrome.bluetoothPrivate.PairingEvent} event
+ * @private
+ */
+ onBluetoothPrivateOnPairing_: function(event) {
+ if (!this.pairingDevice ||
+ event.device.address != this.pairingDevice.address) {
+ return;
+ }
+ if (event.pairing == PairingEventType.KEYS_ENTERED &&
+ event.passkey === undefined && this.pairingEvent_) {
+ // 'keysEntered' event might not include the updated passkey so preserve
+ // the current one.
+ event.passkey = this.pairingEvent_.passkey;
+ }
+ this.pairingEvent_ = event;
+ },
+
+ /**
+ * Process bluetooth.onDeviceChanged events. This ensures that the dialog
+ * updates when the connection state changes.
+ * @param {!chrome.bluetooth.Device} device
+ * @private
+ */
+ onBluetoothDeviceChanged_: function(device) {
+ if (!this.pairingDevice || device.address != this.pairingDevice.address)
+ return;
+ this.pairingDevice = device;
+ },
+
+ /** @private */
+ pairingChanged_: function() {
+ // Auto-close the dialog when pairing completes.
+ if (this.pairingDevice.paired && !this.pairingDevice.connecting &&
+ this.pairingDevice.connected) {
+ this.close();
+ return;
+ }
+ this.errorMessage_ = '';
+ this.pinOrPass_ = '';
+ },
+
+ /**
+ * @return {string}
+ * @private
+ */
+ getMessage_: function() {
+ var message;
+ if (!this.pairingEvent_)
+ message = 'bluetoothStartConnecting';
+ else
+ message = this.getEventDesc_(this.pairingEvent_.pairing);
+ return this.i18n(message, this.pairingDevice.name);
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ showEnterPincode_: function() {
+ return !!this.pairingEvent_ &&
+ this.pairingEvent_.pairing == PairingEventType.REQUEST_PINCODE;
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ showEnterPasskey_: function() {
+ return !!this.pairingEvent_ &&
+ this.pairingEvent_.pairing == PairingEventType.REQUEST_PASSKEY;
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ showDisplayPassOrPin_: function() {
+ if (!this.pairingEvent_)
+ return false;
+ var pairing = this.pairingEvent_.pairing;
+ return (
+ pairing == PairingEventType.DISPLAY_PINCODE ||
+ pairing == PairingEventType.DISPLAY_PASSKEY ||
+ pairing == PairingEventType.CONFIRM_PASSKEY ||
+ pairing == PairingEventType.KEYS_ENTERED);
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ showAcceptReject_: function() {
+ return !!this.pairingEvent_ &&
+ this.pairingEvent_.pairing == PairingEventType.CONFIRM_PASSKEY;
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ showConnect_: function() {
+ if (!this.pairingEvent_)
+ return false;
+ var pairing = this.pairingEvent_.pairing;
+ return pairing == PairingEventType.REQUEST_PINCODE ||
+ pairing == PairingEventType.REQUEST_PASSKEY;
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ enableConnect_: function() {
+ if (!this.showConnect_())
+ return false;
+ var inputId =
+ (this.pairingEvent_.pairing == PairingEventType.REQUEST_PINCODE) ?
+ '#pincode' :
+ '#passkey';
+ var paperInput = /** @type {!PaperInputElement} */ (this.$$(inputId));
+ assert(paperInput);
+ /** @type {string} */ var value = paperInput.value;
+ return !!value && paperInput.validate();
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ showDismiss_: function() {
+ return this.pairingDevice.paired ||
+ (!!this.pairingEvent_ &&
+ this.pairingEvent_.pairing == PairingEventType.COMPLETE);
+ },
+
+ /** @private */
+ onAcceptTap_: function() {
+ this.sendResponse_(chrome.bluetoothPrivate.PairingResponse.CONFIRM);
+ },
+
+ /** @private */
+ onConnectTap_: function() {
+ this.sendResponse_(chrome.bluetoothPrivate.PairingResponse.CONFIRM);
+ },
+
+ /** @private */
+ onRejectTap_: function() {
+ this.sendResponse_(chrome.bluetoothPrivate.PairingResponse.REJECT);
+ },
+
+ /**
+ * @param {!chrome.bluetoothPrivate.PairingResponse} response
+ * @private
+ */
+ sendResponse_: function(response) {
+ if (!this.pairingDevice)
+ return;
+ var options =
+ /** @type {!chrome.bluetoothPrivate.SetPairingResponseOptions} */ (
+ {device: this.pairingDevice, response: response});
+ if (response == chrome.bluetoothPrivate.PairingResponse.CONFIRM) {
+ var pairing = this.pairingEvent_.pairing;
+ if (pairing == PairingEventType.REQUEST_PINCODE)
+ options.pincode = this.$$('#pincode').value;
+ else if (pairing == PairingEventType.REQUEST_PASSKEY)
+ options.passkey = parseInt(this.$$('#passkey').value, 10);
+ }
+ this.bluetoothPrivate.setPairingResponse(options, () => {
+ if (chrome.runtime.lastError) {
+ // TODO(stevenjb): Show error.
+ console.error(
+ 'Error setting pairing response: ' + options.device.name +
+ ': Response: ' + options.response +
+ ': Error: ' + chrome.runtime.lastError.message);
+ }
+ this.close();
+ });
+
+ this.fire('response', options);
+ },
+
+ /**
+ * @param {!PairingEventType} eventType
+ * @return {string}
+ * @private
+ */
+ getEventDesc_: function(eventType) {
+ assert(eventType);
+ if (eventType == PairingEventType.COMPLETE ||
+ eventType == PairingEventType.KEYS_ENTERED ||
+ eventType == PairingEventType.REQUEST_AUTHORIZATION) {
+ return 'bluetoothStartConnecting';
+ }
+ return 'bluetooth_' + /** @type {string} */ (eventType);
+ },
+
+ /**
+ * @param {number} index
+ * @return {string}
+ * @private
+ */
+ getPinDigit_: function(index) {
+ if (!this.pairingEvent_)
+ return '';
+ var digit = '0';
+ var pairing = this.pairingEvent_.pairing;
+ if (pairing == PairingEventType.DISPLAY_PINCODE &&
+ this.pairingEvent_.pincode &&
+ index < this.pairingEvent_.pincode.length) {
+ digit = this.pairingEvent_.pincode[index];
+ } else if (
+ this.pairingEvent_.passkey &&
+ (pairing == PairingEventType.DISPLAY_PASSKEY ||
+ pairing == PairingEventType.KEYS_ENTERED ||
+ pairing == PairingEventType.CONFIRM_PASSKEY)) {
+ var passkeyString = String(this.pairingEvent_.passkey);
+ if (index < passkeyString.length)
+ digit = passkeyString[index];
+ }
+ return digit;
+ },
+
+ /**
+ * @param {number} index
+ * @return {string}
+ * @private
+ */
+ getPinClass_: function(index) {
+ if (!this.pairingEvent_)
+ return '';
+ if (this.pairingEvent_.pairing == PairingEventType.CONFIRM_PASSKEY)
+ return 'confirm';
+ var cssClass = 'display';
+ if (this.pairingEvent_.pairing == PairingEventType.DISPLAY_PASSKEY) {
+ if (index == 0)
+ cssClass += ' next';
+ else
+ cssClass += ' untyped';
+ } else if (
+ this.pairingEvent_.pairing == PairingEventType.KEYS_ENTERED &&
+ this.pairingEvent_.enteredKey) {
+ var enteredKey = this.pairingEvent_.enteredKey; // 1-7
+ var lastKey = this.digits_.length; // 6
+ if ((index == -1 && enteredKey > lastKey) || (index + 1 == enteredKey))
+ cssClass += ' next';
+ else if (index > enteredKey)
+ cssClass += ' untyped';
+ }
+ return cssClass;
+ },
+});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/compiled_resources2.gyp b/chromium/ui/webui/resources/cr_components/chromeos/compiled_resources2.gyp
new file mode 100644
index 00000000000..1e6afe0491a
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/compiled_resources2.gyp
@@ -0,0 +1,30 @@
+# 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.
+{
+ 'targets': [
+ {
+ 'target_name': 'network_resources',
+ 'type': 'none',
+ 'dependencies': [
+ 'network/compiled_resources2.gyp:*',
+ ],
+ },
+ {
+ 'target_name': 'bluetooth_dialog',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_elements/cr_dialog/compiled_resources2.gyp:cr_dialog',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:cr',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ '<(DEPTH)/third_party/polymer/v1_0/components-chromium/iron-resizable-behavior/compiled_resources2.gyp:iron-resizable-behavior-extracted',
+ '<(DEPTH)/third_party/polymer/v1_0/components-chromium/paper-input/compiled_resources2.gyp:paper-input-extracted',
+ '<(EXTERNS_GYP):bluetooth',
+ '<(EXTERNS_GYP):bluetooth_private',
+ '<(INTERFACES_GYP):bluetooth_interface',
+ '<(INTERFACES_GYP):bluetooth_private_interface',
+ ],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ ],
+}
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/compiled_resources2.gyp b/chromium/ui/webui/resources/cr_components/chromeos/network/compiled_resources2.gyp
new file mode 100644
index 00000000000..a18b88baaa0
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/compiled_resources2.gyp
@@ -0,0 +1,63 @@
+# 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.
+{
+ 'targets': [
+ {
+ 'target_name': 'network_apnlist',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ ],
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'network_ip_config',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ ],
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'network_nameservers',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ ],
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'network_property_list',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
+ '<(DEPTH)/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp:cr_policy_network_behavior',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ ],
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'network_proxy',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
+ '<(DEPTH)/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp:cr_policy_network_behavior',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:assert',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ ],
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'network_proxy_input',
+ 'dependencies': [
+ '<(DEPTH)/ui/webui/resources/cr_elements/chromeos/network/compiled_resources2.gyp:cr_onc_types',
+ '<(DEPTH)/ui/webui/resources/js/compiled_resources2.gyp:i18n_behavior',
+ ],
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ {
+ 'target_name': 'network_proxy_exclusions',
+ 'includes': ['../../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
+ ],
+}
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.html
new file mode 100644
index 00000000000..1a2c716e7ee
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.html
@@ -0,0 +1,43 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/html/md_select_css.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="network_property_list.html">
+<link rel="import" href="network_shared_css.html">
+
+<dom-module id="network-apnlist">
+ <template>
+ <style include="network-shared md-select">
+ paper-button {
+ margin: 4px 0;
+ }
+ </style>
+ <div class="property-box">
+ <div class="start">[[i18n('networkAccessPoint')]]</div>
+ <div class="md-select-wrapper">
+ <select id="selectApn" class="md-select" on-change="onSelectApnChange_"
+ value="[[selectedApn_]]"
+ aria-label="[[i18n('networkAccessPoint')]]">
+ <template is="dom-repeat" items="[[apnSelectList_]]">
+ <option value="[[item.AccessPointName]]">[[apnDesc_(item)]]</option>
+ </template>
+ </select>
+ <span class="md-select-underline"></span>
+ </div>
+ </div>
+
+ <div class="property-box single-column indented"
+ hidden$="[[!isOtherSelected_(selectedApn_, networkProperties)]]">
+ <network-property-list on-property-change="onOtherApnChange_"
+ fields="[[otherApnFields_]]" property-dict="[[otherApn_]]"
+ edit-field-types="[[otherApnEditTypes_]]" prefix="Cellular.APN.">
+ </network-property-list>
+ <paper-button class="action-button" on-tap="onSaveOtherTap_">
+ [[i18n('save')]]
+ </paper-button>
+ </div>
+ </template>
+ <script src="network_apnlist.js"></script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.js
new file mode 100644
index 00000000000..c4e5034e13d
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_apnlist.js
@@ -0,0 +1,271 @@
+// 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.
+
+/**
+ * @fileoverview Polymer element for displaying and modifying a list of cellular
+ * access points.
+ */
+Polymer({
+ is: 'network-apnlist',
+
+ behaviors: [I18nBehavior],
+
+ properties: {
+ /**
+ * The current set of properties for the network matching |guid|.
+ * @type {!CrOnc.NetworkProperties|undefined}
+ */
+ networkProperties: {
+ type: Object,
+ observer: 'networkPropertiesChanged_',
+ },
+
+ /**
+ * The CrOnc.APNProperties.AccessPointName value of the selected APN.
+ * @private
+ */
+ selectedApn_: {
+ type: String,
+ value: '',
+ },
+
+ /**
+ * Selectable list of APN dictionaries for the UI. Includes an entry
+ * corresponding to |otherApn| (see below).
+ * @private {!Array<!CrOnc.APNProperties>}
+ */
+ apnSelectList_: {
+ type: Array,
+ value: function() {
+ return [];
+ }
+ },
+
+ /**
+ * The user settable properties for a new ('other') APN. The values for
+ * AccessPointName, Username, and Password will be set to the currently
+ * active APN if it does not match an existing list entry.
+ * @private {CrOnc.APNProperties|undefined}
+ */
+ otherApn_: {
+ type: Object,
+ },
+
+ /**
+ * Array of property names to pass to the Other APN property list.
+ * @private {!Array<string>}
+ */
+ otherApnFields_: {
+ type: Array,
+ value: function() {
+ return ['AccessPointName', 'Username', 'Password'];
+ },
+ readOnly: true
+ },
+
+ /**
+ * Array of edit types to pass to the Other APN property list.
+ * @private
+ */
+ otherApnEditTypes_: {
+ type: Object,
+ value: function() {
+ return {
+ 'AccessPointName': 'String',
+ 'Username': 'String',
+ 'Password': 'Password'
+ };
+ },
+ readOnly: true
+ },
+ },
+
+ /** @const */
+ DefaultAccessPointName: 'none',
+
+ /**
+ * Polymer networkProperties changed method.
+ */
+ networkPropertiesChanged_: function() {
+ if (!this.networkProperties || !this.networkProperties.Cellular)
+ return;
+
+ /** @type {!CrOnc.APNProperties|undefined} */ var activeApn;
+ var cellular = this.networkProperties.Cellular;
+ /** @type {!chrome.networkingPrivate.ManagedAPNProperties|undefined} */ var
+ apn = cellular.APN;
+ if (apn && apn.AccessPointName) {
+ activeApn = /** @type {!CrOnc.APNProperties|undefined} */ (
+ CrOnc.getSimpleActiveProperties(apn));
+ } else if (cellular.LastGoodAPN && cellular.LastGoodAPN.AccessPointName) {
+ activeApn = cellular.LastGoodAPN;
+ }
+ this.setApnSelectList_(activeApn);
+ },
+
+ /**
+ * Sets the list of selectable APNs for the UI. Appends an 'Other' entry
+ * (see comments for |otherApn_| above).
+ * @param {CrOnc.APNProperties|undefined} activeApn The currently active APN
+ * properties.
+ * @private
+ */
+ setApnSelectList_: function(activeApn) {
+ // Copy the list of APNs from this.networkProperties.
+ var result = this.getApnList_().slice();
+
+ // Test whether |activeApn| is in the current APN list in networkProperties.
+ var activeApnInList = activeApn && result.some(function(a) {
+ return a.AccessPointName == activeApn.AccessPointName;
+ });
+
+ // If |activeApn| is specified and not in the list, use the active
+ // properties for 'other'. Otherwise use any existing 'other' properties.
+ var otherApnProperties =
+ (activeApn && !activeApnInList) ? activeApn : this.otherApn_;
+ var otherApn = this.createApnObject_(otherApnProperties);
+
+ // Always use 'Other' for the name of custom APN entries (the name does
+ // not get saved).
+ otherApn.Name = 'Other';
+
+ // If no 'active' or 'other' AccessPointName was provided, use the default.
+ otherApn.AccessPointName =
+ otherApn.AccessPointName || this.DefaultAccessPointName;
+
+ // Save the 'other' properties.
+ this.otherApn_ = otherApn;
+
+ // Append 'other' to the end of the list of APNs.
+ result.push(otherApn);
+
+ this.apnSelectList_ = result;
+ // Set selectedApn_ after dom-repeat has been stamped.
+ this.async(() => {
+ this.selectedApn_ =
+ (activeApn && activeApn.AccessPointName) || otherApn.AccessPointName;
+ });
+ },
+
+ /**
+ * @param {!CrOnc.APNProperties|undefined=} apnProperties
+ * @return {!CrOnc.APNProperties} A new APN object with properties from
+ * |apnProperties| if provided.
+ * @private
+ */
+ createApnObject_: function(apnProperties) {
+ var newApn = {AccessPointName: ''};
+ if (apnProperties)
+ Object.assign(newApn, apnProperties);
+ return newApn;
+ },
+
+ /**
+ * @return {!Array<!CrOnc.APNProperties>} The list of APN properties in
+ * |networkProperties| or an empty list if the property is not set.
+ * @private
+ */
+ getApnList_: function() {
+ if (!this.networkProperties || !this.networkProperties.Cellular)
+ return [];
+ /** @type {!chrome.networkingPrivate.ManagedAPNList|undefined} */ var
+ apnlist = this.networkProperties.Cellular.APNList;
+ if (!apnlist)
+ return [];
+ return /** @type {!Array<!CrOnc.APNProperties>} */ (
+ CrOnc.getActiveValue(apnlist));
+ },
+
+ /**
+ * Event triggered when the selectApn selection changes.
+ * @param {!Event} event
+ * @private
+ */
+ onSelectApnChange_: function(event) {
+ var target = /** @type {!HTMLSelectElement} */ (event.target);
+ var accessPointName = target.value;
+ // When selecting 'Other', don't set a change event unless a valid
+ // non-default value has been set for Other.
+ if (this.isOtherSelected_(accessPointName) &&
+ (!this.otherApn_ || !this.otherApn_.AccessPointName ||
+ this.otherApn_.AccessPointName == this.DefaultAccessPointName)) {
+ this.selectedApn_ = accessPointName;
+ return;
+ }
+ this.sendApnChange_(accessPointName);
+ },
+
+ /**
+ * Event triggered when any 'Other' APN network property changes.
+ * @param {!{detail: {field: string, value: string}}} event
+ * @private
+ */
+ onOtherApnChange_: function(event) {
+ this.set('otherApn_.' + event.detail.field, event.detail.value);
+ // Don't send a change event for 'Other' until the 'Save' button is tapped.
+ },
+
+ /**
+ * Event triggered when the Other APN 'Save' button is tapped.
+ * @param {!Event} event
+ * @private
+ */
+ onSaveOtherTap_: function(event) {
+ this.sendApnChange_(this.selectedApn_);
+ },
+
+ /**
+ * Send the apn-change event.
+ * @param {string} accessPointName
+ * @private
+ */
+ sendApnChange_: function(accessPointName) {
+ var apnList = this.getApnList_();
+ var apn = this.findApnInList(apnList, accessPointName);
+ if (apn == undefined) {
+ apn = this.createApnObject_();
+ if (this.otherApn_) {
+ apn.AccessPointName = this.otherApn_.AccessPointName;
+ apn.Username = this.otherApn_.Username;
+ apn.Password = this.otherApn_.Password;
+ }
+ }
+ this.fire('apn-change', {field: 'APN', value: apn});
+ },
+
+ /**
+ * @param {string} accessPointName
+ * @return {boolean} True if the 'other' APN is currently selected.
+ * @private
+ */
+ isOtherSelected_: function(accessPointName) {
+ if (!this.networkProperties || !this.networkProperties.Cellular)
+ return false;
+ var apnList = this.getApnList_();
+ var apn = this.findApnInList(apnList, accessPointName);
+ return apn == undefined;
+ },
+
+ /**
+ * @param {!CrOnc.APNProperties} apn
+ * @return {string} The most descriptive name for the access point.
+ * @private
+ */
+ apnDesc_: function(apn) {
+ return apn.LocalizedName || apn.Name || apn.AccessPointName;
+ },
+
+ /**
+ * @param {!Array<!CrOnc.APNProperties>} apnList
+ * @param {string} accessPointName
+ * @return {CrOnc.APNProperties|undefined} The entry in |apnList| matching
+ * |accessPointName| if it exists, or undefined.
+ * @private
+ */
+ findApnInList: function(apnList, accessPointName) {
+ return apnList.find(function(a) {
+ return a.AccessPointName == accessPointName;
+ });
+ }
+});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.html
new file mode 100644
index 00000000000..8999e86a290
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.html
@@ -0,0 +1,30 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
+<link rel="import" href="network_property_list.html">
+<link rel="import" href="network_shared_css.html">
+
+<dom-module id="network-ip-config">
+ <template>
+ <style include="network-shared iron-flex"></style>
+ <div class="property-box">
+ <div id="autoIPConfigLabel" class="start">
+ [[i18n('networkIPConfigAuto')]]
+ </div>
+ <paper-toggle-button checked="{{automatic_}}" disabled="[[!editable]]"
+ aria-labelledby="autoIPConfigLabel">
+ </paper-toggle-button>
+ </div>
+ <div class="property-box single-column indented stretch"
+ hidden$="[[!ipConfig_]]">
+ <network-property-list
+ fields="[[ipConfigFields_]]" property-dict="[[ipConfig_]]"
+ edit-field-types="[[getIPEditFields_(editable, automatic_)]]"
+ on-property-change="onIPChange_">
+ </network-property-list>
+ </div>
+ </template>
+ <script src="network_ip_config.js"></script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.js
new file mode 100644
index 00000000000..519367b120a
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_ip_config.js
@@ -0,0 +1,214 @@
+// 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.
+
+/**
+ * @fileoverview Polymer element for displaying the IP Config properties for
+ * a network state. TODO(stevenjb): Allow editing of static IP configurations
+ * when 'editable' is true.
+ */
+Polymer({
+ is: 'network-ip-config',
+
+ behaviors: [I18nBehavior],
+
+ properties: {
+ /**
+ * The network properties dictionary containing the IP Config properties to
+ * display and modify.
+ * @type {!CrOnc.NetworkProperties|undefined}
+ */
+ networkProperties: {
+ type: Object,
+ observer: 'networkPropertiesChanged_',
+ },
+
+ /**
+ * Whether or not the IP Address can be edited.
+ */
+ editable: {
+ type: Boolean,
+ value: false,
+ },
+
+ /**
+ * State of 'Configure IP Addresses Automatically'.
+ * @private
+ */
+ automatic_: {
+ type: Boolean,
+ value: true,
+ observer: 'automaticChanged_',
+ },
+
+ /**
+ * The currently visible IP Config property dictionary. The 'RoutingPrefix'
+ * property is a human-readable mask instead of a prefix length.
+ * @private {?{
+ * ipv4: !CrOnc.IPConfigUIProperties,
+ * ipv6: (!CrOnc.IPConfigUIProperties|undefined)
+ * }}
+ */
+ ipConfig_: {
+ type: Object,
+ value: null,
+ },
+
+ /**
+ * Array of properties to pass to the property list.
+ * @private {!Array<string>}
+ */
+ ipConfigFields_: {
+ type: Array,
+ value: function() {
+ return [
+ 'ipv4.IPAddress',
+ 'ipv4.RoutingPrefix',
+ 'ipv4.Gateway',
+ 'ipv6.IPAddress',
+ ];
+ },
+ readOnly: true
+ },
+ },
+
+ /**
+ * Saved static IP configuration properties when switching to 'automatic'.
+ * @private {!CrOnc.IPConfigUIProperties|undefined}
+ */
+ savedStaticIp_: undefined,
+
+ /**
+ * Polymer networkProperties changed method.
+ */
+ networkPropertiesChanged_: function(newValue, oldValue) {
+ if (!this.networkProperties)
+ return;
+
+ var properties = this.networkProperties;
+ if (newValue.GUID != (oldValue && oldValue.GUID))
+ this.savedStaticIp_ = undefined;
+
+ // Update the 'automatic' property.
+ if (properties.IPAddressConfigType) {
+ var ipConfigType = CrOnc.getActiveValue(properties.IPAddressConfigType);
+ this.automatic_ = (ipConfigType != CrOnc.IPConfigType.STATIC);
+ }
+
+ if (properties.IPConfigs || properties.StaticIPConfig) {
+ // Update the 'ipConfig' property.
+ var ipv4 = CrOnc.getIPConfigForType(properties, CrOnc.IPType.IPV4);
+ var ipv6 = CrOnc.getIPConfigForType(properties, CrOnc.IPType.IPV6);
+ this.ipConfig_ = {
+ ipv4: this.getIPConfigUIProperties_(ipv4),
+ ipv6: this.getIPConfigUIProperties_(ipv6)
+ };
+ } else {
+ this.ipConfig_ = null;
+ }
+ },
+
+ /** @private */
+ automaticChanged_: function() {
+ if (!this.automatic_) {
+ // Ensure that there is a valid IPConfig object.
+ this.ipConfig_ = this.ipConfig_ || {
+ ipv4: {
+ Gateway: '192.168.1.1',
+ IPAddress: '192.168.1.1',
+ RoutingPrefix: '255.255.255.0',
+ Type: CrOnc.IPType.IPV4,
+ },
+ };
+ this.sendStaticIpConfig_();
+ return;
+ }
+
+ // Save the static IP configuration when switching to automatic.
+ if (this.ipConfig_)
+ this.savedStaticIp_ = this.ipConfig_.ipv4;
+ // Send the change.
+ this.fire('ip-change', {
+ field: 'IPAddressConfigType',
+ value: CrOnc.IPConfigType.DHCP,
+ });
+ },
+
+ /**
+ * @param {!CrOnc.IPConfigProperties|undefined} ipconfig
+ * @return {!CrOnc.IPConfigUIProperties} A new IPConfigUIProperties object
+ * with RoutingPrefix expressed as a string mask instead of a prefix
+ * length. Returns an empty object if |ipconfig| is undefined.
+ * @private
+ */
+ getIPConfigUIProperties_: function(ipconfig) {
+ var result = {};
+ if (!ipconfig)
+ return result;
+ for (var key in ipconfig) {
+ var value = ipconfig[key];
+ if (key == 'RoutingPrefix')
+ result.RoutingPrefix = CrOnc.getRoutingPrefixAsNetmask(value);
+ else
+ result[key] = value;
+ }
+ return result;
+ },
+
+ /**
+ * @param {!CrOnc.IPConfigUIProperties} ipconfig The IP Config UI properties.
+ * @return {!CrOnc.IPConfigProperties} A new IPConfigProperties object with
+ * RoutingPrefix expressed as a a prefix length.
+ * @private
+ */
+ getIPConfigProperties_: function(ipconfig) {
+ var result = {};
+ for (var key in ipconfig) {
+ var value = ipconfig[key];
+ if (key == 'RoutingPrefix')
+ result.RoutingPrefix = CrOnc.getRoutingPrefixAsLength(value);
+ else
+ result[key] = value;
+ }
+ return result;
+ },
+
+ /**
+ * @return {Object} An object with the edit type for each editable field.
+ * @private
+ */
+ getIPEditFields_: function() {
+ if (!this.editable || this.automatic_)
+ return {};
+ return {
+ 'ipv4.IPAddress': 'String',
+ 'ipv4.RoutingPrefix': 'String',
+ 'ipv4.Gateway': 'String'
+ };
+ },
+
+ /**
+ * Event triggered when the network property list changes.
+ * @param {!{detail: {field: string, value: string}}} event The
+ * network-property-list change event.
+ * @private
+ */
+ onIPChange_: function(event) {
+ if (!this.ipConfig_)
+ return;
+ var field = event.detail.field;
+ var value = event.detail.value;
+ // Note: |field| includes the 'ipv4.' prefix.
+ this.set('ipConfig_.' + field, value);
+ this.sendStaticIpConfig_();
+ },
+
+ /** @private */
+ sendStaticIpConfig_: function() {
+ // This will also set IPAddressConfigType to STATIC.
+ this.fire('ip-change', {
+ field: 'StaticIPConfig',
+ value: this.getIPConfigProperties_(this.ipConfig_.ipv4)
+ });
+ },
+});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_nameservers.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_nameservers.html
new file mode 100644
index 00000000000..a64f6ca853d
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_nameservers.html
@@ -0,0 +1,43 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/html/md_select_css.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input-container.html">
+<link rel="import" href="network_shared_css.html">
+
+<dom-module id="network-nameservers">
+ <template>
+ <style include=" network-shared md-select">
+ paper-input-container {
+ -webkit-padding-start: 4px;
+ }
+ </style>
+
+ <div class="property-box">
+ <div class="start">[[i18n('networkNameservers')]]</div>
+ <div class="md-select-wrapper">
+ <select id="nameserverType" class="md-select" on-change="onTypeChange_"
+ value="[[nameserversType_]]"
+ aria-label="[[i18n('networkNameservers')]]">
+ <template is="dom-repeat" items="[[nameserverTypeNames_]]">
+ <option value="[[item]]">[[nameserverTypeDesc_(item)]]</option>
+ </template>
+ </select>
+ <span class="md-select-underline"></span>
+ </div>
+ </div>
+
+ <div class="property-box single-column indented"
+ hidden$="[[!nameservers_.length]]">
+ <template is="dom-repeat" items="[[nameservers_]]">
+ <paper-input-container no-label-float>
+ <input id="nameserver[[index]]" is="iron-input" value="[[item]]"
+ disabled="[[!canEdit_(editable, nameserversType_)]]"
+ on-change="onValueChange_">
+ </paper-input-container>
+ </template>
+ </div>
+ </template>
+ <script src="network_nameservers.js"></script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_nameservers.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_nameservers.js
new file mode 100644
index 00000000000..237614403be
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_nameservers.js
@@ -0,0 +1,214 @@
+// 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.
+
+/**
+ * @fileoverview Polymer element for displaying network nameserver options.
+ */
+Polymer({
+ is: 'network-nameservers',
+
+ behaviors: [I18nBehavior],
+
+ properties: {
+ /**
+ * The network properties dictionary containing the nameserver properties to
+ * display and modify.
+ * @type {!CrOnc.NetworkProperties|undefined}
+ */
+ networkProperties: {
+ type: Object,
+ observer: 'networkPropertiesChanged_',
+ },
+
+ /** Whether or not the nameservers can be edited. */
+ editable: {
+ type: Boolean,
+ value: false,
+ },
+
+ /**
+ * Array of nameserver addresses stored as strings.
+ * @private {!Array<string>}
+ */
+ nameservers_: {
+ type: Array,
+ value: function() {
+ return [];
+ },
+ },
+
+ /**
+ * The selected nameserver type.
+ * @private
+ */
+ nameserversType_: {
+ type: String,
+ value: 'automatic',
+ },
+
+ /**
+ * Array of nameserver types.
+ * @private
+ */
+ nameserverTypeNames_: {
+ type: Array,
+ value: ['automatic', 'google', 'custom'],
+ readOnly: true,
+ },
+ },
+
+ /** @const */
+ GOOGLE_NAMESERVERS: [
+ '8.8.4.4',
+ '8.8.8.8',
+ ],
+
+ /** @const */
+ MAX_NAMESERVERS: 4,
+
+ /**
+ * Saved nameservers when switching to 'automatic'.
+ * @private {!Array<string>}
+ */
+ savedNameservers_: [],
+
+ /** @private */
+ networkPropertiesChanged_: function(newValue, oldValue) {
+ if (!this.networkProperties)
+ return;
+
+ if (!oldValue || newValue.GUID != oldValue.GUID)
+ this.savedNameservers_ = [];
+
+ // Update the 'nameservers' property.
+ var nameservers = [];
+ var ipv4 =
+ CrOnc.getIPConfigForType(this.networkProperties, CrOnc.IPType.IPV4);
+ if (ipv4 && ipv4.NameServers)
+ nameservers = ipv4.NameServers;
+
+ // Update the 'nameserversType' property.
+ var configType =
+ CrOnc.getActiveValue(this.networkProperties.NameServersConfigType);
+ var type;
+ if (configType == CrOnc.IPConfigType.STATIC) {
+ if (nameservers.join(',') == this.GOOGLE_NAMESERVERS.join(',')) {
+ type = 'google';
+ } else {
+ type = 'custom';
+ }
+ } else {
+ type = 'automatic';
+ }
+ this.setNameservers_(type, nameservers);
+ },
+
+ /**
+ * @param {string} nameserversType
+ * @param {!Array<string>} nameservers
+ * @private
+ */
+ setNameservers_: function(nameserversType, nameservers) {
+ if (nameserversType == 'custom') {
+ // Add empty entries for unset custom nameservers.
+ for (var i = nameservers.length; i < this.MAX_NAMESERVERS; ++i)
+ nameservers[i] = '';
+ }
+ this.nameservers_ = nameservers;
+ // Set nameserversType_ after dom-repeat has been stamped.
+ this.async(() => {
+ this.nameserversType_ = nameserversType;
+ });
+ },
+
+ /**
+ * @param {string} type The nameservers type.
+ * @return {string} The description for |type|.
+ * @private
+ */
+ nameserverTypeDesc_: function(type) {
+ // TODO(stevenjb): Translate.
+ if (type == 'custom')
+ return 'Custom name servers';
+ if (type == 'google')
+ return 'Google name servers';
+ return 'Automatic name servers';
+ },
+
+ /**
+ * @param {boolean} editable
+ * @param {string} nameserversType
+ * @return {boolean} True if the nameservers are editable.
+ * @private
+ */
+ canEdit_: function(editable, nameserversType) {
+ return editable && nameserversType == 'custom';
+ },
+
+ /**
+ * Event triggered when the selected type changes. Updates nameservers and
+ * sends the change value if necessary.
+ * @param {!Event} event
+ * @private
+ */
+ onTypeChange_: function(event) {
+ if (this.nameserversType_ == 'custom')
+ this.savedNameservers_ = this.nameservers_;
+ var target = /** @type {!HTMLSelectElement} */ (event.target);
+ var type = target.value;
+ this.nameserversType_ = type;
+ if (type == 'custom') {
+ // Restore the saved nameservers.
+ this.setNameservers_(type, this.savedNameservers_);
+ // Only send custom nameservers if they are not empty.
+ if (this.savedNameservers_.length == 0)
+ return;
+ }
+ this.sendNameServers_();
+ },
+
+ /**
+ * Event triggered when a nameserver value changes.
+ * @private
+ */
+ onValueChange_: function() {
+ if (this.nameserversType_ != 'custom') {
+ // If a user inputs Google nameservers in the custom nameservers fields,
+ // |nameserversType| will change to 'google' so don't send the values.
+ return;
+ }
+ this.sendNameServers_();
+ },
+
+ /**
+ * Sends the current nameservers type (for automatic) or value.
+ * @private
+ */
+ sendNameServers_: function() {
+ var type = this.nameserversType_;
+
+ if (type == 'custom') {
+ var nameservers = new Array(this.MAX_NAMESERVERS);
+ for (var i = 0; i < this.MAX_NAMESERVERS; ++i) {
+ var nameserverInput = this.$$('#nameserver' + i);
+ nameservers[i] = nameserverInput ? nameserverInput.value : '';
+ }
+ this.fire('nameservers-change', {
+ field: 'NameServers',
+ value: nameservers,
+ });
+ } else if (type == 'google') {
+ this.fire('nameservers-change', {
+ field: 'NameServers',
+ value: this.GOOGLE_NAMESERVERS,
+ });
+ } else {
+ // automatic
+ this.fire('nameservers-change', {
+ field: 'NameServersConfigType',
+ value: CrOnc.IPConfigType.DHCP,
+ });
+ }
+ },
+});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_property_list.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_property_list.html
new file mode 100644
index 00000000000..0d73594c0af
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_property_list.html
@@ -0,0 +1,71 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
+<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_network_behavior.html">
+<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_network_indicator.html">
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input-container.html">
+<link rel="import" href="network_shared_css.html">
+
+<dom-module id="network-property-list">
+ <template>
+ <style include="network-shared iron-flex">
+ paper-input-container {
+ margin-bottom: -12px;
+ margin-top: -8px;
+ }
+
+ /* Property lists are embedded; remove the padding. */
+ .property-box {
+ padding: 0;
+ }
+
+ .secondary {
+ color: var(--paper-grey-600);
+ font-weight: 400;
+ }
+
+ cr-policy-network-indicator {
+ -webkit-margin-start: var(--settings-controlled-by-spacing);
+ }
+ </style>
+ <template is="dom-repeat" items="[[fields]]"
+ filter="[[computeFilter_(prefix, propertyDict, editFieldTypes)]]">
+ <div class="property-box single-column stretch">
+ <!-- Property label -->
+ <div>[[getPropertyLabel_(item, prefix)]]</div>
+ <!-- Uneditable property value -->
+ <div class="layout horizontal"
+ hidden="[[isEditable_(item, '', propertyDict, editFieldTypes)]]">
+ <div class="secondary">
+ [[getPropertyValue_(item, prefix, propertyDict)]]
+ </div>
+ <cr-policy-network-indicator
+ property="[[getProperty_(item, propertyDict)]]">
+ </cr-policy-network-indicator>
+ </div>
+ <!-- Editable String property value -->
+ <template is="dom-if" if="[[isEditable_(
+ item, 'String', propertyDict, editFieldTypes)]]">
+ <paper-input-container no-label-float>
+ <input id="[[item]]" is="iron-input"
+ value="[[getPropertyValue_(item, prefix, propertyDict)]]"
+ on-change="onValueChange_">
+ </paper-input-container>
+ </template>
+ <!-- Editable Password property value -->
+ <template is="dom-if" if="[[isEditable_(
+ item, 'Password', propertyDict, editFieldTypes)]]">
+ <paper-input-container no-label-float>
+ <input id="[[item]]" is="iron-input" type="password"
+ value="[[getPropertyValue_(item, prefix, propertyDict)]]"
+ on-change="onValueChange_">
+ </paper-input-container>
+ </template>
+ <!-- TODO(stevenjb): Support other types. -->
+ </div>
+ </template>
+ </template>
+ <script src="network_property_list.js"></script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_property_list.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_property_list.js
new file mode 100644
index 00000000000..f333386cb78
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_property_list.js
@@ -0,0 +1,214 @@
+// 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.
+
+/**
+ * @fileoverview Polymer element for displaying a list of network properties
+ * in a list. This also supports editing fields inline for fields listed in
+ * editFieldTypes.
+ */
+Polymer({
+ is: 'network-property-list',
+
+ behaviors: [I18nBehavior, CrPolicyNetworkBehavior],
+
+ properties: {
+ /**
+ * The dictionary containing the properties to display.
+ * @type {!Object|undefined}
+ */
+ propertyDict: {type: Object},
+
+ /**
+ * Fields to display.
+ * @type {!Array<string>}
+ */
+ fields: {
+ type: Array,
+ value: function() {
+ return [];
+ },
+ },
+
+ /**
+ * Edit type of editable fields. May contain a property for any field in
+ * |fields|. Other properties will be ignored. Property values can be:
+ * 'String' - A text input will be displayed.
+ * 'Password' - A string with input type = password.
+ * TODO(stevenjb): Support types with custom validation, e.g. IPAddress.
+ * TODO(stevenjb): Support 'Number'.
+ * When a field changes, the 'property-change' event will be fired with
+ * the field name and the new value provided in the event detail.
+ */
+ editFieldTypes: {
+ type: Object,
+ value: function() {
+ return {};
+ },
+ },
+
+ /** Prefix used to look up property key translations. */
+ prefix: {
+ type: String,
+ value: '',
+ },
+ },
+
+ /**
+ * Event triggered when an input field changes. Fires a 'property-change'
+ * event with the field (property) name set to the target id, and the value
+ * set to the target input value.
+ * @param {!Event} event The input change event.
+ * @private
+ */
+ onValueChange_: function(event) {
+ if (!this.propertyDict)
+ return;
+ var field = event.target.id;
+ var curValue = this.get(field, this.propertyDict);
+ if (typeof curValue == 'object') {
+ // Extract the property from an ONC managed dictionary.
+ curValue = CrOnc.getActiveValue(
+ /** @type {!CrOnc.ManagedProperty} */ (curValue));
+ }
+ var newValue = event.target.value;
+ if (newValue == curValue)
+ return;
+ this.fire('property-change', {field: field, value: newValue});
+ },
+
+ /**
+ * @param {string} key The property key.
+ * @param {string} prefix
+ * @return {string} The text to display for the property label.
+ * @private
+ */
+ getPropertyLabel_: function(key, prefix) {
+ var oncKey = 'Onc' + prefix + key;
+ oncKey = oncKey.replace(/\./g, '-');
+ if (this.i18nExists(oncKey))
+ return this.i18n(oncKey);
+ // We do not provide translations for every possible network property key.
+ // For keys specific to a type, strip the type prefix.
+ var result = prefix + key;
+ for (var entry in chrome.networkingPrivate.NetworkType) {
+ var type = chrome.networkingPrivate.NetworkType[entry];
+ if (result.startsWith(type + '.')) {
+ result = result.substr(type.length + 1);
+ break;
+ }
+ }
+ return result;
+ },
+
+ /**
+ * Generates a filter function dependent on propertyDict and editFieldTypes.
+ * @param {string} prefix
+ * @param {!Object} propertyDict
+ * @param {!Object} editFieldTypes
+ * @private
+ */
+ computeFilter_: function(prefix, propertyDict, editFieldTypes) {
+ return key => {
+ if (editFieldTypes.hasOwnProperty(key))
+ return true;
+ var value = this.getPropertyValue_(key, prefix, propertyDict);
+ return value !== undefined && value !== '';
+ };
+ },
+
+ /**
+ * @param {string} key The property key.
+ * @param {string} type The field type.
+ * @param {!Object} propertyDict
+ * @param {!Object} editFieldTypes
+ * @return {boolean}
+ * @private
+ */
+ isEditable_: function(key, type, propertyDict, editFieldTypes) {
+ var property = /** @type {!CrOnc.ManagedProperty|undefined} */ (
+ this.get(key, propertyDict));
+ if (this.isNetworkPolicyEnforced(property))
+ return false;
+ var editType = editFieldTypes[key];
+ return editType !== undefined && (type == '' || editType == type);
+ },
+
+ /**
+ * @param {string} key The property key.
+ * @param {!Object} propertyDict
+ * @return {*} The managed property dictionary associated with |key|.
+ * @private
+ */
+ getProperty_: function(key, propertyDict) {
+ return this.get(key, propertyDict);
+ },
+
+ /**
+ * @param {string} key The property key.
+ * @param {string} prefix
+ * @param {!Object} propertyDict
+ * @return {string} The text to display for the property value.
+ * @private
+ */
+ getPropertyValue_: function(key, prefix, propertyDict) {
+ var value = this.get(key, propertyDict);
+ if (value === undefined)
+ return '';
+ if (typeof value == 'object') {
+ // Extract the property from an ONC managed dictionary
+ value =
+ CrOnc.getActiveValue(/** @type {!CrOnc.ManagedProperty} */ (value));
+ }
+ var customValue = this.getCustomPropertyValue_(key, value);
+ if (customValue)
+ return customValue;
+ if (typeof value == 'number' || typeof value == 'boolean')
+ return value.toString();
+ assert(typeof value == 'string');
+ var valueStr = /** @type {string} */ (value);
+ var oncKey = 'Onc' + prefix + key;
+ oncKey = oncKey.replace(/\./g, '-');
+ oncKey += '_' + valueStr;
+ if (this.i18nExists(oncKey))
+ return this.i18n(oncKey);
+ return valueStr;
+ },
+
+ /**
+ * @param {string} key The property key.
+ * @param {*} value The property value.
+ * @return {string} The text to display for the property value. If the key
+ * does not correspond to a custom property, an empty string is returned.
+ */
+ getCustomPropertyValue_: function(key, value) {
+ if (key == 'Tether.BatteryPercentage') {
+ assert(typeof value == 'number');
+ return this.i18n('OncTether-BatteryPercentage_Value', value.toString());
+ }
+
+ if (key == 'Tether.SignalStrength') {
+ assert(typeof value == 'number');
+ // Possible |signalStrength| values should be 0, 25, 50, 75, and 100. Add
+ // <= checks for robustness.
+ if (value <= 24)
+ return this.i18n('OncTether-SignalStrength_Weak');
+ if (value <= 49)
+ return this.i18n('OncTether-SignalStrength_Okay');
+ if (value <= 74)
+ return this.i18n('OncTether-SignalStrength_Good');
+ if (value <= 99)
+ return this.i18n('OncTether-SignalStrength_Strong');
+ return this.i18n('OncTether-SignalStrength_VeryStrong');
+ }
+
+ if (key == 'Tether.Carrier') {
+ assert(typeof value == 'string');
+ return (!value || value == 'unknown-carrier') ?
+ this.i18n('tetherUnknownCarrier') :
+ value;
+ }
+
+ return '';
+ },
+});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy.html
new file mode 100644
index 00000000000..4b328f9145b
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy.html
@@ -0,0 +1,154 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/chromeos/network/cr_onc_types.html">
+<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/policy/cr_policy_network_behavior.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/html/md_select_css.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-a11y-keys/iron-a11y-keys.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-button/paper-button.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input-container.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-toggle-button/paper-toggle-button.html">
+<link rel="import" href="network_proxy_exclusions.html">
+<link rel="import" href="network_proxy_input.html">
+<link rel="import" href="network_shared_css.html">
+
+<dom-module id="network-proxy">
+ <template>
+ <style include="network-shared md-select cr-hidden-style iron-flex iron-flex-alignment">
+ network-proxy-input {
+ margin-bottom: 10px;
+ }
+
+ network-proxy-exclusions {
+ margin: 10px 0;
+ }
+
+ #manualProxy {
+ -webkit-padding-start: var(--cr-section-padding);
+ }
+ </style>
+
+ <!-- Proxy type dropdown -->
+ <div class="property-box">
+ <div class="start">[[i18n('networkProxyConnectionType')]]</div>
+ <div class="md-select-wrapper">
+ <select id="proxyType" class="md-select" on-change="onTypeChange_"
+ value="[[proxy_.Type]]"
+ disabled="[[!isEditable_('Type', networkProperties, editable,
+ useSharedProxies)]]"
+ aria-label="[[i18n('networkProxyConnectionType')]]">
+ <template is="dom-repeat" items="[[proxyTypes_]]">
+ <option value="[[item]]">[[getProxyTypeDesc_(item)]]</option>
+ </template>
+ </select>
+ <span class="md-select-underline"></span>
+ </div>
+ </div>
+
+ <!-- Autoconfiguration (PAC) -->
+ <div class="property-box indented"
+ hidden$="[[!matches_(proxy_.Type, ProxySettingsType_.PAC)]]">
+ <div>[[i18n('networkProxyAutoConfig')]]</div>
+ <paper-input no-label-float class="middle" value="{{proxy_.PAC}}"
+ disabled="[[!isEditable_('PAC', networkProperties, editable,
+ useSharedProxies)]]"
+ on-change="onPACChange_">
+ </paper-input>
+ </div>
+
+ <!-- Web Proxy Auto Discovery (WPAD) -->
+ <div class="property-box indented"
+ hidden$="[[!matches_(proxy_.Type, ProxySettingsType_.WPAD)]]">
+ <div>[[i18n('networkProxyWpad')]]</div>
+ <div class="middle">[[WPAD_]]</div>
+ </div>
+
+ <!-- Manual -->
+ <div class="property-box indented"
+ hidden$="[[!matches_(proxy_.Type, ProxySettingsType_.MANUAL)]]">
+ <div id="networkProxyToggleLabel" class="flex">
+ [[i18n('networkProxyUseSame')]]
+ </div>
+ <paper-toggle-button checked="{{useSameProxy_}}"
+ disabled="[[!isEditable_('Type', networkProperties, editable,
+ useSharedProxies)]]"
+ aria-labelledby="networkProxyToggleLabel">
+ </paper-toggle-button>
+ </div>
+
+ <div id="manualProxy" class="layout vertical start"
+ hidden$="[[!matches_(proxy_.Type, ProxySettingsType_.MANUAL)]]">
+ <div hidden$="[[!useSameProxy_]]" class="layout vertical">
+ <network-proxy-input
+ on-proxy-change="onProxyInputChange_"
+ editable="[[isEditable_('Manual.HTTPProxy.Host', networkProperties,
+ editable, useSharedProxies)]]"
+ value="{{proxy_.Manual.HTTPProxy}}"
+ label="[[i18n('networkProxy')]]">
+ </network-proxy-input>
+ </div>
+ <div hidden$="[[useSameProxy_]]" class="layout vertical">
+ <network-proxy-input
+ on-proxy-change="onProxyInputChange_"
+ editable="[[isEditable_('Manual.HTTPProxy.Host', networkProperties,
+ editable, useSharedProxies)]]"
+ value="{{proxy_.Manual.HTTPProxy}}"
+ label="[[i18n('networkProxyHttp')]]">
+ </network-proxy-input>
+ <network-proxy-input
+ on-proxy-change="onProxyInputChange_"
+ editable="[[isEditable_('Manual.SecureHTTPProxy.Host',
+ networkProperties, editable, useSharedProxies)]]"
+ value="{{proxy_.Manual.SecureHTTPProxy}}"
+ label="[[i18n('networkProxyShttp')]]">
+ </network-proxy-input>
+ <network-proxy-input
+ on-proxy-change="onProxyInputChange_"
+ editable="[[isEditable_('Manual.FTPProxy.Host', networkProperties,
+ editable, useSharedProxies)]]"
+ value="{{proxy_.Manual.FTPProxy}}"
+ label="[[i18n('networkProxyFtp')]]">
+ </network-proxy-input>
+ <network-proxy-input
+ on-proxy-change="onProxyInputChange_"
+ editable="[[isEditable_('Manual.SOCKS.Host', networkProperties,
+ editable, useSharedProxies)]]"
+ value="{{proxy_.Manual.SOCKS}}"
+ label="[[i18n('networkProxySocks')]]">
+ </network-proxy-input>
+ </div>
+
+ <div hidden="[[!isEditable_('Type', networkProperties, editable,
+ useSharedProxies)]]">
+ <div>[[i18n('networkProxyExceptionList')]]</div>
+ <network-proxy-exclusions on-proxy-change="onProxyExclusionsChange_"
+ exclusions="{{proxy_.ExcludeDomains}}">
+ </network-proxy-exclusions>
+ <div class="layout horizontal">
+ <paper-input-container no-label-float class="flex">
+ <input id="proxyExclusion" is="iron-input">
+ <iron-a11y-keys keys="enter"
+ on-keys-pressed="onAddProxyExclusionTap_">
+ </iron-a11y-keys>
+ </paper-input-container>
+ <paper-button on-tap="onAddProxyExclusionTap_">
+ [[i18n('networkProxyAddException')]]
+ </paper-button>
+ </div>
+ </div>
+
+ <paper-button id="saveManualProxy"
+ on-tap="onSaveProxyTap_" class="action-button"
+ disabled="[[!isSaveManualProxyEnabled_(networkProperties,
+ proxyModified_, proxy_.*)]]">
+ [[i18n('save')]]
+ </paper-button>
+ </div>
+
+ </template>
+ <script src="network_proxy.js"></script>
+</dom-module>
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
new file mode 100644
index 00000000000..a1f2056eba8
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy.js
@@ -0,0 +1,428 @@
+// 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.
+
+/**
+ * @fileoverview Polymer element for displaying and editing network proxy
+ * values.
+ */
+Polymer({
+ is: 'network-proxy',
+
+ behaviors: [
+ CrPolicyNetworkBehavior,
+ I18nBehavior,
+ ],
+
+ properties: {
+ /**
+ * The network properties dictionary containing the proxy properties to
+ * display and modify.
+ * @type {!CrOnc.NetworkProperties|undefined}
+ */
+ networkProperties: {
+ type: Object,
+ observer: 'networkPropertiesChanged_',
+ },
+
+ /** Whether or not the proxy values can be edited. */
+ editable: {
+ type: Boolean,
+ value: false,
+ },
+
+ /** Whether shared proxies are allowed. */
+ useSharedProxies: {
+ type: Boolean,
+ value: false,
+ observer: 'updateProxy_',
+ },
+
+ /**
+ * UI visible / edited proxy configuration.
+ * @private {!CrOnc.ProxySettings}
+ */
+ proxy_: {
+ type: Object,
+ value: function() {
+ return this.createDefaultProxySettings_();
+ },
+ },
+
+ /**
+ * The Web Proxy Auto Discovery URL extracted from networkProperties.
+ * @private
+ */
+ WPAD_: {
+ type: String,
+ value: '',
+ },
+
+ /**
+ * Whether or not to use the same manual proxy for all protocols.
+ * @private
+ */
+ useSameProxy_: {
+ type: Boolean,
+ value: false,
+ observer: 'useSameProxyChanged_',
+ },
+
+ /**
+ * Array of proxy configuration types.
+ * @private {!Array<string>}
+ * @const
+ */
+ proxyTypes_: {
+ type: Array,
+ value: [
+ CrOnc.ProxySettingsType.DIRECT,
+ CrOnc.ProxySettingsType.PAC,
+ CrOnc.ProxySettingsType.WPAD,
+ CrOnc.ProxySettingsType.MANUAL,
+ ],
+ readOnly: true
+ },
+
+ /**
+ * Object providing proxy type values for data binding.
+ * @private {!Object}
+ * @const
+ */
+ ProxySettingsType_: {
+ type: Object,
+ value: {
+ DIRECT: CrOnc.ProxySettingsType.DIRECT,
+ PAC: CrOnc.ProxySettingsType.PAC,
+ MANUAL: CrOnc.ProxySettingsType.MANUAL,
+ WPAD: CrOnc.ProxySettingsType.WPAD,
+ },
+ readOnly: true,
+ },
+ },
+
+ /**
+ * Saved Manual properties so that switching to another type does not loose
+ * any set properties while the UI is open.
+ * @private {!CrOnc.ManualProxySettings|undefined}
+ */
+ savedManual_: undefined,
+
+ /**
+ * Saved ExcludeDomains properties so that switching to a non-Manual type does
+ * not loose any set exclusions while the UI is open.
+ * @private {!Array<string>|undefined}
+ */
+ savedExcludeDomains_: undefined,
+
+ /**
+ * Set to true while modifying proxy values so that an update does not
+ * override the edited values.
+ * @private {boolean}
+ */
+ proxyModified_: false,
+
+ /** @override */
+ attached: function() {
+ this.reset();
+ },
+
+ /**
+ * Called any time the page is refreshed or navigated to so that the proxy
+ * is updated correctly.
+ */
+ reset: function() {
+ this.proxyModified_ = false;
+ this.proxy_ = this.createDefaultProxySettings_();
+ this.updateProxy_();
+ },
+
+ /** @private */
+ networkPropertiesChanged_: function() {
+ if (this.proxyModified_)
+ return; // Ignore update.
+ this.updateProxy_();
+ },
+
+ /** @private */
+ updateProxy_: function() {
+ if (!this.networkProperties)
+ return;
+
+ /** @type {!CrOnc.ProxySettings} */
+ var proxy = this.createDefaultProxySettings_();
+
+ // For shared networks with unmanaged proxy settings, ignore any saved
+ // proxy settings (use the default values).
+ if (this.isShared_()) {
+ var property = this.getProxySettingsTypeProperty_();
+ if (!this.isControlled(property) && !this.useSharedProxies) {
+ this.setProxyAsync_(proxy);
+ return; // Proxy settings will be ignored.
+ }
+ }
+
+ /** @type {!chrome.networkingPrivate.ManagedProxySettings|undefined} */
+ var proxySettings = this.networkProperties.ProxySettings;
+ if (proxySettings) {
+ proxy.Type = /** @type {!CrOnc.ProxySettingsType} */ (
+ CrOnc.getActiveValue(proxySettings.Type));
+ if (proxySettings.Manual) {
+ proxy.Manual.HTTPProxy = /** @type {!CrOnc.ProxyLocation|undefined} */ (
+ CrOnc.getSimpleActiveProperties(
+ proxySettings.Manual.HTTPProxy)) ||
+ {Host: '', Port: 80};
+ proxy.Manual.SecureHTTPProxy =
+ /** @type {!CrOnc.ProxyLocation|undefined} */ (
+ CrOnc.getSimpleActiveProperties(
+ proxySettings.Manual.SecureHTTPProxy)) ||
+ {Host: '', Port: 80};
+ proxy.Manual.FTPProxy =
+ /** @type {!CrOnc.ProxyLocation|undefined} */ (
+ CrOnc.getSimpleActiveProperties(
+ proxySettings.Manual.FTPProxy)) ||
+ {Host: '', Port: 80};
+ proxy.Manual.SOCKS =
+ /** @type {!CrOnc.ProxyLocation|undefined} */ (
+ CrOnc.getSimpleActiveProperties(proxySettings.Manual.SOCKS)) ||
+ {Host: '', Port: 80};
+ var jsonHttp = proxy.Manual.HTTPProxy;
+ this.useSameProxy_ =
+ (CrOnc.proxyMatches(jsonHttp, proxy.Manual.SecureHTTPProxy) &&
+ CrOnc.proxyMatches(jsonHttp, proxy.Manual.FTPProxy) &&
+ CrOnc.proxyMatches(jsonHttp, proxy.Manual.SOCKS)) ||
+ (!proxy.Manual.SecureHTTPProxy.Host &&
+ !proxy.Manual.FTPProxy.Host && !proxy.Manual.SOCKS.Host);
+ }
+ if (proxySettings.ExcludeDomains) {
+ proxy.ExcludeDomains = /** @type {!Array<string>|undefined} */ (
+ CrOnc.getActiveValue(proxySettings.ExcludeDomains));
+ }
+ proxy.PAC = /** @type {string|undefined} */ (
+ CrOnc.getActiveValue(proxySettings.PAC));
+ }
+ // Use saved ExcludeDomains and Manual if not defined.
+ proxy.ExcludeDomains = proxy.ExcludeDomains || this.savedExcludeDomains_;
+ proxy.Manual = proxy.Manual || this.savedManual_;
+
+ // Set the Web Proxy Auto Discovery URL.
+ var ipv4 =
+ CrOnc.getIPConfigForType(this.networkProperties, CrOnc.IPType.IPV4);
+ this.WPAD_ = (ipv4 && ipv4.WebProxyAutoDiscoveryUrl) || '';
+
+ this.setProxyAsync_(proxy);
+ },
+
+ /**
+ * @param {!CrOnc.ProxySettings} proxy
+ * @private
+ */
+ setProxyAsync_: function(proxy) {
+ // Set this.proxy_ after dom-repeat has been stamped.
+ this.async(() => {
+ this.proxy_ = proxy;
+ this.proxyModified_ = false;
+ });
+ },
+
+ /** @private */
+ useSameProxyChanged_: function() {
+ this.proxyModified_ = true;
+ },
+
+ /**
+ * @return {CrOnc.ProxySettings} An empty/default proxy settings object.
+ * @private
+ */
+ createDefaultProxySettings_: function() {
+ return {
+ Type: CrOnc.ProxySettingsType.DIRECT,
+ ExcludeDomains: [],
+ Manual: {
+ HTTPProxy: {Host: '', Port: 80},
+ SecureHTTPProxy: {Host: '', Port: 80},
+ FTPProxy: {Host: '', Port: 80},
+ SOCKS: {Host: '', Port: 1080}
+ },
+ PAC: ''
+ };
+ },
+
+ /**
+ * Called when the proxy changes in the UI.
+ * @private
+ */
+ sendProxyChange_: function() {
+ var proxy =
+ /** @type {!CrOnc.ProxySettings} */ (Object.assign({}, this.proxy_));
+ if (proxy.Type == CrOnc.ProxySettingsType.MANUAL) {
+ var manual = proxy.Manual;
+ var defaultProxy = manual.HTTPProxy || {Host: '', Port: 80};
+ if (this.useSameProxy_) {
+ proxy.Manual.SecureHTTPProxy = /** @type {!CrOnc.ProxyLocation} */ (
+ Object.assign({}, defaultProxy));
+ proxy.Manual.FTPProxy = /** @type {!CrOnc.ProxyLocation} */ (
+ Object.assign({}, defaultProxy));
+ proxy.Manual.SOCKS = /** @type {!CrOnc.ProxyLocation} */ (
+ Object.assign({}, defaultProxy));
+ } else {
+ // Remove properties with empty hosts to unset them.
+ if (manual.HTTPProxy && !manual.HTTPProxy.Host)
+ delete manual.HTTPProxy;
+ if (manual.SecureHTTPProxy && !manual.SecureHTTPProxy.Host)
+ delete manual.SecureHTTPProxy;
+ if (manual.FTPProxy && !manual.FTPProxy.Host)
+ delete manual.FTPProxy;
+ if (manual.SOCKS && !manual.SOCKS.Host)
+ delete manual.SOCKS;
+ }
+ this.savedManual_ = Object.assign({}, manual);
+ this.savedExcludeDomains_ = proxy.ExcludeDomains;
+ } else if (proxy.Type == CrOnc.ProxySettingsType.PAC) {
+ if (!proxy.PAC)
+ return;
+ }
+ this.fire('proxy-change', {field: 'ProxySettings', value: proxy});
+ this.proxyModified_ = false;
+ },
+
+ /**
+ * Event triggered when the selected proxy type changes.
+ * @param {!Event} event
+ * @private
+ */
+ onTypeChange_: function(event) {
+ var target = /** @type {!HTMLSelectElement} */ (event.target);
+ var type = /** @type {chrome.networkingPrivate.ProxySettingsType} */ (
+ target.value);
+ this.set('proxy_.Type', type);
+ if (type == CrOnc.ProxySettingsType.MANUAL)
+ this.proxyModified_ = true;
+ else
+ this.sendProxyChange_();
+ },
+
+ /** @private */
+ onPACChange_: function() {
+ this.sendProxyChange_();
+ },
+
+ /** @private */
+ onProxyInputChange_: function() {
+ this.proxyModified_ = true;
+ },
+
+ /**
+ * Event triggered when a proxy exclusion is added.
+ * @param {!Event} event The add proxy exclusion event.
+ * @private
+ */
+ onAddProxyExclusionTap_: function(event) {
+ var value = this.$.proxyExclusion.value;
+ if (!value)
+ return;
+ this.push('proxy_.ExcludeDomains', value);
+ // Clear input.
+ this.$.proxyExclusion.value = '';
+ this.proxyModified_ = true;
+ },
+
+ /**
+ * Event triggered when the proxy exclusion list changes.
+ * @param {!Event} event The remove proxy exclusions change event.
+ * @private
+ */
+ onProxyExclusionsChange_: function(event) {
+ this.proxyModified_ = true;
+ },
+
+ /** @private */
+ onSaveProxyTap_: function() {
+ this.sendProxyChange_();
+ },
+
+ /**
+ * @param {string} proxyType The proxy type.
+ * @return {string} The description for |proxyType|.
+ * @private
+ */
+ getProxyTypeDesc_: function(proxyType) {
+ if (proxyType == CrOnc.ProxySettingsType.MANUAL)
+ return this.i18n('networkProxyTypeManual');
+ if (proxyType == CrOnc.ProxySettingsType.PAC)
+ return this.i18n('networkProxyTypePac');
+ if (proxyType == CrOnc.ProxySettingsType.WPAD)
+ return this.i18n('networkProxyTypeWpad');
+ return this.i18n('networkProxyTypeDirect');
+ },
+
+ /**
+ * @return {!CrOnc.ManagedProperty|undefined}
+ * @private
+ */
+ getProxySettingsTypeProperty_: function() {
+ return /** @type {!CrOnc.ManagedProperty|undefined} */ (
+ this.get('ProxySettings.Type', this.networkProperties));
+ },
+
+ /**
+ * @param {string} propertyName
+ * @return {boolean} Whether the named property setting is editable.
+ * @private
+ */
+ isEditable_: function(propertyName) {
+ if (!this.editable || (this.isShared_() && !this.useSharedProxies))
+ return false;
+ if (!this.networkProperties.hasOwnProperty('ProxySettings'))
+ return true; // No proxy settings defined, so not enforced.
+ var property = /** @type {!CrOnc.ManagedProperty|undefined} */ (
+ this.get('ProxySettings.' + propertyName, this.networkProperties));
+ if (!property)
+ return true;
+ return this.isPropertyEditable_(property);
+ },
+
+ /**
+ * @param {!CrOnc.ManagedProperty|undefined} property
+ * @return {boolean} Whether |property| is editable.
+ * @private
+ */
+ isPropertyEditable_: function(property) {
+ return !this.isNetworkPolicyEnforced(property) &&
+ !this.isExtensionControlled(property);
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ isShared_: function() {
+ return this.networkProperties.Source == 'Device' ||
+ this.networkProperties.Source == 'DevicePolicy';
+ },
+
+ /**
+ * @return {boolean}
+ * @private
+ */
+ isSaveManualProxyEnabled_: function() {
+ if (!this.proxyModified_)
+ return false;
+ var manual = this.proxy_.Manual;
+ var httpHost = this.get('HTTPProxy.Host', manual);
+ if (this.useSameProxy_)
+ return !!httpHost;
+ return !!httpHost || !!this.get('SecureHTTPProxy.Host', manual) ||
+ !!this.get('FTPProxy.Host', manual) || !!this.get('SOCKS.Host', manual);
+ },
+
+ /**
+ * @param {string} property The property to test
+ * @param {string} value The value to test against
+ * @return {boolean} True if property == value
+ * @private
+ */
+ matches_: function(property, value) {
+ return property == value;
+ },
+});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy_exclusions.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy_exclusions.html
new file mode 100644
index 00000000000..f574252c285
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy_exclusions.html
@@ -0,0 +1,37 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/icons.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-flex-layout/iron-flex-layout-classes.html">
+<link rel="import" href="network_shared_css.html">
+
+<dom-module id="network-proxy-exclusions">
+ <template>
+ <style include="network-shared cr-hidden-style iron-flex">
+ iron-icon {
+ @apply(--cr-actionable);
+ margin: 5px;
+ }
+
+ #container {
+ align-self: stretch;
+ border: 1px solid lightgrey;
+ height: 100px;
+ margin-top: 10px;
+ overflow-y: auto;
+ padding: 5px;
+ }
+ </style>
+ <div id="container">
+ <template is="dom-repeat" items="[[exclusions]]">
+ <div class="layout horizontal center" tabindex="0" >
+ <div class="flex">[[item]]</div>
+ <iron-icon class="favicon-image" icon="cr:clear"
+ on-tap="onRemoveTap_" tabindex="0" hidden="[[!editable]]">
+ </iron-icon>
+ </div>
+ </template>
+ </div>
+ </template>
+ <script src="network_proxy_exclusions.js"></script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy_exclusions.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy_exclusions.js
new file mode 100644
index 00000000000..347b22980d3
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy_exclusions.js
@@ -0,0 +1,46 @@
+// 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.
+
+/**
+ * @fileoverview Polymer element for displaying a list of proxy exclusions.
+ * Includes UI for adding, changing, and removing entries.
+ */
+
+(function() {
+
+Polymer({
+ is: 'network-proxy-exclusions',
+
+ properties: {
+ /** Whether or not the proxy values can be edited. */
+ editable: {
+ type: Boolean,
+ value: false,
+ },
+
+ /**
+ * The list of exclusions.
+ * @type {!Array<string>}
+ */
+ exclusions: {
+ type: Array,
+ value: function() {
+ return [];
+ },
+ notify: true
+ }
+ },
+
+ /**
+ * Event triggered when an item is removed.
+ * @param {!{model: !{index: number}}} event
+ * @private
+ */
+ onRemoveTap_: function(event) {
+ var index = event.model.index;
+ this.splice('exclusions', index, 1);
+ this.fire('proxy-change');
+ }
+});
+})();
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.html
new file mode 100644
index 00000000000..a1104bde59f
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.html
@@ -0,0 +1,50 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/html/i18n_behavior.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-input/iron-input.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-input/paper-input-container.html">
+<link rel="import" href="network_shared_css.html">
+
+<dom-module id="network-proxy-input">
+ <template>
+ <style include="network-shared">
+ paper-input-container {
+ -webkit-margin-start: 10px;
+ margin-bottom: -12px;
+ margin-top: -8px;
+ }
+
+ #container {
+ align-items: center;
+ display: flex;
+ flex: 0 1 auto;
+ flex-direction: row;
+ }
+
+ #label {
+ flex: 1;
+ }
+
+ #host {
+ width: 200px;
+ }
+
+ #port {
+ width: 50px;
+ }
+ </style>
+ <div id="container">
+ <div id="label">[[label]]</div>
+ <paper-input-container id="host" no-label-float>
+ <input is="iron-input" bind-value="{{value.Host}}"
+ disabled="[[!editable]]" on-change="onValueChange_">
+ </paper-input-container>
+ <div>[[i18n('networkProxyPort')]]</div>
+ <paper-input-container id="port" no-label-float>
+ <input is="iron-input" bind-value="{{value.Port}}"
+ disabled="[[!editable]]" on-change="onValueChange_">
+ </paper-input-container>
+ </div>
+ </template>
+ <script src="network_proxy_input.js"></script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.js b/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.js
new file mode 100644
index 00000000000..63609b074ce
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_proxy_input.js
@@ -0,0 +1,57 @@
+// 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.
+
+/**
+ * @fileoverview Polymer element for displaying and editing a single
+ * network proxy value. When the URL or port changes, a 'proxy-change' event is
+ * fired with the combined url and port values passed as a single string,
+ * url:port.
+ */
+Polymer({
+ is: 'network-proxy-input',
+
+ behaviors: [I18nBehavior],
+
+ properties: {
+ /**
+ * Whether or not the proxy value can be edited.
+ */
+ editable: {
+ type: Boolean,
+ value: false,
+ },
+
+ /**
+ * A label for the proxy value.
+ */
+ label: {
+ type: String,
+ value: 'Proxy',
+ },
+
+ /**
+ * The proxy object.
+ * @type {!CrOnc.ProxyLocation}
+ */
+ value: {
+ type: Object,
+ value: function() {
+ return {Host: '', Port: 80};
+ },
+ notify: true,
+ },
+ },
+
+ /**
+ * Event triggered when an input value changes.
+ * @private
+ */
+ onValueChange_: function() {
+ var port = parseInt(this.value.Port, 10);
+ if (isNaN(port))
+ port = 80;
+ this.value.Port = port;
+ this.fire('proxy-change', {value: this.value});
+ }
+});
diff --git a/chromium/ui/webui/resources/cr_components/chromeos/network/network_shared_css.html b/chromium/ui/webui/resources/cr_components/chromeos/network/network_shared_css.html
new file mode 100644
index 00000000000..c235c50288d
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/chromeos/network/network_shared_css.html
@@ -0,0 +1,51 @@
+<link rel="import" href="chrome://resources/cr_elements/shared_style_css.html">
+
+ <!-- Common styles for network elements. -->
+
+<dom-module id="network-shared">
+ <template>
+ <style include="cr-shared-style">
+ .property-box {
+ @apply(--cr-section);
+ border-top: none;
+ min-height: var(--cr-section-two-line-min-height);
+ padding: 0;
+ }
+
+ .property-box.indented {
+ -webkit-margin-start: var(--cr-section-padding);
+ }
+
+ .property-box.single-column {
+ align-items: flex-start;
+ flex-direction: column;
+ justify-content: center;
+ }
+
+ .property-box.stretch {
+ align-items: stretch;
+ }
+
+ .property-box > .start {
+ align-items: center;
+ flex: auto;
+ }
+
+ .property-box > .middle {
+ -webkit-padding-start: 16px;
+ align-items: center;
+ flex: auto;
+ }
+
+ paper-input-container {
+ --paper-input-container-input: {
+ color: var(--paper-grey-600);
+ font-size: inherit;
+ font-weight: 400;
+ };
+ margin-bottom: 0;
+ margin-top: -9px;
+ }
+ </style>
+ </template>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_components/compiled_resources2.gyp b/chromium/ui/webui/resources/cr_components/compiled_resources2.gyp
new file mode 100644
index 00000000000..eb688de9083
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components/compiled_resources2.gyp
@@ -0,0 +1,15 @@
+# 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.
+{
+ 'targets': [
+ {
+ 'target_name': 'cr_components_resources',
+ 'type': 'none',
+ 'dependencies': [
+ 'chromeos/compiled_resources2.gyp:*',
+ 'certificate_manager/compiled_resources2.gyp:*',
+ ],
+ },
+ ]
+}
diff --git a/chromium/ui/webui/resources/cr_components_resources.grdp b/chromium/ui/webui/resources/cr_components_resources.grdp
new file mode 100644
index 00000000000..164e20e627f
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_components_resources.grdp
@@ -0,0 +1,131 @@
+<?xml version="1.0" encoding="utf-8"?>
+<grit-part>
+ <if expr="use_nss_certs">
+ <structure name="IDR_WEBUI_CA_TRUST_EDIT_DIALOG_JS"
+ file="cr_components/certificate_manager/ca_trust_edit_dialog.js"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CA_TRUST_EDIT_DIALOG_HTML"
+ file="cr_components/certificate_manager/ca_trust_edit_dialog.html"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CERTIFICATE_DELETE_CONFIRMATION_DIALOG_JS"
+ file="cr_components/certificate_manager/certificate_delete_confirmation_dialog.js"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CERTIFICATE_DELETE_CONFIRMATION_DIALOG_HTML"
+ file="cr_components/certificate_manager/certificate_delete_confirmation_dialog.html"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CERTIFICATE_MANAGER_HTML"
+ file="cr_components/certificate_manager/certificate_manager.html"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CERTIFICATE_MANAGER_JS"
+ file="cr_components/certificate_manager/certificate_manager.js"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CERTIFICATE_PASSWORD_ENCRYPTION_DIALOG_JS"
+ file="cr_components/certificate_manager/certificate_password_encryption_dialog.js"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CERTIFICATE_PASSWORD_ENCRYPTION_DIALOG_HTML"
+ file="cr_components/certificate_manager/certificate_password_encryption_dialog.html"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CERTIFICATE_PASSWORD_DECRYPTION_DIALOG_JS"
+ file="cr_components/certificate_manager/certificate_password_decryption_dialog.js"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CERTIFICATE_PASSWORD_DECRYPTION_DIALOG_HTML"
+ file="cr_components/certificate_manager/certificate_password_decryption_dialog.html"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CERTIFICATES_ERROR_DIALOG_JS"
+ file="cr_components/certificate_manager/certificates_error_dialog.js"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CERTIFICATES_ERROR_DIALOG_HTML"
+ file="cr_components/certificate_manager/certificates_error_dialog.html"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CERTIFICATE_ENTRY_HTML"
+ file="cr_components/certificate_manager/certificate_entry.html"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CERTIFICATE_ENTRY_JS"
+ file="cr_components/certificate_manager/certificate_entry.js"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CERTIFICATE_LIST_HTML"
+ file="cr_components/certificate_manager/certificate_list.html"
+ preprocess="true"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CERTIFICATE_LIST_JS"
+ file="cr_components/certificate_manager/certificate_list.js"
+ preprocess="true"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CERTIFICATE_MANAGER_TYPES_HTML"
+ file="cr_components/certificate_manager/certificate_manager_types.html"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CERTIFICATE_MANAGER_TYPES_JS"
+ file="cr_components/certificate_manager/certificate_manager_types.js"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CERTIFICATE_SHARED_CSS_HTML"
+ file="cr_components/certificate_manager/certificate_shared_css.html"
+ type="chrome_html"
+ preprocess="true" />
+ <structure name="IDR_WEBUI_CERTIFICATE_SUBENTRY_HTML"
+ file="cr_components/certificate_manager/certificate_subentry.html"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CERTIFICATE_SUBENTRY_JS"
+ file="cr_components/certificate_manager/certificate_subentry.js"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CERTIFICATES_BROWSER_PROXY_HTML"
+ file="cr_components/certificate_manager/certificates_browser_proxy.html"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CERTIFICATES_BROWSER_PROXY_JS"
+ file="cr_components/certificate_manager/certificates_browser_proxy.js"
+ type="chrome_html" />
+ </if>
+ <if expr="chromeos">
+ <!-- Chrome OS Custom Elements -->
+ <structure name="IDR_WEBUI_CHROMEOS_BLUETOOTH_DIALOG_HTML"
+ file="cr_components/chromeos/bluetooth_dialog.html"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CHROMEOS_BLUETOOTH_DIALOG_JS"
+ file="cr_components/chromeos/bluetooth_dialog.js"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CHROMEOS_NETWORK_APNLIST_HTML"
+ file="cr_components/chromeos/network/network_apnlist.html"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CHROMEOS_NETWORK_APNLIST_JS"
+ file="cr_components/chromeos/network/network_apnlist.js"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CHROMEOS_NETWORK_IP_CONFIG_HTML"
+ file="cr_components/chromeos/network/network_ip_config.html"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CHROMEOS_NETWORK_IP_CONFIG_JS"
+ file="cr_components/chromeos/network/network_ip_config.js"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CHROMEOS_NETWORK_NAMESERVERS_HTML"
+ file="cr_components/chromeos/network/network_nameservers.html"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CHROMEOS_NETWORK_NAMESERVERS_JS"
+ file="cr_components/chromeos/network/network_nameservers.js"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CHROMEOS_NETWORK_PROPERTY_LIST_HTML"
+ file="cr_components/chromeos/network/network_property_list.html"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CHROMEOS_NETWORK_PROPERTY_LIST_JS"
+ file="cr_components/chromeos/network/network_property_list.js"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CHROMEOS_NETWORK_PROXY_HTML"
+ file="cr_components/chromeos/network/network_proxy.html"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CHROMEOS_NETWORK_PROXY_JS"
+ file="cr_components/chromeos/network/network_proxy.js"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CHROMEOS_NETWORK_PROXY_EXCLUSIONS_HTML"
+ file="cr_components/chromeos/network/network_proxy_exclusions.html"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CHROMEOS_NETWORK_PROXY_EXCLUSIONS_JS"
+ file="cr_components/chromeos/network/network_proxy_exclusions.js"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CHROMEOS_NETWORK_PROXY_INPUT_HTML"
+ file="cr_components/chromeos/network/network_proxy_input.html"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CHROMEOS_NETWORK_PROXY_INPUT_JS"
+ file="cr_components/chromeos/network/network_proxy_input.js"
+ type="chrome_html" />
+ <structure name="IDR_WEBUI_CHROMEOS_NETWORK_SHARED_CSS_HTML"
+ file="cr_components/chromeos/network/network_shared_css.html"
+ type="chrome_html" />
+ </if>
+</grit-part>
diff --git a/chromium/ui/webui/resources/cr_elements/OWNERS b/chromium/ui/webui/resources/cr_elements/OWNERS
index 057813143a1..5fd1662abb6 100644
--- a/chromium/ui/webui/resources/cr_elements/OWNERS
+++ b/chromium/ui/webui/resources/cr_elements/OWNERS
@@ -1,2 +1,3 @@
michaelpg@chromium.org
+scottchen@chromium.org
stevenjb@chromium.org
diff --git a/chromium/ui/webui/resources/cr_elements/READE.md b/chromium/ui/webui/resources/cr_elements/READE.md
new file mode 100644
index 00000000000..b8b47ef98b3
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/READE.md
@@ -0,0 +1,16 @@
+This directory contains simple Polymer web components for Web UI. These
+components may be shared across any WebUI and should be compatible across
+all platforms (including ios).
+
+These web components may not contain any i18n dependencies and may not use
+I18nBehavior. Instead, any text (labels, tooltips, etc) should be passed as
+properties.
+
+These web components should avoid the use of chrome.send and should generally
+avoid dependencies on extension APIs as well.
+
+TODO(stevenjb/dpapad): Audit elements currently using chrome.settingsPrivate
+and chrome.networkingPrivate and decide whether to move these or update the
+guidelines.
+
+For more complex components, see cr_components.
diff --git a/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.html b/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.html
index d2e3639bbe8..abc2e47ac82 100644
--- a/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.html
+++ b/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.html
@@ -80,7 +80,7 @@
src="[[getImgSrc_(profileImageUrl_)]]"
hidden="[[!profileImageUrl_]]"
srcset="[[getImgSrc2x_(profileImageUrl_)]]"
- title="[[profileImageLoadingLabel]]">
+ title="[[profileImageLabel]]">
<!-- Shows and selects the previously selected ('old') picture. -->
<img id="oldImage" role="radio"
data-type$="[[selectionTypesEnum_.OLD]]"
diff --git a/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.js b/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.js
index c9cb62fb793..990aaf67fbb 100644
--- a/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.js
+++ b/chromium/ui/webui/resources/cr_elements/chromeos/cr_picture/cr_picture_list.js
@@ -28,7 +28,6 @@ Polymer({
chooseFileLabel: String,
oldImageLabel: String,
profileImageLabel: String,
- profileImageLoadingLabel: String,
takePhotoLabel: String,
/**
diff --git a/chromium/ui/webui/resources/cr_elements/chromeos/network/cr_network_list_item.js b/chromium/ui/webui/resources/cr_elements/chromeos/network/cr_network_list_item.js
index 5e3992a5705..eb4d0dff4c5 100644
--- a/chromium/ui/webui/resources/cr_elements/chromeos/network/cr_network_list_item.js
+++ b/chromium/ui/webui/resources/cr_elements/chromeos/network/cr_network_list_item.js
@@ -108,6 +108,10 @@ Polymer({
if (!this.isStateTextVisible_())
return '';
var state = this.networkState.ConnectionState;
+ // For Cellular, an empty ConnectionState indicates that the device is
+ // still initializing.
+ if (!state && this.networkState.Type == CrOnc.Type.CELLULAR)
+ return CrOncStrings.networkListItemInitializing;
if (state == CrOnc.ConnectionState.CONNECTED)
return CrOncStrings.networkListItemConnected;
if (state == CrOnc.ConnectionState.CONNECTING)
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 0349141de90..4b98c6fff97 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
@@ -108,24 +108,55 @@ Polymer({
},
/**
- * Request the list of visible networks. May be called externally to force a
+ * Requests the device and network states. May be called externally to force a
* refresh and list update (e.g. when the element is shown).
*/
refreshNetworks: function() {
+ chrome.networkingPrivate.getDeviceStates(
+ this.getDeviceStatesCallback_.bind(this));
+ },
+
+ /**
+ * @param {!Array<!CrOnc.DeviceStateProperties>} deviceStates
+ * @private
+ */
+ getDeviceStatesCallback_: function(deviceStates) {
+ var uninitializedCellular = deviceStates.find(function(device) {
+ return device.Type == CrOnc.Type.CELLULAR &&
+ device.State == CrOnc.DeviceState.UNINITIALIZED;
+ });
+ this.getNetworkStates_(uninitializedCellular);
+ },
+
+ /**
+ * @param {!CrOnc.DeviceStateProperties|undefined} uninitializedCellular
+ * A cellular device state to pass to |getNetworksCallback_| or undefined.
+ */
+ getNetworkStates_: function(uninitializedCellular) {
var filter = {
networkType: chrome.networkingPrivate.NetworkType.ALL,
visible: true,
configured: false
};
- chrome.networkingPrivate.getNetworks(
- filter, this.getNetworksCallback_.bind(this));
+ chrome.networkingPrivate.getNetworks(filter, function(states) {
+ this.getNetworksCallback_(uninitializedCellular, states);
+ }.bind(this));
},
/**
+ * @param {!CrOnc.DeviceStateProperties|undefined} uninitializedCellular
+ * If defined, prepends a Cellular state with no ConnectionState to
+ * represent an uninitialized Cellular device.
* @param {!Array<!CrOnc.NetworkStateProperties>} states
* @private
*/
- getNetworksCallback_: function(states) {
+ getNetworksCallback_: function(uninitializedCellular, states) {
+ if (uninitializedCellular) {
+ states.unshift({
+ GUID: '',
+ Type: uninitializedCellular.Type,
+ });
+ }
this.networkStateList_ = states;
var defaultState = (this.networkStateList_.length > 0 &&
this.networkStateList_[0].ConnectionState ==
diff --git a/chromium/ui/webui/resources/cr_elements/chromeos/network/cr_onc_types.js b/chromium/ui/webui/resources/cr_elements/chromeos/network/cr_onc_types.js
index 8382119b6d4..4c51796778b 100644
--- a/chromium/ui/webui/resources/cr_elements/chromeos/network/cr_onc_types.js
+++ b/chromium/ui/webui/resources/cr_elements/chromeos/network/cr_onc_types.js
@@ -29,6 +29,7 @@
* networkListItemConnected: string,
* networkListItemConnecting: string,
* networkListItemConnectingTo: string,
+ * networkListItemInitializing: string,
* networkListItemNotConnected: string,
* vpnNameTemplate: string,
* }}
diff --git a/chromium/ui/webui/resources/cr_elements/compiled_resources2.gyp b/chromium/ui/webui/resources/cr_elements/compiled_resources2.gyp
index cd7896afb8d..89de6886a21 100644
--- a/chromium/ui/webui/resources/cr_elements/compiled_resources2.gyp
+++ b/chromium/ui/webui/resources/cr_elements/compiled_resources2.gyp
@@ -13,6 +13,7 @@
'cr_dialog/compiled_resources2.gyp:*',
'cr_drawer/compiled_resources2.gyp:*',
'cr_expand_button/compiled_resources2.gyp:*',
+ 'cr_link_row/compiled_resources2.gyp:*',
'cr_profile_avatar_selector/compiled_resources2.gyp:*',
'policy/compiled_resources2.gyp:*',
],
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 3fb14c427f5..05ca3cc16ce 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
@@ -1,7 +1,8 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
<link rel="import" href="chrome://resources/html/assert.html">
<link rel="import" href="chrome://resources/html/cr/ui/focus_without_ink.html">
<link rel="import" href="chrome://resources/html/util.html">
-<link rel="import" href="chrome://resources/html/polymer.html">
<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
<dom-module id="cr-action-menu">
@@ -23,6 +24,7 @@
:host ::content .dropdown-item {
background: none;
border: none;
+ border-radius: 0;
box-sizing: border-box;
color: var(--paper-grey-900);
font: inherit;
@@ -55,8 +57,8 @@
outline: none;
}
</style>
- <div class="item-wrapper" tabindex="-1">
- <content select=".dropdown-item,hr"></content>
+ <div class="item-wrapper" tabindex="-1" role="menu">
+ <content select=".dropdown-item,hr" id="contentNode"></content>
</div>
</template>
<script src="cr_action_menu.js"></script>
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 181936d7132..d524c5433cf 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
@@ -30,6 +30,9 @@ var AnchorAlignment = {
AFTER_END: 2,
};
+/** @const {string} */
+var DROPDOWN_ITEM_CLASS = 'dropdown-item';
+
(function() {
/**
* Returns the point to start along the X or Y axis given a start and end
@@ -118,6 +121,9 @@ Polymer({
/** @private {boolean} */
hasMousemoveListener_: false,
+ /** @private {?PolymerDomApi.ObserveHandle} */
+ contentObserver_: null,
+
hostAttributes: {
tabindex: 0,
},
@@ -137,6 +143,10 @@ Polymer({
removeListeners_: function() {
window.removeEventListener('resize', this.boundClose_);
window.removeEventListener('popstate', this.boundClose_);
+ if (this.contentObserver_) {
+ Polymer.dom(this.$.contentNode).unobserveNodes(this.contentObserver_);
+ this.contentObserver_ = null;
+ }
},
/**
@@ -321,7 +331,7 @@ Polymer({
// Restore the scroll position.
doc.scrollTop = scrollTop;
doc.scrollLeft = scrollLeft;
- this.addCloseListeners_();
+ this.addListeners_();
},
/** @private */
@@ -369,13 +379,24 @@ Polymer({
/**
* @private
*/
- addCloseListeners_: function() {
+ addListeners_: function() {
this.boundClose_ = this.boundClose_ || function() {
if (this.open)
this.close();
}.bind(this);
window.addEventListener('resize', this.boundClose_);
window.addEventListener('popstate', this.boundClose_);
+
+ this.contentObserver_ =
+ Polymer.dom(this.$.contentNode).observeNodes((info) => {
+ info.addedNodes.forEach((node) => {
+ if (node.classList &&
+ node.classList.contains(DROPDOWN_ITEM_CLASS) &&
+ !node.getAttribute('role')) {
+ node.setAttribute('role', 'menuitem');
+ }
+ });
+ });
},
});
})();
diff --git a/chromium/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html b/chromium/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html
index bb556e458e8..2d5528b32dc 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html
+++ b/chromium/ui/webui/resources/cr_elements/cr_dialog/cr_dialog.html
@@ -13,12 +13,13 @@
--scroll-border: 1px solid var(--paper-grey-300);
border: 0;
border-radius: 2px;
- bottom: 0;
+ bottom: 50%;
box-shadow: 0 0 16px rgba(0, 0, 0, 0.12),
0 16px 16px rgba(0, 0, 0, 0.24);
color: inherit;
+ overflow-y: hidden;
padding: 0;
- top: 0;
+ top: 50%;
width: 512px;
}
@@ -55,6 +56,7 @@
font-size: calc(15 / 13 * 100%);
line-height: 1;
padding: 16px 16px;
+ @apply(--cr-dialog-title);
}
:host ::slotted([slot=button-container]) {
@@ -95,7 +97,7 @@
.top-container {
align-items: flex-start;
display: flex;
- min-height: 47px;
+ min-height: var(--cr-dialog-top-container-min-height, 47px);
}
.title-container {
@@ -127,6 +129,7 @@
on-keypress="onCloseKeypress_">
</button>
</div>
+ <slot name="header"></slot>
<div class="body-container">
<span id="bodyTopMarker"></span>
<slot name="body"></slot>
diff --git a/chromium/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html b/chromium/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html
index 20d15055f7b..ad9d19fdcf8 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html
+++ b/chromium/ui/webui/resources/cr_elements/cr_drawer/cr_drawer.html
@@ -64,14 +64,14 @@
outline: none;
}
- :host ::content .drawer-content {
+ :host ::slotted(.drawer-content) {
height: calc(100% - 56px);
overflow: auto;
}
</style>
<div id="container" on-tap="onContainerTap_">
<div class="drawer-header" tabindex="-1">[[heading]]</div>
- <content></content>
+ <slot></slot>
</div>
</template>
</dom-module>
diff --git a/chromium/ui/webui/resources/cr_elements/cr_icons_css.html b/chromium/ui/webui/resources/cr_elements/cr_icons_css.html
index 6428c757957..77f613fcf69 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_icons_css.html
+++ b/chromium/ui/webui/resources/cr_elements/cr_icons_css.html
@@ -5,7 +5,7 @@
<template>
<style>
:host-context([dir=rtl]) button[is='paper-icon-button-light'] {
- transform: scaleX(-1); /* Flip on the X axis (aka mirror). */
+ transform: scaleX(-1); /* Invert X: flip on the Y axis (aka mirror). */
}
button[is='paper-icon-button-light'] {
@@ -18,6 +18,15 @@
width: var(--cr-icon-ripple-size);
}
+ button[is='paper-icon-button-light'].no-overlap {
+ margin-left: 0;
+ margin-right: 0;
+ }
+
+ button[is='paper-icon-button-light'].icon-arrow-back {
+ background-image: url(../images/icon_arrow_back.svg);
+ }
+
button[is='paper-icon-button-light'].icon-cancel {
background-image: url(../images/icon_cancel.svg);
}
@@ -50,10 +59,18 @@
background-image: url(../images/open_in_new.svg);
}
+ button[is='paper-icon-button-light'].icon-menu-white {
+ background-image: url(../images/icon_menu_white.svg);
+ }
+
button[is='paper-icon-button-light'].icon-more-vert {
background-image: url(../images/icon_more_vert.svg);
}
+ button[is='paper-icon-button-light'].icon-refresh {
+ background-image: url(../images/icon_refresh.svg);
+ }
+
button[is='paper-icon-button-light'].icon-settings {
background-image: url(../images/icon_settings.svg);
}
diff --git a/chromium/ui/webui/resources/js/chromeos/compiled_resources2.gyp b/chromium/ui/webui/resources/cr_elements/cr_link_row/compiled_resources2.gyp
index a363475a954..11ed485f750 100644
--- a/chromium/ui/webui/resources/js/chromeos/compiled_resources2.gyp
+++ b/chromium/ui/webui/resources/cr_elements/cr_link_row/compiled_resources2.gyp
@@ -1,15 +1,13 @@
-# Copyright 2014 The Chromium Authors. All rights reserved.
+# 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.
{
'targets': [
{
- 'target_name': 'ui_account_tweaks',
+ 'target_name': 'cr_link_row',
'dependencies': [
- '../compiled_resources2.gyp:cr',
- '../compiled_resources2.gyp:load_time_data',
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
- ]
+ ],
}
diff --git a/chromium/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html b/chromium/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html
new file mode 100644
index 00000000000..0ea10f6da08
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.html
@@ -0,0 +1,74 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html">
+<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-styles/default-theme.html">
+
+<dom-module id="cr-link-row">
+ <template strip-whitespace="">
+ <style include="cr-hidden-style cr-icons">
+ :host {
+ background: none;
+ border: none;
+ color: inherit;
+ cursor: pointer;
+ font-size: 100%; /* Specifically for Mac OSX, harmless elsewhere. */
+ line-height: 154%; /* 20px. */
+ margin: 0;
+ outline: none;
+ padding: 0;
+ position: relative;
+ width: 100%;
+ @apply(--cr-section);
+ }
+
+ :host(.continuation),
+ :host(.first) {
+ border-top: none;
+ }
+
+ :host([disabled]) {
+ color: var(--paper-grey-500);
+ cursor: auto;
+ pointer-events: none;
+ }
+
+ #label,
+ #subLabel {
+ display: flex;
+ }
+
+ #labelWrapper {
+ flex: 1;
+ flex-basis: 0.000000001px;
+ }
+
+ #outer {
+ align-items: center;
+ display: flex;
+ min-height: var(--cr-section-two-line-min-height);
+ width: 100%;
+ }
+
+ #outer[noSubLabel] {
+ min-height: var(--cr-section-min-height);
+ }
+
+ #subLabel {
+ /* TODO(dschuyler): replace with: @apply(--cr-secondary-text); */
+ color: var(--paper-grey-600);
+ font-weight: 400;
+ }
+ </style>
+ <div id="outer" noSubLabel$="[[!subLabel]]">
+ <div id="labelWrapper" hidden="[[!label]]">
+ <div id="label" class="label">[[label]]</div>
+ <div id="subLabel" class="secondary label">[[subLabel]]</div>
+ </div>
+ <button class$="[[iconClass]]" is="paper-icon-button-light"></button>
+ </div>
+ </template>
+ <script src="cr_link_row.js"></script>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.js b/chromium/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.js
new file mode 100644
index 00000000000..e700b6d9c2d
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/cr_link_row/cr_link_row.js
@@ -0,0 +1,27 @@
+// 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.
+
+/**
+ * @fileoverview
+ * A link row is a UI element similar to a button, though usually wider than a
+ * button (taking up the whole 'row'). The name link comes from the intended use
+ * of this element to take the user to another page in the app or to an external
+ * page (somewhat like an HTML link).
+ */
+Polymer({
+ is: 'cr-link-row',
+ extends: 'button',
+
+ properties: {
+ iconClass: String,
+
+ label: String,
+
+ subLabel: {
+ type: String,
+ /* Value used for noSubLabel attribute. */
+ value: '',
+ },
+ },
+});
diff --git a/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html b/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html
index 9c37afe5501..29b9923b515 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html
+++ b/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html
@@ -44,7 +44,7 @@
ignore-modified-key-events="[[ignoreModifiedKeyEvents]]">
<template is="dom-repeat" items="[[avatars]]">
<paper-button class="avatar" title="[[item.label]]"
- style$="background-image: [[getIconImageset_(item.url)]]"
+ style$="background-image: [[getIconImageSet_(item.url)]]"
on-tap="onAvatarTap_">
</paper-button>
</template>
diff --git a/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.js b/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.js
index c09ce793656..28c58de1449 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.js
@@ -49,10 +49,10 @@ Polymer({
/**
* @param {string} iconUrl
- * @return {string} A CSS imageset for multiple scale factors.
+ * @return {string} A CSS image-set for multiple scale factors.
* @private
*/
- getIconImageset_: function(iconUrl) {
+ getIconImageSet_: function(iconUrl) {
return cr.icon.getImage(iconUrl);
},
diff --git a/chromium/ui/webui/resources/cr_elements/cr_scrollable_behavior.js b/chromium/ui/webui/resources/cr_elements/cr_scrollable_behavior.js
index 2a497807d95..9535c1a9b40 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_scrollable_behavior.js
+++ b/chromium/ui/webui/resources/cr_elements/cr_scrollable_behavior.js
@@ -63,7 +63,7 @@ var CrScrollableBehavior = {
*/
updateScrollableContents: function() {
if (this.intervalId_ !== null)
- return; // notifyResize is arelady in progress.
+ return; // notifyResize is already in progress.
this.requestUpdateScroll();
@@ -93,7 +93,7 @@ var CrScrollableBehavior = {
},
/**
- * Setup the intial scrolling related classes for each scrollable container.
+ * Setup the initial scrolling related classes for each scrollable container.
* Called from ready() and updateScrollableContents(). May also be called
* directly when the contents change (e.g. when not using iron-list).
*/
@@ -119,7 +119,7 @@ var CrScrollableBehavior = {
this.async(function() {
var scrollTop = list.savedScrollTops.shift();
// Ignore scrollTop of 0 in case it was intermittent (we do not need to
- // explicity scroll to 0).
+ // explicitly scroll to 0).
if (scrollTop != 0)
list.scroll(0, scrollTop);
});
@@ -136,7 +136,8 @@ var CrScrollableBehavior = {
},
/**
- * This gets called once intially and any time a scrollable container scrolls.
+ * This gets called once initially and any time a scrollable container
+ * scrolls.
* @param {!HTMLElement} scrollable
* @private
*/
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 491bbb53d60..9646f99e0be 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
@@ -33,9 +33,8 @@ var CrSearchFieldBehavior = {
},
/**
- * @abstract
* @return {!HTMLInputElement} The input field element the behavior should
- * use.
+ * use.
*/
getSearchInput: function() {},
diff --git a/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.html b/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.html
index bfbe0c97fc8..b53e5f65276 100644
--- a/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.html
+++ b/chromium/ui/webui/resources/cr_elements/cr_toolbar/cr_toolbar.html
@@ -1,11 +1,13 @@
<link rel="import" href="chrome://resources/html/polymer.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/iron-media-query/iron-media-query.html">
-<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button.html">
+
+<link rel="import" href="chrome://resources/cr_elements/cr_icons_css.html">
<link rel="import" href="chrome://resources/cr_elements/cr_toolbar/cr_toolbar_search_field.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/iron-media-query/iron-media-query.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-icon-button/paper-icon-button-light.html">
<dom-module id="cr-toolbar">
<template>
- <style>
+ <style include="cr-icons">
:host {
--cr-toolbar-field-width: 580px;
--cr-toolbar-height: 56px;
@@ -22,9 +24,7 @@
flex: 1;
font-size: 123%;
font-weight: 400;
- overflow: hidden;
- text-overflow: ellipsis;
- white-space: nowrap;
+ line-height: normal;
}
#leftContent {
@@ -130,11 +130,12 @@
<div id="leftSpacer">
<!-- Note: showing #menuPromo relies on this dom-if being [restamp]. -->
<template is="dom-if" if="[[showMenu]]" restamp>
- <paper-icon-button id="menuButton" icon="cr20:menu"
+ <button id="menuButton" is="paper-icon-button-light"
+ class="icon-menu-white no-overlap"
on-tap="onMenuTap_"
title="[[titleIfNotShowMenuPromo_(menuLabel, showMenuPromo)]]"
aria-label$="[[menuLabel]]">
- </paper-icon-button>
+ </button>
<template is="dom-if" if="[[showMenuPromo]]">
<div id="menuPromo" role="tooltip">
[[menuPromo]]
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 5b389334c39..dd002fb9c28 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
@@ -151,7 +151,6 @@
on-blur="onInputBlur_"
incremental
autofocus>
- </input>
</div>
<template is="dom-if" if="[[hasSearchText]]">
<button is="paper-icon-button-light" class="icon-cancel-toolbar"
diff --git a/chromium/ui/webui/resources/cr_elements/icons.html b/chromium/ui/webui/resources/cr_elements/icons.html
index 40e08ef742e..bc0eae71ea2 100644
--- a/chromium/ui/webui/resources/cr_elements/icons.html
+++ b/chromium/ui/webui/resources/cr_elements/icons.html
@@ -17,7 +17,6 @@ blurry at 20 px). Please use 20 px icons when available.
Keep these in sorted order by id="". See also http://goo.gl/Y1OdAq
-->
<g id="domain"><path d="M2,3 L2,17 L11.8267655,17 L13.7904799,17 L18,17 L18,7 L12,7 L12,3 L2,3 Z M8,13 L10,13 L10,15 L8,15 L8,13 Z M4,13 L6,13 L6,15 L4,15 L4,13 Z M8,9 L10,9 L10,11 L8,11 L8,9 Z M4,9 L6,9 L6,11 L4,11 L4,9 Z M12,9 L16,9 L16,15 L12,15 L12,9 Z M12,11 L14,11 L14,13 L12,13 L12,11 Z M8,5 L10,5 L10,7 L8,7 L8,5 Z M4,5 L6,5 L6,7 L4,7 L4,5 Z"></path></g>
- <g id="menu"><rect x="2" y="4" width="16" height="2"></rect><rect x="2" y="9" width="16" height="2"></rect><rect x="2" y="14" width="16" height="2"></rect></g>
</svg>
</iron-iconset-svg>
<iron-iconset-svg name="cr" size="24">
@@ -34,6 +33,7 @@ blurry at 20 px). Please use 20 px icons when available.
<g id="camera-alt"><circle cx="12" cy="12" r="3.2"></circle><path d="M9 2L7.17 4H4c-1.1 0-2 .9-2 2v12c0 1.1.9 2 2 2h16c1.1 0 2-.9 2-2V6c0-1.1-.9-2-2-2h-3.17L15 2H9zm3 15c-2.76 0-5-2.24-5-5s2.24-5 5-5 5 2.24 5 5-2.24 5-5 5z"></path></g>
<g id="check"><path d="M9 16.17L4.83 12l-1.42 1.41L9 19 21 7l-1.41-1.41z"></path></g>
</if>
+ <g id="account-child-invert" viewBox="0 0 48 48"><path d="M24 4c3.31 0 6 2.69 6 6s-2.69 6-6 6-6-2.69-6-6 2.69-6 6-6z"></path><path fill="none" d="M0 0h48v48H0V0z"></path><circle fill="none" cx="24" cy="26" r="4"></circle><path d="M24 18c-6.16 0-13 3.12-13 7.23v11.54c0 2.32 2.19 4.33 5.2 5.63 2.32 1 5.12 1.59 7.8 1.59.66 0 1.33-.06 2-.14v-5.2c-.67.08-1.34.14-2 .14-2.63 0-5.39-.57-7.68-1.55.67-2.12 4.34-3.65 7.68-3.65.86 0 1.75.11 2.6.29 2.79.62 5.2 2.15 5.2 4.04v4.47c3.01-1.31 5.2-3.31 5.2-5.63V25.23C37 21.12 30.16 18 24 18zm0 12c-2.21 0-4-1.79-4-4s1.79-4 4-4 4 1.79 4 4-1.79 4-4 4z"></path></g>
<g id="chevron-right"><path d="M10 6L8.59 7.41 13.17 12l-4.58 4.59L10 18l6-6z"></path></g>
<g id="clear"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g>
<g id="close"><path d="M19 6.41L17.59 5 12 10.59 6.41 5 5 6.41 10.59 12 5 17.59 6.41 19 12 13.41 17.59 19 19 17.59 13.41 12z"></path></g>
@@ -55,6 +55,7 @@ blurry at 20 px). Please use 20 px icons when available.
suffix prevents the naming conflict. -->
<g id="settings_icon"><path d="M19.43 12.98c.04-.32.07-.64.07-.98s-.03-.66-.07-.98l2.11-1.65c.19-.15.24-.42.12-.64l-2-3.46c-.12-.22-.39-.3-.61-.22l-2.49 1c-.52-.4-1.08-.73-1.69-.98l-.38-2.65C14.46 2.18 14.25 2 14 2h-4c-.25 0-.46.18-.49.42l-.38 2.65c-.61.25-1.17.59-1.69.98l-2.49-1c-.23-.09-.49 0-.61.22l-2 3.46c-.13.22-.07.49.12.64l2.11 1.65c-.04.32-.07.65-.07.98s.03.66.07.98l-2.11 1.65c-.19.15-.24.42-.12.64l2 3.46c.12.22.39.3.61.22l2.49-1c.52.4 1.08.73 1.69.98l.38 2.65c.03.24.24.42.49.42h4c.25 0 .46-.18.49-.42l.38-2.65c.61-.25 1.17-.59 1.69-.98l2.49 1c.23.09.49 0 .61-.22l2-3.46c.12-.22.07-.49-.12-.64l-2.11-1.65zM12 15.5c-1.93 0-3.5-1.57-3.5-3.5s1.57-3.5 3.5-3.5 3.5 1.57 3.5 3.5-1.57 3.5-3.5 3.5z"></path></g>
<g id="star"><path d="M12 17.27L18.18 21l-1.64-7.03L22 9.24l-7.19-.61L12 2 9.19 8.63 2 9.24l5.46 4.73L5.82 21z"></path></g>
+ <g id="supervisor-account" viewBox="0 0 48 48"><path d="M0 0h48v48H0z" fill="none"></path><path d="M33 24c2.76 0 4.98-2.24 4.98-5s-2.22-5-4.98-5c-2.76 0-5 2.24-5 5s2.24 5 5 5zm-15-2c3.31 0 5.98-2.69 5.98-6s-2.67-6-5.98-6c-3.31 0-6 2.69-6 6s2.69 6 6 6zm15 6c-3.67 0-11 1.84-11 5.5V38h22v-4.5c0-3.66-7.33-5.5-11-5.5zm-15-2c-4.67 0-14 2.34-14 7v5h14v-4.5c0-1.7.67-4.67 4.74-6.94C21 26.19 19.31 26 18 26z"></path></g>
<g id="warning"><path d="M1 21h22L12 2 1 21zm12-3h-2v-2h2v2zm0-4h-2v-4h2v4z"></path></g>
</defs>
</svg>
diff --git a/chromium/ui/webui/resources/cr_elements/paper_checkbox_style_css.html b/chromium/ui/webui/resources/cr_elements/paper_checkbox_style_css.html
new file mode 100644
index 00000000000..6aab514b762
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/paper_checkbox_style_css.html
@@ -0,0 +1,19 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<!-- Common paper-checkbox styling for Material Design WebUI. -->
+<dom-module id="paper-checkbox-style">
+ <template>
+ <style>
+ paper-checkbox {
+ --paper-checkbox-checked-color: var(--google-blue-500);
+ --paper-checkbox-ink-size: 40px;
+ --paper-checkbox-label-color: inherit;
+ --paper-checkbox-label-spacing: 20px;
+ --paper-checkbox-size: 16px;
+ --paper-checkbox-unchecked-color: var(--paper-grey-600);
+ -webkit-margin-start: 2px;
+ }
+ </style>
+ </template>
+</dom-module>
+
diff --git a/chromium/ui/webui/resources/cr_elements/paper_toggle_style_css.html b/chromium/ui/webui/resources/cr_elements/paper_toggle_style_css.html
new file mode 100644
index 00000000000..95581fd1707
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/paper_toggle_style_css.html
@@ -0,0 +1,42 @@
+<link rel="import" href="chrome://resources/html/polymer.html">
+
+<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
+
+<!-- Common paper-button styling for Material Design WebUI. -->
+<dom-module id="paper-toggle-style">
+ <template>
+ <style>
+ :root {
+ --cr-toggle-bar-size: {
+ height: 12px;
+ left: 4px;
+ width: 28px;
+ };
+ --cr-toggle-button-size: {
+ box-shadow: 0 1px 3px 0 rgba(0, 0, 0, 0.4);
+ height: 16px;
+ top: -2px;
+ width: 16px;
+ };
+ --cr-toggle-ink-size: {
+ height: 40px;
+ top: -12px;
+ left: -12px;
+ width: 40px;
+ };
+
+ --paper-toggle-button-checked-bar: var(--cr-toggle-bar-size);
+ --paper-toggle-button-checked-bar-color: var(--cr-toggle-color);
+ --paper-toggle-button-checked-button: {
+ @apply(--cr-toggle-button-size);
+ transform: translate(18px, 0);
+ };
+ --paper-toggle-button-checked-button-color: var(--cr-toggle-color);
+ --paper-toggle-button-label-spacing: 0;
+ --paper-toggle-button-unchecked-bar: var(--cr-toggle-bar-size);
+ --paper-toggle-button-unchecked-button: var(--cr-toggle-button-size);
+ --paper-toggle-button-unchecked-ink: var(--cr-toggle-ink-size);
+ };
+ </style>
+ </template>
+</dom-module>
diff --git a/chromium/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp b/chromium/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp
index 357d75a6a0d..8b6dede4445 100644
--- a/chromium/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp
+++ b/chromium/ui/webui/resources/cr_elements/policy/compiled_resources2.gyp
@@ -51,5 +51,10 @@
],
'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
},
+ {
+ 'target_name': 'cr_tooltip_icon',
+ 'dependencies': [],
+ 'includes': ['../../../../../third_party/closure_compiler/compile_js2.gypi'],
+ },
],
}
diff --git a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_indicator.html b/chromium/ui/webui/resources/cr_elements/policy/cr_policy_indicator.html
index 0bb096776f1..41b5170eff8 100644
--- a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_indicator.html
+++ b/chromium/ui/webui/resources/cr_elements/policy/cr_policy_indicator.html
@@ -1,29 +1,16 @@
-<link rel="import" href="chrome://resources/cr_elements/icons.html">
-<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
<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/polymer/v1_0/paper-tooltip/paper-tooltip.html">
+
+<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
<link rel="import" href="cr_policy_indicator_behavior.html">
-<link rel="import" href="cr_policy_vars_css.html">
+<link rel="import" href="cr_tooltip_icon.html">
<dom-module id="cr-policy-indicator">
<template>
- <style include="cr-hidden-style">
- :host {
- @apply(--cr-policy-indicator);
- }
-
- paper-tooltip {
- --paper-tooltip: var(--cr-policy-tooltip);
- }
- </style>
- <iron-icon id="indicator" tabindex="0" aria-label$="[[iconAriaLabel]]"
- aria-describedby="tooltip" hidden$="[[!indicatorVisible]]"
- icon="[[indicatorIcon]]"></iron-icon>
- <paper-tooltip id="tooltip" for="indicator" position="top"
- fit-to-visible-bounds>
- [[indicatorTooltip]]
- </paper-tooltip>
+ <style include="cr-hidden-style"></style>
+ <cr-tooltip-icon hidden$="[[!indicatorVisible]]"
+ tooltip-text="[[indicatorTooltip]]" icon-class="[[indicatorIcon]]"
+ icon-aria-label="[[iconAriaLabel]]">
+ </cr-tooltip-icon>
</template>
<script src="cr_policy_indicator.js"></script>
</dom-module>
diff --git a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_indicator.html b/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_indicator.html
index 70082b7a034..0994787a73a 100644
--- a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_indicator.html
+++ b/chromium/ui/webui/resources/cr_elements/policy/cr_policy_network_indicator.html
@@ -1,30 +1,16 @@
-<link rel="import" href="chrome://resources/cr_elements/icons.html">
-<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
<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/polymer/v1_0/paper-tooltip/paper-tooltip.html">
+
+<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
<link rel="import" href="cr_policy_indicator_behavior.html">
<link rel="import" href="cr_policy_network_behavior.html">
-<link rel="import" href="cr_policy_vars_css.html">
+<link rel="import" href="cr_tooltip_icon.html">
<dom-module id="cr-policy-network-indicator">
<template>
- <style include="cr-hidden-style">
- :host {
- @apply(--cr-policy-indicator);
- }
-
- paper-tooltip {
- --paper-tooltip: var(--cr-policy-tooltip);
- }
- </style>
- <iron-icon id="indicator" tabindex="0" aria-describedby="tooltip"
- hidden$="[[!indicatorVisible]]" icon="[[indicatorIcon]]">
- </iron-icon>
- <paper-tooltip id="tooltip" for="indicator" position="top"
- fit-to-visible-bounds>
- [[indicatorTooltip]]
- </paper-tooltip>
+ <style include="cr-hidden-style"></style>
+ <cr-tooltip-icon hidden$="[[!indicatorVisible]]"
+ tooltip-text="[[indicatorTooltip]]" icon-class="[[indicatorIcon]]">
+ </cr-tooltip-icon>
</template>
<script src="cr_policy_network_indicator.js"></script>
</dom-module>
diff --git a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.html b/chromium/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.html
index dd33e679cfb..8758980f279 100644
--- a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.html
+++ b/chromium/ui/webui/resources/cr_elements/policy/cr_policy_pref_indicator.html
@@ -1,29 +1,16 @@
-<link rel="import" href="chrome://resources/cr_elements/icons.html">
-<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
<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/polymer/v1_0/paper-tooltip/paper-tooltip.html">
+
+<link rel="import" href="chrome://resources/cr_elements/hidden_style_css.html">
<link rel="import" href="cr_policy_indicator_behavior.html">
-<link rel="import" href="cr_policy_vars_css.html">
+<link rel="import" href="cr_tooltip_icon.html">
<dom-module id="cr-policy-pref-indicator">
<template>
- <style include="cr-hidden-style">
- :host {
- @apply(--cr-policy-indicator);
- }
-
- paper-tooltip {
- --paper-tooltip: var(--cr-policy-tooltip);
- }
- </style>
- <iron-icon id="indicator" tabindex="0" aria-label$="[[iconAriaLabel]]"
- aria-describedby="tooltip" hidden$="[[!indicatorVisible]]"
- icon="[[indicatorIcon]]"></iron-icon>
- <paper-tooltip id="tooltip" for="indicator" position="top"
- fit-to-visible-bounds>
- [[indicatorTooltip]]
- </paper-tooltip>
+ <style include="cr-hidden-style"></style>
+ <cr-tooltip-icon hidden$="[[!indicatorVisible]]"
+ tooltip-text="[[indicatorTooltip]]" icon-class="[[indicatorIcon]]"
+ icon-aria-label="[[iconAriaLabel]]">
+ </cr-tooltip-icon>
</template>
<script src="cr_policy_pref_indicator.js"></script>
</dom-module>
diff --git a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_vars_css.html b/chromium/ui/webui/resources/cr_elements/policy/cr_policy_vars_css.html
deleted file mode 100644
index c16dd6503b8..00000000000
--- a/chromium/ui/webui/resources/cr_elements/policy/cr_policy_vars_css.html
+++ /dev/null
@@ -1,17 +0,0 @@
-<link rel="import" href="chrome://resources/cr_elements/shared_vars_css.html">
-<style is="custom-style">
- :root {
- --cr-policy-indicator: {
- @apply(--cr-icon-height-width);
- display: flex; /* Position independently from the line-height. */
- };
-
- --cr-policy-tooltip: {
- font-size: 92.31%; /* Effectively 12px if the host default is 13px. */
- font-weight: 500;
- max-width: 330px;
- min-width: 200px;
- padding: 10px 8px;
- };
- }
-</style>
diff --git a/chromium/ui/webui/resources/cr_elements/policy/cr_tooltip_icon.html b/chromium/ui/webui/resources/cr_elements/policy/cr_tooltip_icon.html
new file mode 100644
index 00000000000..c9a1587bf87
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/policy/cr_tooltip_icon.html
@@ -0,0 +1,34 @@
+<link rel="import" href="chrome://resources/html/polymer.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/polymer/v1_0/iron-icon/iron-icon.html">
+<link rel="import" href="chrome://resources/polymer/v1_0/paper-tooltip/paper-tooltip.html">
+
+<dom-module id="cr-tooltip-icon">
+ <template>
+ <style>
+ :host {
+ @apply(--cr-icon-height-width);
+ display: flex; /* Position independently from the line-height. */
+ }
+
+ paper-tooltip {
+ --paper-tooltip: {
+ font-size: 92.31%; /* Effectively 12px if the host default is 13px. */
+ font-weight: 500;
+ max-width: 330px;
+ min-width: 200px;
+ padding: 10px 8px;
+ };
+ }
+ </style>
+ <iron-icon id="indicator" tabindex="0" aria-label$="[[iconAriaLabel]]"
+ aria-describedby="tooltip" icon="[[iconClass]]"></iron-icon>
+ <paper-tooltip id="tooltip" for="indicator" position="top"
+ fit-to-visible-bounds>
+ [[tooltipText]]
+ </paper-tooltip>
+ </template>
+ <script src="cr_tooltip_icon.js"></script>
+</dom-module>
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
new file mode 100644
index 00000000000..ba918fb0ca7
--- /dev/null
+++ b/chromium/ui/webui/resources/cr_elements/policy/cr_tooltip_icon.js
@@ -0,0 +1,12 @@
+// 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.
+
+Polymer({
+ is: 'cr-tooltip-icon',
+ properties: {
+ iconAriaLabel: String,
+ iconClass: String,
+ tooltipText: String,
+ },
+}); \ 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 224a94768a6..2352c441aed 100644
--- a/chromium/ui/webui/resources/cr_elements/shared_vars_css.html
+++ b/chromium/ui/webui/resources/cr_elements/shared_vars_css.html
@@ -37,12 +37,43 @@
-webkit-margin-start: var(--cr-icon-button-margin-start);
}
+ --cr-primary-text: {
+ color: var(--paper-grey-900);
+ line-height: 154%; /* 20px. */
+ }
+
+ --cr-secondary-text: {
+ color: var(--paper-grey-600);
+ font-weight: 400;
+ }
+
+ /* TODO (scottchen): re-implement with paddings instead; */
+ /* These are used for row items such as radio buttons, check boxes, list
+ * items etc. */
+ --cr-section-min-height: 48px;
+ --cr-section-two-line-min-height: 64px;
+ --cr-section-three-line-min-height: 84px;
+
+ --cr-section-padding: 20px;
+ --cr-section-indent-width: 40px;
+ --cr-section-indent-padding: calc(
+ var(--cr-section-padding) + var(--cr-section-indent-width));
+
+ --cr-section: {
+ align-items: center;
+ border-top: var(--cr-separator-line);
+ display: flex;
+ min-height: var(--cr-section-min-height);
+ padding: 0 var(--cr-section-padding);
+ };
+
+ --cr-toggle-color: var(--google-blue-500);
+
--cr-selectable-focus: {
background-color: var(--cr-focused-item-color);
outline: none;
}
--cr-separator-height: 1px;
--cr-separator-line: var(--cr-separator-height) solid rgba(0, 0, 0, 0.06);
- --paper-checkbox-ink-size: 40px;
}
</style>
diff --git a/chromium/ui/webui/resources/cr_elements_images.grdp b/chromium/ui/webui/resources/cr_elements_images.grdp
index a5ec224b864..23265241ab1 100644
--- a/chromium/ui/webui/resources/cr_elements_images.grdp
+++ b/chromium/ui/webui/resources/cr_elements_images.grdp
@@ -9,6 +9,8 @@
file="images/arrow_right.svg" type="BINDATA" />
<include name="IDR_WEBUI_IMAGES_OPEN_IN_NEW"
file="images/open_in_new.svg" type="BINDATA" />
+ <include name="IDR_WEBUI_IMAGES_ICON_ARROW_BACK"
+ file="images/icon_arrow_back.svg" type="BINDATA" />
<include name="IDR_WEBUI_IMAGES_ICON_CANCEL"
file="images/icon_cancel.svg" type="BINDATA" />
<include name="IDR_WEBUI_IMAGES_ICON_CANCEL_TOOLBAR"
@@ -25,8 +27,12 @@
file="images/icon_expand_more.svg" type="BINDATA" />
<include name="IDR_WEBUI_IMAGES_ICON_EXTERNAL"
file="images/open_in_new.svg" type="BINDATA" />
+ <include name="IDR_WEBUI_IMAGES_ICON_MENU_WHITE"
+ file="images/icon_menu_white.svg" type="BINDATA" />
<include name="IDR_WEBUI_IMAGES_ICON_MORE_VERT"
file="images/icon_more_vert.svg" type="BINDATA" />
+ <include name="IDR_WEBUI_IMAGES_ICON_REFRESH"
+ file="images/icon_refresh.svg" type="BINDATA" />
<include name="IDR_WEBUI_IMAGES_ICON_SETTINGS"
file="images/icon_settings.svg" type="BINDATA" />
<include name="IDR_WEBUI_IMAGES_ICON_SEARCH"
diff --git a/chromium/ui/webui/resources/cr_elements_resources.grdp b/chromium/ui/webui/resources/cr_elements_resources.grdp
index d9db27b42bd..d7f4a170287 100644
--- a/chromium/ui/webui/resources/cr_elements_resources.grdp
+++ b/chromium/ui/webui/resources/cr_elements_resources.grdp
@@ -41,6 +41,12 @@
<structure name="IDR_CR_ELEMENTS_CR_LAZY_RENDER_JS"
file="../../webui/resources/cr_elements/cr_lazy_render/cr_lazy_render.js"
type="chrome_html" />
+ <structure name="IDR_CR_ELEMENTS_CR_LINK_ROW_HTML"
+ file="../../webui/resources/cr_elements/cr_link_row/cr_link_row.html"
+ type="chrome_html" />
+ <structure name="IDR_CR_ELEMENTS_CR_LINK_ROW_JS"
+ file="../../webui/resources/cr_elements/cr_link_row/cr_link_row.js"
+ type="chrome_html" />
<if expr="chromeos">
<structure name="IDR_CR_ELEMENTS_CHROMEOS_CR_PICTURE_CR_CAMERA_HTML"
file="../../webui/resources/cr_elements/chromeos/cr_picture/cr_camera.html"
@@ -145,8 +151,11 @@
<structure name="IDR_CR_ELEMENTS_CR_POLICY_PREF_INDICATOR_HTML"
file="../../webui/resources/cr_elements/policy/cr_policy_pref_indicator.html"
type="chrome_html" />
- <structure name="IDR_CR_ELEMENTS_CR_POLICY_VARS_CSS_HTML"
- file="../../webui/resources/cr_elements/policy/cr_policy_vars_css.html"
+ <structure name="IDR_CR_ELEMENTS_CR_TOOLTIP_ICON_HTML"
+ file="../../webui/resources/cr_elements/policy/cr_tooltip_icon.html"
+ type="chrome_html" />
+ <structure name="IDR_CR_ELEMENTS_CR_TOOLTIP_ICON_JS"
+ file="../../webui/resources/cr_elements/policy/cr_tooltip_icon.js"
type="chrome_html" />
<structure name="IDR_CR_ELEMENTS_CR_PROFILE_AVATAR_SELECTOR_HTML"
file="../../webui/resources/cr_elements/cr_profile_avatar_selector/cr_profile_avatar_selector.html"
@@ -179,6 +188,12 @@
<structure name="IDR_CR_ELEMENTS_PAPER_BUTTON_STYLE_CSS_HTML"
file="../../webui/resources/cr_elements/paper_button_style_css.html"
type="chrome_html" />
+ <structure name="IDR_CR_ELEMENTS_PAPER_CHECKBOX_STYLE_CSS_HTML"
+ file="../../webui/resources/cr_elements/paper_checkbox_style_css.html"
+ type="chrome_html" />
+ <structure name="IDR_CR_ELEMENTS_PAPER_TOGGLE_STYLE_CSS_HTML"
+ file="../../webui/resources/cr_elements/paper_toggle_style_css.html"
+ type="chrome_html" />
<structure name="IDR_CR_ELEMENTS_CR_SHARED_VARS_CSS_HTML"
file="../../webui/resources/cr_elements/shared_vars_css.html"
type="chrome_html" />
diff --git a/chromium/ui/webui/resources/css/chrome_shared.css b/chromium/ui/webui/resources/css/chrome_shared.css
index acca2c1cd22..95ef34d5564 100644
--- a/chromium/ui/webui/resources/css/chrome_shared.css
+++ b/chromium/ui/webui/resources/css/chrome_shared.css
@@ -8,9 +8,6 @@
@import url(chrome://resources/css/text_defaults.css);
@import url(i18n_process.css);
@import url(widgets.css);
-<if expr="chromeos">
-@import url(chromeos/ui_account_tweaks.css);
-</if>
/* Prevent CSS from overriding the hidden property. */
[hidden] {
diff --git a/chromium/ui/webui/resources/css/chromeos/ui_account_tweaks.css b/chromium/ui/webui/resources/css/chromeos/ui_account_tweaks.css
deleted file mode 100644
index 91ae0699729..00000000000
--- a/chromium/ui/webui/resources/css/chromeos/ui_account_tweaks.css
+++ /dev/null
@@ -1,14 +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. */
-
-/* This file defines styles for internal page elements that have special
- * look and feel based on account status (owner/non-owner/guest). */
-
-.guest-disabled {
- color: #999;
-}
-
-a.guest-disabled {
- opacity: 0.75;
-}
diff --git a/chromium/ui/webui/resources/css/widgets.css b/chromium/ui/webui/resources/css/widgets.css
index 997bfc04794..419304710cf 100644
--- a/chromium/ui/webui/resources/css/widgets.css
+++ b/chromium/ui/webui/resources/css/widgets.css
@@ -249,7 +249,7 @@ input:disabled:-webkit-any([type='password'],
*
* <div class="checkbox">
* <label>
- * <input type="checkbox"></input>
+ * <input type="checkbox">
* <span>
* </label>
* </div>
diff --git a/chromium/ui/webui/resources/html/chromeos/ui_account_tweaks.html b/chromium/ui/webui/resources/html/chromeos/ui_account_tweaks.html
deleted file mode 100644
index 10b6db6d7e4..00000000000
--- a/chromium/ui/webui/resources/html/chromeos/ui_account_tweaks.html
+++ /dev/null
@@ -1 +0,0 @@
-<script src="chrome://resources/js/chromeos/ui_account_tweaks.js"></script>
diff --git a/chromium/ui/webui/resources/images/icon_arrow_back.svg b/chromium/ui/webui/resources/images/icon_arrow_back.svg
new file mode 100644
index 00000000000..838eb43618d
--- /dev/null
+++ b/chromium/ui/webui/resources/images/icon_arrow_back.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#757575" preserveAspectRatio="xMidYMid meet"><path d="M20 11H7.83l5.59-5.59L12 4l-8 8 8 8 1.41-1.41L7.83 13H20v-2z"></path></svg> \ No newline at end of file
diff --git a/chromium/ui/webui/resources/images/icon_menu_white.svg b/chromium/ui/webui/resources/images/icon_menu_white.svg
new file mode 100644
index 00000000000..aab80273728
--- /dev/null
+++ b/chromium/ui/webui/resources/images/icon_menu_white.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="20" height="20" viewBox="0 0 20 20" fill="#fff" preserveAspectRatio="xMidYMid meet"><rect x="2" y="4" width="16" height="2"></rect><rect x="2" y="9" width="16" height="2"></rect><rect x="2" y="14" width="16" height="2"></rect></svg> \ No newline at end of file
diff --git a/chromium/ui/webui/resources/images/icon_refresh.svg b/chromium/ui/webui/resources/images/icon_refresh.svg
new file mode 100644
index 00000000000..d7f66ccf991
--- /dev/null
+++ b/chromium/ui/webui/resources/images/icon_refresh.svg
@@ -0,0 +1 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="24" height="24" viewBox="0 0 24 24" fill="#757575" preserveAspectRatio="xMidYMid meet"><path d="M17.65 6.35C16.2 4.9 14.21 4 12 4c-4.42 0-7.99 3.58-7.99 8s3.57 8 7.99 8c3.73 0 6.84-2.55 7.73-6h-2.08c-.82 2.33-3.04 4-5.65 4-3.31 0-6-2.69-6-6s2.69-6 6-6c1.66 0 3.14.69 4.22 1.78L13 11h7V4l-2.35 2.35z"></path></svg> \ No newline at end of file
diff --git a/chromium/ui/webui/resources/images/info.svg b/chromium/ui/webui/resources/images/info.svg
new file mode 100644
index 00000000000..e76e2476640
--- /dev/null
+++ b/chromium/ui/webui/resources/images/info.svg
@@ -0,0 +1,4 @@
+<svg xmlns="http://www.w3.org/2000/svg" width="18px" height="18px" viewBox="0 0 48 48" fill="#757575">
+ <path d="M0 0h48v48H0z" fill="none"/>
+ <path d="M24 4C12.95 4 4 12.95 4 24s8.95 20 20 20 20-8.95 20-20S35.05 4 24 4zm2 30h-4V22h4v12zm0-16h-4v-4h4v4z"/>
+</svg>
diff --git a/chromium/ui/webui/resources/js/chromeos/ui_account_tweaks.js b/chromium/ui/webui/resources/js/chromeos/ui_account_tweaks.js
deleted file mode 100644
index 1aa912312cb..00000000000
--- a/chromium/ui/webui/resources/js/chromeos/ui_account_tweaks.js
+++ /dev/null
@@ -1,178 +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.
-
-/**
- * @fileoverview This file contains methods that allow to tweak
- * internal page UI based on the status of current user (owner/user/guest).
- * It is assumed that required data is passed via i18n strings
- * (using loadTimeData dictionary) that are filled with call to
- * AddAccountUITweaksLocalizedValues in ui_account_tweaks.cc.
- * It is also assumed that tweaked page has chrome://resources/css/widgets.css
- * included.
- */
-
-cr.define('uiAccountTweaks', function() {
-
- /////////////////////////////////////////////////////////////////////////////
- // UIAccountTweaks class:
-
- // String specificators for different types of sessions.
- /** @const */ var SESSION_TYPE_GUEST = 'guest';
- /** @const */ var SESSION_TYPE_PUBLIC = 'public-account';
-
- /**
- * Encapsulated handling of ChromeOS accounts options page.
- * @constructor
- */
- function UIAccountTweaks() {}
-
- /**
- * @return {boolean} Whether the current user is owner or not.
- */
- UIAccountTweaks.currentUserIsOwner = function() {
- return loadTimeData.getBoolean('currentUserIsOwner');
- };
-
- /**
- * @return {boolean} Whether we're currently in guest session.
- */
- UIAccountTweaks.loggedInAsGuest = function() {
- return loadTimeData.getBoolean('loggedInAsGuest');
- };
-
- /**
- * @return {boolean} Whether we're currently in public session.
- */
- UIAccountTweaks.loggedInAsPublicAccount = function() {
- return loadTimeData.getBoolean('loggedInAsPublicAccount');
- };
-
- /**
- * @return {boolean} Whether we're currently in supervised user mode.
- */
- UIAccountTweaks.loggedInAsSupervisedUser = function() {
- return loadTimeData.getBoolean('loggedInAsSupervisedUser');
- };
-
- /**
- * Enables an element unless it should be disabled for the session type.
- *
- * @param {!Element} element Element that should be enabled.
- */
- UIAccountTweaks.enableElementIfPossible = function(element) {
- var sessionType;
- if (UIAccountTweaks.loggedInAsGuest())
- sessionType = SESSION_TYPE_GUEST;
- else if (UIAccountTweaks.loggedInAsPublicAccount())
- sessionType = SESSION_TYPE_PUBLIC;
-
- if (sessionType &&
- element.getAttribute(sessionType + '-visibility') == 'disabled') {
- return;
- }
-
- element.disabled = false;
- };
-
- /**
- * Disables or hides some elements in specified type of session in ChromeOS.
- * All elements within given document with *sessionType*-visibility
- * attribute are either hidden (for *sessionType*-visibility="hidden")
- * or disabled (for *sessionType*-visibility="disabled").
- *
- * @param {Document} document Document that should processed.
- * @param {string} sessionType name of the session type processed.
- * @private
- */
- UIAccountTweaks.applySessionTypeVisibility_ = function(
- document, sessionType) {
- var elements =
- document.querySelectorAll('[' + sessionType + '-visibility]');
- for (var i = 0; i < elements.length; i++) {
- var element = elements[i];
- var visibility = element.getAttribute(sessionType + '-visibility');
- if (visibility == 'hidden')
- element.hidden = true;
- else if (visibility == 'disabled')
- UIAccountTweaks.disableElementsForSessionType(element, sessionType);
- }
- };
-
- /**
- * Updates specific visibility of elements for Guest session in ChromeOS.
- * Calls applySessionTypeVisibility_ method.
- *
- * @param {Document} document Document that should processed.
- */
- UIAccountTweaks.applyGuestSessionVisibility = function(document) {
- if (!UIAccountTweaks.loggedInAsGuest())
- return;
- UIAccountTweaks.applySessionTypeVisibility_(document, SESSION_TYPE_GUEST);
- };
-
- /**
- * Updates specific visibility of elements for Public account session in
- * ChromeOS. Calls applySessionTypeVisibility_ method.
- *
- * @param {Document} document Document that should processed.
- */
- UIAccountTweaks.applyPublicSessionVisibility = function(document) {
- if (!UIAccountTweaks.loggedInAsPublicAccount())
- return;
- UIAccountTweaks.applySessionTypeVisibility_(document, SESSION_TYPE_PUBLIC);
- };
-
- /**
- * Disables and marks page elements for specified session type.
- * Adds #-disabled css class to all elements within given subtree,
- * disables interactive elements (input/select/button), and removes href
- * attribute from <a> elements.
- *
- * @param {!Element} element Root element of DOM subtree that should be
- * disabled.
- * @param {string} sessionType session type specificator.
- */
- UIAccountTweaks.disableElementsForSessionType = function(
- element, sessionType) {
- UIAccountTweaks.disableElementForSessionType_(element, sessionType);
-
- // Walk the tree, searching each ELEMENT node.
- var walker = document.createTreeWalker(
- element, NodeFilter.SHOW_ELEMENT, null, false);
-
- var node = walker.nextNode();
- while (node) {
- UIAccountTweaks.disableElementForSessionType_(
- /** @type {!Element} */ (node), sessionType);
- node = walker.nextNode();
- }
- };
-
- /**
- * Disables single element for given session type.
- * Adds *sessionType*-disabled css class, adds disabled attribute for
- * appropriate elements (input/select/button), and removes href attribute from
- * <a> element.
- *
- * @private
- * @param {!Element} element Element that should be disabled.
- * @param {string} sessionType account session Type specificator.
- */
- UIAccountTweaks.disableElementForSessionType_ = function(
- element, sessionType) {
- element.classList.add(sessionType + '-disabled');
- if (element.nodeName == 'INPUT' || element.nodeName == 'SELECT' ||
- element.nodeName == 'BUTTON') {
- element.disabled = true;
- } else if (element.nodeName == 'A') {
- element.onclick = function() {
- return false;
- };
- }
- };
-
- // Export
- return {UIAccountTweaks: UIAccountTweaks};
-
-});
diff --git a/chromium/ui/webui/resources/js/cr/ui/menu.js b/chromium/ui/webui/resources/js/cr/ui/menu.js
index 487ff8553c9..ed00ed84f6a 100644
--- a/chromium/ui/webui/resources/js/cr/ui/menu.js
+++ b/chromium/ui/webui/resources/js/cr/ui/menu.js
@@ -78,6 +78,7 @@ cr.define('cr.ui', function() {
* Clears menu.
*/
clear: function() {
+ this.selectedItem = null;
this.textContent = '';
},
diff --git a/chromium/ui/webui/resources/webui_resources.grd b/chromium/ui/webui/resources/webui_resources.grd
index 24f7ea9c074..e8eb478d2a4 100644
--- a/chromium/ui/webui/resources/webui_resources.grd
+++ b/chromium/ui/webui/resources/webui_resources.grd
@@ -496,18 +496,8 @@ without changes to the corresponding grd file. -->
file="js/web_ui_listener_behavior.js" type="chrome_html" />
<structure name="IDR_WEBUI_JS_WEBUI_RESOURCE_TEST"
file="js/webui_resource_test.js" type="chrome_html" />
- <if expr="chromeos">
- <structure name="IDR_WEBUI_CSS_UI_ACCOUNT_TWEAKS"
- file="css/chromeos/ui_account_tweaks.css"
- type="chrome_html" />
- <structure name="IDR_WEBUI_HTML_UI_ACCOUNT_TWEAKS"
- file="html/chromeos/ui_account_tweaks.html"
- type="chrome_html" />
- <structure name="IDR_WEBUI_JS_UI_ACCOUNT_TWEAKS"
- file="js/chromeos/ui_account_tweaks.js"
- type="chrome_html" />
- </if>
<if expr="not is_android">
+ <part file="cr_components_resources.grdp" />
<part file="cr_elements_resources.grdp" />
<part file="polymer_resources.grdp" />
</if>
diff --git a/chromium/ui/wm/BUILD.gn b/chromium/ui/wm/BUILD.gn
index 2de02709e0b..83f1e187bfb 100644
--- a/chromium/ui/wm/BUILD.gn
+++ b/chromium/ui/wm/BUILD.gn
@@ -29,8 +29,6 @@ component("wm") {
"core/focus_controller.cc",
"core/focus_controller.h",
"core/focus_rules.h",
- "core/masked_window_targeter.cc",
- "core/masked_window_targeter.h",
"core/native_cursor_manager.h",
"core/native_cursor_manager_delegate.h",
"core/shadow.cc",
diff --git a/chromium/ui/wm/core/compound_event_filter.cc b/chromium/ui/wm/core/compound_event_filter.cc
index cd2db9a83fe..a3adb2674cf 100644
--- a/chromium/ui/wm/core/compound_event_filter.cc
+++ b/chromium/ui/wm/core/compound_event_filter.cc
@@ -215,8 +215,7 @@ void CompoundEventFilter::OnMouseEvent(ui::MouseEvent* event) {
event->type() == ui::ET_MOUSE_PRESSED ||
event->type() == ui::ET_MOUSEWHEEL)) {
SetMouseEventsEnableStateOnEvent(window, event, true);
- SetCursorVisibilityOnEvent(window, event,
- !(event->flags() & ui::EF_DIRECT_INPUT));
+ SetCursorVisibilityOnEvent(window, event, true);
UpdateCursor(window, event);
}
diff --git a/chromium/ui/wm/core/easy_resize_window_targeter.cc b/chromium/ui/wm/core/easy_resize_window_targeter.cc
index f5230312c2d..d050c1b434f 100644
--- a/chromium/ui/wm/core/easy_resize_window_targeter.cc
+++ b/chromium/ui/wm/core/easy_resize_window_targeter.cc
@@ -28,39 +28,18 @@ EasyResizeWindowTargeter::EasyResizeWindowTargeter(
EasyResizeWindowTargeter::~EasyResizeWindowTargeter() {}
-void EasyResizeWindowTargeter::SetInsets(const gfx::Insets& mouse_extend,
- const gfx::Insets& touch_extend) {
- if (mouse_extend == mouse_extend_ && touch_extend_ == touch_extend)
- return;
-
- mouse_extend_ = mouse_extend;
- touch_extend_ = touch_extend;
+void EasyResizeWindowTargeter::OnSetInsets() {
if (aura::Env::GetInstance()->mode() != aura::Env::Mode::MUS)
return;
aura::WindowPortMus::Get(container_)
- ->SetExtendedHitRegionForChildren(mouse_extend, touch_extend);
+ ->SetExtendedHitRegionForChildren(mouse_extend(), touch_extend());
}
bool EasyResizeWindowTargeter::EventLocationInsideBounds(
- aura::Window* window,
+ aura::Window* target,
const ui::LocatedEvent& event) const {
- if (ShouldUseExtendedBounds(window)) {
- // Note that |event|'s location is in |window|'s parent's coordinate system,
- // so convert it to |window|'s coordinate system first.
- gfx::Point point = event.location();
- if (window->parent())
- aura::Window::ConvertPointToTarget(window->parent(), window, &point);
-
- gfx::Rect bounds(window->bounds().size());
- if (event.IsTouchEvent() || event.IsGestureEvent())
- bounds.Inset(touch_extend_);
- else
- bounds.Inset(mouse_extend_);
-
- return bounds.Contains(point);
- }
- return WindowTargeter::EventLocationInsideBounds(window, event);
+ return WindowTargeter::EventLocationInsideBounds(target, event);
}
bool EasyResizeWindowTargeter::ShouldUseExtendedBounds(
@@ -70,9 +49,14 @@ bool EasyResizeWindowTargeter::ShouldUseExtendedBounds(
if (window->parent() != container_)
return false;
- const bool can_resize =
- window->GetProperty(aura::client::kResizeBehaviorKey) &
- ui::mojom::kResizeBehaviorCanResize;
+ // Only resizable windows benefit from the extended hit-test region.
+ if ((window->GetProperty(aura::client::kResizeBehaviorKey) &
+ ui::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_|.
aura::client::TransientWindowClient* transient_window_client =
aura::client::GetTransientWindowClient();
const aura::Window* transient_parent =
@@ -80,7 +64,7 @@ bool EasyResizeWindowTargeter::ShouldUseExtendedBounds(
? transient_window_client->GetTransientParent(window)
: nullptr;
return !transient_parent || transient_parent == container_ ||
- (can_resize && transient_parent->parent() == container_);
+ transient_parent->parent() == container_;
}
} // 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 9739fdd6d99..b277bd475c8 100644
--- a/chromium/ui/wm/core/easy_resize_window_targeter.h
+++ b/chromium/ui/wm/core/easy_resize_window_targeter.h
@@ -26,25 +26,20 @@ class WM_CORE_EXPORT EasyResizeWindowTargeter : public aura::WindowTargeter {
~EasyResizeWindowTargeter() override;
protected:
- // NOTE: the insets must be negative.
- void SetInsets(const gfx::Insets& mouse_extend,
- const gfx::Insets& touch_extend);
-
- const gfx::Insets& mouse_extend() const { return mouse_extend_; }
- const gfx::Insets& touch_extend() const { return touch_extend_; }
-
// aura::WindowTargeter:
- bool EventLocationInsideBounds(aura::Window* window,
- const ui::LocatedEvent& event) const override;
+ void OnSetInsets() override;
private:
- // Returns true if the hit testing (EventLocationInsideBounds()) should use
- // the extended bounds.
- bool ShouldUseExtendedBounds(const aura::Window* window) const;
+ // aura::WindowTargeter:
+ // Delegates to WindowTargeter's impl and prevents overriding in subclasses.
+ bool EventLocationInsideBounds(aura::Window* target,
+ const ui::LocatedEvent& event) const final;
+
+ // Returns true if the hit testing (GetHitTestRects()) should use the
+ // extended bounds.
+ bool ShouldUseExtendedBounds(const aura::Window* window) const override;
aura::Window* container_;
- gfx::Insets mouse_extend_;
- gfx::Insets touch_extend_;
DISALLOW_COPY_AND_ASSIGN(EasyResizeWindowTargeter);
};
diff --git a/chromium/ui/wm/core/focus_controller.cc b/chromium/ui/wm/core/focus_controller.cc
index 695be50f980..069e9f46e2c 100644
--- a/chromium/ui/wm/core/focus_controller.cc
+++ b/chromium/ui/wm/core/focus_controller.cc
@@ -206,16 +206,29 @@ void FocusController::FocusAndActivateWindow(
// Activation change observers may change the focused window. If this happens
// we must not adjust the focus below since this will clobber that change.
aura::Window* last_focused_window = focused_window_;
- if (!updating_activation_)
+ if (!updating_activation_) {
+ aura::WindowTracker focusable_window_tracker;
+ if (focusable) {
+ focusable_window_tracker.Add(focusable);
+ focusable = nullptr;
+ }
SetActiveWindow(reason, window, activatable);
+ if (!focusable_window_tracker.windows().empty())
+ focusable = focusable_window_tracker.Pop();
+ }
// If the window's ActivationChangeObserver shifted focus to a valid window,
// we don't want to focus the window we thought would be focused by default.
- bool activation_changed_focus = last_focused_window != focused_window_;
- if (!updating_focus_ && (!activation_changed_focus || !focused_window_)) {
- if (active_window_ && focusable)
- DCHECK(active_window_->Contains(focusable));
- SetFocusedWindow(focusable);
+ if (!updating_focus_) {
+ const bool activation_changed_focus =
+ last_focused_window != focused_window_;
+ if (!activation_changed_focus || !focused_window_) {
+ if (active_window_ && focusable)
+ DCHECK(active_window_->Contains(focusable));
+ SetFocusedWindow(focusable);
+ }
+ if (active_window_ && focused_window_)
+ DCHECK(active_window_->Contains(focused_window_));
}
}
@@ -340,8 +353,17 @@ void FocusController::WindowLostFocusFromDispositionChange(
if (!(active_window_ && active_window_->Contains(focused_window_)))
SetFocusedWindow(next_activatable);
} else if (window->Contains(focused_window_)) {
- // Active window isn't changing, but focused window might be.
- SetFocusedWindow(rules_->GetFocusableWindow(next));
+ if (updating_activation_) {
+ // We're in the process of updating activation, most likely
+ // ActivationChangeObserver::OnWindowActivated() is changing something
+ // about the focused window (visibility perhaps). Temporarily set the
+ // focus to null, we'll set it to something better when activation
+ // completes.
+ SetFocusedWindow(nullptr);
+ } else {
+ // Active window isn't changing, but focused window might be.
+ SetFocusedWindow(rules_->GetFocusableWindow(next));
+ }
}
}
diff --git a/chromium/ui/wm/core/focus_controller_unittest.cc b/chromium/ui/wm/core/focus_controller_unittest.cc
index f4678caec36..1c8630102b8 100644
--- a/chromium/ui/wm/core/focus_controller_unittest.cc
+++ b/chromium/ui/wm/core/focus_controller_unittest.cc
@@ -149,6 +149,39 @@ class RecordingActivationAndFocusChangeObserver
DISALLOW_COPY_AND_ASSIGN(RecordingActivationAndFocusChangeObserver);
};
+// Hides a window when activation changes.
+class HideOnLoseActivationChangeObserver : public ActivationChangeObserver {
+ public:
+ explicit HideOnLoseActivationChangeObserver(aura::Window* window_to_hide)
+ : root_(window_to_hide->GetRootWindow()),
+ window_to_hide_(window_to_hide) {
+ GetActivationClient(root_)->AddObserver(this);
+ }
+
+ ~HideOnLoseActivationChangeObserver() override {
+ GetActivationClient(root_)->RemoveObserver(this);
+ }
+
+ aura::Window* window_to_hide() { return window_to_hide_; }
+
+ private:
+ // Overridden from ActivationChangeObserver:
+ void OnWindowActivated(ActivationReason reason,
+ aura::Window* gained_active,
+ aura::Window* lost_active) override {
+ if (window_to_hide_) {
+ aura::Window* window_to_hide = window_to_hide_;
+ window_to_hide_ = nullptr;
+ window_to_hide->Hide();
+ }
+ }
+
+ aura::Window* root_;
+ aura::Window* window_to_hide_;
+
+ DISALLOW_COPY_AND_ASSIGN(HideOnLoseActivationChangeObserver);
+};
+
// ActivationChangeObserver that deletes the window losing activation.
class DeleteOnLoseActivationChangeObserver : public ActivationChangeObserver,
public WindowDeleter {
@@ -465,6 +498,7 @@ class FocusControllerTestBase : public aura::test::AuraTestBase {
virtual void ChangeFocusWhenNothingFocusedAndCaptured() {}
virtual void DontPassDeletedWindow() {}
virtual void StackWindowAtTopOnActivation() {}
+ virtual void HideFocusedWindowDuringActivationLoss() {}
private:
std::unique_ptr<FocusController> focus_controller_;
@@ -865,6 +899,22 @@ class FocusControllerDirectTestBase : public FocusControllerTestBase {
EXPECT_EQ(window1.get(), GetActiveWindow());
}
+ // Verifies focus isn't left when during notification of an activation change
+ // the focused window is hidden.
+ void HideFocusedWindowDuringActivationLoss() override {
+ aura::Window* w11 = root_window()->GetChildById(11);
+ FocusWindow(w11);
+ EXPECT_EQ(11, GetFocusedWindowId());
+ EXPECT_EQ(1, GetActiveWindowId());
+ {
+ HideOnLoseActivationChangeObserver observer(w11);
+ ActivateWindowById(2);
+ EXPECT_EQ(nullptr, observer.window_to_hide());
+ EXPECT_EQ(2, GetActiveWindowId());
+ EXPECT_EQ(2, GetFocusedWindowId());
+ }
+ }
+
private:
DISALLOW_COPY_AND_ASSIGN(FocusControllerDirectTestBase);
};
@@ -1311,6 +1361,9 @@ FOCUS_CONTROLLER_TEST(FocusControllerApiTest, DontPassDeletedWindow);
FOCUS_CONTROLLER_TEST(FocusControllerApiTest, StackWindowAtTopOnActivation);
+FOCUS_CONTROLLER_TEST(FocusControllerApiTest,
+ HideFocusedWindowDuringActivationLoss);
+
// See description above TransientChildWindowActivationTest() for details.
FOCUS_CONTROLLER_TEST(FocusControllerParentHideTest,
TransientChildWindowActivationTest);
diff --git a/chromium/ui/wm/core/masked_window_targeter.cc b/chromium/ui/wm/core/masked_window_targeter.cc
deleted file mode 100644
index 74e8bc8a7c1..00000000000
--- a/chromium/ui/wm/core/masked_window_targeter.cc
+++ /dev/null
@@ -1,43 +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/wm/core/masked_window_targeter.h"
-
-#include "ui/aura/window.h"
-#include "ui/events/event.h"
-#include "ui/gfx/path.h"
-
-namespace wm {
-
-MaskedWindowTargeter::MaskedWindowTargeter(aura::Window* masked_window)
- : masked_window_(masked_window) {
-}
-
-MaskedWindowTargeter::~MaskedWindowTargeter() {}
-
-bool MaskedWindowTargeter::EventLocationInsideBounds(
- aura::Window* window,
- const ui::LocatedEvent& event) const {
- if (window == masked_window_) {
- gfx::Path mask;
- if (!GetHitTestMask(window, &mask))
- return WindowTargeter::EventLocationInsideBounds(window, event);
-
- gfx::Size size = window->bounds().size();
- SkRegion clip_region;
- clip_region.setRect(0, 0, size.width(), size.height());
-
- gfx::Point point = event.location();
- if (window->parent())
- aura::Window::ConvertPointToTarget(window->parent(), window, &point);
-
- SkRegion mask_region;
- return mask_region.setPath(mask, clip_region) &&
- mask_region.contains(point.x(), point.y());
- }
-
- return WindowTargeter::EventLocationInsideBounds(window, event);
-}
-
-} // namespace wm
diff --git a/chromium/ui/wm/core/masked_window_targeter.h b/chromium/ui/wm/core/masked_window_targeter.h
deleted file mode 100644
index 272fde909a2..00000000000
--- a/chromium/ui/wm/core/masked_window_targeter.h
+++ /dev/null
@@ -1,40 +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_WM_CORE_MASKED_WINDOW_TARGETER_H_
-#define UI_WM_CORE_MASKED_WINDOW_TARGETER_H_
-
-#include "base/macros.h"
-#include "ui/aura/window_targeter.h"
-#include "ui/wm/core/wm_core_export.h"
-
-namespace gfx {
-class Path;
-}
-
-namespace wm {
-
-class WM_CORE_EXPORT MaskedWindowTargeter : public aura::WindowTargeter {
- public:
- explicit MaskedWindowTargeter(aura::Window* masked_window);
- ~MaskedWindowTargeter() override;
-
- protected:
- // Sets the hit-test mask for |window| in |mask| (in |window|'s local
- // coordinate system). Returns whether a valid mask has been set in |mask|.
- virtual bool GetHitTestMask(aura::Window* window, gfx::Path* mask) const = 0;
-
- // aura::WindowTargeter:
- bool EventLocationInsideBounds(aura::Window* target,
- const ui::LocatedEvent& event) const override;
-
- private:
- aura::Window* masked_window_;
-
- DISALLOW_COPY_AND_ASSIGN(MaskedWindowTargeter);
-};
-
-} // namespace wm
-
-#endif // UI_WM_CORE_MASKED_WINDOW_TARGETER_H_
diff --git a/chromium/ui/wm/core/window_animations.cc b/chromium/ui/wm/core/window_animations.cc
index cca7067e2af..346a7ce9dec 100644
--- a/chromium/ui/wm/core/window_animations.cc
+++ b/chromium/ui/wm/core/window_animations.cc
@@ -166,7 +166,9 @@ base::LazyInstance<HidingWindowMetricsReporter>::Leaky g_reporter_hide =
DEFINE_UI_CLASS_PROPERTY_KEY(int,
kWindowVisibilityAnimationTypeKey,
WINDOW_VISIBILITY_ANIMATION_TYPE_DEFAULT);
-DEFINE_UI_CLASS_PROPERTY_KEY(int, kWindowVisibilityAnimationDurationKey, 0);
+DEFINE_UI_CLASS_PROPERTY_KEY(base::TimeDelta,
+ kWindowVisibilityAnimationDurationKey,
+ base::TimeDelta());
DEFINE_UI_CLASS_PROPERTY_KEY(WindowVisibilityAnimationTransition,
kWindowVisibilityAnimationTransitionKey,
ANIMATE_BOTH);
@@ -214,13 +216,13 @@ const int kWindowAnimation_Bounce_GrowShrinkDurationPercent = 40;
base::TimeDelta GetWindowVisibilityAnimationDuration(
const aura::Window& window) {
- int duration =
+ base::TimeDelta duration =
window.GetProperty(kWindowVisibilityAnimationDurationKey);
- if (duration == 0 && window.type() == aura::client::WINDOW_TYPE_MENU) {
+ if (duration.is_zero() && window.type() == aura::client::WINDOW_TYPE_MENU) {
return base::TimeDelta::FromMilliseconds(
kDefaultAnimationDurationForMenuMS);
}
- return base::TimeDelta::FromInternalValue(duration);
+ return duration;
}
// Gets/sets the WindowVisibilityAnimationType associated with a window.
@@ -301,7 +303,7 @@ void AnimateShowWindowCommon(aura::Window* window,
// Property sets within this scope will be implicitly animated.
ui::ScopedLayerAnimationSettings settings(window->layer()->GetAnimator());
base::TimeDelta duration = GetWindowVisibilityAnimationDuration(*window);
- if (duration.ToInternalValue() > 0)
+ if (duration > base::TimeDelta())
settings.SetTransitionDuration(duration);
window->layer()->SetTransform(end_transform);
@@ -320,7 +322,7 @@ void AnimateHideWindowCommon(aura::Window* window,
hiding_settings.layer_animation_settings()->SetAnimationMetricsReporter(
g_reporter_hide.Pointer());
base::TimeDelta duration = GetWindowVisibilityAnimationDuration(*window);
- if (duration.ToInternalValue() > 0)
+ if (duration > base::TimeDelta())
hiding_settings.layer_animation_settings()->SetTransitionDuration(duration);
window->layer()->SetOpacity(kWindowAnimation_HideOpacity);
@@ -632,14 +634,12 @@ bool HasWindowVisibilityAnimationTransition(
void SetWindowVisibilityAnimationDuration(aura::Window* window,
const base::TimeDelta& duration) {
- window->SetProperty(kWindowVisibilityAnimationDurationKey,
- static_cast<int>(duration.ToInternalValue()));
+ window->SetProperty(kWindowVisibilityAnimationDurationKey, duration);
}
base::TimeDelta GetWindowVisibilityAnimationDuration(
const aura::Window& window) {
- return base::TimeDelta::FromInternalValue(
- window.GetProperty(kWindowVisibilityAnimationDurationKey));
+ return window.GetProperty(kWindowVisibilityAnimationDurationKey);
}
void SetWindowVisibilityAnimationVerticalPosition(aura::Window* window,
diff --git a/chromium/ui/wm/core/window_modality_controller.cc b/chromium/ui/wm/core/window_modality_controller.cc
index 0501aaf037e..3c220ed1aa3 100644
--- a/chromium/ui/wm/core/window_modality_controller.cc
+++ b/chromium/ui/wm/core/window_modality_controller.cc
@@ -22,19 +22,10 @@
#include "ui/wm/core/window_util.h"
namespace wm {
-
-// Transient child's modal parent.
-extern const aura::WindowProperty<aura::Window*>* const kModalParentKey;
-DEFINE_UI_CLASS_PROPERTY_KEY(aura::Window*, kModalParentKey, NULL);
-
namespace {
bool HasAncestor(aura::Window* window, aura::Window* ancestor) {
- if (!window)
- return false;
- if (window == ancestor)
- return true;
- return HasAncestor(window->parent(), ancestor);
+ return ancestor && ancestor->Contains(window);
}
bool TransientChildIsWindowModal(aura::Window* window) {
@@ -50,15 +41,15 @@ bool TransientChildIsChildModal(aura::Window* window) {
}
aura::Window* GetModalParent(aura::Window* window) {
- return window->GetProperty(kModalParentKey);
+ return window->GetProperty(aura::client::kChildModalParentKey);
}
bool IsModalTransientChild(aura::Window* transient, aura::Window* original) {
return transient->IsVisible() &&
- (TransientChildIsWindowModal(transient) ||
- TransientChildIsSystemModal(transient) ||
- (TransientChildIsChildModal(transient) &&
- (HasAncestor(original, GetModalParent(transient)))));
+ (TransientChildIsWindowModal(transient) ||
+ TransientChildIsSystemModal(transient) ||
+ (TransientChildIsChildModal(transient) &&
+ HasAncestor(original, GetModalParent(transient))));
}
aura::Window* GetModalTransientChild(
@@ -83,7 +74,7 @@ aura::Window* GetModalTransientChild(
} // namespace
void SetModalParent(aura::Window* child, aura::Window* parent) {
- child->SetProperty(kModalParentKey, parent);
+ child->SetProperty(aura::client::kChildModalParentKey, parent);
}
aura::Window* GetModalTransient(aura::Window* window) {
diff --git a/chromium/ui/wm/public/activation_client.cc b/chromium/ui/wm/public/activation_client.cc
index 8b5b8e7518f..b653b666980 100644
--- a/chromium/ui/wm/public/activation_client.cc
+++ b/chromium/ui/wm/public/activation_client.cc
@@ -7,7 +7,6 @@
#include "ui/aura/window.h"
#include "ui/base/class_property.h"
-DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(WM_PUBLIC_EXPORT, aura::Window*)
DECLARE_UI_CLASS_PROPERTY_TYPE(wm::ActivationClient*)
namespace wm {
diff --git a/chromium/ui/wm/public/scoped_drag_drop_disabler.cc b/chromium/ui/wm/public/scoped_drag_drop_disabler.cc
index 4ca3572f752..2f30f647510 100644
--- a/chromium/ui/wm/public/scoped_drag_drop_disabler.cc
+++ b/chromium/ui/wm/public/scoped_drag_drop_disabler.cc
@@ -24,6 +24,9 @@ class NopDragDropClient : public aura::client::DragDropClient {
bool IsDragDropInProgress() override {
return false;
}
+ void AddObserver(aura::client::DragDropClientObserver* observer) override {}
+ void RemoveObserver(aura::client::DragDropClientObserver* observer) override {
+ }
};
ScopedDragDropDisabler::ScopedDragDropDisabler(aura::Window* window)