summaryrefslogtreecommitdiff
path: root/chromium/ui/views
diff options
context:
space:
mode:
authorAllan Sandfeld Jensen <allan.jensen@qt.io>2019-08-30 10:22:43 +0200
committerAllan Sandfeld Jensen <allan.jensen@qt.io>2019-08-30 12:36:28 +0000
commit271a6c3487a14599023a9106329505597638d793 (patch)
treee040d58ffc86c1480b79ca8528020ca9ec919bf8 /chromium/ui/views
parent7b2ffa587235a47d4094787d72f38102089f402a (diff)
downloadqtwebengine-chromium-271a6c3487a14599023a9106329505597638d793.tar.gz
BASELINE: Update Chromium to 77.0.3865.59
Change-Id: I1e89a5f3b009a9519a6705102ad65c92fe736f21 Reviewed-by: Michael BrĂ¼ning <michael.bruning@qt.io>
Diffstat (limited to 'chromium/ui/views')
-rw-r--r--chromium/ui/views/BUILD.gn52
-rw-r--r--chromium/ui/views/OWNERS4
-rw-r--r--chromium/ui/views/accessibility/ax_root_obj_wrapper.cc2
-rw-r--r--chromium/ui/views/accessibility/ax_tree_source_views.cc6
-rw-r--r--chromium/ui/views/accessibility/ax_tree_source_views.h1
-rw-r--r--chromium/ui/views/accessibility/ax_tree_source_views_unittest.cc2
-rw-r--r--chromium/ui/views/accessibility/ax_virtual_view_unittest.cc42
-rw-r--r--chromium/ui/views/accessibility/view_accessibility.cc8
-rw-r--r--chromium/ui/views/accessibility/view_ax_platform_node_delegate.cc91
-rw-r--r--chromium/ui/views/accessibility/view_ax_platform_node_delegate.h11
-rw-r--r--chromium/ui/views/accessibility/view_ax_platform_node_delegate_auralinux.cc25
-rw-r--r--chromium/ui/views/accessibility/view_ax_platform_node_delegate_mac.mm14
-rw-r--r--chromium/ui/views/accessibility/view_ax_platform_node_delegate_unittest.cc183
-rw-r--r--chromium/ui/views/accessible_pane_view.cc4
-rw-r--r--chromium/ui/views/accessible_pane_view.h2
-rw-r--r--chromium/ui/views/animation/animation_delegate_views.cc27
-rw-r--r--chromium/ui/views/animation/animation_delegate_views.h16
-rw-r--r--chromium/ui/views/animation/bounds_animator.cc5
-rw-r--r--chromium/ui/views/animation/bounds_animator.h5
-rw-r--r--chromium/ui/views/animation/compositor_animation_runner.cc1
-rw-r--r--chromium/ui/views/animation/compositor_animation_runner_unittest.cc9
-rw-r--r--chromium/ui/views/animation/ink_drop_host_view.cc22
-rw-r--r--chromium/ui/views/animation/ink_drop_host_view.h17
-rw-r--r--chromium/ui/views/animation/installable_ink_drop.cc179
-rw-r--r--chromium/ui/views/animation/installable_ink_drop.h105
-rw-r--r--chromium/ui/views/animation/installable_ink_drop_animator.cc257
-rw-r--r--chromium/ui/views/animation/installable_ink_drop_animator.h90
-rw-r--r--chromium/ui/views/animation/installable_ink_drop_animator_unittest.cc267
-rw-r--r--chromium/ui/views/animation/installable_ink_drop_config.h23
-rw-r--r--chromium/ui/views/animation/installable_ink_drop_painter.cc68
-rw-r--r--chromium/ui/views/animation/installable_ink_drop_painter.h53
-rw-r--r--chromium/ui/views/animation/installable_ink_drop_unittest.cc62
-rw-r--r--chromium/ui/views/bubble/bubble_dialog_delegate_view.cc31
-rw-r--r--chromium/ui/views/bubble/bubble_dialog_delegate_view.h25
-rw-r--r--chromium/ui/views/bubble/bubble_frame_view.cc23
-rw-r--r--chromium/ui/views/bubble/bubble_frame_view.h8
-rw-r--r--chromium/ui/views/bubble/bubble_frame_view_unittest.cc32
-rw-r--r--chromium/ui/views/bubble/footnote_container_view.cc45
-rw-r--r--chromium/ui/views/bubble/footnote_container_view.h10
-rw-r--r--chromium/ui/views/bubble/info_bubble.cc4
-rw-r--r--chromium/ui/views/bubble/info_bubble.h2
-rw-r--r--chromium/ui/views/bubble/tooltip_icon.cc8
-rw-r--r--chromium/ui/views/bubble/tooltip_icon.h3
-rw-r--r--chromium/ui/views/cocoa/bridge_factory_host.cc33
-rw-r--r--chromium/ui/views/cocoa/bridge_factory_host.h41
-rw-r--r--chromium/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm8
-rw-r--r--chromium/ui/views/cocoa/bridged_native_widget_unittest.mm67
-rw-r--r--chromium/ui/views/cocoa/drag_drop_client_mac.h16
-rw-r--r--chromium/ui/views/cocoa/drag_drop_client_mac.mm13
-rw-r--r--chromium/ui/views/cocoa/drag_drop_client_mac_unittest.mm30
-rw-r--r--chromium/ui/views/cocoa/native_widget_mac_ns_window_host.h (renamed from chromium/ui/views/cocoa/bridged_native_widget_host_impl.h)137
-rw-r--r--chromium/ui/views/cocoa/native_widget_mac_ns_window_host.mm (renamed from chromium/ui/views/cocoa/bridged_native_widget_host_impl.mm)477
-rw-r--r--chromium/ui/views/cocoa/text_input_host.h6
-rw-r--r--chromium/ui/views/cocoa/text_input_host.mm10
-rw-r--r--chromium/ui/views/cocoa/tooltip_manager_mac.h8
-rw-r--r--chromium/ui/views/cocoa/tooltip_manager_mac.mm4
-rw-r--r--chromium/ui/views/color_chooser/color_chooser_view.cc45
-rw-r--r--chromium/ui/views/controls/animated_image_view.cc7
-rw-r--r--chromium/ui/views/controls/animated_image_view.h3
-rw-r--r--chromium/ui/views/controls/button/button.cc16
-rw-r--r--chromium/ui/views/controls/button/button.h12
-rw-r--r--chromium/ui/views/controls/button/checkbox.cc9
-rw-r--r--chromium/ui/views/controls/button/checkbox.h3
-rw-r--r--chromium/ui/views/controls/button/image_button.cc50
-rw-r--r--chromium/ui/views/controls/button/image_button.h19
-rw-r--r--chromium/ui/views/controls/button/image_button_unittest.cc35
-rw-r--r--chromium/ui/views/controls/button/label_button.cc15
-rw-r--r--chromium/ui/views/controls/button/label_button.h3
-rw-r--r--chromium/ui/views/controls/button/label_button_label.cc2
-rw-r--r--chromium/ui/views/controls/button/label_button_label_unittest.cc2
-rw-r--r--chromium/ui/views/controls/button/label_button_unittest.cc12
-rw-r--r--chromium/ui/views/controls/button/md_text_button.cc12
-rw-r--r--chromium/ui/views/controls/button/menu_button.cc14
-rw-r--r--chromium/ui/views/controls/button/menu_button.h8
-rw-r--r--chromium/ui/views/controls/button/menu_button_controller.cc26
-rw-r--r--chromium/ui/views/controls/button/menu_button_unittest.cc4
-rw-r--r--chromium/ui/views/controls/button/radio_button.cc11
-rw-r--r--chromium/ui/views/controls/button/radio_button.h4
-rw-r--r--chromium/ui/views/controls/button/toggle_button.cc10
-rw-r--r--chromium/ui/views/controls/button/toggle_button.h3
-rw-r--r--chromium/ui/views/controls/combobox/combobox.cc7
-rw-r--r--chromium/ui/views/controls/combobox/combobox.h3
-rw-r--r--chromium/ui/views/controls/editable_combobox/editable_combobox.cc65
-rw-r--r--chromium/ui/views/controls/editable_combobox/editable_combobox.h17
-rw-r--r--chromium/ui/views/controls/editable_combobox/editable_combobox_unittest.cc116
-rw-r--r--chromium/ui/views/controls/focus_ring.cc13
-rw-r--r--chromium/ui/views/controls/focus_ring.h3
-rw-r--r--chromium/ui/views/controls/image_view.cc11
-rw-r--r--chromium/ui/views/controls/image_view.h4
-rw-r--r--chromium/ui/views/controls/image_view_base.h1
-rw-r--r--chromium/ui/views/controls/image_view_unittest.cc6
-rw-r--r--chromium/ui/views/controls/label.cc261
-rw-r--r--chromium/ui/views/controls/label.h93
-rw-r--r--chromium/ui/views/controls/label_unittest.cc79
-rw-r--r--chromium/ui/views/controls/link.cc13
-rw-r--r--chromium/ui/views/controls/link.h3
-rw-r--r--chromium/ui/views/controls/menu/menu_closure_animation_mac.h5
-rw-r--r--chromium/ui/views/controls/menu/menu_closure_animation_mac.mm2
-rw-r--r--chromium/ui/views/controls/menu/menu_closure_animation_mac_unittest.cc28
-rw-r--r--chromium/ui/views/controls/menu/menu_cocoa_watcher_mac.h16
-rw-r--r--chromium/ui/views/controls/menu/menu_cocoa_watcher_mac.mm36
-rw-r--r--chromium/ui/views/controls/menu/menu_config_mac.mm2
-rw-r--r--chromium/ui/views/controls/menu/menu_controller.cc56
-rw-r--r--chromium/ui/views/controls/menu/menu_controller.h10
-rw-r--r--chromium/ui/views/controls/menu/menu_controller_unittest.cc25
-rw-r--r--chromium/ui/views/controls/menu/menu_delegate.h12
-rw-r--r--chromium/ui/views/controls/menu/menu_image_util.cc10
-rw-r--r--chromium/ui/views/controls/menu/menu_image_util.h8
-rw-r--r--chromium/ui/views/controls/menu/menu_item_view.cc22
-rw-r--r--chromium/ui/views/controls/menu/menu_item_view.h6
-rw-r--r--chromium/ui/views/controls/menu/menu_item_view_unittest.cc4
-rw-r--r--chromium/ui/views/controls/menu/menu_pre_target_handler_aura.cc7
-rw-r--r--chromium/ui/views/controls/menu/menu_runner_impl.cc3
-rw-r--r--chromium/ui/views/controls/menu/menu_runner_impl.h2
-rw-r--r--chromium/ui/views/controls/menu/menu_scroll_view_container.cc4
-rw-r--r--chromium/ui/views/controls/menu/menu_scroll_view_container.h2
-rw-r--r--chromium/ui/views/controls/menu/menu_separator.cc4
-rw-r--r--chromium/ui/views/controls/menu/menu_separator.h2
-rw-r--r--chromium/ui/views/controls/menu/submenu_view.cc36
-rw-r--r--chromium/ui/views/controls/menu/submenu_view.h7
-rw-r--r--chromium/ui/views/controls/message_box_view.cc43
-rw-r--r--chromium/ui/views/controls/message_box_view.h8
-rw-r--r--chromium/ui/views/controls/native/native_view_host.cc9
-rw-r--r--chromium/ui/views/controls/native/native_view_host.h4
-rw-r--r--chromium/ui/views/controls/native/native_view_host_aura.cc17
-rw-r--r--chromium/ui/views/controls/native/native_view_host_mac.h9
-rw-r--r--chromium/ui/views/controls/native/native_view_host_mac.mm39
-rw-r--r--chromium/ui/views/controls/progress_bar.cc11
-rw-r--r--chromium/ui/views/controls/progress_bar.h5
-rw-r--r--chromium/ui/views/controls/resize_area.cc10
-rw-r--r--chromium/ui/views/controls/resize_area.h3
-rw-r--r--chromium/ui/views/controls/resize_area_unittest.cc5
-rw-r--r--chromium/ui/views/controls/scroll_view.cc36
-rw-r--r--chromium/ui/views/controls/scroll_view.h25
-rw-r--r--chromium/ui/views/controls/scroll_view_unittest.cc2
-rw-r--r--chromium/ui/views/controls/scrollbar/base_scroll_bar_button.cc4
-rw-r--r--chromium/ui/views/controls/scrollbar/base_scroll_bar_button.h2
-rw-r--r--chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc4
-rw-r--r--chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.h2
-rw-r--r--chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.h2
-rw-r--r--chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.mm4
-rw-r--r--chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc4
-rw-r--r--chromium/ui/views/controls/scrollbar/overlay_scroll_bar.h2
-rw-r--r--chromium/ui/views/controls/scrollbar/scroll_bar.cc8
-rw-r--r--chromium/ui/views/controls/scrollbar/scroll_bar.h2
-rw-r--r--chromium/ui/views/controls/scrollbar/scroll_bar_views.cc12
-rw-r--r--chromium/ui/views/controls/scrollbar/scroll_bar_views.h3
-rw-r--r--chromium/ui/views/controls/separator.cc31
-rw-r--r--chromium/ui/views/controls/separator.h6
-rw-r--r--chromium/ui/views/controls/slider.cc44
-rw-r--r--chromium/ui/views/controls/slider.h16
-rw-r--r--chromium/ui/views/controls/slider_unittest.cc36
-rw-r--r--chromium/ui/views/controls/styled_label.cc67
-rw-r--r--chromium/ui/views/controls/styled_label.h25
-rw-r--r--chromium/ui/views/controls/styled_label_unittest.cc39
-rw-r--r--chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc154
-rw-r--r--chromium/ui/views/controls/tabbed_pane/tabbed_pane.h57
-rw-r--r--chromium/ui/views/controls/tabbed_pane/tabbed_pane_accessibility_mac_unittest.mm13
-rw-r--r--chromium/ui/views/controls/tabbed_pane/tabbed_pane_unittest.cc92
-rw-r--r--chromium/ui/views/controls/textfield/textfield.cc40
-rw-r--r--chromium/ui/views/controls/textfield/textfield.h17
-rw-r--r--chromium/ui/views/controls/textfield/textfield_model.cc30
-rw-r--r--chromium/ui/views/controls/textfield/textfield_model.h8
-rw-r--r--chromium/ui/views/controls/textfield/textfield_model_unittest.cc55
-rw-r--r--chromium/ui/views/controls/textfield/textfield_unittest.cc181
-rw-r--r--chromium/ui/views/controls/throbber.cc39
-rw-r--r--chromium/ui/views/controls/throbber.h13
-rw-r--r--chromium/ui/views/controls/tree/tree_view.cc124
-rw-r--r--chromium/ui/views/controls/tree/tree_view.h12
-rw-r--r--chromium/ui/views/controls/tree/tree_view_unittest.cc31
-rw-r--r--chromium/ui/views/controls/webview/unhandled_keyboard_event_handler_mac.mm4
-rw-r--r--chromium/ui/views/controls/webview/web_dialog_view.cc4
-rw-r--r--chromium/ui/views/controls/webview/web_dialog_view.h1
-rw-r--r--chromium/ui/views/controls/webview/webview.cc62
-rw-r--r--chromium/ui/views/controls/webview/webview.h30
-rw-r--r--chromium/ui/views/controls/webview/webview_unittest.cc46
-rw-r--r--chromium/ui/views/corewm/tooltip_aura.cc52
-rw-r--r--chromium/ui/views/corewm/tooltip_controller_unittest.cc2
-rw-r--r--chromium/ui/views/drag_utils.h9
-rw-r--r--chromium/ui/views/drag_utils_aura.cc7
-rw-r--r--chromium/ui/views/drag_utils_mac.mm2
-rw-r--r--chromium/ui/views/event_utils.cc21
-rw-r--r--chromium/ui/views/event_utils.h28
-rw-r--r--chromium/ui/views/examples/BUILD.gn1
-rw-r--r--chromium/ui/views/examples/DEPS1
-rw-r--r--chromium/ui/views/examples/animated_image_view_example.cc6
-rw-r--r--chromium/ui/views/examples/bubble_example.cc12
-rw-r--r--chromium/ui/views/examples/button_example.cc4
-rw-r--r--chromium/ui/views/examples/button_sticker_sheet.cc46
-rw-r--r--chromium/ui/views/examples/combobox_example.cc4
-rw-r--r--chromium/ui/views/examples/dialog_example.cc41
-rw-r--r--chromium/ui/views/examples/example_base.cc35
-rw-r--r--chromium/ui/views/examples/example_base.h2
-rw-r--r--chromium/ui/views/examples/examples_main.cc9
-rw-r--r--chromium/ui/views/examples/examples_window.cc48
-rw-r--r--chromium/ui/views/examples/flex_layout_example.cc9
-rw-r--r--chromium/ui/views/examples/label_example.cc98
-rw-r--r--chromium/ui/views/examples/layout_example_base.cc2
-rw-r--r--chromium/ui/views/examples/message_box_example.cc24
-rw-r--r--chromium/ui/views/examples/multiline_example.cc58
-rw-r--r--chromium/ui/views/examples/native_theme_example.cc13
-rw-r--r--chromium/ui/views/examples/progress_bar_example.cc31
-rw-r--r--chromium/ui/views/examples/radio_button_example.cc22
-rw-r--r--chromium/ui/views/examples/scroll_view_example.cc30
-rw-r--r--chromium/ui/views/examples/slider_example.cc4
-rw-r--r--chromium/ui/views/examples/tabbed_pane_example.cc30
-rw-r--r--chromium/ui/views/examples/table_example.cc39
-rw-r--r--chromium/ui/views/examples/text_example.cc24
-rw-r--r--chromium/ui/views/examples/textfield_example.cc114
-rw-r--r--chromium/ui/views/examples/toggle_button_example.cc2
-rw-r--r--chromium/ui/views/examples/tree_view_example.cc37
-rw-r--r--chromium/ui/views/examples/vector_example.cc9
-rw-r--r--chromium/ui/views/examples/widget_example.cc23
-rw-r--r--chromium/ui/views/focus/focus_traversal_unittest.cc240
-rw-r--r--chromium/ui/views/input_event_activation_protector.cc50
-rw-r--r--chromium/ui/views/input_event_activation_protector.h49
-rw-r--r--chromium/ui/views/layout/box_layout.cc78
-rw-r--r--chromium/ui/views/layout/box_layout.h4
-rw-r--r--chromium/ui/views/layout/box_layout_unittest.cc173
-rw-r--r--chromium/ui/views/layout/flex_layout.cc1014
-rw-r--r--chromium/ui/views/layout/flex_layout.h178
-rw-r--r--chromium/ui/views/layout/flex_layout_types.cc157
-rw-r--r--chromium/ui/views/layout/flex_layout_types.h118
-rw-r--r--chromium/ui/views/layout/flex_layout_types_internal.cc123
-rw-r--r--chromium/ui/views/layout/flex_layout_types_internal.h98
-rw-r--r--chromium/ui/views/layout/flex_layout_types_internal_unittest.cc50
-rw-r--r--chromium/ui/views/layout/flex_layout_unittest.cc468
-rw-r--r--chromium/ui/views/layout/grid_layout.cc70
-rw-r--r--chromium/ui/views/layout/grid_layout.h71
-rw-r--r--chromium/ui/views/layout/grid_layout_unittest.cc546
-rw-r--r--chromium/ui/views/layout/interpolating_layout_manager.cc251
-rw-r--r--chromium/ui/views/layout/interpolating_layout_manager.h132
-rw-r--r--chromium/ui/views/layout/interpolating_layout_manager_unittest.cc323
-rw-r--r--chromium/ui/views/layout/layout_manager_base.cc171
-rw-r--r--chromium/ui/views/layout/layout_manager_base.h125
-rw-r--r--chromium/ui/views/layout/layout_manager_base_unittest.cc479
-rw-r--r--chromium/ui/views/layout/layout_types.cc62
-rw-r--r--chromium/ui/views/layout/layout_types.h58
-rw-r--r--chromium/ui/views/linux_ui/status_icon_linux.cc8
-rw-r--r--chromium/ui/views/linux_ui/status_icon_linux.h16
-rw-r--r--chromium/ui/views/metadata/metadata_header_macros.h6
-rw-r--r--chromium/ui/views/metadata/metadata_impl_macros.h6
-rw-r--r--chromium/ui/views/metadata/metadata_macros_internal.h10
-rw-r--r--chromium/ui/views/metadata/metadata_types.cc23
-rw-r--r--chromium/ui/views/metadata/metadata_types.h6
-rw-r--r--chromium/ui/views/metadata/metadata_unittest.cc1
-rw-r--r--chromium/ui/views/mouse_watcher.cc4
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/blue_button.pngbin198 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/blue_button_focused.pngbin199 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/blue_button_focused_hover.pngbin238 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/blue_button_focused_pressed.pngbin177 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/blue_button_hover.pngbin239 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/blue_button_inactive.pngbin206 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/blue_button_pressed.pngbin176 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/button.pngbin153 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/button_focused.pngbin205 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/button_focused_hover.pngbin239 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/button_focused_pressed.pngbin180 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/button_hover.pngbin181 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/button_inactive.pngbin132 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/button_pressed.pngbin180 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/checkbox.pngbin157 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/checkbox_checked.pngbin222 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/checkbox_checked_hover.pngbin227 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/checkbox_checked_inactive.pngbin203 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/checkbox_checked_pressed.pngbin280 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/checkbox_focused.pngbin208 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/checkbox_focused_checked.pngbin302 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/checkbox_focused_checked_hover.pngbin320 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/checkbox_focused_checked_pressed.pngbin288 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/checkbox_focused_hover.pngbin245 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/checkbox_focused_pressed.pngbin190 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/checkbox_hover.pngbin165 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/checkbox_inactive.pngbin135 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/checkbox_pressed.pngbin181 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/folder_open.pngbin393 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_100_percent/common/folder_open_rtl.pngbin390 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/blue_button.pngbin315 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/blue_button_focused.pngbin329 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/blue_button_focused_hover.pngbin355 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/blue_button_focused_pressed.pngbin282 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/blue_button_hover.pngbin348 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/blue_button_inactive.pngbin255 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/blue_button_pressed.pngbin287 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/button.pngbin218 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/button_focused.pngbin303 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/button_focused_hover.pngbin326 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/button_focused_pressed.pngbin279 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/button_hover.pngbin225 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/button_inactive.pngbin162 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/button_pressed.pngbin224 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/checkbox.pngbin220 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/checkbox_checked.pngbin480 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/checkbox_checked_hover.pngbin512 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/checkbox_checked_inactive.pngbin383 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/checkbox_checked_pressed.pngbin493 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/checkbox_focused.pngbin312 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/checkbox_focused_checked.pngbin718 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/checkbox_focused_checked_hover.pngbin759 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/checkbox_focused_checked_pressed.pngbin699 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/checkbox_focused_hover.pngbin377 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/checkbox_focused_pressed.pngbin263 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/checkbox_hover.pngbin241 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/checkbox_inactive.pngbin159 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/checkbox_pressed.pngbin214 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/folder_open.pngbin1308 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/default_200_percent/common/folder_open_rtl.pngbin1179 -> 0 bytes
-rw-r--r--chromium/ui/views/resources/views_resources.grd23
-rw-r--r--chromium/ui/views/touchui/touch_selection_controller_impl.cc5
-rw-r--r--chromium/ui/views/touchui/touch_selection_menu_views.cc9
-rw-r--r--chromium/ui/views/touchui/touch_selection_menu_views.h2
-rw-r--r--chromium/ui/views/view.cc115
-rw-r--r--chromium/ui/views/view.h37
-rw-r--r--chromium/ui/views/view_class_properties.cc3
-rw-r--r--chromium/ui/views/view_class_properties.h7
-rw-r--r--chromium/ui/views/view_observer.h3
-rw-r--r--chromium/ui/views/view_unittest.cc102
-rw-r--r--chromium/ui/views/views_features.cc6
-rw-r--r--chromium/ui/views/views_features.h5
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.cc14
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11.h2
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc27
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc7
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h2
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc7
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.cc9
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h2
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_drop_target_win.cc2
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_focus_rules.cc4
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_focus_rules_unittest.cc10
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.cc36
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_native_widget_aura.h12
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc47
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_x11.h2
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_screen_x11_unittest.cc3
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host.h7
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc23
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h4
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.cc47
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_win.h8
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.cc1839
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h236
-rw-r--r--chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_x11_unittest.cc2
-rw-r--r--chromium/ui/views/widget/desktop_aura/x11_desktop_handler.cc3
-rw-r--r--chromium/ui/views/widget/desktop_aura/x11_topmost_window_finder_interactive_uitest.cc5
-rw-r--r--chromium/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc5
-rw-r--r--chromium/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h2
-rw-r--r--chromium/ui/views/widget/native_widget_aura.cc42
-rw-r--r--chromium/ui/views/widget/native_widget_aura.h16
-rw-r--r--chromium/ui/views/widget/native_widget_mac.h39
-rw-r--r--chromium/ui/views/widget/native_widget_mac.mm409
-rw-r--r--chromium/ui/views/widget/native_widget_mac_unittest.mm52
-rw-r--r--chromium/ui/views/widget/native_widget_private.cc2
-rw-r--r--chromium/ui/views/widget/native_widget_private.h10
-rw-r--r--chromium/ui/views/widget/root_view.cc15
-rw-r--r--chromium/ui/views/widget/root_view.h3
-rw-r--r--chromium/ui/views/widget/widget.cc52
-rw-r--r--chromium/ui/views/widget/widget.h21
-rw-r--r--chromium/ui/views/widget/widget_delegate.cc17
-rw-r--r--chromium/ui/views/widget/widget_delegate.h6
-rw-r--r--chromium/ui/views/widget/widget_hwnd_utils.cc5
-rw-r--r--chromium/ui/views/widget/widget_interactive_uitest.cc2
-rw-r--r--chromium/ui/views/widget/widget_unittest.cc20
-rw-r--r--chromium/ui/views/widget/widget_utils_mac.mm4
-rw-r--r--chromium/ui/views/widget/window_reorderer.cc13
-rw-r--r--chromium/ui/views/widget/window_reorderer_unittest.cc38
-rw-r--r--chromium/ui/views/win/hwnd_message_handler.cc90
-rw-r--r--chromium/ui/views/win/hwnd_message_handler.h11
-rw-r--r--chromium/ui/views/win/hwnd_util.h7
-rw-r--r--chromium/ui/views/win/hwnd_util_aurawin.cc14
-rw-r--r--chromium/ui/views/win/pen_event_processor.cc2
-rw-r--r--chromium/ui/views/window/client_view.cc11
-rw-r--r--chromium/ui/views/window/client_view.h4
-rw-r--r--chromium/ui/views/window/custom_frame_view.cc23
-rw-r--r--chromium/ui/views/window/custom_frame_view.h8
-rw-r--r--chromium/ui/views/window/dialog_client_view.cc57
-rw-r--r--chromium/ui/views/window/dialog_client_view.h6
-rw-r--r--chromium/ui/views/window/dialog_client_view_unittest.cc48
-rw-r--r--chromium/ui/views/window/dialog_delegate.cc4
-rw-r--r--chromium/ui/views/window/dialog_delegate.h6
-rw-r--r--chromium/ui/views/window/non_client_view.cc47
-rw-r--r--chromium/ui/views/window/non_client_view.h22
382 files changed, 9110 insertions, 6342 deletions
diff --git a/chromium/ui/views/BUILD.gn b/chromium/ui/views/BUILD.gn
index 081c13d1250..263f4a8b8ef 100644
--- a/chromium/ui/views/BUILD.gn
+++ b/chromium/ui/views/BUILD.gn
@@ -84,6 +84,9 @@ jumbo_component("views") {
"animation/ink_drop_stub.h",
"animation/ink_drop_util.h",
"animation/installable_ink_drop.h",
+ "animation/installable_ink_drop_animator.h",
+ "animation/installable_ink_drop_config.h",
+ "animation/installable_ink_drop_painter.h",
"animation/scroll_animator.h",
"animation/square_ink_drop_ripple.h",
"background.h",
@@ -94,8 +97,7 @@ jumbo_component("views") {
"bubble/info_bubble.h",
"bubble/tooltip_icon.h",
"button_drag_utils.h",
- "cocoa/bridge_factory_host.h",
- "cocoa/bridged_native_widget_host_impl.h",
+ "cocoa/native_widget_mac_ns_window_host.h",
"color_chooser/color_chooser_listener.h",
"color_chooser/color_chooser_view.h",
"context_menu_controller.h",
@@ -190,24 +192,23 @@ jumbo_component("views") {
"drag_utils.h",
"event_monitor.h",
"event_monitor_mac.h",
- "event_utils.h",
"focus/external_focus_tracker.h",
"focus/focus_manager.h",
"focus/focus_manager_delegate.h",
"focus/focus_manager_factory.h",
"focus/focus_search.h",
"focus/widget_focus_manager.h",
+ "input_event_activation_protector.h",
"layout/box_layout.h",
"layout/fill_layout.h",
"layout/flex_layout.h",
"layout/flex_layout_types.h",
"layout/grid_layout.h",
+ "layout/interpolating_layout_manager.h",
"layout/layout_manager.h",
+ "layout/layout_manager_base.h",
"layout/layout_provider.h",
- "linux_ui/device_scale_factor_observer.h",
- "linux_ui/linux_ui.h",
- "linux_ui/status_icon_linux.h",
- "linux_ui/window_button_order_observer.h",
+ "layout/layout_types.h",
"masked_targeter_delegate.h",
"metadata/metadata_cache.h",
"metadata/metadata_header_macros.h",
@@ -306,6 +307,8 @@ jumbo_component("views") {
"animation/ink_drop_stub.cc",
"animation/ink_drop_util.cc",
"animation/installable_ink_drop.cc",
+ "animation/installable_ink_drop_animator.cc",
+ "animation/installable_ink_drop_painter.cc",
"animation/scroll_animator.cc",
"animation/square_ink_drop_ripple.cc",
"background.cc",
@@ -398,23 +401,23 @@ jumbo_component("views") {
"drag_utils.cc",
"drag_utils_mac.mm",
"event_monitor_mac.mm",
- "event_utils.cc",
"focus/external_focus_tracker.cc",
"focus/focus_manager.cc",
"focus/focus_manager_factory.cc",
"focus/focus_search.cc",
"focus/widget_focus_manager.cc",
+ "input_event_activation_protector.cc",
"layout/box_layout.cc",
"layout/fill_layout.cc",
"layout/flex_layout.cc",
"layout/flex_layout_types.cc",
"layout/flex_layout_types_internal.cc",
"layout/grid_layout.cc",
+ "layout/interpolating_layout_manager.cc",
"layout/layout_manager.cc",
+ "layout/layout_manager_base.cc",
"layout/layout_provider.cc",
- "linux_ui/linux_ui.cc",
- "linux_ui/status_icon_linux.cc",
- "linux_ui/window_button_order_provider.cc",
+ "layout/layout_types.cc",
"masked_targeter_delegate.cc",
"metadata/metadata_cache.cc",
"metadata/metadata_types.cc",
@@ -479,10 +482,9 @@ jumbo_component("views") {
# Internal sources. TODO(https://crbug.com/871123): Move more headers from
# public into this list, along with the implementation file.
sources += [
- "cocoa/bridge_factory_host.cc",
- "cocoa/bridged_native_widget_host_impl.mm",
"cocoa/drag_drop_client_mac.h",
"cocoa/drag_drop_client_mac.mm",
+ "cocoa/native_widget_mac_ns_window_host.mm",
"cocoa/text_input_host.h",
"cocoa/text_input_host.mm",
"cocoa/tooltip_manager_mac.h",
@@ -545,23 +547,21 @@ jumbo_component("views") {
"//ui/base/ime/linux",
"//ui/shell_dialogs",
]
- } else {
- public -= [
+ public += [
+ "linux_ui/device_scale_factor_observer.h",
"linux_ui/linux_ui.h",
+ "linux_ui/status_icon_linux.h",
"linux_ui/window_button_order_observer.h",
]
- sources -= [
+ sources += [
"linux_ui/linux_ui.cc",
+ "linux_ui/status_icon_linux.cc",
"linux_ui/window_button_order_provider.cc",
]
}
if (is_chromeos) {
- public -= [ "linux_ui/status_icon_linux.h" ]
- sources -= [
- "controls/menu/menu_config_linux.cc",
- "linux_ui/status_icon_linux.cc",
- ]
+ sources -= [ "controls/menu/menu_config_linux.cc" ]
}
if (is_win) {
@@ -961,7 +961,10 @@ jumbo_source_set("test_support") {
}
}
if (use_x11) {
- deps += [ "//ui/gfx/x" ]
+ deps += [
+ "//ui/events/x",
+ "//ui/gfx/x",
+ ]
}
if (ozone_platform_x11) {
deps += [ "//ui/base/x" ]
@@ -985,6 +988,7 @@ test("views_unittests") {
"animation/ink_drop_impl_unittest.cc",
"animation/ink_drop_ripple_unittest.cc",
"animation/ink_drop_unittest.cc",
+ "animation/installable_ink_drop_animator_unittest.cc",
"animation/installable_ink_drop_unittest.cc",
"animation/square_ink_drop_ripple_unittest.cc",
"border_unittest.cc",
@@ -1007,6 +1011,7 @@ test("views_unittests") {
"controls/editable_combobox/editable_combobox_unittest.cc",
"controls/image_view_unittest.cc",
"controls/label_unittest.cc",
+ "controls/menu/menu_closure_animation_mac_unittest.cc",
"controls/menu/menu_controller_unittest.cc",
"controls/menu/menu_item_view_unittest.cc",
"controls/menu/menu_model_adapter_unittest.cc",
@@ -1041,8 +1046,11 @@ test("views_unittests") {
"focus/focus_traversal_unittest.cc",
"layout/box_layout_unittest.cc",
"layout/fill_layout_unittest.cc",
+ "layout/flex_layout_types_internal_unittest.cc",
"layout/flex_layout_unittest.cc",
"layout/grid_layout_unittest.cc",
+ "layout/interpolating_layout_manager_unittest.cc",
+ "layout/layout_manager_base_unittest.cc",
"metadata/metadata_unittest.cc",
"metadata/type_conversion_unittest.cc",
"paint_info_unittest.cc",
diff --git a/chromium/ui/views/OWNERS b/chromium/ui/views/OWNERS
index a5aeea2cc4d..3da3cff33a4 100644
--- a/chromium/ui/views/OWNERS
+++ b/chromium/ui/views/OWNERS
@@ -1,10 +1,12 @@
# Prefer tapted@ for mac specific changes.
+kylixrd@chromium.org
msw@chromium.org
pkasting@chromium.org
-sadrul@chromium.org
+robliao@chromium.org
sky@chromium.org
tapted@chromium.org
+weili@chromium.org
# Prefer ellyjones@ for any changes to these files.
per-file *_mac.*=ellyjones@chromium.org
diff --git a/chromium/ui/views/accessibility/ax_root_obj_wrapper.cc b/chromium/ui/views/accessibility/ax_root_obj_wrapper.cc
index e03f06abf9b..c5bc7b0efa1 100644
--- a/chromium/ui/views/accessibility/ax_root_obj_wrapper.cc
+++ b/chromium/ui/views/accessibility/ax_root_obj_wrapper.cc
@@ -32,7 +32,7 @@ AXRootObjWrapper::~AXRootObjWrapper() {
bool AXRootObjWrapper::HasChild(views::AXAuraObjWrapper* child) {
std::vector<views::AXAuraObjWrapper*> children;
GetChildren(&children);
- return base::ContainsValue(children, child);
+ return base::Contains(children, child);
}
bool AXRootObjWrapper::IsIgnored() {
diff --git a/chromium/ui/views/accessibility/ax_tree_source_views.cc b/chromium/ui/views/accessibility/ax_tree_source_views.cc
index 1cb8e7cf6f7..9e52448ad75 100644
--- a/chromium/ui/views/accessibility/ax_tree_source_views.cc
+++ b/chromium/ui/views/accessibility/ax_tree_source_views.cc
@@ -99,8 +99,12 @@ AXAuraObjWrapper* AXTreeSourceViews::GetParent(AXAuraObjWrapper* node) const {
return parent;
}
+bool AXTreeSourceViews::IsIgnored(AXAuraObjWrapper* node) const {
+ return node && node->IsIgnored();
+}
+
bool AXTreeSourceViews::IsValid(AXAuraObjWrapper* node) const {
- return node && !node->IsIgnored();
+ return node;
}
bool AXTreeSourceViews::IsEqual(AXAuraObjWrapper* node1,
diff --git a/chromium/ui/views/accessibility/ax_tree_source_views.h b/chromium/ui/views/accessibility/ax_tree_source_views.h
index 12d1f3b5ada..d7256c6d838 100644
--- a/chromium/ui/views/accessibility/ax_tree_source_views.h
+++ b/chromium/ui/views/accessibility/ax_tree_source_views.h
@@ -46,6 +46,7 @@ class VIEWS_EXPORT AXTreeSourceViews
void GetChildren(AXAuraObjWrapper* node,
std::vector<AXAuraObjWrapper*>* out_children) const override;
AXAuraObjWrapper* GetParent(AXAuraObjWrapper* node) const override;
+ bool IsIgnored(AXAuraObjWrapper* node) const override;
bool IsValid(AXAuraObjWrapper* node) const override;
bool IsEqual(AXAuraObjWrapper* node1, AXAuraObjWrapper* node2) const override;
AXAuraObjWrapper* GetNull() const override;
diff --git a/chromium/ui/views/accessibility/ax_tree_source_views_unittest.cc b/chromium/ui/views/accessibility/ax_tree_source_views_unittest.cc
index f94c0082a18..aeff646bcf7 100644
--- a/chromium/ui/views/accessibility/ax_tree_source_views_unittest.cc
+++ b/chromium/ui/views/accessibility/ax_tree_source_views_unittest.cc
@@ -151,7 +151,7 @@ TEST_F(AXTreeSourceViewsTest, IgnoredView) {
AXAuraObjCache cache;
TestAXTreeSourceViews tree(cache.GetOrCreate(widget_.get()), &cache);
- EXPECT_FALSE(tree.IsValid(cache.GetOrCreate(ignored_view)));
+ EXPECT_TRUE(tree.IsValid(cache.GetOrCreate(ignored_view)));
}
} // namespace
diff --git a/chromium/ui/views/accessibility/ax_virtual_view_unittest.cc b/chromium/ui/views/accessibility/ax_virtual_view_unittest.cc
index cdb60abc79f..e7520c33976 100644
--- a/chromium/ui/views/accessibility/ax_virtual_view_unittest.cc
+++ b/chromium/ui/views/accessibility/ax_virtual_view_unittest.cc
@@ -343,5 +343,47 @@ TEST_F(AXVirtualViewTest, OverrideFocus) {
button_accessibility.GetFocusedDescendant());
}
+TEST_F(AXVirtualViewTest, Navigation) {
+ ASSERT_EQ(0, virtual_label_->GetChildCount());
+
+ AXVirtualView* virtual_child_1 = new AXVirtualView;
+ virtual_label_->AddChildView(base::WrapUnique(virtual_child_1));
+ EXPECT_EQ(1, virtual_label_->GetChildCount());
+
+ AXVirtualView* virtual_child_2 = new AXVirtualView;
+ virtual_label_->AddChildView(base::WrapUnique(virtual_child_2));
+ EXPECT_EQ(2, virtual_label_->GetChildCount());
+
+ AXVirtualView* virtual_child_3 = new AXVirtualView;
+ virtual_label_->AddChildView(base::WrapUnique(virtual_child_3));
+
+ AXVirtualView* virtual_child_4 = new AXVirtualView;
+ virtual_child_2->AddChildView(base::WrapUnique(virtual_child_4));
+
+ EXPECT_EQ(nullptr, virtual_label_->GetNextSibling());
+ EXPECT_EQ(nullptr, virtual_label_->GetPreviousSibling());
+ EXPECT_EQ(0, virtual_label_->GetIndexInParent());
+
+ EXPECT_EQ(virtual_child_2->GetNativeObject(),
+ virtual_child_1->GetNextSibling());
+ EXPECT_EQ(nullptr, virtual_child_1->GetPreviousSibling());
+ EXPECT_EQ(0, virtual_child_1->GetIndexInParent());
+
+ EXPECT_EQ(virtual_child_3->GetNativeObject(),
+ virtual_child_2->GetNextSibling());
+ EXPECT_EQ(virtual_child_1->GetNativeObject(),
+ virtual_child_2->GetPreviousSibling());
+ EXPECT_EQ(1, virtual_child_2->GetIndexInParent());
+
+ EXPECT_EQ(nullptr, virtual_child_3->GetNextSibling());
+ EXPECT_EQ(virtual_child_2->GetNativeObject(),
+ virtual_child_3->GetPreviousSibling());
+ EXPECT_EQ(2, virtual_child_3->GetIndexInParent());
+
+ EXPECT_EQ(nullptr, virtual_child_4->GetNextSibling());
+ EXPECT_EQ(nullptr, virtual_child_4->GetPreviousSibling());
+ EXPECT_EQ(0, virtual_child_4->GetIndexInParent());
+}
+
} // namespace test
} // namespace views
diff --git a/chromium/ui/views/accessibility/view_accessibility.cc b/chromium/ui/views/accessibility/view_accessibility.cc
index aca46ef2d5c..4bc4f4067c3 100644
--- a/chromium/ui/views/accessibility/view_accessibility.cc
+++ b/chromium/ui/views/accessibility/view_accessibility.cc
@@ -189,6 +189,14 @@ void ViewAccessibility::GetAccessibleNodeData(ui::AXNodeData* data) const {
data->AddStringAttribute(ax::mojom::StringAttribute::kClassName,
view_->GetClassName());
+ if (IsIgnored()) {
+ // Prevent screen readers from navigating to or speaking ignored nodes.
+ data->AddState(ax::mojom::State::kInvisible);
+ data->AddState(ax::mojom::State::kIgnored);
+ data->role = ax::mojom::Role::kIgnored;
+ return;
+ }
+
if (view_->IsAccessibilityFocusable())
data->AddState(ax::mojom::State::kFocusable);
diff --git a/chromium/ui/views/accessibility/view_ax_platform_node_delegate.cc b/chromium/ui/views/accessibility/view_ax_platform_node_delegate.cc
index 49769ae210c..fed95665862 100644
--- a/chromium/ui/views/accessibility/view_ax_platform_node_delegate.cc
+++ b/chromium/ui/views/accessibility/view_ax_platform_node_delegate.cc
@@ -399,10 +399,101 @@ base::string16 ViewAXPlatformNodeDelegate::GetAuthorUniqueId() const {
return base::string16();
}
+bool ViewAXPlatformNodeDelegate::IsMinimized() const {
+ Widget* widget = view()->GetWidget();
+ return widget && widget->IsMinimized();
+}
+
const ui::AXUniqueId& ViewAXPlatformNodeDelegate::GetUniqueId() const {
return ViewAccessibility::GetUniqueId();
}
+bool ViewAXPlatformNodeDelegate::IsOrderedSetItem() const {
+ const ui::AXNodeData& data = GetData();
+ return (view()->GetGroup() >= 0) ||
+ (data.HasIntAttribute(ax::mojom::IntAttribute::kPosInSet) &&
+ data.HasIntAttribute(ax::mojom::IntAttribute::kSetSize));
+}
+
+bool ViewAXPlatformNodeDelegate::IsOrderedSet() const {
+ return (view()->GetGroup() >= 0) ||
+ GetData().HasIntAttribute(ax::mojom::IntAttribute::kSetSize);
+}
+
+base::Optional<int> ViewAXPlatformNodeDelegate::GetPosInSet() const {
+ // Consider overridable attributes first.
+ const ui::AXNodeData& data = GetData();
+ if (data.HasIntAttribute(ax::mojom::IntAttribute::kPosInSet))
+ return data.GetIntAttribute(ax::mojom::IntAttribute::kPosInSet);
+
+ std::vector<View*> views_in_group;
+ GetViewsInGroupForSet(&views_in_group);
+ if (views_in_group.empty())
+ return base::nullopt;
+ // Check this is in views_in_group; it may be removed if it is ignored.
+ auto found_view =
+ std::find(views_in_group.begin(), views_in_group.end(), view());
+ if (found_view == views_in_group.end())
+ return base::nullopt;
+
+ int posInSet = std::distance(views_in_group.begin(), found_view);
+ // posInSet is zero-based; users expect one-based, so increment.
+ return ++posInSet;
+}
+
+base::Optional<int> ViewAXPlatformNodeDelegate::GetSetSize() const {
+ // Consider overridable attributes first.
+ const ui::AXNodeData& data = GetData();
+ if (data.HasIntAttribute(ax::mojom::IntAttribute::kSetSize))
+ return data.GetIntAttribute(ax::mojom::IntAttribute::kSetSize);
+
+ std::vector<View*> views_in_group;
+ GetViewsInGroupForSet(&views_in_group);
+ if (views_in_group.empty())
+ return base::nullopt;
+ // Check this is in views_in_group; it may be removed if it is ignored.
+ auto found_view =
+ std::find(views_in_group.begin(), views_in_group.end(), view());
+ if (found_view == views_in_group.end())
+ return base::nullopt;
+
+ return views_in_group.size();
+}
+
+void ViewAXPlatformNodeDelegate::GetViewsInGroupForSet(
+ std::vector<View*>* views_in_group) const {
+ const int group_id = view()->GetGroup();
+ if (group_id < 0)
+ return;
+
+ View* view_to_check = view();
+ // If this view has a parent, check from the parent, to make sure we catch any
+ // siblings.
+ if (view()->parent())
+ view_to_check = view()->parent();
+ view_to_check->GetViewsInGroup(group_id, views_in_group);
+
+ // Remove any views that are ignored in the accessibility tree.
+ views_in_group->erase(
+ std::remove_if(
+ views_in_group->begin(), views_in_group->end(),
+ [](View* view) {
+ ViewAccessibility& view_accessibility =
+ view->GetViewAccessibility();
+ bool is_ignored = view_accessibility.IsIgnored();
+ // TODO Remove the ViewAXPlatformNodeDelegate::GetData() part of
+ // this lambda, once the temporary code in GetData() setting the
+ // role to kIgnored is moved to ViewAccessibility.
+ ViewAXPlatformNodeDelegate* ax_delegate =
+ static_cast<ViewAXPlatformNodeDelegate*>(&view_accessibility);
+ if (ax_delegate)
+ is_ignored = is_ignored || (ax_delegate->GetData().role ==
+ ax::mojom::Role::kIgnored);
+ return is_ignored;
+ }),
+ views_in_group->end());
+}
+
ViewAXPlatformNodeDelegate::ChildWidgetsResult
ViewAXPlatformNodeDelegate::GetChildWidgets() const {
// Only attach child widgets to the root view.
diff --git a/chromium/ui/views/accessibility/view_ax_platform_node_delegate.h b/chromium/ui/views/accessibility/view_ax_platform_node_delegate.h
index bc16cfef9fd..d6fed0ddaea 100644
--- a/chromium/ui/views/accessibility/view_ax_platform_node_delegate.h
+++ b/chromium/ui/views/accessibility/view_ax_platform_node_delegate.h
@@ -62,13 +62,24 @@ class ViewAXPlatformNodeDelegate : public ViewAccessibility,
bool ShouldIgnoreHoveredStateForTesting() override;
bool IsOffscreen() const override;
base::string16 GetAuthorUniqueId() const override;
+ bool IsMinimized() const override;
// Also in |ViewAccessibility|.
const ui::AXUniqueId& GetUniqueId() const override;
+ // Ordered-set-like and item-like nodes.
+ bool IsOrderedSetItem() const override;
+ bool IsOrderedSet() const override;
+ base::Optional<int> GetPosInSet() const override;
+ base::Optional<int> GetSetSize() const override;
+
protected:
explicit ViewAXPlatformNodeDelegate(View* view);
private:
+ // Uses Views::GetViewsInGroup to find nearby Views in the same group.
+ // Searches from the View's parent to include siblings within that group.
+ void GetViewsInGroupForSet(std::vector<View*>* views_in_group) const;
+
struct ChildWidgetsResult;
ChildWidgetsResult GetChildWidgets() const;
diff --git a/chromium/ui/views/accessibility/view_ax_platform_node_delegate_auralinux.cc b/chromium/ui/views/accessibility/view_ax_platform_node_delegate_auralinux.cc
index aa9c6ef4c9c..cd191e5ffdd 100644
--- a/chromium/ui/views/accessibility/view_ax_platform_node_delegate_auralinux.cc
+++ b/chromium/ui/views/accessibility/view_ax_platform_node_delegate_auralinux.cc
@@ -16,6 +16,7 @@
#include "ui/accessibility/ax_node_data.h"
#include "ui/accessibility/platform/ax_platform_node_auralinux.h"
#include "ui/accessibility/platform/ax_platform_node_delegate_base.h"
+#include "ui/aura/window.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/views/view.h"
#include "ui/views/views_delegate.h"
@@ -33,7 +34,8 @@ namespace {
// top-level widget to a vector so we can return the list of all top-level
// windows as children of this application object.
class AuraLinuxApplication : public ui::AXPlatformNodeDelegateBase,
- public WidgetObserver {
+ public WidgetObserver,
+ public aura::WindowObserver {
public:
// Get the single instance of this class.
static AuraLinuxApplication* GetInstance() {
@@ -48,11 +50,16 @@ class AuraLinuxApplication : public ui::AXPlatformNodeDelegateBase,
return;
widget = widget->GetTopLevelWidget();
- if (base::ContainsValue(widgets_, widget))
+ if (base::Contains(widgets_, widget))
return;
widgets_.push_back(widget);
widget->AddObserver(this);
+
+ aura::Window* window = widget->GetNativeWindow();
+ if (!window)
+ return;
+ window->AddObserver(this);
}
gfx::NativeViewAccessible GetNativeViewAccessible() {
@@ -69,6 +76,20 @@ class AuraLinuxApplication : public ui::AXPlatformNodeDelegateBase,
widgets_.erase(iter);
}
+ void OnWindowVisibilityChanged(aura::Window* window, bool visible) override {
+ for (Widget* widget : widgets_) {
+ if (widget->GetNativeWindow() != window)
+ continue;
+
+ View* root_view = widget->GetRootView();
+ if (!root_view)
+ continue;
+
+ root_view->NotifyAccessibilityEvent(
+ ax::mojom::Event::kWindowVisibilityChanged, true);
+ }
+ }
+
// ui::AXPlatformNodeDelegate:
const ui::AXNodeData& GetData() const override { return data_; }
diff --git a/chromium/ui/views/accessibility/view_ax_platform_node_delegate_mac.mm b/chromium/ui/views/accessibility/view_ax_platform_node_delegate_mac.mm
index de71650a132..5a1d1f28924 100644
--- a/chromium/ui/views/accessibility/view_ax_platform_node_delegate_mac.mm
+++ b/chromium/ui/views/accessibility/view_ax_platform_node_delegate_mac.mm
@@ -6,7 +6,7 @@
#include <memory>
-#include "ui/views/cocoa/bridged_native_widget_host_impl.h"
+#include "ui/views/cocoa/native_widget_mac_ns_window_host.h"
#include "ui/views/view.h"
#include "ui/views/widget/widget.h"
@@ -31,12 +31,12 @@ gfx::NativeViewAccessible ViewAXPlatformNodeDelegateMac::GetNSWindow() {
if (!top_level_widget)
return nil;
- auto* bridge_host = BridgedNativeWidgetHostImpl::GetFromNativeWindow(
+ auto* window_host = NativeWidgetMacNSWindowHost::GetFromNativeWindow(
top_level_widget->GetNativeWindow());
- if (!bridge_host)
+ if (!window_host)
return nil;
- return bridge_host->GetNativeViewAccessibleForNSWindow();
+ return window_host->GetNativeViewAccessibleForNSWindow();
}
gfx::NativeViewAccessible ViewAXPlatformNodeDelegateMac::GetParent() {
@@ -47,12 +47,12 @@ gfx::NativeViewAccessible ViewAXPlatformNodeDelegateMac::GetParent() {
if (!widget)
return nil;
- auto* bridge_host = BridgedNativeWidgetHostImpl::GetFromNativeWindow(
+ auto* window_host = NativeWidgetMacNSWindowHost::GetFromNativeWindow(
view()->GetWidget()->GetNativeWindow());
- if (!bridge_host)
+ if (!window_host)
return nil;
- return bridge_host->GetNativeViewAccessibleForNSView();
+ return window_host->GetNativeViewAccessibleForNSView();
}
} // namespace views
diff --git a/chromium/ui/views/accessibility/view_ax_platform_node_delegate_unittest.cc b/chromium/ui/views/accessibility/view_ax_platform_node_delegate_unittest.cc
index 5671f5fb3b3..a0727e4bad4 100644
--- a/chromium/ui/views/accessibility/view_ax_platform_node_delegate_unittest.cc
+++ b/chromium/ui/views/accessibility/view_ax_platform_node_delegate_unittest.cc
@@ -78,6 +78,11 @@ class ViewAXPlatformNodeDelegateTest : public ViewsTestBase {
&label_->GetViewAccessibility());
}
+ ViewAXPlatformNodeDelegate* view_accessibility(View* view) {
+ return static_cast<ViewAXPlatformNodeDelegate*>(
+ &view->GetViewAccessibility());
+ }
+
bool SetFocused(ViewAXPlatformNodeDelegate* ax_delegate, bool focused) {
ui::AXActionData data;
data.action =
@@ -85,6 +90,58 @@ class ViewAXPlatformNodeDelegateTest : public ViewsTestBase {
return ax_delegate->AccessibilityPerformAction(data);
}
+ // Sets up a more complicated structure of Views - one parent View with four
+ // child Views.
+ std::vector<View*> SetUpExtraViews() {
+ View* parent_view = new View();
+ widget_->GetContentsView()->AddChildView(parent_view);
+ std::vector<View*> views{parent_view};
+
+ const int num_children = 4;
+ for (int i = 0; i < num_children; i++) {
+ View* child_view = new View();
+ parent_view->AddChildView(child_view);
+ views.push_back(child_view);
+ }
+ return views;
+ }
+
+ // Adds group id information to the first 5 values in |views|. If |views| is
+ // empty, populates it with one parent View and four child Views. It is
+ // assumed |views| is either empty or has at least 5 items.
+ void SetUpExtraViewsWithGroups(std::vector<View*>& views) {
+ // v[0] g1
+ // | | | |
+ // v[1] g1 v[2] g1 v[3] g2 v[4]
+ if (views.empty())
+ views = SetUpExtraViews();
+ EXPECT_GE(views.size(), (size_t)5);
+
+ views[0]->SetGroup(1);
+ views[1]->SetGroup(1);
+ views[2]->SetGroup(1);
+ views[3]->SetGroup(2);
+ // Skip views[4] - no group id.
+ }
+
+ // Adds posInSet and setSize overrides to the first 5 values in |views|. If
+ // |views| is empty, populates it with one parent View and four child Views.
+ // It is assumed |views| is either empty or has at least 5 items.
+ void SetUpExtraViewsWithSetOverrides(std::vector<View*>& views) {
+ // v[0] p4 s4
+ // | | | |
+ // v[1] p3 s4 v[2] p2 s4 v[3] p- s- v[4] p1 s4
+ if (views.empty())
+ views = SetUpExtraViews();
+ EXPECT_GE(views.size(), (size_t)5);
+
+ views[0]->GetViewAccessibility().OverridePosInSet(4, 4);
+ views[1]->GetViewAccessibility().OverridePosInSet(3, 4);
+ views[2]->GetViewAccessibility().OverridePosInSet(2, 4);
+ // Skip views[3] - no override.
+ views[4]->GetViewAccessibility().OverridePosInSet(1, 4);
+ }
+
protected:
const int DEFAULT_VIEW_ID = 0;
const int NON_DEFAULT_VIEW_ID = 1;
@@ -185,6 +242,132 @@ TEST_F(ViewAXPlatformNodeDelegateTest, GetAuthorUniqueIdNonDefault) {
button_accessibility()->GetAuthorUniqueId());
}
+TEST_F(ViewAXPlatformNodeDelegateTest, IsOrderedSet) {
+ std::vector<View*> group_ids;
+ SetUpExtraViewsWithGroups(group_ids);
+ // Only last element has no group id.
+ EXPECT_TRUE(view_accessibility(group_ids[0])->IsOrderedSet());
+ EXPECT_TRUE(view_accessibility(group_ids[1])->IsOrderedSet());
+ EXPECT_TRUE(view_accessibility(group_ids[2])->IsOrderedSet());
+ EXPECT_TRUE(view_accessibility(group_ids[3])->IsOrderedSet());
+ EXPECT_FALSE(view_accessibility(group_ids[4])->IsOrderedSet());
+
+ EXPECT_TRUE(view_accessibility(group_ids[0])->IsOrderedSetItem());
+ EXPECT_TRUE(view_accessibility(group_ids[1])->IsOrderedSetItem());
+ EXPECT_TRUE(view_accessibility(group_ids[2])->IsOrderedSetItem());
+ EXPECT_TRUE(view_accessibility(group_ids[3])->IsOrderedSetItem());
+ EXPECT_FALSE(view_accessibility(group_ids[4])->IsOrderedSetItem());
+
+ std::vector<View*> overrides;
+ SetUpExtraViewsWithSetOverrides(overrides);
+ // Only overrides[3] has no override values for setSize/ posInSet.
+ EXPECT_TRUE(view_accessibility(overrides[0])->IsOrderedSet());
+ EXPECT_TRUE(view_accessibility(overrides[1])->IsOrderedSet());
+ EXPECT_TRUE(view_accessibility(overrides[2])->IsOrderedSet());
+ EXPECT_FALSE(view_accessibility(overrides[3])->IsOrderedSet());
+ EXPECT_TRUE(view_accessibility(overrides[4])->IsOrderedSet());
+
+ EXPECT_TRUE(view_accessibility(overrides[0])->IsOrderedSetItem());
+ EXPECT_TRUE(view_accessibility(overrides[1])->IsOrderedSetItem());
+ EXPECT_TRUE(view_accessibility(overrides[2])->IsOrderedSetItem());
+ EXPECT_FALSE(view_accessibility(overrides[3])->IsOrderedSetItem());
+ EXPECT_TRUE(view_accessibility(overrides[4])->IsOrderedSetItem());
+}
+
+TEST_F(ViewAXPlatformNodeDelegateTest, SetSizeAndPosition) {
+ // Test Views with group ids.
+ std::vector<View*> group_ids;
+ SetUpExtraViewsWithGroups(group_ids);
+ EXPECT_EQ(view_accessibility(group_ids[0])->GetSetSize(), 3);
+ EXPECT_EQ(view_accessibility(group_ids[0])->GetPosInSet(), 1);
+ EXPECT_EQ(view_accessibility(group_ids[1])->GetSetSize(), 3);
+ EXPECT_EQ(view_accessibility(group_ids[1])->GetPosInSet(), 2);
+ EXPECT_EQ(view_accessibility(group_ids[2])->GetSetSize(), 3);
+ EXPECT_EQ(view_accessibility(group_ids[2])->GetPosInSet(), 3);
+
+ EXPECT_EQ(view_accessibility(group_ids[3])->GetSetSize(), 1);
+ EXPECT_EQ(view_accessibility(group_ids[3])->GetPosInSet(), 1);
+
+ EXPECT_FALSE(view_accessibility(group_ids[4])->GetSetSize().has_value());
+ EXPECT_FALSE(view_accessibility(group_ids[4])->GetPosInSet().has_value());
+
+ // Check if a View is ignored, it is not counted in SetSize or PosInSet
+ group_ids[1]->GetViewAccessibility().OverrideIsIgnored(true);
+ group_ids[2]->GetViewAccessibility().OverrideIsIgnored(true);
+ EXPECT_EQ(view_accessibility(group_ids[0])->GetSetSize(), 1);
+ EXPECT_EQ(view_accessibility(group_ids[0])->GetPosInSet(), 1);
+ EXPECT_FALSE(view_accessibility(group_ids[1])->GetSetSize().has_value());
+ EXPECT_FALSE(view_accessibility(group_ids[1])->GetPosInSet().has_value());
+ EXPECT_FALSE(view_accessibility(group_ids[2])->GetSetSize().has_value());
+ EXPECT_FALSE(view_accessibility(group_ids[2])->GetPosInSet().has_value());
+ group_ids[1]->GetViewAccessibility().OverrideIsIgnored(false);
+ group_ids[2]->GetViewAccessibility().OverrideIsIgnored(false);
+
+ // Test Views with setSize/ posInSet override values set.
+ std::vector<View*> overrides;
+ SetUpExtraViewsWithSetOverrides(overrides);
+ EXPECT_EQ(view_accessibility(overrides[0])->GetSetSize(), 4);
+ EXPECT_EQ(view_accessibility(overrides[0])->GetPosInSet(), 4);
+ EXPECT_EQ(view_accessibility(overrides[1])->GetSetSize(), 4);
+ EXPECT_EQ(view_accessibility(overrides[1])->GetPosInSet(), 3);
+ EXPECT_EQ(view_accessibility(overrides[2])->GetSetSize(), 4);
+ EXPECT_EQ(view_accessibility(overrides[2])->GetPosInSet(), 2);
+
+ EXPECT_FALSE(view_accessibility(overrides[3])->GetSetSize().has_value());
+ EXPECT_FALSE(view_accessibility(overrides[3])->GetPosInSet().has_value());
+
+ EXPECT_EQ(view_accessibility(overrides[4])->GetSetSize(), 4);
+ EXPECT_EQ(view_accessibility(overrides[4])->GetPosInSet(), 1);
+
+ // Test Views with both group ids and setSize/ posInSet override values set.
+ // Make sure the override values take precedence when both are set.
+ // Add setSize/ posInSet overrides to the Views with group ids.
+ SetUpExtraViewsWithSetOverrides(group_ids);
+ EXPECT_EQ(view_accessibility(group_ids[0])->GetSetSize(), 4);
+ EXPECT_EQ(view_accessibility(group_ids[0])->GetPosInSet(), 4);
+ EXPECT_EQ(view_accessibility(group_ids[1])->GetSetSize(), 4);
+ EXPECT_EQ(view_accessibility(group_ids[1])->GetPosInSet(), 3);
+ EXPECT_EQ(view_accessibility(group_ids[2])->GetSetSize(), 4);
+ EXPECT_EQ(view_accessibility(group_ids[2])->GetPosInSet(), 2);
+
+ EXPECT_EQ(view_accessibility(group_ids[3])->GetSetSize(), 1);
+ EXPECT_EQ(view_accessibility(group_ids[3])->GetPosInSet(), 1);
+
+ EXPECT_EQ(view_accessibility(group_ids[4])->GetSetSize(), 4);
+ EXPECT_EQ(view_accessibility(group_ids[4])->GetPosInSet(), 1);
+}
+
+TEST_F(ViewAXPlatformNodeDelegateTest, Navigation) {
+ std::vector<View*> view_ids = SetUpExtraViews();
+
+ EXPECT_EQ(view_accessibility(view_ids[0])->GetNextSibling(), nullptr);
+ EXPECT_EQ(view_accessibility(view_ids[0])->GetPreviousSibling(),
+ view_accessibility(button_)->GetNativeObject());
+ EXPECT_EQ(view_accessibility(view_ids[0])->GetIndexInParent(), 3);
+
+ EXPECT_EQ(view_accessibility(view_ids[1])->GetNextSibling(),
+ view_accessibility(view_ids[2])->GetNativeObject());
+ EXPECT_EQ(view_accessibility(view_ids[1])->GetPreviousSibling(), nullptr);
+ EXPECT_EQ(view_accessibility(view_ids[1])->GetIndexInParent(), 0);
+
+ EXPECT_EQ(view_accessibility(view_ids[2])->GetNextSibling(),
+ view_accessibility(view_ids[3])->GetNativeObject());
+ EXPECT_EQ(view_accessibility(view_ids[2])->GetPreviousSibling(),
+ view_accessibility(view_ids[1])->GetNativeObject());
+ EXPECT_EQ(view_accessibility(view_ids[2])->GetIndexInParent(), 1);
+
+ EXPECT_EQ(view_accessibility(view_ids[3])->GetNextSibling(),
+ view_accessibility(view_ids[4])->GetNativeObject());
+ EXPECT_EQ(view_accessibility(view_ids[3])->GetPreviousSibling(),
+ view_accessibility(view_ids[2])->GetNativeObject());
+ EXPECT_EQ(view_accessibility(view_ids[3])->GetIndexInParent(), 2);
+
+ EXPECT_EQ(view_accessibility(view_ids[4])->GetNextSibling(), nullptr);
+ EXPECT_EQ(view_accessibility(view_ids[4])->GetPreviousSibling(),
+ view_accessibility(view_ids[3])->GetNativeObject());
+ EXPECT_EQ(view_accessibility(view_ids[4])->GetIndexInParent(), 3);
+}
+
#if defined(USE_AURA)
class DerivedTestView : public View {
public:
diff --git a/chromium/ui/views/accessible_pane_view.cc b/chromium/ui/views/accessible_pane_view.cc
index 2e2229db524..73b501c64e4 100644
--- a/chromium/ui/views/accessible_pane_view.cc
+++ b/chromium/ui/views/accessible_pane_view.cc
@@ -255,4 +255,8 @@ views::View* AccessiblePaneView::GetFocusTraversableParentView() {
return nullptr;
}
+BEGIN_METADATA(AccessiblePaneView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/accessible_pane_view.h b/chromium/ui/views/accessible_pane_view.h
index d4d0c8aba14..1c70cd36de3 100644
--- a/chromium/ui/views/accessible_pane_view.h
+++ b/chromium/ui/views/accessible_pane_view.h
@@ -25,6 +25,8 @@ class VIEWS_EXPORT AccessiblePaneView : public View,
public FocusChangeListener,
public FocusTraversable {
public:
+ METADATA_HEADER(AccessiblePaneView);
+
AccessiblePaneView();
~AccessiblePaneView() override;
diff --git a/chromium/ui/views/animation/animation_delegate_views.cc b/chromium/ui/views/animation/animation_delegate_views.cc
index ce725286c52..660e42f28de 100644
--- a/chromium/ui/views/animation/animation_delegate_views.cc
+++ b/chromium/ui/views/animation/animation_delegate_views.cc
@@ -12,17 +12,27 @@
namespace views {
AnimationDelegateViews::AnimationDelegateViews(View* view) : view_(view) {
- scoped_observer_.Add(view);
+ if (view)
+ scoped_observer_.Add(view);
}
-AnimationDelegateViews::~AnimationDelegateViews() = default;
+AnimationDelegateViews::~AnimationDelegateViews() {
+ // Reset the delegate so that we don't attempt to notify our observer from
+ // the destructor.
+ if (container_)
+ container_->set_observer(nullptr);
+}
void AnimationDelegateViews::AnimationContainerWasSet(
gfx::AnimationContainer* container) {
if (container_ == container)
return;
+ if (container_)
+ container_->set_observer(nullptr);
+
container_ = container;
+ container_->set_observer(this);
UpdateAnimationRunner();
}
@@ -40,11 +50,22 @@ void AnimationDelegateViews::OnViewIsDeleting(View* observed_view) {
UpdateAnimationRunner();
}
+void AnimationDelegateViews::AnimationContainerShuttingDown(
+ gfx::AnimationContainer* container) {
+ container_ = nullptr;
+}
+
void AnimationDelegateViews::UpdateAnimationRunner() {
+#if defined(OS_CHROMEOS)
+ // TODO(crbug.com/969788): Re-enable this function with better ui::Compositor
+ // switching support.
+ return;
+#endif // defined(OS_CHROMEOS)
+
if (!container_)
return;
- if (!view_ || !view_->GetWidget()) {
+ if (!view_ || !view_->GetWidget() || !view_->GetWidget()->GetCompositor()) {
// TODO(https://crbug.com/960621): make sure the container has a correct
// compositor-assisted runner.
container_->SetAnimationRunner(nullptr);
diff --git a/chromium/ui/views/animation/animation_delegate_views.h b/chromium/ui/views/animation/animation_delegate_views.h
index 318d5585ca2..ee025be516f 100644
--- a/chromium/ui/views/animation/animation_delegate_views.h
+++ b/chromium/ui/views/animation/animation_delegate_views.h
@@ -8,6 +8,7 @@
#include <memory>
#include "base/scoped_observer.h"
+#include "ui/gfx/animation/animation_container_observer.h"
#include "ui/gfx/animation/animation_delegate.h"
#include "ui/views/view_observer.h"
#include "ui/views/views_export.h"
@@ -17,9 +18,11 @@ namespace views {
class View;
// Provides default implementaton to adapt CompositorAnimationRunner for
-// Animation.
-class VIEWS_EXPORT AnimationDelegateViews : public gfx::AnimationDelegate,
- public ViewObserver {
+// Animation. Falls back to the default animation runner when |view| is nullptr.
+class VIEWS_EXPORT AnimationDelegateViews
+ : public gfx::AnimationDelegate,
+ public ViewObserver,
+ public gfx::AnimationContainerObserver {
public:
explicit AnimationDelegateViews(View* view);
~AnimationDelegateViews() override;
@@ -32,6 +35,13 @@ class VIEWS_EXPORT AnimationDelegateViews : public gfx::AnimationDelegate,
void OnViewRemovedFromWidget(View* observed_view) final;
void OnViewIsDeleting(View* observed_view) final;
+ // gfx::AnimationContainerObserver:
+ void AnimationContainerProgressed(
+ gfx::AnimationContainer* container) override {}
+ void AnimationContainerEmpty(gfx::AnimationContainer* container) override {}
+ void AnimationContainerShuttingDown(
+ gfx::AnimationContainer* container) override;
+
gfx::AnimationContainer* container() { return container_; }
private:
diff --git a/chromium/ui/views/animation/bounds_animator.cc b/chromium/ui/views/animation/bounds_animator.cc
index 90e1d3280ff..303c8ee65c8 100644
--- a/chromium/ui/views/animation/bounds_animator.cc
+++ b/chromium/ui/views/animation/bounds_animator.cc
@@ -18,14 +18,9 @@ BoundsAnimator::BoundsAnimator(View* parent)
: AnimationDelegateViews(parent),
parent_(parent),
container_(new gfx::AnimationContainer()) {
- container_->set_observer(this);
}
BoundsAnimator::~BoundsAnimator() {
- // Reset the delegate so that we don't attempt to notify our observer from
- // the destructor.
- container_->set_observer(nullptr);
-
// Delete all the animations, but don't remove any child views. We assume the
// view owns us and is going to be deleted anyway.
for (auto& entry : data_)
diff --git a/chromium/ui/views/animation/bounds_animator.h b/chromium/ui/views/animation/bounds_animator.h
index ba268c91a29..8e11253f414 100644
--- a/chromium/ui/views/animation/bounds_animator.h
+++ b/chromium/ui/views/animation/bounds_animator.h
@@ -38,8 +38,7 @@ class View;
// You can attach an AnimationDelegate to the individual animation for a view
// by way of SetAnimationDelegate. Additionally you can attach an observer to
// the BoundsAnimator that is notified when all animations are complete.
-class VIEWS_EXPORT BoundsAnimator : public AnimationDelegateViews,
- public gfx::AnimationContainerObserver {
+class VIEWS_EXPORT BoundsAnimator : public AnimationDelegateViews {
public:
explicit BoundsAnimator(View* view);
~BoundsAnimator() override;
@@ -158,8 +157,6 @@ class VIEWS_EXPORT BoundsAnimator : public AnimationDelegateViews,
void AnimationProgressed(const gfx::Animation* animation) override;
void AnimationEnded(const gfx::Animation* animation) override;
void AnimationCanceled(const gfx::Animation* animation) override;
-
- // gfx::AnimationContainerObserver overrides.
void AnimationContainerProgressed(
gfx::AnimationContainer* container) override;
void AnimationContainerEmpty(gfx::AnimationContainer* container) override;
diff --git a/chromium/ui/views/animation/compositor_animation_runner.cc b/chromium/ui/views/animation/compositor_animation_runner.cc
index 6ec26f29401..e5abea4d20b 100644
--- a/chromium/ui/views/animation/compositor_animation_runner.cc
+++ b/chromium/ui/views/animation/compositor_animation_runner.cc
@@ -65,6 +65,7 @@ void CompositorAnimationRunner::OnStart(base::TimeDelta min_interval) {
if (!compositor_)
return;
+ last_tick_ = base::TimeTicks::Now();
min_interval_ = min_interval;
DCHECK(!compositor_->HasAnimationObserver(this));
compositor_->AddAnimationObserver(this);
diff --git a/chromium/ui/views/animation/compositor_animation_runner_unittest.cc b/chromium/ui/views/animation/compositor_animation_runner_unittest.cc
index ca380cfd204..78923d4f4df 100644
--- a/chromium/ui/views/animation/compositor_animation_runner_unittest.cc
+++ b/chromium/ui/views/animation/compositor_animation_runner_unittest.cc
@@ -15,7 +15,14 @@ namespace test {
using CompositorAnimationRunnerTest = WidgetTest;
-TEST_F(CompositorAnimationRunnerTest, BasicCoverageTest) {
+// TODO(crbug.com/969788): Re-enable CompositorAnimationRunner with better
+// ui::Compositor switching support.
+#if defined(OS_CHROMEOS)
+#define MAYBE_BasicCoverageTest DISABLED_BasicCoverageTest
+#else
+#define MAYBE_BasicCoverageTest BasicCoverageTest
+#endif
+TEST_F(CompositorAnimationRunnerTest, MAYBE_BasicCoverageTest) {
WidgetAutoclosePtr widget(CreateTopLevelPlatformWidget());
widget->Show();
diff --git a/chromium/ui/views/animation/ink_drop_host_view.cc b/chromium/ui/views/animation/ink_drop_host_view.cc
index 64a14517067..5f8a9ac4f16 100644
--- a/chromium/ui/views/animation/ink_drop_host_view.cc
+++ b/chromium/ui/views/animation/ink_drop_host_view.cc
@@ -105,7 +105,7 @@ void InkDropHostView::SetInkDropMode(InkDropMode ink_drop_mode) {
void InkDropHostView::AnimateInkDrop(InkDropState state,
const ui::LocatedEvent* event) {
- ink_drop_event_handler_.AnimateInkDrop(state, event);
+ GetEventHandler()->AnimateInkDrop(state, event);
}
std::unique_ptr<InkDropImpl> InkDropHostView::CreateDefaultInkDropImpl() {
@@ -170,9 +170,8 @@ InkDrop* InkDropHostView::GetInkDrop() {
}
gfx::Point InkDropHostView::GetInkDropCenterBasedOnLastEvent() const {
- return ink_drop_event_handler_.GetLastRippleTriggeringEvent()
- ? ink_drop_event_handler_.GetLastRippleTriggeringEvent()
- ->location()
+ return GetEventHandler()->GetLastRippleTriggeringEvent()
+ ? GetEventHandler()->GetLastRippleTriggeringEvent()->location()
: GetMirroredRect(GetContentsBounds()).CenterPoint();
}
@@ -195,4 +194,19 @@ gfx::Size InkDropHostView::CalculateLargeInkDropSize(
return gfx::ScaleToCeiledSize(gfx::Size(small_size), kLargeInkDropScale);
}
+const InkDropEventHandler* InkDropHostView::GetEventHandler() const {
+ if (ink_drop_event_handler_override_)
+ return ink_drop_event_handler_override_;
+ return &ink_drop_event_handler_;
+}
+
+InkDropEventHandler* InkDropHostView::GetEventHandler() {
+ return const_cast<InkDropEventHandler*>(
+ const_cast<const InkDropHostView*>(this)->GetEventHandler());
+}
+
+BEGIN_METADATA(InkDropHostView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/animation/ink_drop_host_view.h b/chromium/ui/views/animation/ink_drop_host_view.h
index 30879738568..c410d9fb249 100644
--- a/chromium/ui/views/animation/ink_drop_host_view.h
+++ b/chromium/ui/views/animation/ink_drop_host_view.h
@@ -38,6 +38,8 @@ class InkDropHostViewTestApi;
// A view that provides InkDropHost functionality.
class VIEWS_EXPORT InkDropHostView : public View {
public:
+ METADATA_HEADER(InkDropHostView);
+
// Used in SetInkDropMode() to specify whether the ink drop effect is enabled
// or not for the view. In case of having an ink drop, it also specifies
// whether the default event handler for the ink drop should be installed or
@@ -111,6 +113,16 @@ class VIEWS_EXPORT InkDropHostView : public View {
return ink_drop_large_corner_radius_;
}
+ // Allows InstallableInkDrop to override our InkDropEventHandler
+ // instance.
+ //
+ // TODO(crbug.com/931964): Remove this, either by finishing refactor or by
+ // giving up.
+ void set_ink_drop_event_handler_override(
+ InkDropEventHandler* ink_drop_event_handler_override) {
+ ink_drop_event_handler_override_ = ink_drop_event_handler_override;
+ }
+
// Animates |ink_drop_| to the desired |ink_drop_state|. Caches |event| as the
// last_ripple_triggering_event().
//
@@ -204,6 +216,9 @@ class VIEWS_EXPORT InkDropHostView : public View {
InkDropHostView* const host_view_;
};
+ const InkDropEventHandler* GetEventHandler() const;
+ InkDropEventHandler* GetEventHandler();
+
// Defines what type of |ink_drop_| to create.
InkDropMode ink_drop_mode_ = InkDropMode::OFF;
@@ -215,6 +230,8 @@ class VIEWS_EXPORT InkDropHostView : public View {
InkDropHostViewEventHandlerDelegate ink_drop_event_handler_delegate_;
InkDropEventHandler ink_drop_event_handler_;
+ InkDropEventHandler* ink_drop_event_handler_override_ = nullptr;
+
float ink_drop_visible_opacity_ = 0.175f;
// TODO(pbos): Audit call sites to make sure highlight opacity is either
diff --git a/chromium/ui/views/animation/installable_ink_drop.cc b/chromium/ui/views/animation/installable_ink_drop.cc
index 8e826ee4129..edfd31a63bc 100644
--- a/chromium/ui/views/animation/installable_ink_drop.cc
+++ b/chromium/ui/views/animation/installable_ink_drop.cc
@@ -4,25 +4,119 @@
#include "ui/views/animation/installable_ink_drop.h"
+#include <algorithm>
+
#include "base/logging.h"
+#include "base/memory/ptr_util.h"
+#include "cc/paint/paint_flags.h"
+#include "third_party/skia/include/core/SkColor.h"
+#include "third_party/skia/include/core/SkPath.h"
+#include "ui/compositor/layer.h"
+#include "ui/compositor/paint_context.h"
+#include "ui/compositor/paint_recorder.h"
+#include "ui/gfx/animation/animation_container.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/color_palette.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/skia_util.h"
+#include "ui/views/animation/compositor_animation_runner.h"
+#include "ui/views/animation/ink_drop_host_view.h"
+#include "ui/views/view.h"
+#include "ui/views/view_class_properties.h"
+#include "ui/views/widget/widget.h"
namespace views {
+namespace {
+
+InstallableInkDropConfig GetPlaceholderInstallableInkDropConfig() {
+ InstallableInkDropConfig config{0};
+ config.base_color = gfx::kPlaceholderColor;
+ config.ripple_opacity = 1.0f;
+ config.highlight_opacity = 1.0f;
+ return config;
+}
+
+} // namespace
+
const base::Feature kInstallableInkDropFeature{
"InstallableInkDrop", base::FEATURE_DISABLED_BY_DEFAULT};
-InstallableInkDrop::InstallableInkDrop() = default;
+InstallableInkDrop::InstallableInkDrop(View* view)
+ : view_(view),
+ config_(GetPlaceholderInstallableInkDropConfig()),
+ layer_(std::make_unique<ui::Layer>()),
+ event_handler_(view_, this),
+ painter_(&config_, &visual_state_),
+ animation_container_(base::MakeRefCounted<gfx::AnimationContainer>()),
+ animator_(layer_->size(),
+ &visual_state_,
+ animation_container_.get(),
+ base::Bind(&InstallableInkDrop::SchedulePaint,
+ base::Unretained(this))) {
+ // Catch if |view_| is destroyed out from under us.
+ if (DCHECK_IS_ON())
+ view_->AddObserver(this);
+
+ layer_->set_delegate(this);
+ layer_->SetFillsBoundsOpaquely(false);
+ layer_->SetFillsBoundsCompletely(false);
+ view_->AddLayerBeneathView(layer_.get());
+
+ // AddLayerBeneathView() changes the location of |layer_| so this must be done
+ // after.
+ layer_->SetBounds(gfx::Rect(view_->size()) +
+ layer_->bounds().OffsetFromOrigin());
+ layer_->SchedulePaint(gfx::Rect(layer_->size()));
+
+ if (view_->GetWidget()) {
+ // Using CompositorAnimationRunner keeps our animation updates in sync with
+ // compositor frames and avoids jank.
+ animation_container_->SetAnimationRunner(
+ std::make_unique<CompositorAnimationRunner>(
+ view_->GetWidget()->GetCompositor()));
+ }
+}
-InstallableInkDrop::~InstallableInkDrop() = default;
+InstallableInkDrop::InstallableInkDrop(InkDropHostView* ink_drop_host_view)
+ : InstallableInkDrop(static_cast<View*>(ink_drop_host_view)) {
+ // To get all events, we must override InkDropHostView's event handler.
+ ink_drop_host_view->set_ink_drop_event_handler_override(&event_handler_);
+ ink_drop_host_view_ = ink_drop_host_view;
+}
-void InstallableInkDrop::HostSizeChanged(const gfx::Size& new_size) {}
+InstallableInkDrop::~InstallableInkDrop() {
+ view_->RemoveLayerBeneathView(layer_.get());
+ if (ink_drop_host_view_)
+ ink_drop_host_view_->set_ink_drop_event_handler_override(nullptr);
+ if (DCHECK_IS_ON())
+ view_->RemoveObserver(this);
+}
+
+void InstallableInkDrop::SetConfig(InstallableInkDropConfig config) {
+ config_ = config;
+ SchedulePaint();
+}
+
+void InstallableInkDrop::HostSizeChanged(const gfx::Size& new_size) {
+ layer_->SetBounds(gfx::Rect(new_size) + layer_->bounds().OffsetFromOrigin());
+ layer_->SchedulePaint(gfx::Rect(layer_->size()));
+ animator_.SetSize(layer_->size());
+}
InkDropState InstallableInkDrop::GetTargetInkDropState() const {
- return current_state_;
+ return animator_.target_state();
}
void InstallableInkDrop::AnimateToState(InkDropState ink_drop_state) {
- current_state_ = ink_drop_state;
+ const gfx::Point ripple_center =
+ event_handler_.GetLastRippleTriggeringEvent()
+ ? event_handler_.GetLastRippleTriggeringEvent()->location()
+ : view_->GetMirroredRect(view_->GetLocalBounds()).CenterPoint();
+ animator_.SetLastEventLocation(ripple_center);
+ animator_.AnimateToState(ink_drop_state);
}
void InstallableInkDrop::SetHoverHighlightFadeDurationMs(int duration_ms) {
@@ -34,19 +128,27 @@ void InstallableInkDrop::UseDefaultHoverHighlightFadeDuration() {
}
void InstallableInkDrop::SnapToActivated() {
- NOTREACHED();
+ // TODO(crbug.com/933384): do this without animation.
+ animator_.AnimateToState(InkDropState::ACTIVATED);
}
void InstallableInkDrop::SnapToHidden() {
- NOTREACHED();
+ // TODO(crbug.com/933384): do this without animation.
+ animator_.AnimateToState(InkDropState::HIDDEN);
}
-void InstallableInkDrop::SetHovered(bool is_hovered) {}
+void InstallableInkDrop::SetHovered(bool is_hovered) {
+ is_hovered_ = is_hovered;
+ UpdateAnimatorHighlight();
+}
-void InstallableInkDrop::SetFocused(bool is_focused) {}
+void InstallableInkDrop::SetFocused(bool is_focused) {
+ is_focused_ = is_focused;
+ UpdateAnimatorHighlight();
+}
bool InstallableInkDrop::IsHighlightFadingInOrVisible() const {
- return false;
+ return is_hovered_ || is_focused_;
}
void InstallableInkDrop::SetShowHighlightOnHover(bool show_highlight_on_hover) {
@@ -57,4 +159,61 @@ void InstallableInkDrop::SetShowHighlightOnFocus(bool show_highlight_on_focus) {
NOTREACHED();
}
+InkDrop* InstallableInkDrop::GetInkDrop() {
+ return this;
+}
+
+bool InstallableInkDrop::HasInkDrop() const {
+ return true;
+}
+
+bool InstallableInkDrop::SupportsGestureEvents() const {
+ return true;
+}
+
+void InstallableInkDrop::OnViewIsDeleting(View* observed_view) {
+ DCHECK_EQ(view_, observed_view);
+ NOTREACHED() << "|this| needs to outlive the view it's installed on";
+}
+
+void InstallableInkDrop::OnPaintLayer(const ui::PaintContext& context) {
+ DCHECK_EQ(view_->size(), layer_->size());
+
+ ui::PaintRecorder paint_recorder(context, layer_->size());
+ gfx::Canvas* canvas = paint_recorder.canvas();
+ canvas->ClipPath(GetHighlightPathForView(view_), true);
+
+ painter_.Paint(canvas, view_->size());
+}
+
+void InstallableInkDrop::OnDeviceScaleFactorChanged(
+ float old_device_scale_factor,
+ float new_device_scale_factor) {}
+
+// static
+SkPath InstallableInkDrop::GetHighlightPathForView(const View* view) {
+ // Use the provided highlight path if there is one.
+ const SkPath* const path_property = view->GetProperty(kHighlightPathKey);
+ if (path_property)
+ return *path_property;
+
+ // Otherwise, construct a default path. This will be pill shaped, or circular
+ // when |view| is square.
+ SkPath path;
+
+ const float radius =
+ std::min(view->size().width(), view->size().height()) / 2.0f;
+ path.addRoundRect(gfx::RectToSkRect(view->GetLocalBounds()), radius, radius);
+
+ return path;
+}
+
+void InstallableInkDrop::SchedulePaint() {
+ layer_->SchedulePaint(gfx::Rect(layer_->size()));
+}
+
+void InstallableInkDrop::UpdateAnimatorHighlight() {
+ animator_.AnimateHighlight(is_hovered_ || is_focused_);
+}
+
} // namespace views
diff --git a/chromium/ui/views/animation/installable_ink_drop.h b/chromium/ui/views/animation/installable_ink_drop.h
index 0670195ea20..a61c8944a57 100644
--- a/chromium/ui/views/animation/installable_ink_drop.h
+++ b/chromium/ui/views/animation/installable_ink_drop.h
@@ -5,25 +5,68 @@
#ifndef UI_VIEWS_ANIMATION_INSTALLABLE_INK_DROP_H_
#define UI_VIEWS_ANIMATION_INSTALLABLE_INK_DROP_H_
+#include <memory>
+
#include "base/feature_list.h"
-#include "ui/gfx/geometry/size.h"
+#include "base/memory/scoped_refptr.h"
+#include "ui/compositor/layer_delegate.h"
#include "ui/views/animation/ink_drop.h"
+#include "ui/views/animation/ink_drop_event_handler.h"
#include "ui/views/animation/ink_drop_state.h"
+#include "ui/views/animation/installable_ink_drop_animator.h"
+#include "ui/views/animation/installable_ink_drop_config.h"
+#include "ui/views/animation/installable_ink_drop_painter.h"
+#include "ui/views/view_observer.h"
#include "ui/views/views_export.h"
+class SkPath;
+
+namespace gfx {
+class AnimationContainer;
+class Size;
+} // namespace gfx
+
+namespace ui {
+class Layer;
+class PaintContext;
+} // namespace ui
+
namespace views {
+class InkDropHostView;
+class View;
+
extern const VIEWS_EXPORT base::Feature kInstallableInkDropFeature;
// Stub for future InkDrop implementation that will be installable on any View
// without needing InkDropHostView. This is currently non-functional and fails
// on some method calls. TODO(crbug.com/931964): implement the necessary parts
// of the API and remove the rest from the InkDrop interface.
-class VIEWS_EXPORT InstallableInkDrop : public InkDrop {
+class VIEWS_EXPORT InstallableInkDrop : public InkDrop,
+ public InkDropEventHandler::Delegate,
+ public ui::LayerDelegate,
+ public ViewObserver {
public:
- InstallableInkDrop();
+ // Create ink drop for |view|. Note that |view| must live longer than us.
+ explicit InstallableInkDrop(View* view);
+
+ // Overload for working within the InkDropHostView hierarchy. Similar to
+ // above, |ink_drop_host_view| must outlive us.
+ //
+ // TODO(crbug.com/931964): Remove this.
+ explicit InstallableInkDrop(InkDropHostView* ink_drop_host_view);
+
+ InstallableInkDrop(const InstallableInkDrop&) = delete;
+ InstallableInkDrop(InstallableInkDrop&&) = delete;
+
~InstallableInkDrop() override;
+ void SetConfig(InstallableInkDropConfig config);
+ InstallableInkDropConfig config() const { return config_; }
+
+ // Should only be used for inspecting properties of the layer in tests.
+ const ui::Layer* layer_for_testing() const { return layer_.get(); }
+
// InkDrop:
void HostSizeChanged(const gfx::Size& new_size) override;
InkDropState GetTargetInkDropState() const override;
@@ -38,8 +81,62 @@ class VIEWS_EXPORT InstallableInkDrop : public InkDrop {
void SetShowHighlightOnHover(bool show_highlight_on_hover) override;
void SetShowHighlightOnFocus(bool show_highlight_on_focus) override;
+ // InkDropEventHandler::Delegate:
+ InkDrop* GetInkDrop() override;
+ bool HasInkDrop() const override;
+ bool SupportsGestureEvents() const override;
+
+ // ViewObserver:
+ void OnViewIsDeleting(View* observed_view) override;
+
+ // ui::LayerDelegate:
+ void OnPaintLayer(const ui::PaintContext& context) override;
+ void OnDeviceScaleFactorChanged(float old_device_scale_factor,
+ float new_device_scale_factor) override;
+
+ // Gets the path that the ink drop fills in for the highlight. This uses
+ // |kHighlightPathKey| if provided but falls back to a pill-shaped path.
+ static SkPath GetHighlightPathForView(const View* view);
+
private:
- InkDropState current_state_ = InkDropState::HIDDEN;
+ void SchedulePaint();
+ void UpdateAnimatorHighlight();
+
+ // The view this ink drop is showing for. |layer_| is added to the layer
+ // hierarchy that |view_| belongs to. We track events on |view_| to update our
+ // visual state.
+ View* const view_;
+
+ // If we were installed on an InkDropHostView, this will be non-null. We store
+ // this to to remove our InkDropEventHandler override.
+ InkDropHostView* ink_drop_host_view_ = nullptr;
+
+ // Contains the colors and opacities used to paint.
+ InstallableInkDropConfig config_;
+
+ // The layer we paint to.
+ std::unique_ptr<ui::Layer> layer_;
+
+ // Observes |view_| and updates our visual state accordingly.
+ InkDropEventHandler event_handler_;
+
+ // Completely describes the current visual state of the ink drop, including
+ // progress of animations.
+ InstallableInkDropPainter::State visual_state_;
+
+ // Handles painting |visual_state_| on request.
+ InstallableInkDropPainter painter_;
+
+ // Used to synchronize the hover and activation animations within this ink
+ // drop. Since we use |views::CompositorAnimationRunner|, this also
+ // synchronizes them with compositor frames.
+ scoped_refptr<gfx::AnimationContainer> animation_container_;
+
+ // Manages our animations and maniuplates |visual_state_| for us.
+ InstallableInkDropAnimator animator_;
+
+ bool is_hovered_ = false;
+ bool is_focused_ = false;
};
} // namespace views
diff --git a/chromium/ui/views/animation/installable_ink_drop_animator.cc b/chromium/ui/views/animation/installable_ink_drop_animator.cc
new file mode 100644
index 00000000000..0445cdf8d96
--- /dev/null
+++ b/chromium/ui/views/animation/installable_ink_drop_animator.cc
@@ -0,0 +1,257 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/animation/installable_ink_drop_animator.h"
+
+#include <algorithm>
+
+#include "base/bind.h"
+#include "base/logging.h"
+#include "base/trace_event/trace_event.h"
+#include "ui/gfx/animation/tween.h"
+#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/rect_conversions.h"
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/size_f.h"
+#include "ui/gfx/geometry/vector2d_f.h"
+#include "ui/views/animation/installable_ink_drop_painter.h"
+
+namespace views {
+
+// static
+constexpr base::TimeDelta InstallableInkDropAnimator::kAnimationDuration;
+
+InstallableInkDropAnimator::InstallableInkDropAnimator(
+ gfx::Size size,
+ InstallableInkDropPainter::State* visual_state,
+ gfx::AnimationContainer* animation_container,
+ base::RepeatingClosure repaint_callback)
+ : size_(size),
+ visual_state_(visual_state),
+ repaint_callback_(repaint_callback),
+ highlight_animation_(this),
+ flood_fill_animation_(this),
+ fade_out_animation_(this) {
+ highlight_animation_.SetContainer(animation_container);
+ highlight_animation_.SetSlideDuration(kAnimationDuration.InMilliseconds());
+
+ flood_fill_animation_.SetContainer(animation_container);
+ flood_fill_animation_.SetDuration(kAnimationDuration);
+
+ fade_out_animation_.SetContainer(animation_container);
+ fade_out_animation_.SetDuration(kAnimationDuration);
+}
+
+InstallableInkDropAnimator::~InstallableInkDropAnimator() = default;
+
+void InstallableInkDropAnimator::SetSize(gfx::Size size) {
+ size_ = size;
+}
+
+void InstallableInkDropAnimator::SetLastEventLocation(
+ gfx::Point last_event_location) {
+ last_event_location_ = last_event_location;
+}
+
+void InstallableInkDropAnimator::AnimateToState(InkDropState target_state) {
+ VerifyAnimationState();
+
+ const InkDropState last_state = target_state_;
+
+ TRACE_EVENT2("views", "InstallableInkDropAnimator::AnimateToState",
+ "target_state", target_state, "last_state", last_state);
+
+ switch (target_state) {
+ case InkDropState::HIDDEN:
+ case InkDropState::DEACTIVATED:
+ // If we weren't animating to a visible state, we shouldn't do anything.
+ if (last_state == InkDropState::HIDDEN ||
+ last_state == InkDropState::DEACTIVATED) {
+ break;
+ }
+ // If we were flood-filling, jump to the end of that animation.
+ if (flood_fill_animation_.is_animating()) {
+ flood_fill_animation_.End();
+ }
+ // If we weren't already fading out, start fading out. Otherwise, just
+ // continue fading out.
+ if (!fade_out_animation_.is_animating())
+ fade_out_animation_.Start();
+ break;
+
+ case InkDropState::ACTION_PENDING:
+ if (last_state != InkDropState::HIDDEN) {
+ // Snap to hidden state by stopping all animations.
+ flood_fill_animation_.Stop();
+ fade_out_animation_.Stop();
+ }
+ flood_fill_animation_.Start();
+ break;
+
+ case InkDropState::ACTION_TRIGGERED:
+ if (last_state == InkDropState::HIDDEN) {
+ // Start the flood fill. On this animation's end, we will start the fade
+ // out animation in AnimationEnded().
+ flood_fill_animation_.Start();
+ } else if (last_state == InkDropState::ACTION_PENDING &&
+ !flood_fill_animation_.is_animating()) {
+ // If we were done animating to ACTION_PENDING, we must start the fade
+ // out animation here.
+ fade_out_animation_.Start();
+ // If we were in ACTION_PENDING but weren't done animating, we will
+ // start the fade out animation in AnimationEnded().
+ } else if (last_state != InkDropState::ACTION_PENDING) {
+ // Any other state transitions are invalid.
+ NOTREACHED() << "Transition from " << ToString(last_state)
+ << " to ACTION_TRIGGERED is invalid.";
+ }
+ break;
+
+ case InkDropState::ALTERNATE_ACTION_PENDING:
+ case InkDropState::ALTERNATE_ACTION_TRIGGERED:
+ // TODO(crbug.com/933384): handle these.
+ NOTREACHED() << "target_state = " << ToString(target_state);
+ break;
+
+ case InkDropState::ACTIVATED:
+ if (fade_out_animation_.is_animating()) {
+ // If we were fading out of ACTIVATED or ACTION_TRIGGERED, finish the
+ // animation to reset to HIDDEN state.
+ fade_out_animation_.End();
+ }
+
+ // Now simply start the flood fill animation again.
+ flood_fill_animation_.Start();
+ break;
+ }
+
+ target_state_ = target_state;
+ VerifyAnimationState();
+ repaint_callback_.Run();
+}
+
+void InstallableInkDropAnimator::AnimateHighlight(bool fade_in) {
+ if (fade_in) {
+ highlight_animation_.Show();
+ } else {
+ highlight_animation_.Hide();
+ }
+}
+
+void InstallableInkDropAnimator::VerifyAnimationState() const {
+#if DCHECK_IS_ON()
+ switch (target_state_) {
+ case InkDropState::HIDDEN:
+ case InkDropState::DEACTIVATED:
+ // We can only be fading out or completely invisible. So, we cannot be
+ // flood-filling.
+ DCHECK(!flood_fill_animation_.is_animating());
+ break;
+ case InkDropState::ACTION_PENDING:
+ case InkDropState::ACTIVATED:
+ // These states flood-fill then stay visible.
+ DCHECK(!fade_out_animation_.is_animating());
+ if (!flood_fill_animation_.is_animating())
+ DCHECK_EQ(1.0f, visual_state_->flood_fill_progress);
+ break;
+ case InkDropState::ACTION_TRIGGERED:
+ // We should always be animating during this state. Once animations are
+ // done, we automatically transition to HIDDEN. Make sure exactly one of
+ // our animations are running.
+ DCHECK_NE(flood_fill_animation_.is_animating(),
+ fade_out_animation_.is_animating());
+ break;
+ case InkDropState::ALTERNATE_ACTION_PENDING:
+ case InkDropState::ALTERNATE_ACTION_TRIGGERED:
+ // TODO(crbug.com/933384): handle these.
+ NOTREACHED() << "target_state = " << ToString(target_state_);
+ break;
+ }
+#endif // DCHECK_IS_ON()
+}
+
+void InstallableInkDropAnimator::AnimationEnded(
+ const gfx::Animation* animation) {
+ TRACE_EVENT0("views", "InstallableInkDropAnimator::AnimationEnded");
+
+ if (animation == &flood_fill_animation_) {
+ switch (target_state_) {
+ case InkDropState::ACTION_PENDING:
+ case InkDropState::ACTIVATED:
+ // The ink drop stays filled in these states so nothing needs to be
+ // done.
+ break;
+
+ case InkDropState::ACTION_TRIGGERED:
+ // After filling, the ink drop should fade out.
+ fade_out_animation_.Start();
+ break;
+
+ case InkDropState::ALTERNATE_ACTION_PENDING:
+ case InkDropState::ALTERNATE_ACTION_TRIGGERED:
+ // TODO(crbug.com/933384): handle these.
+ NOTREACHED() << "target_state_ = " << ToString(target_state_);
+ break;
+
+ case InkDropState::HIDDEN:
+ case InkDropState::DEACTIVATED:
+ // The flood fill animation should never run in these states.
+ NOTREACHED() << "target_state_ = " << ToString(target_state_);
+ break;
+ }
+
+ // The ink drop is now fully activated.
+ visual_state_->flood_fill_progress = 1.0f;
+ repaint_callback_.Run();
+ } else if (animation == &fade_out_animation_) {
+ switch (target_state_) {
+ case InkDropState::HIDDEN:
+ // Nothing to do.
+ break;
+
+ case InkDropState::ACTION_TRIGGERED:
+ case InkDropState::DEACTIVATED:
+ // These states transition to HIDDEN when they're done animating.
+ target_state_ = InkDropState::HIDDEN;
+ break;
+
+ case InkDropState::ACTION_PENDING:
+ case InkDropState::ACTIVATED:
+ // The fade out animation should never run in these states.
+ NOTREACHED() << "target_state_ = " << ToString(target_state_);
+ break;
+
+ case InkDropState::ALTERNATE_ACTION_PENDING:
+ case InkDropState::ALTERNATE_ACTION_TRIGGERED:
+ // TODO(crbug.com/933384): handle these.
+ NOTREACHED() << "target_state_ = " << ToString(target_state_);
+ break;
+ }
+
+ // The ink drop fill is fully invisible.
+ visual_state_->flood_fill_progress = 0.0f;
+ repaint_callback_.Run();
+ }
+}
+
+void InstallableInkDropAnimator::AnimationProgressed(
+ const gfx::Animation* animation) {
+ TRACE_EVENT0("views", "InstallableInkDropAnimator::AnimationProgressed");
+
+ if (animation == &highlight_animation_) {
+ visual_state_->highlighted_ratio = highlight_animation_.GetCurrentValue();
+ } else if (animation == &flood_fill_animation_) {
+ visual_state_->flood_fill_center = gfx::PointF(last_event_location_);
+ visual_state_->flood_fill_progress = gfx::Tween::CalculateValue(
+ gfx::Tween::EASE_IN_OUT, flood_fill_animation_.GetCurrentValue());
+ } else if (animation == &fade_out_animation_) {
+ // Do nothing for now.
+ } else {
+ NOTREACHED();
+ }
+
+ repaint_callback_.Run();
+}
+
+} // namespace views
diff --git a/chromium/ui/views/animation/installable_ink_drop_animator.h b/chromium/ui/views/animation/installable_ink_drop_animator.h
new file mode 100644
index 00000000000..b6bd89644f8
--- /dev/null
+++ b/chromium/ui/views/animation/installable_ink_drop_animator.h
@@ -0,0 +1,90 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_ANIMATION_INSTALLABLE_INK_DROP_ANIMATOR_H_
+#define UI_VIEWS_ANIMATION_INSTALLABLE_INK_DROP_ANIMATOR_H_
+
+#include "base/callback.h"
+#include "base/optional.h"
+#include "base/time/time.h"
+#include "base/timer/timer.h"
+#include "ui/gfx/animation/animation_delegate.h"
+#include "ui/gfx/animation/linear_animation.h"
+#include "ui/gfx/animation/slide_animation.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/views/animation/ink_drop_state.h"
+#include "ui/views/animation/installable_ink_drop_painter.h"
+
+namespace gfx {
+class AnimationContainer;
+}
+
+namespace views {
+
+// Manages animating the ink drop's visual state. This class is essentially a
+// state machine, using the current and target InkDropStates to affect the
+// InstallableInkDropPainter passed in. The animations are currently minimal.
+class VIEWS_EXPORT InstallableInkDropAnimator : public gfx::AnimationDelegate {
+ public:
+ // Placeholder duration used for all animations. TODO(crbug.com/933384):
+ // remove this and replace it with separate durations for different
+ // animations.
+ static constexpr base::TimeDelta kAnimationDuration =
+ base::TimeDelta::FromMilliseconds(500);
+
+ // We use a shared gfx::AnimationContainer for our animations to allow them to
+ // update in sync. It is passed in at construction for two reasons: it allows
+ // |views::CompositorAnimationRunner| to be used for more efficient and less
+ // janky animations, and it enables easier unit testing.
+ explicit InstallableInkDropAnimator(
+ gfx::Size size,
+ InstallableInkDropPainter::State* visual_state,
+ gfx::AnimationContainer* animation_container,
+ base::RepeatingClosure repaint_callback);
+ ~InstallableInkDropAnimator() override;
+
+ void SetSize(gfx::Size size);
+ void SetLastEventLocation(gfx::Point last_event_location);
+
+ // Set the target state and animate to it.
+ void AnimateToState(InkDropState target_state);
+
+ // Animates the hover highlight in or out. Animates in if |fade_in| is true,
+ // and out otherwise.
+ void AnimateHighlight(bool fade_in);
+
+ InkDropState target_state() const { return target_state_; }
+
+ private:
+ // Checks that the states of our animations make sense given
+ // |target_state_|. DCHECKs if something is wrong.
+ void VerifyAnimationState() const;
+
+ // gfx::AnimationDelegate:
+ void AnimationEnded(const gfx::Animation* animation) override;
+ void AnimationProgressed(const gfx::Animation* animation) override;
+
+ gfx::Size size_;
+
+ // The visual state we are controlling.
+ InstallableInkDropPainter::State* const visual_state_;
+
+ // Called when |visual_state_| changes so the user can repaint.
+ base::RepeatingClosure repaint_callback_;
+
+ InkDropState target_state_ = InkDropState::HIDDEN;
+
+ // Used to animate the painter's highlight value in and out.
+ gfx::SlideAnimation highlight_animation_;
+
+ gfx::LinearAnimation flood_fill_animation_;
+ gfx::LinearAnimation fade_out_animation_;
+
+ gfx::Point last_event_location_;
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_ANIMATION_INSTALLABLE_INK_DROP_ANIMATOR_H_
diff --git a/chromium/ui/views/animation/installable_ink_drop_animator_unittest.cc b/chromium/ui/views/animation/installable_ink_drop_animator_unittest.cc
new file mode 100644
index 00000000000..d11209e9842
--- /dev/null
+++ b/chromium/ui/views/animation/installable_ink_drop_animator_unittest.cc
@@ -0,0 +1,267 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/animation/installable_ink_drop_animator.h"
+
+#include "base/bind_helpers.h"
+#include "base/memory/scoped_refptr.h"
+#include "base/run_loop.h"
+#include "base/test/scoped_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/animation/animation_test_api.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/point_conversions.h"
+#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/views/animation/ink_drop_state.h"
+#include "ui/views/animation/installable_ink_drop_painter.h"
+
+namespace views {
+
+namespace {
+
+class InstallableInkDropAnimatorTest : public ::testing::Test {
+ public:
+ InstallableInkDropAnimatorTest()
+ : animation_container_(base::MakeRefCounted<gfx::AnimationContainer>()),
+ animation_tester_(animation_container_.get()),
+ callback_(
+ base::Bind([](bool* callback_called) { *callback_called = true; },
+ &callback_called_)) {}
+
+ protected:
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+
+ scoped_refptr<gfx::AnimationContainer> animation_container_;
+ gfx::AnimationContainerTestApi animation_tester_;
+
+ InstallableInkDropPainter::State visual_state_;
+
+ bool callback_called_ = false;
+ base::RepeatingClosure callback_;
+};
+
+} // namespace
+
+TEST_F(InstallableInkDropAnimatorTest, UpdatesTargetState) {
+ InstallableInkDropAnimator animator(gfx::Size(2, 2), &visual_state_,
+ animation_container_.get(),
+ base::DoNothing());
+ EXPECT_EQ(InkDropState::HIDDEN, animator.target_state());
+
+ animator.AnimateToState(InkDropState::ACTIVATED);
+ EXPECT_EQ(InkDropState::ACTIVATED, animator.target_state());
+}
+
+TEST_F(InstallableInkDropAnimatorTest, AnimateToTriggeredFromHidden) {
+ InstallableInkDropAnimator animator(gfx::Size(10, 10), &visual_state_,
+ animation_container_.get(), callback_);
+ EXPECT_EQ(0.0f, visual_state_.flood_fill_progress);
+
+ animator.SetLastEventLocation(gfx::Point(5, 5));
+ animator.AnimateToState(InkDropState::ACTION_TRIGGERED);
+ EXPECT_EQ(InkDropState::ACTION_TRIGGERED, animator.target_state());
+ EXPECT_GT(1.0f, visual_state_.flood_fill_progress);
+
+ callback_called_ = false;
+ animation_tester_.IncrementTime(
+ InstallableInkDropAnimator::kAnimationDuration);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(InkDropState::ACTION_TRIGGERED, animator.target_state());
+ EXPECT_EQ(1.0f, visual_state_.flood_fill_progress);
+ EXPECT_TRUE(callback_called_);
+
+ callback_called_ = false;
+ animation_tester_.IncrementTime(
+ InstallableInkDropAnimator::kAnimationDuration);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(InkDropState::HIDDEN, animator.target_state());
+ EXPECT_EQ(0.0f, visual_state_.flood_fill_progress);
+ EXPECT_TRUE(callback_called_);
+}
+
+TEST_F(InstallableInkDropAnimatorTest,
+ AnimateToPendingThenTriggeredFromHidden) {
+ InstallableInkDropAnimator animator(gfx::Size(10, 10), &visual_state_,
+ animation_container_.get(), callback_);
+
+ animator.SetLastEventLocation(gfx::Point(5, 5));
+ animator.AnimateToState(InkDropState::ACTION_PENDING);
+ EXPECT_EQ(InkDropState::ACTION_PENDING, animator.target_state());
+ EXPECT_GT(1.0f, visual_state_.flood_fill_progress);
+
+ callback_called_ = false;
+ animation_tester_.IncrementTime(
+ InstallableInkDropAnimator::kAnimationDuration);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(InkDropState::ACTION_PENDING, animator.target_state());
+ EXPECT_EQ(1.0f, visual_state_.flood_fill_progress);
+ EXPECT_TRUE(callback_called_);
+
+ // The animation should be finished now and the visual state should *not*
+ // change; ACTION_PENDING lasts indefinitely.
+ animation_tester_.IncrementTime(
+ InstallableInkDropAnimator::kAnimationDuration);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(InkDropState::ACTION_PENDING, animator.target_state());
+ EXPECT_EQ(1.0f, visual_state_.flood_fill_progress);
+
+ // Animating to ACTION_TRIGGERED from ACTION_PENDING should not repeat the
+ // flood-fill animation. Instead, it should just fade out.
+ animator.AnimateToState(InkDropState::ACTION_TRIGGERED);
+ EXPECT_EQ(InkDropState::ACTION_TRIGGERED, animator.target_state());
+ EXPECT_EQ(1.0f, visual_state_.flood_fill_progress);
+
+ animation_tester_.IncrementTime(
+ InstallableInkDropAnimator::kAnimationDuration);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(InkDropState::HIDDEN, animator.target_state());
+ EXPECT_EQ(0.0f, visual_state_.flood_fill_progress);
+}
+
+TEST_F(InstallableInkDropAnimatorTest,
+ AnimateToPendingWhileAnimatingToTriggered) {
+ const base::TimeDelta kHalfAnimationDuration =
+ InstallableInkDropAnimator::kAnimationDuration / 2;
+ const base::TimeDelta kRemainingAnimationDuration =
+ InstallableInkDropAnimator::kAnimationDuration - kHalfAnimationDuration;
+
+ InstallableInkDropAnimator animator(gfx::Size(10, 10), &visual_state_,
+ animation_container_.get(), callback_);
+
+ animator.SetLastEventLocation(gfx::Point(5, 5));
+ animator.AnimateToState(InkDropState::ACTION_PENDING);
+ EXPECT_EQ(InkDropState::ACTION_PENDING, animator.target_state());
+ EXPECT_GT(1.0f, visual_state_.flood_fill_progress);
+
+ callback_called_ = false;
+ animation_tester_.IncrementTime(kHalfAnimationDuration);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(InkDropState::ACTION_PENDING, animator.target_state());
+ EXPECT_LT(0.0f, visual_state_.flood_fill_progress);
+ EXPECT_GT(1.0f, visual_state_.flood_fill_progress);
+ EXPECT_TRUE(callback_called_);
+
+ // Switching to ACTION_TRIGGERED should not restart the animation. Instead, it
+ // should just add a transition to HIDDEN after the flood-fill is done.
+ animator.AnimateToState(InkDropState::ACTION_TRIGGERED);
+ EXPECT_EQ(InkDropState::ACTION_TRIGGERED, animator.target_state());
+ EXPECT_LT(0.0f, visual_state_.flood_fill_progress);
+ EXPECT_GT(1.0f, visual_state_.flood_fill_progress);
+
+ callback_called_ = false;
+ animation_tester_.IncrementTime(kRemainingAnimationDuration);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(InkDropState::ACTION_TRIGGERED, animator.target_state());
+ EXPECT_EQ(1.0f, visual_state_.flood_fill_progress);
+ EXPECT_TRUE(callback_called_);
+}
+
+TEST_F(InstallableInkDropAnimatorTest, AnimateToActivatedThenDeactivated) {
+ InstallableInkDropAnimator animator(gfx::Size(10, 10), &visual_state_,
+ animation_container_.get(), callback_);
+
+ animator.SetLastEventLocation(gfx::Point(5, 5));
+ animator.AnimateToState(InkDropState::ACTIVATED);
+ EXPECT_EQ(InkDropState::ACTIVATED, animator.target_state());
+ EXPECT_GT(1.0f, visual_state_.flood_fill_progress);
+
+ callback_called_ = false;
+ animation_tester_.IncrementTime(
+ InstallableInkDropAnimator::kAnimationDuration);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(InkDropState::ACTIVATED, animator.target_state());
+ EXPECT_EQ(1.0f, visual_state_.flood_fill_progress);
+ EXPECT_TRUE(callback_called_);
+
+ // The state should stay the same indefinitely.
+ animation_tester_.IncrementTime(
+ InstallableInkDropAnimator::kAnimationDuration);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(InkDropState::ACTIVATED, animator.target_state());
+ EXPECT_EQ(1.0f, visual_state_.flood_fill_progress);
+
+ // Animating to DEACTIVATED should fade out and transition to HIDDEN.
+ animator.AnimateToState(InkDropState::DEACTIVATED);
+ EXPECT_EQ(InkDropState::DEACTIVATED, animator.target_state());
+ EXPECT_EQ(1.0f, visual_state_.flood_fill_progress);
+
+ callback_called_ = false;
+ animation_tester_.IncrementTime(
+ InstallableInkDropAnimator::kAnimationDuration);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(InkDropState::HIDDEN, animator.target_state());
+ EXPECT_EQ(0.0f, visual_state_.flood_fill_progress);
+}
+
+TEST_F(InstallableInkDropAnimatorTest,
+ FloodFillAnimationExpandsFromEventLocation) {
+ constexpr gfx::Point kEventLocation(3, 7);
+
+ // Split |InstallableInkDrop::kAnimationDuration| into three chunks.
+ const base::TimeDelta kFirstDuration =
+ InstallableInkDropAnimator::kAnimationDuration / 3;
+ const base::TimeDelta kSecondDuration = kFirstDuration;
+ const base::TimeDelta kLastDuration =
+ InstallableInkDropAnimator::kAnimationDuration - kFirstDuration -
+ kSecondDuration;
+
+ InstallableInkDropAnimator animator(gfx::Size(10, 10), &visual_state_,
+ animation_container_.get(), callback_);
+
+ animator.SetLastEventLocation(kEventLocation);
+ animator.AnimateToState(InkDropState::ACTIVATED);
+
+ callback_called_ = false;
+ animation_tester_.IncrementTime(kFirstDuration);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(callback_called_);
+ EXPECT_LT(0.0f, visual_state_.flood_fill_progress);
+ EXPECT_GT(1.0f, visual_state_.flood_fill_progress);
+
+ const float first_progress = visual_state_.flood_fill_progress;
+
+ callback_called_ = false;
+ animation_tester_.IncrementTime(kSecondDuration);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(callback_called_);
+ EXPECT_LT(first_progress, visual_state_.flood_fill_progress);
+ EXPECT_GT(1.0f, visual_state_.flood_fill_progress);
+
+ callback_called_ = false;
+ animation_tester_.IncrementTime(kLastDuration);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_TRUE(callback_called_);
+ EXPECT_EQ(1.0f, visual_state_.flood_fill_progress);
+}
+
+TEST_F(InstallableInkDropAnimatorTest, HighlightAnimationFadesInAndOut) {
+ InstallableInkDropAnimator animator(gfx::Size(2, 2), &visual_state_,
+ animation_container_.get(), callback_);
+ EXPECT_EQ(0.0f, visual_state_.highlighted_ratio);
+ EXPECT_FALSE(callback_called_);
+
+ animator.AnimateHighlight(true);
+ EXPECT_EQ(0.0f, visual_state_.highlighted_ratio);
+
+ callback_called_ = false;
+ animation_tester_.IncrementTime(
+ InstallableInkDropAnimator::kAnimationDuration);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(1.0f, visual_state_.highlighted_ratio);
+ EXPECT_TRUE(callback_called_);
+
+ animator.AnimateHighlight(false);
+ EXPECT_EQ(1.0f, visual_state_.highlighted_ratio);
+
+ callback_called_ = false;
+ animation_tester_.IncrementTime(
+ InstallableInkDropAnimator::kAnimationDuration);
+ base::RunLoop().RunUntilIdle();
+ EXPECT_EQ(0.0f, visual_state_.highlighted_ratio);
+ EXPECT_TRUE(callback_called_);
+}
+
+} // namespace views
diff --git a/chromium/ui/views/animation/installable_ink_drop_config.h b/chromium/ui/views/animation/installable_ink_drop_config.h
new file mode 100644
index 00000000000..8e19ae13ce0
--- /dev/null
+++ b/chromium/ui/views/animation/installable_ink_drop_config.h
@@ -0,0 +1,23 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_ANIMATION_INSTALLABLE_INK_DROP_CONFIG_H_
+#define UI_VIEWS_ANIMATION_INSTALLABLE_INK_DROP_CONFIG_H_
+
+#include "third_party/skia/include/core/SkColor.h"
+
+namespace views {
+
+struct InstallableInkDropConfig {
+ // The color of ink drop effects, modulated by opacity.
+ SkColor base_color;
+ // The opacity to paint |base_color| at for a fully-visible ripple.
+ float ripple_opacity;
+ // The opacity to paint |base_color| at for a fully-visible hover highlight.
+ float highlight_opacity;
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_ANIMATION_INSTALLABLE_INK_DROP_CONFIG_H_
diff --git a/chromium/ui/views/animation/installable_ink_drop_painter.cc b/chromium/ui/views/animation/installable_ink_drop_painter.cc
new file mode 100644
index 00000000000..8ae4abe39e1
--- /dev/null
+++ b/chromium/ui/views/animation/installable_ink_drop_painter.cc
@@ -0,0 +1,68 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/animation/installable_ink_drop_painter.h"
+
+#include "base/trace_event/trace_event.h"
+#include "cc/paint/paint_flags.h"
+#include "ui/gfx/animation/tween.h"
+#include "ui/gfx/canvas.h"
+#include "ui/gfx/geometry/point.h"
+#include "ui/gfx/geometry/point_f.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/gfx/geometry/vector2d_f.h"
+#include "ui/views/animation/installable_ink_drop_config.h"
+
+namespace views {
+
+InstallableInkDropPainter::State::State() = default;
+InstallableInkDropPainter::State::~State() = default;
+
+gfx::Size InstallableInkDropPainter::GetMinimumSize() const {
+ return gfx::Size();
+}
+
+void InstallableInkDropPainter::Paint(gfx::Canvas* canvas,
+ const gfx::Size& size) {
+ TRACE_EVENT0("views", "InstallableInkDropPainter::Paint");
+
+ DCHECK_GE(state_->flood_fill_progress, 0.0f);
+ DCHECK_LE(state_->flood_fill_progress, 1.0f);
+ DCHECK_GE(state_->highlighted_ratio, 0.0f);
+ DCHECK_LE(state_->highlighted_ratio, 1.0f);
+
+ if (state_->highlighted_ratio > 0.0f) {
+ canvas->FillRect(
+ gfx::Rect(size),
+ SkColorSetA(config_->base_color, config_->highlight_opacity *
+ state_->highlighted_ratio *
+ SK_AlphaOPAQUE));
+ }
+
+ // If fully filled, we can draw the activated color more efficiently as a
+ // rectangle.
+ if (state_->flood_fill_progress == 1.0f) {
+ canvas->FillRect(gfx::Rect(size),
+ SkColorSetA(config_->base_color,
+ config_->ripple_opacity * SK_AlphaOPAQUE));
+ } else if (state_->flood_fill_progress > 0.0f) {
+ // We interpolate between a circle of radius 2 and a circle whose radius is
+ // the diagonal of |size|.
+ const float min_radius = 2.0f;
+ const float max_radius =
+ gfx::Vector2dF(size.width(), size.height()).Length();
+ const float cur_radius = gfx::Tween::FloatValueBetween(
+ state_->flood_fill_progress, min_radius, max_radius);
+
+ cc::PaintFlags flags;
+ flags.setStyle(cc::PaintFlags::kFill_Style);
+ flags.setColor(SkColorSetA(config_->base_color,
+ config_->ripple_opacity * SK_AlphaOPAQUE));
+ canvas->DrawCircle(state_->flood_fill_center, cur_radius, flags);
+ }
+}
+
+} // namespace views
diff --git a/chromium/ui/views/animation/installable_ink_drop_painter.h b/chromium/ui/views/animation/installable_ink_drop_painter.h
new file mode 100644
index 00000000000..2ac1dcf0fc0
--- /dev/null
+++ b/chromium/ui/views/animation/installable_ink_drop_painter.h
@@ -0,0 +1,53 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_ANIMATION_INSTALLABLE_INK_DROP_PAINTER_H_
+#define UI_VIEWS_ANIMATION_INSTALLABLE_INK_DROP_PAINTER_H_
+
+#include "base/optional.h"
+#include "ui/gfx/geometry/rect_f.h"
+#include "ui/views/painter.h"
+
+namespace views {
+
+struct InstallableInkDropConfig;
+
+// Holds the current visual state of the installable ink drop and handles
+// painting it. The |Painter::Paint()| implementation draws a rectangular ink
+// drop of the given size; the user should set a clip path via
+// |gfx::Canvas::ClipPath()| to control the shape.
+class VIEWS_EXPORT InstallableInkDropPainter : public Painter {
+ public:
+ struct VIEWS_EXPORT State {
+ State();
+ ~State();
+
+ gfx::PointF flood_fill_center;
+ float flood_fill_progress = 0.0f;
+ float highlighted_ratio = 0.0f;
+ };
+
+ // Pointer arguments must outlive |this|.
+ InstallableInkDropPainter(const InstallableInkDropConfig* config,
+ const State* state)
+ : config_(config), state_(state) {}
+ ~InstallableInkDropPainter() override = default;
+
+ // Painter:
+ gfx::Size GetMinimumSize() const override;
+ void Paint(gfx::Canvas* canvas, const gfx::Size& size) override;
+
+ private:
+ // Contains the colors and opacities we use to paint, given the current state.
+ // This isn't modified inside this class, but it can be modified by our user.
+ const InstallableInkDropConfig* const config_;
+
+ // The current visual state. This isn't modified inside this class, but it can
+ // be modified by our user.
+ const State* const state_;
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_ANIMATION_INSTALLABLE_INK_DROP_PAINTER_H_
diff --git a/chromium/ui/views/animation/installable_ink_drop_unittest.cc b/chromium/ui/views/animation/installable_ink_drop_unittest.cc
index d75acaee15f..b6d27e2e9a4 100644
--- a/chromium/ui/views/animation/installable_ink_drop_unittest.cc
+++ b/chromium/ui/views/animation/installable_ink_drop_unittest.cc
@@ -4,20 +4,70 @@
#include "ui/views/animation/installable_ink_drop.h"
+#include <memory>
+
+#include "base/test/scoped_task_environment.h"
#include "testing/gtest/include/gtest/gtest.h"
+#include "third_party/skia/include/core/SkPath.h"
+#include "ui/gfx/geometry/rect.h"
#include "ui/views/animation/ink_drop_state.h"
+#include "ui/views/view.h"
+#include "ui/views/view_class_properties.h"
namespace views {
-TEST(InstallableInkDropTest, UpdatesState) {
- InstallableInkDrop installable_ink_drop;
+class InstallableInkDropTest : public ::testing::Test {
+ protected:
+ void SetUp() override {
+ // Ink drop layers get installed as siblings to their host view's
+ // layer. Hence, there needs to be a root view with a layer above them.
+ root_view_.SetPaintToLayer();
+ }
+
+ View* root_view() { return &root_view_; }
+
+ private:
+ base::test::ScopedTaskEnvironment scoped_task_environment_;
+
+ View root_view_;
+};
+
+TEST_F(InstallableInkDropTest, LayerIsAddedAndRemoved) {
+ View* view = root_view()->AddChildView(std::make_unique<View>());
+ view->SetPaintToLayer();
+ EXPECT_EQ(1, static_cast<int>(root_view()->layer()->children().size()));
+
+ {
+ InstallableInkDrop ink_drop(view);
+ EXPECT_EQ(2, static_cast<int>(root_view()->layer()->children().size()));
+ }
+
+ EXPECT_EQ(1, static_cast<int>(root_view()->layer()->children().size()));
+}
+
+TEST_F(InstallableInkDropTest, LayerSizeTracksViewSize) {
+ View* view = root_view()->AddChildView(std::make_unique<View>());
+ view->SetBoundsRect(gfx::Rect(0, 0, 10, 10));
+
+ InstallableInkDrop ink_drop(view);
+ EXPECT_EQ(view->size(), ink_drop.layer_for_testing()->size());
+
+ view->SetBoundsRect(gfx::Rect(0, 0, 20, 15));
+ EXPECT_EQ(view->size(), ink_drop.layer_for_testing()->size());
+
+ view->SetBoundsRect(gfx::Rect(10, 10, 30, 30));
+ EXPECT_EQ(view->size(), ink_drop.layer_for_testing()->size());
+}
+
+TEST_F(InstallableInkDropTest, UpdatesState) {
+ View* view = root_view()->AddChildView(std::make_unique<View>());
+ InstallableInkDrop ink_drop(view);
// Initial state should be HIDDEN.
- EXPECT_EQ(installable_ink_drop.GetTargetInkDropState(), InkDropState::HIDDEN);
+ EXPECT_EQ(ink_drop.GetTargetInkDropState(), InkDropState::HIDDEN);
- installable_ink_drop.AnimateToState(InkDropState::ACTIVATED);
- EXPECT_EQ(installable_ink_drop.GetTargetInkDropState(),
- InkDropState::ACTIVATED);
+ ink_drop.AnimateToState(InkDropState::ACTIVATED);
+ EXPECT_EQ(ink_drop.GetTargetInkDropState(), InkDropState::ACTIVATED);
}
} // namespace views
diff --git a/chromium/ui/views/bubble/bubble_dialog_delegate_view.cc b/chromium/ui/views/bubble/bubble_dialog_delegate_view.cc
index ee6f0497efb..161f0b5fd49 100644
--- a/chromium/ui/views/bubble/bubble_dialog_delegate_view.cc
+++ b/chromium/ui/views/bubble/bubble_dialog_delegate_view.cc
@@ -33,6 +33,9 @@
namespace views {
+// static
+bool BubbleDialogDelegateView::devtools_dismiss_override_ = false;
+
namespace {
// Override base functionality of Widget to give bubble dialogs access to the
@@ -116,10 +119,6 @@ Widget* CreateBubbleWidget(BubbleDialogDelegateView* bubble) {
} // namespace
-// static
-const char BubbleDialogDelegateView::kViewClassName[] =
- "BubbleDialogDelegateView";
-
BubbleDialogDelegateView::~BubbleDialogDelegateView() {
if (GetWidget())
GetWidget()->RemoveObserver(this);
@@ -181,10 +180,6 @@ NonClientFrameView* BubbleDialogDelegateView::CreateNonClientFrameView(
return frame;
}
-const char* BubbleDialogDelegateView::GetClassName() const {
- return kViewClassName;
-}
-
bool BubbleDialogDelegateView::AcceleratorPressed(
const ui::Accelerator& accelerator) {
if (accelerator.key_code() == ui::VKEY_DOWN ||
@@ -230,6 +225,9 @@ void BubbleDialogDelegateView::OnWidgetVisibilityChanged(Widget* widget,
void BubbleDialogDelegateView::OnWidgetActivationChanged(Widget* widget,
bool active) {
+ if (devtools_dismiss_override_)
+ return;
+
#if defined(OS_MACOSX)
// Install |mac_bubble_closer_| the first time the widget becomes active.
if (widget == GetWidget() && active && !mac_bubble_closer_) {
@@ -273,6 +271,15 @@ void BubbleDialogDelegateView::SetHighlightedButton(
}
void BubbleDialogDelegateView::SetArrow(BubbleBorder::Arrow arrow) {
+ SetArrowWithoutResizing(arrow);
+ // If SetArrow() is called before CreateWidget(), there's no need to update
+ // the BubbleFrameView.
+ if (GetBubbleFrameView())
+ SizeToContents();
+}
+
+void BubbleDialogDelegateView::SetArrowWithoutResizing(
+ BubbleBorder::Arrow arrow) {
if (base::i18n::IsRTL())
arrow = BubbleBorder::horizontal_mirror(arrow);
if (arrow_ == arrow)
@@ -281,10 +288,8 @@ void BubbleDialogDelegateView::SetArrow(BubbleBorder::Arrow arrow) {
// If SetArrow() is called before CreateWidget(), there's no need to update
// the BubbleFrameView.
- if (GetBubbleFrameView()) {
+ if (GetBubbleFrameView())
GetBubbleFrameView()->SetArrow(arrow);
- SizeToContents();
- }
}
gfx::Rect BubbleDialogDelegateView::GetAnchorRect() const {
@@ -517,4 +522,8 @@ void BubbleDialogDelegateView::UpdateHighlightedButton(bool highlighted) {
button->SetHighlighted(highlighted);
}
+BEGIN_METADATA(BubbleDialogDelegateView)
+METADATA_PARENT_CLASS(DialogDelegateView)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/bubble/bubble_dialog_delegate_view.h b/chromium/ui/views/bubble/bubble_dialog_delegate_view.h
index bb495e34edb..77288a2077c 100644
--- a/chromium/ui/views/bubble/bubble_dialog_delegate_view.h
+++ b/chromium/ui/views/bubble/bubble_dialog_delegate_view.h
@@ -30,6 +30,10 @@ namespace ui {
class Accelerator;
} // namespace ui
+namespace ui_devtools {
+class PageAgentViews;
+}
+
namespace views {
class BubbleFrameView;
@@ -39,8 +43,7 @@ class Button;
class VIEWS_EXPORT BubbleDialogDelegateView : public DialogDelegateView,
public WidgetObserver {
public:
- // Internal class name.
- static const char kViewClassName[];
+ METADATA_HEADER(BubbleDialogDelegateView);
enum class CloseReason {
DEACTIVATION,
@@ -58,7 +61,6 @@ class VIEWS_EXPORT BubbleDialogDelegateView : public DialogDelegateView,
bool ShouldShowCloseButton() const override;
ClientView* CreateClientView(Widget* widget) override;
NonClientFrameView* CreateNonClientFrameView(Widget* widget) override;
- const char* GetClassName() const override;
bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
// WidgetObserver:
@@ -81,9 +83,19 @@ class VIEWS_EXPORT BubbleDialogDelegateView : public DialogDelegateView,
// The anchor rect is used in the absence of an assigned anchor view.
const gfx::Rect& anchor_rect() const { return anchor_rect_; }
- // Set the desired arrow for the bubble. The arrow will be mirrored for RTL.
+ // Set the desired arrow for the bubble and updates the bubble's bounds
+ // accordingly. The arrow will be mirrored for RTL.
void SetArrow(BubbleBorder::Arrow arrow);
+ // Sets the arrow without recaluclating or updating bounds. This could be used
+ // proceeding another function call which also sets bounds, so that bounds are
+ // not set multiple times in a row. When animating bounds changes, setting
+ // bounds twice in a row can make the widget position jump.
+ // TODO(crbug.com/982880) It would be good to be able to re-target the
+ // animation rather than expet callers to use SetArrowWithoutResizing if they
+ // are also changing the anchor rect, or similar.
+ void SetArrowWithoutResizing(BubbleBorder::Arrow arrow);
+
BubbleBorder::Shadow GetShadow() const;
void set_shadow(BubbleBorder::Shadow shadow) { shadow_ = shadow; }
@@ -184,6 +196,7 @@ class VIEWS_EXPORT BubbleDialogDelegateView : public DialogDelegateView,
private:
friend class BubbleBorderDelegate;
friend class BubbleWindowTargeter;
+ friend class ui_devtools::PageAgentViews;
FRIEND_TEST_ALL_PREFIXES(BubbleDelegateTest, CreateDelegate);
FRIEND_TEST_ALL_PREFIXES(BubbleDelegateTest, NonClientHitTest);
@@ -202,6 +215,10 @@ class VIEWS_EXPORT BubbleDialogDelegateView : public DialogDelegateView,
// provide different highlight effects.
virtual void UpdateHighlightedButton(bool highlighted);
+ // Set from UI DevTools to prevent bubbles from closing in
+ // OnWidgetActivationChanged().
+ static bool devtools_dismiss_override_;
+
// A flag controlling bubble closure on deactivation.
bool close_on_deactivate_;
diff --git a/chromium/ui/views/bubble/bubble_frame_view.cc b/chromium/ui/views/bubble/bubble_frame_view.cc
index 419abab9192..1508e41f366 100644
--- a/chromium/ui/views/bubble/bubble_frame_view.cc
+++ b/chromium/ui/views/bubble/bubble_frame_view.cc
@@ -28,7 +28,6 @@
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/button/image_button_factory.h"
#include "ui/views/controls/image_view.h"
-#include "ui/views/event_utils.h"
#include "ui/views/layout/box_layout.h"
#include "ui/views/layout/layout_provider.h"
#include "ui/views/paint_info.h"
@@ -104,7 +103,7 @@ std::unique_ptr<Label> BubbleFrameView::CreateDefaultTitleLabel(
const base::string16& title_text) {
auto title = std::make_unique<Label>(title_text, style::CONTEXT_DIALOG_TITLE);
title->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- title->set_collapse_when_hidden(true);
+ title->SetCollapseWhenHidden(true);
title->SetMultiLine(true);
return title;
}
@@ -404,9 +403,7 @@ void BubbleFrameView::ViewHierarchyChanged(
void BubbleFrameView::VisibilityChanged(View* starting_from, bool is_visible) {
NonClientFrameView::VisibilityChanged(starting_from, is_visible);
-
- if (is_visible)
- view_shown_time_stamp_ = base::TimeTicks::Now();
+ input_protector_.VisibilityChanged(is_visible);
}
void BubbleFrameView::OnPaint(gfx::Canvas* canvas) {
@@ -426,7 +423,7 @@ void BubbleFrameView::PaintChildren(const PaintInfo& paint_info) {
}
void BubbleFrameView::ButtonPressed(Button* sender, const ui::Event& event) {
- if (IsPossiblyUnintendedInteraction(view_shown_time_stamp_, event))
+ if (input_protector_.IsPossiblyUnintendedInteraction(event))
return;
if (sender == close_) {
@@ -446,15 +443,17 @@ void BubbleFrameView::SetBubbleBorder(std::unique_ptr<BubbleBorder> border) {
SetBackground(std::make_unique<views::BubbleBackground>(bubble_border_));
}
-void BubbleFrameView::SetFootnoteView(View* view) {
- if (!view)
+void BubbleFrameView::SetFootnoteView(std::unique_ptr<View> view) {
+ if (!view) {
+ delete footnote_container_;
+ footnote_container_ = nullptr;
return;
+ }
DCHECK(!footnote_container_);
int radius = bubble_border_ ? bubble_border_->corner_radius() : 0;
- footnote_container_ =
- new FootnoteContainerView(footnote_margins_, view, radius);
- AddChildView(footnote_container_);
+ footnote_container_ = AddChildView(std::make_unique<FootnoteContainerView>(
+ footnote_margins_, std::move(view), radius));
}
void BubbleFrameView::SetCornerRadius(int radius) {
@@ -512,7 +511,7 @@ gfx::Rect BubbleFrameView::GetUpdatedWindowBounds(
}
void BubbleFrameView::ResetViewShownTimeStampForTesting() {
- view_shown_time_stamp_ = base::TimeTicks();
+ input_protector_.ResetForTesting();
}
gfx::Rect BubbleFrameView::GetAvailableScreenBounds(
diff --git a/chromium/ui/views/bubble/bubble_frame_view.h b/chromium/ui/views/bubble/bubble_frame_view.h
index a3b91eb0840..45eb1ef8413 100644
--- a/chromium/ui/views/bubble/bubble_frame_view.h
+++ b/chromium/ui/views/bubble/bubble_frame_view.h
@@ -16,6 +16,7 @@
#include "ui/views/bubble/bubble_border.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/label.h"
+#include "ui/views/input_event_activation_protector.h"
#include "ui/views/window/non_client_view.h"
namespace views {
@@ -88,7 +89,7 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView,
gfx::Insets content_margins() const { return content_margins_; }
- void SetFootnoteView(View* view);
+ void SetFootnoteView(std::unique_ptr<View> view);
void set_footnote_margins(const gfx::Insets& footnote_margins) {
footnote_margins_ = footnote_margins;
}
@@ -216,9 +217,6 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView,
// A view to contain the footnote view, if it exists.
FootnoteContainerView* footnote_container_;
- // Time when view has been shown.
- base::TimeTicks view_shown_time_stamp_;
-
// Set preference for how the arrow will be adjusted if the window is outside
// the available bounds.
PreferredArrowAdjustment preferred_arrow_adjustment_ =
@@ -228,6 +226,8 @@ class VIEWS_EXPORT BubbleFrameView : public NonClientFrameView,
// hover).
bool hit_test_transparent_ = false;
+ InputEventActivationProtector input_protector_;
+
DISALLOW_COPY_AND_ASSIGN(BubbleFrameView);
};
diff --git a/chromium/ui/views/bubble/bubble_frame_view_unittest.cc b/chromium/ui/views/bubble/bubble_frame_view_unittest.cc
index 82b0779727c..d4b6ed70794 100644
--- a/chromium/ui/views/bubble/bubble_frame_view_unittest.cc
+++ b/chromium/ui/views/bubble/bubble_frame_view_unittest.cc
@@ -180,22 +180,22 @@ TEST_F(BubbleFrameViewTest, GetBoundsForClientViewWithClose) {
TEST_F(BubbleFrameViewTest, RemoveFootnoteView) {
TestBubbleFrameView frame(this);
EXPECT_EQ(nullptr, frame.footnote_container_);
- View* footnote_dummy_view = new StaticSizedView(gfx::Size(200, 200));
- frame.SetFootnoteView(footnote_dummy_view);
+ auto footnote = std::make_unique<StaticSizedView>(gfx::Size(200, 200));
+ View* footnote_dummy_view = footnote.get();
+ frame.SetFootnoteView(std::move(footnote));
EXPECT_EQ(footnote_dummy_view->parent(), frame.footnote_container_);
- View* container_view = footnote_dummy_view->parent();
- delete footnote_dummy_view;
- footnote_dummy_view = nullptr;
- EXPECT_FALSE(container_view->GetVisible());
+ frame.SetFootnoteView(nullptr);
EXPECT_EQ(nullptr, frame.footnote_container_);
}
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);
+ std::unique_ptr<View> footnote =
+ std::make_unique<StaticSizedView>(gfx::Size(200, 200));
+ footnote->SetVisible(false);
+ View* footnote_dummy_view = footnote.get();
+ frame.SetFootnoteView(std::move(footnote));
View* footnote_container_view = footnote_dummy_view->parent();
EXPECT_FALSE(footnote_container_view->GetVisible());
footnote_dummy_view->SetVisible(true);
@@ -807,19 +807,21 @@ TEST_F(BubbleFrameViewTest, GetPreferredSizeWithFootnote) {
constexpr int kFootnoteHeight = 20;
const gfx::Size no_footnote_size = frame.GetPreferredSize();
- View* footnote = new StaticSizedView(gfx::Size(10, kFootnoteHeight));
+ std::unique_ptr<View> footnote =
+ std::make_unique<StaticSizedView>(gfx::Size(10, kFootnoteHeight));
footnote->SetVisible(false);
- frame.SetFootnoteView(footnote);
+ View* footnote_dummy_view = footnote.get();
+ frame.SetFootnoteView(std::move(footnote));
EXPECT_EQ(no_footnote_size, frame.GetPreferredSize()); // No change.
- footnote->SetVisible(true);
+ footnote_dummy_view->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);
+ footnote_dummy_view->SetVisible(false);
EXPECT_EQ(no_footnote_size, frame.GetPreferredSize());
}
@@ -1106,8 +1108,8 @@ TEST_F(BubbleFrameViewTest, NoElideTitle) {
// Sanity check: Title labels default to multiline and elide tail. Either of
// which result in the Layout system making the title and resulting dialog
// very narrow.
- EXPECT_EQ(gfx::ELIDE_TAIL, title_label->elide_behavior());
- EXPECT_TRUE(title_label->multi_line());
+ EXPECT_EQ(gfx::ELIDE_TAIL, title_label->GetElideBehavior());
+ EXPECT_TRUE(title_label->GetMultiLine());
EXPECT_GT(empty_bubble_width, title_label->size().width());
EXPECT_EQ(empty_bubble_width, bubble->GetClientAreaBoundsInScreen().width());
diff --git a/chromium/ui/views/bubble/footnote_container_view.cc b/chromium/ui/views/bubble/footnote_container_view.cc
index 4277f0329c0..33a01690829 100644
--- a/chromium/ui/views/bubble/footnote_container_view.cc
+++ b/chromium/ui/views/bubble/footnote_container_view.cc
@@ -49,26 +49,27 @@ class HalfRoundedRectBackground : public Background {
} // namespace
FootnoteContainerView::FootnoteContainerView(const gfx::Insets& margins,
- View* child_view,
+ std::unique_ptr<View> child_view,
float corner_radius) {
- SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kVertical, margins, 0));
+ SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kVertical, margins, 0));
SetCornerRadius(corner_radius);
- SetBorder(CreateSolidSidedBorder(1, 0, 0, 0,
- GetNativeTheme()->SystemDarkModeEnabled()
- ? gfx::kGoogleGrey900
- : gfx::kGoogleGrey200));
- AddChildView(child_view);
- SetVisible(child_view->GetVisible());
+ ResetBorder();
+ auto* child_view_ptr = AddChildView(std::move(child_view));
+ SetVisible(child_view_ptr->GetVisible());
}
FootnoteContainerView::~FootnoteContainerView() = default;
void FootnoteContainerView::SetCornerRadius(float corner_radius) {
- SkColor background_color = GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_BubbleFooterBackground);
- SetBackground(std::make_unique<HalfRoundedRectBackground>(background_color,
- corner_radius));
+ corner_radius_ = corner_radius;
+ ResetBackground();
+}
+
+void FootnoteContainerView::OnThemeChanged() {
+ View::OnThemeChanged();
+ ResetBorder();
+ ResetBackground();
}
void FootnoteContainerView::ChildVisibilityChanged(View* child) {
@@ -76,4 +77,22 @@ void FootnoteContainerView::ChildVisibilityChanged(View* child) {
SetVisible(child->GetVisible());
}
+void FootnoteContainerView::ResetBackground() {
+ SkColor background_color = GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_BubbleFooterBackground);
+ SetBackground(std::make_unique<HalfRoundedRectBackground>(background_color,
+ corner_radius_));
+}
+
+void FootnoteContainerView::ResetBorder() {
+ SetBorder(CreateSolidSidedBorder(1, 0, 0, 0,
+ GetNativeTheme()->SystemDarkModeEnabled()
+ ? gfx::kGoogleGrey900
+ : gfx::kGoogleGrey200));
+}
+
+BEGIN_METADATA(FootnoteContainerView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/bubble/footnote_container_view.h b/chromium/ui/views/bubble/footnote_container_view.h
index 2b4bea9235f..d49778e064c 100644
--- a/chromium/ui/views/bubble/footnote_container_view.h
+++ b/chromium/ui/views/bubble/footnote_container_view.h
@@ -13,17 +13,25 @@ namespace views {
// background with rounded corners at the bottom.
class FootnoteContainerView : public View {
public:
+ METADATA_HEADER(FootnoteContainerView);
+
FootnoteContainerView(const gfx::Insets& margins,
- View* child_view,
+ std::unique_ptr<View> child_view,
float corner_radius);
~FootnoteContainerView() override;
void SetCornerRadius(float corner_radius);
// View:
+ void OnThemeChanged() override;
void ChildVisibilityChanged(View* child) override;
private:
+ void ResetBackground();
+ void ResetBorder();
+
+ float corner_radius_;
+
DISALLOW_IMPLICIT_CONSTRUCTORS(FootnoteContainerView);
};
diff --git a/chromium/ui/views/bubble/info_bubble.cc b/chromium/ui/views/bubble/info_bubble.cc
index bce25293961..aeaa6c71352 100644
--- a/chromium/ui/views/bubble/info_bubble.cc
+++ b/chromium/ui/views/bubble/info_bubble.cc
@@ -125,4 +125,8 @@ void InfoBubble::UpdatePosition() {
}
}
+BEGIN_METADATA(InfoBubble)
+METADATA_PARENT_CLASS(BubbleDialogDelegateView)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/bubble/info_bubble.h b/chromium/ui/views/bubble/info_bubble.h
index c1f092d10d1..7d607e76fdf 100644
--- a/chromium/ui/views/bubble/info_bubble.h
+++ b/chromium/ui/views/bubble/info_bubble.h
@@ -17,6 +17,8 @@ class InfoBubbleFrame;
// Class to create and manage an information bubble for errors or tooltips.
class InfoBubble : public BubbleDialogDelegateView {
public:
+ METADATA_HEADER(InfoBubble);
+
InfoBubble(View* anchor, const base::string16& message);
~InfoBubble() override;
diff --git a/chromium/ui/views/bubble/tooltip_icon.cc b/chromium/ui/views/bubble/tooltip_icon.cc
index 0ff1e6bd3b3..289e92115b8 100644
--- a/chromium/ui/views/bubble/tooltip_icon.cc
+++ b/chromium/ui/views/bubble/tooltip_icon.cc
@@ -28,10 +28,6 @@ TooltipIcon::~TooltipIcon() {
HideBubble();
}
-const char* TooltipIcon::GetClassName() const {
- return "TooltipIcon";
-}
-
void TooltipIcon::OnMouseEntered(const ui::MouseEvent& event) {
mouse_inside_ = true;
show_timer_.Start(FROM_HERE, base::TimeDelta::FromMilliseconds(150), this,
@@ -113,4 +109,8 @@ void TooltipIcon::OnWidgetDestroyed(Widget* widget) {
bubble_ = nullptr;
}
+BEGIN_METADATA(TooltipIcon)
+METADATA_PARENT_CLASS(ImageView)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/bubble/tooltip_icon.h b/chromium/ui/views/bubble/tooltip_icon.h
index 97dbe043b45..cb10e596539 100644
--- a/chromium/ui/views/bubble/tooltip_icon.h
+++ b/chromium/ui/views/bubble/tooltip_icon.h
@@ -25,12 +25,13 @@ class VIEWS_EXPORT TooltipIcon : public ImageView,
public MouseWatcherListener,
public WidgetObserver {
public:
+ METADATA_HEADER(TooltipIcon);
+
explicit TooltipIcon(const base::string16& tooltip,
int tooltip_icon_size = 16);
~TooltipIcon() override;
// ImageView:
- const char* GetClassName() const override;
void OnMouseEntered(const ui::MouseEvent& event) override;
void OnMouseExited(const ui::MouseEvent& event) override;
bool OnMousePressed(const ui::MouseEvent& event) override;
diff --git a/chromium/ui/views/cocoa/bridge_factory_host.cc b/chromium/ui/views/cocoa/bridge_factory_host.cc
deleted file mode 100644
index 20c2e163c85..00000000000
--- a/chromium/ui/views/cocoa/bridge_factory_host.cc
+++ /dev/null
@@ -1,33 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/cocoa/bridge_factory_host.h"
-
-#include "mojo/public/cpp/bindings/interface_request.h"
-
-namespace views {
-
-BridgeFactoryHost::BridgeFactoryHost(
- remote_cocoa::mojom::BridgeFactoryAssociatedRequest* request) {
- *request = mojo::MakeRequest(&bridge_factory_ptr_);
-}
-
-BridgeFactoryHost::~BridgeFactoryHost() {
- for (Observer& obs : observers_)
- obs.OnBridgeFactoryHostDestroying(this);
-}
-
-remote_cocoa::mojom::BridgeFactory* BridgeFactoryHost::GetFactory() {
- return bridge_factory_ptr_.get();
-}
-
-void BridgeFactoryHost::AddObserver(Observer* observer) {
- observers_.AddObserver(observer);
-}
-
-void BridgeFactoryHost::RemoveObserver(const Observer* observer) {
- observers_.RemoveObserver(observer);
-}
-
-} // namespace views
diff --git a/chromium/ui/views/cocoa/bridge_factory_host.h b/chromium/ui/views/cocoa/bridge_factory_host.h
deleted file mode 100644
index 82a77a8cdd5..00000000000
--- a/chromium/ui/views/cocoa/bridge_factory_host.h
+++ /dev/null
@@ -1,41 +0,0 @@
-// Copyright 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_COCOA_BRIDGE_FACTORY_HOST_H_
-#define UI_VIEWS_COCOA_BRIDGE_FACTORY_HOST_H_
-
-#include "base/observer_list.h"
-#include "base/observer_list_types.h"
-#include "components/remote_cocoa/common/bridge_factory.mojom.h"
-#include "ui/views/views_export.h"
-
-namespace views {
-
-class VIEWS_EXPORT BridgeFactoryHost {
- public:
- class Observer : public base::CheckedObserver {
- public:
- virtual void OnBridgeFactoryHostDestroying(BridgeFactoryHost* host) = 0;
-
- protected:
- ~Observer() override {}
- };
-
- BridgeFactoryHost(
- remote_cocoa::mojom::BridgeFactoryAssociatedRequest* request);
- ~BridgeFactoryHost();
-
- remote_cocoa::mojom::BridgeFactory* GetFactory();
-
- void AddObserver(Observer* observer);
- void RemoveObserver(const Observer* observer);
-
- private:
- remote_cocoa::mojom::BridgeFactoryAssociatedPtr bridge_factory_ptr_;
- base::ObserverList<Observer> observers_;
-};
-
-} // namespace views
-
-#endif // UI_VIEWS_COCOA_BRIDGE_FACTORY_HOST_H_
diff --git a/chromium/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm b/chromium/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm
index 20ee22947de..736f61161be 100644
--- a/chromium/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm
+++ b/chromium/ui/views/cocoa/bridged_native_widget_interactive_uitest.mm
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h"
+#import "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h"
#import <Cocoa/Cocoa.h>
@@ -15,7 +15,7 @@
#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/cocoa/bridged_native_widget_host_impl.h"
+#include "ui/views/cocoa/native_widget_mac_ns_window_host.h"
#include "ui/views/test/widget_test.h"
#include "ui/views/widget/native_widget_mac.h"
#include "ui/views/window/native_frame_view.h"
@@ -251,13 +251,13 @@ void WaitForEvent(NSUInteger mask) {
} // namespace
// This is used to inject test versions of NativeFrameView and
-// BridgedNativeWidgetImpl.
+// NativeWidgetNSWindowBridge.
class HitTestNativeWidgetMac : public NativeWidgetMac {
public:
HitTestNativeWidgetMac(internal::NativeWidgetDelegate* delegate,
NativeFrameView* native_frame_view)
: NativeWidgetMac(delegate), native_frame_view_(native_frame_view) {
- bridge_host_ = std::make_unique<BridgedNativeWidgetHostImpl>(this);
+ ns_window_host_ = std::make_unique<NativeWidgetMacNSWindowHost>(this);
}
// internal::NativeWidgetPrivate:
diff --git a/chromium/ui/views/cocoa/bridged_native_widget_unittest.mm b/chromium/ui/views/cocoa/bridged_native_widget_unittest.mm
index 8a871ad6526..d925401a44b 100644
--- a/chromium/ui/views/cocoa/bridged_native_widget_unittest.mm
+++ b/chromium/ui/views/cocoa/bridged_native_widget_unittest.mm
@@ -2,7 +2,7 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h"
+#import "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h"
#import <Cocoa/Cocoa.h>
#include <objc/runtime.h>
@@ -29,7 +29,7 @@
#import "ui/base/test/cocoa_helper.h"
#include "ui/events/test/cocoa_test_event_utils.h"
#import "ui/gfx/mac/coordinate_conversion.h"
-#import "ui/views/cocoa/bridged_native_widget_host_impl.h"
+#import "ui/views/cocoa/native_widget_mac_ns_window_host.h"
#import "ui/views/cocoa/text_input_host.h"
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/controls/textfield/textfield_controller.h"
@@ -295,13 +295,13 @@ NSTextInputContext* g_fake_current_input_context = nullptr;
namespace views {
namespace test {
-// Provides the |parent| argument to construct a BridgedNativeWidgetImpl.
+// Provides the |parent| argument to construct a NativeWidgetNSWindowBridge.
class MockNativeWidgetMac : public NativeWidgetMac {
public:
explicit MockNativeWidgetMac(internal::NativeWidgetDelegate* delegate)
: NativeWidgetMac(delegate) {}
- using NativeWidgetMac::bridge_impl;
- using NativeWidgetMac::bridge_host;
+ using NativeWidgetMac::GetInProcessNSWindowBridge;
+ using NativeWidgetMac::GetNSWindowHost;
// internal::NativeWidgetPrivate:
void InitNativeWidget(const Widget::InitParams& params) override {
@@ -313,19 +313,19 @@ class MockNativeWidgetMac : public NativeWidgetMac {
styleMask:NSBorderlessWindowMask
backing:NSBackingStoreBuffered
defer:NO]);
- bridge_host()->CreateLocalBridge(window);
+ GetNSWindowHost()->CreateInProcessNSWindowBridge(window);
if (auto* parent =
- BridgedNativeWidgetHostImpl::GetFromNativeView(params.parent)) {
- bridge_host()->SetParent(parent);
+ NativeWidgetMacNSWindowHost::GetFromNativeView(params.parent)) {
+ GetNSWindowHost()->SetParent(parent);
}
- bridge_host()->InitWindow(params);
+ GetNSWindowHost()->InitWindow(params);
// Usually the bridge gets initialized here. It is skipped to run extra
// checks in tests, and so that a second window isn't created.
delegate()->OnNativeWidgetCreated();
// To allow events to dispatch to a view, it needs a way to get focus.
- bridge_host()->SetFocusManager(GetWidget()->GetFocusManager());
+ GetNSWindowHost()->SetFocusManager(GetWidget()->GetFocusManager());
}
void ReorderNativeViews() override {
@@ -336,7 +336,8 @@ class MockNativeWidgetMac : public NativeWidgetMac {
DISALLOW_COPY_AND_ASSIGN(MockNativeWidgetMac);
};
-// Helper test base to construct a BridgedNativeWidgetImpl with a valid parent.
+// Helper test base to construct a NativeWidgetNSWindowBridge with a valid
+// parent.
class BridgedNativeWidgetTestBase : public ui::CocoaTest {
public:
struct SkipInitialization {};
@@ -348,11 +349,11 @@ class BridgedNativeWidgetTestBase : public ui::CocoaTest {
explicit BridgedNativeWidgetTestBase(SkipInitialization tag)
: native_widget_mac_(nullptr) {}
- BridgedNativeWidgetImpl* bridge() {
- return native_widget_mac_->bridge_impl();
+ remote_cocoa::NativeWidgetNSWindowBridge* bridge() {
+ return native_widget_mac_->GetInProcessNSWindowBridge();
}
- BridgedNativeWidgetHostImpl* bridge_host() {
- return native_widget_mac_->bridge_host();
+ NativeWidgetMacNSWindowHost* GetNSWindowHost() {
+ return native_widget_mac_->GetNSWindowHost();
}
// Generate an autoreleased KeyDown NSEvent* in |widget_| for pressing the
@@ -404,8 +405,8 @@ class BridgedNativeWidgetTestBase : public ui::CocoaTest {
}
NSWindow* bridge_window() const {
- if (native_widget_mac_->bridge_impl())
- return native_widget_mac_->bridge_impl()->ns_window();
+ if (auto* bridge = native_widget_mac_->GetInProcessNSWindowBridge())
+ return bridge->ns_window();
return nil;
}
@@ -550,7 +551,7 @@ Textfield* BridgedNativeWidgetTest::InstallTextField(
// schedules a task to flash the cursor, so this requires |message_loop_|.
textfield->RequestFocus();
- bridge_host()->text_input_host()->SetTextInputClient(textfield);
+ GetNSWindowHost()->text_input_host()->SetTextInputClient(textfield);
// Initialize the dummy text view. Initializing this with NSZeroRect causes
// weird NSTextView behavior on OSX 10.9.
@@ -632,8 +633,8 @@ void BridgedNativeWidgetTest::SetUp() {
// The delegate should exist before setting the root view.
EXPECT_TRUE([window delegate]);
- bridge_host()->SetRootView(view_.get());
- bridge()->CreateContentView(bridge_host()->GetRootViewNSViewId(),
+ GetNSWindowHost()->SetRootView(view_.get());
+ bridge()->CreateContentView(GetNSWindowHost()->GetRootViewNSViewId(),
view_->bounds());
ns_view_ = bridge()->ns_view();
@@ -646,8 +647,8 @@ void BridgedNativeWidgetTest::TearDown() {
// Clear kill buffer so that no state persists between tests.
TextfieldModel::ClearKillBuffer();
- if (bridge_host()) {
- bridge_host()->SetRootView(nullptr);
+ if (GetNSWindowHost()) {
+ GetNSWindowHost()->SetRootView(nullptr);
bridge()->DestroyContentView();
}
view_.reset();
@@ -849,7 +850,7 @@ TEST_F(BridgedNativeWidgetTest, ViewSizeTracksWindow) {
}
TEST_F(BridgedNativeWidgetTest, GetInputMethodShouldNotReturnNull) {
- EXPECT_TRUE(bridge_host()->GetInputMethod());
+ EXPECT_TRUE(GetNSWindowHost()->GetInputMethod());
}
// A simpler test harness for testing initialization flows.
@@ -873,7 +874,7 @@ class BridgedNativeWidgetInitTest : public BridgedNativeWidgetTestBase {
DISALLOW_COPY_AND_ASSIGN(BridgedNativeWidgetInitTest);
};
-// Test that BridgedNativeWidgetImpl remains sane if Init() is never called.
+// Test that NativeWidgetNSWindowBridge remains sane if Init() is never called.
TEST_F(BridgedNativeWidgetInitTest, InitNotCalled) {
// Don't use a Widget* as the delegate. ~Widget() checks for Widget::
// |native_widget_destroyed_| being set to true. That can only happen with a
@@ -883,7 +884,7 @@ TEST_F(BridgedNativeWidgetInitTest, InitNotCalled) {
new MockNativeWidgetMac(nullptr));
native_widget_mac_ = native_widget.get();
EXPECT_FALSE(bridge());
- EXPECT_FALSE(bridge_host()->GetLocalNSWindow());
+ EXPECT_FALSE(GetNSWindowHost()->GetInProcessNSWindow());
}
// Tests the shadow type given in InitParams.
@@ -930,7 +931,7 @@ TEST_F(BridgedNativeWidgetTest, InputContext) {
EXPECT_FALSE([ns_view_ inputContext]);
InstallTextField(test_string, ui::TEXT_INPUT_TYPE_TEXT);
EXPECT_TRUE([ns_view_ inputContext]);
- bridge_host()->text_input_host()->SetTextInputClient(nullptr);
+ GetNSWindowHost()->text_input_host()->SetTextInputClient(nullptr);
EXPECT_FALSE([ns_view_ inputContext]);
InstallTextField(test_string, ui::TEXT_INPUT_TYPE_NONE);
EXPECT_FALSE([ns_view_ inputContext]);
@@ -1339,7 +1340,7 @@ TEST_F(BridgedNativeWidgetTest, TextInput_DeleteCommands) {
// Test that we don't crash during an action message even if the TextInputClient
// is nil. Regression test for crbug.com/615745.
TEST_F(BridgedNativeWidgetTest, NilTextInputClient) {
- bridge_host()->text_input_host()->SetTextInputClient(nullptr);
+ GetNSWindowHost()->text_input_host()->SetTextInputClient(nullptr);
NSMutableArray* selectors = [NSMutableArray array];
[selectors addObjectsFromArray:kMoveActions];
[selectors addObjectsFromArray:kSelectActions];
@@ -1751,7 +1752,7 @@ TEST_F(BridgedNativeWidgetTest, TextInput_RecursiveUpdateWindows) {
bool saw_update_windows = false;
base::RepeatingClosure update_windows_closure = base::BindRepeating(
[](bool* saw_update_windows, BridgedContentView* view,
- BridgedNativeWidgetHostImpl* host, Textfield* textfield) {
+ NativeWidgetMacNSWindowHost* host, Textfield* textfield) {
// Ensure updateWindows is not invoked recursively.
EXPECT_FALSE(*saw_update_windows);
*saw_update_windows = true;
@@ -1777,11 +1778,11 @@ TEST_F(BridgedNativeWidgetTest, TextInput_RecursiveUpdateWindows) {
// Now, the |textfield| set above should have been set again.
EXPECT_TRUE(g_fake_current_input_context);
},
- &saw_update_windows, ns_view_, bridge_host(), textfield);
+ &saw_update_windows, ns_view_, GetNSWindowHost(), textfield);
SetHandleKeyEventCallback(base::BindRepeating(
[](int* saw_return_count, BridgedContentView* view,
- BridgedNativeWidgetHostImpl* host, Textfield* textfield,
+ NativeWidgetMacNSWindowHost* host, Textfield* textfield,
const ui::KeyEvent& event) {
if (event.key_code() == ui::VKEY_RETURN) {
*saw_return_count += 1;
@@ -1791,7 +1792,7 @@ TEST_F(BridgedNativeWidgetTest, TextInput_RecursiveUpdateWindows) {
}
return false;
},
- &vkey_return_count, ns_view_, bridge_host()));
+ &vkey_return_count, ns_view_, GetNSWindowHost()));
// Starting text (just insert it).
[ns_view_ insertText:@"ă…‚" replacementRange:NSMakeRange(NSNotFound, 0)];
@@ -1880,8 +1881,8 @@ TEST_F(BridgedNativeWidgetSimulateFullscreenTest, FailToEnterAndExit) {
object:window];
// On a failure, Cocoa starts by sending an unexpected *exit* fullscreen, and
- // BridgedNativeWidgetImpl will think it's just a delayed transition and try
- // to go back into fullscreen but get ignored by Cocoa.
+ // NativeWidgetNSWindowBridge will think it's just a delayed transition and
+ // try to go back into fullscreen but get ignored by Cocoa.
EXPECT_EQ(0, [window ignoredToggleFullScreenCount]);
EXPECT_TRUE(bridge()->target_fullscreen_state());
[center postNotificationName:NSWindowDidExitFullScreenNotification
diff --git a/chromium/ui/views/cocoa/drag_drop_client_mac.h b/chromium/ui/views/cocoa/drag_drop_client_mac.h
index 450a2edb705..608e73a075c 100644
--- a/chromium/ui/views/cocoa/drag_drop_client_mac.h
+++ b/chromium/ui/views/cocoa/drag_drop_client_mac.h
@@ -19,14 +19,17 @@
namespace gfx {
class Point;
-}
+} // namespace gfx
+
+namespace remote_cocoa {
+class NativeWidgetNSWindowBridge;
+} // namespace remote_cocoa
namespace views {
namespace test {
class DragDropClientMacTest;
-}
+} // namespace test
-class BridgedNativeWidgetImpl;
class View;
// Implements drag and drop on MacViews. This class acts as a bridge between
@@ -34,13 +37,14 @@ class View;
// DesktopDragDropClientAuraX11.
class VIEWS_EXPORT DragDropClientMac : public remote_cocoa::DragDropClient {
public:
- DragDropClientMac(BridgedNativeWidgetImpl* bridge, View* root_view);
+ DragDropClientMac(remote_cocoa::NativeWidgetNSWindowBridge* bridge,
+ View* root_view);
~DragDropClientMac() override;
// Initiates a drag and drop session. Returns the drag operation that was
// applied at the end of the drag drop session.
void StartDragAndDrop(View* view,
- const ui::OSExchangeData& data,
+ std::unique_ptr<ui::OSExchangeData> data,
int operation,
ui::DragDropTypes::DragEventSource source);
@@ -69,7 +73,7 @@ class VIEWS_EXPORT DragDropClientMac : public remote_cocoa::DragDropClient {
int last_operation_ = 0;
// The bridge between the content view and the drag drop client.
- BridgedNativeWidgetImpl* bridge_; // Weak. Owns |this|.
+ remote_cocoa::NativeWidgetNSWindowBridge* bridge_; // Weak. Owns |this|.
// The closure for the drag and drop's run loop.
base::OnceClosure quit_closure_;
diff --git a/chromium/ui/views/cocoa/drag_drop_client_mac.mm b/chromium/ui/views/cocoa/drag_drop_client_mac.mm
index ac1c1b5bdf0..16ed882e3e9 100644
--- a/chromium/ui/views/cocoa/drag_drop_client_mac.mm
+++ b/chromium/ui/views/cocoa/drag_drop_client_mac.mm
@@ -8,7 +8,7 @@
#include "base/run_loop.h"
#include "base/strings/sys_string_conversions.h"
#import "components/remote_cocoa/app_shim/bridged_content_view.h"
-#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h"
+#import "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h"
#import "ui/base/dragdrop/os_exchange_data_provider_mac.h"
#include "ui/gfx/image/image_skia_util_mac.h"
#include "ui/views/drag_utils.h"
@@ -16,8 +16,9 @@
namespace views {
-DragDropClientMac::DragDropClientMac(BridgedNativeWidgetImpl* bridge,
- View* root_view)
+DragDropClientMac::DragDropClientMac(
+ remote_cocoa::NativeWidgetNSWindowBridge* bridge,
+ View* root_view)
: drop_helper_(root_view), bridge_(bridge) {
DCHECK(bridge);
}
@@ -26,12 +27,10 @@ DragDropClientMac::~DragDropClientMac() {}
void DragDropClientMac::StartDragAndDrop(
View* view,
- const ui::OSExchangeData& data,
+ std::unique_ptr<ui::OSExchangeData> data,
int operation,
ui::DragDropTypes::DragEventSource source) {
- // TODO(avi): Why must this data be cloned?
- exchange_data_ =
- std::make_unique<ui::OSExchangeData>(data.provider().Clone());
+ exchange_data_ = std::move(data);
source_operation_ = operation;
is_drag_source_ = true;
diff --git a/chromium/ui/views/cocoa/drag_drop_client_mac_unittest.mm b/chromium/ui/views/cocoa/drag_drop_client_mac_unittest.mm
index e19072b03c3..10ad4b6d0ca 100644
--- a/chromium/ui/views/cocoa/drag_drop_client_mac_unittest.mm
+++ b/chromium/ui/views/cocoa/drag_drop_client_mac_unittest.mm
@@ -12,10 +12,10 @@
#include "base/mac/sdk_forward_declarations.h"
#include "base/strings/utf_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
-#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h"
+#import "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h"
#import "ui/base/clipboard/clipboard_util_mac.h"
#include "ui/gfx/image/image_unittest_util.h"
-#import "ui/views/cocoa/bridged_native_widget_host_impl.h"
+#import "ui/views/cocoa/native_widget_mac_ns_window_host.h"
#include "ui/views/test/widget_test.h"
#include "ui/views/view.h"
#include "ui/views/widget/native_widget_mac.h"
@@ -158,7 +158,7 @@ class DragDropClientMacTest : public WidgetTest {
DragDropClientMacTest() : widget_(new Widget) {}
DragDropClientMac* drag_drop_client() {
- return bridge_host_->drag_drop_client();
+ return ns_window_host_->drag_drop_client();
}
NSDragOperation DragUpdate(NSPasteboard* pasteboard) {
@@ -189,9 +189,9 @@ class DragDropClientMacTest : public WidgetTest {
gfx::Rect bounds(0, 0, 100, 100);
widget_->SetBounds(bounds);
- bridge_host_ = BridgedNativeWidgetHostImpl::GetFromNativeWindow(
+ ns_window_host_ = NativeWidgetMacNSWindowHost::GetFromNativeWindow(
widget_->GetNativeWindow());
- bridge_ = bridge_host_->bridge_impl();
+ bridge_ = ns_window_host_->GetInProcessNSWindowBridge();
widget_->Show();
target_ = new DragDropView();
@@ -209,8 +209,8 @@ class DragDropClientMacTest : public WidgetTest {
protected:
Widget* widget_ = nullptr;
- BridgedNativeWidgetImpl* bridge_ = nullptr;
- BridgedNativeWidgetHostImpl* bridge_host_ = nullptr;
+ remote_cocoa::NativeWidgetNSWindowBridge* bridge_ = nullptr;
+ NativeWidgetMacNSWindowHost* ns_window_host_ = nullptr;
DragDropView* target_ = nullptr;
base::scoped_nsobject<MockDraggingInfo> dragging_info_;
@@ -242,15 +242,15 @@ TEST_F(DragDropClientMacTest, ReleaseCapture) {
// since the runloop will exit before the system has any opportunity to
// capture anything.
bridge_->AcquireCapture();
- EXPECT_TRUE(bridge_host_->IsMouseCaptureActive());
+ EXPECT_TRUE(ns_window_host_->IsMouseCaptureActive());
// Create the drop data
- OSExchangeData data;
+ std::unique_ptr<OSExchangeData> data(std::make_unique<OSExchangeData>());
const base::string16& text = ASCIIToUTF16("text");
- data.SetString(text);
- data.provider().SetDragImage(gfx::test::CreateImageSkia(100, 100),
- gfx::Vector2d());
- SetData(data);
+ data->SetString(text);
+ data->provider().SetDragImage(gfx::test::CreateImageSkia(100, 100),
+ gfx::Vector2d());
+ SetData(*data.get());
// There's no way to cleanly stop NSDraggingSession inside unit tests, so just
// don't start it at all.
@@ -265,10 +265,10 @@ TEST_F(DragDropClientMacTest, ReleaseCapture) {
// It will call ReleaseCapture().
drag_drop_client()->StartDragAndDrop(
- target_, data, 0, ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
+ target_, std::move(data), 0, ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
// The capture should be released.
- EXPECT_FALSE(bridge_host_->IsMouseCaptureActive());
+ EXPECT_FALSE(ns_window_host_->IsMouseCaptureActive());
}
// Tests if the drag and drop target rejects the dropped data with the
diff --git a/chromium/ui/views/cocoa/bridged_native_widget_host_impl.h b/chromium/ui/views/cocoa/native_widget_mac_ns_window_host.h
index 75f3dd1ec82..528ec883d22 100644
--- a/chromium/ui/views/cocoa/bridged_native_widget_host_impl.h
+++ b/chromium/ui/views/cocoa/native_widget_mac_ns_window_host.h
@@ -2,25 +2,25 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#ifndef UI_VIEWS_COCOA_BRIDGED_NATIVE_WIDGET_HOST_IMPL_H_
-#define UI_VIEWS_COCOA_BRIDGED_NATIVE_WIDGET_HOST_IMPL_H_
+#ifndef UI_VIEWS_COCOA_NATIVE_WIDGET_MAC_NS_WINDOW_HOST_H_
+#define UI_VIEWS_COCOA_NATIVE_WIDGET_MAC_NS_WINDOW_HOST_H_
#include <memory>
#include <vector>
#include "base/mac/scoped_nsobject.h"
#include "base/macros.h"
-#include "components/remote_cocoa/app_shim/bridged_native_widget_host_helper.h"
+#include "components/remote_cocoa/app_shim/native_widget_ns_window_host_helper.h"
#include "components/remote_cocoa/app_shim/ns_view_ids.h"
-#include "components/remote_cocoa/common/bridged_native_widget.mojom.h"
-#include "components/remote_cocoa/common/bridged_native_widget_host.mojom.h"
+#include "components/remote_cocoa/browser/application_host.h"
+#include "components/remote_cocoa/common/native_widget_ns_window.mojom.h"
+#include "components/remote_cocoa/common/native_widget_ns_window_host.mojom.h"
#include "mojo/public/cpp/bindings/associated_binding.h"
#include "ui/accelerated_widget_mac/accelerated_widget_mac.h"
-#include "ui/accelerated_widget_mac/display_link_mac.h"
#include "ui/base/cocoa/accessibility_focus_overrider.h"
#include "ui/base/ime/input_method_delegate.h"
#include "ui/compositor/layer_owner.h"
-#include "ui/views/cocoa/bridge_factory_host.h"
+#include "ui/display/mac/display_link_mac.h"
#include "ui/views/cocoa/drag_drop_client_mac.h"
#include "ui/views/focus/focus_manager.h"
#include "ui/views/views_export.h"
@@ -31,23 +31,27 @@
@class NSAccessibilityRemoteUIElement;
@class NSView;
+namespace remote_cocoa {
+class NativeWidgetNSWindowBridge;
+class ScopedNativeWindowMapping;
+} // namespace remote_cocoa
+
namespace ui {
class RecyclableCompositorMac;
} // namespace ui
namespace views {
-class BridgedNativeWidgetImpl;
class NativeWidgetMac;
class TextInputHost;
// The portion of NativeWidgetMac that lives in the browser process. This
-// communicates to the BridgedNativeWidgetImpl, which interacts with the Cocoa
-// APIs, and which may live in an app shim process.
-class VIEWS_EXPORT BridgedNativeWidgetHostImpl
- : public remote_cocoa::BridgedNativeWidgetHostHelper,
- public BridgeFactoryHost::Observer,
- public remote_cocoa::mojom::BridgedNativeWidgetHost,
+// communicates to the NativeWidgetNSWindowBridge, which interacts with the
+// Cocoa APIs, and which may live in an app shim process.
+class VIEWS_EXPORT NativeWidgetMacNSWindowHost
+ : public remote_cocoa::NativeWidgetNSWindowHostHelper,
+ public remote_cocoa::ApplicationHost::Observer,
+ public remote_cocoa::mojom::NativeWidgetNSWindowHost,
public DialogObserver,
public FocusChangeListener,
public ui::internal::InputMethodDelegate,
@@ -58,34 +62,34 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
public:
// Retrieves the bridge host associated with the given NativeWindow. Returns
// null if the supplied handle has no associated Widget.
- static BridgedNativeWidgetHostImpl* GetFromNativeWindow(
+ static NativeWidgetMacNSWindowHost* GetFromNativeWindow(
gfx::NativeWindow window);
- static BridgedNativeWidgetHostImpl* GetFromNativeView(gfx::NativeView view);
+ static NativeWidgetMacNSWindowHost* GetFromNativeView(gfx::NativeView view);
// Unique integer id handles are used to bridge between the
- // BridgedNativeWidgetHostImpl in one process and the BridgedNativeWidgetHost
+ // NativeWidgetMacNSWindowHost in one process and the NativeWidgetNSWindowHost
// potentially in another.
- static BridgedNativeWidgetHostImpl* GetFromId(
+ static NativeWidgetMacNSWindowHost* GetFromId(
uint64_t bridged_native_widget_id);
uint64_t bridged_native_widget_id() const { return widget_id_; }
// Creates one side of the bridge. |owner| must not be NULL.
- explicit BridgedNativeWidgetHostImpl(NativeWidgetMac* owner);
- ~BridgedNativeWidgetHostImpl() override;
+ explicit NativeWidgetMacNSWindowHost(NativeWidgetMac* owner);
+ ~NativeWidgetMacNSWindowHost() override;
// The NativeWidgetMac that owns |this|.
views::NativeWidgetMac* native_widget_mac() const {
return native_widget_mac_;
}
- BridgedNativeWidgetHostImpl* parent() const { return parent_; }
- std::vector<BridgedNativeWidgetHostImpl*> children() const {
+ NativeWidgetMacNSWindowHost* parent() const { return parent_; }
+ std::vector<NativeWidgetMacNSWindowHost*> children() const {
return children_;
}
// The bridge factory that was used to create the true NSWindow for this
// widget. This is nullptr for in-process windows.
- BridgeFactoryHost* bridge_factory_host() const {
- return bridge_factory_host_;
+ remote_cocoa::ApplicationHost* application_host() const {
+ return application_host_;
}
TextInputHost* text_input_host() const { return text_input_host_.get(); }
@@ -93,7 +97,7 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
// A NSWindow that is guaranteed to exist in this process. If the bridge
// object for this host is in this process, then this points to the bridge's
// NSWindow. Otherwise, it mirrors the id and bounds of the child window.
- NativeWidgetMacNSWindow* GetLocalNSWindow() const;
+ NativeWidgetMacNSWindow* GetInProcessNSWindow() const;
// Return the accessibility object for the content NSView.
gfx::NativeViewAccessible GetNativeViewAccessibleForNSView() const;
@@ -102,13 +106,16 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
gfx::NativeViewAccessible GetNativeViewAccessibleForNSWindow() const;
// The mojo interface through which to communicate with the underlying
- // NSWindow and NSView.
- remote_cocoa::mojom::BridgedNativeWidget* bridge() const;
+ // NSWindow and NSView. This points to either |remote_ns_window_ptr_| or
+ // |in_process_ns_window_bridge_|.
+ remote_cocoa::mojom::NativeWidgetNSWindow* GetNSWindowMojo() const;
- // Direct access to the BridgedNativeWidgetImpl that this is hosting.
+ // Direct access to the NativeWidgetNSWindowBridge that this is hosting.
// TODO(ccameron): Remove all accesses to this member, and replace them
// with methods that may be sent across processes.
- BridgedNativeWidgetImpl* bridge_impl() const { return bridge_impl_.get(); }
+ remote_cocoa::NativeWidgetNSWindowBridge* GetInProcessNSWindowBridge() const {
+ return in_process_ns_window_bridge_.get();
+ }
TooltipManager* tooltip_manager() { return tooltip_manager_.get(); }
@@ -117,11 +124,12 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
}
// Create and set the bridge object to be in this process.
- void CreateLocalBridge(base::scoped_nsobject<NativeWidgetMacNSWindow> window);
+ void CreateInProcessNSWindowBridge(
+ base::scoped_nsobject<NativeWidgetMacNSWindow> window);
// Create and set the bridge object to be potentially in another process.
- void CreateRemoteBridge(
- BridgeFactoryHost* bridge_factory_host,
+ void CreateRemoteNSWindow(
+ remote_cocoa::ApplicationHost* application_host,
remote_cocoa::mojom::CreateWindowParamsPtr window_create_params);
void InitWindow(const Widget::InitParams& params);
@@ -191,7 +199,7 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
// Set |parent_| and update the old and new parents' |children_|. It is valid
// to set |new_parent| to nullptr. Propagate this to the BridgedNativeWidget.
- void SetParent(BridgedNativeWidgetHostImpl* new_parent);
+ void SetParent(NativeWidgetMacNSWindowHost* new_parent);
// Properties set and queried by views. Not actually native.
void SetNativeWindowProperty(const char* name, void* value);
@@ -220,12 +228,12 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
void RankNSViewsRecursive(View* view, std::map<NSView*, int>* rank) const;
// If we are accessing the BridgedNativeWidget through mojo, then
- // |local_window_| is not the true window that is resized. This function
- // updates the frame of |local_window_| to keep it in sync for any native
- // calls that may use it (e.g, for context menu positioning).
+ // |in_process_ns_window_| is not the true window that is resized. This
+ // function updates the frame of |in_process_ns_window_| to keep it in sync
+ // for any native calls that may use it (e.g, for context menu positioning).
void UpdateLocalWindowFrame(const gfx::Rect& frame);
- // BridgedNativeWidgetHostHelper:
+ // NativeWidgetNSWindowHostHelper:
id GetNativeViewAccessible() override;
void DispatchKeyEvent(ui::KeyEvent* event) override;
bool DispatchKeyEventToMenuController(ui::KeyEvent* event) override;
@@ -236,10 +244,11 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
remote_cocoa::DragDropClient* GetDragDropClient() override;
ui::TextInputClient* GetTextInputClient() override;
- // BridgeFactoryHost::Observer:
- void OnBridgeFactoryHostDestroying(BridgeFactoryHost* host) override;
+ // remote_cocoa::ApplicationHost::Observer:
+ void OnApplicationHostDestroying(
+ remote_cocoa::ApplicationHost* host) override;
- // remote_cocoa::mojom::BridgedNativeWidgetHost:
+ // remote_cocoa::mojom::NativeWidgetNSWindowHost:
void OnVisibilityChanged(bool visible) override;
void OnWindowNativeThemeChanged() override;
void OnViewSizeChanged(const gfx::Size& new_size) override;
@@ -306,7 +315,7 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
bool require_priority_handler,
bool* was_handled) override;
- // remote_cocoa::mojom::BridgedNativeWidgetHost, synchronous callbacks:
+ // remote_cocoa::mojom::NativeWidgetNSWindowHost, synchronous callbacks:
void GetSheetOffsetY(GetSheetOffsetYCallback callback) override;
void DispatchKeyEventRemote(std::unique_ptr<ui::Event> event,
DispatchKeyEventRemoteCallback callback) override;
@@ -355,9 +364,7 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
void OnDidChangeFocus(View* focused_before, View* focused_now) override;
// ui::internal::InputMethodDelegate:
- ui::EventDispatchDetails DispatchKeyEventPostIME(
- ui::KeyEvent* key,
- DispatchKeyEventPostIMECallback callback) override;
+ ui::EventDispatchDetails DispatchKeyEventPostIME(ui::KeyEvent* key) override;
// ui::AccessibilityFocusOverrider::Client:
id GetAccessibilityFocusedUIElement() override;
@@ -375,13 +382,18 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
const uint64_t widget_id_;
views::NativeWidgetMac* const native_widget_mac_; // Weak. Owns |this_|.
+ // Structure used to look up this structure's interfaces from its
+ // gfx::NativeWindow.
+ std::unique_ptr<remote_cocoa::ScopedNativeWindowMapping>
+ native_window_mapping_;
+
// Parent and child widgets.
- BridgedNativeWidgetHostImpl* parent_ = nullptr;
- std::vector<BridgedNativeWidgetHostImpl*> children_;
+ NativeWidgetMacNSWindowHost* parent_ = nullptr;
+ std::vector<NativeWidgetMacNSWindowHost*> children_;
- // The factory that was used to create |bridge_ptr_|. This must be the same
- // as |parent_->bridge_factory_host_|.
- BridgeFactoryHost* bridge_factory_host_ = nullptr;
+ // The factory that was used to create |remote_ns_window_ptr_|. This must be
+ // the same as |parent_->application_host_|.
+ remote_cocoa::ApplicationHost* application_host_ = nullptr;
Widget::InitParams::Type widget_type_ = Widget::InitParams::TYPE_WINDOW;
@@ -395,7 +407,7 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
// The mojo pointer to a BridgedNativeWidget, which may exist in another
// process.
- remote_cocoa::mojom::BridgedNativeWidgetAssociatedPtr bridge_ptr_;
+ remote_cocoa::mojom::NativeWidgetNSWindowAssociatedPtr remote_ns_window_ptr_;
// Remote accessibility objects corresponding to the NSWindow and its root
// NSView.
@@ -407,16 +419,19 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
// views::Views accessibility tree when the NSView for this is focused.
ui::AccessibilityFocusOverrider accessibility_focus_overrider_;
- // TODO(ccameron): Rather than instantiate a BridgedNativeWidgetImpl here,
- // we will instantiate a mojo BridgedNativeWidgetImpl interface to a Cocoa
+ // TODO(ccameron): Rather than instantiate a NativeWidgetNSWindowBridge here,
+ // we will instantiate a mojo NativeWidgetNSWindowBridge interface to a Cocoa
// instance that may be in another process.
- std::unique_ptr<BridgedNativeWidgetImpl> bridge_impl_;
+ std::unique_ptr<remote_cocoa::NativeWidgetNSWindowBridge>
+ in_process_ns_window_bridge_;
- // Window that is guaranteed to exist in this process (see GetLocalNSWindow).
- base::scoped_nsobject<NativeWidgetMacNSWindow> local_window_;
+ // Window that is guaranteed to exist in this process (see
+ // GetInProcessNSWindow).
+ base::scoped_nsobject<NativeWidgetMacNSWindow> in_process_ns_window_;
- // Id mapping for |local_window_|'s content NSView.
- std::unique_ptr<remote_cocoa::ScopedNSViewIdMapping> local_view_id_mapping_;
+ // Id mapping for |in_process_ns_window_|'s content NSView.
+ std::unique_ptr<remote_cocoa::ScopedNSViewIdMapping>
+ in_process_view_id_mapping_;
std::unique_ptr<TooltipManager> tooltip_manager_;
std::unique_ptr<ui::InputMethod> input_method_;
@@ -456,11 +471,11 @@ class VIEWS_EXPORT BridgedNativeWidgetHostImpl
// Contains NativeViewHost->gfx::NativeView associations.
std::map<const views::View*, NSView*> associated_views_;
- mojo::AssociatedBinding<remote_cocoa::mojom::BridgedNativeWidgetHost>
- host_mojo_binding_;
- DISALLOW_COPY_AND_ASSIGN(BridgedNativeWidgetHostImpl);
+ mojo::AssociatedBinding<remote_cocoa::mojom::NativeWidgetNSWindowHost>
+ remote_ns_window_host_binding_;
+ DISALLOW_COPY_AND_ASSIGN(NativeWidgetMacNSWindowHost);
};
} // namespace views
-#endif // UI_VIEWS_COCOA_BRIDGED_NATIVE_WIDGET_HOST_IMPL_H_
+#endif // UI_VIEWS_COCOA_NATIVE_WIDGET_MAC_NS_WINDOW_HOST_H_
diff --git a/chromium/ui/views/cocoa/bridged_native_widget_host_impl.mm b/chromium/ui/views/cocoa/native_widget_mac_ns_window_host.mm
index be87bb2cede..95f1c6ce19a 100644
--- a/chromium/ui/views/cocoa/bridged_native_widget_host_impl.mm
+++ b/chromium/ui/views/cocoa/native_widget_mac_ns_window_host.mm
@@ -2,16 +2,17 @@
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
-#include "ui/views/cocoa/bridged_native_widget_host_impl.h"
+#include "ui/views/cocoa/native_widget_mac_ns_window_host.h"
#include <utility>
#include "base/mac/foundation_util.h"
#include "base/strings/sys_string_conversions.h"
-#include "components/remote_cocoa/app_shim/bridged_native_widget_impl.h"
#include "components/remote_cocoa/app_shim/mouse_capture.h"
#include "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h"
+#include "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h"
#include "components/remote_cocoa/browser/ns_view_ids.h"
+#include "components/remote_cocoa/browser/window.h"
#include "mojo/public/cpp/bindings/strong_associated_binding.h"
#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
#include "ui/base/cocoa/animation_utils.h"
@@ -22,6 +23,7 @@
#include "ui/base/ime/input_method.h"
#include "ui/compositor/recyclable_compositor_mac.h"
#include "ui/display/screen.h"
+#include "ui/events/cocoa/cocoa_event_utils.h"
#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/mac/coordinate_conversion.h"
#include "ui/native_theme/native_theme_mac.h"
@@ -38,7 +40,7 @@
#include "ui/views/window/dialog_delegate.h"
#include "ui/views/word_lookup_client.h"
-using remote_cocoa::mojom::BridgedNativeWidgetInitParams;
+using remote_cocoa::mojom::NativeWidgetNSWindowInitParams;
using remote_cocoa::mojom::WindowVisibilityState;
namespace views {
@@ -52,7 +54,7 @@ namespace {
// underlying connection closes.
// https://crbug.com/915572
class BridgedNativeWidgetHostDummy
- : public remote_cocoa::mojom::BridgedNativeWidgetHost {
+ : public remote_cocoa::mojom::NativeWidgetNSWindowHost {
public:
BridgedNativeWidgetHostDummy() = default;
~BridgedNativeWidgetHostDummy() override = default;
@@ -201,8 +203,8 @@ bool PositionWindowInScreenCoordinates(Widget* widget,
return widget && widget->is_top_level();
}
-std::map<uint64_t, BridgedNativeWidgetHostImpl*>& GetIdToWidgetHostImplMap() {
- static base::NoDestructor<std::map<uint64_t, BridgedNativeWidgetHostImpl*>>
+std::map<uint64_t, NativeWidgetMacNSWindowHost*>& GetIdToWidgetHostImplMap() {
+ static base::NoDestructor<std::map<uint64_t, NativeWidgetMacNSWindowHost*>>
id_map;
return *id_map;
}
@@ -220,7 +222,7 @@ uint64_t g_last_bridged_native_widget_id = 0;
// IOSurface as its contents, and hosts this CALayer in a CAContext that is
// the gfx::CALayerParams is then pointed to.
// https://crbug.com/942213
-class BridgedNativeWidgetHostImpl::IOSurfaceToRemoteLayerInterceptor {
+class NativeWidgetMacNSWindowHost::IOSurfaceToRemoteLayerInterceptor {
public:
IOSurfaceToRemoteLayerInterceptor() = default;
~IOSurfaceToRemoteLayerInterceptor() = default;
@@ -266,7 +268,7 @@ class BridgedNativeWidgetHostImpl::IOSurfaceToRemoteLayerInterceptor {
};
// static
-BridgedNativeWidgetHostImpl* BridgedNativeWidgetHostImpl::GetFromNativeWindow(
+NativeWidgetMacNSWindowHost* NativeWidgetMacNSWindowHost::GetFromNativeWindow(
gfx::NativeWindow native_window) {
NSWindow* window = native_window.GetNativeNSWindow();
if (NativeWidgetMacNSWindow* widget_window =
@@ -277,13 +279,13 @@ BridgedNativeWidgetHostImpl* BridgedNativeWidgetHostImpl::GetFromNativeWindow(
}
// static
-BridgedNativeWidgetHostImpl* BridgedNativeWidgetHostImpl::GetFromNativeView(
+NativeWidgetMacNSWindowHost* NativeWidgetMacNSWindowHost::GetFromNativeView(
gfx::NativeView native_view) {
return GetFromNativeWindow([native_view.GetNativeNSView() window]);
}
// static
-BridgedNativeWidgetHostImpl* BridgedNativeWidgetHostImpl::GetFromId(
+NativeWidgetMacNSWindowHost* NativeWidgetMacNSWindowHost::GetFromId(
uint64_t bridged_native_widget_id) {
auto found = GetIdToWidgetHostImplMap().find(bridged_native_widget_id);
if (found == GetIdToWidgetHostImplMap().end())
@@ -291,30 +293,31 @@ BridgedNativeWidgetHostImpl* BridgedNativeWidgetHostImpl::GetFromId(
return found->second;
}
-BridgedNativeWidgetHostImpl::BridgedNativeWidgetHostImpl(NativeWidgetMac* owner)
+NativeWidgetMacNSWindowHost::NativeWidgetMacNSWindowHost(NativeWidgetMac* owner)
: widget_id_(++g_last_bridged_native_widget_id),
native_widget_mac_(owner),
root_view_id_(remote_cocoa::GetNewNSViewId()),
accessibility_focus_overrider_(this),
text_input_host_(new TextInputHost(this)),
- host_mojo_binding_(this) {
+ remote_ns_window_host_binding_(this) {
DCHECK(GetIdToWidgetHostImplMap().find(widget_id_) ==
GetIdToWidgetHostImplMap().end());
GetIdToWidgetHostImplMap().insert(std::make_pair(widget_id_, this));
DCHECK(owner);
}
-BridgedNativeWidgetHostImpl::~BridgedNativeWidgetHostImpl() {
+NativeWidgetMacNSWindowHost::~NativeWidgetMacNSWindowHost() {
DCHECK(children_.empty());
- if (bridge_factory_host_) {
- bridge_ptr_.reset();
- bridge_factory_host_->RemoveObserver(this);
- bridge_factory_host_ = nullptr;
+ native_window_mapping_.reset();
+ if (application_host_) {
+ remote_ns_window_ptr_.reset();
+ application_host_->RemoveObserver(this);
+ application_host_ = nullptr;
}
// Workaround for https://crbug.com/915572
- if (host_mojo_binding_.is_bound()) {
- auto request = host_mojo_binding_.Unbind();
+ if (remote_ns_window_host_binding_.is_bound()) {
+ auto request = remote_ns_window_host_binding_.Unbind();
if (request.is_pending()) {
mojo::MakeStrongAssociatedBinding(
std::make_unique<BridgedNativeWidgetHostDummy>(), std::move(request));
@@ -331,98 +334,108 @@ BridgedNativeWidgetHostImpl::~BridgedNativeWidgetHostImpl() {
// destruction.
// TODO(ccameron): When all communication from |bridge_| to this goes through
// the BridgedNativeWidgetHost, this can be replaced with closing that pipe.
- bridge_impl_.reset();
+ in_process_ns_window_bridge_.reset();
SetFocusManager(nullptr);
DestroyCompositor();
}
-NativeWidgetMacNSWindow* BridgedNativeWidgetHostImpl::GetLocalNSWindow() const {
- return local_window_.get();
+NativeWidgetMacNSWindow* NativeWidgetMacNSWindowHost::GetInProcessNSWindow()
+ const {
+ return in_process_ns_window_.get();
}
gfx::NativeViewAccessible
-BridgedNativeWidgetHostImpl::GetNativeViewAccessibleForNSView() const {
- if (bridge_impl_)
- return bridge_impl_->ns_view();
+NativeWidgetMacNSWindowHost::GetNativeViewAccessibleForNSView() const {
+ if (in_process_ns_window_bridge_)
+ return in_process_ns_window_bridge_->ns_view();
return remote_view_accessible_.get();
}
gfx::NativeViewAccessible
-BridgedNativeWidgetHostImpl::GetNativeViewAccessibleForNSWindow() const {
- if (bridge_impl_)
- return bridge_impl_->ns_window();
+NativeWidgetMacNSWindowHost::GetNativeViewAccessibleForNSWindow() const {
+ if (in_process_ns_window_bridge_)
+ return in_process_ns_window_bridge_->ns_window();
return remote_window_accessible_.get();
}
-remote_cocoa::mojom::BridgedNativeWidget* BridgedNativeWidgetHostImpl::bridge()
- const {
- if (bridge_ptr_)
- return bridge_ptr_.get();
- if (bridge_impl_)
- return bridge_impl_.get();
+remote_cocoa::mojom::NativeWidgetNSWindow*
+NativeWidgetMacNSWindowHost::GetNSWindowMojo() const {
+ if (remote_ns_window_ptr_)
+ return remote_ns_window_ptr_.get();
+ if (in_process_ns_window_bridge_)
+ return in_process_ns_window_bridge_.get();
return nullptr;
}
-void BridgedNativeWidgetHostImpl::CreateLocalBridge(
+void NativeWidgetMacNSWindowHost::CreateInProcessNSWindowBridge(
base::scoped_nsobject<NativeWidgetMacNSWindow> window) {
- local_window_ = window;
- bridge_impl_ = std::make_unique<BridgedNativeWidgetImpl>(
- widget_id_, this, this, text_input_host_.get());
- bridge_impl_->SetWindow(window);
+ in_process_ns_window_ = window;
+ in_process_ns_window_bridge_ =
+ std::make_unique<remote_cocoa::NativeWidgetNSWindowBridge>(
+ widget_id_, this, this, text_input_host_.get());
+ in_process_ns_window_bridge_->SetWindow(window);
}
-void BridgedNativeWidgetHostImpl::CreateRemoteBridge(
- BridgeFactoryHost* bridge_factory_host,
+void NativeWidgetMacNSWindowHost::CreateRemoteNSWindow(
+ remote_cocoa::ApplicationHost* application_host,
remote_cocoa::mojom::CreateWindowParamsPtr window_create_params) {
accessibility_focus_overrider_.SetAppIsRemote(true);
- bridge_factory_host_ = bridge_factory_host;
- bridge_factory_host_->AddObserver(this);
+ application_host_ = application_host;
+ application_host_->AddObserver(this);
// Create a local invisible window that will be used as the gfx::NativeWindow
// handle to track this window in this process.
{
- auto local_window_create_params =
+ auto in_process_ns_window_create_params =
remote_cocoa::mojom::CreateWindowParams::New();
- local_window_create_params->style_mask = NSBorderlessWindowMask;
- local_window_ = BridgedNativeWidgetImpl::CreateNSWindow(
- local_window_create_params.get());
- [local_window_ setBridgedNativeWidgetId:widget_id_];
- [local_window_ setAlphaValue:0.0];
- local_view_id_mapping_ =
+ in_process_ns_window_create_params->style_mask = NSBorderlessWindowMask;
+ in_process_ns_window_ =
+ remote_cocoa::NativeWidgetNSWindowBridge::CreateNSWindow(
+ in_process_ns_window_create_params.get());
+ [in_process_ns_window_ setBridgedNativeWidgetId:widget_id_];
+ [in_process_ns_window_ setAlphaValue:0.0];
+ in_process_view_id_mapping_ =
std::make_unique<remote_cocoa::ScopedNSViewIdMapping>(
- root_view_id_, [local_window_ contentView]);
+ root_view_id_, [in_process_ns_window_ contentView]);
}
- // Initialize |bridge_ptr_| to point to a bridge created by |factory|.
- remote_cocoa::mojom::BridgedNativeWidgetHostAssociatedPtr host_ptr;
- host_mojo_binding_.Bind(mojo::MakeRequest(&host_ptr),
- ui::WindowResizeHelperMac::Get()->task_runner());
+ // Initialize |remote_ns_window_ptr_| to point to a bridge created by
+ // |factory|.
+ remote_cocoa::mojom::NativeWidgetNSWindowHostAssociatedPtr host_ptr;
+ remote_ns_window_host_binding_.Bind(
+ mojo::MakeRequest(&host_ptr),
+ ui::WindowResizeHelperMac::Get()->task_runner());
remote_cocoa::mojom::TextInputHostAssociatedPtr text_input_host_ptr;
text_input_host_->BindRequest(mojo::MakeRequest(&text_input_host_ptr));
- bridge_factory_host_->GetFactory()->CreateBridgedNativeWidget(
- widget_id_, mojo::MakeRequest(&bridge_ptr_), host_ptr.PassInterface(),
- text_input_host_ptr.PassInterface());
+ application_host_->GetApplication()->CreateNativeWidgetNSWindow(
+ widget_id_, mojo::MakeRequest(&remote_ns_window_ptr_),
+ host_ptr.PassInterface(), text_input_host_ptr.PassInterface());
// Create the window in its process, and attach it to its parent window.
- bridge()->CreateWindow(std::move(window_create_params));
+ GetNSWindowMojo()->CreateWindow(std::move(window_create_params));
}
-void BridgedNativeWidgetHostImpl::InitWindow(const Widget::InitParams& params) {
+void NativeWidgetMacNSWindowHost::InitWindow(const Widget::InitParams& params) {
+ native_window_mapping_ =
+ std::make_unique<remote_cocoa::ScopedNativeWindowMapping>(
+ gfx::NativeWindow(in_process_ns_window_.get()), application_host_,
+ in_process_ns_window_bridge_.get(), GetNSWindowMojo());
+
Widget* widget = native_widget_mac_->GetWidget();
// Tooltip Widgets shouldn't have their own tooltip manager, but tooltips are
// native on Mac, so nothing should ever want one in Widget form.
DCHECK_NE(params.type, Widget::InitParams::TYPE_TOOLTIP);
widget_type_ = params.type;
- tooltip_manager_.reset(new TooltipManagerMac(bridge()));
+ tooltip_manager_.reset(new TooltipManagerMac(GetNSWindowMojo()));
// Initialize the window.
{
- auto bridge_params = BridgedNativeWidgetInitParams::New();
- bridge_params->modal_type = widget->widget_delegate()->GetModalType();
- bridge_params->is_translucent =
+ auto window_params = NativeWidgetNSWindowInitParams::New();
+ window_params->modal_type = widget->widget_delegate()->GetModalType();
+ window_params->is_translucent =
params.opacity == Widget::InitParams::TRANSLUCENT_WINDOW;
- bridge_params->widget_is_top_level = widget->is_top_level();
- bridge_params->position_window_in_screen_coords =
+ window_params->widget_is_top_level = widget->is_top_level();
+ window_params->position_window_in_screen_coords =
PositionWindowInScreenCoordinates(widget, widget_type_);
// OSX likes to put shadows on most things. However, frameless windows (with
@@ -431,25 +444,25 @@ void BridgedNativeWidgetHostImpl::InitWindow(const Widget::InitParams& params) {
// Mac.
switch (params.shadow_type) {
case Widget::InitParams::SHADOW_TYPE_NONE:
- bridge_params->has_window_server_shadow = false;
+ window_params->has_window_server_shadow = false;
break;
case Widget::InitParams::SHADOW_TYPE_DEFAULT:
// Controls should get views shadows instead of native shadows.
- bridge_params->has_window_server_shadow =
+ window_params->has_window_server_shadow =
params.type != Widget::InitParams::TYPE_CONTROL;
break;
case Widget::InitParams::SHADOW_TYPE_DROP:
- bridge_params->has_window_server_shadow = true;
+ window_params->has_window_server_shadow = true;
break;
} // No default case, to pick up new types.
// Include "regular" windows without the standard frame in the window cycle.
// These use NSBorderlessWindowMask so do not get it by default.
- bridge_params->force_into_collection_cycle =
+ window_params->force_into_collection_cycle =
widget_type_ == Widget::InitParams::TYPE_WINDOW &&
params.remove_standard_frame;
- bridge()->InitWindow(std::move(bridge_params));
+ GetNSWindowMojo()->InitWindow(std::move(window_params));
}
// Set a meaningful initial bounds. Note that except for frameless widgets
@@ -459,22 +472,22 @@ void BridgedNativeWidgetHostImpl::InitWindow(const Widget::InitParams& params) {
// before calling Widget::Show() to avoid a kWindowSizeDeterminedLater-sized
// (i.e. 1x1) window appearing.
UpdateLocalWindowFrame(params.bounds);
- bridge()->SetInitialBounds(params.bounds, widget->GetMinimumSize());
+ GetNSWindowMojo()->SetInitialBounds(params.bounds, widget->GetMinimumSize());
- // TODO(ccameron): Correctly set these based |local_window_|.
+ // TODO(ccameron): Correctly set these based |in_process_ns_window_|.
window_bounds_in_screen_ = params.bounds;
content_bounds_in_screen_ = params.bounds;
// Widgets for UI controls (usually layered above web contents) start visible.
if (widget_type_ == Widget::InitParams::TYPE_CONTROL)
- bridge()->SetVisibilityState(WindowVisibilityState::kShowInactive);
+ GetNSWindowMojo()->SetVisibilityState(WindowVisibilityState::kShowInactive);
}
-void BridgedNativeWidgetHostImpl::CloseWindowNow() {
- bool is_out_of_process = !bridge_impl_;
+void NativeWidgetMacNSWindowHost::CloseWindowNow() {
+ bool is_out_of_process = !in_process_ns_window_bridge_;
// Note that CloseWindowNow may delete |this| for in-process windows.
- if (bridge())
- bridge()->CloseWindowNow();
+ if (GetNSWindowMojo())
+ GetNSWindowMojo()->CloseWindowNow();
// If it is out-of-process, then simulate the calls that would have been
// during window closure.
@@ -486,36 +499,46 @@ void BridgedNativeWidgetHostImpl::CloseWindowNow() {
}
}
-void BridgedNativeWidgetHostImpl::SetBounds(const gfx::Rect& bounds) {
+void NativeWidgetMacNSWindowHost::SetBounds(const gfx::Rect& bounds) {
UpdateLocalWindowFrame(bounds);
- bridge()->SetBounds(bounds,
- native_widget_mac_->GetWidget()->GetMinimumSize());
+ GetNSWindowMojo()->SetBounds(
+ bounds, native_widget_mac_->GetWidget()->GetMinimumSize());
+
+ if (remote_ns_window_ptr_) {
+ gfx::Rect window_in_screen =
+ gfx::ScreenRectFromNSRect([in_process_ns_window_ frame]);
+ gfx::Rect content_in_screen =
+ gfx::ScreenRectFromNSRect([in_process_ns_window_
+ contentRectForFrameRect:[in_process_ns_window_ frame]]);
+
+ OnWindowGeometryChanged(window_in_screen, content_in_screen);
+ }
}
-void BridgedNativeWidgetHostImpl::SetFullscreen(bool fullscreen) {
+void NativeWidgetMacNSWindowHost::SetFullscreen(bool fullscreen) {
// Note that when the NSWindow begins a fullscreen transition, the value of
// |target_fullscreen_state_| updates via OnWindowFullscreenTransitionStart.
// The update here is necessary for the case where we are currently in
// transition (and therefore OnWindowFullscreenTransitionStart will not be
// called until the current transition completes).
target_fullscreen_state_ = fullscreen;
- bridge()->SetFullscreen(target_fullscreen_state_);
+ GetNSWindowMojo()->SetFullscreen(target_fullscreen_state_);
}
-void BridgedNativeWidgetHostImpl::SetRootView(views::View* root_view) {
+void NativeWidgetMacNSWindowHost::SetRootView(views::View* root_view) {
root_view_ = root_view;
if (root_view_) {
// TODO(ccameron): Drag-drop functionality does not yet run over mojo.
- if (bridge_impl_) {
- drag_drop_client_.reset(
- new DragDropClientMac(bridge_impl_.get(), root_view_));
+ if (in_process_ns_window_bridge_) {
+ drag_drop_client_.reset(new DragDropClientMac(
+ in_process_ns_window_bridge_.get(), root_view_));
}
} else {
drag_drop_client_.reset();
}
}
-void BridgedNativeWidgetHostImpl::CreateCompositor(
+void NativeWidgetMacNSWindowHost::CreateCompositor(
const Widget::InitParams& params) {
DCHECK(!compositor_);
DCHECK(!layer());
@@ -550,10 +573,10 @@ void BridgedNativeWidgetHostImpl::CreateCompositor(
if (is_visible_)
compositor_->Unsuspend();
- bridge()->InitCompositorView();
+ GetNSWindowMojo()->InitCompositorView();
}
-void BridgedNativeWidgetHostImpl::UpdateCompositorProperties() {
+void NativeWidgetMacNSWindowHost::UpdateCompositorProperties() {
if (!compositor_)
return;
gfx::Size surface_size_in_dip = content_bounds_in_screen_.size();
@@ -563,11 +586,11 @@ void BridgedNativeWidgetHostImpl::UpdateCompositorProperties() {
display_.device_scale_factor());
}
-void BridgedNativeWidgetHostImpl::DestroyCompositor() {
+void NativeWidgetMacNSWindowHost::DestroyCompositor() {
if (layer()) {
// LayerOwner supports a change in ownership, e.g., to animate a closing
// window, but that won't work as expected for the root layer in
- // BridgedNativeWidgetImpl.
+ // NativeWidgetNSWindowBridge.
DCHECK_EQ(this, layer()->owner());
layer()->CompleteAllAnimations();
layer()->SuppressPaint();
@@ -582,7 +605,7 @@ void BridgedNativeWidgetHostImpl::DestroyCompositor() {
std::move(compositor_));
}
-void BridgedNativeWidgetHostImpl::SetFocusManager(FocusManager* focus_manager) {
+void NativeWidgetMacNSWindowHost::SetFocusManager(FocusManager* focus_manager) {
if (focus_manager_ == focus_manager)
return;
@@ -602,37 +625,33 @@ void BridgedNativeWidgetHostImpl::SetFocusManager(FocusManager* focus_manager) {
OnDidChangeFocus(nullptr, new_focus);
}
-bool BridgedNativeWidgetHostImpl::SetWindowTitle(const base::string16& title) {
+bool NativeWidgetMacNSWindowHost::SetWindowTitle(const base::string16& title) {
if (window_title_ == title)
return false;
window_title_ = title;
- bridge()->SetWindowTitle(window_title_);
+ GetNSWindowMojo()->SetWindowTitle(window_title_);
return true;
}
-void BridgedNativeWidgetHostImpl::OnWidgetInitDone() {
+void NativeWidgetMacNSWindowHost::OnWidgetInitDone() {
Widget* widget = native_widget_mac_->GetWidget();
if (DialogDelegate* dialog = widget->widget_delegate()->AsDialogDelegate())
dialog->AddObserver(this);
}
-bool BridgedNativeWidgetHostImpl::RedispatchKeyEvent(NSEvent* event) {
+bool NativeWidgetMacNSWindowHost::RedispatchKeyEvent(NSEvent* event) {
// If the target window is in-process, then redispatch the event directly,
// and give an accurate return value.
- if (bridge_impl_)
- return bridge_impl_->RedispatchKeyEvent(event);
+ if (in_process_ns_window_bridge_)
+ return in_process_ns_window_bridge_->RedispatchKeyEvent(event);
// If the target window is out of process then always report the event as
// handled (because it should never be handled in this process).
- bridge()->RedispatchKeyEvent(
- [event type], [event modifierFlags], [event timestamp],
- base::SysNSStringToUTF16([event characters]),
- base::SysNSStringToUTF16([event charactersIgnoringModifiers]),
- [event keyCode]);
+ GetNSWindowMojo()->RedispatchKeyEvent(ui::EventToData(event));
return true;
}
-ui::InputMethod* BridgedNativeWidgetHostImpl::GetInputMethod() {
+ui::InputMethod* NativeWidgetMacNSWindowHost::GetInputMethod() {
if (!input_method_) {
input_method_ = ui::CreateInputMethod(this, gfx::kNullAcceleratedWidget);
// For now, use always-focused mode on Mac for the input method.
@@ -642,13 +661,13 @@ ui::InputMethod* BridgedNativeWidgetHostImpl::GetInputMethod() {
return input_method_.get();
}
-gfx::Rect BridgedNativeWidgetHostImpl::GetRestoredBounds() const {
+gfx::Rect NativeWidgetMacNSWindowHost::GetRestoredBounds() const {
if (target_fullscreen_state_ || in_fullscreen_transition_)
return window_bounds_before_fullscreen_;
return window_bounds_in_screen_;
}
-void BridgedNativeWidgetHostImpl::SetNativeWindowProperty(const char* name,
+void NativeWidgetMacNSWindowHost::SetNativeWindowProperty(const char* name,
void* value) {
if (value)
native_window_properties_[name] = value;
@@ -656,7 +675,7 @@ void BridgedNativeWidgetHostImpl::SetNativeWindowProperty(const char* name,
native_window_properties_.erase(name);
}
-void* BridgedNativeWidgetHostImpl::GetNativeWindowProperty(
+void* NativeWidgetMacNSWindowHost::GetNativeWindowProperty(
const char* name) const {
auto found = native_window_properties_.find(name);
if (found == native_window_properties_.end())
@@ -664,8 +683,8 @@ void* BridgedNativeWidgetHostImpl::GetNativeWindowProperty(
return found->second;
}
-void BridgedNativeWidgetHostImpl::SetParent(
- BridgedNativeWidgetHostImpl* new_parent) {
+void NativeWidgetMacNSWindowHost::SetParent(
+ NativeWidgetMacNSWindowHost* new_parent) {
if (new_parent == parent_)
return;
@@ -681,48 +700,48 @@ void BridgedNativeWidgetHostImpl::SetParent(
// same process that we were already hosted by. If this is not the case, just
// close the Widget.
// https://crbug.com/957927
- BridgeFactoryHost* new_bridge_factory_host =
- new_parent ? new_parent->bridge_factory_host() : bridge_factory_host_;
- if (new_bridge_factory_host != bridge_factory_host_) {
+ remote_cocoa::ApplicationHost* new_application_host =
+ new_parent ? new_parent->application_host() : application_host_;
+ if (new_application_host != application_host_) {
DLOG(ERROR) << "Cannot migrate views::NativeWidget to another process, "
"closing it instead.";
- bridge()->CloseWindow();
+ GetNSWindowMojo()->CloseWindow();
return;
}
parent_ = new_parent;
if (parent_) {
parent_->children_.push_back(this);
- bridge()->SetParent(parent_->bridged_native_widget_id());
+ GetNSWindowMojo()->SetParent(parent_->bridged_native_widget_id());
} else {
- bridge()->SetParent(0);
+ GetNSWindowMojo()->SetParent(0);
}
}
-void BridgedNativeWidgetHostImpl::SetAssociationForView(const View* view,
+void NativeWidgetMacNSWindowHost::SetAssociationForView(const View* view,
NSView* native_view) {
DCHECK_EQ(0u, associated_views_.count(view));
associated_views_[view] = native_view;
native_widget_mac_->GetWidget()->ReorderNativeViews();
}
-void BridgedNativeWidgetHostImpl::ClearAssociationForView(const View* view) {
+void NativeWidgetMacNSWindowHost::ClearAssociationForView(const View* view) {
auto it = associated_views_.find(view);
DCHECK(it != associated_views_.end());
associated_views_.erase(it);
}
-void BridgedNativeWidgetHostImpl::ReorderChildViews() {
+void NativeWidgetMacNSWindowHost::ReorderChildViews() {
Widget* widget = native_widget_mac_->GetWidget();
if (!widget->GetRootView())
return;
std::map<NSView*, int> rank;
RankNSViewsRecursive(widget->GetRootView(), &rank);
- if (bridge_impl_)
- bridge_impl_->SortSubviews(std::move(rank));
+ if (in_process_ns_window_bridge_)
+ in_process_ns_window_bridge_->SortSubviews(std::move(rank));
}
-void BridgedNativeWidgetHostImpl::RankNSViewsRecursive(
+void NativeWidgetMacNSWindowHost::RankNSViewsRecursive(
View* view,
std::map<NSView*, int>* rank) const {
auto it = associated_views_.find(view);
@@ -732,32 +751,35 @@ void BridgedNativeWidgetHostImpl::RankNSViewsRecursive(
RankNSViewsRecursive(child, rank);
}
-void BridgedNativeWidgetHostImpl::UpdateLocalWindowFrame(
+void NativeWidgetMacNSWindowHost::UpdateLocalWindowFrame(
const gfx::Rect& frame) {
- if (!bridge_ptr_)
+ if (!remote_ns_window_ptr_)
return;
- [local_window_ setFrame:gfx::ScreenRectToNSRect(frame) display:NO animate:NO];
+ [in_process_ns_window_ setFrame:gfx::ScreenRectToNSRect(frame)
+ display:NO
+ animate:NO];
}
// static
-NSView* BridgedNativeWidgetHostImpl::GetGlobalCaptureView() {
+NSView* NativeWidgetMacNSWindowHost::GetGlobalCaptureView() {
// TODO(ccameron): This will not work across process boundaries.
- return [CocoaMouseCapture::GetGlobalCaptureWindow() contentView];
+ return
+ [remote_cocoa::CocoaMouseCapture::GetGlobalCaptureWindow() contentView];
}
////////////////////////////////////////////////////////////////////////////////
-// BridgedNativeWidgetHostImpl, remote_cocoa::BridgedNativeWidgetHostHelper:
+// NativeWidgetMacNSWindowHost, remote_cocoa::BridgedNativeWidgetHostHelper:
-id BridgedNativeWidgetHostImpl::GetNativeViewAccessible() {
+id NativeWidgetMacNSWindowHost::GetNativeViewAccessible() {
return root_view_ ? root_view_->GetNativeViewAccessible() : nil;
}
-void BridgedNativeWidgetHostImpl::DispatchKeyEvent(ui::KeyEvent* event) {
+void NativeWidgetMacNSWindowHost::DispatchKeyEvent(ui::KeyEvent* event) {
ignore_result(
root_view_->GetWidget()->GetInputMethod()->DispatchKeyEvent(event));
}
-bool BridgedNativeWidgetHostImpl::DispatchKeyEventToMenuController(
+bool NativeWidgetMacNSWindowHost::DispatchKeyEventToMenuController(
ui::KeyEvent* event) {
MenuController* menu_controller = MenuController::GetActiveInstance();
if (menu_controller && root_view_ &&
@@ -768,21 +790,21 @@ bool BridgedNativeWidgetHostImpl::DispatchKeyEventToMenuController(
return false;
}
-remote_cocoa::DragDropClient* BridgedNativeWidgetHostImpl::GetDragDropClient() {
+remote_cocoa::DragDropClient* NativeWidgetMacNSWindowHost::GetDragDropClient() {
return drag_drop_client_.get();
}
-ui::TextInputClient* BridgedNativeWidgetHostImpl::GetTextInputClient() {
+ui::TextInputClient* NativeWidgetMacNSWindowHost::GetTextInputClient() {
return text_input_host_->GetTextInputClient();
}
////////////////////////////////////////////////////////////////////////////////
-// BridgedNativeWidgetHostImpl, BridgeFactoryHost::Observer:
-void BridgedNativeWidgetHostImpl::OnBridgeFactoryHostDestroying(
- BridgeFactoryHost* host) {
- DCHECK_EQ(host, bridge_factory_host_);
- bridge_factory_host_->RemoveObserver(this);
- bridge_factory_host_ = nullptr;
+// NativeWidgetMacNSWindowHost, remote_cocoa::ApplicationHost::Observer:
+void NativeWidgetMacNSWindowHost::OnApplicationHostDestroying(
+ remote_cocoa::ApplicationHost* host) {
+ DCHECK_EQ(host, application_host_);
+ application_host_->RemoveObserver(this);
+ application_host_ = nullptr;
// Because the process hosting this window has ended, close the window by
// sending the window close messages that the bridge would have sent.
@@ -792,15 +814,15 @@ void BridgedNativeWidgetHostImpl::OnBridgeFactoryHostDestroying(
// tear-down assumptions). This would have been done by the bridge, had it
// shut down cleanly.
while (!children_.empty())
- children_.front()->OnBridgeFactoryHostDestroying(host);
+ children_.front()->OnApplicationHostDestroying(host);
OnWindowHasClosed();
}
////////////////////////////////////////////////////////////////////////////////
-// BridgedNativeWidgetHostImpl,
-// remote_cocoa::mojom::BridgedNativeWidgetHost:
+// NativeWidgetMacNSWindowHost,
+// remote_cocoa::mojom::NativeWidgetNSWindowHost:
-void BridgedNativeWidgetHostImpl::OnVisibilityChanged(bool window_visible) {
+void NativeWidgetMacNSWindowHost::OnVisibilityChanged(bool window_visible) {
is_visible_ = window_visible;
if (compositor_) {
layer()->SetVisible(window_visible);
@@ -815,26 +837,26 @@ void BridgedNativeWidgetHostImpl::OnVisibilityChanged(bool window_visible) {
window_visible);
}
-void BridgedNativeWidgetHostImpl::OnWindowNativeThemeChanged() {
+void NativeWidgetMacNSWindowHost::OnWindowNativeThemeChanged() {
ui::NativeTheme::GetInstanceForNativeUi()->NotifyObservers();
}
-void BridgedNativeWidgetHostImpl::OnScrollEvent(
+void NativeWidgetMacNSWindowHost::OnScrollEvent(
std::unique_ptr<ui::Event> event) {
root_view_->GetWidget()->OnScrollEvent(event->AsScrollEvent());
}
-void BridgedNativeWidgetHostImpl::OnMouseEvent(
+void NativeWidgetMacNSWindowHost::OnMouseEvent(
std::unique_ptr<ui::Event> event) {
root_view_->GetWidget()->OnMouseEvent(event->AsMouseEvent());
}
-void BridgedNativeWidgetHostImpl::OnGestureEvent(
+void NativeWidgetMacNSWindowHost::OnGestureEvent(
std::unique_ptr<ui::Event> event) {
root_view_->GetWidget()->OnGestureEvent(event->AsGestureEvent());
}
-bool BridgedNativeWidgetHostImpl::DispatchKeyEventRemote(
+bool NativeWidgetMacNSWindowHost::DispatchKeyEventRemote(
std::unique_ptr<ui::Event> event,
bool* event_handled) {
DispatchKeyEvent(event->AsKeyEvent());
@@ -842,7 +864,7 @@ bool BridgedNativeWidgetHostImpl::DispatchKeyEventRemote(
return true;
}
-bool BridgedNativeWidgetHostImpl::DispatchKeyEventToMenuControllerRemote(
+bool NativeWidgetMacNSWindowHost::DispatchKeyEventToMenuControllerRemote(
std::unique_ptr<ui::Event> event,
bool* event_swallowed,
bool* event_handled) {
@@ -851,7 +873,7 @@ bool BridgedNativeWidgetHostImpl::DispatchKeyEventToMenuControllerRemote(
return true;
}
-bool BridgedNativeWidgetHostImpl::GetHasMenuController(
+bool NativeWidgetMacNSWindowHost::GetHasMenuController(
bool* has_menu_controller) {
MenuController* menu_controller = MenuController::GetActiveInstance();
*has_menu_controller = menu_controller && root_view_ &&
@@ -861,23 +883,23 @@ bool BridgedNativeWidgetHostImpl::GetHasMenuController(
return true;
}
-void BridgedNativeWidgetHostImpl::OnViewSizeChanged(const gfx::Size& new_size) {
+void NativeWidgetMacNSWindowHost::OnViewSizeChanged(const gfx::Size& new_size) {
root_view_->SetSize(new_size);
}
-bool BridgedNativeWidgetHostImpl::GetSheetOffsetY(int32_t* offset_y) {
+bool NativeWidgetMacNSWindowHost::GetSheetOffsetY(int32_t* offset_y) {
*offset_y = native_widget_mac_->SheetOffsetY();
return true;
}
-void BridgedNativeWidgetHostImpl::SetKeyboardAccessible(bool enabled) {
+void NativeWidgetMacNSWindowHost::SetKeyboardAccessible(bool enabled) {
views::FocusManager* focus_manager =
root_view_->GetWidget()->GetFocusManager();
if (focus_manager)
focus_manager->SetKeyboardAccessible(enabled);
}
-void BridgedNativeWidgetHostImpl::OnIsFirstResponderChanged(
+void NativeWidgetMacNSWindowHost::OnIsFirstResponderChanged(
bool is_first_responder) {
accessibility_focus_overrider_.SetViewIsFirstResponder(is_first_responder);
if (is_first_responder) {
@@ -891,14 +913,14 @@ void BridgedNativeWidgetHostImpl::OnIsFirstResponderChanged(
}
}
-void BridgedNativeWidgetHostImpl::OnMouseCaptureActiveChanged(bool is_active) {
+void NativeWidgetMacNSWindowHost::OnMouseCaptureActiveChanged(bool is_active) {
DCHECK_NE(is_mouse_capture_active_, is_active);
is_mouse_capture_active_ = is_active;
if (!is_mouse_capture_active_)
native_widget_mac_->GetWidget()->OnMouseCaptureLost();
}
-bool BridgedNativeWidgetHostImpl::GetIsDraggableBackgroundAt(
+bool NativeWidgetMacNSWindowHost::GetIsDraggableBackgroundAt(
const gfx::Point& location_in_content,
bool* is_draggable_background) {
int component =
@@ -907,7 +929,7 @@ bool BridgedNativeWidgetHostImpl::GetIsDraggableBackgroundAt(
return true;
}
-bool BridgedNativeWidgetHostImpl::GetTooltipTextAt(
+bool NativeWidgetMacNSWindowHost::GetTooltipTextAt(
const gfx::Point& location_in_content,
base::string16* new_tooltip_text) {
views::View* view =
@@ -921,7 +943,7 @@ bool BridgedNativeWidgetHostImpl::GetTooltipTextAt(
return true;
}
-void BridgedNativeWidgetHostImpl::GetWordAt(
+void NativeWidgetMacNSWindowHost::GetWordAt(
const gfx::Point& location_in_content,
bool* found_word,
gfx::DecoratedText* decorated_word,
@@ -949,12 +971,12 @@ void BridgedNativeWidgetHostImpl::GetWordAt(
*found_word = true;
}
-bool BridgedNativeWidgetHostImpl::GetWidgetIsModal(bool* widget_is_modal) {
+bool NativeWidgetMacNSWindowHost::GetWidgetIsModal(bool* widget_is_modal) {
*widget_is_modal = native_widget_mac_->GetWidget()->IsModal();
return true;
}
-bool BridgedNativeWidgetHostImpl::GetIsFocusedViewTextual(bool* is_textual) {
+bool NativeWidgetMacNSWindowHost::GetIsFocusedViewTextual(bool* is_textual) {
views::FocusManager* focus_manager =
root_view_ ? root_view_->GetWidget()->GetFocusManager() : nullptr;
*is_textual = focus_manager && focus_manager->GetFocusedView() &&
@@ -963,7 +985,7 @@ bool BridgedNativeWidgetHostImpl::GetIsFocusedViewTextual(bool* is_textual) {
return true;
}
-void BridgedNativeWidgetHostImpl::OnWindowGeometryChanged(
+void NativeWidgetMacNSWindowHost::OnWindowGeometryChanged(
const gfx::Rect& new_window_bounds_in_screen,
const gfx::Rect& new_content_bounds_in_screen) {
UpdateLocalWindowFrame(new_window_bounds_in_screen);
@@ -983,15 +1005,16 @@ void BridgedNativeWidgetHostImpl::OnWindowGeometryChanged(
// Note we can't use new_window_bounds_in_screen.size(), since it includes the
// titlebar for the purposes of detecting a window move.
- if (content_has_resized)
+ if (content_has_resized) {
native_widget_mac_->GetWidget()->OnNativeWidgetSizeChanged(
content_bounds_in_screen_.size());
- // Update the compositor surface and layer size.
- UpdateCompositorProperties();
+ // Update the compositor surface and layer size.
+ UpdateCompositorProperties();
+ }
}
-void BridgedNativeWidgetHostImpl::OnWindowFullscreenTransitionStart(
+void NativeWidgetMacNSWindowHost::OnWindowFullscreenTransitionStart(
bool target_fullscreen_state) {
target_fullscreen_state_ = target_fullscreen_state;
in_fullscreen_transition_ = true;
@@ -1004,7 +1027,7 @@ void BridgedNativeWidgetHostImpl::OnWindowFullscreenTransitionStart(
native_widget_mac_->OnWindowFullscreenStateChange();
}
-void BridgedNativeWidgetHostImpl::OnWindowFullscreenTransitionComplete(
+void NativeWidgetMacNSWindowHost::OnWindowFullscreenTransitionComplete(
bool actual_fullscreen_state) {
in_fullscreen_transition_ = false;
@@ -1012,14 +1035,14 @@ void BridgedNativeWidgetHostImpl::OnWindowFullscreenTransitionComplete(
native_widget_mac_->OnSizeConstraintsChanged();
}
-void BridgedNativeWidgetHostImpl::OnWindowMiniaturizedChanged(
+void NativeWidgetMacNSWindowHost::OnWindowMiniaturizedChanged(
bool miniaturized) {
is_miniaturized_ = miniaturized;
if (native_widget_mac_)
native_widget_mac_->GetWidget()->OnNativeWidgetWindowShowStateChanged();
}
-void BridgedNativeWidgetHostImpl::OnWindowDisplayChanged(
+void NativeWidgetMacNSWindowHost::OnWindowDisplayChanged(
const display::Display& new_display) {
bool scale_factor_changed =
display_.device_scale_factor() != new_display.device_scale_factor();
@@ -1041,7 +1064,7 @@ void BridgedNativeWidgetHostImpl::OnWindowDisplayChanged(
}
}
-void BridgedNativeWidgetHostImpl::OnWindowWillClose() {
+void NativeWidgetMacNSWindowHost::OnWindowWillClose() {
Widget* widget = native_widget_mac_->GetWidget();
if (DialogDelegate* dialog = widget->widget_delegate()->AsDialogDelegate())
dialog->RemoveObserver(this);
@@ -1050,14 +1073,14 @@ void BridgedNativeWidgetHostImpl::OnWindowWillClose() {
SetParent(nullptr);
}
-void BridgedNativeWidgetHostImpl::OnWindowHasClosed() {
+void NativeWidgetMacNSWindowHost::OnWindowHasClosed() {
// OnWindowHasClosed will be called only after all child windows have had
// OnWindowWillClose called on them.
DCHECK(children_.empty());
native_widget_mac_->WindowDestroyed();
}
-void BridgedNativeWidgetHostImpl::OnWindowKeyStatusChanged(
+void NativeWidgetMacNSWindowHost::OnWindowKeyStatusChanged(
bool is_key,
bool is_content_first_responder,
bool full_keyboard_access_enabled) {
@@ -1082,7 +1105,7 @@ void BridgedNativeWidgetHostImpl::OnWindowKeyStatusChanged(
}
}
-void BridgedNativeWidgetHostImpl::DoDialogButtonAction(
+void NativeWidgetMacNSWindowHost::DoDialogButtonAction(
ui::DialogButton button) {
views::DialogDelegate* dialog =
root_view_->GetWidget()->widget_delegate()->AsDialogDelegate();
@@ -1096,7 +1119,7 @@ void BridgedNativeWidgetHostImpl::DoDialogButtonAction(
}
}
-bool BridgedNativeWidgetHostImpl::GetDialogButtonInfo(
+bool NativeWidgetMacNSWindowHost::GetDialogButtonInfo(
ui::DialogButton button,
bool* button_exists,
base::string16* button_label,
@@ -1114,14 +1137,14 @@ bool BridgedNativeWidgetHostImpl::GetDialogButtonInfo(
return true;
}
-bool BridgedNativeWidgetHostImpl::GetDoDialogButtonsExist(bool* buttons_exist) {
+bool NativeWidgetMacNSWindowHost::GetDoDialogButtonsExist(bool* buttons_exist) {
views::DialogDelegate* dialog =
root_view_->GetWidget()->widget_delegate()->AsDialogDelegate();
*buttons_exist = dialog && dialog->GetDialogButtons();
return true;
}
-bool BridgedNativeWidgetHostImpl::GetShouldShowWindowTitle(
+bool NativeWidgetMacNSWindowHost::GetShouldShowWindowTitle(
bool* should_show_window_title) {
*should_show_window_title =
root_view_
@@ -1130,21 +1153,21 @@ bool BridgedNativeWidgetHostImpl::GetShouldShowWindowTitle(
return true;
}
-bool BridgedNativeWidgetHostImpl::GetCanWindowBecomeKey(
+bool NativeWidgetMacNSWindowHost::GetCanWindowBecomeKey(
bool* can_window_become_key) {
*can_window_become_key =
root_view_ ? root_view_->GetWidget()->CanActivate() : false;
return true;
}
-bool BridgedNativeWidgetHostImpl::GetAlwaysRenderWindowAsKey(
+bool NativeWidgetMacNSWindowHost::GetAlwaysRenderWindowAsKey(
bool* always_render_as_key) {
*always_render_as_key =
root_view_ ? root_view_->GetWidget()->ShouldPaintAsActive() : false;
return true;
}
-bool BridgedNativeWidgetHostImpl::GetCanWindowClose(bool* can_window_close) {
+bool NativeWidgetMacNSWindowHost::GetCanWindowClose(bool* can_window_close) {
*can_window_close = true;
views::NonClientView* non_client_view =
root_view_ ? root_view_->GetWidget()->non_client_view() : nullptr;
@@ -1153,7 +1176,7 @@ bool BridgedNativeWidgetHostImpl::GetCanWindowClose(bool* can_window_close) {
return true;
}
-bool BridgedNativeWidgetHostImpl::GetWindowFrameTitlebarHeight(
+bool NativeWidgetMacNSWindowHost::GetWindowFrameTitlebarHeight(
bool* override_titlebar_height,
float* titlebar_height) {
native_widget_mac_->GetWindowFrameTitlebarHeight(override_titlebar_height,
@@ -1161,11 +1184,11 @@ bool BridgedNativeWidgetHostImpl::GetWindowFrameTitlebarHeight(
return true;
}
-void BridgedNativeWidgetHostImpl::OnFocusWindowToolbar() {
+void NativeWidgetMacNSWindowHost::OnFocusWindowToolbar() {
native_widget_mac_->OnFocusWindowToolbar();
}
-void BridgedNativeWidgetHostImpl::SetRemoteAccessibilityTokens(
+void NativeWidgetMacNSWindowHost::SetRemoteAccessibilityTokens(
const std::vector<uint8_t>& window_token,
const std::vector<uint8_t>& view_token) {
remote_window_accessible_ =
@@ -1177,7 +1200,7 @@ void BridgedNativeWidgetHostImpl::SetRemoteAccessibilityTokens(
setTopLevelUIElement:remote_window_accessible_.get()];
}
-bool BridgedNativeWidgetHostImpl::GetRootViewAccessibilityToken(
+bool NativeWidgetMacNSWindowHost::GetRootViewAccessibilityToken(
int64_t* pid,
std::vector<uint8_t>* token) {
*pid = getpid();
@@ -1186,7 +1209,7 @@ bool BridgedNativeWidgetHostImpl::GetRootViewAccessibilityToken(
return true;
}
-bool BridgedNativeWidgetHostImpl::ValidateUserInterfaceItem(
+bool NativeWidgetMacNSWindowHost::ValidateUserInterfaceItem(
int32_t command,
remote_cocoa::mojom::ValidateUserInterfaceItemResultPtr* out_result) {
*out_result = remote_cocoa::mojom::ValidateUserInterfaceItemResult::New();
@@ -1194,7 +1217,7 @@ bool BridgedNativeWidgetHostImpl::ValidateUserInterfaceItem(
return true;
}
-bool BridgedNativeWidgetHostImpl::ExecuteCommand(
+bool NativeWidgetMacNSWindowHost::ExecuteCommand(
int32_t command,
WindowOpenDisposition window_open_disposition,
bool is_before_first_responder,
@@ -1204,7 +1227,7 @@ bool BridgedNativeWidgetHostImpl::ExecuteCommand(
return true;
}
-bool BridgedNativeWidgetHostImpl::HandleAccelerator(
+bool NativeWidgetMacNSWindowHost::HandleAccelerator(
const ui::Accelerator& accelerator,
bool require_priority_handler,
bool* was_handled) {
@@ -1220,17 +1243,17 @@ bool BridgedNativeWidgetHostImpl::HandleAccelerator(
}
////////////////////////////////////////////////////////////////////////////////
-// BridgedNativeWidgetHostImpl,
-// remote_cocoa::mojom::BridgedNativeWidgetHost synchronous callbacks:
+// NativeWidgetMacNSWindowHost,
+// remote_cocoa::mojom::NativeWidgetNSWindowHost synchronous callbacks:
-void BridgedNativeWidgetHostImpl::GetSheetOffsetY(
+void NativeWidgetMacNSWindowHost::GetSheetOffsetY(
GetSheetOffsetYCallback callback) {
int32_t offset_y = 0;
GetSheetOffsetY(&offset_y);
std::move(callback).Run(offset_y);
}
-void BridgedNativeWidgetHostImpl::DispatchKeyEventRemote(
+void NativeWidgetMacNSWindowHost::DispatchKeyEventRemote(
std::unique_ptr<ui::Event> event,
DispatchKeyEventRemoteCallback callback) {
bool event_handled = false;
@@ -1238,7 +1261,7 @@ void BridgedNativeWidgetHostImpl::DispatchKeyEventRemote(
std::move(callback).Run(event_handled);
}
-void BridgedNativeWidgetHostImpl::DispatchKeyEventToMenuControllerRemote(
+void NativeWidgetMacNSWindowHost::DispatchKeyEventToMenuControllerRemote(
std::unique_ptr<ui::Event> event,
DispatchKeyEventToMenuControllerRemoteCallback callback) {
ui::KeyEvent* key_event = event->AsKeyEvent();
@@ -1246,14 +1269,14 @@ void BridgedNativeWidgetHostImpl::DispatchKeyEventToMenuControllerRemote(
std::move(callback).Run(event_swallowed, key_event->handled());
}
-void BridgedNativeWidgetHostImpl::GetHasMenuController(
+void NativeWidgetMacNSWindowHost::GetHasMenuController(
GetHasMenuControllerCallback callback) {
bool has_menu_controller = false;
GetHasMenuController(&has_menu_controller);
std::move(callback).Run(has_menu_controller);
}
-void BridgedNativeWidgetHostImpl::GetIsDraggableBackgroundAt(
+void NativeWidgetMacNSWindowHost::GetIsDraggableBackgroundAt(
const gfx::Point& location_in_content,
GetIsDraggableBackgroundAtCallback callback) {
bool is_draggable_background = false;
@@ -1261,7 +1284,7 @@ void BridgedNativeWidgetHostImpl::GetIsDraggableBackgroundAt(
std::move(callback).Run(is_draggable_background);
}
-void BridgedNativeWidgetHostImpl::GetTooltipTextAt(
+void NativeWidgetMacNSWindowHost::GetTooltipTextAt(
const gfx::Point& location_in_content,
GetTooltipTextAtCallback callback) {
base::string16 new_tooltip_text;
@@ -1269,21 +1292,21 @@ void BridgedNativeWidgetHostImpl::GetTooltipTextAt(
std::move(callback).Run(new_tooltip_text);
}
-void BridgedNativeWidgetHostImpl::GetIsFocusedViewTextual(
+void NativeWidgetMacNSWindowHost::GetIsFocusedViewTextual(
GetIsFocusedViewTextualCallback callback) {
bool is_textual = false;
GetIsFocusedViewTextual(&is_textual);
std::move(callback).Run(is_textual);
}
-void BridgedNativeWidgetHostImpl::GetWidgetIsModal(
+void NativeWidgetMacNSWindowHost::GetWidgetIsModal(
GetWidgetIsModalCallback callback) {
bool widget_is_modal = false;
GetWidgetIsModal(&widget_is_modal);
std::move(callback).Run(widget_is_modal);
}
-void BridgedNativeWidgetHostImpl::GetDialogButtonInfo(
+void NativeWidgetMacNSWindowHost::GetDialogButtonInfo(
ui::DialogButton button,
GetDialogButtonInfoCallback callback) {
bool exists = false;
@@ -1294,42 +1317,42 @@ void BridgedNativeWidgetHostImpl::GetDialogButtonInfo(
std::move(callback).Run(exists, label, is_enabled, is_default);
}
-void BridgedNativeWidgetHostImpl::GetDoDialogButtonsExist(
+void NativeWidgetMacNSWindowHost::GetDoDialogButtonsExist(
GetDoDialogButtonsExistCallback callback) {
bool buttons_exist = false;
GetDoDialogButtonsExist(&buttons_exist);
std::move(callback).Run(buttons_exist);
}
-void BridgedNativeWidgetHostImpl::GetShouldShowWindowTitle(
+void NativeWidgetMacNSWindowHost::GetShouldShowWindowTitle(
GetShouldShowWindowTitleCallback callback) {
bool should_show_window_title = false;
GetShouldShowWindowTitle(&should_show_window_title);
std::move(callback).Run(should_show_window_title);
}
-void BridgedNativeWidgetHostImpl::GetCanWindowBecomeKey(
+void NativeWidgetMacNSWindowHost::GetCanWindowBecomeKey(
GetCanWindowBecomeKeyCallback callback) {
bool can_window_become_key = false;
GetCanWindowBecomeKey(&can_window_become_key);
std::move(callback).Run(can_window_become_key);
}
-void BridgedNativeWidgetHostImpl::GetAlwaysRenderWindowAsKey(
+void NativeWidgetMacNSWindowHost::GetAlwaysRenderWindowAsKey(
GetAlwaysRenderWindowAsKeyCallback callback) {
bool always_render_as_key = false;
GetAlwaysRenderWindowAsKey(&always_render_as_key);
std::move(callback).Run(always_render_as_key);
}
-void BridgedNativeWidgetHostImpl::GetCanWindowClose(
+void NativeWidgetMacNSWindowHost::GetCanWindowClose(
GetCanWindowCloseCallback callback) {
bool can_window_close = false;
GetCanWindowClose(&can_window_close);
std::move(callback).Run(can_window_close);
}
-void BridgedNativeWidgetHostImpl::GetWindowFrameTitlebarHeight(
+void NativeWidgetMacNSWindowHost::GetWindowFrameTitlebarHeight(
GetWindowFrameTitlebarHeightCallback callback) {
bool override_titlebar_height = false;
float titlebar_height = 0;
@@ -1337,7 +1360,7 @@ void BridgedNativeWidgetHostImpl::GetWindowFrameTitlebarHeight(
std::move(callback).Run(override_titlebar_height, titlebar_height);
}
-void BridgedNativeWidgetHostImpl::GetRootViewAccessibilityToken(
+void NativeWidgetMacNSWindowHost::GetRootViewAccessibilityToken(
GetRootViewAccessibilityTokenCallback callback) {
std::vector<uint8_t> token;
int64_t pid;
@@ -1345,7 +1368,7 @@ void BridgedNativeWidgetHostImpl::GetRootViewAccessibilityToken(
std::move(callback).Run(pid, token);
}
-void BridgedNativeWidgetHostImpl::ValidateUserInterfaceItem(
+void NativeWidgetMacNSWindowHost::ValidateUserInterfaceItem(
int32_t command,
ValidateUserInterfaceItemCallback callback) {
remote_cocoa::mojom::ValidateUserInterfaceItemResultPtr result;
@@ -1353,7 +1376,7 @@ void BridgedNativeWidgetHostImpl::ValidateUserInterfaceItem(
std::move(callback).Run(std::move(result));
}
-void BridgedNativeWidgetHostImpl::ExecuteCommand(
+void NativeWidgetMacNSWindowHost::ExecuteCommand(
int32_t command,
WindowOpenDisposition window_open_disposition,
bool is_before_first_responder,
@@ -1364,7 +1387,7 @@ void BridgedNativeWidgetHostImpl::ExecuteCommand(
std::move(callback).Run(was_executed);
}
-void BridgedNativeWidgetHostImpl::HandleAccelerator(
+void NativeWidgetMacNSWindowHost::HandleAccelerator(
const ui::Accelerator& accelerator,
bool require_priority_handler,
HandleAcceleratorCallback callback) {
@@ -1374,21 +1397,21 @@ void BridgedNativeWidgetHostImpl::HandleAccelerator(
}
////////////////////////////////////////////////////////////////////////////////
-// BridgedNativeWidgetHostImpl, DialogObserver:
+// NativeWidgetMacNSWindowHost, DialogObserver:
-void BridgedNativeWidgetHostImpl::OnDialogChanged() {
+void NativeWidgetMacNSWindowHost::OnDialogChanged() {
// Note it's only necessary to clear the TouchBar. If the OS needs it again,
// a new one will be created.
- bridge()->ClearTouchBar();
+ GetNSWindowMojo()->ClearTouchBar();
}
////////////////////////////////////////////////////////////////////////////////
-// BridgedNativeWidgetHostImpl, FocusChangeListener:
+// NativeWidgetMacNSWindowHost, FocusChangeListener:
-void BridgedNativeWidgetHostImpl::OnWillChangeFocus(View* focused_before,
+void NativeWidgetMacNSWindowHost::OnWillChangeFocus(View* focused_before,
View* focused_now) {}
-void BridgedNativeWidgetHostImpl::OnDidChangeFocus(View* focused_before,
+void NativeWidgetMacNSWindowHost::OnDidChangeFocus(View* focused_before,
View* focused_now) {
ui::InputMethod* input_method =
native_widget_mac_->GetWidget()->GetInputMethod();
@@ -1404,50 +1427,48 @@ void BridgedNativeWidgetHostImpl::OnDidChangeFocus(View* focused_before,
}
////////////////////////////////////////////////////////////////////////////////
-// BridgedNativeWidgetImpl, internal::InputMethodDelegate:
+// NativeWidgetMacNSWindowHost, internal::InputMethodDelegate:
-ui::EventDispatchDetails BridgedNativeWidgetHostImpl::DispatchKeyEventPostIME(
- ui::KeyEvent* key,
- DispatchKeyEventPostIMECallback callback) {
+ui::EventDispatchDetails NativeWidgetMacNSWindowHost::DispatchKeyEventPostIME(
+ ui::KeyEvent* key) {
DCHECK(focus_manager_);
if (!focus_manager_->OnKeyEvent(*key))
key->StopPropagation();
else
native_widget_mac_->GetWidget()->OnKeyEvent(key);
- RunDispatchKeyEventPostIMECallback(key, std::move(callback));
return ui::EventDispatchDetails();
}
////////////////////////////////////////////////////////////////////////////////
-// BridgedNativeWidgetHostImpl, AccessibilityFocusOverrider::Client:
+// NativeWidgetMacNSWindowHost, AccessibilityFocusOverrider::Client:
-id BridgedNativeWidgetHostImpl::GetAccessibilityFocusedUIElement() {
+id NativeWidgetMacNSWindowHost::GetAccessibilityFocusedUIElement() {
return [GetNativeViewAccessible() accessibilityFocusedUIElement];
}
////////////////////////////////////////////////////////////////////////////////
-// BridgedNativeWidgetHostImpl, LayerDelegate:
+// NativeWidgetMacNSWindowHost, LayerDelegate:
-void BridgedNativeWidgetHostImpl::OnPaintLayer(
+void NativeWidgetMacNSWindowHost::OnPaintLayer(
const ui::PaintContext& context) {
native_widget_mac_->GetWidget()->OnNativeWidgetPaint(context);
}
-void BridgedNativeWidgetHostImpl::OnDeviceScaleFactorChanged(
+void NativeWidgetMacNSWindowHost::OnDeviceScaleFactorChanged(
float old_device_scale_factor,
float new_device_scale_factor) {
native_widget_mac_->GetWidget()->DeviceScaleFactorChanged(
old_device_scale_factor, new_device_scale_factor);
}
-void BridgedNativeWidgetHostImpl::UpdateVisualState() {
+void NativeWidgetMacNSWindowHost::UpdateVisualState() {
native_widget_mac_->GetWidget()->LayoutRootViewIfNecessary();
}
////////////////////////////////////////////////////////////////////////////////
-// BridgedNativeWidgetHostImpl, AcceleratedWidgetMac:
+// NativeWidgetMacNSWindowHost, AcceleratedWidgetMac:
-void BridgedNativeWidgetHostImpl::AcceleratedWidgetCALayerParamsUpdated() {
+void NativeWidgetMacNSWindowHost::AcceleratedWidgetCALayerParamsUpdated() {
const gfx::CALayerParams* ca_layer_params =
compositor_->widget()->GetCALayerParams();
if (ca_layer_params) {
@@ -1457,7 +1478,7 @@ void BridgedNativeWidgetHostImpl::AcceleratedWidgetCALayerParamsUpdated() {
// mach port has been specified (in practice, when software compositing is
// enabled).
// https://crbug.com/942213
- if (bridge_ptr_ && ca_layer_params->io_surface_mach_port) {
+ if (remote_ns_window_ptr_ && ca_layer_params->io_surface_mach_port) {
gfx::CALayerParams updated_ca_layer_params = *ca_layer_params;
if (!io_surface_to_remote_layer_interceptor_) {
io_surface_to_remote_layer_interceptor_ =
@@ -1465,9 +1486,9 @@ void BridgedNativeWidgetHostImpl::AcceleratedWidgetCALayerParamsUpdated() {
}
io_surface_to_remote_layer_interceptor_->UpdateCALayerParams(
&updated_ca_layer_params);
- bridge_ptr_->SetCALayerParams(updated_ca_layer_params);
+ remote_ns_window_ptr_->SetCALayerParams(updated_ca_layer_params);
} else {
- bridge()->SetCALayerParams(*ca_layer_params);
+ GetNSWindowMojo()->SetCALayerParams(*ca_layer_params);
}
}
diff --git a/chromium/ui/views/cocoa/text_input_host.h b/chromium/ui/views/cocoa/text_input_host.h
index 27284019fda..f53ba460a26 100644
--- a/chromium/ui/views/cocoa/text_input_host.h
+++ b/chromium/ui/views/cocoa/text_input_host.h
@@ -16,11 +16,11 @@ class TextInputClient;
namespace views {
-class BridgedNativeWidgetHostImpl;
+class NativeWidgetMacNSWindowHost;
class VIEWS_EXPORT TextInputHost : public remote_cocoa::mojom::TextInputHost {
public:
- explicit TextInputHost(BridgedNativeWidgetHostImpl* host_impl);
+ explicit TextInputHost(NativeWidgetMacNSWindowHost* host_impl);
~TextInputHost() override;
void BindRequest(remote_cocoa::mojom::TextInputHostAssociatedRequest request);
@@ -78,7 +78,7 @@ class VIEWS_EXPORT TextInputHost : public remote_cocoa::mojom::TextInputHost {
// IME requests using the old |text_input_client_|.
ui::TextInputClient* pending_text_input_client_ = nullptr;
- BridgedNativeWidgetHostImpl* const host_impl_;
+ NativeWidgetMacNSWindowHost* const host_impl_;
mojo::AssociatedBinding<remote_cocoa::mojom::TextInputHost> mojo_binding_;
DISALLOW_COPY_AND_ASSIGN(TextInputHost);
diff --git a/chromium/ui/views/cocoa/text_input_host.mm b/chromium/ui/views/cocoa/text_input_host.mm
index a61021991f7..2af42b55ba7 100644
--- a/chromium/ui/views/cocoa/text_input_host.mm
+++ b/chromium/ui/views/cocoa/text_input_host.mm
@@ -4,11 +4,11 @@
#include "ui/views/cocoa/text_input_host.h"
-#include "components/remote_cocoa/app_shim/bridged_native_widget_impl.h"
+#include "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h"
#include "ui/accelerated_widget_mac/window_resize_helper_mac.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/events/keycodes/dom/dom_code.h"
-#include "ui/views/cocoa/bridged_native_widget_host_impl.h"
+#include "ui/views/cocoa/native_widget_mac_ns_window_host.h"
namespace {
@@ -131,7 +131,7 @@ namespace views {
////////////////////////////////////////////////////////////////////////////////
// TextInputHost, public:
-TextInputHost::TextInputHost(BridgedNativeWidgetHostImpl* host_impl)
+TextInputHost::TextInputHost(NativeWidgetMacNSWindowHost* host_impl)
: host_impl_(host_impl), mojo_binding_(this) {}
TextInputHost::~TextInputHost() = default;
@@ -175,8 +175,8 @@ void TextInputHost::SetTextInputClient(
text_input_client_ = new_text_input_client;
pending_text_input_client_ = new_text_input_client;
- if (host_impl_->bridge_impl_ &&
- host_impl_->bridge_impl_->NeedsUpdateWindows()) {
+ if (host_impl_->in_process_ns_window_bridge_ &&
+ host_impl_->in_process_ns_window_bridge_->NeedsUpdateWindows()) {
text_input_client_ = old_text_input_client;
[NSApp updateWindows];
// Note: |pending_text_input_client_| (and therefore +[NSTextInputContext
diff --git a/chromium/ui/views/cocoa/tooltip_manager_mac.h b/chromium/ui/views/cocoa/tooltip_manager_mac.h
index c1d1c1bf04d..e8a0eb14515 100644
--- a/chromium/ui/views/cocoa/tooltip_manager_mac.h
+++ b/chromium/ui/views/cocoa/tooltip_manager_mac.h
@@ -10,16 +10,16 @@
namespace remote_cocoa {
namespace mojom {
-class BridgedNativeWidget;
+class NativeWidgetNSWindow;
} // namespace mojom
} // namespace remote_cocoa
namespace views {
-// Manages native Cocoa tooltips for the given BridgedNativeWidgetHostImpl.
+// Manages native Cocoa tooltips for the given NativeWidgetNSWindowHostImpl.
class TooltipManagerMac : public TooltipManager {
public:
- explicit TooltipManagerMac(remote_cocoa::mojom::BridgedNativeWidget* bridge);
+ explicit TooltipManagerMac(remote_cocoa::mojom::NativeWidgetNSWindow* bridge);
~TooltipManagerMac() override;
// TooltipManager:
@@ -29,7 +29,7 @@ class TooltipManagerMac : public TooltipManager {
void TooltipTextChanged(View* view) override;
private:
- remote_cocoa::mojom::BridgedNativeWidget*
+ remote_cocoa::mojom::NativeWidgetNSWindow*
bridge_; // Weak. Owned by the owner of this.
DISALLOW_COPY_AND_ASSIGN(TooltipManagerMac);
diff --git a/chromium/ui/views/cocoa/tooltip_manager_mac.mm b/chromium/ui/views/cocoa/tooltip_manager_mac.mm
index b625af9f60d..da34d6035bb 100644
--- a/chromium/ui/views/cocoa/tooltip_manager_mac.mm
+++ b/chromium/ui/views/cocoa/tooltip_manager_mac.mm
@@ -6,7 +6,7 @@
#include "base/no_destructor.h"
#import "components/remote_cocoa/app_shim/bridged_content_view.h"
-#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h"
+#import "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h"
#include "ui/base/cocoa/cocoa_base_utils.h"
#include "ui/gfx/font_list.h"
#import "ui/gfx/mac/coordinate_conversion.h"
@@ -21,7 +21,7 @@ const int kTooltipMaxWidthPixels = 250;
namespace views {
TooltipManagerMac::TooltipManagerMac(
- remote_cocoa::mojom::BridgedNativeWidget* bridge)
+ remote_cocoa::mojom::NativeWidgetNSWindow* bridge)
: bridge_(bridge) {}
TooltipManagerMac::~TooltipManagerMac() {
diff --git a/chromium/ui/views/color_chooser/color_chooser_view.cc b/chromium/ui/views/color_chooser/color_chooser_view.cc
index 252fb7c73e5..3427ed0d5d6 100644
--- a/chromium/ui/views/color_chooser/color_chooser_view.cc
+++ b/chromium/ui/views/color_chooser/color_chooser_view.cc
@@ -4,6 +4,9 @@
#include "ui/views/color_chooser/color_chooser_view.h"
+#include <memory>
+#include <utility>
+
#include <stdint.h>
#include "base/logging.h"
@@ -366,21 +369,21 @@ ColorChooserView::ColorChooserView(ColorChooserListener* listener,
DCHECK(listener_);
SetBackground(CreateSolidBackground(SK_ColorLTGRAY));
- SetLayoutManager(std::make_unique<BoxLayout>(
- BoxLayout::kVertical, gfx::Insets(kMarginWidth), kMarginWidth));
+ SetLayoutManager(
+ std::make_unique<BoxLayout>(BoxLayout::Orientation::kVertical,
+ gfx::Insets(kMarginWidth), kMarginWidth));
- View* container = new View();
+ auto container = std::make_unique<View>();
container->SetLayoutManager(std::make_unique<BoxLayout>(
- BoxLayout::kHorizontal, gfx::Insets(), kMarginWidth));
- saturation_value_ = new SaturationValueView(this);
- container->AddChildView(saturation_value_);
- hue_ = new HueView(this);
- container->AddChildView(hue_);
- AddChildView(container);
-
- View* container2 = new View();
- GridLayout* layout = container2->SetLayoutManager(
- std::make_unique<views::GridLayout>(container2));
+ BoxLayout::Orientation::kHorizontal, gfx::Insets(), kMarginWidth));
+ saturation_value_ =
+ container->AddChildView(std::make_unique<SaturationValueView>(this));
+ hue_ = container->AddChildView(std::make_unique<HueView>(this));
+ AddChildView(std::move(container));
+
+ auto container2 = std::make_unique<View>();
+ GridLayout* layout =
+ container2->SetLayoutManager(std::make_unique<views::GridLayout>());
ColumnSet* columns = layout->AddColumnSet(0);
columns->AddColumn(
GridLayout::LEADING, GridLayout::FILL, 0, GridLayout::USE_PREF, 0, 0);
@@ -388,15 +391,15 @@ ColorChooserView::ColorChooserView(ColorChooserListener* listener,
columns->AddColumn(
GridLayout::FILL, GridLayout::FILL, 1, GridLayout::USE_PREF, 0, 0);
layout->StartRow(0, 0);
- textfield_ = new Textfield();
- textfield_->set_controller(this);
- textfield_->SetDefaultWidthInChars(kTextfieldLengthInChars);
- textfield_->SetAccessibleName(
+ auto textfield = std::make_unique<Textfield>();
+ textfield->set_controller(this);
+ textfield->SetDefaultWidthInChars(kTextfieldLengthInChars);
+ textfield->SetAccessibleName(
l10n_util::GetStringUTF16(IDS_APP_ACCNAME_COLOR_CHOOSER_HEX_INPUT));
- layout->AddView(textfield_);
- selected_color_patch_ = new SelectedColorPatchView();
- layout->AddView(selected_color_patch_);
- AddChildView(container2);
+ textfield_ = layout->AddView(std::move(textfield));
+ selected_color_patch_ =
+ layout->AddView(std::make_unique<SelectedColorPatchView>());
+ AddChildView(std::move(container2));
OnColorChanged(initial_color);
}
diff --git a/chromium/ui/views/controls/animated_image_view.cc b/chromium/ui/views/controls/animated_image_view.cc
index bb379bc3d7e..aca500c6792 100644
--- a/chromium/ui/views/controls/animated_image_view.cc
+++ b/chromium/ui/views/controls/animated_image_view.cc
@@ -90,9 +90,6 @@ void AnimatedImageView::OnPaint(gfx::Canvas* canvas) {
canvas->Restore();
}
-const char* AnimatedImageView::GetClassName() const {
- return "AnimatedImageView";
-}
void AnimatedImageView::NativeViewHierarchyChanged() {
ui::Compositor* compositor = GetWidget()->GetCompositor();
@@ -142,4 +139,8 @@ void AnimatedImageView::ClearCurrentCompositor() {
}
}
+BEGIN_METADATA(AnimatedImageView)
+METADATA_PARENT_CLASS(ImageViewBase)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/animated_image_view.h b/chromium/ui/views/controls/animated_image_view.h
index f3868c28a97..58ea3ee2b55 100644
--- a/chromium/ui/views/controls/animated_image_view.h
+++ b/chromium/ui/views/controls/animated_image_view.h
@@ -34,6 +34,8 @@ namespace views {
class VIEWS_EXPORT AnimatedImageView : public ImageViewBase,
public ui::CompositorAnimationObserver {
public:
+ METADATA_HEADER(AnimatedImageView);
+
enum class State {
kPlaying, // The animation is currently playing.
kStopped // The animation is stopped and paint will raster the first
@@ -60,7 +62,6 @@ class VIEWS_EXPORT AnimatedImageView : public ImageViewBase,
// Overridden from View:
void OnPaint(gfx::Canvas* canvas) override;
- const char* GetClassName() const override;
void NativeViewHierarchyChanged() override;
void RemovedFromWidget() override;
diff --git a/chromium/ui/views/controls/button/button.cc b/chromium/ui/views/controls/button/button.cc
index cd9b168c18c..7c7562e22a1 100644
--- a/chromium/ui/views/controls/button/button.cc
+++ b/chromium/ui/views/controls/button/button.cc
@@ -70,10 +70,6 @@ void Button::WidgetObserverButtonBridge::OnWidgetDestroying(Widget* widget) {
}
////////////////////////////////////////////////////////////////////////////////
-// Button, static public:
-
-// static
-const char Button::kViewClassName[] = "Button";
// static
const Button* Button::AsButton(const views::View* view) {
@@ -227,10 +223,6 @@ void Button::RemoveButtonObserver(ButtonObserver* observer) {
////////////////////////////////////////////////////////////////////////////////
// Button, View overrides:
-const char* Button::GetClassName() const {
- return kViewClassName;
-}
-
bool Button::OnMousePressed(const ui::MouseEvent& event) {
return button_controller_->OnMousePressed(event);
}
@@ -482,7 +474,9 @@ Button::CreateButtonControllerDelegate() {
}
Button::Button(ButtonListener* listener)
- : listener_(listener), ink_drop_base_color_(gfx::kPlaceholderColor) {
+ : AnimationDelegateViews(this),
+ listener_(listener),
+ ink_drop_base_color_(gfx::kPlaceholderColor) {
SetFocusBehavior(FocusBehavior::ACCESSIBLE_ONLY);
SetProperty(kIsButtonProperty, true);
hover_animation_.SetSlideDuration(kHoverFadeDurationMs);
@@ -599,4 +593,8 @@ void Button::WidgetActivationChanged(Widget* widget, bool active) {
StateChanged(state());
}
+BEGIN_METADATA(Button)
+METADATA_PARENT_CLASS(InkDropHostView)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/button/button.h b/chromium/ui/views/controls/button/button.h
index c923869f45a..cc11bbff633 100644
--- a/chromium/ui/views/controls/button/button.h
+++ b/chromium/ui/views/controls/button/button.h
@@ -11,9 +11,9 @@
#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/animation_delegate_views.h"
#include "ui/views/animation/ink_drop_host_view.h"
#include "ui/views/animation/ink_drop_state.h"
#include "ui/views/controls/button/button_controller_delegate.h"
@@ -45,8 +45,10 @@ class VIEWS_EXPORT ButtonListener {
// not be part of the focus chain, unless in accessibility mode (see
// SetFocusForPlatform()).
class VIEWS_EXPORT Button : public InkDropHostView,
- public gfx::AnimationDelegate {
+ public AnimationDelegateViews {
public:
+ METADATA_HEADER(Button);
+
~Button() override;
// Button states for various button sub-types.
@@ -72,9 +74,6 @@ class VIEWS_EXPORT Button : public InkDropHostView,
CLICK_NONE,
};
- // The menu button's class name.
- static const char kViewClassName[];
-
static const Button* AsButton(const View* view);
static Button* AsButton(View* view);
@@ -165,7 +164,6 @@ class VIEWS_EXPORT Button : public InkDropHostView,
void RemoveButtonObserver(ButtonObserver* observer);
// Overridden from View:
- 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;
@@ -198,7 +196,7 @@ class VIEWS_EXPORT Button : public InkDropHostView,
std::unique_ptr<InkDrop> CreateInkDrop() override;
SkColor GetInkDropBaseColor() const override;
- // Overridden from gfx::AnimationDelegate:
+ // Overridden from views::AnimationDelegateViews:
void AnimationProgressed(const gfx::Animation* animation) override;
// Returns the click action for the given key event.
diff --git a/chromium/ui/views/controls/button/checkbox.cc b/chromium/ui/views/controls/button/checkbox.cc
index f0f88894609..affe2c7e257 100644
--- a/chromium/ui/views/controls/button/checkbox.cc
+++ b/chromium/ui/views/controls/button/checkbox.cc
@@ -31,9 +31,6 @@
namespace views {
-// static
-const char Checkbox::kViewClassName[] = "Checkbox";
-
Checkbox::Checkbox(const base::string16& label, ButtonListener* listener)
: LabelButton(listener, label), checked_(false), label_ax_id_(0) {
SetHorizontalAlignment(gfx::ALIGN_LEFT);
@@ -77,7 +74,7 @@ void Checkbox::SetMultiLine(bool multi_line) {
}
bool Checkbox::GetMultiLine() const {
- return label()->multi_line();
+ return label()->GetMultiLine();
}
void Checkbox::SetAssociatedLabel(View* labelling_view) {
@@ -92,10 +89,6 @@ void Checkbox::SetAssociatedLabel(View* labelling_view) {
node_data.GetString16Attribute(ax::mojom::StringAttribute::kName));
}
-const char* Checkbox::GetClassName() const {
- return kViewClassName;
-}
-
void Checkbox::GetAccessibleNodeData(ui::AXNodeData* node_data) {
LabelButton::GetAccessibleNodeData(node_data);
node_data->role = ax::mojom::Role::kCheckBox;
diff --git a/chromium/ui/views/controls/button/checkbox.h b/chromium/ui/views/controls/button/checkbox.h
index 68ea1f7b2ab..47b500e0a3c 100644
--- a/chromium/ui/views/controls/button/checkbox.h
+++ b/chromium/ui/views/controls/button/checkbox.h
@@ -26,8 +26,6 @@ class VIEWS_EXPORT Checkbox : public LabelButton {
public:
METADATA_HEADER(Checkbox);
- static const char kViewClassName[];
-
// |force_md| forces MD even when --secondary-ui-md flag is not set.
explicit Checkbox(const base::string16& label,
ButtonListener* listener = nullptr);
@@ -51,7 +49,6 @@ class VIEWS_EXPORT Checkbox : public LabelButton {
protected:
// LabelButton:
- const char* GetClassName() const override;
void OnThemeChanged() override;
std::unique_ptr<InkDrop> CreateInkDrop() override;
std::unique_ptr<InkDropRipple> CreateInkDropRipple() const override;
diff --git a/chromium/ui/views/controls/button/image_button.cc b/chromium/ui/views/controls/button/image_button.cc
index ea134d4e078..e7717ed341f 100644
--- a/chromium/ui/views/controls/button/image_button.cc
+++ b/chromium/ui/views/controls/button/image_button.cc
@@ -24,8 +24,6 @@ namespace views {
static constexpr int kDefaultWidth = 16;
static constexpr int kDefaultHeight = 14;
-const char ImageButton::kViewClassName[] = "ImageButton";
-
////////////////////////////////////////////////////////////////////////////////
// ImageButton, public:
@@ -55,8 +53,9 @@ void ImageButton::SetImage(ButtonState for_state, const gfx::ImageSkia& image) {
if (old_preferred_size != GetPreferredSize())
PreferredSizeChanged();
- if (state() == for_state)
- SchedulePaint();
+ // Even if |for_state| isn't the current state this image could be painted;
+ // see |GetImageToPaint()|. So, always repaint.
+ SchedulePaint();
}
void ImageButton::SetBackgroundImage(SkColor color,
@@ -94,13 +93,6 @@ void ImageButton::SetImageVerticalAlignment(VerticalAlignment v_alignment) {
OnPropertyChanged(&v_alignment_, kPropertyEffectsPaint);
}
-void ImageButton::SetBackgroundImageAlignment(HorizontalAlignment h_align,
- VerticalAlignment v_align) {
- h_background_alignment_ = h_align;
- v_background_alignment_ = v_align;
- SchedulePaint();
-}
-
gfx::Size ImageButton::GetMinimumImageSize() const {
return minimum_image_size_;
}
@@ -115,10 +107,6 @@ void ImageButton::SetMinimumImageSize(const gfx::Size& size) {
////////////////////////////////////////////////////////////////////////////////
// ImageButton, View overrides:
-const char* ImageButton::GetClassName() const {
- return kViewClassName;
-}
-
gfx::Size ImageButton::CalculatePreferredSize() const {
gfx::Size size(kDefaultWidth, kDefaultHeight);
if (!images_[STATE_NORMAL].isNull()) {
@@ -160,20 +148,14 @@ void ImageButton::PaintButtonContents(gfx::Canvas* canvas) {
}
if (!background_image_.isNull()) {
- // If the background image alignment was not set, use the image
- // alignment.
- HorizontalAlignment h_alignment =
- h_background_alignment_.value_or(GetImageHorizontalAlignment());
- VerticalAlignment v_alignment =
- v_background_alignment_.value_or(GetImageVerticalAlignment());
- gfx::Point background_position = ComputeImagePaintPosition(
- background_image_, h_alignment, v_alignment);
+ // The background image alignment is the same as for the image.
+ gfx::Point background_position =
+ ComputeImagePaintPosition(background_image_);
canvas->DrawImageInt(background_image_, background_position.x(),
background_position.y());
}
- gfx::Point position = ComputeImagePaintPosition(
- img, GetImageHorizontalAlignment(), GetImageVerticalAlignment());
+ gfx::Point position = ComputeImagePaintPosition(img);
canvas->DrawImageInt(img, position.x(), position.y());
}
}
@@ -199,12 +181,9 @@ gfx::ImageSkia ImageButton::GetImageToPaint() {
// ImageButton, private:
const gfx::Point ImageButton::ComputeImagePaintPosition(
- const gfx::ImageSkia& image,
- HorizontalAlignment h_alignment,
- VerticalAlignment v_alignment) {
- int x = 0, y = 0;
- gfx::Rect rect = GetContentsBounds();
-
+ const gfx::ImageSkia& image) const {
+ HorizontalAlignment h_alignment = GetImageHorizontalAlignment();
+ VerticalAlignment v_alignment = GetImageVerticalAlignment();
if (draw_image_mirrored_) {
if (h_alignment == ALIGN_RIGHT)
h_alignment = ALIGN_LEFT;
@@ -212,20 +191,21 @@ const gfx::Point ImageButton::ComputeImagePaintPosition(
h_alignment = ALIGN_RIGHT;
}
+ const gfx::Rect rect = GetContentsBounds();
+
+ int x = 0;
if (h_alignment == ALIGN_CENTER)
x = (rect.width() - image.width()) / 2;
else if (h_alignment == ALIGN_RIGHT)
x = rect.width() - image.width();
+ int y = 0;
if (v_alignment == ALIGN_MIDDLE)
y = (rect.height() - image.height()) / 2;
else if (v_alignment == ALIGN_BOTTOM)
y = rect.height() - image.height();
- x += rect.x();
- y += rect.y();
-
- return gfx::Point(x, y);
+ return rect.origin() + gfx::Vector2d(x, y);
}
////////////////////////////////////////////////////////////////////////////////
diff --git a/chromium/ui/views/controls/button/image_button.h b/chromium/ui/views/controls/button/image_button.h
index 833234d5ce9..bcad731513c 100644
--- a/chromium/ui/views/controls/button/image_button.h
+++ b/chromium/ui/views/controls/button/image_button.h
@@ -23,8 +23,6 @@ class VIEWS_EXPORT ImageButton : public Button {
public:
METADATA_HEADER(ImageButton);
- static const char kViewClassName[];
-
// An enum describing the horizontal alignment of images on Buttons.
enum HorizontalAlignment {
ALIGN_LEFT = 0,
@@ -53,7 +51,8 @@ class VIEWS_EXPORT ImageButton : public Button {
// consolidated.
virtual void SetImage(ButtonState state, const gfx::ImageSkia& image);
- // Set the background details.
+ // Set the background details. The background image uses the same alignment
+ // as the image.
void SetBackgroundImage(SkColor color,
const gfx::ImageSkia* image,
const gfx::ImageSkia* mask);
@@ -64,10 +63,6 @@ class VIEWS_EXPORT ImageButton : public Button {
void SetImageHorizontalAlignment(HorizontalAlignment h_alignment);
void SetImageVerticalAlignment(VerticalAlignment v_alignment);
- // Sets how the background is laid out within the button's bounds.
- void SetBackgroundImageAlignment(HorizontalAlignment h_align,
- VerticalAlignment v_align);
-
// The minimum size of the contents (not including the border). The contents
// will be at least this size, but may be larger if the image itself is
// larger.
@@ -80,7 +75,6 @@ class VIEWS_EXPORT ImageButton : public Button {
}
// Overridden from View:
- const char* GetClassName() const override;
gfx::Size CalculatePreferredSize() const override;
views::PaintInfo::ScaleType GetPaintScaleType() const override;
@@ -110,20 +104,13 @@ class VIEWS_EXPORT ImageButton : public Button {
FRIEND_TEST_ALL_PREFIXES(ImageButtonFactoryTest, CreateVectorImageButton);
// Returns the correct position of the image for painting.
- const gfx::Point ComputeImagePaintPosition(const gfx::ImageSkia& image,
- HorizontalAlignment h_alignment,
- VerticalAlignment v_alignment);
+ const gfx::Point ComputeImagePaintPosition(const gfx::ImageSkia& image) const;
// Image alignment.
HorizontalAlignment h_alignment_ = ALIGN_LEFT;
VerticalAlignment v_alignment_ = ALIGN_TOP;
gfx::Size minimum_image_size_;
- // Background alignment. If these are not set, the background image uses the
- // image alignment.
- base::Optional<HorizontalAlignment> h_background_alignment_;
- base::Optional<VerticalAlignment> v_background_alignment_;
-
// Whether we draw our resources horizontally flipped. This can happen in the
// linux titlebar, where image resources were designed to be flipped so a
// small curved corner in the close button designed to fit into the frame
diff --git a/chromium/ui/views/controls/button/image_button_unittest.cc b/chromium/ui/views/controls/button/image_button_unittest.cc
index ad2be97e889..ec76c1846f1 100644
--- a/chromium/ui/views/controls/button/image_button_unittest.cc
+++ b/chromium/ui/views/controls/button/image_button_unittest.cc
@@ -39,13 +39,6 @@ class Parent : public views::View {
namespace views {
-namespace {
-const ImageButton::HorizontalAlignment kDefaultHorizontalAlignment =
- ImageButton::ALIGN_LEFT;
-const ImageButton::VerticalAlignment kDefaultVerticalAlignment =
- ImageButton::ALIGN_TOP;
-} // namespace
-
using ImageButtonTest = ViewsTestBase;
TEST_F(ImageButtonTest, Basics) {
@@ -128,30 +121,20 @@ TEST_F(ImageButtonTest, ImagePositionWithBorder) {
button.SetImage(Button::STATE_NORMAL, &image);
// The image should be painted at the top-left corner.
- EXPECT_EQ(gfx::Point(),
- button.ComputeImagePaintPosition(image, kDefaultHorizontalAlignment,
- kDefaultVerticalAlignment));
+ EXPECT_EQ(gfx::Point(), button.ComputeImagePaintPosition(image));
button.SetBorder(views::CreateEmptyBorder(10, 5, 0, 0));
- EXPECT_EQ(gfx::Point(5, 10),
- button.ComputeImagePaintPosition(image, kDefaultHorizontalAlignment,
- kDefaultVerticalAlignment));
+ EXPECT_EQ(gfx::Point(5, 10), button.ComputeImagePaintPosition(image));
button.SetBorder(NullBorder());
button.SetBounds(0, 0, 50, 50);
- EXPECT_EQ(gfx::Point(),
- button.ComputeImagePaintPosition(image, kDefaultHorizontalAlignment,
- kDefaultVerticalAlignment));
+ EXPECT_EQ(gfx::Point(), button.ComputeImagePaintPosition(image));
button.SetImageHorizontalAlignment(ImageButton::ALIGN_CENTER);
button.SetImageVerticalAlignment(ImageButton::ALIGN_MIDDLE);
- EXPECT_EQ(gfx::Point(15, 10),
- button.ComputeImagePaintPosition(image, ImageButton::ALIGN_CENTER,
- ImageButton::ALIGN_MIDDLE));
+ EXPECT_EQ(gfx::Point(15, 10), button.ComputeImagePaintPosition(image));
button.SetBorder(views::CreateEmptyBorder(10, 10, 0, 0));
- EXPECT_EQ(gfx::Point(20, 15),
- button.ComputeImagePaintPosition(image, ImageButton::ALIGN_CENTER,
- ImageButton::ALIGN_MIDDLE));
+ EXPECT_EQ(gfx::Point(20, 15), button.ComputeImagePaintPosition(image));
// The entire button's size should take the border into account.
EXPECT_EQ(gfx::Size(30, 40), button.GetPreferredSize());
@@ -171,9 +154,7 @@ TEST_F(ImageButtonTest, LeftAlignedMirrored) {
// Because the coordinates are flipped, we should expect this to draw as if
// it were ALIGN_RIGHT.
- EXPECT_EQ(gfx::Point(30, 0),
- button.ComputeImagePaintPosition(image, ImageButton::ALIGN_LEFT,
- ImageButton::ALIGN_BOTTOM));
+ EXPECT_EQ(gfx::Point(30, 0), button.ComputeImagePaintPosition(image));
}
TEST_F(ImageButtonTest, RightAlignedMirrored) {
@@ -187,9 +168,7 @@ TEST_F(ImageButtonTest, RightAlignedMirrored) {
// Because the coordinates are flipped, we should expect this to draw as if
// it were ALIGN_LEFT.
- EXPECT_EQ(gfx::Point(0, 0),
- button.ComputeImagePaintPosition(image, ImageButton::ALIGN_RIGHT,
- ImageButton::ALIGN_BOTTOM));
+ EXPECT_EQ(gfx::Point(0, 0), button.ComputeImagePaintPosition(image));
}
TEST_F(ImageButtonTest, PreferredSizeInvalidation) {
diff --git a/chromium/ui/views/controls/button/label_button.cc b/chromium/ui/views/controls/button/label_button.cc
index 90e6f9e1b00..214b1a74c5b 100644
--- a/chromium/ui/views/controls/button/label_button.cc
+++ b/chromium/ui/views/controls/button/label_button.cc
@@ -29,9 +29,6 @@
namespace views {
-// static
-const char LabelButton::kViewClassName[] = "LabelButton";
-
LabelButton::LabelButton(ButtonListener* listener,
const base::string16& text,
int button_context)
@@ -70,7 +67,7 @@ void LabelButton::SetImage(ButtonState for_state, const gfx::ImageSkia& image) {
}
base::string16 LabelButton::GetText() const {
- return label_->text();
+ return label_->GetText();
}
void LabelButton::SetText(const base::string16& text) {
@@ -259,7 +256,7 @@ void LabelButton::Layout() {
label_area.height());
gfx::Point image_origin(child_area.origin());
- if (label_->multi_line()) {
+ if (label_->GetMultiLine()) {
// Right now this code currently only works for CheckBox and RadioButton
// descendants that have multi-line enabled for their label.
image_origin.Offset(
@@ -295,10 +292,6 @@ void LabelButton::Layout() {
Button::Layout();
}
-const char* LabelButton::GetClassName() const {
- return kViewClassName;
-}
-
void LabelButton::EnableCanvasFlippingForRTLUI(bool flip) {
Button::EnableCanvasFlippingForRTLUI(flip);
image_->EnableCanvasFlippingForRTLUI(flip);
@@ -389,7 +382,7 @@ void LabelButton::GetExtraParams(ui::NativeTheme::ExtraParams* params) const {
params->button.is_focused = HasFocus() && IsAccessibilityFocusable();
params->button.has_border = false;
params->button.classic_state = 0;
- params->button.background_color = label_->background_color();
+ params->button.background_color = label_->GetBackgroundColor();
}
void LabelButton::ResetColorsFromNativeTheme() {
@@ -510,7 +503,7 @@ gfx::Size LabelButton::GetUnclampedSizeWithoutLabel() const {
void LabelButton::ResetLabelEnabledColor() {
const SkColor color = button_state_colors_[state()];
- if (state() != STATE_DISABLED && label_->enabled_color() != color)
+ if (state() != STATE_DISABLED && label_->GetEnabledColor() != color)
label_->SetEnabledColor(color);
}
diff --git a/chromium/ui/views/controls/button/label_button.h b/chromium/ui/views/controls/button/label_button.h
index 93538c101aa..c183274ec44 100644
--- a/chromium/ui/views/controls/button/label_button.h
+++ b/chromium/ui/views/controls/button/label_button.h
@@ -31,8 +31,6 @@ class VIEWS_EXPORT LabelButton : public Button, public NativeThemeDelegate {
public:
METADATA_HEADER(LabelButton);
- static const char kViewClassName[];
-
// Creates a LabelButton with ButtonPressed() events sent to |listener| and
// label |text|. |button_context| is a value from views::style::TextContext
// and determines the appearance of |text|.
@@ -93,7 +91,6 @@ class VIEWS_EXPORT LabelButton : public Button, public NativeThemeDelegate {
gfx::Size CalculatePreferredSize() const override;
int GetHeightForWidth(int w) const override;
void Layout() override;
- const char* GetClassName() const override;
void EnableCanvasFlippingForRTLUI(bool flip) override;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
void AddLayerBeneathView(ui::Layer* new_layer) override;
diff --git a/chromium/ui/views/controls/button/label_button_label.cc b/chromium/ui/views/controls/button/label_button_label.cc
index b2eff942a40..81c7c3dc00c 100644
--- a/chromium/ui/views/controls/button/label_button_label.cc
+++ b/chromium/ui/views/controls/button/label_button_label.cc
@@ -40,7 +40,7 @@ void LabelButtonLabel::SetColorForEnableState() {
: requested_disabled_color_);
} else {
int style = GetEnabled() ? style::STYLE_PRIMARY : style::STYLE_DISABLED;
- Label::SetEnabledColor(style::GetColor(*this, text_context(), style));
+ Label::SetEnabledColor(style::GetColor(*this, GetTextContext(), style));
}
}
diff --git a/chromium/ui/views/controls/button/label_button_label_unittest.cc b/chromium/ui/views/controls/button/label_button_label_unittest.cc
index 1f5cd70ee28..a1254e2cc9f 100644
--- a/chromium/ui/views/controls/button/label_button_label_unittest.cc
+++ b/chromium/ui/views/controls/button/label_button_label_unittest.cc
@@ -43,7 +43,7 @@ class TestLabel : public LabelButtonLabel {
// LabelButtonLabel:
void SchedulePaintInRect(const gfx::Rect& r) override {
LabelButtonLabel::SchedulePaintInRect(r);
- *last_color_ = enabled_color();
+ *last_color_ = GetEnabledColor();
}
private:
diff --git a/chromium/ui/views/controls/button/label_button_unittest.cc b/chromium/ui/views/controls/button/label_button_unittest.cc
index 483d3fa33d7..c55ee6e146f 100644
--- a/chromium/ui/views/controls/button/label_button_unittest.cc
+++ b/chromium/ui/views/controls/button/label_button_unittest.cc
@@ -481,24 +481,24 @@ TEST_F(LabelButtonTest, ChangeLabelImageSpacing) {
TEST_F(LabelButtonTest, HighlightedButtonStyle) {
// The NativeTheme might not provide SK_ColorBLACK, but it should be the same
// for normal and pressed states.
- EXPECT_EQ(themed_normal_text_color_, button_->label()->enabled_color());
+ EXPECT_EQ(themed_normal_text_color_, button_->label()->GetEnabledColor());
button_->SetState(Button::STATE_PRESSED);
- EXPECT_EQ(themed_normal_text_color_, button_->label()->enabled_color());
+ EXPECT_EQ(themed_normal_text_color_, button_->label()->GetEnabledColor());
}
// Ensure the label gets the correct enabled color after
// LabelButton::ResetColorsFromNativeTheme() is invoked.
TEST_F(LabelButtonTest, ResetColorsFromNativeTheme) {
ASSERT_FALSE(color_utils::IsInvertedColorScheme());
- ASSERT_NE(button_->label()->background_color(), SK_ColorBLACK);
- EXPECT_EQ(themed_normal_text_color_, button_->label()->enabled_color());
+ ASSERT_NE(button_->label()->GetBackgroundColor(), SK_ColorBLACK);
+ EXPECT_EQ(themed_normal_text_color_, button_->label()->GetEnabledColor());
button_->label()->SetBackgroundColor(SK_ColorBLACK);
button_->label()->SetAutoColorReadabilityEnabled(true);
- EXPECT_NE(themed_normal_text_color_, button_->label()->enabled_color());
+ EXPECT_NE(themed_normal_text_color_, button_->label()->GetEnabledColor());
button_->ResetColorsFromNativeTheme();
- EXPECT_EQ(themed_normal_text_color_, button_->label()->enabled_color());
+ EXPECT_EQ(themed_normal_text_color_, button_->label()->GetEnabledColor());
}
// Test fixture for a LabelButton that has an ink drop configured.
diff --git a/chromium/ui/views/controls/button/md_text_button.cc b/chromium/ui/views/controls/button/md_text_button.cc
index 0e8d5319b7e..0b4f7d74b60 100644
--- a/chromium/ui/views/controls/button/md_text_button.cc
+++ b/chromium/ui/views/controls/button/md_text_button.cc
@@ -114,7 +114,7 @@ void MdTextButton::OnThemeChanged() {
}
SkColor MdTextButton::GetInkDropBaseColor() const {
- return color_utils::DeriveDefaultIconColor(label()->enabled_color());
+ return color_utils::DeriveDefaultIconColor(label()->GetEnabledColor());
}
void MdTextButton::StateChanged(ButtonState old_state) {
@@ -240,20 +240,20 @@ void MdTextButton::UpdatePadding() {
void MdTextButton::UpdateColors() {
bool is_disabled = state() == STATE_DISABLED;
SkColor enabled_text_color =
- style::GetColor(*this, label()->text_context(),
+ style::GetColor(*this, label()->GetTextContext(),
is_prominent_ ? style::STYLE_DIALOG_BUTTON_DEFAULT
: style::STYLE_PRIMARY);
if (!explicitly_set_normal_color()) {
const auto colors = explicitly_set_colors();
LabelButton::SetEnabledTextColors(enabled_text_color);
// Disabled buttons need the disabled color explicitly set.
- // This ensures that label()->enabled_color() returns the correct color as
+ // This ensures that label()->GetEnabledColor() 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) {
- LabelButton::SetTextColor(STATE_DISABLED,
- style::GetColor(*this, label()->text_context(),
- style::STYLE_DISABLED));
+ LabelButton::SetTextColor(
+ STATE_DISABLED, style::GetColor(*this, label()->GetTextContext(),
+ style::STYLE_DISABLED));
}
set_explicitly_set_colors(colors);
}
diff --git a/chromium/ui/views/controls/button/menu_button.cc b/chromium/ui/views/controls/button/menu_button.cc
index 32bf07c7533..d78277df63a 100644
--- a/chromium/ui/views/controls/button/menu_button.cc
+++ b/chromium/ui/views/controls/button/menu_button.cc
@@ -11,8 +11,6 @@
#include "ui/views/controls/button/menu_button_controller.h"
namespace views {
-// static
-const char MenuButton::kViewClassName[] = "MenuButton";
MenuButton::MenuButton(const base::string16& text,
MenuButtonListener* menu_button_listener,
@@ -31,18 +29,14 @@ bool MenuButton::Activate(const ui::Event* event) {
return button_controller()->Activate(event);
}
-bool MenuButton::IsTriggerableEventType(const ui::Event& event) {
- return button_controller()->IsTriggerableEventType(event);
-}
-
-const char* MenuButton::GetClassName() const {
- return kViewClassName;
-}
-
void MenuButton::NotifyClick(const ui::Event& event) {
// Notify MenuButtonListener via MenuButtonController, instead of
// ButtonListener::ButtonPressed.
button_controller()->Activate(&event);
}
+BEGIN_METADATA(MenuButton)
+METADATA_PARENT_CLASS(LabelButton)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/button/menu_button.h b/chromium/ui/views/controls/button/menu_button.h
index 61423f00713..d55a4752620 100644
--- a/chromium/ui/views/controls/button/menu_button.h
+++ b/chromium/ui/views/controls/button/menu_button.h
@@ -23,7 +23,7 @@ class MenuButtonListener;
////////////////////////////////////////////////////////////////////////////////
class VIEWS_EXPORT MenuButton : public LabelButton {
public:
- static const char kViewClassName[];
+ METADATA_HEADER(MenuButton);
// How much padding to put on the left and right of the menu marker.
static constexpr int kMenuMarkerPaddingLeft = 3;
@@ -41,12 +41,6 @@ class VIEWS_EXPORT MenuButton : public LabelButton {
bool Activate(const ui::Event* event);
- // TODO(cyan): Remove this method and move into MenuButtonController.
- virtual bool IsTriggerableEventType(const ui::Event& event);
-
- // View:
- const char* GetClassName() const override;
-
protected:
// Button:
void NotifyClick(const ui::Event& event) final;
diff --git a/chromium/ui/views/controls/button/menu_button_controller.cc b/chromium/ui/views/controls/button/menu_button_controller.cc
index 3a741cca1bf..7d77b7a2dee 100644
--- a/chromium/ui/views/controls/button/menu_button_controller.cc
+++ b/chromium/ui/views/controls/button/menu_button_controller.cc
@@ -20,6 +20,17 @@ using base::TimeTicks;
namespace views {
+namespace {
+ui::EventType NotifyActionToMouseEventType(Button::NotifyAction notify_action) {
+ switch (notify_action) {
+ case Button::NOTIFY_ON_PRESS:
+ return ui::ET_MOUSE_PRESSED;
+ case Button::NOTIFY_ON_RELEASE:
+ return ui::ET_MOUSE_RELEASED;
+ }
+}
+} // namespace
+
////////////////////////////////////////////////////////////////////////////////
//
// MenuButtonController::PressedLock
@@ -66,7 +77,13 @@ MenuButtonController::MenuButtonController(
Button* button,
MenuButtonListener* listener,
std::unique_ptr<ButtonControllerDelegate> delegate)
- : ButtonController(button, std::move(delegate)), listener_(listener) {}
+ : ButtonController(button, std::move(delegate)), listener_(listener) {
+ // Triggers on button press by default, unless drag-and-drop is enabled, see
+ // MenuButtonController::IsTriggerableEventType.
+ // TODO(cyan): Investigate using PlatformStyle::kMenuNotifyActivationAction.
+ // TODO(cyan): Move NotifyAction into ButtonController.
+ button->set_notify_action(Button::NOTIFY_ON_PRESS);
+}
MenuButtonController::~MenuButtonController() = default;
@@ -267,12 +284,13 @@ bool MenuButtonController::IsTriggerableEventType(const ui::Event& event) {
// would also activate a context menu.
if (!(mouse_event->button_flags() & button()->triggerable_event_flags()))
return false;
- // If dragging is supported activate on release, otherwise activate on
- // pressed.
+
+ // Activate on release if dragging, otherwise activate based on
+ // notify_action.
ui::EventType active_on =
delegate()->GetDragOperations(mouse_event->location()) ==
ui::DragDropTypes::DRAG_NONE
- ? ui::ET_MOUSE_PRESSED
+ ? NotifyActionToMouseEventType(button()->notify_action())
: ui::ET_MOUSE_RELEASED;
return event.type() == active_on;
}
diff --git a/chromium/ui/views/controls/button/menu_button_unittest.cc b/chromium/ui/views/controls/button/menu_button_unittest.cc
index 18665c52d20..f296f95aac6 100644
--- a/chromium/ui/views/controls/button/menu_button_unittest.cc
+++ b/chromium/ui/views/controls/button/menu_button_unittest.cc
@@ -243,7 +243,7 @@ class TestDragDropClient : public aura::client::DragDropClient,
~TestDragDropClient() override;
// aura::client::DragDropClient:
- int StartDragAndDrop(const ui::OSExchangeData& data,
+ int StartDragAndDrop(std::unique_ptr<ui::OSExchangeData> data,
aura::Window* root_window,
aura::Window* source_window,
const gfx::Point& screen_location,
@@ -273,7 +273,7 @@ TestDragDropClient::TestDragDropClient() = default;
TestDragDropClient::~TestDragDropClient() = default;
int TestDragDropClient::StartDragAndDrop(
- const ui::OSExchangeData& data,
+ std::unique_ptr<ui::OSExchangeData> data,
aura::Window* root_window,
aura::Window* source_window,
const gfx::Point& screen_location,
diff --git a/chromium/ui/views/controls/button/radio_button.cc b/chromium/ui/views/controls/button/radio_button.cc
index e7189a5924c..975862f4496 100644
--- a/chromium/ui/views/controls/button/radio_button.cc
+++ b/chromium/ui/views/controls/button/radio_button.cc
@@ -16,9 +16,6 @@
namespace views {
-// static
-const char RadioButton::kViewClassName[] = "RadioButton";
-
RadioButton::RadioButton(const base::string16& label, int group_id)
: Checkbox(label, nullptr) {
SetGroup(group_id);
@@ -26,10 +23,6 @@ RadioButton::RadioButton(const base::string16& label, int group_id)
RadioButton::~RadioButton() = default;
-const char* RadioButton::GetClassName() const {
- return kViewClassName;
-}
-
void RadioButton::GetAccessibleNodeData(ui::AXNodeData* node_data) {
Checkbox::GetAccessibleNodeData(node_data);
node_data->role = ax::mojom::Role::kRadioButton;
@@ -114,4 +107,8 @@ void RadioButton::GetViewsInGroupFromParent(int group, Views* views) {
parent()->GetViewsInGroup(group, views);
}
+BEGIN_METADATA(RadioButton)
+METADATA_PARENT_CLASS(Checkbox)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/button/radio_button.h b/chromium/ui/views/controls/button/radio_button.h
index eda57860d3c..3bb6d4a5fe3 100644
--- a/chromium/ui/views/controls/button/radio_button.h
+++ b/chromium/ui/views/controls/button/radio_button.h
@@ -16,14 +16,12 @@ namespace views {
// platform specific objects to replicate the native platforms looks and feel.
class VIEWS_EXPORT RadioButton : public Checkbox {
public:
- // The button's class name.
- static const char kViewClassName[];
+ METADATA_HEADER(RadioButton);
RadioButton(const base::string16& label, int group_id);
~RadioButton() override;
// Overridden from View:
- const char* GetClassName() const override;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
View* GetSelectedViewForGroup(int group) override;
bool IsGroupFocusTraversable() const override;
diff --git a/chromium/ui/views/controls/button/toggle_button.cc b/chromium/ui/views/controls/button/toggle_button.cc
index 57a0eafcec7..5e6f4a4af54 100644
--- a/chromium/ui/views/controls/button/toggle_button.cc
+++ b/chromium/ui/views/controls/button/toggle_button.cc
@@ -67,9 +67,6 @@ class ToggleButton::ThumbView : public InkDropHostView {
static constexpr int kShadowBlur = 2;
// views::View:
- const char* GetClassName() const override {
- return "ToggleButton::ThumbView";
- }
void OnPaint(gfx::Canvas* canvas) override {
const float dsf = canvas->UndoDeviceScaleFactor();
@@ -111,9 +108,6 @@ class ToggleButton::ThumbView : public InkDropHostView {
DISALLOW_COPY_AND_ASSIGN(ThumbView);
};
-// static
-const char ToggleButton::kViewClassName[] = "ToggleButton";
-
ToggleButton::ToggleButton(ButtonListener* listener) : Button(listener) {
slide_animation_.SetSlideDuration(80 /* ms */);
slide_animation_.SetTweenType(gfx::Tween::LINEAR);
@@ -200,10 +194,6 @@ SkColor ToggleButton::GetTrackColor(bool is_on) const {
return SkColorSetA(GetNativeTheme()->GetSystemColor(color_id), kTrackAlpha);
}
-const char* ToggleButton::GetClassName() const {
- return kViewClassName;
-}
-
bool ToggleButton::CanAcceptEvent(const ui::Event& event) {
return GetAcceptsEvents() && Button::CanAcceptEvent(event);
}
diff --git a/chromium/ui/views/controls/button/toggle_button.h b/chromium/ui/views/controls/button/toggle_button.h
index e8b77da6f57..54fa757da89 100644
--- a/chromium/ui/views/controls/button/toggle_button.h
+++ b/chromium/ui/views/controls/button/toggle_button.h
@@ -17,8 +17,6 @@ class VIEWS_EXPORT ToggleButton : public Button {
public:
METADATA_HEADER(ToggleButton);
- static const char kViewClassName[];
-
explicit ToggleButton(ButtonListener* listener);
~ToggleButton() override;
@@ -49,7 +47,6 @@ class VIEWS_EXPORT ToggleButton : public Button {
SkColor GetTrackColor(bool is_on) const;
// views::View:
- const char* GetClassName() const override;
bool CanAcceptEvent(const ui::Event& event) override;
void OnBoundsChanged(const gfx::Rect& previous_bounds) override;
void OnThemeChanged() override;
diff --git a/chromium/ui/views/controls/combobox/combobox.cc b/chromium/ui/views/controls/combobox/combobox.cc
index 107b9e7af60..caf05ca43c9 100644
--- a/chromium/ui/views/controls/combobox/combobox.cc
+++ b/chromium/ui/views/controls/combobox/combobox.cc
@@ -117,9 +117,6 @@ int GetAdjacentIndex(ui::ComboboxModel* model, int increment, int index) {
} // namespace
-// static
-const char Combobox::kViewClassName[] = "views/Combobox";
-
// Adapts a ui::ComboboxModel to a ui::MenuModel.
class Combobox::ComboboxMenuModel : public ui::MenuModel {
public:
@@ -358,10 +355,6 @@ gfx::Size Combobox::CalculatePreferredSize() const {
return gfx::Size(total_width, content_size_.height() + insets.height());
}
-const char* Combobox::GetClassName() const {
- return kViewClassName;
-}
-
bool Combobox::SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) {
// Escape should close the drop down list when it is active, not host UI.
if (e.key_code() != ui::VKEY_ESCAPE ||
diff --git a/chromium/ui/views/controls/combobox/combobox.h b/chromium/ui/views/controls/combobox/combobox.h
index de84ae9d4bf..23771760cdd 100644
--- a/chromium/ui/views/controls/combobox/combobox.h
+++ b/chromium/ui/views/controls/combobox/combobox.h
@@ -41,8 +41,6 @@ class VIEWS_EXPORT Combobox : public View,
public:
METADATA_HEADER(Combobox);
- // The combobox's class name.
- static const char kViewClassName[];
static constexpr int kDefaultComboboxTextContext = style::CONTEXT_BUTTON;
static constexpr int kDefaultComboboxTextStyle = style::STYLE_PRIMARY;
@@ -86,7 +84,6 @@ class VIEWS_EXPORT Combobox : public View,
// Overridden from View:
gfx::Size CalculatePreferredSize() const override;
- const char* GetClassName() const override;
bool SkipDefaultKeyEventProcessing(const ui::KeyEvent& e) override;
bool OnKeyPressed(const ui::KeyEvent& e) override;
void OnPaint(gfx::Canvas* canvas) override;
diff --git a/chromium/ui/views/controls/editable_combobox/editable_combobox.cc b/chromium/ui/views/controls/editable_combobox/editable_combobox.cc
index d418b307dfb..cc70d3cd1c8 100644
--- a/chromium/ui/views/controls/editable_combobox/editable_combobox.cc
+++ b/chromium/ui/views/controls/editable_combobox/editable_combobox.cc
@@ -15,6 +15,7 @@
#include "base/strings/string16.h"
#include "build/build_config.h"
#include "third_party/skia/include/core/SkColor.h"
+#include "ui/accessibility/ax_action_data.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/base/accelerators/accelerator.h"
#include "ui/base/ime/text_input_type.h"
@@ -104,7 +105,8 @@ class Arrow : public Button {
}
void GetAccessibleNodeData(ui::AXNodeData* node_data) override {
- node_data->role = ax::mojom::Role::kPopUpButton;
+ node_data->role = ax::mojom::Role::kComboBoxMenuButton;
+ node_data->SetName(GetAccessibleName());
node_data->SetHasPopup(ax::mojom::HasPopup::kMenu);
if (GetEnabled())
node_data->SetDefaultActionVerb(ax::mojom::DefaultActionVerb::kOpen);
@@ -117,9 +119,6 @@ class Arrow : public Button {
} // namespace
-// static
-const char EditableCombobox::kViewClassName[] = "EditableCombobox";
-
// Adapts a ui::ComboboxModel to a ui::MenuModel to be used by EditableCombobox.
// Also provides a filtering capability.
class EditableCombobox::EditableComboboxMenuModel
@@ -278,6 +277,7 @@ class EditableCombobox::EditableComboboxPreTargetHandler
event->flags() == event->changed_button_flags())
HandlePressEvent(event->root_location());
}
+
void OnTouchEvent(ui::TouchEvent* event) override {
if (event->type() == ui::ET_TOUCH_PRESSED)
HandlePressEvent(event->root_location());
@@ -357,7 +357,6 @@ void EditableCombobox::SetText(const base::string16& text) {
// SetText does not actually notify the TextfieldController, so we call the
// handling code directly.
HandleNewContent(text);
- ShowDropDownMenu();
}
const gfx::FontList& EditableCombobox::GetFontList() const {
@@ -370,6 +369,8 @@ void EditableCombobox::SelectRange(const gfx::Range& range) {
void EditableCombobox::SetAccessibleName(const base::string16& name) {
textfield_->SetAccessibleName(name);
+ if (arrow_)
+ arrow_->SetAccessibleName(name);
}
void EditableCombobox::SetAssociatedLabel(View* labelling_view) {
@@ -384,7 +385,6 @@ void EditableCombobox::RevealPasswords(bool revealed) {
textfield_->SetTextInputType(revealed ? ui::TEXT_INPUT_TYPE_TEXT
: ui::TEXT_INPUT_TYPE_PASSWORD);
menu_model_->UpdateItemsShown();
- ShowDropDownMenu();
}
int EditableCombobox::GetItemCountForTest() {
@@ -398,10 +398,6 @@ base::string16 EditableCombobox::GetItemForTest(int index) {
////////////////////////////////////////////////////////////////////////////////
// EditableCombobox, View overrides:
-const char* EditableCombobox::GetClassName() const {
- return kViewClassName;
-}
-
void EditableCombobox::Layout() {
View::Layout();
if (arrow_) {
@@ -415,6 +411,13 @@ void EditableCombobox::OnThemeChanged() {
textfield_->OnThemeChanged();
}
+void EditableCombobox::GetAccessibleNodeData(ui::AXNodeData* node_data) {
+ node_data->role = ax::mojom::Role::kComboBoxGrouping;
+
+ node_data->SetName(textfield_->accessible_name());
+ node_data->SetValue(GetText());
+}
+
////////////////////////////////////////////////////////////////////////////////
// EditableCombobox, TextfieldController overrides:
@@ -424,27 +427,17 @@ void EditableCombobox::ContentsChanged(Textfield* sender,
ShowDropDownMenu(ui::MENU_SOURCE_KEYBOARD);
}
-bool EditableCombobox::HandleMouseEvent(Textfield* sender,
- const ui::MouseEvent& mouse_event) {
- // We show the menu on mouse release instead of mouse press so that the menu
- // showing up doesn't interrupt a potential text selection operation by the
- // user.
- if (mouse_event.type() == ui::ET_MOUSE_PRESSED) {
- mouse_pressed_ = true;
- } else if (mouse_event.type() == ui::ET_MOUSE_RELEASED) {
- mouse_pressed_ = false;
- ShowDropDownMenu(ui::MENU_SOURCE_MOUSE);
+bool EditableCombobox::HandleKeyEvent(Textfield* sender,
+ const ui::KeyEvent& key_event) {
+ if (key_event.type() == ui::ET_KEY_PRESSED &&
+ (key_event.key_code() == ui::VKEY_UP ||
+ key_event.key_code() == ui::VKEY_DOWN)) {
+ ShowDropDownMenu(ui::MENU_SOURCE_KEYBOARD);
+ return true;
}
return false;
}
-bool EditableCombobox::HandleGestureEvent(
- Textfield* sender,
- const ui::GestureEvent& gesture_event) {
- ShowDropDownMenu(ui::MENU_SOURCE_TOUCH);
- return false;
-}
-
////////////////////////////////////////////////////////////////////////////////
// EditableCombobox, View overrides:
@@ -452,23 +445,15 @@ void EditableCombobox::OnViewBlurred(View* observed_view) {
CloseMenu();
}
-void EditableCombobox::OnViewFocused(View* observed_view) {
- // We only show the menu if the mouse is not currently pressed to avoid
- // interrupting a text selection operation. The menu will be shown on mouse
- // release inside HandleMouseEvent.
- if (!mouse_pressed_)
- ShowDropDownMenu();
-}
-
////////////////////////////////////////////////////////////////////////////////
// EditableCombobox, ButtonListener overrides:
void EditableCombobox::ButtonPressed(Button* sender, const ui::Event& event) {
+ textfield_->RequestFocus();
if (menu_runner_ && menu_runner_->IsRunning()) {
CloseMenu();
return;
}
- textfield_->RequestFocus();
ui::MenuSourceType source_type = ui::MENU_SOURCE_MOUSE;
if (event.IsKeyEvent())
source_type = ui::MENU_SOURCE_KEYBOARD;
@@ -523,7 +508,9 @@ void EditableCombobox::ShowDropDownMenu(ui::MenuSourceType source_type) {
CloseMenu();
return;
}
- if (!textfield_->HasFocus() || (menu_runner_ && menu_runner_->IsRunning()))
+ if (menu_runner_ && menu_runner_->IsRunning())
+ return;
+ if (!GetWidget())
return;
// Since we don't capture the mouse, we want to see the events that happen in
@@ -554,4 +541,8 @@ void EditableCombobox::ShowDropDownMenu(ui::MenuSourceType source_type) {
MenuAnchorPosition::kTopLeft, source_type);
}
+BEGIN_METADATA(EditableCombobox)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/editable_combobox/editable_combobox.h b/chromium/ui/views/controls/editable_combobox/editable_combobox.h
index d0208e1e406..1bdfcecd336 100644
--- a/chromium/ui/views/controls/editable_combobox/editable_combobox.h
+++ b/chromium/ui/views/controls/editable_combobox/editable_combobox.h
@@ -41,13 +41,13 @@ class VIEWS_EXPORT EditableCombobox : public View,
public ViewObserver,
public ButtonListener {
public:
+ METADATA_HEADER(EditableCombobox);
+
enum class Type {
kRegular,
kPassword,
};
- // The class name.
- static const char kViewClassName[];
static constexpr int kDefaultTextContext = style::CONTEXT_BUTTON;
static constexpr int kDefaultTextStyle = style::STYLE_PRIMARY;
@@ -119,20 +119,17 @@ class VIEWS_EXPORT EditableCombobox : public View,
void ShowDropDownMenu(ui::MenuSourceType source_type = ui::MENU_SOURCE_NONE);
// Overridden from View:
- const char* GetClassName() const override;
void Layout() override;
void OnThemeChanged() override;
+ void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
// Overridden from TextfieldController:
void ContentsChanged(Textfield* sender,
const base::string16& new_contents) override;
- bool HandleMouseEvent(Textfield* sender,
- const ui::MouseEvent& mouse_event) override;
- bool HandleGestureEvent(Textfield* sender,
- const ui::GestureEvent& gesture_event) override;
+ bool HandleKeyEvent(Textfield* sender,
+ const ui::KeyEvent& key_event) override;
// Overridden from ViewObserver:
- void OnViewFocused(View* observed_view) override;
void OnViewBlurred(View* observed_view) override;
// Overridden from ButtonListener:
@@ -160,10 +157,6 @@ class VIEWS_EXPORT EditableCombobox : public View,
const Type type_;
- // True between mouse press and release, used to avoid opening the menu and
- // interrupting textfield selection interactions.
- bool mouse_pressed_ = false;
-
// Set while the drop-down is showing.
std::unique_ptr<MenuRunner> menu_runner_;
diff --git a/chromium/ui/views/controls/editable_combobox/editable_combobox_unittest.cc b/chromium/ui/views/controls/editable_combobox/editable_combobox_unittest.cc
index 396f86bb4cc..54eab4cbf0d 100644
--- a/chromium/ui/views/controls/editable_combobox/editable_combobox_unittest.cc
+++ b/chromium/ui/views/controls/editable_combobox/editable_combobox_unittest.cc
@@ -25,6 +25,7 @@
#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/render_text.h"
+#include "ui/views/context_menu_controller.h"
#include "ui/views/controls/editable_combobox/editable_combobox_listener.h"
#include "ui/views/controls/menu/menu_runner.h"
#include "ui/views/controls/textfield/textfield.h"
@@ -56,6 +57,27 @@ class DummyListener : public EditableComboboxListener {
DISALLOW_COPY_AND_ASSIGN(DummyListener);
};
+// No-op test double of a ContextMenuController
+class TestContextMenuController : public ContextMenuController {
+ public:
+ TestContextMenuController() = default;
+ ~TestContextMenuController() override = default;
+
+ // ContextMenuController:
+ void ShowContextMenuForViewImpl(View* source,
+ const gfx::Point& point,
+ ui::MenuSourceType source_type) override {
+ opened_menu_ = true;
+ }
+
+ bool opened_menu() const { return opened_menu_; }
+
+ private:
+ bool opened_menu_ = false;
+
+ DISALLOW_COPY_AND_ASSIGN(TestContextMenuController);
+};
+
class EditableComboboxTest : public ViewsTestBase {
public:
EditableComboboxTest() { views::test::DisableMenuClosureAnimations(); }
@@ -171,6 +193,18 @@ void EditableComboboxTest::InitWidget() {
container->AddChildView(dummy_focusable_view_);
widget_->Show();
+#if defined(OS_MACOSX)
+ // The event loop needs to be flushed here, otherwise in various tests:
+ // 1. The actual showing of the native window backing the widget gets delayed
+ // until a spin of the event loop.
+ // 2. The combobox menu object is triggered, and it starts listening for the
+ // "window did become key" notification as a sign that it lost focus and
+ // should close.
+ // 3. The event loop is spun, and the actual showing of the native window
+ // triggers the close of the menu opened from within the window.
+ base::RunLoop().RunUntilIdle();
+#endif
+
event_generator_ =
std::make_unique<ui::test::EventGenerator>(GetRootWindow(widget_));
event_generator_->set_target(ui::test::EventGenerator::Target::WINDOW);
@@ -208,7 +242,7 @@ void EditableComboboxTest::DragMouseTo(const gfx::Point& location) {
}
bool EditableComboboxTest::IsMenuOpen() {
- return combobox_->GetMenuRunnerForTest() &&
+ return combobox_ && combobox_->GetMenuRunnerForTest() &&
combobox_->GetMenuRunnerForTest()->IsRunning();
}
@@ -246,16 +280,24 @@ void EditableComboboxTest::SendKeyEvent(ui::KeyboardCode key_code,
event_generator_->PressKey(key_code, flags);
}
-TEST_F(EditableComboboxTest, FocusOnTextfieldOpensMenu) {
+TEST_F(EditableComboboxTest, FocusOnTextfieldDoesntOpenMenu) {
InitEditableCombobox();
EXPECT_FALSE(IsMenuOpen());
combobox_->GetTextfieldForTest()->RequestFocus();
+ EXPECT_FALSE(IsMenuOpen());
+}
+
+TEST_F(EditableComboboxTest, ArrowDownOpensMenu) {
+ InitEditableCombobox();
+ EXPECT_FALSE(IsMenuOpen());
+ combobox_->GetTextfieldForTest()->RequestFocus();
+ SendKeyEvent(ui::VKEY_DOWN);
EXPECT_TRUE(IsMenuOpen());
}
TEST_F(EditableComboboxTest, TabMovesToOtherViewAndClosesMenu) {
InitEditableCombobox();
- combobox_->GetTextfieldForTest()->RequestFocus();
+ ClickArrow();
EXPECT_TRUE(IsMenuOpen());
EXPECT_TRUE(combobox_->GetTextfieldForTest()->HasFocus());
SendKeyEvent(ui::VKEY_TAB);
@@ -268,8 +310,9 @@ TEST_F(EditableComboboxTest, TabMovesToOtherViewAndClosesMenu) {
TEST_F(EditableComboboxTest,
ClickOutsideEditableComboboxWithoutLosingFocusClosesMenu) {
InitEditableCombobox();
- combobox_->GetTextfieldForTest()->RequestFocus();
+ ClickArrow();
EXPECT_TRUE(IsMenuOpen());
+ EXPECT_TRUE(combobox_->GetTextfieldForTest()->HasFocus());
const gfx::Point outside_point(combobox_->x() + combobox_->width() + 1,
combobox_->y() + 1);
@@ -282,7 +325,7 @@ TEST_F(EditableComboboxTest,
TEST_F(EditableComboboxTest, ClickTextfieldDoesntCloseMenu) {
InitEditableCombobox();
- combobox_->GetTextfieldForTest()->RequestFocus();
+ ClickArrow();
EXPECT_TRUE(IsMenuOpen());
MenuRunner* menu_runner1 = combobox_->GetMenuRunnerForTest();
@@ -296,7 +339,7 @@ TEST_F(EditableComboboxTest, ClickTextfieldDoesntCloseMenu) {
TEST_F(EditableComboboxTest, RemovingControlWhileMenuOpenClosesMenu) {
InitEditableCombobox();
- combobox_->GetTextfieldForTest()->RequestFocus();
+ ClickArrow();
EXPECT_TRUE(IsMenuOpen());
parent_of_combobox_->RemoveChildView(combobox_);
EXPECT_EQ(nullptr, combobox_->GetMenuRunnerForTest());
@@ -304,7 +347,7 @@ TEST_F(EditableComboboxTest, RemovingControlWhileMenuOpenClosesMenu) {
TEST_F(EditableComboboxTest, RemovingParentOfControlWhileMenuOpenClosesMenu) {
InitEditableCombobox();
- combobox_->GetTextfieldForTest()->RequestFocus();
+ ClickArrow();
EXPECT_TRUE(IsMenuOpen());
widget_->GetContentsView()->RemoveChildView(parent_of_combobox_);
EXPECT_EQ(nullptr, combobox_->GetMenuRunnerForTest());
@@ -497,8 +540,8 @@ TEST_F(EditableComboboxTest, TypingInTextfieldUnhighlightsMenuItem) {
TEST_F(EditableComboboxTest, ClickOnMenuItemSelectsItAndClosesMenu) {
InitEditableCombobox();
- combobox_->GetTextfieldForTest()->RequestFocus();
- EXPECT_TRUE(IsMenuOpen());
+ ClickArrow();
+ ASSERT_TRUE(IsMenuOpen());
ClickMenuItem(/*index=*/0);
WaitForMenuClosureAnimation();
@@ -526,7 +569,8 @@ TEST_F(EditableComboboxTest, MenuCanAdaptToContentChange) {
ASCIIToUTF16("bac"),
ASCIIToUTF16("bad")};
InitEditableCombobox(items, /*filter_on_edit=*/true);
- combobox_->GetTextfieldForTest()->RequestFocus();
+ ClickArrow();
+ ASSERT_TRUE(IsMenuOpen());
SendKeyEvent(ui::VKEY_DOWN);
SendKeyEvent(ui::VKEY_RETURN);
@@ -569,7 +613,7 @@ TEST_F(EditableComboboxTest, RefocusingReopensMenuBasedOnLatestContent) {
// "bac", the selected item, instead of showing completions of "b", what we
// had typed.
dummy_focusable_view_->RequestFocus();
- combobox_->GetTextfieldForTest()->RequestFocus();
+ ClickArrow();
EXPECT_TRUE(IsMenuOpen());
ASSERT_EQ(2, combobox_->GetItemCountForTest());
}
@@ -709,36 +753,33 @@ TEST_F(EditableComboboxTest, ArrowButtonOpensAndClosesMenu) {
EXPECT_FALSE(IsMenuOpen());
}
-TEST_F(EditableComboboxTest, ShowMenuOnMouseRelease) {
+TEST_F(EditableComboboxTest, ShowContextMenuOnMouseRelease) {
std::vector<base::string16> items = {ASCIIToUTF16("item0"),
ASCIIToUTF16("item1")};
InitEditableCombobox(items, /*filter_on_edit=*/false,
/*show_on_empty=*/true);
- dummy_focusable_view_->RequestFocus();
- WaitForMenuClosureAnimation();
EXPECT_FALSE(IsMenuOpen());
-
- // Without initial focus.
- EXPECT_FALSE(combobox_->GetTextfieldForTest()->HasFocus());
+ TestContextMenuController context_menu_controller;
+ combobox_->GetTextfieldForTest()->set_context_menu_controller(
+ &context_menu_controller);
const gfx::Point textfield_point(combobox_->x() + 1, combobox_->y() + 1);
- PerformMouseEvent(widget_, textfield_point, ui::ET_MOUSE_PRESSED);
+ ui::MouseEvent click_mouse_event(ui::ET_MOUSE_PRESSED, textfield_point,
+ textfield_point, ui::EventTimeForNow(),
+ ui::EF_RIGHT_MOUSE_BUTTON,
+ ui::EF_RIGHT_MOUSE_BUTTON);
+ widget_->OnMouseEvent(&click_mouse_event);
EXPECT_FALSE(IsMenuOpen());
- PerformMouseEvent(widget_, textfield_point, ui::ET_MOUSE_RELEASED);
- EXPECT_TRUE(IsMenuOpen());
-
- SendKeyEvent(ui::VKEY_ESCAPE);
- WaitForMenuClosureAnimation();
+ ui::MouseEvent release_mouse_event(ui::ET_MOUSE_RELEASED, textfield_point,
+ textfield_point, ui::EventTimeForNow(),
+ ui::EF_RIGHT_MOUSE_BUTTON,
+ ui::EF_RIGHT_MOUSE_BUTTON);
+ widget_->OnMouseEvent(&release_mouse_event);
+ // The context menu should appear, not the combobox dropdown.
EXPECT_FALSE(IsMenuOpen());
-
- // With initial focus.
- EXPECT_TRUE(combobox_->GetTextfieldForTest()->HasFocus());
- PerformMouseEvent(widget_, textfield_point, ui::ET_MOUSE_PRESSED);
- EXPECT_FALSE(IsMenuOpen());
- PerformMouseEvent(widget_, textfield_point, ui::ET_MOUSE_RELEASED);
- EXPECT_TRUE(IsMenuOpen());
+ EXPECT_TRUE(context_menu_controller.opened_menu());
}
-TEST_F(EditableComboboxTest, DragToSelectDoesntOpenTheMenuUntilDone) {
+TEST_F(EditableComboboxTest, DragToSelectDoesntOpenTheMenu) {
std::vector<base::string16> items = {ASCIIToUTF16("item0"),
ASCIIToUTF16("item1")};
InitEditableCombobox(items, /*filter_on_edit=*/false,
@@ -765,7 +806,18 @@ TEST_F(EditableComboboxTest, DragToSelectDoesntOpenTheMenuUntilDone) {
PerformMouseEvent(widget_, end_point, ui::ET_MOUSE_RELEASED);
ASSERT_EQ(ASCIIToUTF16("abc"),
combobox_->GetTextfieldForTest()->GetSelectedText());
- EXPECT_TRUE(IsMenuOpen());
+ EXPECT_FALSE(IsMenuOpen());
+}
+
+TEST_F(EditableComboboxTest, NoCrashWithoutWidget) {
+ std::vector<base::string16> items = {ASCIIToUTF16("item0"),
+ ASCIIToUTF16("item1")};
+ auto combobox = std::make_unique<EditableCombobox>(
+ std::make_unique<ui::SimpleComboboxModel>(items),
+ /*filter_on_edit=*/false,
+ /*show_on_empty=*/true, EditableCombobox::Type::kPassword);
+ // Showing the dropdown should silently fail.
+ combobox->RevealPasswords(true);
}
} // namespace
diff --git a/chromium/ui/views/controls/focus_ring.cc b/chromium/ui/views/controls/focus_ring.cc
index 95c79c95fd9..0fcf8e4ade1 100644
--- a/chromium/ui/views/controls/focus_ring.cc
+++ b/chromium/ui/views/controls/focus_ring.cc
@@ -25,13 +25,12 @@ double GetCornerRadius() {
} // namespace
-const char FocusRing::kViewClassName[] = "FocusRing";
-
// static
std::unique_ptr<FocusRing> FocusRing::Install(View* parent) {
auto ring = base::WrapUnique<FocusRing>(new FocusRing());
ring->set_owned_by_client();
parent->AddChildView(ring.get());
+ ring->EnableCanvasFlippingForRTLUI(parent->flip_canvas_on_paint_for_rtl_ui());
ring->InvalidateLayout();
ring->SchedulePaint();
return ring;
@@ -63,10 +62,6 @@ void FocusRing::SetColor(base::Optional<SkColor> color) {
SchedulePaint();
}
-const char* FocusRing::GetClassName() const {
- return kViewClassName;
-}
-
void FocusRing::Layout() {
// The focus ring handles its own sizing, which is simply to fill the parent
// and extend a little beyond its borders.
@@ -107,6 +102,8 @@ void FocusRing::OnPaint(gfx::Canvas* canvas) {
path = GetHighlightPath(parent());
DCHECK(IsPathUseable(path));
+ DCHECK_EQ(flip_canvas_on_paint_for_rtl_ui(),
+ parent()->flip_canvas_on_paint_for_rtl_ui());
SkRect bounds;
SkRRect rbounds;
if (path.isRect(&bounds)) {
@@ -179,4 +176,8 @@ SkPath GetHighlightPath(const View* view) {
return path;
}
+BEGIN_METADATA(FocusRing)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/focus_ring.h b/chromium/ui/views/controls/focus_ring.h
index f5e22f6d862..561e8ec57fc 100644
--- a/chromium/ui/views/controls/focus_ring.h
+++ b/chromium/ui/views/controls/focus_ring.h
@@ -37,7 +37,7 @@ namespace views {
// these take care of repainting it when the state changes.
class VIEWS_EXPORT FocusRing : public View, public ViewObserver {
public:
- static const char kViewClassName[];
+ METADATA_HEADER(FocusRing);
using ViewPredicate = std::function<bool(View* view)>;
@@ -77,7 +77,6 @@ class VIEWS_EXPORT FocusRing : public View, public ViewObserver {
void SetColor(base::Optional<SkColor> color);
// View:
- const char* GetClassName() const override;
void Layout() override;
void ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) override;
diff --git a/chromium/ui/views/controls/image_view.cc b/chromium/ui/views/controls/image_view.cc
index 2e9c4062526..8ca173c2233 100644
--- a/chromium/ui/views/controls/image_view.cc
+++ b/chromium/ui/views/controls/image_view.cc
@@ -23,9 +23,6 @@ void* GetBitmapPixels(const gfx::ImageSkia& img, float image_scale) {
} // namespace
-// static
-const char ImageView::kViewClassName[] = "ImageView";
-
ImageView::ImageView() = default;
ImageView::~ImageView() = default;
@@ -76,10 +73,6 @@ void ImageView::OnPaint(gfx::Canvas* canvas) {
OnPaintImage(canvas);
}
-const char* ImageView::GetClassName() const {
- return kViewClassName;
-}
-
void ImageView::OnPaintImage(gfx::Canvas* canvas) {
last_paint_scale_ = canvas->image_scale();
last_painted_bitmap_pixels_ = nullptr;
@@ -130,4 +123,8 @@ gfx::ImageSkia ImageView::GetPaintImage(float scale) {
return scaled_image_;
}
+BEGIN_METADATA(ImageView)
+METADATA_PARENT_CLASS(ImageViewBase)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/image_view.h b/chromium/ui/views/controls/image_view.h
index e80a97a34a1..0df833d88d7 100644
--- a/chromium/ui/views/controls/image_view.h
+++ b/chromium/ui/views/controls/image_view.h
@@ -27,8 +27,7 @@ namespace views {
/////////////////////////////////////////////////////////////////////////////
class VIEWS_EXPORT ImageView : public ImageViewBase {
public:
- // Internal class name.
- static const char kViewClassName[];
+ METADATA_HEADER(ImageView);
ImageView();
~ImageView() override;
@@ -47,7 +46,6 @@ class VIEWS_EXPORT ImageView : public ImageViewBase {
// Overridden from View:
void OnPaint(gfx::Canvas* canvas) override;
- const char* GetClassName() const override;
protected:
// Overridden from ImageViewBase:
diff --git a/chromium/ui/views/controls/image_view_base.h b/chromium/ui/views/controls/image_view_base.h
index 3784c9c0196..e8bc0b2196d 100644
--- a/chromium/ui/views/controls/image_view_base.h
+++ b/chromium/ui/views/controls/image_view_base.h
@@ -53,7 +53,6 @@ class VIEWS_EXPORT ImageViewBase : public View {
// Overridden from View:
void OnPaint(gfx::Canvas* canvas) override = 0;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
- const char* GetClassName() const override = 0;
base::string16 GetTooltipText(const gfx::Point& p) const override;
gfx::Size CalculatePreferredSize() const override;
views::PaintInfo::ScaleType GetPaintScaleType() const override;
diff --git a/chromium/ui/views/controls/image_view_unittest.cc b/chromium/ui/views/controls/image_view_unittest.cc
index 1ff073b62c5..f5b69ab8a92 100644
--- a/chromium/ui/views/controls/image_view_unittest.cc
+++ b/chromium/ui/views/controls/image_view_unittest.cc
@@ -51,9 +51,9 @@ class ImageViewTest : public ViewsTestBase,
widget_.Init(params);
View* container = new View();
// Make sure children can take up exactly as much space as they require.
- BoxLayout::Orientation orientation = GetParam() == Axis::kHorizontal
- ? BoxLayout::kHorizontal
- : BoxLayout::kVertical;
+ BoxLayout::Orientation orientation =
+ GetParam() == Axis::kHorizontal ? BoxLayout::Orientation::kHorizontal
+ : BoxLayout::Orientation::kVertical;
container->SetLayoutManager(std::make_unique<BoxLayout>(orientation));
widget_.SetContentsView(container);
diff --git a/chromium/ui/views/controls/label.cc b/chromium/ui/views/controls/label.cc
index 24d08c798ce..e2d51fc87b2 100644
--- a/chromium/ui/views/controls/label.cc
+++ b/chromium/ui/views/controls/label.cc
@@ -44,8 +44,6 @@ bool IsOpaque(SkColor color) {
namespace views {
-const char Label::kViewClassName[] = "Label";
-
Label::Label() : Label(base::string16()) {
}
@@ -82,19 +80,36 @@ void Label::SetFontList(const gfx::FontList& font_list) {
ResetLayout();
}
+const base::string16& Label::GetText() const {
+ return full_text_->text();
+}
+
void Label::SetText(const base::string16& new_text) {
- if (new_text == text())
+ if (new_text == GetText())
return;
full_text_->SetText(new_text);
- ResetLayout();
+ OnPropertyChanged(&new_text, kPropertyEffectsLayout);
stored_selection_range_ = gfx::Range::InvalidRange();
}
-void Label::SetAutoColorReadabilityEnabled(bool enabled) {
- if (auto_color_readability_ == enabled)
+int Label::GetTextContext() const {
+ return text_context_;
+}
+
+bool Label::GetAutoColorReadabilityEnabled() const {
+ return auto_color_readability_enabled_;
+}
+
+void Label::SetAutoColorReadabilityEnabled(
+ bool auto_color_readability_enabled) {
+ if (auto_color_readability_enabled_ == auto_color_readability_enabled)
return;
- auto_color_readability_ = enabled;
- RecalculateColors();
+ auto_color_readability_enabled_ = auto_color_readability_enabled;
+ OnPropertyChanged(&auto_color_readability_enabled_, kPropertyEffectsPaint);
+}
+
+SkColor Label::GetEnabledColor() const {
+ return actual_enabled_color_;
}
void Label::SetEnabledColor(SkColor color) {
@@ -102,7 +117,11 @@ void Label::SetEnabledColor(SkColor color) {
return;
requested_enabled_color_ = color;
enabled_color_set_ = true;
- RecalculateColors();
+ OnPropertyChanged(&requested_enabled_color_, kPropertyEffectsPaint);
+}
+
+SkColor Label::GetBackgroundColor() const {
+ return background_color_;
}
void Label::SetBackgroundColor(SkColor color) {
@@ -110,7 +129,11 @@ void Label::SetBackgroundColor(SkColor color) {
return;
background_color_ = color;
background_color_set_ = true;
- RecalculateColors();
+ OnPropertyChanged(&background_color_, kPropertyEffectsPaint);
+}
+
+SkColor Label::GetSelectionTextColor() const {
+ return actual_selection_text_color_;
}
void Label::SetSelectionTextColor(SkColor color) {
@@ -118,7 +141,11 @@ void Label::SetSelectionTextColor(SkColor color) {
return;
requested_selection_text_color_ = color;
selection_text_color_set_ = true;
- RecalculateColors();
+ OnPropertyChanged(&requested_selection_text_color_, kPropertyEffectsPaint);
+}
+
+SkColor Label::GetSelectionBackgroundColor() const {
+ return selection_background_color_;
}
void Label::SetSelectionBackgroundColor(SkColor color) {
@@ -126,7 +153,11 @@ void Label::SetSelectionBackgroundColor(SkColor color) {
return;
selection_background_color_ = color;
selection_background_color_set_ = true;
- RecalculateColors();
+ OnPropertyChanged(&selection_background_color_, kPropertyEffectsPaint);
+}
+
+const gfx::ShadowValues& Label::shadows() const {
+ return full_text_->shadows();
}
void Label::SetShadows(const gfx::ShadowValues& shadows) {
@@ -136,53 +167,82 @@ void Label::SetShadows(const gfx::ShadowValues& shadows) {
ResetLayout();
}
+bool Label::GetSubpixelRenderingEnabled() const {
+ return subpixel_rendering_enabled_;
+}
+
void Label::SetSubpixelRenderingEnabled(bool subpixel_rendering_enabled) {
if (subpixel_rendering_enabled_ == subpixel_rendering_enabled)
return;
subpixel_rendering_enabled_ = subpixel_rendering_enabled;
- RecalculateColors();
+ OnPropertyChanged(&subpixel_rendering_enabled_, kPropertyEffectsPaint);
+}
+
+gfx::HorizontalAlignment Label::GetHorizontalAlignment() const {
+ return full_text_->horizontal_alignment();
}
void Label::SetHorizontalAlignment(gfx::HorizontalAlignment alignment) {
alignment = gfx::MaybeFlipForRTL(alignment);
- if (horizontal_alignment() == alignment)
+ if (GetHorizontalAlignment() == alignment)
return;
full_text_->SetHorizontalAlignment(alignment);
ResetLayout();
}
+int Label::GetLineHeight() const {
+ return full_text_->min_line_height();
+}
+
void Label::SetLineHeight(int height) {
- if (line_height() == height)
+ if (GetLineHeight() == height)
return;
full_text_->SetMinLineHeight(height);
- ResetLayout();
+ OnPropertyChanged(&height, kPropertyEffectsLayout);
+}
+
+bool Label::GetMultiLine() const {
+ return multi_line_;
}
void Label::SetMultiLine(bool multi_line) {
DCHECK(!multi_line || (elide_behavior_ == gfx::ELIDE_TAIL ||
elide_behavior_ == gfx::NO_ELIDE));
- if (this->multi_line() == multi_line)
+ if (this->GetMultiLine() == multi_line)
return;
multi_line_ = multi_line;
full_text_->SetMultiline(multi_line);
full_text_->SetReplaceNewlineCharsWithSymbols(!multi_line);
- ResetLayout();
+ OnPropertyChanged(&multi_line_, kPropertyEffectsLayout);
+}
+
+int Label::GetMaxLines() const {
+ return max_lines_;
}
void Label::SetMaxLines(int max_lines) {
if (max_lines_ == max_lines)
return;
max_lines_ = max_lines;
- ResetLayout();
+ OnPropertyChanged(&max_lines_, kPropertyEffectsLayout);
+}
+
+bool Label::GetObscured() const {
+ return full_text_->obscured();
}
void Label::SetObscured(bool obscured) {
- if (this->obscured() == obscured)
+ if (this->GetObscured() == obscured)
return;
full_text_->SetObscured(obscured);
if (obscured)
SetSelectable(false);
- ResetLayout();
+ OnPropertyChanged(&obscured, kPropertyEffectsLayout);
+}
+
+bool Label::GetAllowCharacterBreak() const {
+ return full_text_->word_wrap_behavior() == gfx::WRAP_LONG_WORDS ? true
+ : false;
}
void Label::SetAllowCharacterBreak(bool allow_character_break) {
@@ -191,41 +251,75 @@ void Label::SetAllowCharacterBreak(bool allow_character_break) {
if (full_text_->word_wrap_behavior() == behavior)
return;
full_text_->SetWordWrapBehavior(behavior);
- if (multi_line()) {
- ResetLayout();
- }
+ OnPropertyChanged(&allow_character_break, kPropertyEffectsLayout);
+}
+
+gfx::ElideBehavior Label::GetElideBehavior() const {
+ return elide_behavior_;
}
void Label::SetElideBehavior(gfx::ElideBehavior elide_behavior) {
- DCHECK(!multi_line() || (elide_behavior_ == gfx::ELIDE_TAIL ||
- elide_behavior_ == gfx::NO_ELIDE));
+ DCHECK(!GetMultiLine() || (elide_behavior_ == gfx::ELIDE_TAIL ||
+ elide_behavior_ == gfx::NO_ELIDE));
if (elide_behavior_ == elide_behavior)
return;
elide_behavior_ = elide_behavior;
ResetLayout();
}
+base::string16 Label::GetTooltipText() const {
+ return tooltip_text_;
+}
+
void Label::SetTooltipText(const base::string16& tooltip_text) {
DCHECK(handles_tooltips_);
+ if (tooltip_text_ == tooltip_text)
+ return;
tooltip_text_ = tooltip_text;
+ OnPropertyChanged(&tooltip_text_, kPropertyEffectsNone);
+}
+
+bool Label::GetHandlesTooltips() const {
+ return handles_tooltips_;
}
void Label::SetHandlesTooltips(bool enabled) {
+ if (handles_tooltips_ == enabled)
+ return;
handles_tooltips_ = enabled;
+ OnPropertyChanged(&handles_tooltips_, kPropertyEffectsNone);
}
void Label::SizeToFit(int fixed_width) {
- DCHECK(multi_line());
+ DCHECK(GetMultiLine());
DCHECK_EQ(0, max_width_);
fixed_width_ = fixed_width;
SizeToPreferredSize();
}
+int Label::GetMaximumWidth() const {
+ return max_width_;
+}
+
void Label::SetMaximumWidth(int max_width) {
- DCHECK(multi_line());
+ DCHECK(GetMultiLine());
DCHECK_EQ(0, fixed_width_);
+ if (max_width_ == max_width)
+ return;
max_width_ = max_width;
- SizeToPreferredSize();
+ OnPropertyChanged(&max_width_, kPropertyEffectsPreferredSizeChanged);
+}
+
+bool Label::GetCollapseWhenHidden() const {
+ return collapse_when_hidden_;
+}
+
+void Label::SetCollapseWhenHidden(bool value) {
+ if (collapse_when_hidden_ == value)
+ return;
+ collapse_when_hidden_ = value;
+ OnPropertyChanged(&collapse_when_hidden_,
+ kPropertyEffectsPreferredSizeChanged);
}
size_t Label::GetRequiredLines() const {
@@ -243,11 +337,15 @@ base::i18n::TextDirection Label::GetTextDirectionForTesting() {
}
bool Label::IsSelectionSupported() const {
- return !obscured() && full_text_->IsSelectionSupported();
+ return !GetObscured() && full_text_->IsSelectionSupported();
+}
+
+bool Label::GetSelectable() const {
+ return !!selection_controller_;
}
bool Label::SetSelectable(bool value) {
- if (value == selectable())
+ if (value == GetSelectable())
return true;
if (!value) {
@@ -305,17 +403,17 @@ gfx::Size Label::CalculatePreferredSize() const {
if (!GetVisible() && collapse_when_hidden_)
return gfx::Size();
- if (multi_line() && fixed_width_ != 0 && !text().empty())
+ if (GetMultiLine() && fixed_width_ != 0 && !GetText().empty())
return gfx::Size(fixed_width_, GetHeightForWidth(fixed_width_));
gfx::Size size(GetTextSize());
const gfx::Insets insets = GetInsets();
size.Enlarge(insets.width(), insets.height());
- if (multi_line() && max_width_ != 0 && max_width_ < size.width())
+ if (GetMultiLine() && max_width_ != 0 && max_width_ < size.width())
return gfx::Size(max_width_, GetHeightForWidth(max_width_));
- if (multi_line() && max_lines() > 0)
+ if (GetMultiLine() && GetMaxLines() > 0)
return gfx::Size(size.width(), GetHeightForWidth(size.width()));
return size;
}
@@ -333,7 +431,7 @@ gfx::Size Label::GetMinimumSize() const {
base::string16(gfx::kEllipsisUTF16), font_list()));
}
- if (!multi_line()) {
+ if (!GetMultiLine()) {
if (elide_behavior_ == gfx::NO_ELIDE) {
// If elision is disabled on single-line Labels, use text size as minimum.
// This is OK because clients can use |gfx::ElideBehavior::TRUNCATE|
@@ -353,8 +451,8 @@ 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) {
+ int base_line_height = std::max(GetLineHeight(), font_list().GetHeight());
+ if (!GetMultiLine() || GetText().empty() || w <= 0) {
height = base_line_height;
} else {
// SetDisplayRect() has a side effect for later calls of GetStringSize().
@@ -365,10 +463,10 @@ int Label::GetHeightForWidth(int w) const {
// and |full_text_| can cache the height.
full_text_->SetDisplayRect(gfx::Rect(0, 0, w, 0));
int string_height = full_text_->GetStringSize().height();
- // Cap the number of lines to |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)
+ // Cap the number of lines to |GetMaxLines()| if multi-line and non-zero
+ // |GetMaxLines()|.
+ height = GetMultiLine() && GetMaxLines() > 0
+ ? std::min(GetMaxLines() * base_line_height, string_height)
: string_height;
}
height -= gfx::ShadowValue::GetMargin(full_text_->shadows()).height();
@@ -379,10 +477,6 @@ void Label::Layout() {
ClearDisplayText();
}
-const char* Label::GetClassName() const {
- return kViewClassName;
-}
-
View* Label::GetTooltipHandlerForPoint(const gfx::Point& point) {
if (!handles_tooltips_ ||
(tooltip_text_.empty() && !ShouldShowDefaultTooltip()))
@@ -420,29 +514,38 @@ base::string16 Label::GetTooltipText(const gfx::Point& p) const {
return base::string16();
}
+void Label::OnHandlePropertyChangeEffects(PropertyEffects property_effects) {
+ if (property_effects & kPropertyEffectsPreferredSizeChanged)
+ SizeToPreferredSize();
+ if (property_effects & kPropertyEffectsLayout)
+ ResetLayout();
+ if (property_effects & kPropertyEffectsPaint)
+ RecalculateColors();
+}
+
std::unique_ptr<gfx::RenderText> Label::CreateRenderText() const {
// 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() && (elide_behavior_ != gfx::NO_ELIDE) ? gfx::ELIDE_TAIL
- : elide_behavior_;
+ GetMultiLine() && (elide_behavior_ != gfx::NO_ELIDE) ? gfx::ELIDE_TAIL
+ : elide_behavior_;
auto render_text = gfx::RenderText::CreateHarfBuzzInstance();
- render_text->SetHorizontalAlignment(horizontal_alignment());
+ render_text->SetHorizontalAlignment(GetHorizontalAlignment());
render_text->SetDirectionalityMode(full_text_->directionality_mode());
render_text->SetElideBehavior(elide_behavior);
- render_text->SetObscured(obscured());
- render_text->SetMinLineHeight(line_height());
+ render_text->SetObscured(GetObscured());
+ render_text->SetMinLineHeight(GetLineHeight());
render_text->SetFontList(font_list());
render_text->set_shadows(shadows());
render_text->SetCursorEnabled(false);
- render_text->SetText(text());
- render_text->SetMultiline(multi_line());
- render_text->SetMaxLines(multi_line() ? max_lines() : 0);
+ render_text->SetText(GetText());
+ render_text->SetMultiline(GetMultiLine());
+ render_text->SetMaxLines(GetMultiLine() ? GetMaxLines() : 0);
render_text->SetWordWrapBehavior(full_text_->word_wrap_behavior());
// Setup render text for selection controller.
- if (selectable()) {
+ if (GetSelectable()) {
render_text->set_focused(HasFocus());
if (stored_selection_range_.IsValid())
render_text->SelectRange(stored_selection_range_);
@@ -601,7 +704,7 @@ bool Label::OnKeyPressed(const ui::KeyEvent& event) {
}
break;
case ui::VKEY_A:
- if (control && !alt && !text().empty()) {
+ if (control && !alt && !GetText().empty()) {
SelectAll();
DCHECK(HasSelection());
UpdateSelectionClipboard();
@@ -734,8 +837,8 @@ bool Label::PasteSelectionClipboard() {
void Label::UpdateSelectionClipboard() {
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
- if (!obscured()) {
- ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_SELECTION)
+ if (!GetObscured()) {
+ ui::ScopedClipboardWriter(ui::ClipboardType::kSelection)
.WriteText(GetSelectedText());
}
#endif
@@ -748,9 +851,9 @@ bool Label::IsCommandIdChecked(int command_id) const {
bool Label::IsCommandIdEnabled(int command_id) const {
switch (command_id) {
case IDS_APP_COPY:
- return HasSelection() && !obscured();
+ return HasSelection() && !GetObscured();
case IDS_APP_SELECT_ALL:
- return GetRenderTextForSelectionController() && !text().empty();
+ return GetRenderTextForSelectionController() && !GetText().empty();
}
return false;
}
@@ -787,7 +890,7 @@ bool Label::GetAcceleratorForCommandId(int command_id,
}
const gfx::RenderText* Label::GetRenderTextForSelectionController() const {
- if (!selectable())
+ if (!GetSelectable())
return nullptr;
MaybeBuildDisplayText();
@@ -814,7 +917,7 @@ void Label::Init(const base::string16& text,
enabled_color_set_ = background_color_set_ = false;
selection_text_color_set_ = selection_background_color_set_ = false;
subpixel_rendering_enabled_ = true;
- auto_color_readability_ = true;
+ auto_color_readability_enabled_ = true;
multi_line_ = false;
max_lines_ = 0;
UpdateColorsFromTheme();
@@ -857,8 +960,8 @@ void Label::MaybeBuildDisplayText() const {
gfx::Size Label::GetTextSize() const {
gfx::Size size;
- if (text().empty()) {
- size = gfx::Size(0, std::max(line_height(), font_list().GetHeight()));
+ if (GetText().empty()) {
+ size = gfx::Size(0, std::max(GetLineHeight(), font_list().GetHeight()));
} else {
// Cancel the display rect of |full_text_|. The display rect may be
// specified in GetHeightForWidth(), and specifying empty Rect cancels
@@ -876,7 +979,7 @@ gfx::Size Label::GetTextSize() const {
SkColor Label::GetForegroundColor(SkColor foreground,
SkColor background) const {
- return (auto_color_readability_ && IsOpaque(background))
+ return (auto_color_readability_enabled_ && IsOpaque(background))
? color_utils::BlendForMinContrast(foreground, background).color
: foreground;
}
@@ -933,8 +1036,9 @@ void Label::UpdateColorsFromTheme() {
bool Label::ShouldShowDefaultTooltip() const {
const gfx::Size text_size = GetTextSize();
const gfx::Size size = GetContentsBounds().size();
- return !obscured() && (text_size.width() > size.width() ||
- (multi_line() && text_size.height() > size.height()));
+ return !GetObscured() &&
+ (text_size.width() > size.width() ||
+ (GetMultiLine() && text_size.height() > size.height()));
}
void Label::ClearDisplayText() const {
@@ -958,9 +1062,9 @@ base::string16 Label::GetSelectedText() const {
}
void Label::CopyToClipboard() {
- if (!HasSelection() || obscured())
+ if (!HasSelection() || GetObscured())
return;
- ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_COPY_PASTE)
+ ui::ScopedClipboardWriter(ui::ClipboardType::kCopyPaste)
.WriteText(GetSelectedText());
}
@@ -970,4 +1074,25 @@ void Label::BuildContextMenuContents() {
IDS_APP_SELECT_ALL);
}
+BEGIN_METADATA(Label)
+METADATA_PARENT_CLASS(View)
+ADD_PROPERTY_METADATA(Label, bool, AutoColorReadabilityEnabled)
+ADD_PROPERTY_METADATA(Label, base::string16, Text)
+ADD_PROPERTY_METADATA(Label, SkColor, EnabledColor)
+ADD_PROPERTY_METADATA(Label, SkColor, BackgroundColor)
+ADD_PROPERTY_METADATA(Label, SkColor, SelectionTextColor)
+ADD_PROPERTY_METADATA(Label, SkColor, SelectionBackgroundColor)
+ADD_PROPERTY_METADATA(Label, bool, SubpixelRenderingEnabled)
+ADD_PROPERTY_METADATA(Label, int, LineHeight)
+ADD_PROPERTY_METADATA(Label, bool, MultiLine)
+ADD_PROPERTY_METADATA(Label, int, MaxLines)
+ADD_PROPERTY_METADATA(Label, bool, Obscured)
+ADD_PROPERTY_METADATA(Label, bool, AllowCharacterBreak)
+ADD_PROPERTY_METADATA(Label, base::string16, TooltipText)
+ADD_PROPERTY_METADATA(Label, bool, HandlesTooltips)
+ADD_PROPERTY_METADATA(Label, bool, CollapseWhenHidden)
+ADD_PROPERTY_METADATA(Label, int, MaximumWidth)
+ADD_READONLY_PROPERTY_METADATA(Label, int, TextContext)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/label.h b/chromium/ui/views/controls/label.h
index 50e30e5cf35..ce169b164bc 100644
--- a/chromium/ui/views/controls/label.h
+++ b/chromium/ui/views/controls/label.h
@@ -14,6 +14,7 @@
#include "ui/gfx/render_text.h"
#include "ui/gfx/text_constants.h"
#include "ui/views/context_menu_controller.h"
+#include "ui/views/metadata/metadata_header_macros.h"
#include "ui/views/selection_controller_delegate.h"
#include "ui/views/style/typography.h"
#include "ui/views/view.h"
@@ -31,8 +32,7 @@ class VIEWS_EXPORT Label : public View,
public SelectionControllerDelegate,
public ui::SimpleMenuModel::Delegate {
public:
- // Internal class name.
- static const char kViewClassName[];
+ METADATA_HEADER(Label);
// Helper to construct a Label that doesn't use the views typography spec.
// Using this causes Label to obtain colors from ui::NativeTheme and line
@@ -77,72 +77,71 @@ class VIEWS_EXPORT Label : public View,
virtual void SetFontList(const gfx::FontList& font_list);
// Get or set the label text.
- const base::string16& text() const { return full_text_->text(); }
+ const base::string16& GetText() const;
virtual void SetText(const base::string16& text);
// Where the label appears in the UI. Passed in from the constructor. This is
// a value from views::style::TextContext or an enum that extends it.
- int text_context() const { return text_context_; }
+ int GetTextContext() const;
// Enables or disables auto-color-readability (enabled by default). If this
// is enabled, then calls to set any foreground or background color will
// trigger an automatic mapper that uses color_utils::BlendForMinContrast()
// to ensure that the foreground colors are readable over the background
// color.
+ bool GetAutoColorReadabilityEnabled() const;
void SetAutoColorReadabilityEnabled(bool enabled);
- // Sets the color. This will automatically force the color to be readable
- // over the current background color, if auto color readability is enabled.
+ // Gets/Sets the color. This will automatically force the color to be
+ // readable over the current background color, if auto color readability is
+ // enabled.
+ SkColor GetEnabledColor() const;
virtual void SetEnabledColor(SkColor color);
- SkColor enabled_color() const { return actual_enabled_color_; }
-
- // Sets the background color. This won't be explicitly drawn, but the label
- // will force the text color to be readable over it.
+ // Gets/Sets the background color. This won't be explicitly drawn, but the
+ // label will force the text color to be readable over it.
+ SkColor GetBackgroundColor() const;
void SetBackgroundColor(SkColor color);
- SkColor background_color() const { return background_color_; }
- // Sets the selection text color. This will automatically force the color to
- // be readable over the selection background color, if auto color readability
- // is enabled. Initialized with system default.
+ // Gets/Sets the selection text color. This will automatically force the color
+ // to be readable over the selection background color, if auto color
+ // readability is enabled. Initialized with system default.
+ SkColor GetSelectionTextColor() const;
void SetSelectionTextColor(SkColor color);
- SkColor selection_text_color() const { return actual_selection_text_color_; }
- // Sets the selection background color. Initialized with system default.
+ // Gets/Sets the selection background color. Initialized with system default.
+ SkColor GetSelectionBackgroundColor() const;
void SetSelectionBackgroundColor(SkColor color);
- SkColor selection_background_color() const {
- return selection_background_color_;
- }
- // Set drop shadows underneath the text.
+ // Get/Set drop shadows underneath the text.
+ const gfx::ShadowValues& shadows() const;
void SetShadows(const gfx::ShadowValues& shadows);
- const gfx::ShadowValues& shadows() const { return full_text_->shadows(); }
- // Sets whether subpixel rendering is used; the default is true, but this
+ // Gets/Sets whether subpixel rendering is used; the default is true, but this
// feature also requires an opaque background color.
// TODO(mukai): rename this as SetSubpixelRenderingSuppressed() to keep the
// consistency with RenderText field name.
+ bool GetSubpixelRenderingEnabled() const;
void SetSubpixelRenderingEnabled(bool subpixel_rendering_enabled);
- // Sets the horizontal alignment; the argument value is mirrored in RTL UI.
+ // Gets/Sets the horizontal alignment; the argument value is mirrored in RTL
+ // UI.
+ gfx::HorizontalAlignment GetHorizontalAlignment() const;
void SetHorizontalAlignment(gfx::HorizontalAlignment alignment);
- gfx::HorizontalAlignment horizontal_alignment() const {
- return full_text_->horizontal_alignment();
- }
// Get or set the distance in pixels between baselines of multi-line text.
// Default is 0, indicating the distance between lines should be the standard
// one for the label's text, font list, and platform.
- int line_height() const { return full_text_->min_line_height(); }
+ int GetLineHeight() const;
void SetLineHeight(int height);
// Get or set if the label text can wrap on multiple lines; default is false.
- bool multi_line() const { return multi_line_; }
+ bool GetMultiLine() const;
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_; }
+ int GetMaxLines() const;
void SetMaxLines(int max_lines);
// Returns the number of lines required to render all text. The actual number
@@ -151,28 +150,31 @@ class VIEWS_EXPORT Label : public View,
// 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 full_text_->obscured(); }
+ bool GetObscured() const;
void SetObscured(bool obscured);
- // Sets whether multi-line text can wrap mid-word; the default is false.
+ // Gets/Sets whether multi-line text can wrap mid-word; the default is false.
// TODO(mukai): allow specifying WordWrapBehavior.
+ bool GetAllowCharacterBreak() const;
void SetAllowCharacterBreak(bool allow_character_break);
- // Sets the eliding or fading behavior, applied as necessary. The default is
- // to elide at the end. Eliding is not well-supported for multi-line labels.
+ // Gets/Sets the eliding or fading behavior, applied as necessary. The default
+ // is to elide at the end. Eliding is not well-supported for multi-line
+ // labels.
+ gfx::ElideBehavior GetElideBehavior() const;
void SetElideBehavior(gfx::ElideBehavior elide_behavior);
- gfx::ElideBehavior elide_behavior() const { return elide_behavior_; }
- // Sets the tooltip text. Default behavior for a label (single-line) is to
- // show the full text if it is wider than its bounds. Calling this overrides
- // the default behavior and lets you set a custom tooltip. To revert to
- // default behavior, call this with an empty string.
+ // Gets/Sets the tooltip text. Default behavior for a label (single-line) is
+ // to show the full text if it is wider than its bounds. Calling this
+ // overrides the default behavior and lets you set a custom tooltip. To
+ // revert to default behavior, call this with an empty string.
+ base::string16 GetTooltipText() const;
void SetTooltipText(const base::string16& tooltip_text);
// Get or set whether this label can act as a tooltip handler; the default is
// true. Set to false whenever an ancestor view should handle tooltips
// instead.
- bool handles_tooltips() const { return handles_tooltips_; }
+ bool GetHandlesTooltips() const;
void SetHandlesTooltips(bool enabled);
// Resizes the label so its width is set to the fixed width and its height
@@ -185,10 +187,13 @@ class VIEWS_EXPORT Label : public View,
void SizeToFit(int fixed_width);
// Like SizeToFit, but uses a smaller width if possible.
+ int GetMaximumWidth() const;
void SetMaximumWidth(int max_width);
- // Sets whether the preferred size is empty when the label is not visible.
- void set_collapse_when_hidden(bool value) { collapse_when_hidden_ = value; }
+ // Gets/Sets whether the preferred size is empty when the label is not
+ // visible.
+ bool GetCollapseWhenHidden() const;
+ void SetCollapseWhenHidden(bool value);
// Get the text as displayed to the user, respecting the obscured flag.
base::string16 GetDisplayTextForTesting();
@@ -204,7 +209,7 @@ class VIEWS_EXPORT Label : public View,
virtual bool IsSelectionSupported() const;
// Returns true if the label is selectable. Default is false.
- bool selectable() const { return !!selection_controller_; }
+ bool GetSelectable() const;
// Sets whether the label is selectable. False is returned if the call fails,
// i.e. when selection is not supported but |selectable| is true. For example,
@@ -230,12 +235,12 @@ class VIEWS_EXPORT Label : public View,
gfx::Size GetMinimumSize() const override;
int GetHeightForWidth(int w) const override;
void Layout() override;
- const char* GetClassName() const override;
View* GetTooltipHandlerForPoint(const gfx::Point& point) override;
bool CanProcessEventsWithinSubtree() const override;
WordLookupClient* GetWordLookupClient() override;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
base::string16 GetTooltipText(const gfx::Point& p) const override;
+ void OnHandlePropertyChangeEffects(PropertyEffects property_effects) override;
protected:
// Create a single RenderText instance to actually be painted.
@@ -381,7 +386,7 @@ class VIEWS_EXPORT Label : public View,
gfx::ElideBehavior elide_behavior_;
bool subpixel_rendering_enabled_;
- bool auto_color_readability_;
+ bool auto_color_readability_enabled_;
// TODO(mukai): remove |multi_line_| when all RenderText can render multiline.
bool multi_line_;
int max_lines_;
diff --git a/chromium/ui/views/controls/label_unittest.cc b/chromium/ui/views/controls/label_unittest.cc
index 2cab103de88..847e8c76124 100644
--- a/chromium/ui/views/controls/label_unittest.cc
+++ b/chromium/ui/views/controls/label_unittest.cc
@@ -286,14 +286,14 @@ TEST_F(LabelTest, FontPropertyArial) {
TEST_F(LabelTest, TextProperty) {
base::string16 test_text(ASCIIToUTF16("A random string."));
label()->SetText(test_text);
- EXPECT_EQ(test_text, label()->text());
+ EXPECT_EQ(test_text, label()->GetText());
}
TEST_F(LabelTest, ColorProperty) {
SkColor color = SkColorSetARGB(20, 40, 10, 5);
label()->SetAutoColorReadabilityEnabled(false);
label()->SetEnabledColor(color);
- EXPECT_EQ(color, label()->enabled_color());
+ EXPECT_EQ(color, label()->GetEnabledColor());
}
TEST_F(LabelTest, AlignmentProperty) {
@@ -307,18 +307,18 @@ TEST_F(LabelTest, AlignmentProperty) {
// The alignment should be flipped in RTL UI.
label()->SetHorizontalAlignment(gfx::ALIGN_RIGHT);
EXPECT_EQ(reverse_alignment ? gfx::ALIGN_LEFT : gfx::ALIGN_RIGHT,
- label()->horizontal_alignment());
+ label()->GetHorizontalAlignment());
label()->SetHorizontalAlignment(gfx::ALIGN_LEFT);
EXPECT_EQ(reverse_alignment ? gfx::ALIGN_RIGHT : gfx::ALIGN_LEFT,
- label()->horizontal_alignment());
+ label()->GetHorizontalAlignment());
label()->SetHorizontalAlignment(gfx::ALIGN_CENTER);
- EXPECT_EQ(gfx::ALIGN_CENTER, label()->horizontal_alignment());
+ EXPECT_EQ(gfx::ALIGN_CENTER, label()->GetHorizontalAlignment());
for (size_t j = 0; j < 2; ++j) {
label()->SetHorizontalAlignment(gfx::ALIGN_TO_HEAD);
const bool rtl = j == 0;
label()->SetText(rtl ? base::WideToUTF16(L"\x5d0") : ASCIIToUTF16("A"));
- EXPECT_EQ(gfx::ALIGN_TO_HEAD, label()->horizontal_alignment());
+ EXPECT_EQ(gfx::ALIGN_TO_HEAD, label()->GetHorizontalAlignment());
}
}
@@ -328,7 +328,7 @@ TEST_F(LabelTest, AlignmentProperty) {
TEST_F(LabelTest, ElideBehavior) {
base::string16 text(ASCIIToUTF16("This is example text."));
label()->SetText(text);
- EXPECT_EQ(gfx::ELIDE_TAIL, label()->elide_behavior());
+ EXPECT_EQ(gfx::ELIDE_TAIL, label()->GetElideBehavior());
gfx::Size size = label()->GetPreferredSize();
label()->SetBoundsRect(gfx::Rect(size));
EXPECT_EQ(text, label()->GetDisplayTextForTesting());
@@ -348,7 +348,7 @@ TEST_F(LabelTest, ElideBehaviorMinimumWidth) {
label()->SetText(text);
// Default should be |gfx::ELIDE_TAIL|.
- EXPECT_EQ(gfx::ELIDE_TAIL, label()->elide_behavior());
+ EXPECT_EQ(gfx::ELIDE_TAIL, label()->GetElideBehavior());
gfx::Size size = label()->GetMinimumSize();
// Elidable labels have a minimum width that fits |gfx::kEllipsisUTF16|.
EXPECT_EQ(gfx::Canvas::GetStringWidth(base::string16(gfx::kEllipsisUTF16),
@@ -367,7 +367,7 @@ TEST_F(LabelTest, ElideBehaviorMinimumWidth) {
// Non-elidable single-line labels should take up their full text size, since
// this behavior implies the text should not be cut off.
- EXPECT_FALSE(label()->multi_line());
+ EXPECT_FALSE(label()->GetMultiLine());
label()->SetElideBehavior(gfx::NO_ELIDE);
size = label()->GetMinimumSize();
EXPECT_EQ(text.length(), label()->GetDisplayTextForTesting().length());
@@ -377,11 +377,11 @@ TEST_F(LabelTest, ElideBehaviorMinimumWidth) {
}
TEST_F(LabelTest, MultiLineProperty) {
- EXPECT_FALSE(label()->multi_line());
+ EXPECT_FALSE(label()->GetMultiLine());
label()->SetMultiLine(true);
- EXPECT_TRUE(label()->multi_line());
+ EXPECT_TRUE(label()->GetMultiLine());
label()->SetMultiLine(false);
- EXPECT_FALSE(label()->multi_line());
+ EXPECT_FALSE(label()->GetMultiLine());
}
TEST_F(LabelTest, ObscuredProperty) {
@@ -390,30 +390,30 @@ TEST_F(LabelTest, ObscuredProperty) {
label()->SizeToPreferredSize();
// The text should be unobscured by default.
- EXPECT_FALSE(label()->obscured());
+ EXPECT_FALSE(label()->GetObscured());
EXPECT_EQ(test_text, label()->GetDisplayTextForTesting());
- EXPECT_EQ(test_text, label()->text());
+ EXPECT_EQ(test_text, label()->GetText());
label()->SetObscured(true);
label()->SizeToPreferredSize();
- EXPECT_TRUE(label()->obscured());
+ EXPECT_TRUE(label()->GetObscured());
EXPECT_EQ(base::string16(test_text.size(),
gfx::RenderText::kPasswordReplacementChar),
label()->GetDisplayTextForTesting());
- EXPECT_EQ(test_text, label()->text());
+ EXPECT_EQ(test_text, label()->GetText());
label()->SetText(test_text + test_text);
label()->SizeToPreferredSize();
EXPECT_EQ(base::string16(test_text.size() * 2,
gfx::RenderText::kPasswordReplacementChar),
label()->GetDisplayTextForTesting());
- EXPECT_EQ(test_text + test_text, label()->text());
+ EXPECT_EQ(test_text + test_text, label()->GetText());
label()->SetObscured(false);
label()->SizeToPreferredSize();
- EXPECT_FALSE(label()->obscured());
+ EXPECT_FALSE(label()->GetObscured());
EXPECT_EQ(test_text + test_text, label()->GetDisplayTextForTesting());
- EXPECT_EQ(test_text + test_text, label()->text());
+ EXPECT_EQ(test_text + test_text, label()->GetText());
}
TEST_F(LabelTest, ObscuredSurrogatePair) {
@@ -425,7 +425,7 @@ TEST_F(LabelTest, ObscuredSurrogatePair) {
label()->SizeToPreferredSize();
EXPECT_EQ(base::string16(1, gfx::RenderText::kPasswordReplacementChar),
label()->GetDisplayTextForTesting());
- EXPECT_EQ(test_text, label()->text());
+ EXPECT_EQ(test_text, label()->GetText());
}
// This test case verifies the label preferred size will change based on the
@@ -456,7 +456,7 @@ TEST_F(LabelTest, TooltipProperty) {
// Initially, label has no bounds, its text does not fit, and therefore its
// text should be returned as the tooltip text.
- EXPECT_EQ(label()->text(), label()->GetTooltipText(gfx::Point()));
+ EXPECT_EQ(label()->GetText(), label()->GetTooltipText(gfx::Point()));
// While tooltip handling is disabled, GetTooltipText() should fail.
label()->SetHandlesTooltips(false);
@@ -477,7 +477,7 @@ TEST_F(LabelTest, TooltipProperty) {
// When the tooltip text is set to an empty string, the original behavior is
// restored.
label()->SetTooltipText(base::string16());
- EXPECT_EQ(label()->text(), label()->GetTooltipText(gfx::Point()));
+ EXPECT_EQ(label()->GetText(), label()->GetTooltipText(gfx::Point()));
// While tooltip handling is disabled, GetTooltipText() should fail.
label()->SetHandlesTooltips(false);
@@ -531,7 +531,7 @@ TEST_F(LabelTest, Accessibility) {
ui::AXNodeData node_data;
label()->GetAccessibleNodeData(&node_data);
EXPECT_EQ(ax::mojom::Role::kStaticText, node_data.role);
- EXPECT_EQ(label()->text(),
+ EXPECT_EQ(label()->GetText(),
node_data.GetString16Attribute(ax::mojom::StringAttribute::kName));
EXPECT_FALSE(
node_data.HasIntAttribute(ax::mojom::IntAttribute::kRestriction));
@@ -557,7 +557,7 @@ TEST_F(LabelTest, TextChangeWithoutLayout) {
TEST_F(LabelTest, EmptyLabelSizing) {
const gfx::Size expected_size(0, label()->font_list().GetHeight());
EXPECT_EQ(expected_size, label()->GetPreferredSize());
- label()->SetMultiLine(!label()->multi_line());
+ label()->SetMultiLine(!label()->GetMultiLine());
EXPECT_EQ(expected_size, label()->GetPreferredSize());
}
@@ -768,7 +768,7 @@ TEST_F(LabelTest, GetTooltipHandlerForPoint) {
label()->SetBounds(0, 0, 10, 10);
// By default, labels start out as tooltip handlers.
- ASSERT_TRUE(label()->handles_tooltips());
+ ASSERT_TRUE(label()->GetHandlesTooltips());
// There's a default tooltip if the text is too big to fit.
EXPECT_EQ(label(), label()->GetTooltipHandlerForPoint(gfx::Point(2, 2)));
@@ -827,7 +827,7 @@ TEST_F(LabelTest, ResetRenderTextData) {
// Querying fields or size information should not recompute the layout
// unnecessarily.
- EXPECT_EQ(ASCIIToUTF16("Example"), label()->text());
+ EXPECT_EQ(ASCIIToUTF16("Example"), label()->GetText());
EXPECT_FALSE(label()->display_text_);
EXPECT_EQ(preferred_size, label()->GetPreferredSize());
@@ -879,7 +879,7 @@ TEST_F(LabelTest, NoSchedulePaintInOnPaint) {
label.SetEnabled(false);
EXPECT_TRUE(Increased(label.schedule_paint_count(), &count));
- label.SetText(label.text() + ASCIIToUTF16("Changed"));
+ label.SetText(label.GetText() + ASCIIToUTF16("Changed"));
EXPECT_TRUE(Increased(label.schedule_paint_count(), &count));
label.SizeToPreferredSize();
@@ -946,20 +946,20 @@ TEST_F(LabelTest, DefaultDirectionalityIsFromText) {
TEST_F(LabelSelectionTest, Selectable) {
// By default, labels don't support text selection.
- EXPECT_FALSE(label()->selectable());
+ EXPECT_FALSE(label()->GetSelectable());
ASSERT_TRUE(label()->SetSelectable(true));
- EXPECT_TRUE(label()->selectable());
+ EXPECT_TRUE(label()->GetSelectable());
// Verify that making a label multiline still causes the label to support text
// selection.
label()->SetMultiLine(true);
- EXPECT_TRUE(label()->selectable());
+ EXPECT_TRUE(label()->GetSelectable());
// Verify that obscuring the label text causes the label to not support text
// selection.
label()->SetObscured(true);
- EXPECT_FALSE(label()->selectable());
+ EXPECT_FALSE(label()->GetSelectable());
}
// Verify that labels supporting text selection get focus on clicks.
@@ -1022,7 +1022,7 @@ TEST_F(LabelSelectionTest, DoubleTripleClick) {
// Triple clicking should select all the text.
PerformClick(GetCursorPoint(0));
- EXPECT_EQ(label()->text(), GetSelectedText());
+ EXPECT_EQ(label()->GetText(), GetSelectedText());
// Clicking again should alternate to double click.
PerformClick(GetCursorPoint(0));
@@ -1053,7 +1053,7 @@ TEST_F(LabelSelectionTest, MouseDrag) {
EXPECT_STR_EQ(" mouse drag", GetSelectedText());
event_generator()->PressKey(ui::VKEY_C, kControlCommandModifier);
- EXPECT_STR_EQ(" mouse drag", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
+ EXPECT_STR_EQ(" mouse drag", GetClipboardText(ui::ClipboardType::kCopyPaste));
}
TEST_F(LabelSelectionTest, MouseDragMultilineLTR) {
@@ -1138,7 +1138,8 @@ TEST_F(LabelSelectionTest, MouseDragMultilineRTL) {
label()->SetMultiLine(true);
label()->SetText(ToRTL("012\n345"));
// Sanity check.
- EXPECT_EQ(WideToUTF16(L"\x5d0\x5d1\x5d2\n\x5d3\x5d4\x5d5"), label()->text());
+ EXPECT_EQ(WideToUTF16(L"\x5d0\x5d1\x5d2\n\x5d3\x5d4\x5d5"),
+ label()->GetText());
label()->SizeToPreferredSize();
ASSERT_TRUE(label()->SetSelectable(true));
@@ -1249,14 +1250,14 @@ TEST_F(LabelSelectionTest, SelectionClipboard) {
// selection clipboard.
label()->SelectRange(gfx::Range(2, 5));
EXPECT_STR_EQ("bel", GetSelectedText());
- EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION).empty());
+ EXPECT_TRUE(GetClipboardText(ui::ClipboardType::kSelection).empty());
// Verify text selection using the mouse updates the selection clipboard.
PerformMousePress(GetCursorPoint(5));
PerformMouseDragTo(GetCursorPoint(0));
PerformMouseRelease(GetCursorPoint(0));
EXPECT_STR_EQ("Label", GetSelectedText());
- EXPECT_STR_EQ("Label", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
+ EXPECT_STR_EQ("Label", GetClipboardText(ui::ClipboardType::kSelection));
}
#endif
@@ -1275,7 +1276,7 @@ TEST_F(LabelSelectionTest, KeyboardActions) {
EXPECT_EQ(initial_text, GetSelectedText());
event_generator()->PressKey(ui::VKEY_C, kControlCommandModifier);
- EXPECT_EQ(initial_text, GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
+ EXPECT_EQ(initial_text, GetClipboardText(ui::ClipboardType::kCopyPaste));
// The selection should get cleared on changing the text, but focus should not
// be affected.
@@ -1286,7 +1287,7 @@ TEST_F(LabelSelectionTest, KeyboardActions) {
// Obscured labels do not support text selection.
label()->SetObscured(true);
- EXPECT_FALSE(label()->selectable());
+ EXPECT_FALSE(label()->GetSelectable());
event_generator()->PressKey(ui::VKEY_A, kControlCommandModifier);
EXPECT_EQ(base::string16(), GetSelectedText());
}
@@ -1318,7 +1319,7 @@ TEST_F(LabelSelectionTest, ContextMenuContents) {
// An obscured label would not show a context menu and both COPY and
// SELECT_ALL should be disabled for it.
label()->SetObscured(true);
- EXPECT_FALSE(label()->selectable());
+ EXPECT_FALSE(label()->GetSelectable());
EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_COPY));
EXPECT_FALSE(IsMenuCommandEnabled(IDS_APP_SELECT_ALL));
label()->SetObscured(false);
diff --git a/chromium/ui/views/controls/link.cc b/chromium/ui/views/controls/link.cc
index 476a77af1ca..9b200179b8a 100644
--- a/chromium/ui/views/controls/link.cc
+++ b/chromium/ui/views/controls/link.cc
@@ -23,7 +23,6 @@
namespace views {
-const char Link::kViewClassName[] = "Link";
constexpr int Link::kFocusBorderPadding;
Link::Link(const base::string16& title, int text_context, int text_style)
@@ -61,16 +60,12 @@ gfx::Insets Link::GetInsets() const {
gfx::Insets insets = Label::GetInsets();
if (GetFocusStyle() == FocusStyle::RING &&
GetFocusBehavior() != FocusBehavior::NEVER) {
- DCHECK(!text().empty());
+ DCHECK(!GetText().empty());
insets += gfx::Insets(kFocusBorderPadding);
}
return insets;
}
-const char* Link::GetClassName() const {
- return kViewClassName;
-}
-
gfx::NativeCursor Link::GetCursor(const ui::MouseEvent& event) {
if (!GetEnabled())
return gfx::kNullCursor;
@@ -253,7 +248,7 @@ void Link::RecalculateFont() {
void Link::ConfigureFocus() {
// Disable focusability for empty links.
- if (text().empty()) {
+ if (GetText().empty()) {
SetFocusBehavior(FocusBehavior::NEVER);
} else {
#if defined(OS_MACOSX)
@@ -279,4 +274,8 @@ SkColor Link::GetColor() {
: ui::NativeTheme::kColorId_LinkEnabled);
}
+BEGIN_METADATA(Link)
+METADATA_PARENT_CLASS(Label)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/link.h b/chromium/ui/views/controls/link.h
index 3379ee9bd54..8f4f6af95f4 100644
--- a/chromium/ui/views/controls/link.h
+++ b/chromium/ui/views/controls/link.h
@@ -26,7 +26,7 @@ class LinkListener;
////////////////////////////////////////////////////////////////////////////////
class VIEWS_EXPORT Link : public Label {
public:
- static const char kViewClassName[];
+ METADATA_HEADER(Link);
// The padding for the focus ring border when rendering a focused Link with
// FocusStyle::RING.
@@ -56,7 +56,6 @@ class VIEWS_EXPORT Link : public Label {
// Label:
void PaintFocusRing(gfx::Canvas* canvas) const override;
gfx::Insets GetInsets() const override;
- const char* GetClassName() const override;
gfx::NativeCursor GetCursor(const ui::MouseEvent& event) override;
bool CanProcessEventsWithinSubtree() const override;
bool OnMousePressed(const ui::MouseEvent& event) override;
diff --git a/chromium/ui/views/controls/menu/menu_closure_animation_mac.h b/chromium/ui/views/controls/menu/menu_closure_animation_mac.h
index e966edd9888..fecbe83fc41 100644
--- a/chromium/ui/views/controls/menu/menu_closure_animation_mac.h
+++ b/chromium/ui/views/controls/menu/menu_closure_animation_mac.h
@@ -6,6 +6,7 @@
#define UI_VIEWS_CONTROLS_MENU_MENU_CLOSURE_ANIMATION_MAC_H_
#include "base/macros.h"
+#include "base/memory/weak_ptr.h"
#include "base/timer/timer.h"
#include "ui/gfx/animation/animation.h"
#include "ui/gfx/animation/animation_delegate.h"
@@ -29,7 +30,9 @@ class SubmenuView;
// This class also supports animating a menu away without animating the
// selection effect, which is achieved by passing nullptr for the item to
// animate. In this case, the animation skips straight to step 3 above.
-class VIEWS_EXPORT MenuClosureAnimationMac : public gfx::AnimationDelegate {
+class VIEWS_EXPORT MenuClosureAnimationMac
+ : public gfx::AnimationDelegate,
+ public base::SupportsWeakPtr<MenuClosureAnimationMac> {
public:
// After this closure animation is done, |callback| is run to finish
// dismissing the menu. If |item| is given, this will animate the item being
diff --git a/chromium/ui/views/controls/menu/menu_closure_animation_mac.mm b/chromium/ui/views/controls/menu/menu_closure_animation_mac.mm
index 1ebd33f83c6..b4d8b6fd11f 100644
--- a/chromium/ui/views/controls/menu/menu_closure_animation_mac.mm
+++ b/chromium/ui/views/controls/menu/menu_closure_animation_mac.mm
@@ -39,7 +39,7 @@ void MenuClosureAnimationMac::Start() {
step_ = AnimationStep::kFading;
base::ThreadTaskRunnerHandle::Get()->PostTask(
FROM_HERE, base::BindOnce(&MenuClosureAnimationMac::AdvanceAnimation,
- base::Unretained(this)));
+ AsWeakPtr()));
return;
}
AdvanceAnimation();
diff --git a/chromium/ui/views/controls/menu/menu_closure_animation_mac_unittest.cc b/chromium/ui/views/controls/menu/menu_closure_animation_mac_unittest.cc
new file mode 100644
index 00000000000..ef40b47dc52
--- /dev/null
+++ b/chromium/ui/views/controls/menu/menu_closure_animation_mac_unittest.cc
@@ -0,0 +1,28 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/controls/menu/menu_closure_animation_mac.h"
+
+#include "base/test/bind_test_util.h"
+#include "base/test/scoped_task_environment.h"
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/views/test/menu_test_utils.h"
+
+TEST(MenuClosureAnimationMacTest, DestructCancelsCleanly) {
+ views::test::DisableMenuClosureAnimations();
+ base::test::ScopedTaskEnvironment environment;
+
+ bool called = false;
+ auto animation = std::make_unique<views::MenuClosureAnimationMac>(
+ nullptr, nullptr, base::BindLambdaForTesting([&]() { called = true; }));
+
+ animation->Start();
+ animation.reset();
+
+ // If the animation callback runs after the animation is destroyed, this line
+ // may crash; if not, |called| will get set to true and fail the test below.
+ views::test::WaitForMenuClosureAnimation();
+
+ EXPECT_FALSE(called);
+}
diff --git a/chromium/ui/views/controls/menu/menu_cocoa_watcher_mac.h b/chromium/ui/views/controls/menu/menu_cocoa_watcher_mac.h
index 96e55221033..f375ae5cc00 100644
--- a/chromium/ui/views/controls/menu/menu_cocoa_watcher_mac.h
+++ b/chromium/ui/views/controls/menu/menu_cocoa_watcher_mac.h
@@ -13,20 +13,26 @@
namespace views {
-// This class executes a callback when a native menu begins tracking. With
-// native menus, each one automatically closes when a new one begins tracking.
-// This allows Views menus to tie into this behavior.
+// This class executes a callback when a native menu begins tracking, or when a
+// new window takes focus. With native menus, each one automatically closes when
+// a new one begins tracking, and MenuPreTargetHandlerAura::OnWindowActivated()
+// closes menus when new windows take focus. This allows Views menus to have the
+// correct behavior.
class VIEWS_EXPORT MenuCocoaWatcherMac {
public:
explicit MenuCocoaWatcherMac(base::OnceClosure callback);
~MenuCocoaWatcherMac();
private:
+ void ExecuteCallback();
+
// The closure to call when the notification comes in.
base::OnceClosure callback_;
- // The token representing the notification observer.
- id observer_token_;
+ // Tokens representing the notification observers.
+ id observer_token_other_menu_;
+ id observer_token_new_window_focus_;
+ id observer_token_app_change_;
DISALLOW_COPY_AND_ASSIGN(MenuCocoaWatcherMac);
};
diff --git a/chromium/ui/views/controls/menu/menu_cocoa_watcher_mac.mm b/chromium/ui/views/controls/menu/menu_cocoa_watcher_mac.mm
index da563e6a4cd..c5d53055a4e 100644
--- a/chromium/ui/views/controls/menu/menu_cocoa_watcher_mac.mm
+++ b/chromium/ui/views/controls/menu/menu_cocoa_watcher_mac.mm
@@ -5,6 +5,7 @@
#include "ui/views/controls/menu/menu_cocoa_watcher_mac.h"
#import <Cocoa/Cocoa.h>
+#include <dispatch/dispatch.h>
#import <utility>
@@ -12,17 +13,46 @@ namespace views {
MenuCocoaWatcherMac::MenuCocoaWatcherMac(base::OnceClosure callback)
: callback_(std::move(callback)) {
- observer_token_ = [[NSNotificationCenter defaultCenter]
+ observer_token_other_menu_ = [[NSNotificationCenter defaultCenter]
addObserverForName:NSMenuDidBeginTrackingNotification
object:[NSApp mainMenu]
queue:nil
usingBlock:^(NSNotification* notification) {
- std::move(this->callback_).Run();
+ ExecuteCallback();
}];
+ observer_token_new_window_focus_ = [[NSNotificationCenter defaultCenter]
+ addObserverForName:NSWindowDidBecomeKeyNotification
+ object:nil
+ queue:nil
+ usingBlock:^(NSNotification* notification) {
+ ExecuteCallback();
+ }];
+ observer_token_app_change_ =
+ [[[NSWorkspace sharedWorkspace] notificationCenter]
+ addObserverForName:NSWorkspaceDidActivateApplicationNotification
+ object:nil
+ queue:nil
+ usingBlock:^(NSNotification* notification) {
+ ExecuteCallback();
+ }];
}
MenuCocoaWatcherMac::~MenuCocoaWatcherMac() {
- [[NSNotificationCenter defaultCenter] removeObserver:observer_token_];
+ [[NSNotificationCenter defaultCenter]
+ removeObserver:observer_token_other_menu_];
+ [[NSNotificationCenter defaultCenter]
+ removeObserver:observer_token_new_window_focus_];
+ [[[NSWorkspace sharedWorkspace] notificationCenter]
+ removeObserver:observer_token_app_change_];
+}
+
+void MenuCocoaWatcherMac::ExecuteCallback() {
+ __block base::OnceClosure callback = std::move(callback_);
+ dispatch_async(dispatch_get_main_queue(), ^{
+ if (callback) {
+ std::move(callback).Run();
+ }
+ });
}
} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu_config_mac.mm b/chromium/ui/views/controls/menu/menu_config_mac.mm
index 607ed754986..1de2eb9c7ec 100644
--- a/chromium/ui/views/controls/menu/menu_config_mac.mm
+++ b/chromium/ui/views/controls/menu/menu_config_mac.mm
@@ -33,6 +33,8 @@ void InitMaterialMenuConfig(views::MenuConfig* config) {
config->icons_in_label = true;
config->corner_radius = 8;
config->auxiliary_corner_radius = 4;
+ config->item_top_margin = 4;
+ config->item_bottom_margin = 4;
}
} // namespace
diff --git a/chromium/ui/views/controls/menu/menu_controller.cc b/chromium/ui/views/controls/menu/menu_controller.cc
index 3ae7da55cf1..bceec6f1721 100644
--- a/chromium/ui/views/controls/menu/menu_controller.cc
+++ b/chromium/ui/views/controls/menu/menu_controller.cc
@@ -475,7 +475,7 @@ void MenuController::Run(Widget* parent,
#if defined(OS_MACOSX)
menu_cocoa_watcher_ = std::make_unique<MenuCocoaWatcherMac>(base::BindOnce(
- &MenuController::Cancel, base::Unretained(this), ExitType::kAll));
+ &MenuController::Cancel, this->AsWeakPtr(), ExitType::kAll));
#endif
// Reset current state.
@@ -982,7 +982,7 @@ int MenuController::OnDragUpdated(SubmenuView* source,
if (menu_item)
over_empty_menu = true;
}
- MenuDelegate::DropPosition drop_position = MenuDelegate::DROP_NONE;
+ MenuDelegate::DropPosition drop_position = MenuDelegate::DropPosition::kNone;
int drop_operation = ui::DragDropTypes::DRAG_NONE;
if (menu_item) {
gfx::Point menu_item_loc(event.location());
@@ -993,16 +993,16 @@ int MenuController::OnDragUpdated(SubmenuView* source,
if (menu_item->HasSubmenu() &&
(menu_item_loc.y() > kDropBetweenPixels &&
menu_item_loc.y() < (menu_item_height - kDropBetweenPixels))) {
- drop_position = MenuDelegate::DROP_ON;
+ drop_position = MenuDelegate::DropPosition::kOn;
} else {
drop_position = (menu_item_loc.y() < menu_item_height / 2)
- ? MenuDelegate::DROP_BEFORE
- : MenuDelegate::DROP_AFTER;
+ ? MenuDelegate::DropPosition::kBefore
+ : MenuDelegate::DropPosition::kAfter;
}
query_menu_item = menu_item;
} else {
query_menu_item = menu_item->GetParentMenuItem();
- drop_position = MenuDelegate::DROP_ON;
+ drop_position = MenuDelegate::DropPosition::kOn;
}
drop_operation = menu_item->GetDelegate()->GetDropOperation(
query_menu_item, event, &drop_position);
@@ -1011,7 +1011,7 @@ int MenuController::OnDragUpdated(SubmenuView* source,
SetSelection(menu_item, menu_item->HasSubmenu() ? SELECTION_OPEN_SUBMENU
: SELECTION_DEFAULT);
- if (drop_position == MenuDelegate::DROP_NONE ||
+ if (drop_position == MenuDelegate::DropPosition::kNone ||
drop_operation == ui::DragDropTypes::DRAG_NONE)
menu_item = nullptr;
} else {
@@ -1027,7 +1027,7 @@ void MenuController::OnDragExited(SubmenuView* source) {
if (drop_target_) {
StopShowTimer();
- SetDropMenuItem(nullptr, MenuDelegate::DROP_NONE);
+ SetDropMenuItem(nullptr, MenuDelegate::DropPosition::kNone);
}
}
@@ -1075,14 +1075,14 @@ void MenuController::OnDragEnteredScrollButton(SubmenuView* source,
UpdateScrolling(part);
// Do this to force the selection to hide.
- SetDropMenuItem(source->GetMenuItemAt(0), MenuDelegate::DROP_NONE);
+ SetDropMenuItem(source->GetMenuItemAt(0), MenuDelegate::DropPosition::kNone);
StopCancelAllTimer();
}
void MenuController::OnDragExitedScrollButton(SubmenuView* source) {
StartCancelAllTimer();
- SetDropMenuItem(nullptr, MenuDelegate::DROP_NONE);
+ SetDropMenuItem(nullptr, MenuDelegate::DropPosition::kNone);
StopScrolling();
}
@@ -1138,30 +1138,35 @@ ui::PostDispatchAction MenuController::OnWillDispatchKeyEvent(
base::WeakPtr<MenuController> this_ref = AsWeakPtr();
if (event->type() == ui::ET_KEY_PRESSED) {
+ bool key_handled = false;
#if defined(OS_MACOSX)
// Special handling for Option-Up and Option-Down, which should behave like
// Home and End respectively in menus.
if ((event->flags() & ui::EF_ALT_DOWN)) {
if (event->key_code() == ui::VKEY_UP) {
- OnKeyDown(ui::VKEY_HOME);
+ key_handled = OnKeyPressed(ui::VKEY_HOME);
} else if (event->key_code() == ui::VKEY_DOWN) {
- OnKeyDown(ui::VKEY_END);
+ key_handled = OnKeyPressed(ui::VKEY_END);
} else {
- OnKeyDown(event->key_code());
+ key_handled = OnKeyPressed(event->key_code());
}
} else {
- OnKeyDown(event->key_code());
+ key_handled = OnKeyPressed(event->key_code());
}
#else
- OnKeyDown(event->key_code());
+ key_handled = OnKeyPressed(event->key_code());
#endif
+
+ if (key_handled)
+ event->StopPropagation();
+
// Key events can lead to this being deleted.
if (!this_ref) {
event->StopPropagation();
return ui::POST_DISPATCH_NONE;
}
- if (!IsEditableCombobox()) {
+ if (!IsEditableCombobox() && !event->stopped_propagation()) {
// Do not check mnemonics if the Alt or Ctrl modifiers are pressed. For
// example Ctrl+<T> is an accelerator, but <T> only is a mnemonic.
const int kKeyFlagsMask = ui::EF_CONTROL_DOWN | ui::EF_ALT_DOWN;
@@ -1402,16 +1407,17 @@ void MenuController::StartDrag(SubmenuView* source,
item->PaintButton(&canvas, MenuItemView::PB_FOR_DRAG);
gfx::ImageSkia image(gfx::ImageSkiaRep(canvas.GetBitmap(), raster_scale));
- OSExchangeData data;
- item->GetDelegate()->WriteDragData(item, &data);
- data.provider().SetDragImage(image, press_loc.OffsetFromOrigin());
+ std::unique_ptr<OSExchangeData> data(std::make_unique<OSExchangeData>());
+ item->GetDelegate()->WriteDragData(item, data.get());
+ data->provider().SetDragImage(image, press_loc.OffsetFromOrigin());
StopScrolling();
int drag_ops = item->GetDelegate()->GetDragOperations(item);
did_initiate_drag_ = true;
base::WeakPtr<MenuController> this_ref = AsWeakPtr();
// TODO(varunjain): Properly determine and send DRAG_EVENT_SOURCE below.
- item->GetWidget()->RunShellDrag(nullptr, data, widget_loc, drag_ops,
+ item->GetWidget()->RunShellDrag(nullptr, std::move(data), widget_loc,
+ drag_ops,
ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
// MenuController may have been deleted so check before accessing member
// variables.
@@ -1419,10 +1425,12 @@ void MenuController::StartDrag(SubmenuView* source,
did_initiate_drag_ = false;
}
-void MenuController::OnKeyDown(ui::KeyboardCode key_code) {
+bool MenuController::OnKeyPressed(ui::KeyboardCode key_code) {
// Do not process while performing drag-and-drop
if (for_drop_)
- return;
+ return false;
+
+ bool handled_key_code = false;
switch (key_code) {
case ui::VKEY_HOME:
@@ -1499,6 +1507,7 @@ void MenuController::OnKeyDown(ui::KeyboardCode key_code) {
else
OpenSubmenuChangeSelectionIfCan();
} else {
+ handled_key_code = true;
if (!SendAcceleratorToHotTrackedView() &&
pending_state_.item->GetEnabled()) {
Accept(pending_state_.item, 0);
@@ -1555,6 +1564,7 @@ void MenuController::OnKeyDown(ui::KeyboardCode key_code) {
default:
break;
}
+ return handled_key_code;
}
MenuController::MenuController(bool for_drop,
@@ -2747,7 +2757,7 @@ void MenuController::SetDropMenuItem(MenuItemView* new_target,
if (drop_target_) {
drop_target_->GetParentMenuItem()->GetSubmenu()->SetDropMenuItem(
- nullptr, MenuDelegate::DROP_NONE);
+ nullptr, MenuDelegate::DropPosition::kNone);
}
drop_target_ = new_target;
drop_position_ = new_position;
diff --git a/chromium/ui/views/controls/menu/menu_controller.h b/chromium/ui/views/controls/menu/menu_controller.h
index c65b0ac30b1..1b12cd52e93 100644
--- a/chromium/ui/views/controls/menu/menu_controller.h
+++ b/chromium/ui/views/controls/menu/menu_controller.h
@@ -350,8 +350,9 @@ class VIEWS_EXPORT MenuController
const ui::LocatedEvent* event);
void StartDrag(SubmenuView* source, const gfx::Point& location);
- // Key processing.
- void OnKeyDown(ui::KeyboardCode key_code);
+ // Handles |key_code| as a keypress. Returns true if OnKeyPressed handled the
+ // key code.
+ bool OnKeyPressed(ui::KeyboardCode key_code);
// Creates a MenuController. See |for_drop_| member for details on |for_drop|.
MenuController(bool for_drop, internal::MenuControllerDelegate* delegate);
@@ -677,7 +678,8 @@ class VIEWS_EXPORT MenuController
// Drop target.
MenuItemView* drop_target_ = nullptr;
- MenuDelegate::DropPosition drop_position_ = MenuDelegate::DROP_UNKNOWN;
+ MenuDelegate::DropPosition drop_position_ =
+ MenuDelegate::DropPosition::kUnknow;
// Owner of child windows.
// WARNING: this may be NULL.
@@ -701,7 +703,7 @@ class VIEWS_EXPORT MenuController
// continually processing whether we can drop, we cache the coordinates.
bool valid_drop_coordinates_ = false;
gfx::Point drop_pt_;
- int last_drop_operation_ = MenuDelegate::DROP_UNKNOWN;
+ int last_drop_operation_ = ui::DragDropTypes::DRAG_NONE;
// If true, we're in the middle of invoking ShowAt on a submenu.
bool showing_submenu_ = false;
diff --git a/chromium/ui/views/controls/menu/menu_controller_unittest.cc b/chromium/ui/views/controls/menu/menu_controller_unittest.cc
index 57031c8b3f9..ce0b8a3f65d 100644
--- a/chromium/ui/views/controls/menu/menu_controller_unittest.cc
+++ b/chromium/ui/views/controls/menu/menu_controller_unittest.cc
@@ -184,7 +184,7 @@ class TestDragDropClient : public aura::client::DragDropClient {
~TestDragDropClient() override = default;
// aura::client::DragDropClient:
- int StartDragAndDrop(const ui::OSExchangeData& data,
+ int StartDragAndDrop(std::unique_ptr<ui::OSExchangeData> data,
aura::Window* root_window,
aura::Window* source_window,
const gfx::Point& screen_location,
@@ -205,7 +205,7 @@ class TestDragDropClient : public aura::client::DragDropClient {
};
int TestDragDropClient::StartDragAndDrop(
- const ui::OSExchangeData& data,
+ std::unique_ptr<ui::OSExchangeData> data,
aura::Window* root_window,
aura::Window* source_window,
const gfx::Point& screen_location,
@@ -1291,7 +1291,7 @@ TEST_F(MenuControllerTest, AsynchronousPerformDrop) {
SubmenuView* source = menu_item()->GetSubmenu();
MenuItemView* target = source->GetMenuItemAt(0);
- SetDropMenuItem(target, MenuDelegate::DropPosition::DROP_AFTER);
+ SetDropMenuItem(target, MenuDelegate::DropPosition::kAfter);
ui::OSExchangeData drop_data;
gfx::PointF location(target->origin());
@@ -1898,14 +1898,7 @@ TEST_F(MenuControllerTest, AsynchronousCancelEvent) {
}
// Tests that menus without parent widgets do not crash in MenuPreTargetHandler.
-// This is generally true, except on Chrome OS running with the window service.
-// In that case, a DCHECK fires to ensure menus can consume parents' key events.
TEST_F(MenuControllerTest, RunWithoutWidgetDoesntCrash) {
-#if defined(OS_CHROMEOS)
- if (::features::IsUsingWindowService())
- return;
-#endif // OS_CHROMEOS
-
ExitMenuRun();
MenuController* controller = menu_controller();
controller->Run(nullptr, nullptr, menu_item(), gfx::Rect(),
@@ -2257,12 +2250,6 @@ TEST_F(MenuControllerTest, SetSelectionIndices_Buttons_SkipHiddenAndDisabled) {
}
TEST_F(MenuControllerTest, SetSelectionIndices_NestedButtons) {
- class DummyButtonListener : public ButtonListener {
- public:
- ~DummyButtonListener() override = default;
- void ButtonPressed(Button* sender, const ui::Event& event) override {}
- };
-
MenuItemView* const item1 = menu_item()->GetSubmenu()->GetMenuItemAt(0);
MenuItemView* const item2 = menu_item()->GetSubmenu()->GetMenuItemAt(1);
MenuItemView* const item3 = menu_item()->GetSubmenu()->GetMenuItemAt(2);
@@ -2277,13 +2264,11 @@ TEST_F(MenuControllerTest, SetSelectionIndices_NestedButtons) {
container_view->AddChildView(new Label());
// Add two focusable buttons (buttons in menus are always focusable).
- Button* const button1 =
- new LabelButton(new DummyButtonListener(), base::string16());
+ Button* const button1 = new LabelButton(nullptr, base::string16());
button1->SetFocusBehavior(View::FocusBehavior::ALWAYS);
button1->GetViewAccessibility().OverrideRole(ax::mojom::Role::kMenuItem);
container_view->AddChildView(button1);
- Button* const button2 =
- new LabelButton(new DummyButtonListener(), base::string16());
+ Button* const button2 = new LabelButton(nullptr, base::string16());
button2->GetViewAccessibility().OverrideRole(ax::mojom::Role::kMenuItem);
button2->SetFocusBehavior(View::FocusBehavior::ALWAYS);
container_view->AddChildView(button2);
diff --git a/chromium/ui/views/controls/menu/menu_delegate.h b/chromium/ui/views/controls/menu/menu_delegate.h
index 921aef245bf..bdbd9c7e37b 100644
--- a/chromium/ui/views/controls/menu/menu_delegate.h
+++ b/chromium/ui/views/controls/menu/menu_delegate.h
@@ -45,20 +45,20 @@ class VIEWS_EXPORT MenuDelegate {
public:
// Used during drag and drop to indicate where the drop indicator should
// be rendered.
- enum DropPosition {
- DROP_UNKNOWN = -1,
+ enum class DropPosition {
+ kUnknow = -1,
// Indicates a drop is not allowed here.
- DROP_NONE,
+ kNone,
// Indicates the drop should occur before the item.
- DROP_BEFORE,
+ kBefore,
// Indicates the drop should occur after the item.
- DROP_AFTER,
+ kAfter,
// Indicates the drop should occur on the item.
- DROP_ON
+ kOn
};
// Used when indicating the style for a given label.
diff --git a/chromium/ui/views/controls/menu/menu_image_util.cc b/chromium/ui/views/controls/menu/menu_image_util.cc
index d1cc32bc757..80673906f76 100644
--- a/chromium/ui/views/controls/menu/menu_image_util.cc
+++ b/chromium/ui/views/controls/menu/menu_image_util.cc
@@ -15,16 +15,6 @@ gfx::ImageSkia GetMenuCheckImage(SkColor icon_color) {
return gfx::CreateVectorIcon(kMenuCheckIcon, icon_color);
}
-gfx::ImageSkia GetRadioButtonImage(bool toggled,
- bool hovered,
- SkColor default_icon_color) {
- const gfx::VectorIcon& icon =
- toggled ? kMenuRadioSelectedIcon : kMenuRadioEmptyIcon;
- SkColor color =
- toggled && !hovered ? gfx::kGoogleBlue500 : default_icon_color;
- return gfx::CreateVectorIcon(icon, kMenuCheckSize, color);
-}
-
gfx::ImageSkia GetSubmenuArrowImage(SkColor icon_color) {
return gfx::CreateVectorIcon(kSubmenuArrowIcon, icon_color);
}
diff --git a/chromium/ui/views/controls/menu/menu_image_util.h b/chromium/ui/views/controls/menu/menu_image_util.h
index bda82266bbf..10713e0bc13 100644
--- a/chromium/ui/views/controls/menu/menu_image_util.h
+++ b/chromium/ui/views/controls/menu/menu_image_util.h
@@ -17,14 +17,6 @@ constexpr int kSubmenuArrowSize = 8;
// Returns the Menu Check box image (always checked).
gfx::ImageSkia GetMenuCheckImage(SkColor icon_color);
-// Return the RadioButton image for given state. |toggled| is true when
-// the radio option is active, |hovered| describes the menu higlight/selection
-// state, and |default_icon_color| is the base color that should be used for
-// the icon (which may be ignored based on the other two flags).
-gfx::ImageSkia GetRadioButtonImage(bool toggled,
- bool hovered,
- SkColor default_icon_color);
-
// Returns the image for submenu arrow for current RTL setting.
gfx::ImageSkia GetSubmenuArrowImage(SkColor icon_color);
diff --git a/chromium/ui/views/controls/menu/menu_item_view.cc b/chromium/ui/views/controls/menu/menu_item_view.cc
index 1e27d88823a..c8a32b58cf7 100644
--- a/chromium/ui/views/controls/menu/menu_item_view.cc
+++ b/chromium/ui/views/controls/menu/menu_item_view.cc
@@ -40,6 +40,7 @@
#include "ui/views/controls/menu/menu_separator.h"
#include "ui/views/controls/menu/submenu_view.h"
#include "ui/views/controls/separator.h"
+#include "ui/views/vector_icons.h"
#include "ui/views/view_class_properties.h"
#include "ui/views/widget/widget.h"
@@ -98,9 +99,6 @@ int MenuItemView::item_right_margin_;
// static
int MenuItemView::pref_menu_height_;
-// static
-const char MenuItemView::kViewClassName[] = "MenuItemView";
-
MenuItemView::MenuItemView(MenuDelegate* delegate)
: delegate_(delegate),
controller_(nullptr),
@@ -765,10 +763,6 @@ MenuItemView::~MenuItemView() {
delete item;
}
-const char* MenuItemView::GetClassName() const {
- return kViewClassName;
-}
-
// Calculates all sizes that we can from the OS.
//
// This is invoked prior to Running a menu.
@@ -981,8 +975,14 @@ void MenuItemView::PaintButton(gfx::Canvas* canvas, PaintButtonMode mode) {
if (type_ == CHECKBOX && delegate->IsItemChecked(GetCommand())) {
radio_check_image_view_->SetImage(GetMenuCheckImage(icon_color));
} else if (type_ == RADIO) {
- radio_check_image_view_->SetImage(GetRadioButtonImage(
- delegate->IsItemChecked(GetCommand()), render_selection, icon_color));
+ const bool toggled = delegate->IsItemChecked(GetCommand());
+ const gfx::VectorIcon& radio_icon =
+ toggled ? kMenuRadioSelectedIcon : kMenuRadioEmptyIcon;
+ const SkColor radio_icon_color = GetNativeTheme()->GetSystemColor(
+ toggled ? ui::NativeTheme::kColorId_ProminentButtonColor
+ : ui::NativeTheme::kColorId_ButtonEnabledColor);
+ radio_check_image_view_->SetImage(
+ gfx::CreateVectorIcon(radio_icon, kMenuCheckSize, radio_icon_color));
}
// Render the foreground.
@@ -1405,4 +1405,8 @@ bool MenuItemView::HasChecksOrRadioButtons() const {
[](const auto* item) { return item->HasChecksOrRadioButtons(); });
}
+BEGIN_METADATA(MenuItemView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu_item_view.h b/chromium/ui/views/controls/menu/menu_item_view.h
index 6d22433f46e..690d6671e9a 100644
--- a/chromium/ui/views/controls/menu/menu_item_view.h
+++ b/chromium/ui/views/controls/menu/menu_item_view.h
@@ -74,10 +74,9 @@ class SubmenuView;
class VIEWS_EXPORT MenuItemView : public View {
public:
- friend class MenuController;
+ METADATA_HEADER(MenuItemView);
- // The menu item view's class name.
- static const char kViewClassName[];
+ friend class MenuController;
// ID used to identify menu items.
static const int kMenuItemViewID;
@@ -384,7 +383,6 @@ class VIEWS_EXPORT MenuItemView : public View {
// View:
void ChildPreferredSizeChanged(View* child) override;
- const char* GetClassName() const override;
// Returns the preferred size (and padding) of any children.
virtual gfx::Size GetChildPreferredSize() const;
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 d33c7bc2a66..e745aec4fea 100644
--- a/chromium/ui/views/controls/menu/menu_item_view_unittest.cc
+++ b/chromium/ui/views/controls/menu/menu_item_view_unittest.cc
@@ -218,7 +218,7 @@ TEST_F(MenuItemViewLayoutTest, ContainerLayoutRespectsMarginsAndPreferredSize) {
const gfx::Size child_size(200, 50);
const gfx::Insets child_margins(5, 10);
child_view->SetPreferredSize(child_size);
- child_view->SetProperty(kMarginsKey, new gfx::Insets(child_margins));
+ child_view->SetProperty(kMarginsKey, child_margins);
PerformLayout();
@@ -267,7 +267,7 @@ TEST_F(MenuItemViewLayoutTest, ContainerLayoutPassesTrueWidth) {
FakeView* child_view =
test_item()->AddChildView(std::make_unique<FakeView>(child_size.width()));
child_view->SetPreferredSize(child_size);
- child_view->SetProperty(kMarginsKey, new gfx::Insets(child_margins));
+ child_view->SetProperty(kMarginsKey, child_margins);
PerformLayout();
diff --git a/chromium/ui/views/controls/menu/menu_pre_target_handler_aura.cc b/chromium/ui/views/controls/menu/menu_pre_target_handler_aura.cc
index 2bfd2942c01..94976c23ef5 100644
--- a/chromium/ui/views/controls/menu/menu_pre_target_handler_aura.cc
+++ b/chromium/ui/views/controls/menu/menu_pre_target_handler_aura.cc
@@ -6,7 +6,6 @@
#include "ui/aura/env.h"
#include "ui/aura/window.h"
-#include "ui/base/ui_base_features.h"
#include "ui/views/controls/menu/menu_controller.h"
#include "ui/views/widget/widget.h"
#include "ui/wm/public/activation_client.h"
@@ -29,11 +28,7 @@ MenuPreTargetHandlerAura::MenuPreTargetHandlerAura(MenuController* controller,
root_->AddObserver(this);
} else {
// This should only happen in cases like when context menus are shown for
- // Windows OS system tray items and there is no parent window. This should
- // not be hit on Chrome OS, where Window Service clients need to install a
- // pre-target handler on the aura::Env associated with their app window.
- DCHECK(!::features::IsUsingWindowService())
- << "MenuPreTargetHandlerAura may not work correctly without an owner.";
+ // Windows OS system tray items and there is no parent window.
}
aura::Env::GetInstance()->AddPreTargetHandler(
this, ui::EventTarget::Priority::kSystem);
diff --git a/chromium/ui/views/controls/menu/menu_runner_impl.cc b/chromium/ui/views/controls/menu/menu_runner_impl.cc
index f1e43947259..cc93c948eb8 100644
--- a/chromium/ui/views/controls/menu/menu_runner_impl.cc
+++ b/chromium/ui/views/controls/menu/menu_runner_impl.cc
@@ -42,8 +42,7 @@ MenuRunnerImpl::MenuRunnerImpl(MenuItemView* menu)
delete_after_run_(false),
for_drop_(false),
controller_(nullptr),
- owns_controller_(false),
- weak_factory_(this) {}
+ owns_controller_(false) {}
bool MenuRunnerImpl::IsRunning() const {
return running_;
diff --git a/chromium/ui/views/controls/menu/menu_runner_impl.h b/chromium/ui/views/controls/menu/menu_runner_impl.h
index 8617acc7383..79f43820be6 100644
--- a/chromium/ui/views/controls/menu/menu_runner_impl.h
+++ b/chromium/ui/views/controls/menu/menu_runner_impl.h
@@ -94,7 +94,7 @@ class VIEWS_EXPORT MenuRunnerImpl : public MenuRunnerImplInterface,
base::TimeTicks closing_event_time_;
// Used to detect deletion of |this| when notifying delegate of success.
- base::WeakPtrFactory<MenuRunnerImpl> weak_factory_;
+ base::WeakPtrFactory<MenuRunnerImpl> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(MenuRunnerImpl);
};
diff --git a/chromium/ui/views/controls/menu/menu_scroll_view_container.cc b/chromium/ui/views/controls/menu/menu_scroll_view_container.cc
index 7ae246a53bd..3e7c6460bc1 100644
--- a/chromium/ui/views/controls/menu/menu_scroll_view_container.cc
+++ b/chromium/ui/views/controls/menu/menu_scroll_view_container.cc
@@ -358,4 +358,8 @@ BubbleBorder::Arrow MenuScrollViewContainer::BubbleBorderTypeFromAnchor(
}
}
+BEGIN_METADATA(MenuScrollViewContainer)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu_scroll_view_container.h b/chromium/ui/views/controls/menu/menu_scroll_view_container.h
index 24f01963880..6dbb6b9df89 100644
--- a/chromium/ui/views/controls/menu/menu_scroll_view_container.h
+++ b/chromium/ui/views/controls/menu/menu_scroll_view_container.h
@@ -20,6 +20,8 @@ class SubmenuView;
// the preferred height of the SubmenuView is bigger than our bounds.
class MenuScrollViewContainer : public View {
public:
+ METADATA_HEADER(MenuScrollViewContainer);
+
explicit MenuScrollViewContainer(SubmenuView* content_view);
// Returns the buttons for scrolling up/down.
diff --git a/chromium/ui/views/controls/menu/menu_separator.cc b/chromium/ui/views/controls/menu/menu_separator.cc
index aa27d3c260b..b48d80919ce 100644
--- a/chromium/ui/views/controls/menu/menu_separator.cc
+++ b/chromium/ui/views/controls/menu/menu_separator.cc
@@ -88,4 +88,8 @@ gfx::Size MenuSeparator::CalculatePreferredSize() const {
height);
}
+BEGIN_METADATA(MenuSeparator)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/menu/menu_separator.h b/chromium/ui/views/controls/menu/menu_separator.h
index 4e91f1707e2..a331914d44a 100644
--- a/chromium/ui/views/controls/menu/menu_separator.h
+++ b/chromium/ui/views/controls/menu/menu_separator.h
@@ -15,6 +15,8 @@ namespace views {
class VIEWS_EXPORT MenuSeparator : public View {
public:
+ METADATA_HEADER(MenuSeparator);
+
explicit MenuSeparator(ui::MenuSeparatorType type) : type_(type) {}
// View overrides.
diff --git a/chromium/ui/views/controls/menu/submenu_view.cc b/chromium/ui/views/controls/menu/submenu_view.cc
index caa47b1ccfd..ecdc432e9cb 100644
--- a/chromium/ui/views/controls/menu/submenu_view.cc
+++ b/chromium/ui/views/controls/menu/submenu_view.cc
@@ -34,14 +34,11 @@ constexpr SkColor kDropIndicatorColor = SK_ColorBLACK;
namespace views {
-// static
-const char SubmenuView::kViewClassName[] = "SubmenuView";
-
SubmenuView::SubmenuView(MenuItemView* parent)
: parent_menu_item_(parent),
host_(nullptr),
drop_item_(nullptr),
- drop_position_(MenuDelegate::DROP_NONE),
+ drop_position_(MenuDelegate::DropPosition::kNone),
scroll_view_container_(nullptr),
max_minor_text_width_(0),
minimum_preferred_width_(0),
@@ -216,12 +213,12 @@ void SubmenuView::PaintChildren(const PaintInfo& paint_info) {
bool paint_drop_indicator = false;
if (drop_item_) {
switch (drop_position_) {
- case MenuDelegate::DROP_NONE:
- case MenuDelegate::DROP_ON:
+ case MenuDelegate::DropPosition::kNone:
+ case MenuDelegate::DropPosition::kOn:
break;
- case MenuDelegate::DROP_UNKNOWN:
- case MenuDelegate::DROP_BEFORE:
- case MenuDelegate::DROP_AFTER:
+ case MenuDelegate::DropPosition::kUnknow:
+ case MenuDelegate::DropPosition::kBefore:
+ case MenuDelegate::DropPosition::kAfter:
paint_drop_indicator = true;
break;
}
@@ -458,7 +455,8 @@ bool SubmenuView::GetShowSelection(MenuItemView* item) {
// Something is being dropped on one of this menus items. Show the
// selection if the drop is on the passed in item and the drop position is
// ON.
- return (drop_item_ == item && drop_position_ == MenuDelegate::DROP_ON);
+ return (drop_item_ == item &&
+ drop_position_ == MenuDelegate::DropPosition::kOn);
}
MenuScrollViewContainer* SubmenuView::GetScrollViewContainer() {
@@ -482,10 +480,6 @@ void SubmenuView::MenuHostDestroyed() {
controller->Cancel(MenuController::ExitType::kDestroyed);
}
-const char* SubmenuView::GetClassName() const {
- return kViewClassName;
-}
-
void SubmenuView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
SchedulePaint();
}
@@ -496,9 +490,9 @@ void SubmenuView::SchedulePaintForDropIndicator(
if (item == nullptr)
return;
- if (position == MenuDelegate::DROP_ON) {
+ if (position == MenuDelegate::DropPosition::kOn) {
item->SchedulePaint();
- } else if (position != MenuDelegate::DROP_NONE) {
+ } else if (position != MenuDelegate::DropPosition::kNone) {
SchedulePaintInRect(CalculateDropIndicatorBounds(item, position));
}
}
@@ -506,15 +500,15 @@ void SubmenuView::SchedulePaintForDropIndicator(
gfx::Rect SubmenuView::CalculateDropIndicatorBounds(
MenuItemView* item,
MenuDelegate::DropPosition position) {
- DCHECK(position != MenuDelegate::DROP_NONE);
+ DCHECK(position != MenuDelegate::DropPosition::kNone);
gfx::Rect item_bounds = item->bounds();
switch (position) {
- case MenuDelegate::DROP_BEFORE:
+ case MenuDelegate::DropPosition::kBefore:
item_bounds.Offset(0, -kDropIndicatorHeight / 2);
item_bounds.set_height(kDropIndicatorHeight);
return item_bounds;
- case MenuDelegate::DROP_AFTER:
+ case MenuDelegate::DropPosition::kAfter:
item_bounds.Offset(0, item_bounds.height() - kDropIndicatorHeight / 2);
item_bounds.set_height(kDropIndicatorHeight);
return item_bounds;
@@ -543,4 +537,8 @@ bool SubmenuView::OnScroll(float dx, float dy) {
return false;
}
+BEGIN_METADATA(SubmenuView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/menu/submenu_view.h b/chromium/ui/views/controls/menu/submenu_view.h
index 3009bd48f73..84ecd3cd6db 100644
--- a/chromium/ui/views/controls/menu/submenu_view.h
+++ b/chromium/ui/views/controls/menu/submenu_view.h
@@ -44,10 +44,9 @@ class VIEWS_EXPORT SubmenuView : public View,
public PrefixDelegate,
public ScrollDelegate {
public:
- using MenuItems = std::vector<MenuItemView*>;
+ METADATA_HEADER(SubmenuView);
- // The submenu's class name.
- static const char kViewClassName[];
+ using MenuItems = std::vector<MenuItemView*>;
// Creates a SubmenuView for the specified menu item.
explicit SubmenuView(MenuItemView* parent);
@@ -172,8 +171,6 @@ class VIEWS_EXPORT SubmenuView : public View,
}
protected:
- // Overridden from View:
- const char* GetClassName() const override;
// View method. Overridden to schedule a paint. We do this so that when
// scrolling occurs, everything is repainted correctly.
diff --git a/chromium/ui/views/controls/message_box_view.cc b/chromium/ui/views/controls/message_box_view.cc
index 73b3997b43f..aa9ce75b487 100644
--- a/chromium/ui/views/controls/message_box_view.cc
+++ b/chromium/ui/views/controls/message_box_view.cc
@@ -72,9 +72,6 @@ namespace views {
///////////////////////////////////////////////////////////////////////////////
// MessageBoxView, public:
-// static
-const char MessageBoxView::kViewClassName[] = "MessageBoxView";
-
MessageBoxView::InitParams::InitParams(const base::string16& message)
: options(NO_OPTIONS),
message(message),
@@ -85,7 +82,8 @@ MessageBoxView::InitParams::InitParams(const base::string16& message)
MessageBoxView::InitParams::~InitParams() = default;
MessageBoxView::MessageBoxView(const InitParams& params)
- : message_width_(params.message_width) {
+ : inter_row_vertical_spacing_(params.inter_row_vertical_spacing),
+ message_width_(params.message_width) {
Init(params);
}
@@ -168,20 +166,18 @@ bool MessageBoxView::AcceleratorPressed(const ui::Accelerator& accelerator) {
// Don't intercept Ctrl-C if we only use a single message label supporting
// text selection.
- if (message_labels_.size() == 1u && message_labels_[0]->selectable())
+ if (message_labels_.size() == 1u && message_labels_[0]->GetSelectable())
return false;
- ui::ScopedClipboardWriter scw(ui::CLIPBOARD_TYPE_COPY_PASTE);
- scw.WriteText(std::accumulate(
- message_labels_.cbegin(), message_labels_.cend(), base::string16(),
- [](base::string16& left, Label* right) { return left + right->text(); }));
+ ui::ScopedClipboardWriter scw(ui::ClipboardType::kCopyPaste);
+ scw.WriteText(std::accumulate(message_labels_.cbegin(),
+ message_labels_.cend(), base::string16(),
+ [](base::string16& left, Label* right) {
+ return left + right->GetText();
+ }));
return true;
}
-const char* MessageBoxView::GetClassName() const {
- return kViewClassName;
-}
-
///////////////////////////////////////////////////////////////////////////////
// MessageBoxView, private:
@@ -192,8 +188,8 @@ void MessageBoxView::Init(const InitParams& params) {
// We explicitly set insets on the message contents instead of the scroll view
// so that the scroll view borders are not capped by dialog insets.
message_contents->SetBorder(CreateEmptyBorder(GetHorizontalInsets(provider)));
- message_contents->SetLayoutManager(
- std::make_unique<views::BoxLayout>(views::BoxLayout::kVertical));
+ message_contents->SetLayoutManager(std::make_unique<views::BoxLayout>(
+ views::BoxLayout::Orientation::kVertical));
auto add_label = [&message_contents, this](
const base::string16& text, bool multi_line,
gfx::HorizontalAlignment alignment) {
@@ -232,15 +228,12 @@ void MessageBoxView::Init(const InitParams& params) {
prompt_field_ = AddChildView(std::move(prompt_field));
}
- inter_row_vertical_spacing_ = params.inter_row_vertical_spacing;
-
ResetLayoutManager();
}
void MessageBoxView::ResetLayoutManager() {
// Initialize the Grid Layout Manager used for this dialog box.
- GridLayout* layout =
- SetLayoutManager(std::make_unique<views::GridLayout>(this));
+ GridLayout* layout = SetLayoutManager(std::make_unique<views::GridLayout>());
// Add the column set for the message displayed at the top of the dialog box.
constexpr int kMessageViewColumnSetId = 0;
@@ -262,27 +255,27 @@ void MessageBoxView::ResetLayoutManager() {
}
layout->StartRow(0, kMessageViewColumnSetId);
- layout->AddView(scroll_view_);
+ layout->AddExistingView(scroll_view_);
views::DialogContentType trailing_content_type = views::TEXT;
if (prompt_field_) {
layout->AddPaddingRow(0, inter_row_vertical_spacing_);
layout->StartRow(0, kExtraViewColumnSetId);
- layout->AddView(prompt_field_);
+ layout->AddExistingView(prompt_field_);
trailing_content_type = views::CONTROL;
}
if (checkbox_) {
layout->AddPaddingRow(0, inter_row_vertical_spacing_);
layout->StartRow(0, kExtraViewColumnSetId);
- layout->AddView(checkbox_);
+ layout->AddExistingView(checkbox_);
trailing_content_type = views::TEXT;
}
if (link_) {
layout->AddPaddingRow(0, inter_row_vertical_spacing_);
layout->StartRow(0, kExtraViewColumnSetId);
- layout->AddView(link_);
+ layout->AddExistingView(link_);
trailing_content_type = views::TEXT;
}
@@ -303,4 +296,8 @@ gfx::Insets MessageBoxView::GetHorizontalInsets(
return horizontal_insets;
}
+BEGIN_METADATA(MessageBoxView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/message_box_view.h b/chromium/ui/views/controls/message_box_view.h
index 48262a52ba8..9660518cbbf 100644
--- a/chromium/ui/views/controls/message_box_view.h
+++ b/chromium/ui/views/controls/message_box_view.h
@@ -29,8 +29,7 @@ class Textfield;
// and Cancel buttons.
class VIEWS_EXPORT MessageBoxView : public View {
public:
- // Internal class name.
- static const char kViewClassName[];
+ METADATA_HEADER(MessageBoxView);
enum Options {
NO_OPTIONS = 0,
@@ -94,7 +93,6 @@ class VIEWS_EXPORT MessageBoxView : public View {
const ViewHierarchyChangedDetails& details) override;
// Handles Ctrl-C and writes the message in the system clipboard.
bool AcceleratorPressed(const ui::Accelerator& accelerator) override;
- const char* GetClassName() const override;
private:
// Sets up the layout manager and initializes the message labels and prompt
@@ -124,10 +122,10 @@ class VIEWS_EXPORT MessageBoxView : public View {
Link* link_ = nullptr;
// Spacing between rows in the grid layout.
- int inter_row_vertical_spacing_ = 0;
+ const int inter_row_vertical_spacing_ = 0;
// Maximum width of the message label.
- int message_width_;
+ int message_width_ = 0;
DISALLOW_COPY_AND_ASSIGN(MessageBoxView);
};
diff --git a/chromium/ui/views/controls/native/native_view_host.cc b/chromium/ui/views/controls/native/native_view_host.cc
index 9d2c42e2ef4..d6116fdbdd0 100644
--- a/chromium/ui/views/controls/native/native_view_host.cc
+++ b/chromium/ui/views/controls/native/native_view_host.cc
@@ -14,7 +14,6 @@
namespace views {
// static
-const char NativeViewHost::kViewClassName[] = "NativeViewHost";
const char kWidgetNativeViewHostKey[] = "WidgetNativeViewHost";
////////////////////////////////////////////////////////////////////////////////
@@ -195,10 +194,6 @@ void NativeViewHost::ViewHierarchyChanged(
}
}
-const char* NativeViewHost::GetClassName() const {
- return kViewClassName;
-}
-
void NativeViewHost::OnFocus() {
if (native_view_)
native_wrapper_->SetFocus();
@@ -256,4 +251,8 @@ void NativeViewHost::ClearFocus() {
}
}
+BEGIN_METADATA(NativeViewHost)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/native/native_view_host.h b/chromium/ui/views/controls/native/native_view_host.h
index c64341390fc..2a6cfc54d86 100644
--- a/chromium/ui/views/controls/native/native_view_host.h
+++ b/chromium/ui/views/controls/native/native_view_host.h
@@ -28,8 +28,7 @@ extern const char kWidgetNativeViewHostKey[];
// the platform-specific work of manipulating the underlying OS widget type.
class VIEWS_EXPORT NativeViewHost : public View {
public:
- // The NativeViewHost's class name.
- static const char kViewClassName[];
+ METADATA_HEADER(NativeViewHost);
NativeViewHost();
~NativeViewHost() override;
@@ -104,7 +103,6 @@ class VIEWS_EXPORT NativeViewHost : public View {
void OnVisibleBoundsChanged() override;
void ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) override;
- const char* GetClassName() const override;
private:
friend class test::NativeViewHostTestBase;
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 6e97d8e28d7..b8837382ab2 100644
--- a/chromium/ui/views/controls/native/native_view_host_aura.cc
+++ b/chromium/ui/views/controls/native/native_view_host_aura.cc
@@ -24,7 +24,6 @@
#include "ui/views/view_class_properties.h"
#include "ui/views/view_constants_aura.h"
#include "ui/views/widget/widget.h"
-#include "ui/wm/core/window_util.h"
namespace views {
@@ -271,15 +270,8 @@ void NativeViewHostAura::OnWindowBoundsChanged(
const gfx::Rect& old_bounds,
const gfx::Rect& new_bounds,
ui::PropertyChangeReason reason) {
- if (mask_) {
- // Having a mask means this layer has a render surface of its own. This
- // means we want this layer snapped as the render surface uses this layer
- // (its primary layer) to snap to the physical pixel grid.
- // See https://crbug.com/843250 for more details.
- wm::SnapWindowToPixelBoundary(window);
-
+ if (mask_)
mask_->layer()->SetBounds(gfx::Rect(host_->native_view()->bounds().size()));
- }
}
void NativeViewHostAura::OnWindowDestroying(aura::Window* window) {
@@ -346,13 +338,6 @@ void NativeViewHostAura::InstallMask() {
if (!mask_)
return;
if (host_->native_view()) {
- // Setting a mask triggers this layer to have a render surface of its own.
- // This means we cannot skip computing its subpixel offset positioning as
- // the render surface uses this layer (its primary layer) to snap to the
- // physical pixel grid.
- // See https://crbug.com/843250 for more details.
- wm::SnapWindowToPixelBoundary(host_->native_view());
-
mask_->layer()->SetBounds(gfx::Rect(host_->native_view()->bounds().size()));
host_->native_view()->layer()->SetMaskLayer(mask_->layer());
}
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 04e4e620f72..01b34f7f6a8 100644
--- a/chromium/ui/views/controls/native/native_view_host_mac.h
+++ b/chromium/ui/views/controls/native/native_view_host_mac.h
@@ -18,7 +18,7 @@ class ViewsHostableView;
namespace views {
-class BridgedNativeWidgetHostImpl;
+class NativeWidgetMacNSWindowHost;
class NativeViewHost;
// Mac implementation of NativeViewHostWrapper.
@@ -30,8 +30,7 @@ class NativeViewHostMac : public NativeViewHostWrapper,
// ViewsHostableView::Host:
ui::Layer* GetUiLayer() const override;
- remote_cocoa::mojom::BridgeFactory* GetRemoteCocoaApplication()
- const override;
+ remote_cocoa::mojom::Application* GetRemoteCocoaApplication() const override;
uint64_t GetNSViewId() const override;
void OnHostableViewDestroying() override;
@@ -57,8 +56,8 @@ class NativeViewHostMac : public NativeViewHostWrapper,
void SetParentAccessible(gfx::NativeViewAccessible) override;
private:
- // Return the BridgedNativeWidgetHostImpl for this hosted view.
- BridgedNativeWidgetHostImpl* GetBridgedNativeWidgetHost() const;
+ // Return the NativeWidgetMacNSWindowHost for this hosted view.
+ NativeWidgetMacNSWindowHost* GetNSWindowHost() const;
// Our associated NativeViewHost. Owns this.
NativeViewHost* host_;
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 9604ab93a9b..be0e09c0953 100644
--- a/chromium/ui/views/controls/native/native_view_host_mac.mm
+++ b/chromium/ui/views/controls/native/native_view_host_mac.mm
@@ -8,7 +8,7 @@
#include "base/mac/foundation_util.h"
#import "ui/accessibility/platform/ax_platform_node_mac.h"
-#import "ui/views/cocoa/bridged_native_widget_host_impl.h"
+#import "ui/views/cocoa/native_widget_mac_ns_window_host.h"
#include "ui/views/controls/native/native_view_host.h"
#include "ui/views/widget/native_widget_mac.h"
#include "ui/views/widget/widget.h"
@@ -40,9 +40,8 @@ NativeViewHostMac::NativeViewHostMac(NativeViewHost* host) : host_(host) {
NativeViewHostMac::~NativeViewHostMac() {
}
-BridgedNativeWidgetHostImpl* NativeViewHostMac::GetBridgedNativeWidgetHost()
- const {
- return BridgedNativeWidgetHostImpl::GetFromNativeWindow(
+NativeWidgetMacNSWindowHost* NativeViewHostMac::GetNSWindowHost() const {
+ return NativeWidgetMacNSWindowHost::GetFromNativeWindow(
host_->GetWidget()->GetNativeWindow());
}
@@ -53,19 +52,19 @@ ui::Layer* NativeViewHostMac::GetUiLayer() const {
return host_->layer();
}
-remote_cocoa::mojom::BridgeFactory*
-NativeViewHostMac::GetRemoteCocoaApplication() const {
- if (auto* bridge_host = GetBridgedNativeWidgetHost()) {
- if (bridge_host->bridge_factory_host())
- return bridge_host->bridge_factory_host()->GetFactory();
+remote_cocoa::mojom::Application* NativeViewHostMac::GetRemoteCocoaApplication()
+ const {
+ if (auto* window_host = GetNSWindowHost()) {
+ if (auto* application_host = window_host->application_host())
+ return application_host->GetApplication();
}
return nullptr;
}
uint64_t NativeViewHostMac::GetNSViewId() const {
- auto* bridge_host = GetBridgedNativeWidgetHost();
- if (bridge_host)
- return bridge_host->GetRootViewNSViewId();
+ auto* window_host = GetNSWindowHost();
+ if (window_host)
+ return window_host->GetRootViewNSViewId();
return 0;
}
@@ -88,13 +87,13 @@ void NativeViewHostMac::AttachNativeView() {
}
EnsureNativeViewHasNoChildWidgets(native_view_);
- auto* bridge_host = GetBridgedNativeWidgetHost();
- CHECK(bridge_host);
+ auto* window_host = GetNSWindowHost();
+ CHECK(window_host);
// TODO(https://crbug.com/933679): This is lifted out the ViewsHostableAttach
// call below because of crashes being observed in the field.
NSView* superview =
- bridge_host->native_widget_mac()->GetNativeView().GetNativeNSView();
+ window_host->native_widget_mac()->GetNativeView().GetNativeNSView();
[superview addSubview:native_view_];
if (native_view_hostable_) {
@@ -105,7 +104,7 @@ void NativeViewHostMac::AttachNativeView() {
host_->parent()->GetNativeViewAccessible());
}
- bridge_host->SetAssociationForView(host_, native_view_);
+ window_host->SetAssociationForView(host_, native_view_);
}
void NativeViewHostMac::NativeViewDetaching(bool destroyed) {
@@ -131,10 +130,10 @@ void NativeViewHostMac::NativeViewDetaching(bool destroyed) {
}
EnsureNativeViewHasNoChildWidgets(native_view_);
- auto* bridge_host = GetBridgedNativeWidgetHost();
- // BridgedNativeWidgetImpl can be null when Widget is closing.
- if (bridge_host)
- bridge_host->ClearAssociationForView(host_);
+ auto* window_host = GetNSWindowHost();
+ // NativeWidgetNSWindowBridge can be null when Widget is closing.
+ if (window_host)
+ window_host->ClearAssociationForView(host_);
native_view_.reset();
}
diff --git a/chromium/ui/views/controls/progress_bar.cc b/chromium/ui/views/controls/progress_bar.cc
index deb1d931973..e37b7c973bf 100644
--- a/chromium/ui/views/controls/progress_bar.cc
+++ b/chromium/ui/views/controls/progress_bar.cc
@@ -42,9 +42,6 @@ void AddPossiblyRoundRectToPath(const gfx::Rect& rectangle,
} // namespace
-// static
-const char ProgressBar::kViewClassName[] = "ProgressBar";
-
ProgressBar::ProgressBar(int preferred_height, bool allow_round_corner)
: preferred_height_(preferred_height),
allow_round_corner_(allow_round_corner) {
@@ -65,10 +62,6 @@ gfx::Size ProgressBar::CalculatePreferredSize() const {
return pref_size;
}
-const char* ProgressBar::GetClassName() const {
- return kViewClassName;
-}
-
void ProgressBar::OnPaint(gfx::Canvas* canvas) {
if (IsIndeterminate())
return OnPaintIndeterminate(canvas);
@@ -212,4 +205,8 @@ void ProgressBar::OnPaintIndeterminate(gfx::Canvas* canvas) {
canvas->DrawPath(slice_path, slice_flags);
}
+BEGIN_METADATA(ProgressBar)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/progress_bar.h b/chromium/ui/views/controls/progress_bar.h
index 58909de1e7c..131451fb0f9 100644
--- a/chromium/ui/views/controls/progress_bar.h
+++ b/chromium/ui/views/controls/progress_bar.h
@@ -20,6 +20,8 @@ namespace views {
// Progress bar is a control that indicates progress visually.
class VIEWS_EXPORT ProgressBar : public View, public gfx::AnimationDelegate {
public:
+ METADATA_HEADER(ProgressBar);
+
// The preferred height parameter makes it easier to use a ProgressBar with
// layout managers that size to preferred size.
explicit ProgressBar(int preferred_height = 5,
@@ -29,7 +31,6 @@ class VIEWS_EXPORT ProgressBar : public View, public gfx::AnimationDelegate {
// Overridden from View:
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
gfx::Size CalculatePreferredSize() const override;
- const char* GetClassName() const override;
void OnPaint(gfx::Canvas* canvas) override;
double current_value() const { return current_value_; }
@@ -49,8 +50,6 @@ class VIEWS_EXPORT ProgressBar : public View, public gfx::AnimationDelegate {
int preferred_height() const { return preferred_height_; }
private:
- static const char kViewClassName[];
-
// gfx::AnimationDelegate:
void AnimationProgressed(const gfx::Animation* animation) override;
void AnimationEnded(const gfx::Animation* animation) override;
diff --git a/chromium/ui/views/controls/resize_area.cc b/chromium/ui/views/controls/resize_area.cc
index 51c8f95502c..e0045d3f9e7 100644
--- a/chromium/ui/views/controls/resize_area.cc
+++ b/chromium/ui/views/controls/resize_area.cc
@@ -12,8 +12,6 @@
namespace views {
-const char ResizeArea::kViewClassName[] = "ResizeArea";
-
ResizeArea::ResizeArea(ResizeAreaDelegate* delegate)
: delegate_(delegate),
initial_position_(0) {
@@ -21,10 +19,6 @@ ResizeArea::ResizeArea(ResizeAreaDelegate* delegate)
ResizeArea::~ResizeArea() = default;
-const char* ResizeArea::GetClassName() const {
- return kViewClassName;
-}
-
gfx::NativeCursor ResizeArea::GetCursor(const ui::MouseEvent& event) {
return GetEnabled() ? GetNativeEastWestResizeCursor() : gfx::kNullCursor;
}
@@ -85,4 +79,8 @@ void ResizeArea::SetInitialPosition(int event_x) {
initial_position_ = point.x();
}
+BEGIN_METADATA(ResizeArea)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/resize_area.h b/chromium/ui/views/controls/resize_area.h
index 31dc6e35235..77567910b90 100644
--- a/chromium/ui/views/controls/resize_area.h
+++ b/chromium/ui/views/controls/resize_area.h
@@ -17,13 +17,12 @@ class ResizeAreaDelegate;
// An invisible area that acts like a horizontal resizer.
class VIEWS_EXPORT ResizeArea : public View {
public:
- static const char kViewClassName[];
+ METADATA_HEADER(ResizeArea);
explicit ResizeArea(ResizeAreaDelegate* delegate);
~ResizeArea() override;
// views::View:
- const char* GetClassName() const override;
gfx::NativeCursor GetCursor(const ui::MouseEvent& event) override;
void OnGestureEvent(ui::GestureEvent* event) override;
bool OnMousePressed(const ui::MouseEvent& event) override;
diff --git a/chromium/ui/views/controls/resize_area_unittest.cc b/chromium/ui/views/controls/resize_area_unittest.cc
index 8a593488d67..0e14fca5681 100644
--- a/chromium/ui/views/controls/resize_area_unittest.cc
+++ b/chromium/ui/views/controls/resize_area_unittest.cc
@@ -9,7 +9,6 @@
#include "base/bind.h"
#include "build/build_config.h"
#include "testing/gtest/include/gtest/gtest.h"
-#include "ui/aura/window.h"
#include "ui/events/test/event_generator.h"
#include "ui/views/controls/resize_area_delegate.h"
#include "ui/views/test/views_test_base.h"
@@ -17,6 +16,10 @@
#include "ui/views/widget/widget.h"
#include "ui/views/widget/widget_utils.h"
+#if !defined(OS_MACOSX)
+#include "ui/aura/window.h"
+#endif
+
namespace {
// Constants used by the ResizeAreaTest.SuccessfulGestureDrag test to simulate
// a gesture drag by |kGestureScrollDistance| resulting from
diff --git a/chromium/ui/views/controls/scroll_view.cc b/chromium/ui/views/controls/scroll_view.cc
index a7739588d67..f6616623ce7 100644
--- a/chromium/ui/views/controls/scroll_view.cc
+++ b/chromium/ui/views/controls/scroll_view.cc
@@ -24,8 +24,6 @@
namespace views {
-const char ScrollView::kViewClassName[] = "ScrollView";
-
namespace {
class ScrollCornerView : public View {
@@ -114,8 +112,6 @@ class ScrollView::Viewport : public View {
explicit Viewport(ScrollView* scroll_view) : scroll_view_(scroll_view) {}
~Viewport() override = default;
- const char* GetClassName() const override { return "ScrollView::Viewport"; }
-
void ScrollRectToVisible(const gfx::Rect& rect) override {
if (children().empty() || !parent())
return;
@@ -279,9 +275,12 @@ void ScrollView::SetHeader(std::nullptr_t) {
}
void ScrollView::SetBackgroundColor(SkColor color) {
+ if (background_color_data_.color == color)
+ return;
background_color_data_.color = color;
use_color_id_ = false;
UpdateBackground();
+ OnPropertyChanged(&background_color_data_, kPropertyEffectsPaint);
}
void ScrollView::SetBackgroundThemeColorId(ui::NativeTheme::ColorId color_id) {
@@ -298,6 +297,20 @@ gfx::Rect ScrollView::GetVisibleRect() const {
contents_viewport_->height());
}
+void ScrollView::SetHideHorizontalScrollBar(bool visible) {
+ if (hide_horizontal_scrollbar_ == visible)
+ return;
+ hide_horizontal_scrollbar_ = visible;
+ OnPropertyChanged(&hide_horizontal_scrollbar_, kPropertyEffectsPaint);
+}
+
+void ScrollView::SetDrawOverflowIndicator(bool draw_overflow_indicator) {
+ if (draw_overflow_indicator_ == draw_overflow_indicator)
+ return;
+ draw_overflow_indicator_ = draw_overflow_indicator;
+ OnPropertyChanged(&draw_overflow_indicator, kPropertyEffectsPaint);
+}
+
void ScrollView::ClipHeightTo(int min_height, int max_height) {
min_height_ = min_height;
max_height_ = max_height;
@@ -336,6 +349,7 @@ void ScrollView::SetHasFocusIndicator(bool has_focus_indicator) {
focus_ring_->SchedulePaint();
SchedulePaint();
+ OnPropertyChanged(&has_focus_indicator, kPropertyEffectsPaint);
}
gfx::Size ScrollView::CalculatePreferredSize() const {
@@ -623,10 +637,6 @@ void ScrollView::OnGestureEvent(ui::GestureEvent* event) {
}
}
-const char* ScrollView::GetClassName() const {
- return kViewClassName;
-}
-
void ScrollView::OnThemeChanged() {
UpdateBorder();
if (use_color_id_)
@@ -953,6 +963,16 @@ void ScrollView::UpdateOverflowIndicatorVisibility(
offset.x() < horiz_sb_->GetMaxPosition() && draw_overflow_indicator_);
}
+BEGIN_METADATA(ScrollView)
+METADATA_PARENT_CLASS(View)
+ADD_READONLY_PROPERTY_METADATA(ScrollView, int, MinHeight)
+ADD_READONLY_PROPERTY_METADATA(ScrollView, int, MaxHeight)
+ADD_PROPERTY_METADATA(ScrollView, SkColor, BackgroundColor)
+ADD_PROPERTY_METADATA(ScrollView, bool, DrawOverflowIndicator)
+ADD_PROPERTY_METADATA(ScrollView, bool, HasFocusIndicator)
+ADD_PROPERTY_METADATA(ScrollView, bool, HideHorizontalScrollBar)
+END_METADATA()
+
// VariableRowHeightScrollHelper ----------------------------------------------
VariableRowHeightScrollHelper::VariableRowHeightScrollHelper(
diff --git a/chromium/ui/views/controls/scroll_view.h b/chromium/ui/views/controls/scroll_view.h
index e83fd367c52..cebafcdf217 100644
--- a/chromium/ui/views/controls/scroll_view.h
+++ b/chromium/ui/views/controls/scroll_view.h
@@ -43,7 +43,7 @@ class Separator;
class VIEWS_EXPORT ScrollView : public View, public ScrollBarController {
public:
- static const char kViewClassName[];
+ METADATA_HEADER(ScrollView);
ScrollView();
@@ -77,6 +77,10 @@ class VIEWS_EXPORT ScrollView : public View, public ScrollBarController {
}
void SetHeader(std::nullptr_t);
+ int GetMaxHeight() const { return max_height_; }
+
+ int GetMinHeight() const { return min_height_; }
+
// The background color can be configured in two distinct ways:
// . By way of SetBackgroundThemeColorId(). This is the default and when
// called the background color comes from the theme (and changes if the
@@ -84,19 +88,21 @@ class VIEWS_EXPORT ScrollView : public View, public ScrollBarController {
// . By way of setting an explicit color, i.e. SetBackgroundColor(). Use
// SK_ColorTRANSPARENT if you don't want any color, but be warned this
// produces awful results when layers are used with subpixel rendering.
+ SkColor GetBackgroundColor() const;
void SetBackgroundColor(SkColor color);
+
void SetBackgroundThemeColorId(ui::NativeTheme::ColorId color_id);
// Returns the visible region of the content View.
gfx::Rect GetVisibleRect() const;
- void set_hide_horizontal_scrollbar(bool visible) {
- hide_horizontal_scrollbar_ = visible;
- }
+ bool GetUseColorId() const { return use_color_id_; }
- void set_draw_overflow_indicator(bool draw_overflow_indicator) {
- draw_overflow_indicator_ = draw_overflow_indicator;
- }
+ bool GetHideHorizontalScrollBar() const { return hide_horizontal_scrollbar_; }
+ void SetHideHorizontalScrollBar(bool visible);
+
+ bool GetDrawOverflowIndicator() const { return draw_overflow_indicator_; }
+ void SetDrawOverflowIndicator(bool draw_overflow_indicator);
// Turns this scroll view into a bounded scroll view, with a fixed height.
// By default, a ScrollView will stretch to fill its outer container.
@@ -119,7 +125,8 @@ class VIEWS_EXPORT ScrollView : public View, public ScrollBarController {
void SetHorizontalScrollBar(ScrollBar* horiz_sb);
void SetVerticalScrollBar(ScrollBar* vert_sb);
- // Sets whether this ScrollView has a focus indicator or not.
+ // Gets/Sets whether this ScrollView has a focus indicator or not.
+ bool GetHasFocusIndicator() const { return draw_focus_indicator_; }
void SetHasFocusIndicator(bool has_focus_indicator);
// View overrides:
@@ -130,7 +137,6 @@ class VIEWS_EXPORT ScrollView : public View, public ScrollBarController {
bool OnMouseWheel(const ui::MouseWheelEvent& e) override;
void OnScrollEvent(ui::ScrollEvent* event) override;
void OnGestureEvent(ui::GestureEvent* event) override;
- const char* GetClassName() const override;
void OnThemeChanged() override;
// ScrollBarController overrides:
@@ -208,7 +214,6 @@ class VIEWS_EXPORT ScrollView : public View, public ScrollBarController {
void UpdateBorder();
void UpdateBackground();
- SkColor GetBackgroundColor() const;
// Positions each overflow indicator against their respective content edge.
void PositionOverflowIndicators();
diff --git a/chromium/ui/views/controls/scroll_view_unittest.cc b/chromium/ui/views/controls/scroll_view_unittest.cc
index 9a2125e09fc..685261b3d1c 100644
--- a/chromium/ui/views/controls/scroll_view_unittest.cc
+++ b/chromium/ui/views/controls/scroll_view_unittest.cc
@@ -1514,7 +1514,7 @@ TEST_F(ScrollViewTest, IgnoreOverlapWithHiddenHorizontalScroll) {
/* horizontal */ false, /* overlaps_content */ false, kThickness));
// Also, let's turn off horizontal scroll bar.
- scroll_view_->set_hide_horizontal_scrollbar(true);
+ scroll_view_->SetHideHorizontalScrollBar(true);
View* contents = InstallContents();
contents->SetBoundsRect(gfx::Rect(0, 0, 300, 300));
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 d9adbdd3658..122d1c13caa 100644
--- a/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.cc
+++ b/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.cc
@@ -42,4 +42,8 @@ void BaseScrollBarButton::RepeaterNotifyClick() {
Button::NotifyClick(event);
}
+BEGIN_METADATA(BaseScrollBarButton)
+METADATA_PARENT_CLASS(Button)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.h b/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.h
index 245d60f0861..052f5f1f62f 100644
--- a/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.h
+++ b/chromium/ui/views/controls/scrollbar/base_scroll_bar_button.h
@@ -24,6 +24,8 @@ namespace views {
///////////////////////////////////////////////////////////////////////////////
class VIEWS_EXPORT BaseScrollBarButton : public Button {
public:
+ METADATA_HEADER(BaseScrollBarButton);
+
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 f6f78dbde7c..3221a12abf4 100644
--- a/chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc
+++ b/chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.cc
@@ -130,4 +130,8 @@ bool BaseScrollBarThumb::IsHorizontal() const {
return scroll_bar_->IsHorizontal();
}
+BEGIN_METADATA(BaseScrollBarThumb)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
} // namespace views
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 a8f29dafe80..e43da4686c0 100644
--- a/chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.h
+++ b/chromium/ui/views/controls/scrollbar/base_scroll_bar_thumb.h
@@ -29,6 +29,8 @@ class ScrollBar;
///////////////////////////////////////////////////////////////////////////////
class VIEWS_EXPORT BaseScrollBarThumb : public View {
public:
+ METADATA_HEADER(BaseScrollBarThumb);
+
explicit BaseScrollBarThumb(ScrollBar* scroll_bar);
~BaseScrollBarThumb() override;
diff --git a/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.h b/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.h
index a839959b93a..42c1d11cc95 100644
--- a/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.h
+++ b/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.h
@@ -24,6 +24,8 @@ class VIEWS_EXPORT CocoaScrollBar : public ScrollBar,
public ui::ImplicitAnimationObserver,
public gfx::AnimationDelegate {
public:
+ METADATA_HEADER(CocoaScrollBar);
+
explicit CocoaScrollBar(bool horizontal);
~CocoaScrollBar() override;
diff --git a/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.mm b/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
index a3cc7582a40..8d59d8936d4 100644
--- a/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
+++ b/chromium/ui/views/controls/scrollbar/cocoa_scroll_bar.mm
@@ -551,4 +551,8 @@ base::RetainingOneShotTimer* ScrollBar::GetHideTimerForTesting(
return &static_cast<CocoaScrollBar*>(scroll_bar)->hide_scrollbar_timer_;
}
+BEGIN_METADATA(CocoaScrollBar)
+METADATA_PARENT_CLASS(ScrollBar)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc b/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc
index 1e2940afc0c..06f70c996b9 100644
--- a/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc
+++ b/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.cc
@@ -192,4 +192,8 @@ void OverlayScrollBar::StartHideCountdown() {
base::BindOnce(&OverlayScrollBar::Hide, base::Unretained(this)));
}
+BEGIN_METADATA(OverlayScrollBar)
+METADATA_PARENT_CLASS(ScrollBar)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.h b/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.h
index 3ae0c0bee4a..d39b6094b9b 100644
--- a/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.h
+++ b/chromium/ui/views/controls/scrollbar/overlay_scroll_bar.h
@@ -15,6 +15,8 @@ namespace views {
// The transparent scrollbar which overlays its contents.
class VIEWS_EXPORT OverlayScrollBar : public ScrollBar {
public:
+ METADATA_HEADER(OverlayScrollBar);
+
explicit OverlayScrollBar(bool horizontal);
~OverlayScrollBar() override;
diff --git a/chromium/ui/views/controls/scrollbar/scroll_bar.cc b/chromium/ui/views/controls/scrollbar/scroll_bar.cc
index 2679f2adbdc..b272d268bab 100644
--- a/chromium/ui/views/controls/scrollbar/scroll_bar.cc
+++ b/chromium/ui/views/controls/scrollbar/scroll_bar.cc
@@ -455,4 +455,12 @@ base::Optional<int> ScrollBar::GetDesiredScrollOffset(ScrollAmount amount) {
return base::nullopt;
}
}
+
+BEGIN_METADATA(ScrollBar)
+METADATA_PARENT_CLASS(View)
+ADD_READONLY_PROPERTY_METADATA(ScrollBar, int, MaxPosition)
+ADD_READONLY_PROPERTY_METADATA(ScrollBar, int, MinPosition)
+ADD_READONLY_PROPERTY_METADATA(ScrollBar, int, Position)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/scrollbar/scroll_bar.h b/chromium/ui/views/controls/scrollbar/scroll_bar.h
index de7b9449d62..d2b54f5854e 100644
--- a/chromium/ui/views/controls/scrollbar/scroll_bar.h
+++ b/chromium/ui/views/controls/scrollbar/scroll_bar.h
@@ -75,6 +75,8 @@ class VIEWS_EXPORT ScrollBar : public View,
public ContextMenuController,
public ui::SimpleMenuModel::Delegate {
public:
+ METADATA_HEADER(ScrollBar);
+
// An enumeration of different amounts of incremental scroll, representing
// events sent from different parts of the UI/keyboard.
enum class ScrollAmount {
diff --git a/chromium/ui/views/controls/scrollbar/scroll_bar_views.cc b/chromium/ui/views/controls/scrollbar/scroll_bar_views.cc
index 37c2fd7bbed..bef64bf018c 100644
--- a/chromium/ui/views/controls/scrollbar/scroll_bar_views.cc
+++ b/chromium/ui/views/controls/scrollbar/scroll_bar_views.cc
@@ -31,7 +31,6 @@ class ScrollBarButton : public BaseScrollBarButton {
~ScrollBarButton() override;
gfx::Size CalculatePreferredSize() const override;
- const char* GetClassName() const override { return "ScrollBarButton"; }
protected:
void PaintButtonContents(gfx::Canvas* canvas) override;
@@ -51,7 +50,6 @@ class ScrollBarThumb : public BaseScrollBarThumb {
~ScrollBarThumb() override;
gfx::Size CalculatePreferredSize() const override;
- const char* GetClassName() const override { return "ScrollBarThumb"; }
protected:
void OnPaint(gfx::Canvas* canvas) override;
@@ -197,8 +195,6 @@ ui::NativeTheme::State ScrollBarThumb::GetNativeThemeState() const {
////////////////////////////////////////////////////////////////////////////////
// ScrollBarViews, public:
-const char ScrollBarViews::kViewClassName[] = "ScrollBarViews";
-
ScrollBarViews::ScrollBarViews(bool horizontal) : ScrollBar(horizontal) {
using Type = ScrollBarButton::Type;
SetThumb(new ScrollBarThumb(this));
@@ -280,10 +276,6 @@ gfx::Size ScrollBarViews::CalculatePreferredSize() const {
IsHorizontal() ? GetThickness() : 0);
}
-const char* ScrollBarViews::GetClassName() const {
- return kViewClassName;
-}
-
int ScrollBarViews::GetThickness() const {
const ui::NativeTheme* theme = GetNativeTheme();
return IsHorizontal() ? GetHorizontalScrollBarHeight(theme)
@@ -339,4 +331,8 @@ int ScrollBarViews::GetHorizontalScrollBarHeight(const ui::NativeTheme* theme) {
return std::max(track_size.height(), button_size.height());
}
+BEGIN_METADATA(ScrollBarViews)
+METADATA_PARENT_CLASS(ScrollBar)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/scrollbar/scroll_bar_views.h b/chromium/ui/views/controls/scrollbar/scroll_bar_views.h
index 847a7811c25..b7f1ada8dce 100644
--- a/chromium/ui/views/controls/scrollbar/scroll_bar_views.h
+++ b/chromium/ui/views/controls/scrollbar/scroll_bar_views.h
@@ -22,7 +22,7 @@ namespace views {
// Views implementation for the scrollbar.
class VIEWS_EXPORT ScrollBarViews : public ScrollBar, public ButtonListener {
public:
- static const char kViewClassName[];
+ METADATA_HEADER(ScrollBarViews);
// Creates new scrollbar, either horizontal or vertical.
explicit ScrollBarViews(bool horizontal);
@@ -35,7 +35,6 @@ class VIEWS_EXPORT ScrollBarViews : public ScrollBar, public ButtonListener {
void Layout() override;
void OnPaint(gfx::Canvas* canvas) override;
gfx::Size CalculatePreferredSize() const override;
- const char* GetClassName() const override;
// ScrollBar overrides:
int GetThickness() const override;
diff --git a/chromium/ui/views/controls/separator.cc b/chromium/ui/views/controls/separator.cc
index 4e1c570782b..4a9d55853d5 100644
--- a/chromium/ui/views/controls/separator.cc
+++ b/chromium/ui/views/controls/separator.cc
@@ -11,23 +11,36 @@
namespace views {
// static
-const char Separator::kViewClassName[] = "Separator";
-
-// static
const int Separator::kThickness = 1;
Separator::Separator() = default;
Separator::~Separator() = default;
+SkColor Separator::GetColor() const {
+ if (overridden_color_ == true)
+ return overridden_color_.value();
+ return 0;
+}
+
void Separator::SetColor(SkColor color) {
+ if (overridden_color_ == color)
+ return;
+
overridden_color_ = color;
- SchedulePaint();
+ OnPropertyChanged(&overridden_color_, kPropertyEffectsPaint);
+}
+
+int Separator::GetPreferredHeight() const {
+ return preferred_height_;
}
void Separator::SetPreferredHeight(int height) {
+ if (preferred_height_ == height)
+ return;
+
preferred_height_ = height;
- PreferredSizeChanged();
+ OnPropertyChanged(&preferred_height_, kPropertyEffectsPreferredSizeChanged);
}
////////////////////////////////////////////////////////////////////////////////
@@ -63,8 +76,10 @@ void Separator::OnPaint(gfx::Canvas* canvas) {
View::OnPaint(canvas);
}
-const char* Separator::GetClassName() const {
- return kViewClassName;
-}
+BEGIN_METADATA(Separator)
+METADATA_PARENT_CLASS(View)
+ADD_PROPERTY_METADATA(Separator, SkColor, Color)
+ADD_PROPERTY_METADATA(Separator, int, PreferredHeight)
+END_METADATA()
} // namespace views
diff --git a/chromium/ui/views/controls/separator.h b/chromium/ui/views/controls/separator.h
index b0674fcbe3c..f547479c86e 100644
--- a/chromium/ui/views/controls/separator.h
+++ b/chromium/ui/views/controls/separator.h
@@ -17,8 +17,7 @@ namespace views {
// other views.
class VIEWS_EXPORT Separator : public View {
public:
- // The separator's class name.
- static const char kViewClassName[];
+ METADATA_HEADER(Separator);
// The separator's thickness in dip.
static const int kThickness;
@@ -26,15 +25,16 @@ class VIEWS_EXPORT Separator : public View {
Separator();
~Separator() override;
+ SkColor GetColor() const;
void SetColor(SkColor color);
+ int GetPreferredHeight() const;
void SetPreferredHeight(int height);
// Overridden from View:
gfx::Size CalculatePreferredSize() const override;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
void OnPaint(gfx::Canvas* canvas) override;
- const char* GetClassName() const override;
private:
int preferred_height_ = kThickness;
diff --git a/chromium/ui/views/controls/slider.cc b/chromium/ui/views/controls/slider.cc
index 75432a2c8a4..183868535c0 100644
--- a/chromium/ui/views/controls/slider.cc
+++ b/chromium/ui/views/controls/slider.cc
@@ -59,9 +59,6 @@ constexpr int kSlideHighlightChangeDurationMs = 150;
} // namespace
-// static
-const char Slider::kViewClassName[] = "Slider";
-
Slider::Slider(SliderListener* listener)
: listener_(listener),
highlight_animation_(this),
@@ -79,13 +76,34 @@ Slider::Slider(SliderListener* listener)
Slider::~Slider() = default;
+float Slider::GetValue() const {
+ return value_;
+}
+
void Slider::SetValue(float value) {
SetValueInternal(value, VALUE_CHANGED_BY_API);
}
-void Slider::UpdateState(bool control_on) {
- is_active_ = control_on;
- SchedulePaint();
+bool Slider::GetEnableAccessibilityEvents() const {
+ return accessibility_events_enabled_;
+}
+
+void Slider::SetEnableAccessibilityEvents(bool enabled) {
+ if (accessibility_events_enabled_ == enabled)
+ return;
+ accessibility_events_enabled_ = enabled;
+ OnPropertyChanged(&accessibility_events_enabled_, kPropertyEffectsNone);
+}
+
+bool Slider::GetIsActive() const {
+ return is_active_;
+}
+
+void Slider::SetIsActive(bool is_active) {
+ if (is_active == is_active_)
+ return;
+ is_active_ = is_active;
+ OnPropertyChanged(&is_active_, kPropertyEffectsPaint);
}
float Slider::GetAnimatingValue() const{
@@ -143,8 +161,9 @@ void Slider::SetValueInternal(float value, SliderChangeReason reason) {
move_animation_->SetSlideDuration(kSlideValueChangeDurationMs);
move_animation_->Show();
}
+ OnPropertyChanged(&value_, kPropertyEffectsNone);
} else {
- SchedulePaint();
+ OnPropertyChanged(&value_, kPropertyEffectsPaint);
}
if (accessibility_events_enabled_) {
@@ -196,10 +215,6 @@ void Slider::OnSliderDragEnded() {
listener_->SliderDragEnded(this);
}
-const char* Slider::GetClassName() const {
- return kViewClassName;
-}
-
gfx::Size Slider::CalculatePreferredSize() const {
constexpr int kSizeMajor = 200;
constexpr int kSizeMinor = 40;
@@ -360,4 +375,11 @@ void Slider::OnGestureEvent(ui::GestureEvent* event) {
}
}
+BEGIN_METADATA(Slider)
+METADATA_PARENT_CLASS(View)
+ADD_PROPERTY_METADATA(Slider, float, Value)
+ADD_PROPERTY_METADATA(Slider, bool, EnableAccessibilityEvents)
+ADD_PROPERTY_METADATA(Slider, bool, IsActive)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/slider.h b/chromium/ui/views/controls/slider.h
index 64869aa37c4..7ecf9eb0fba 100644
--- a/chromium/ui/views/controls/slider.h
+++ b/chromium/ui/views/controls/slider.h
@@ -44,21 +44,20 @@ class VIEWS_EXPORT SliderListener {
class VIEWS_EXPORT Slider : public View, public gfx::AnimationDelegate {
public:
- // Internal class name.
- static const char kViewClassName[];
+ METADATA_HEADER(Slider);
explicit Slider(SliderListener* listener);
~Slider() override;
- float value() const { return value_; }
+ float GetValue() const;
void SetValue(float value);
- void set_enable_accessibility_events(bool enabled) {
- accessibility_events_enabled_ = enabled;
- }
+ bool GetEnableAccessibilityEvents() const;
+ void SetEnableAccessibilityEvents(bool enabled);
- // Update UI based on control on/off state.
- void UpdateState(bool control_on);
+ // Gets/Sets IsActive state
+ bool GetIsActive() const;
+ void SetIsActive(bool is_active);
protected:
// Returns the current position of the thumb on the slider.
@@ -92,7 +91,6 @@ class VIEWS_EXPORT Slider : public View, public gfx::AnimationDelegate {
void OnSliderDragEnded();
// views::View:
- const char* GetClassName() const override;
gfx::Size CalculatePreferredSize() const override;
bool OnMousePressed(const ui::MouseEvent& event) override;
bool OnMouseDragged(const ui::MouseEvent& event) override;
diff --git a/chromium/ui/views/controls/slider_unittest.cc b/chromium/ui/views/controls/slider_unittest.cc
index f5775d9069c..b2844dc4a0d 100644
--- a/chromium/ui/views/controls/slider_unittest.cc
+++ b/chromium/ui/views/controls/slider_unittest.cc
@@ -233,20 +233,20 @@ void SliderTest::ClickAt(int x, int y) {
TEST_F(SliderTest, UpdateFromClickHorizontal) {
ClickAt(0, 0);
- EXPECT_EQ(0.0f, slider()->value());
+ EXPECT_EQ(0.0f, slider()->GetValue());
ClickAt(max_x(), 0);
- EXPECT_EQ(1.0f, slider()->value());
+ EXPECT_EQ(1.0f, slider()->GetValue());
}
TEST_F(SliderTest, UpdateFromClickRTLHorizontal) {
base::i18n::SetICUDefaultLocale("he");
ClickAt(0, 0);
- EXPECT_EQ(1.0f, slider()->value());
+ EXPECT_EQ(1.0f, slider()->GetValue());
ClickAt(max_x(), 0);
- EXPECT_EQ(0.0f, slider()->value());
+ EXPECT_EQ(0.0f, slider()->GetValue());
}
// No touch on desktop Mac. Tracked in http://crbug.com/445520.
@@ -257,17 +257,17 @@ TEST_F(SliderTest, SliderValueForTapGesture) {
// Tap below the minimum.
slider()->SetValue(0.5);
event_generator()->GestureTapAt(gfx::Point(0, 0));
- EXPECT_FLOAT_EQ(0, slider()->value());
+ EXPECT_FLOAT_EQ(0, slider()->GetValue());
// Tap above the maximum.
slider()->SetValue(0.5);
event_generator()->GestureTapAt(gfx::Point(max_x(), max_y()));
- EXPECT_FLOAT_EQ(1, slider()->value());
+ EXPECT_FLOAT_EQ(1, slider()->GetValue());
// Tap somwhere in the middle.
slider()->SetValue(0.5);
event_generator()->GestureTapAt(gfx::Point(0.75 * max_x(), 0.75 * max_y()));
- EXPECT_NEAR(0.75, slider()->value(), 0.03);
+ EXPECT_NEAR(0.75, slider()->GetValue(), 0.03);
}
// Test the slider location after a scroll gesture.
@@ -277,14 +277,14 @@ TEST_F(SliderTest, SliderValueForScrollGesture) {
event_generator()->GestureScrollSequence(
gfx::Point(0.5 * max_x(), 0.5 * max_y()), gfx::Point(0, 0),
base::TimeDelta::FromMilliseconds(10), 5 /* steps */);
- EXPECT_EQ(0, slider()->value());
+ EXPECT_EQ(0, slider()->GetValue());
// Scroll above the maximum.
slider()->SetValue(0.5);
event_generator()->GestureScrollSequence(
gfx::Point(0.5 * max_x(), 0.5 * max_y()), gfx::Point(max_x(), max_y()),
base::TimeDelta::FromMilliseconds(10), 5 /* steps */);
- EXPECT_EQ(1, slider()->value());
+ EXPECT_EQ(1, slider()->GetValue());
// Scroll somewhere in the middle.
slider()->SetValue(0.25);
@@ -292,7 +292,7 @@ TEST_F(SliderTest, SliderValueForScrollGesture) {
gfx::Point(0.25 * max_x(), 0.25 * max_y()),
gfx::Point(0.75 * max_x(), 0.75 * max_y()),
base::TimeDelta::FromMilliseconds(10), 5 /* steps */);
- EXPECT_NEAR(0.75, slider()->value(), 0.03);
+ EXPECT_NEAR(0.75, slider()->GetValue(), 0.03);
}
// Test the slider location by adjusting it using keyboard.
@@ -301,38 +301,38 @@ TEST_F(SliderTest, SliderValueForKeyboard) {
slider()->SetValue(value);
slider()->RequestFocus();
event_generator()->PressKey(ui::VKEY_RIGHT, 0);
- EXPECT_GT(slider()->value(), value);
+ EXPECT_GT(slider()->GetValue(), value);
slider()->SetValue(value);
event_generator()->PressKey(ui::VKEY_LEFT, 0);
- EXPECT_LT(slider()->value(), value);
+ EXPECT_LT(slider()->GetValue(), value);
slider()->SetValue(value);
event_generator()->PressKey(ui::VKEY_UP, 0);
- EXPECT_GT(slider()->value(), value);
+ EXPECT_GT(slider()->GetValue(), value);
slider()->SetValue(value);
event_generator()->PressKey(ui::VKEY_DOWN, 0);
- EXPECT_LT(slider()->value(), value);
+ EXPECT_LT(slider()->GetValue(), value);
// RTL reverse left/right but not up/down.
base::i18n::SetICUDefaultLocale("he");
EXPECT_TRUE(base::i18n::IsRTL());
event_generator()->PressKey(ui::VKEY_RIGHT, 0);
- EXPECT_LT(slider()->value(), value);
+ EXPECT_LT(slider()->GetValue(), value);
slider()->SetValue(value);
event_generator()->PressKey(ui::VKEY_LEFT, 0);
- EXPECT_GT(slider()->value(), value);
+ EXPECT_GT(slider()->GetValue(), value);
slider()->SetValue(value);
event_generator()->PressKey(ui::VKEY_UP, 0);
- EXPECT_GT(slider()->value(), value);
+ EXPECT_GT(slider()->GetValue(), value);
slider()->SetValue(value);
event_generator()->PressKey(ui::VKEY_DOWN, 0);
- EXPECT_LT(slider()->value(), value);
+ EXPECT_LT(slider()->GetValue(), value);
}
// Verifies the correct SliderListener events are raised for a tap gesture.
diff --git a/chromium/ui/views/controls/styled_label.cc b/chromium/ui/views/controls/styled_label.cc
index ee21d283095..0d27d16f5ef 100644
--- a/chromium/ui/views/controls/styled_label.cc
+++ b/chromium/ui/views/controls/styled_label.cc
@@ -116,9 +116,6 @@ bool StyledLabel::StyleRange::operator<(
// StyledLabel ----------------------------------------------------------------
-// static
-const char StyledLabel::kViewClassName[] = "StyledLabel";
-
StyledLabel::StyledLabel(const base::string16& text,
StyledLabelListener* listener)
: specified_line_height_(0),
@@ -133,11 +130,18 @@ StyledLabel::StyledLabel(const base::string16& text,
StyledLabel::~StyledLabel() = default;
+const base::string16& StyledLabel::GetText() const {
+ return text_;
+}
+
void StyledLabel::SetText(const base::string16& text) {
+ if (text_ == text)
+ return;
+
text_ = text;
style_ranges_.clear();
RemoveAllChildViews(true);
- PreferredSizeChanged();
+ OnPropertyChanged(&text_, kPropertyEffectsPreferredSizeChanged);
}
gfx::FontList StyledLabel::GetDefaultFontList() const {
@@ -163,12 +167,20 @@ void StyledLabel::AddCustomView(std::unique_ptr<View> custom_view) {
custom_views_.insert(std::move(custom_view));
}
+int StyledLabel::GetTextContext() const {
+ return text_context_;
+}
+
void StyledLabel::SetTextContext(int text_context) {
if (text_context_ == text_context)
return;
text_context_ = text_context;
- PreferredSizeChanged();
+ OnPropertyChanged(&text_context_, kPropertyEffectsPreferredSizeChanged);
+}
+
+int StyledLabel::GetDefaultTextStyle() const {
+ return default_text_style_;
}
void StyledLabel::SetDefaultTextStyle(int text_style) {
@@ -176,12 +188,24 @@ void StyledLabel::SetDefaultTextStyle(int text_style) {
return;
default_text_style_ = text_style;
- PreferredSizeChanged();
+ OnPropertyChanged(&default_text_style_, kPropertyEffectsPreferredSizeChanged);
+}
+
+int StyledLabel::GetLineHeight() const {
+ return specified_line_height_;
}
void StyledLabel::SetLineHeight(int line_height) {
+ if (specified_line_height_ == line_height)
+ return;
+
specified_line_height_ = line_height;
- PreferredSizeChanged();
+ OnPropertyChanged(&specified_line_height_,
+ kPropertyEffectsPreferredSizeChanged);
+}
+
+SkColor StyledLabel::GetDisplayedOnBackgroundColor() const {
+ return displayed_on_background_color_;
}
void StyledLabel::SetDisplayedOnBackgroundColor(SkColor color) {
@@ -197,6 +221,19 @@ void StyledLabel::SetDisplayedOnBackgroundColor(SkColor color) {
(child->GetClassName() == Link::kViewClassName));
static_cast<Label*>(child)->SetBackgroundColor(color);
}
+ OnPropertyChanged(&displayed_on_background_color_, kPropertyEffectsNone);
+}
+
+bool StyledLabel::GetAutoColorReadabilityEnabled() const {
+ return auto_color_readability_enabled_;
+}
+
+void StyledLabel::SetAutoColorReadabilityEnabled(bool auto_color_readability) {
+ if (auto_color_readability_enabled_ == auto_color_readability)
+ return;
+
+ auto_color_readability_enabled_ = auto_color_readability;
+ OnPropertyChanged(&auto_color_readability, kPropertyEffectsNone);
}
void StyledLabel::SizeToFit(int max_width) {
@@ -206,17 +243,13 @@ void StyledLabel::SizeToFit(int max_width) {
SetSize(CalculateAndDoLayout(max_width, true));
}
-const char* StyledLabel::GetClassName() const {
- return kViewClassName;
-}
-
void StyledLabel::GetAccessibleNodeData(ui::AXNodeData* node_data) {
if (text_context_ == style::CONTEXT_DIALOG_TITLE)
node_data->role = ax::mojom::Role::kTitleBar;
else
node_data->role = ax::mojom::Role::kStaticText;
- node_data->SetName(text());
+ node_data->SetName(GetText());
}
gfx::Size StyledLabel::CalculatePreferredSize() const {
@@ -528,4 +561,14 @@ void StyledLabel::AdvanceOneLine(int* line_number,
offset->set_x(0);
}
+BEGIN_METADATA(StyledLabel)
+ADD_PROPERTY_METADATA(StyledLabel, base::string16, Text)
+ADD_PROPERTY_METADATA(StyledLabel, int, TextContext)
+ADD_PROPERTY_METADATA(StyledLabel, int, DefaultTextStyle)
+ADD_PROPERTY_METADATA(StyledLabel, int, LineHeight)
+ADD_PROPERTY_METADATA(StyledLabel, bool, AutoColorReadabilityEnabled)
+ADD_PROPERTY_METADATA(StyledLabel, SkColor, DisplayedOnBackgroundColor)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/styled_label.h b/chromium/ui/views/controls/styled_label.h
index e4ca7ccfaa7..38592c1795a 100644
--- a/chromium/ui/views/controls/styled_label.h
+++ b/chromium/ui/views/controls/styled_label.h
@@ -34,8 +34,7 @@ class StyledLabelListener;
// In this case, leading whitespace is ignored.
class VIEWS_EXPORT StyledLabel : public View, public LinkListener {
public:
- // Internal class name.
- static const char kViewClassName[];
+ METADATA_HEADER(StyledLabel);
// TestApi is used for tests to get internal implementation details.
class VIEWS_EXPORT TestApi {
@@ -90,10 +89,9 @@ class VIEWS_EXPORT StyledLabel : public View, public LinkListener {
~StyledLabel() override;
// Sets the text to be displayed, and clears any previous styling.
+ const base::string16& GetText() const;
void SetText(const base::string16& text);
- const base::string16& text() const { return text_; }
-
// Returns the font list that results from the default text context and style
// for ranges. This can be used as the basis for a range |custom_font|.
gfx::FontList GetDefaultFontList() const;
@@ -105,30 +103,30 @@ class VIEWS_EXPORT StyledLabel : public View, public LinkListener {
// Passes ownership of a custom view for use by RangeStyleInfo structs.
void AddCustomView(std::unique_ptr<View> custom_view);
- // Set the context of this text. All ranges have the same context.
+ // Get/Set the context of this text. All ranges have the same context.
// |text_context| must be a value from views::style::TextContext.
+ int GetTextContext() const;
void SetTextContext(int text_context);
// Set the default text style.
// |text_style| must be a value from views::style::TextStyle.
+ int GetDefaultTextStyle() const;
void SetDefaultTextStyle(int text_style);
// Get or set the distance in pixels between baselines of multi-line text.
// Default is 0, indicating the distance between lines should be the standard
// one for the label's text, font list, and platform.
+ int GetLineHeight() const;
void SetLineHeight(int height);
- // Sets the color of the background on which the label is drawn. This won't
- // be explicitly drawn, but the label will force the text color to be
+ // Gets/Sets the color of the background on which the label is drawn. This
+ // won't be explicitly drawn, but the label will force the text color to be
// readable over it.
+ SkColor GetDisplayedOnBackgroundColor() const;
void SetDisplayedOnBackgroundColor(SkColor color);
- SkColor displayed_on_background_color() const {
- return displayed_on_background_color_;
- }
- void set_auto_color_readability_enabled(bool auto_color_readability) {
- auto_color_readability_enabled_ = auto_color_readability;
- }
+ bool GetAutoColorReadabilityEnabled() const;
+ void SetAutoColorReadabilityEnabled(bool auto_color_readability);
// Resizes the label so its width is set to the width of the longest line and
// its height deduced accordingly.
@@ -139,7 +137,6 @@ class VIEWS_EXPORT StyledLabel : public View, public LinkListener {
void SizeToFit(int max_width);
// View:
- const char* GetClassName() const override;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
gfx::Size CalculatePreferredSize() const override;
int GetHeightForWidth(int w) const override;
diff --git a/chromium/ui/views/controls/styled_label_unittest.cc b/chromium/ui/views/controls/styled_label_unittest.cc
index 310bf9f02d8..8d9c27b4e3c 100644
--- a/chromium/ui/views/controls/styled_label_unittest.cc
+++ b/chromium/ui/views/controls/styled_label_unittest.cc
@@ -84,7 +84,8 @@ TEST_F(StyledLabelTest, TrailingWhitespaceiIgnored) {
styled()->Layout();
ASSERT_EQ(1u, styled()->children().size());
- EXPECT_EQ(ASCIIToUTF16("This is a test block of text"), LabelAt(0)->text());
+ EXPECT_EQ(ASCIIToUTF16("This is a test block of text"),
+ LabelAt(0)->GetText());
}
TEST_F(StyledLabelTest, RespectLeadingWhitespace) {
@@ -96,7 +97,7 @@ TEST_F(StyledLabelTest, RespectLeadingWhitespace) {
ASSERT_EQ(1u, styled()->children().size());
EXPECT_EQ(ASCIIToUTF16(" This is a test block of text"),
- LabelAt(0)->text());
+ LabelAt(0)->GetText());
}
TEST_F(StyledLabelTest, RespectLeadingSpacesInNonFirstLine) {
@@ -106,7 +107,7 @@ TEST_F(StyledLabelTest, RespectLeadingSpacesInNonFirstLine) {
styled()->SetBounds(0, 0, 1000, 1000);
styled()->Layout();
ASSERT_EQ(2u, styled()->children().size());
- EXPECT_EQ(ASCIIToUTF16(indented_line), LabelAt(1)->text());
+ EXPECT_EQ(ASCIIToUTF16(indented_line), LabelAt(1)->GetText());
}
TEST_F(StyledLabelTest, CorrectWrapAtNewline) {
@@ -120,9 +121,9 @@ TEST_F(StyledLabelTest, CorrectWrapAtNewline) {
styled()->SetBounds(0, 0, label_preferred_size.width(), 1000);
styled()->Layout();
ASSERT_EQ(2u, styled()->children().size());
- EXPECT_EQ(ASCIIToUTF16(first_line), LabelAt(0)->text());
+ EXPECT_EQ(ASCIIToUTF16(first_line), LabelAt(0)->GetText());
const auto* label_1 = LabelAt(1);
- EXPECT_EQ(ASCIIToUTF16(second_line), label_1->text());
+ EXPECT_EQ(ASCIIToUTF16(second_line), label_1->GetText());
EXPECT_EQ(styled()->GetHeightForWidth(1000), label_1->bounds().bottom());
}
@@ -137,7 +138,7 @@ TEST_F(StyledLabelTest, FirstLineNotEmptyWhenLeadingWhitespaceTooLong) {
styled()->Layout();
ASSERT_EQ(1u, styled()->children().size());
- EXPECT_EQ(ASCIIToUTF16("a"), LabelAt(0)->text());
+ EXPECT_EQ(ASCIIToUTF16("a"), LabelAt(0)->GetText());
EXPECT_EQ(label_preferred_size.height(),
styled()->GetHeightForWidth(label_preferred_size.width() / 2));
}
@@ -198,9 +199,9 @@ TEST_F(StyledLabelTest, WrapLongWords) {
EXPECT_EQ(gfx::Point(), label_0->origin());
EXPECT_EQ(gfx::Point(0, styled()->height() / 2), label_1->origin());
- EXPECT_FALSE(label_0->text().empty());
- EXPECT_FALSE(label_1->text().empty());
- EXPECT_EQ(ASCIIToUTF16(text), label_0->text() + label_1->text());
+ EXPECT_FALSE(label_0->GetText().empty());
+ EXPECT_FALSE(label_1->GetText().empty());
+ EXPECT_EQ(ASCIIToUTF16(text), label_0->GetText() + label_1->GetText());
}
TEST_F(StyledLabelTest, CreateLinks) {
@@ -383,26 +384,26 @@ TEST_F(StyledLabelTest, Color) {
// Obtain the default text color for a label.
Label* label = new Label(ASCIIToUTF16(text));
container->AddChildView(label);
- const SkColor kDefaultTextColor = label->enabled_color();
+ const SkColor kDefaultTextColor = label->GetEnabledColor();
// Obtain the default text color for a link.
Link* link = new Link(ASCIIToUTF16(text_link));
container->AddChildView(link);
- const SkColor kDefaultLinkColor = link->enabled_color();
+ const SkColor kDefaultLinkColor = link->GetEnabledColor();
- EXPECT_EQ(SK_ColorBLUE, LabelAt(0)->enabled_color());
+ EXPECT_EQ(SK_ColorBLUE, LabelAt(0)->GetEnabledColor());
EXPECT_EQ(kDefaultLinkColor,
- LabelAt(1, Link::kViewClassName)->enabled_color());
- EXPECT_EQ(kDefaultTextColor, LabelAt(2)->enabled_color());
+ LabelAt(1, Link::kViewClassName)->GetEnabledColor());
+ EXPECT_EQ(kDefaultTextColor, LabelAt(2)->GetEnabledColor());
// Test adjusted color readability.
styled()->SetDisplayedOnBackgroundColor(SK_ColorBLACK);
styled()->Layout();
label->SetBackgroundColor(SK_ColorBLACK);
- const SkColor kAdjustedTextColor = label->enabled_color();
+ const SkColor kAdjustedTextColor = label->GetEnabledColor();
EXPECT_NE(kAdjustedTextColor, kDefaultTextColor);
- EXPECT_EQ(kAdjustedTextColor, LabelAt(2)->enabled_color());
+ EXPECT_EQ(kAdjustedTextColor, LabelAt(2)->GetEnabledColor());
widget->CloseNow();
}
@@ -478,10 +479,10 @@ TEST_F(StyledLabelTest, SetTextContextAndDefaultStyle) {
styled()->Layout();
ASSERT_EQ(1u, styled()->children().size());
Label* sublabel = LabelAt(0);
- EXPECT_EQ(style::CONTEXT_DIALOG_TITLE, sublabel->text_context());
+ EXPECT_EQ(style::CONTEXT_DIALOG_TITLE, sublabel->GetTextContext());
- EXPECT_NE(SK_ColorBLACK, label.enabled_color()); // Sanity check,
- EXPECT_EQ(label.enabled_color(), sublabel->enabled_color());
+ EXPECT_NE(SK_ColorBLACK, label.GetEnabledColor()); // Sanity check,
+ EXPECT_EQ(label.GetEnabledColor(), sublabel->GetEnabledColor());
}
TEST_F(StyledLabelTest, LineHeight) {
diff --git a/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc b/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc
index 7cc8c5f06c8..905c9144c6a 100644
--- a/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc
+++ b/chromium/ui/views/controls/tabbed_pane/tabbed_pane.cc
@@ -4,7 +4,7 @@
#include "ui/views/controls/tabbed_pane/tabbed_pane.h"
-#include <memory>
+#include <utility>
#include "base/i18n/rtl.h"
#include "base/logging.h"
@@ -69,9 +69,6 @@ constexpr int kBorderThickness = 2;
} // namespace
-// static
-const char TabbedPane::kViewClassName[] = "TabbedPane";
-
// A subclass of Tab that implements the Harmony visual styling.
class MdTab : public Tab {
public:
@@ -124,23 +121,23 @@ class MdTabStrip : public TabStrip, public gfx::AnimationDelegate {
DISALLOW_COPY_AND_ASSIGN(MdTabStrip);
};
-// static
-const char Tab::kViewClassName[] = "Tab";
Tab::Tab(TabbedPane* tabbed_pane, const base::string16& title, View* contents)
: tabbed_pane_(tabbed_pane),
- title_(new Label(title, style::CONTEXT_LABEL, style::STYLE_TAB_ACTIVE)),
state_(State::kActive),
contents_(contents) {
// Calculate the size while the font list is bold.
- preferred_title_size_ = title_->GetPreferredSize();
+ auto title_label = std::make_unique<Label>(title, style::CONTEXT_LABEL,
+ style::STYLE_TAB_ACTIVE);
+ title_ = title_label.get();
+ preferred_title_size_ = title_label->GetPreferredSize();
const bool is_vertical =
tabbed_pane_->GetOrientation() == TabbedPane::Orientation::kVertical;
const bool is_highlight_style =
tabbed_pane_->GetStyle() == TabbedPane::TabStripStyle::kHighlight;
if (is_vertical)
- title_->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
+ title_label->SetHorizontalAlignment(gfx::HorizontalAlignment::ALIGN_LEFT);
if (is_highlight_style && is_vertical) {
constexpr int kTabVerticalPadding = 8;
@@ -156,8 +153,8 @@ Tab::Tab(TabbedPane* tabbed_pane, const base::string16& title, View* contents)
SetLayoutManager(std::make_unique<FillLayout>());
SetState(State::kInactive);
// Calculate the size while the font list is normal and set the max size.
- preferred_title_size_.SetToMax(title_->GetPreferredSize());
- AddChildView(title_);
+ preferred_title_size_.SetToMax(title_label->GetPreferredSize());
+ AddChildView(std::move(title_label));
// Use leaf so that name is spoken by screen reader without exposing the
// children.
@@ -177,6 +174,25 @@ void Tab::SetSelected(bool selected) {
#endif
}
+const base::string16& Tab::GetTitleText() const {
+ return title_->GetText();
+}
+
+void Tab::SetTitleText(const base::string16& text) {
+ title_->SetText(text);
+
+ // Active and inactive states use different font sizes. Find the largest size
+ // and reserve that amount of space.
+ State old_state = state_;
+ SetState(State::kActive);
+ preferred_title_size_ = GetPreferredSize();
+ SetState(State::kInactive);
+ preferred_title_size_.SetToMax(GetPreferredSize());
+ SetState(old_state);
+
+ InvalidateLayout();
+}
+
void Tab::OnStateChanged() {
ui::ResourceBundle& rb = ui::ResourceBundle::GetSharedInstance();
const bool is_highlight_mode =
@@ -254,10 +270,6 @@ gfx::Size Tab::CalculatePreferredSize() const {
return size;
}
-const char* Tab::GetClassName() const {
- return kViewClassName;
-}
-
void Tab::SetState(State state) {
if (state == state_)
return;
@@ -297,7 +309,7 @@ void Tab::OnPaint(gfx::Canvas* canvas) {
void Tab::GetAccessibleNodeData(ui::AXNodeData* data) {
data->role = ax::mojom::Role::kTab;
- data->SetName(title()->text());
+ data->SetName(title()->GetText());
data->AddBoolAttribute(ax::mojom::BoolAttribute::kSelected, selected());
}
@@ -340,6 +352,10 @@ bool Tab::OnKeyPressed(const ui::KeyEvent& event) {
tabbed_pane_->MoveSelectionBy(key == ui::VKEY_DOWN ? 1 : -1);
}
+BEGIN_METADATA(Tab)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
MdTab::MdTab(TabbedPane* tabbed_pane,
const base::string16& title,
View* contents)
@@ -388,10 +404,8 @@ void MdTab::OnFocus() {
// Do not draw focus ring in kHighlight mode.
if (tabbed_pane()->GetStyle() != TabbedPane::TabStripStyle::kHighlight) {
SetBorder(CreateSolidBorder(
- GetInsets().top(),
- SkColorSetA(GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_FocusedBorderColor),
- 0x66)));
+ GetInsets().top(), GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_FocusedBorderColor)));
}
// When the tab gains focus, send an accessibility event indicating that the
@@ -412,7 +426,6 @@ void MdTab::OnBlur() {
// static
constexpr size_t TabStrip::kNoSelectedTab;
-const char TabStrip::kViewClassName[] = "TabStrip";
TabStrip::TabStrip(TabbedPane::Orientation orientation,
TabbedPane::TabStripStyle style)
@@ -421,14 +434,15 @@ TabStrip::TabStrip(TabbedPane::Orientation orientation,
if (orientation == TabbedPane::Orientation::kHorizontal) {
constexpr int kTabStripLeadingEdgePadding = 9;
layout = std::make_unique<BoxLayout>(
- BoxLayout::kHorizontal, gfx::Insets(0, kTabStripLeadingEdgePadding));
+ BoxLayout::Orientation::kHorizontal,
+ gfx::Insets(0, kTabStripLeadingEdgePadding));
layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kEnd);
} else {
constexpr int kTabStripEdgePadding = 8;
constexpr int kTabSpacing = 8;
layout = std::make_unique<BoxLayout>(
- BoxLayout::kVertical, gfx::Insets(kTabStripEdgePadding, 0, 0, 0),
- kTabSpacing);
+ BoxLayout::Orientation::kVertical,
+ gfx::Insets(kTabStripEdgePadding, 0, 0, 0), kTabSpacing);
layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kStart);
}
layout->set_main_axis_alignment(BoxLayout::MainAxisAlignment::kStart);
@@ -442,10 +456,6 @@ TabStrip::~TabStrip() = default;
void TabStrip::OnSelectedTabChanged(Tab* from_tab, Tab* to_tab) {}
-const char* TabStrip::GetClassName() const {
- return kViewClassName;
-}
-
void TabStrip::OnPaintBorder(gfx::Canvas* canvas) {
// Do not draw border line in kHighlight mode.
if (style_ == TabbedPane::TabStripStyle::kHighlight)
@@ -541,11 +551,39 @@ Tab* TabStrip::GetTabAtDeltaFromSelected(int delta) const {
num_children);
}
+TabbedPane::Orientation TabStrip::GetOrientation() const {
+ return orientation_;
+}
+
+TabbedPane::TabStripStyle TabStrip::GetStyle() const {
+ return style_;
+}
+
+DEFINE_ENUM_CONVERTERS(TabbedPane::Orientation,
+ {TabbedPane::Orientation::kHorizontal,
+ base::ASCIIToUTF16("HORIZONTAL")},
+ {TabbedPane::Orientation::kVertical,
+ base::ASCIIToUTF16("VERTICAL")})
+
+DEFINE_ENUM_CONVERTERS(TabbedPane::TabStripStyle,
+ {TabbedPane::TabStripStyle::kBorder,
+ base::ASCIIToUTF16("BORDER")},
+ {TabbedPane::TabStripStyle::kHighlight,
+ base::ASCIIToUTF16("HIGHLIGHT")})
+
+BEGIN_METADATA(TabStrip)
+METADATA_PARENT_CLASS(View)
+ADD_READONLY_PROPERTY_METADATA(TabStrip, int, SelectedTabIndex)
+ADD_READONLY_PROPERTY_METADATA(TabStrip, TabbedPane::Orientation, Orientation)
+ADD_READONLY_PROPERTY_METADATA(TabStrip, TabbedPane::TabStripStyle, Style)
+END_METADATA()
+
MdTabStrip::MdTabStrip(TabbedPane::Orientation orientation,
TabbedPane::TabStripStyle style)
: TabStrip(orientation, style) {
if (orientation == TabbedPane::Orientation::kHorizontal) {
- auto layout = std::make_unique<BoxLayout>(BoxLayout::kHorizontal);
+ auto layout =
+ std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal);
layout->set_main_axis_alignment(BoxLayout::MainAxisAlignment::kCenter);
layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kStretch);
layout->SetDefaultFlex(1);
@@ -568,7 +606,7 @@ void MdTabStrip::OnSelectedTabChanged(Tab* from_tab, Tab* to_tab) {
DCHECK(!from_tab->selected());
DCHECK(to_tab->selected());
- if (orientation() == TabbedPane::Orientation::kHorizontal) {
+ if (GetOrientation() == TabbedPane::Orientation::kHorizontal) {
animating_from_ = gfx::Range(from_tab->GetMirroredX(),
from_tab->GetMirroredX() + from_tab->width());
animating_to_ = gfx::Range(to_tab->GetMirroredX(),
@@ -586,13 +624,13 @@ void MdTabStrip::OnSelectedTabChanged(Tab* from_tab, Tab* to_tab) {
void MdTabStrip::OnPaintBorder(gfx::Canvas* canvas) {
// Do not draw border line in kHighlight mode.
- if (style() == TabbedPane::TabStripStyle::kHighlight)
+ if (GetStyle() == TabbedPane::TabStripStyle::kHighlight)
return;
constexpr int kUnselectedBorderThickness = 1;
constexpr int kSelectedBorderThickness = 2;
const bool is_horizontal =
- orientation() == TabbedPane::Orientation::kHorizontal;
+ GetOrientation() == TabbedPane::Orientation::kHorizontal;
int max_cross_axis;
@@ -673,8 +711,10 @@ void MdTabStrip::OnPaintBorder(gfx::Canvas* canvas) {
rect = gfx::Rect(max_cross_axis - kSelectedBorderThickness, min_main_axis,
kSelectedBorderThickness, max_main_axis - min_main_axis);
}
- canvas->FillRect(rect, GetNativeTheme()->GetSystemColor(
- ui::NativeTheme::kColorId_FocusedBorderColor));
+ canvas->FillRect(
+ rect, SkColorSetA(GetNativeTheme()->GetSystemColor(
+ ui::NativeTheme::kColorId_FocusedBorderColor),
+ SK_AlphaOPAQUE));
}
void MdTabStrip::AnimationProgressed(const gfx::Animation* animation) {
@@ -687,13 +727,11 @@ void MdTabStrip::AnimationEnded(const gfx::Animation* animation) {
}
TabbedPane::TabbedPane(TabbedPane::Orientation orientation,
- TabbedPane::TabStripStyle style)
- : contents_(new View()) {
+ TabbedPane::TabStripStyle style) {
DCHECK(orientation != TabbedPane::Orientation::kHorizontal ||
style != TabbedPane::TabStripStyle::kHighlight);
- tab_strip_ = new MdTabStrip(orientation, style);
- AddChildView(tab_strip_);
- AddChildView(contents_);
+ tab_strip_ = AddChildView(std::make_unique<MdTabStrip>(orientation, style));
+ contents_ = AddChildView(std::make_unique<View>());
}
TabbedPane::~TabbedPane() = default;
@@ -707,19 +745,18 @@ size_t TabbedPane::GetTabCount() {
return contents_->children().size();
}
-void TabbedPane::AddTab(const base::string16& title, View* contents) {
- AddTabAtIndex(tab_strip_->children().size(), title, contents);
-}
-
-void TabbedPane::AddTabAtIndex(size_t index,
- const base::string16& title,
- View* contents) {
+void TabbedPane::AddTabInternal(size_t index,
+ const base::string16& title,
+ std::unique_ptr<View> contents) {
DCHECK_LE(index, GetTabCount());
contents->SetVisible(false);
+ contents->GetViewAccessibility().OverrideName(title);
+ contents->GetViewAccessibility().OverrideRole(ax::mojom::Role::kTab);
- tab_strip_->AddChildViewAt(new MdTab(this, title, contents),
- static_cast<int>(index));
- contents_->AddChildViewAt(contents, static_cast<int>(index));
+ tab_strip_->AddChildViewAt(
+ std::make_unique<MdTab>(this, title, contents.get()),
+ static_cast<int>(index));
+ contents_->AddChildViewAt(std::move(contents), static_cast<int>(index));
if (!GetSelectedTab())
SelectTabAt(index);
@@ -770,11 +807,15 @@ gfx::Size TabbedPane::CalculatePreferredSize() const {
}
TabbedPane::Orientation TabbedPane::GetOrientation() const {
- return tab_strip_->orientation();
+ return tab_strip_->GetOrientation();
}
TabbedPane::TabStripStyle TabbedPane::GetStyle() const {
- return tab_strip_->style();
+ return tab_strip_->GetStyle();
+}
+
+Tab* TabbedPane::GetTabAt(size_t index) {
+ return tab_strip_->GetTabAtIndex(index);
}
Tab* TabbedPane::GetSelectedTab() {
@@ -823,12 +864,15 @@ bool TabbedPane::AcceleratorPressed(const ui::Accelerator& accelerator) {
return MoveSelectionBy(accelerator.IsShiftDown() ? -1 : 1);
}
-const char* TabbedPane::GetClassName() const {
- return kViewClassName;
-}
-
void TabbedPane::GetAccessibleNodeData(ui::AXNodeData* node_data) {
node_data->role = ax::mojom::Role::kTabList;
+ const Tab* const selected_tab = GetSelectedTab();
+ if (selected_tab)
+ node_data->SetName(selected_tab->GetTitleText());
}
+BEGIN_METADATA(TabbedPane)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/tabbed_pane/tabbed_pane.h b/chromium/ui/views/controls/tabbed_pane/tabbed_pane.h
index 7d0ab36fe8e..ec2d831f64f 100644
--- a/chromium/ui/views/controls/tabbed_pane/tabbed_pane.h
+++ b/chromium/ui/views/controls/tabbed_pane/tabbed_pane.h
@@ -5,6 +5,8 @@
#ifndef UI_VIEWS_CONTROLS_TABBED_PANE_TABBED_PANE_H_
#define UI_VIEWS_CONTROLS_TABBED_PANE_TABBED_PANE_H_
+#include <memory>
+
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/strings/string16.h"
@@ -28,6 +30,8 @@ class TabbedPaneTest;
// may require additional polish.
class VIEWS_EXPORT TabbedPane : public View {
public:
+ METADATA_HEADER(TabbedPane);
+
// The orientation of the tab alignment.
enum class Orientation {
kHorizontal,
@@ -40,9 +44,6 @@ class VIEWS_EXPORT TabbedPane : public View {
kHighlight, // Highlight background and text of the selected tab.
};
- // Internal class name.
- static const char kViewClassName[];
-
explicit TabbedPane(Orientation orientation = Orientation::kHorizontal,
TabStripStyle style = TabStripStyle::kBorder);
~TabbedPane() override;
@@ -60,12 +61,22 @@ class VIEWS_EXPORT TabbedPane : public View {
// Adds a new tab at the end of this TabbedPane with the specified |title|.
// |contents| is the view displayed when the tab is selected and is owned by
// the TabbedPane.
- void AddTab(const base::string16& title, View* contents);
+ template <typename T>
+ T* AddTab(const base::string16& title, std::unique_ptr<T> contents) {
+ return AddTabAtIndex(GetTabCount(), title, std::move(contents));
+ }
// Adds a new tab at |index| with |title|. |contents| is the view displayed
// when the tab is selected and is owned by the TabbedPane. If the tabbed pane
// is currently empty, the new tab is selected.
- void AddTabAtIndex(size_t index, const base::string16& title, View* contents);
+ template <typename T>
+ T* AddTabAtIndex(size_t index,
+ const base::string16& title,
+ std::unique_ptr<T> contents) {
+ T* result = contents.get();
+ AddTabInternal(index, title, std::move(contents));
+ return result;
+ }
// Selects the tab at |index|, which must be valid.
void SelectTabAt(size_t index);
@@ -75,7 +86,6 @@ class VIEWS_EXPORT TabbedPane : public View {
// Overridden from View:
gfx::Size CalculatePreferredSize() const override;
- const char* GetClassName() const override;
// Gets the orientation of the tab alignment.
Orientation GetOrientation() const;
@@ -83,6 +93,9 @@ class VIEWS_EXPORT TabbedPane : public View {
// Gets the style of the tab strip.
TabStripStyle GetStyle() const;
+ // Returns the tab at the given index.
+ Tab* GetTabAt(size_t index);
+
private:
friend class FocusTraversalTest;
friend class Tab;
@@ -90,6 +103,13 @@ class VIEWS_EXPORT TabbedPane : public View {
friend class test::TabbedPaneTest;
friend class test::TabbedPaneAccessibilityMacTest;
+ // Adds a new tab at |index| with |title|. |contents| is the view displayed
+ // when the tab is selected and is owned by the TabbedPane. If the tabbed pane
+ // is currently empty, the new tab is selected.
+ void AddTabInternal(size_t index,
+ const base::string16& title,
+ std::unique_ptr<View> contents);
+
// Get the Tab (the tabstrip view, not its content) at the selected index.
Tab* GetSelectedTab();
@@ -114,17 +134,16 @@ class VIEWS_EXPORT TabbedPane : public View {
// The tab strip and contents container. The child indices of these members
// correspond to match each Tab with its respective content View.
- TabStrip* tab_strip_;
- View* contents_;
+ TabStrip* tab_strip_ = nullptr;
+ View* contents_ = nullptr;
DISALLOW_COPY_AND_ASSIGN(TabbedPane);
};
// The tab view shown in the tab strip.
-class Tab : public View {
+class VIEWS_EXPORT Tab : public View {
public:
- // Internal class name.
- static const char kViewClassName[];
+ METADATA_HEADER(Tab);
Tab(TabbedPane* tabbed_pane, const base::string16& title, View* contents);
~Tab() override;
@@ -134,13 +153,15 @@ class Tab : public View {
bool selected() const { return contents_->GetVisible(); }
void SetSelected(bool selected);
+ const base::string16& GetTitleText() const;
+ void SetTitleText(const base::string16& text);
+
// Overridden from View:
bool OnMousePressed(const ui::MouseEvent& event) override;
void OnMouseEntered(const ui::MouseEvent& event) override;
void OnMouseExited(const ui::MouseEvent& event) override;
void OnGestureEvent(ui::GestureEvent* event) override;
gfx::Size CalculatePreferredSize() const override;
- const char* GetClassName() const override;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
bool HandleAccessibleAction(const ui::AXActionData& action_data) override;
void OnFocus() override;
@@ -168,7 +189,7 @@ class Tab : public View {
void OnPaint(gfx::Canvas* canvas) override;
TabbedPane* tabbed_pane_;
- Label* title_;
+ Label* title_ = nullptr;
gfx::Size preferred_title_size_;
State state_;
// The content view associated with this tab.
@@ -180,12 +201,11 @@ class Tab : public View {
// The tab strip shown above/left of the tab contents.
class TabStrip : public View {
public:
+ METADATA_HEADER(TabStrip);
+
// The return value of GetSelectedTabIndex() when no tab is selected.
static constexpr size_t kNoSelectedTab = size_t{-1};
- // Internal class name.
- static const char kViewClassName[];
-
TabStrip(TabbedPane::Orientation orientation,
TabbedPane::TabStripStyle style);
~TabStrip() override;
@@ -196,7 +216,6 @@ class TabStrip : public View {
virtual void OnSelectedTabChanged(Tab* from_tab, Tab* to_tab);
// Overridden from View:
- const char* GetClassName() const override;
void OnPaintBorder(gfx::Canvas* canvas) override;
Tab* GetSelectedTab() const;
@@ -204,9 +223,9 @@ class TabStrip : public View {
Tab* GetTabAtIndex(size_t index) const;
size_t GetSelectedTabIndex() const;
- TabbedPane::Orientation orientation() const { return orientation_; }
+ TabbedPane::Orientation GetOrientation() const;
- TabbedPane::TabStripStyle style() const { return style_; }
+ TabbedPane::TabStripStyle GetStyle() const;
private:
// The orientation of the tab alignment.
diff --git a/chromium/ui/views/controls/tabbed_pane/tabbed_pane_accessibility_mac_unittest.mm b/chromium/ui/views/controls/tabbed_pane/tabbed_pane_accessibility_mac_unittest.mm
index bdd006460ef..2dc681afc0a 100644
--- a/chromium/ui/views/controls/tabbed_pane/tabbed_pane_accessibility_mac_unittest.mm
+++ b/chromium/ui/views/controls/tabbed_pane/tabbed_pane_accessibility_mac_unittest.mm
@@ -49,15 +49,16 @@ class TabbedPaneAccessibilityMacTest : public WidgetTest {
WidgetTest::SetUp();
widget_ = CreateTopLevelPlatformWidget();
widget_->SetBounds(gfx::Rect(50, 50, 100, 100));
- tabbed_pane_ = new TabbedPane();
- tabbed_pane_->SetSize(gfx::Size(100, 100));
+ auto tabbed_pane = std::make_unique<TabbedPane>();
+ tabbed_pane->SetSize(gfx::Size(100, 100));
// Create two tabs and position/size them.
- tabbed_pane_->AddTab(base::ASCIIToUTF16("Tab 1"), new View());
- tabbed_pane_->AddTab(base::ASCIIToUTF16("Tab 2"), new View());
- tabbed_pane_->Layout();
+ tabbed_pane->AddTab(base::ASCIIToUTF16("Tab 1"), std::make_unique<View>());
+ tabbed_pane->AddTab(base::ASCIIToUTF16("Tab 2"), std::make_unique<View>());
+ tabbed_pane->Layout();
- widget_->GetContentsView()->AddChildView(tabbed_pane_);
+ tabbed_pane_ =
+ widget_->GetContentsView()->AddChildView(std::move(tabbed_pane));
widget_->Show();
}
diff --git a/chromium/ui/views/controls/tabbed_pane/tabbed_pane_unittest.cc b/chromium/ui/views/controls/tabbed_pane/tabbed_pane_unittest.cc
index f2e3f28a39d..b92e074af5b 100644
--- a/chromium/ui/views/controls/tabbed_pane/tabbed_pane_unittest.cc
+++ b/chromium/ui/views/controls/tabbed_pane/tabbed_pane_unittest.cc
@@ -13,6 +13,7 @@
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/events/keycodes/keyboard_code_conversion.h"
+#include "ui/views/accessibility/view_accessibility.h"
#include "ui/views/test/test_views.h"
#include "ui/views/test/views_test_base.h"
#include "ui/views/widget/widget.h"
@@ -27,6 +28,18 @@ base::string16 DefaultTabTitle() {
return ASCIIToUTF16("tab");
}
+base::string16 GetAccessibleName(View* view) {
+ ui::AXNodeData ax_node_data;
+ view->GetViewAccessibility().GetAccessibleNodeData(&ax_node_data);
+ return ax_node_data.GetString16Attribute(ax::mojom::StringAttribute::kName);
+}
+
+ax::mojom::Role GetAccessibleRole(View* view) {
+ ui::AXNodeData ax_node_data;
+ view->GetViewAccessibility().GetAccessibleNodeData(&ax_node_data);
+ return ax_node_data.role;
+}
+
} // namespace
class TabbedPaneTest : public ViewsTestBase {
@@ -37,6 +50,21 @@ class TabbedPaneTest : public ViewsTestBase {
ViewsTestBase::SetUp();
tabbed_pane_ = std::make_unique<TabbedPane>();
tabbed_pane_->set_owned_by_client();
+
+ // Create a widget so that accessibility data will be returned correctly.
+ widget_ = std::make_unique<Widget>();
+ Widget::InitParams params =
+ CreateParams(Widget::InitParams::TYPE_WINDOW_FRAMELESS);
+ params.ownership = views::Widget::InitParams::WIDGET_OWNS_NATIVE_WIDGET;
+ params.bounds = gfx::Rect(0, 0, 650, 650);
+ widget_->Init(params);
+ widget_->SetContentsView(tabbed_pane_.get());
+ }
+
+ void TearDown() override {
+ tabbed_pane_.reset();
+ widget_.reset();
+ ViewsTestBase::TearDown();
}
protected:
@@ -60,6 +88,7 @@ class TabbedPaneTest : public ViewsTestBase {
ui::UsLayoutKeyboardCodeToDomCode(keyboard_code), 0));
}
+ std::unique_ptr<Widget> widget_;
std::unique_ptr<TabbedPane> tabbed_pane_;
private:
@@ -96,10 +125,12 @@ TEST_F(TabbedPaneTest, TabStripHighlightStyle) {
// width of horizontal tab strips for preferred size calculations. Tab titles
// are elided to fit the actual width.
TEST_F(TabbedPaneTest, SizeAndLayout) {
- View* child1 = new StaticSizedView(gfx::Size(20, 10));
- tabbed_pane_->AddTab(ASCIIToUTF16("tab1 with very long text"), child1);
- View* child2 = new StaticSizedView(gfx::Size(5, 5));
- tabbed_pane_->AddTab(ASCIIToUTF16("tab2 with very long text"), child2);
+ View* child1 = tabbed_pane_->AddTab(
+ ASCIIToUTF16("tab1 with very long text"),
+ std::make_unique<StaticSizedView>(gfx::Size(20, 10)));
+ View* child2 =
+ tabbed_pane_->AddTab(ASCIIToUTF16("tab2 with very long text"),
+ std::make_unique<StaticSizedView>(gfx::Size(5, 5)));
tabbed_pane_->SelectTabAt(0);
// |tabbed_pane_| width should match the largest child in horizontal mode.
@@ -127,10 +158,11 @@ TEST_F(TabbedPaneTest, SizeAndLayout) {
TEST_F(TabbedPaneTest, SizeAndLayoutInVerticalOrientation) {
MakeTabbedPane(TabbedPane::Orientation::kVertical,
TabbedPane::TabStripStyle::kBorder);
- View* child1 = new StaticSizedView(gfx::Size(20, 10));
- tabbed_pane_->AddTab(ASCIIToUTF16("tab1"), child1);
- View* child2 = new StaticSizedView(gfx::Size(5, 5));
- tabbed_pane_->AddTab(ASCIIToUTF16("tab2"), child2);
+ View* child1 = tabbed_pane_->AddTab(
+ ASCIIToUTF16("tab1"),
+ std::make_unique<StaticSizedView>(gfx::Size(20, 10)));
+ View* child2 = tabbed_pane_->AddTab(
+ ASCIIToUTF16("tab2"), std::make_unique<StaticSizedView>(gfx::Size(5, 5)));
tabbed_pane_->SelectTabAt(0);
// |tabbed_pane_| reserves extra width for the tab strip in vertical mode.
@@ -157,8 +189,7 @@ TEST_F(TabbedPaneTest, SizeAndLayoutInVerticalOrientation) {
TEST_F(TabbedPaneTest, AddAndSelect) {
// Add several tabs; only the first should be selected automatically.
for (size_t i = 0; i < 3; ++i) {
- View* tab = new View();
- tabbed_pane_->AddTab(DefaultTabTitle(), tab);
+ tabbed_pane_->AddTab(DefaultTabTitle(), std::make_unique<View>());
EXPECT_EQ(i + 1, tabbed_pane_->GetTabCount());
EXPECT_EQ(0u, tabbed_pane_->GetSelectedTabIndex());
}
@@ -170,8 +201,8 @@ TEST_F(TabbedPaneTest, AddAndSelect) {
}
// Add a tab at index 0, it should not be selected automatically.
- View* tab0 = new View();
- tabbed_pane_->AddTabAtIndex(0, ASCIIToUTF16("tab0"), tab0);
+ View* tab0 = tabbed_pane_->AddTabAtIndex(0, ASCIIToUTF16("tab0"),
+ std::make_unique<View>());
EXPECT_NE(tab0, GetSelectedTabContentView());
EXPECT_NE(0u, tabbed_pane_->GetSelectedTabIndex());
}
@@ -179,8 +210,7 @@ TEST_F(TabbedPaneTest, AddAndSelect) {
TEST_F(TabbedPaneTest, ArrowKeyBindings) {
// Add several tabs; only the first should be selected automatically.
for (size_t i = 0; i < 3; ++i) {
- View* tab = new View();
- tabbed_pane_->AddTab(DefaultTabTitle(), tab);
+ tabbed_pane_->AddTab(DefaultTabTitle(), std::make_unique<View>());
EXPECT_EQ(i + 1, tabbed_pane_->GetTabCount());
}
@@ -215,7 +245,7 @@ TEST_F(TabbedPaneTest, SelectTabWithAccessibleAction) {
constexpr size_t kNumTabs = 3;
for (size_t i = 0; i < kNumTabs; ++i) {
- tabbed_pane_->AddTab(DefaultTabTitle(), new View());
+ tabbed_pane_->AddTab(DefaultTabTitle(), std::make_unique<View>());
}
// Check the first tab is selected.
EXPECT_EQ(0u, tabbed_pane_->GetSelectedTabIndex());
@@ -249,5 +279,37 @@ TEST_F(TabbedPaneTest, SelectTabWithAccessibleAction) {
widget->CloseNow();
}
+TEST_F(TabbedPaneTest, AccessiblePaneTitleTracksActiveTabTitle) {
+ const base::string16 kFirstTitle = ASCIIToUTF16("Tab1");
+ const base::string16 kSecondTitle = ASCIIToUTF16("Tab2");
+ tabbed_pane_->AddTab(kFirstTitle, std::make_unique<View>());
+ tabbed_pane_->AddTab(kSecondTitle, std::make_unique<View>());
+ EXPECT_EQ(kFirstTitle, GetAccessibleName(tabbed_pane_.get()));
+ tabbed_pane_->SelectTabAt(1);
+ EXPECT_EQ(kSecondTitle, GetAccessibleName(tabbed_pane_.get()));
+}
+
+TEST_F(TabbedPaneTest, AccessiblePaneContentsTitleTracksTabTitle) {
+ const base::string16 kFirstTitle = ASCIIToUTF16("Tab1");
+ const base::string16 kSecondTitle = ASCIIToUTF16("Tab2");
+ View* const tab1_contents =
+ tabbed_pane_->AddTab(kFirstTitle, std::make_unique<View>());
+ View* const tab2_contents =
+ tabbed_pane_->AddTab(kSecondTitle, std::make_unique<View>());
+ EXPECT_EQ(kFirstTitle, GetAccessibleName(tab1_contents));
+ EXPECT_EQ(kSecondTitle, GetAccessibleName(tab2_contents));
+}
+
+TEST_F(TabbedPaneTest, AccessiblePaneContentsRoleIsTab) {
+ const base::string16 kFirstTitle = ASCIIToUTF16("Tab1");
+ const base::string16 kSecondTitle = ASCIIToUTF16("Tab2");
+ View* const tab1_contents =
+ tabbed_pane_->AddTab(kFirstTitle, std::make_unique<View>());
+ View* const tab2_contents =
+ tabbed_pane_->AddTab(kSecondTitle, std::make_unique<View>());
+ EXPECT_EQ(ax::mojom::Role::kTab, GetAccessibleRole(tab1_contents));
+ EXPECT_EQ(ax::mojom::Role::kTab, GetAccessibleRole(tab2_contents));
+}
+
} // namespace test
} // namespace views
diff --git a/chromium/ui/views/controls/textfield/textfield.cc b/chromium/ui/views/controls/textfield/textfield.cc
index e0e651b3163..c2b7981007a 100644
--- a/chromium/ui/views/controls/textfield/textfield.cc
+++ b/chromium/ui/views/controls/textfield/textfield.cc
@@ -17,8 +17,6 @@
#include "build/build_config.h"
#include "ui/accessibility/ax_action_data.h"
#include "ui/accessibility/ax_node_data.h"
-#include "ui/aura/client/aura_constants.h"
-#include "ui/aura/window.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/default_style.h"
@@ -73,6 +71,7 @@
#endif
#if defined(OS_CHROMEOS)
+#include "ui/aura/window.h"
#include "ui/wm/core/ime_util_chromeos.h"
#endif
@@ -250,9 +249,6 @@ bool IsControlKeyModifier(int flags) {
} // namespace
// static
-const char Textfield::kViewClassName[] = "Textfield";
-
-// static
base::TimeDelta Textfield::GetCaretBlinkInterval() {
#if defined(OS_WIN)
static const size_t system_value = ::GetCaretBlinkTime();
@@ -278,14 +274,14 @@ const gfx::FontList& Textfield::GetDefaultFontList() {
Textfield::Textfield()
: model_(new TextfieldModel(this)),
placeholder_text_draw_flags_(gfx::Canvas::DefaultCanvasTextAlignment()),
- selection_controller_(this),
- weak_ptr_factory_(this) {
+ selection_controller_(this) {
set_context_menu_controller(this);
set_drag_controller(this);
cursor_view_.SetPaintToLayer(ui::LAYER_SOLID_COLOR);
cursor_view_.layer()->SetColor(GetTextColor());
// |cursor_view_| is owned by Textfield view.
cursor_view_.set_owned_by_client();
+ cursor_view_.GetViewAccessibility().OverrideIsIgnored(true);
AddChildView(&cursor_view_);
GetRenderText()->SetFontList(GetDefaultFontList());
UpdateBorder();
@@ -637,10 +633,6 @@ gfx::Size Textfield::GetMinimumSize() const {
return minimum_size;
}
-const char* Textfield::GetClassName() const {
- return kViewClassName;
-}
-
void Textfield::SetBorder(std::unique_ptr<Border> b) {
use_focus_ring_ = false;
if (focus_ring_)
@@ -1175,6 +1167,10 @@ void Textfield::OnCompositionTextConfirmedOrCleared() {
GetInputMethod()->CancelComposition(this);
}
+void Textfield::OnTextChanged() {
+ OnPropertyChanged(&model_ + kTextProperty, kPropertyEffectsPaint);
+}
+
////////////////////////////////////////////////////////////////////////////////
// Textfield, ContextMenuController overrides:
@@ -1712,7 +1708,7 @@ bool Textfield::IsTextEditCommandEnabled(ui::TextEditCommand command) const {
return readable && model_->HasSelection();
case ui::TextEditCommand::PASTE:
ui::Clipboard::GetForCurrentThread()->ReadText(
- ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
+ ui::ClipboardType::kCopyPaste, &result);
return editable && !result.empty();
case ui::TextEditCommand::SELECT_ALL:
return !text().empty() && GetSelectedRange().length() != text().length();
@@ -1810,7 +1806,7 @@ gfx::Point Textfield::GetLastClickRootLocation() const {
base::string16 Textfield::GetSelectionClipboardText() const {
base::string16 selection_clipboard_text;
- ui::Clipboard::GetForCurrentThread()->ReadText(ui::CLIPBOARD_TYPE_SELECTION,
+ ui::Clipboard::GetForCurrentThread()->ReadText(ui::ClipboardType::kSelection,
&selection_clipboard_text);
return selection_clipboard_text;
}
@@ -2039,6 +2035,12 @@ bool Textfield::ShouldShowPlaceholderText() const {
return text().empty() && !GetPlaceholderText().empty();
}
+views::PropertyChangedSubscription Textfield::AddTextChangedCallback(
+ views::PropertyChangedCallback callback) {
+ return AddPropertyChangedCallback(&model_ + kTextProperty,
+ std::move(callback));
+}
+
////////////////////////////////////////////////////////////////////////////////
// Textfield, private:
@@ -2111,10 +2113,10 @@ bool Textfield::PasteSelectionClipboard() {
void Textfield::UpdateSelectionClipboard() {
#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
if (text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD) {
- ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_SELECTION)
+ ui::ScopedClipboardWriter(ui::ClipboardType::kSelection)
.WriteText(GetSelectedText());
if (controller_)
- controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_SELECTION);
+ controller_->OnAfterCutOrCopy(ui::ClipboardType::kSelection);
}
#endif
}
@@ -2270,7 +2272,7 @@ bool Textfield::Cut() {
if (!read_only() && text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD &&
model_->Cut()) {
if (controller_)
- controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_COPY_PASTE);
+ controller_->OnAfterCutOrCopy(ui::ClipboardType::kCopyPaste);
return true;
}
return false;
@@ -2279,7 +2281,7 @@ bool Textfield::Cut() {
bool Textfield::Copy() {
if (text_input_type_ != ui::TEXT_INPUT_TYPE_PASSWORD && model_->Copy()) {
if (controller_)
- controller_->OnAfterCutOrCopy(ui::CLIPBOARD_TYPE_COPY_PASTE);
+ controller_->OnAfterCutOrCopy(ui::ClipboardType::kCopyPaste);
return true;
}
return false;
@@ -2390,4 +2392,8 @@ void Textfield::OnEnabledChanged() {
GetInputMethod()->OnTextInputTypeChanged(this);
}
+BEGIN_METADATA(Textfield)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/textfield/textfield.h b/chromium/ui/views/controls/textfield/textfield.h
index 0a88abfda2e..363d2182cfb 100644
--- a/chromium/ui/views/controls/textfield/textfield.h
+++ b/chromium/ui/views/controls/textfield/textfield.h
@@ -71,8 +71,13 @@ class VIEWS_EXPORT Textfield : public View,
public ui::TouchEditable,
public ui::TextInputClient {
public:
- // The textfield's class name.
- static const char kViewClassName[];
+ METADATA_HEADER(Textfield);
+
+ // An enum giving different model properties unique keys for the
+ // OnPropertyChanged call.
+ enum ModelPropertyKey {
+ kTextProperty = 1,
+ };
// Returns the text cursor blink time, or 0 for no blinking.
static base::TimeDelta GetCaretBlinkInterval();
@@ -242,6 +247,7 @@ class VIEWS_EXPORT Textfield : public View,
// Set the accessible name of the text field. If the textfield has a visible
// label, use SetAssociatedLabel() instead.
void SetAccessibleName(const base::string16& name);
+ const base::string16& accessible_name() const { return accessible_name_; }
// If the accessible name should be the same as the labelling view's text,
// use this. It will set the accessible label relationship and copy the
@@ -260,7 +266,6 @@ class VIEWS_EXPORT Textfield : public View,
int GetBaseline() const override;
gfx::Size CalculatePreferredSize() const override;
gfx::Size GetMinimumSize() const override;
- const char* GetClassName() const override;
void SetBorder(std::unique_ptr<Border> b) override;
gfx::NativeCursor GetCursor(const ui::MouseEvent& event) override;
bool OnMousePressed(const ui::MouseEvent& event) override;
@@ -294,6 +299,7 @@ class VIEWS_EXPORT Textfield : public View,
// TextfieldModel::Delegate overrides:
void OnCompositionTextConfirmedOrCleared() override;
+ void OnTextChanged() override;
// ContextMenuController overrides:
void ShowContextMenuForViewImpl(View* source,
@@ -385,6 +391,9 @@ class VIEWS_EXPORT Textfield : public View,
bool is_composition_committed) override;
#endif
+ views::PropertyChangedSubscription AddTextChangedCallback(
+ views::PropertyChangedCallback callback);
+
protected:
// Inserts or appends a character in response to an IME operation.
virtual void DoInsertChar(base::char16 ch);
@@ -668,7 +677,7 @@ class VIEWS_EXPORT Textfield : public View,
base::Unretained(this)));
// Used to bind callback functions to this object.
- base::WeakPtrFactory<Textfield> weak_ptr_factory_;
+ base::WeakPtrFactory<Textfield> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(Textfield);
};
diff --git a/chromium/ui/views/controls/textfield/textfield_model.cc b/chromium/ui/views/controls/textfield/textfield_model.cc
index 5b9f9db1e54..853914d0d50 100644
--- a/chromium/ui/views/controls/textfield/textfield_model.cc
+++ b/chromium/ui/views/controls/textfield/textfield_model.cc
@@ -522,8 +522,8 @@ bool TextfieldModel::Redo() {
bool TextfieldModel::Cut() {
if (!HasCompositionText() && HasSelection() && !render_text_->obscured()) {
- ui::ScopedClipboardWriter(
- ui::CLIPBOARD_TYPE_COPY_PASTE).WriteText(GetSelectedText());
+ ui::ScopedClipboardWriter(ui::ClipboardType::kCopyPaste)
+ .WriteText(GetSelectedText());
// A trick to let undo/redo handle cursor correctly.
// Undoing CUT moves the cursor to the end of the change rather
// than beginning, unlike Delete/Backspace.
@@ -539,8 +539,8 @@ bool TextfieldModel::Cut() {
bool TextfieldModel::Copy() {
if (!HasCompositionText() && HasSelection() && !render_text_->obscured()) {
- ui::ScopedClipboardWriter(
- ui::CLIPBOARD_TYPE_COPY_PASTE).WriteText(GetSelectedText());
+ ui::ScopedClipboardWriter(ui::ClipboardType::kCopyPaste)
+ .WriteText(GetSelectedText());
return true;
}
return false;
@@ -548,7 +548,7 @@ bool TextfieldModel::Copy() {
bool TextfieldModel::Paste() {
base::string16 text;
- ui::Clipboard::GetForCurrentThread()->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE,
+ ui::Clipboard::GetForCurrentThread()->ReadText(ui::ClipboardType::kCopyPaste,
&text);
if (text.empty())
return false;
@@ -641,7 +641,7 @@ void TextfieldModel::SetCompositionText(
size_t cursor = GetCursorPosition();
base::string16 new_text = text();
- render_text_->SetText(new_text.insert(cursor, composition.text));
+ SetRenderTextText(new_text.insert(cursor, composition.text));
composition_range_ = gfx::Range(cursor, cursor + composition.text.length());
// Don't render IME spans with thickness "kNone".
if (composition.ime_text_spans.size() > 0 &&
@@ -669,7 +669,11 @@ void TextfieldModel::SetCompositionText(
}
void TextfieldModel::SetCompositionFromExistingText(const gfx::Range& range) {
- DCHECK(!HasCompositionText());
+ if (range.is_empty() || !gfx::Range(0, text().length()).Contains(range)) {
+ ClearComposition();
+ return;
+ }
+
composition_range_ = range;
render_text_->SetCompositionRange(range);
}
@@ -693,7 +697,7 @@ void TextfieldModel::CancelCompositionText() {
gfx::Range range = composition_range_;
ClearComposition();
base::string16 new_text = text();
- render_text_->SetText(new_text.erase(range.start(), range.length()));
+ SetRenderTextText(new_text.erase(range.start(), range.length()));
render_text_->SetCursorPosition(range.start());
if (delegate_)
delegate_->OnCompositionTextConfirmedOrCleared();
@@ -839,9 +843,9 @@ void TextfieldModel::ModifyText(size_t delete_from,
base::string16 old_text = text();
ClearComposition();
if (delete_from != delete_to)
- render_text_->SetText(old_text.erase(delete_from, delete_to - delete_from));
+ SetRenderTextText(old_text.erase(delete_from, delete_to - delete_from));
if (!new_text.empty())
- render_text_->SetText(old_text.insert(new_text_insert_at, new_text));
+ SetRenderTextText(old_text.insert(new_text_insert_at, new_text));
if (selection.start() == selection.end()) {
render_text_->SetCursorPosition(selection.start());
} else {
@@ -849,6 +853,12 @@ void TextfieldModel::ModifyText(size_t delete_from,
}
}
+void TextfieldModel::SetRenderTextText(const base::string16& text) {
+ render_text_->SetText(text);
+ if (delegate_)
+ delegate_->OnTextChanged();
+}
+
// static
void TextfieldModel::ClearKillBuffer() {
SetKillBuffer(base::string16());
diff --git a/chromium/ui/views/controls/textfield/textfield_model.h b/chromium/ui/views/controls/textfield/textfield_model.h
index c2391a35645..9efa1f36e03 100644
--- a/chromium/ui/views/controls/textfield/textfield_model.h
+++ b/chromium/ui/views/controls/textfield/textfield_model.h
@@ -52,6 +52,9 @@ class VIEWS_EXPORT TextfieldModel {
// Called when the current composition text is confirmed or cleared.
virtual void OnCompositionTextConfirmedOrCleared() = 0;
+ // Called any time that the text property is modified in TextfieldModel
+ virtual void OnTextChanged() {}
+
protected:
virtual ~Delegate();
};
@@ -221,6 +224,8 @@ class VIEWS_EXPORT TextfieldModel {
// Puts the text in the specified range into composition mode.
// This method should not be called with composition text or an invalid range.
+ // The provided range is checked against the string's length, if |range| is
+ // out of bounds, the composition will be cleared.
void SetCompositionFromExistingText(const gfx::Range& range);
// Converts current composition text into final content.
@@ -284,6 +289,9 @@ class VIEWS_EXPORT TextfieldModel {
size_t new_text_insert_at,
gfx::Range selection);
+ // Calls render_text->SetText() and delegate's callback.
+ void SetRenderTextText(const base::string16& text);
+
void ClearComposition();
// Clears the kill buffer. Used to clear global state between tests.
diff --git a/chromium/ui/views/controls/textfield/textfield_model_unittest.cc b/chromium/ui/views/controls/textfield/textfield_model_unittest.cc
index 27a7566b866..38174b5ec8f 100644
--- a/chromium/ui/views/controls/textfield/textfield_model_unittest.cc
+++ b/chromium/ui/views/controls/textfield/textfield_model_unittest.cc
@@ -591,7 +591,7 @@ TEST_F(TextfieldModelTest, Clipboard) {
ui::Clipboard* clipboard = ui::Clipboard::GetForCurrentThread();
const base::string16 initial_clipboard_text =
base::ASCIIToUTF16("initial text");
- ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_COPY_PASTE)
+ ui::ScopedClipboardWriter(ui::ClipboardType::kCopyPaste)
.WriteText(initial_clipboard_text);
base::string16 clipboard_text;
@@ -601,14 +601,14 @@ TEST_F(TextfieldModelTest, Clipboard) {
// Cut with an empty selection should do nothing.
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_NONE);
EXPECT_FALSE(model.Cut());
- clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &clipboard_text);
+ clipboard->ReadText(ui::ClipboardType::kCopyPaste, &clipboard_text);
EXPECT_EQ(initial_clipboard_text, clipboard_text);
EXPECT_STR_EQ("HELLO WORLD", model.text());
EXPECT_EQ(11U, model.GetCursorPosition());
// Copy with an empty selection should do nothing.
model.Copy();
- clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &clipboard_text);
+ clipboard->ReadText(ui::ClipboardType::kCopyPaste, &clipboard_text);
EXPECT_EQ(initial_clipboard_text, clipboard_text);
EXPECT_STR_EQ("HELLO WORLD", model.text());
EXPECT_EQ(11U, model.GetCursorPosition());
@@ -617,7 +617,7 @@ TEST_F(TextfieldModelTest, Clipboard) {
model.render_text()->SetObscured(true);
model.SelectAll(false);
EXPECT_FALSE(model.Cut());
- clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &clipboard_text);
+ clipboard->ReadText(ui::ClipboardType::kCopyPaste, &clipboard_text);
EXPECT_EQ(initial_clipboard_text, clipboard_text);
EXPECT_STR_EQ("HELLO WORLD", model.text());
EXPECT_STR_EQ("HELLO WORLD", model.GetSelectedText());
@@ -625,7 +625,7 @@ TEST_F(TextfieldModelTest, Clipboard) {
// Copy on obscured (password) text should do nothing.
model.SelectAll(false);
EXPECT_FALSE(model.Copy());
- clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &clipboard_text);
+ clipboard->ReadText(ui::ClipboardType::kCopyPaste, &clipboard_text);
EXPECT_EQ(initial_clipboard_text, clipboard_text);
EXPECT_STR_EQ("HELLO WORLD", model.text());
EXPECT_STR_EQ("HELLO WORLD", model.GetSelectedText());
@@ -635,7 +635,7 @@ TEST_F(TextfieldModelTest, Clipboard) {
model.MoveCursor(gfx::LINE_BREAK, gfx::CURSOR_RIGHT, gfx::SELECTION_NONE);
model.MoveCursor(gfx::WORD_BREAK, gfx::CURSOR_LEFT, gfx::SELECTION_RETAIN);
EXPECT_TRUE(model.Cut());
- clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &clipboard_text);
+ clipboard->ReadText(ui::ClipboardType::kCopyPaste, &clipboard_text);
EXPECT_STR_EQ("WORLD", clipboard_text);
EXPECT_STR_EQ("HELLO ", model.text());
EXPECT_EQ(6U, model.GetCursorPosition());
@@ -643,7 +643,7 @@ TEST_F(TextfieldModelTest, Clipboard) {
// Copy with non-empty selection.
model.SelectAll(false);
EXPECT_TRUE(model.Copy());
- clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &clipboard_text);
+ clipboard->ReadText(ui::ClipboardType::kCopyPaste, &clipboard_text);
EXPECT_STR_EQ("HELLO ", clipboard_text);
EXPECT_STR_EQ("HELLO ", model.text());
EXPECT_EQ(6U, model.GetCursorPosition());
@@ -1741,7 +1741,7 @@ TEST_F(TextfieldModelTest, UndoRedo_CompositionText) {
TEST_F(TextfieldModelTest, Clipboard_WhiteSpaceStringTest) {
// Test 1
// Clipboard text with a leading tab should be pasted with the tab stripped.
- ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_COPY_PASTE)
+ ui::ScopedClipboardWriter(ui::ClipboardType::kCopyPaste)
.WriteText(base::ASCIIToUTF16("\tB"));
TextfieldModel model(nullptr);
@@ -1760,7 +1760,7 @@ TEST_F(TextfieldModelTest, Clipboard_WhiteSpaceStringTest) {
// Test 2
// Clipboard text with multiple leading tabs and spaces should be pasted with
// all tabs and spaces stripped.
- ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_COPY_PASTE)
+ ui::ScopedClipboardWriter(ui::ClipboardType::kCopyPaste)
.WriteText(base::ASCIIToUTF16("\t\t\t B"));
model.Append(base::ASCIIToUTF16("HELLO WORLD"));
@@ -1777,7 +1777,7 @@ TEST_F(TextfieldModelTest, Clipboard_WhiteSpaceStringTest) {
// Test 3
// Clipboard text with multiple tabs separating the words should be pasted
// with one space replacing all tabs.
- ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_COPY_PASTE)
+ ui::ScopedClipboardWriter(ui::ClipboardType::kCopyPaste)
.WriteText(base::ASCIIToUTF16("FOO \t\t BAR"));
model.Append(base::ASCIIToUTF16("HELLO WORLD"));
@@ -1795,7 +1795,7 @@ TEST_F(TextfieldModelTest, Clipboard_WhiteSpaceStringTest) {
// Clipboard text with multiple leading tabs and multiple tabs separating
// the words should be pasted with the leading tabs stripped and one space
// replacing the intermediate tabs.
- ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_COPY_PASTE)
+ ui::ScopedClipboardWriter(ui::ClipboardType::kCopyPaste)
.WriteText(base::ASCIIToUTF16("\t\tFOO \t\t BAR"));
EXPECT_TRUE(model.Paste());
@@ -1808,7 +1808,7 @@ TEST_F(TextfieldModelTest, Clipboard_WhiteSpaceStringTest) {
// Test 5
// Clipboard text with multiple trailing tabs should be pasted with all
// trailing tabs stripped.
- ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_COPY_PASTE)
+ ui::ScopedClipboardWriter(ui::ClipboardType::kCopyPaste)
.WriteText(base::ASCIIToUTF16("FOO BAR\t\t\t"));
EXPECT_TRUE(model.Paste());
EXPECT_STR_EQ("FOO BAR", model.text());
@@ -1820,7 +1820,7 @@ TEST_F(TextfieldModelTest, Clipboard_WhiteSpaceStringTest) {
// Test 6
// Clipboard text with only spaces and tabs should be pasted as a single
// space.
- ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_COPY_PASTE)
+ ui::ScopedClipboardWriter(ui::ClipboardType::kCopyPaste)
.WriteText(base::ASCIIToUTF16(" \t\t"));
EXPECT_TRUE(model.Paste());
EXPECT_STR_EQ(" ", model.text());
@@ -1832,7 +1832,7 @@ TEST_F(TextfieldModelTest, Clipboard_WhiteSpaceStringTest) {
// Test 7
// Clipboard text with lots of spaces between words should have all spaces
// replaced with a single space.
- ui::ScopedClipboardWriter(ui::CLIPBOARD_TYPE_COPY_PASTE)
+ ui::ScopedClipboardWriter(ui::ClipboardType::kCopyPaste)
.WriteText(base::ASCIIToUTF16("FOO BAR"));
EXPECT_TRUE(model.Paste());
EXPECT_STR_EQ("FOO BAR", model.text());
@@ -1954,6 +1954,9 @@ TEST_F(TextfieldModelTest, SetCompositionFromExistingText) {
TextfieldModel model(nullptr);
model.SetText(base::ASCIIToUTF16("abcde"));
+ model.SetCompositionFromExistingText(gfx::Range(0, 1));
+ EXPECT_TRUE(model.HasCompositionText());
+
model.SetCompositionFromExistingText(gfx::Range(1, 3));
EXPECT_TRUE(model.HasCompositionText());
@@ -1963,4 +1966,28 @@ TEST_F(TextfieldModelTest, SetCompositionFromExistingText) {
EXPECT_STR_EQ("a123de", model.text());
}
+TEST_F(TextfieldModelTest, SetCompositionFromExistingText_Empty) {
+ TextfieldModel model(nullptr);
+ model.SetText(base::ASCIIToUTF16("abc"));
+
+ model.SetCompositionFromExistingText(gfx::Range(0, 2));
+ EXPECT_TRUE(model.HasCompositionText());
+
+ model.SetCompositionFromExistingText(gfx::Range(1, 1));
+ EXPECT_FALSE(model.HasCompositionText());
+ EXPECT_STR_EQ("abc", model.text());
+}
+
+TEST_F(TextfieldModelTest, SetCompositionFromExistingText_OutOfBounds) {
+ TextfieldModel model(nullptr);
+ model.SetText(base::string16());
+
+ model.SetCompositionFromExistingText(gfx::Range(0, 2));
+ EXPECT_FALSE(model.HasCompositionText());
+
+ model.SetText(base::ASCIIToUTF16("abc"));
+ model.SetCompositionFromExistingText(gfx::Range(1, 4));
+ EXPECT_FALSE(model.HasCompositionText());
+}
+
} // namespace views
diff --git a/chromium/ui/views/controls/textfield/textfield_unittest.cc b/chromium/ui/views/controls/textfield/textfield_unittest.cc
index 108b0f746e2..1cd9cb3d45d 100644
--- a/chromium/ui/views/controls/textfield/textfield_unittest.cc
+++ b/chromium/ui/views/controls/textfield/textfield_unittest.cc
@@ -11,7 +11,6 @@
#include <string>
#include <vector>
-#include "base/bind_helpers.h"
#include "base/command_line.h"
#include "base/format_macros.h"
#include "base/i18n/rtl.h"
@@ -22,7 +21,6 @@
#include "base/strings/utf_string_conversions.h"
#include "build/build_config.h"
#include "ui/accessibility/ax_node_data.h"
-#include "ui/aura/window.h"
#include "ui/base/clipboard/clipboard.h"
#include "ui/base/clipboard/scoped_clipboard_writer.h"
#include "ui/base/clipboard/test/test_clipboard.h"
@@ -67,6 +65,7 @@
#endif
#if defined(OS_CHROMEOS)
+#include "ui/aura/window.h"
#include "ui/wm/core/ime_util_chromeos.h"
#endif
@@ -150,7 +149,7 @@ ui::EventDispatchDetails MockInputMethod::DispatchKeyEvent(ui::KeyEvent* key) {
// which trigger the appropriate NSResponder action messages for composition.
#if defined(OS_MACOSX)
if (key->is_char())
- return DispatchKeyEventPostIME(key, base::NullCallback());
+ return DispatchKeyEventPostIME(key);
#endif
// Checks whether the key event is from EventGenerator on Windows which will
@@ -170,9 +169,9 @@ ui::EventDispatchDetails MockInputMethod::DispatchKeyEvent(ui::KeyEvent* key) {
ui::KeyEvent mock_key(ui::ET_KEY_PRESSED,
ui::VKEY_PROCESSKEY,
key->flags());
- dispatch_details = DispatchKeyEventPostIME(&mock_key, base::NullCallback());
+ dispatch_details = DispatchKeyEventPostIME(&mock_key);
} else {
- dispatch_details = DispatchKeyEventPostIME(key, base::NullCallback());
+ dispatch_details = DispatchKeyEventPostIME(key);
}
if (key->handled() || dispatch_details.dispatcher_destroyed)
@@ -417,7 +416,7 @@ class TextfieldTest : public ViewsTestBase, public TextfieldController {
ui::ClipboardType GetAndResetCopiedToClipboard() {
ui::ClipboardType clipboard_type = copied_to_clipboard_;
- copied_to_clipboard_ = ui::CLIPBOARD_TYPE_LAST;
+ copied_to_clipboard_ = ui::ClipboardType::kMaxValue;
return clipboard_type;
}
@@ -731,7 +730,7 @@ class TextfieldTest : public ViewsTestBase, public TextfieldController {
menu->IsEnabledAt(menu_index++ /* CUT */));
EXPECT_EQ(textfield_has_selection,
menu->IsEnabledAt(menu_index++ /* COPY */));
- EXPECT_NE(GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE).empty(),
+ EXPECT_NE(GetClipboardText(ui::ClipboardType::kCopyPaste).empty(),
menu->IsEnabledAt(menu_index++ /* PASTE */));
EXPECT_EQ(textfield_has_selection,
menu->IsEnabledAt(menu_index++ /* DELETE */));
@@ -804,7 +803,7 @@ class TextfieldTest : public ViewsTestBase, public TextfieldController {
// Position of the mouse for synthetic mouse events.
gfx::Point mouse_position_;
- ui::ClipboardType copied_to_clipboard_ = ui::CLIPBOARD_TYPE_LAST;
+ ui::ClipboardType copied_to_clipboard_ = ui::ClipboardType::kMaxValue;
std::unique_ptr<ui::test::EventGenerator> event_generator_;
private:
@@ -1284,7 +1283,7 @@ TEST_F(TextfieldTest, PasswordTest) {
EXPECT_STR_EQ("password", textfield_->text());
EXPECT_TRUE(last_contents_.empty());
model_->SelectAll(false);
- SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "foo");
+ SetClipboardText(ui::ClipboardType::kCopyPaste, "foo");
// Cut and copy should be disabled.
EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_CUT));
@@ -1294,7 +1293,7 @@ TEST_F(TextfieldTest, PasswordTest) {
textfield_->ExecuteCommand(IDS_APP_COPY, 0);
SendKeyEvent(ui::VKEY_C, false, true);
SendAlternateCopy();
- EXPECT_STR_EQ("foo", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
+ EXPECT_STR_EQ("foo", GetClipboardText(ui::ClipboardType::kCopyPaste));
EXPECT_STR_EQ("password", textfield_->text());
// [Shift]+[Delete] should just delete without copying text to the clipboard.
textfield_->SelectAll(false);
@@ -1305,7 +1304,7 @@ TEST_F(TextfieldTest, PasswordTest) {
textfield_->ExecuteCommand(IDS_APP_PASTE, 0);
SendKeyEvent(ui::VKEY_V, false, true);
SendAlternatePaste();
- EXPECT_STR_EQ("foo", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
+ EXPECT_STR_EQ("foo", GetClipboardText(ui::ClipboardType::kCopyPaste));
EXPECT_STR_EQ("foofoofoo", textfield_->text());
}
@@ -1580,7 +1579,7 @@ TEST_F(TextfieldTest, ContextMenuDisplayTest) {
EXPECT_TRUE(textfield_->context_menu_controller());
textfield_->SetText(ASCIIToUTF16("hello world"));
- ui::Clipboard::GetForCurrentThread()->Clear(ui::CLIPBOARD_TYPE_COPY_PASTE);
+ ui::Clipboard::GetForCurrentThread()->Clear(ui::ClipboardType::kCopyPaste);
textfield_->ClearEditHistory();
EXPECT_TRUE(GetContextMenuModel());
VerifyTextfieldContextMenuContents(false, false, GetContextMenuModel());
@@ -1595,7 +1594,7 @@ TEST_F(TextfieldTest, ContextMenuDisplayTest) {
VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
// Exercise the "paste enabled?" check in the verifier.
- SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
+ SetClipboardText(ui::ClipboardType::kCopyPaste, "Test");
VerifyTextfieldContextMenuContents(true, true, GetContextMenuModel());
}
@@ -1966,12 +1965,12 @@ TEST_F(TextfieldTest, ReadOnlyTest) {
EXPECT_STR_EQ("read only", textfield_->GetSelectedText());
// Cut should be disabled.
- SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
+ SetClipboardText(ui::ClipboardType::kCopyPaste, "Test");
EXPECT_FALSE(textfield_->IsCommandIdEnabled(IDS_APP_CUT));
textfield_->ExecuteCommand(IDS_APP_CUT, 0);
SendKeyEvent(ui::VKEY_X, false, true);
SendAlternateCut();
- EXPECT_STR_EQ("Test", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
+ EXPECT_STR_EQ("Test", GetClipboardText(ui::ClipboardType::kCopyPaste));
EXPECT_STR_EQ("read only", textfield_->text());
// Paste should be disabled.
@@ -1982,16 +1981,16 @@ TEST_F(TextfieldTest, ReadOnlyTest) {
EXPECT_STR_EQ("read only", textfield_->text());
// Copy should work normally.
- SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
+ SetClipboardText(ui::ClipboardType::kCopyPaste, "Test");
EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_COPY));
textfield_->ExecuteCommand(IDS_APP_COPY, 0);
- EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
- SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
+ EXPECT_STR_EQ("read only", GetClipboardText(ui::ClipboardType::kCopyPaste));
+ SetClipboardText(ui::ClipboardType::kCopyPaste, "Test");
SendKeyEvent(ui::VKEY_C, false, true);
- EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
- SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "Test");
+ EXPECT_STR_EQ("read only", GetClipboardText(ui::ClipboardType::kCopyPaste));
+ SetClipboardText(ui::ClipboardType::kCopyPaste, "Test");
SendAlternateCopy();
- EXPECT_STR_EQ("read only", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
+ EXPECT_STR_EQ("read only", GetClipboardText(ui::ClipboardType::kCopyPaste));
// SetText should work even in read only mode.
textfield_->SetText(ASCIIToUTF16(" four five six "));
@@ -2305,70 +2304,70 @@ TEST_F(TextfieldTest, CutCopyPaste) {
textfield_->SelectAll(false);
EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_CUT));
textfield_->ExecuteCommand(IDS_APP_CUT, 0);
- EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
+ EXPECT_STR_EQ("123", GetClipboardText(ui::ClipboardType::kCopyPaste));
EXPECT_STR_EQ("", textfield_->text());
- EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
+ EXPECT_EQ(ui::ClipboardType::kCopyPaste, GetAndResetCopiedToClipboard());
// Ensure [Ctrl]+[x] cuts and [Ctrl]+[Alt][x] does nothing.
textfield_->SetText(ASCIIToUTF16("456"));
textfield_->SelectAll(false);
SendKeyEvent(ui::VKEY_X, true, false, true, false);
- EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
+ EXPECT_STR_EQ("123", GetClipboardText(ui::ClipboardType::kCopyPaste));
EXPECT_STR_EQ("456", textfield_->text());
- EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
+ EXPECT_EQ(ui::ClipboardType::kMaxValue, GetAndResetCopiedToClipboard());
SendKeyEvent(ui::VKEY_X, false, true);
- EXPECT_STR_EQ("456", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
+ EXPECT_STR_EQ("456", GetClipboardText(ui::ClipboardType::kCopyPaste));
EXPECT_STR_EQ("", textfield_->text());
- EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
+ EXPECT_EQ(ui::ClipboardType::kCopyPaste, GetAndResetCopiedToClipboard());
// Ensure [Shift]+[Delete] cuts.
textfield_->SetText(ASCIIToUTF16("123"));
textfield_->SelectAll(false);
SendAlternateCut();
- EXPECT_STR_EQ("123", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
+ EXPECT_STR_EQ("123", GetClipboardText(ui::ClipboardType::kCopyPaste));
EXPECT_STR_EQ("", textfield_->text());
- EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
+ EXPECT_EQ(ui::ClipboardType::kCopyPaste, GetAndResetCopiedToClipboard());
// Reset clipboard text.
- SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "");
+ SetClipboardText(ui::ClipboardType::kCopyPaste, "");
// Ensure [Shift]+[Delete] is a no-op in case there is no selection.
textfield_->SetText(ASCIIToUTF16("123"));
textfield_->SelectRange(gfx::Range(0));
SendAlternateCut();
- EXPECT_STR_EQ("", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
+ EXPECT_STR_EQ("", GetClipboardText(ui::ClipboardType::kCopyPaste));
EXPECT_STR_EQ("123", textfield_->text());
- EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
+ EXPECT_EQ(ui::ClipboardType::kMaxValue, GetAndResetCopiedToClipboard());
// Ensure IDS_APP_COPY copies.
textfield_->SetText(ASCIIToUTF16("789"));
textfield_->SelectAll(false);
EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_COPY));
textfield_->ExecuteCommand(IDS_APP_COPY, 0);
- EXPECT_STR_EQ("789", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
- EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
+ EXPECT_STR_EQ("789", GetClipboardText(ui::ClipboardType::kCopyPaste));
+ EXPECT_EQ(ui::ClipboardType::kCopyPaste, GetAndResetCopiedToClipboard());
// Ensure [Ctrl]+[c] copies and [Ctrl]+[Alt][c] does nothing.
textfield_->SetText(ASCIIToUTF16("012"));
textfield_->SelectAll(false);
SendKeyEvent(ui::VKEY_C, true, false, true, false);
- EXPECT_STR_EQ("789", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
- EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
+ EXPECT_STR_EQ("789", GetClipboardText(ui::ClipboardType::kCopyPaste));
+ EXPECT_EQ(ui::ClipboardType::kMaxValue, GetAndResetCopiedToClipboard());
SendKeyEvent(ui::VKEY_C, false, true);
- EXPECT_STR_EQ("012", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
- EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
+ EXPECT_STR_EQ("012", GetClipboardText(ui::ClipboardType::kCopyPaste));
+ EXPECT_EQ(ui::ClipboardType::kCopyPaste, GetAndResetCopiedToClipboard());
// Ensure [Ctrl]+[Insert] copies.
textfield_->SetText(ASCIIToUTF16("345"));
textfield_->SelectAll(false);
SendAlternateCopy();
- EXPECT_STR_EQ("345", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
+ EXPECT_STR_EQ("345", GetClipboardText(ui::ClipboardType::kCopyPaste));
EXPECT_STR_EQ("345", textfield_->text());
- EXPECT_EQ(ui::CLIPBOARD_TYPE_COPY_PASTE, GetAndResetCopiedToClipboard());
+ EXPECT_EQ(ui::ClipboardType::kCopyPaste, GetAndResetCopiedToClipboard());
// Ensure IDS_APP_PASTE, [Ctrl]+[V], and [Shift]+[Insert] pastes;
// also ensure that [Ctrl]+[Alt]+[V] does nothing.
- SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "abc");
+ SetClipboardText(ui::ClipboardType::kCopyPaste, "abc");
textfield_->SetText(base::string16());
EXPECT_TRUE(textfield_->IsCommandIdEnabled(IDS_APP_PASTE));
textfield_->ExecuteCommand(IDS_APP_PASTE, 0);
@@ -2383,9 +2382,9 @@ TEST_F(TextfieldTest, CutCopyPaste) {
// Ensure [Ctrl]+[Shift]+[Insert] is a no-op.
textfield_->SelectAll(false);
SendKeyEvent(ui::VKEY_INSERT, true, true);
- EXPECT_STR_EQ("abc", GetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE));
+ EXPECT_STR_EQ("abc", GetClipboardText(ui::ClipboardType::kCopyPaste));
EXPECT_STR_EQ("abcabcabc", textfield_->text());
- EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
+ EXPECT_EQ(ui::ClipboardType::kMaxValue, GetAndResetCopiedToClipboard());
}
TEST_F(TextfieldTest, CutCopyPasteWithEditCommand) {
@@ -2864,13 +2863,13 @@ TEST_F(TextfieldTest, SelectionClipboard) {
ui::EF_LEFT_MOUSE_BUTTON);
textfield_->OnMouseReleased(release);
EXPECT_EQ(gfx::Range(1, 3), textfield_->GetSelectedRange());
- EXPECT_STR_EQ("12", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
+ EXPECT_STR_EQ("12", GetClipboardText(ui::ClipboardType::kSelection));
// Select-all should update the selection clipboard.
SendKeyEvent(ui::VKEY_A, false, true);
EXPECT_EQ(gfx::Range(0, 4), textfield_->GetSelectedRange());
- EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
- EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
+ EXPECT_STR_EQ("0123", GetClipboardText(ui::ClipboardType::kSelection));
+ EXPECT_EQ(ui::ClipboardType::kSelection, GetAndResetCopiedToClipboard());
// Shift-click selection modifications should update the clipboard.
NonClientMouseClick();
@@ -2887,25 +2886,25 @@ TEST_F(TextfieldTest, SelectionClipboard) {
ui::EF_LEFT_MOUSE_BUTTON);
textfield_->OnMouseReleased(release_2);
EXPECT_EQ(gfx::Range(0, 2), textfield_->GetSelectedRange());
- EXPECT_STR_EQ("01", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
- EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
+ EXPECT_STR_EQ("01", GetClipboardText(ui::ClipboardType::kSelection));
+ EXPECT_EQ(ui::ClipboardType::kSelection, GetAndResetCopiedToClipboard());
// Shift-Left/Right should update the selection clipboard.
SendKeyEvent(ui::VKEY_RIGHT, true, false);
- EXPECT_STR_EQ("012", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
- EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
+ EXPECT_STR_EQ("012", GetClipboardText(ui::ClipboardType::kSelection));
+ EXPECT_EQ(ui::ClipboardType::kSelection, GetAndResetCopiedToClipboard());
SendKeyEvent(ui::VKEY_LEFT, true, false);
- EXPECT_STR_EQ("01", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
- EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
+ EXPECT_STR_EQ("01", GetClipboardText(ui::ClipboardType::kSelection));
+ EXPECT_EQ(ui::ClipboardType::kSelection, GetAndResetCopiedToClipboard());
SendKeyEvent(ui::VKEY_RIGHT, true, true);
- EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
- EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
+ EXPECT_STR_EQ("0123", GetClipboardText(ui::ClipboardType::kSelection));
+ EXPECT_EQ(ui::ClipboardType::kSelection, GetAndResetCopiedToClipboard());
// Moving the cursor without a selection should not change the clipboard.
SendKeyEvent(ui::VKEY_LEFT, false, false);
EXPECT_EQ(gfx::Range(0, 0), textfield_->GetSelectedRange());
- EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
- EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
+ EXPECT_STR_EQ("0123", GetClipboardText(ui::ClipboardType::kSelection));
+ EXPECT_EQ(ui::ClipboardType::kMaxValue, GetAndResetCopiedToClipboard());
// Middle clicking should paste at the mouse (not cursor) location.
// The cursor should be placed at the end of the pasted text.
@@ -2915,7 +2914,7 @@ TEST_F(TextfieldTest, SelectionClipboard) {
textfield_->OnMousePressed(middle);
EXPECT_STR_EQ("01230123", textfield_->text());
EXPECT_EQ(gfx::Range(8, 8), textfield_->GetSelectedRange());
- EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
+ EXPECT_STR_EQ("0123", GetClipboardText(ui::ClipboardType::kSelection));
// Middle clicking on an unfocused textfield should focus it and paste.
textfield_->GetFocusManager()->ClearFocus();
@@ -2924,27 +2923,27 @@ TEST_F(TextfieldTest, SelectionClipboard) {
EXPECT_TRUE(textfield_->HasFocus());
EXPECT_STR_EQ("012301230123", textfield_->text());
EXPECT_EQ(gfx::Range(8, 8), textfield_->GetSelectedRange());
- EXPECT_STR_EQ("0123", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
+ EXPECT_STR_EQ("0123", GetClipboardText(ui::ClipboardType::kSelection));
// Middle clicking with an empty selection clipboard should still focus.
- SetClipboardText(ui::CLIPBOARD_TYPE_SELECTION, std::string());
+ SetClipboardText(ui::ClipboardType::kSelection, std::string());
textfield_->GetFocusManager()->ClearFocus();
EXPECT_FALSE(textfield_->HasFocus());
textfield_->OnMousePressed(middle);
EXPECT_TRUE(textfield_->HasFocus());
EXPECT_STR_EQ("012301230123", textfield_->text());
EXPECT_EQ(gfx::Range(4, 4), textfield_->GetSelectedRange());
- EXPECT_TRUE(GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION).empty());
+ EXPECT_TRUE(GetClipboardText(ui::ClipboardType::kSelection).empty());
// Middle clicking in the selection should insert the selection clipboard
// contents into the middle of the selection, and move the cursor to the end
// of the pasted content.
- SetClipboardText(ui::CLIPBOARD_TYPE_COPY_PASTE, "foo");
+ SetClipboardText(ui::ClipboardType::kCopyPaste, "foo");
textfield_->SelectRange(gfx::Range(2, 6));
textfield_->OnMousePressed(middle);
EXPECT_STR_EQ("0123foo01230123", textfield_->text());
EXPECT_EQ(gfx::Range(7, 7), textfield_->GetSelectedRange());
- EXPECT_STR_EQ("foo", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
+ EXPECT_STR_EQ("foo", GetClipboardText(ui::ClipboardType::kSelection));
// Double and triple clicking should update the clipboard contents.
textfield_->SetText(ASCIIToUTF16("ab cd ef"));
@@ -2964,25 +2963,25 @@ TEST_F(TextfieldTest, SelectionClipboard) {
textfield_->OnMousePressed(double_click);
textfield_->OnMouseReleased(release_word);
EXPECT_EQ(gfx::Range(3, 5), textfield_->GetSelectedRange());
- EXPECT_STR_EQ("cd", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
- EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
+ EXPECT_STR_EQ("cd", GetClipboardText(ui::ClipboardType::kSelection));
+ EXPECT_EQ(ui::ClipboardType::kSelection, GetAndResetCopiedToClipboard());
textfield_->OnMousePressed(press_word);
textfield_->OnMouseReleased(release_word);
EXPECT_EQ(gfx::Range(0, 8), textfield_->GetSelectedRange());
- EXPECT_STR_EQ("ab cd ef", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
- EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
+ EXPECT_STR_EQ("ab cd ef", GetClipboardText(ui::ClipboardType::kSelection));
+ EXPECT_EQ(ui::ClipboardType::kSelection, GetAndResetCopiedToClipboard());
// Selecting a range of text without any user interaction should not change
// the clipboard content.
textfield_->SelectRange(gfx::Range(0, 3));
EXPECT_STR_EQ("ab ", textfield_->GetSelectedText());
- EXPECT_STR_EQ("ab cd ef", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
- EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
+ EXPECT_STR_EQ("ab cd ef", GetClipboardText(ui::ClipboardType::kSelection));
+ EXPECT_EQ(ui::ClipboardType::kMaxValue, GetAndResetCopiedToClipboard());
- SetClipboardText(ui::CLIPBOARD_TYPE_SELECTION, "other");
+ SetClipboardText(ui::ClipboardType::kSelection, "other");
textfield_->SelectAll(false);
- EXPECT_STR_EQ("other", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
- EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
+ EXPECT_STR_EQ("other", GetClipboardText(ui::ClipboardType::kSelection));
+ EXPECT_EQ(ui::ClipboardType::kMaxValue, GetAndResetCopiedToClipboard());
}
// Verify that the selection clipboard is not updated for selections on a
@@ -2995,8 +2994,8 @@ TEST_F(TextfieldTest, SelectionClipboard_Password) {
// textfield.
SendKeyEvent(ui::VKEY_A, false, true);
EXPECT_EQ(gfx::Range(0, 4), textfield_->GetSelectedRange());
- EXPECT_STR_EQ("abcd", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
- EXPECT_EQ(ui::CLIPBOARD_TYPE_SELECTION, GetAndResetCopiedToClipboard());
+ EXPECT_STR_EQ("abcd", GetClipboardText(ui::ClipboardType::kSelection));
+ EXPECT_EQ(ui::ClipboardType::kSelection, GetAndResetCopiedToClipboard());
// Move focus to the next textfield.
widget_->GetFocusManager()->AdvanceFocus(false);
@@ -3009,20 +3008,20 @@ TEST_F(TextfieldTest, SelectionClipboard_Password) {
textfield2->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
SendKeyEvent(ui::VKEY_A, false, true);
EXPECT_EQ(gfx::Range(0, 4), textfield2->GetSelectedRange());
- EXPECT_STR_EQ("abcd", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
- EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
+ EXPECT_STR_EQ("abcd", GetClipboardText(ui::ClipboardType::kSelection));
+ EXPECT_EQ(ui::ClipboardType::kMaxValue, GetAndResetCopiedToClipboard());
// Shift-Left/Right should not modify the selection clipboard for a password
// textfield.
SendKeyEvent(ui::VKEY_LEFT, true, false);
EXPECT_EQ(gfx::Range(0, 3), textfield2->GetSelectedRange());
- EXPECT_STR_EQ("abcd", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
- EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
+ EXPECT_STR_EQ("abcd", GetClipboardText(ui::ClipboardType::kSelection));
+ EXPECT_EQ(ui::ClipboardType::kMaxValue, GetAndResetCopiedToClipboard());
SendKeyEvent(ui::VKEY_RIGHT, true, false);
EXPECT_EQ(gfx::Range(0, 4), textfield2->GetSelectedRange());
- EXPECT_STR_EQ("abcd", GetClipboardText(ui::CLIPBOARD_TYPE_SELECTION));
- EXPECT_EQ(ui::CLIPBOARD_TYPE_LAST, GetAndResetCopiedToClipboard());
+ EXPECT_STR_EQ("abcd", GetClipboardText(ui::ClipboardType::kSelection));
+ EXPECT_EQ(ui::ClipboardType::kMaxValue, GetAndResetCopiedToClipboard());
}
#endif
@@ -3753,4 +3752,28 @@ TEST_F(TextfieldTest, ChangeTextDirectionAndLayoutAlignmentTest) {
gfx::HorizontalAlignment::ALIGN_LEFT);
}
+TEST_F(TextfieldTest, TextChangedCallbackTest) {
+ InitTextfield();
+
+ bool text_changed = false;
+ auto subscription = textfield_->AddTextChangedCallback(base::BindRepeating(
+ [](bool* text_changed) { *text_changed = true; }, &text_changed));
+
+ textfield_->SetText(ASCIIToUTF16("abc"));
+ EXPECT_TRUE(text_changed);
+
+ text_changed = false;
+ textfield_->AppendText(ASCIIToUTF16("def"));
+ EXPECT_TRUE(text_changed);
+
+ // Undo should still cause callback.
+ text_changed = false;
+ SendKeyEvent(ui::VKEY_Z, false, true);
+ EXPECT_TRUE(text_changed);
+
+ text_changed = false;
+ SendKeyEvent(ui::VKEY_BACK);
+ EXPECT_TRUE(text_changed);
+}
+
} // namespace views
diff --git a/chromium/ui/views/controls/throbber.cc b/chromium/ui/views/controls/throbber.cc
index 0987bec314f..44bd36d6f6b 100644
--- a/chromium/ui/views/controls/throbber.cc
+++ b/chromium/ui/views/controls/throbber.cc
@@ -52,12 +52,16 @@ void Throbber::Stop() {
SchedulePaint();
}
+bool Throbber::GetChecked() const {
+ return checked_;
+}
+
void Throbber::SetChecked(bool checked) {
if (checked == checked_)
return;
checked_ = checked;
- SchedulePaint();
+ OnPropertyChanged(&checked_, kPropertyEffectsPaint);
}
gfx::Size Throbber::CalculatePreferredSize() const {
@@ -86,6 +90,11 @@ bool Throbber::IsRunning() const {
return timer_.IsRunning();
}
+BEGIN_METADATA(Throbber)
+METADATA_PARENT_CLASS(View)
+ADD_PROPERTY_METADATA(Throbber, bool, Checked)
+END_METADATA()
+
// Smoothed throbber ---------------------------------------------------------
// Delay after work starts before starting throbber, in milliseconds.
@@ -124,8 +133,36 @@ void SmoothedThrobber::Stop() {
&SmoothedThrobber::StopDelayOver);
}
+int SmoothedThrobber::GetStartDelayMs() const {
+ return start_delay_ms_;
+}
+
+void SmoothedThrobber::SetStartDelayMs(int start_delay_ms) {
+ if (start_delay_ms == start_delay_ms_)
+ return;
+ start_delay_ms_ = start_delay_ms;
+ OnPropertyChanged(&start_delay_ms_, kPropertyEffectsNone);
+}
+
+int SmoothedThrobber::GetStopDelayMs() const {
+ return stop_delay_ms_;
+}
+
+void SmoothedThrobber::SetStopDelayMs(int stop_delay_ms) {
+ if (stop_delay_ms == stop_delay_ms_)
+ return;
+ stop_delay_ms_ = stop_delay_ms;
+ OnPropertyChanged(&stop_delay_ms_, kPropertyEffectsNone);
+}
+
void SmoothedThrobber::StopDelayOver() {
Throbber::Stop();
}
+BEGIN_METADATA(SmoothedThrobber)
+METADATA_PARENT_CLASS(Throbber)
+ADD_PROPERTY_METADATA(SmoothedThrobber, int, StartDelayMs)
+ADD_PROPERTY_METADATA(SmoothedThrobber, int, StopDelayMs)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/throbber.h b/chromium/ui/views/controls/throbber.h
index 8ba2b9ff876..2b19d996f40 100644
--- a/chromium/ui/views/controls/throbber.h
+++ b/chromium/ui/views/controls/throbber.h
@@ -17,6 +17,7 @@ namespace views {
class VIEWS_EXPORT Throbber : public View {
public:
+ METADATA_HEADER(Throbber);
Throbber();
~Throbber() override;
@@ -24,7 +25,9 @@ class VIEWS_EXPORT Throbber : public View {
virtual void Start();
virtual void Stop();
- // Stop spinning and, if checked is true, display a checkmark.
+ // Gets/Sets checked. For SetChecked, stop spinning and, if
+ // checked is true, display a checkmark.
+ bool GetChecked() const;
void SetChecked(bool checked);
// Overridden from View:
@@ -51,14 +54,18 @@ class VIEWS_EXPORT Throbber : public View {
// a small amount of work time has passed.
class VIEWS_EXPORT SmoothedThrobber : public Throbber {
public:
+ METADATA_HEADER(SmoothedThrobber);
SmoothedThrobber();
~SmoothedThrobber() override;
void Start() override;
void Stop() override;
- void set_start_delay_ms(int value) { start_delay_ms_ = value; }
- void set_stop_delay_ms(int value) { stop_delay_ms_ = value; }
+ int GetStartDelayMs() const;
+ void SetStartDelayMs(int start_delay_ms);
+
+ int GetStopDelayMs() const;
+ void SetStopDelayMs(int stop_delay_ms);
private:
// Called when the startup-delay timer fires
diff --git a/chromium/ui/views/controls/tree/tree_view.cc b/chromium/ui/views/controls/tree/tree_view.cc
index 560877ca6e3..7cc025f8431 100644
--- a/chromium/ui/views/controls/tree/tree_view.cc
+++ b/chromium/ui/views/controls/tree/tree_view.cc
@@ -25,6 +25,7 @@
#include "ui/gfx/image/image.h"
#include "ui/gfx/image/image_skia_operations.h"
#include "ui/gfx/paint_vector_icon.h"
+#include "ui/gfx/scoped_canvas.h"
#include "ui/gfx/skia_util.h"
#include "ui/native_theme/native_theme.h"
#include "ui/resources/grit/ui_resources.h"
@@ -35,7 +36,6 @@
#include "ui/views/controls/textfield/textfield.h"
#include "ui/views/controls/tree/tree_view_controller.h"
#include "ui/views/layout/layout_provider.h"
-#include "ui/views/resources/grit/views_resources.h"
#include "ui/views/style/platform_style.h"
#include "ui/views/vector_icons.h"
@@ -56,11 +56,16 @@ static constexpr int kTextHorizontalPadding = 2;
// How much children are indented from their parent.
static constexpr int kIndent = 20;
-// static
-const char TreeView::kViewClassName[] = "TreeView";
-
namespace {
+void PaintRowIcon(gfx::Canvas* canvas,
+ const gfx::ImageSkia& icon,
+ int x,
+ const gfx::Rect& rect) {
+ canvas->DrawImageInt(icon, rect.x() + x,
+ rect.y() + (rect.height() - icon.height()) / 2);
+}
+
bool EventIsDoubleTapOrClick(const ui::LocatedEvent& event) {
if (event.type() == ui::ET_GESTURE_TAP)
return event.AsGestureEvent()->details().tap_count() == 2;
@@ -84,14 +89,11 @@ TreeView::TreeView()
} else {
// TODO(ellyjones): if the pre-Harmony codepath goes away, merge
// closed_icon_ and open_icon_.
- closed_icon_ =
- *ui::ResourceBundle::GetSharedInstance()
- .GetImageNamed((base::i18n::IsRTL() ? IDR_FOLDER_CLOSED_RTL
- : IDR_FOLDER_CLOSED))
- .ToImageSkia();
+ closed_icon_ = *ui::ResourceBundle::GetSharedInstance()
+ .GetImageNamed(IDR_FOLDER_CLOSED)
+ .ToImageSkia();
open_icon_ = *ui::ResourceBundle::GetSharedInstance()
- .GetImageNamed((base::i18n::IsRTL() ? IDR_FOLDER_OPEN_RTL
- : IDR_FOLDER_OPEN))
+ .GetImageNamed(IDR_FOLDER_OPEN)
.ToImageSkia();
}
text_offset_ = closed_icon_.width() + kImagePadding + kImagePadding +
@@ -142,8 +144,8 @@ void TreeView::SetModel(TreeModel* model) {
root_.set_is_expanded(true);
if (root_shown_)
selected_node_ = &root_;
- else if (root_.child_count())
- selected_node_ = root_.GetChild(0);
+ else if (!root_.children().empty())
+ selected_node_ = root_.children().front().get();
}
DrawnNodesChanged();
}
@@ -440,22 +442,18 @@ void TreeView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
node_data->SetName(selected_node_->model_node()->GetTitle());
}
-const char* TreeView::GetClassName() const {
- return kViewClassName;
-}
-
void TreeView::TreeNodesAdded(TreeModel* model,
TreeModelNode* parent,
- int start,
- int count) {
+ size_t start,
+ size_t count) {
InternalNode* parent_node =
GetInternalNodeForModelNode(parent, DONT_CREATE_IF_NOT_LOADED);
if (!parent_node || !parent_node->loaded_children())
return;
const auto& children = model_->GetChildren(parent);
- for (int i = start; i < start + count; ++i) {
+ for (size_t i = start; i < start + count; ++i) {
auto child = std::make_unique<InternalNode>();
- ConfigureInternalNode(children[size_t{i}], child.get());
+ ConfigureInternalNode(children[i], child.get());
parent_node->Add(std::move(child), i);
}
if (IsExpanded(parent))
@@ -464,15 +462,15 @@ void TreeView::TreeNodesAdded(TreeModel* model,
void TreeView::TreeNodesRemoved(TreeModel* model,
TreeModelNode* parent,
- int start,
- int count) {
+ size_t start,
+ size_t count) {
InternalNode* parent_node =
GetInternalNodeForModelNode(parent, DONT_CREATE_IF_NOT_LOADED);
if (!parent_node || !parent_node->loaded_children())
return;
bool reset_selection = false;
- for (int i = 0; i < count; ++i) {
- InternalNode* child_removing = parent_node->GetChild(start);
+ for (size_t i = 0; i < count; ++i) {
+ InternalNode* child_removing = parent_node->children()[start].get();
if (selected_node_ && selected_node_->HasAncestor(child_removing))
reset_selection = true;
parent_node->Remove(start);
@@ -690,13 +688,13 @@ bool TreeView::OnClickOrTap(const ui::LocatedEvent& event) {
}
void TreeView::LoadChildren(InternalNode* node) {
- DCHECK_EQ(0, node->child_count());
+ DCHECK(node->children().empty());
DCHECK(!node->loaded_children());
node->set_loaded_children(true);
for (auto* model_child : model_->GetChildren(node->model_node())) {
std::unique_ptr<InternalNode> child = std::make_unique<InternalNode>();
ConfigureInternalNode(model_child, child.get());
- node->Add(std::move(child), node->child_count());
+ node->Add(std::move(child));
}
}
@@ -776,8 +774,8 @@ void TreeView::PaintRows(gfx::Canvas* canvas,
if (!node->is_expanded())
return;
depth++;
- for (int i = 0; i < node->child_count() && *row < max_row; ++i)
- PaintRows(canvas, min_row, max_row, node->GetChild(i), depth, row);
+ for (size_t i = 0; i < node->children().size() && *row < max_row; ++i)
+ PaintRows(canvas, min_row, max_row, node->children()[i].get(), depth, row);
}
void TreeView::PaintRow(gfx::Canvas* canvas,
@@ -867,22 +865,24 @@ void TreeView::PaintExpandControl(gfx::Canvas* canvas,
void TreeView::PaintNodeIcon(gfx::Canvas* canvas,
InternalNode* node,
const gfx::Rect& bounds) {
- gfx::ImageSkia icon;
int icon_index = model_->GetIconIndex(node->model_node());
- if (icon_index != -1)
- icon = icons_[icon_index];
- else if (node->is_expanded())
- icon = open_icon_;
- else
- icon = closed_icon_;
- int icon_x = kArrowRegionSize + kImagePadding +
- (open_icon_.width() - icon.width()) / 2;
- if (base::i18n::IsRTL())
- icon_x = bounds.right() - icon_x - open_icon_.width();
- else
- icon_x += bounds.x();
- canvas->DrawImageInt(icon, icon_x,
- bounds.y() + (bounds.height() - icon.height()) / 2);
+ int icon_x = kArrowRegionSize + kImagePadding;
+ if (icon_index == -1) {
+ // Flip just the |bounds| region of |canvas|.
+ gfx::ScopedCanvas scoped_canvas(canvas);
+ canvas->Translate(gfx::Vector2d(bounds.x(), 0));
+ scoped_canvas.FlipIfRTL(bounds.width());
+ // Now paint the icon local to that flipped region.
+ PaintRowIcon(canvas, node->is_expanded() ? open_icon_ : closed_icon_,
+ icon_x,
+ gfx::Rect(0, bounds.y(), bounds.width(), bounds.height()));
+ } else {
+ const gfx::ImageSkia& icon = icons_[icon_index];
+ icon_x += (open_icon_.width() - icon.width()) / 2;
+ if (base::i18n::IsRTL())
+ icon_x = bounds.width() - icon_x - icon.width();
+ PaintRowIcon(canvas, icon, icon_x, bounds);
+ }
}
TreeView::InternalNode* TreeView::GetInternalNodeForModelNode(
@@ -899,8 +899,9 @@ TreeView::InternalNode* TreeView::GetInternalNodeForModelNode(
return nullptr;
LoadChildren(parent_internal_node);
}
- return parent_internal_node->GetChild(
- model_->GetIndexOf(parent_internal_node->model_node(), model_node));
+ size_t index =
+ model_->GetIndexOf(parent_internal_node->model_node(), model_node);
+ return parent_internal_node->children()[index].get();
}
gfx::Rect TreeView::GetBoundsForNode(InternalNode* node) {
@@ -967,11 +968,11 @@ int TreeView::GetRowForInternalNode(InternalNode* node, int* depth) {
int row = -1;
InternalNode* tmp_node = node;
while (tmp_node->parent()) {
- int index_in_parent = tmp_node->parent()->GetIndexOf(tmp_node);
+ size_t index_in_parent = tmp_node->parent()->GetIndexOf(tmp_node);
(*depth)++;
row++; // For node.
- for (int i = 0; i < index_in_parent; ++i)
- row += tmp_node->parent()->GetChild(i)->NumExpandedNodes();
+ for (size_t i = 0; i < index_in_parent; ++i)
+ row += tmp_node->parent()->children()[i]->NumExpandedNodes();
tmp_node = tmp_node->parent();
}
if (root_shown_) {
@@ -1014,10 +1015,9 @@ TreeView::InternalNode* TreeView::GetNodeByRowImpl(InternalNode* node,
(*current_row)++;
if (node->is_expanded()) {
current_depth++;
- for (int i = 0; i < node->child_count(); ++i) {
+ for (const auto& child : node->children()) {
InternalNode* result = GetNodeByRowImpl(
- node->GetChild(i), target_row, current_depth, current_row,
- node_depth);
+ child.get(), target_row, current_depth, current_row, node_depth);
if (result)
return result;
}
@@ -1031,7 +1031,7 @@ void TreeView::IncrementSelection(IncrementType type) {
if (!GetSelectedNode()) {
// If nothing is selected select the first or last node.
- if (!root_.child_count())
+ if (root_.children().empty())
return;
if (type == INCREMENT_PREVIOUS) {
int row_count = GetRowCount();
@@ -1042,7 +1042,7 @@ void TreeView::IncrementSelection(IncrementType type) {
} else if (root_shown_) {
SetSelectedNode(root_.model_node());
} else {
- SetSelectedNode(root_.GetChild(0)->model_node());
+ SetSelectedNode(root_.children().front()->model_node());
}
return;
}
@@ -1069,8 +1069,8 @@ void TreeView::ExpandOrSelectChild() {
if (selected_node_) {
if (!selected_node_->is_expanded())
Expand(selected_node_->model_node());
- else if (selected_node_->child_count())
- SetSelectedNode(selected_node_->GetChild(0)->model_node());
+ else if (!selected_node_->children().empty())
+ SetSelectedNode(selected_node_->children().front()->model_node());
}
}
@@ -1146,8 +1146,8 @@ int TreeView::InternalNode::NumExpandedNodes() const {
int result = 1; // For this.
if (!is_expanded_)
return result;
- for (int i = 0; i < child_count(); ++i)
- result += GetChild(i)->NumExpandedNodes();
+ for (const auto& child : children())
+ result += child->NumExpandedNodes();
return result;
}
@@ -1157,11 +1157,15 @@ int TreeView::InternalNode::GetMaxWidth(TreeView* tree, int indent, int depth) {
int max_width = (has_icon ? text_width_ : kArrowRegionSize) + indent * depth;
if (!is_expanded_)
return max_width;
- for (int i = 0; i < child_count(); ++i) {
+ for (const auto& child : children()) {
max_width =
- std::max(max_width, GetChild(i)->GetMaxWidth(tree, indent, depth + 1));
+ std::max(max_width, child->GetMaxWidth(tree, indent, depth + 1));
}
return max_width;
}
+BEGIN_METADATA(TreeView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/tree/tree_view.h b/chromium/ui/views/controls/tree/tree_view.h
index 649a244dbfa..facb792fac1 100644
--- a/chromium/ui/views/controls/tree/tree_view.h
+++ b/chromium/ui/views/controls/tree/tree_view.h
@@ -43,8 +43,7 @@ class VIEWS_EXPORT TreeView : public View,
public FocusChangeListener,
public PrefixDelegate {
public:
- // The tree view's class name.
- static const char kViewClassName[];
+ METADATA_HEADER(TreeView);
TreeView();
~TreeView() override;
@@ -139,17 +138,16 @@ class VIEWS_EXPORT TreeView : public View,
void ShowContextMenu(const gfx::Point& p,
ui::MenuSourceType source_type) override;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
- const char* GetClassName() const override;
// TreeModelObserver overrides:
void TreeNodesAdded(ui::TreeModel* model,
ui::TreeModelNode* parent,
- int start,
- int count) override;
+ size_t start,
+ size_t count) override;
void TreeNodesRemoved(ui::TreeModel* model,
ui::TreeModelNode* parent,
- int start,
- int count) override;
+ size_t start,
+ size_t count) override;
void TreeNodeChanged(ui::TreeModel* model,
ui::TreeModelNode* model_node) override;
diff --git a/chromium/ui/views/controls/tree/tree_view_unittest.cc b/chromium/ui/views/controls/tree/tree_view_unittest.cc
index d37796e9d68..37bffe1d376 100644
--- a/chromium/ui/views/controls/tree/tree_view_unittest.cc
+++ b/chromium/ui/views/controls/tree/tree_view_unittest.cc
@@ -4,6 +4,7 @@
#include "ui/views/controls/tree/tree_view.h"
+#include <numeric>
#include <string>
#include "base/macros.h"
@@ -47,9 +48,7 @@ class TreeViewTest : public ViewsTestBase {
}
protected:
- TestNode* Add(TestNode* parent,
- int index,
- const std::string& title);
+ TestNode* Add(TestNode* parent, size_t index, const std::string& title);
std::string TreeViewContentsAsString();
@@ -77,7 +76,7 @@ class TreeViewTest : public ViewsTestBase {
};
TestNode* TreeViewTest::Add(TestNode* parent,
- int index,
+ size_t index,
const std::string& title) {
std::unique_ptr<TestNode> new_node = std::make_unique<TestNode>();
new_node->SetTitle(ASCIIToUTF16(title));
@@ -125,10 +124,10 @@ TestNode* TreeViewTest::GetNodeByTitleImpl(TestNode* node,
const base::string16& title) {
if (node->GetTitle() == title)
return node;
- for (int i = 0; i < node->child_count(); ++i) {
- TestNode* child = GetNodeByTitleImpl(node->GetChild(i), title);
- if (child)
- return child;
+ for (auto& child : node->children()) {
+ TestNode* matching_node = GetNodeByTitleImpl(child.get(), title);
+ if (matching_node)
+ return matching_node;
}
return nullptr;
}
@@ -136,14 +135,14 @@ TestNode* TreeViewTest::GetNodeByTitleImpl(TestNode* node,
std::string TreeViewTest::InternalNodeAsString(
TreeView::InternalNode* node) {
std::string result = base::UTF16ToASCII(node->model_node()->GetTitle());
- if (node->is_expanded() && node->child_count()) {
- result += " [";
- for (int i = 0; i < node->child_count(); ++i) {
- if (i > 0)
- result += " ";
- result += InternalNodeAsString(node->GetChild(i));
- }
- result += "]";
+ if (node->is_expanded() && !node->children().empty()) {
+ result += std::accumulate(
+ node->children().cbegin() + 1, node->children().cend(),
+ " [" + InternalNodeAsString(node->children().front().get()),
+ [this](const std::string& str, const auto& child) {
+ return str + " " + InternalNodeAsString(child.get());
+ }) +
+ "]";
}
return result;
}
diff --git a/chromium/ui/views/controls/webview/unhandled_keyboard_event_handler_mac.mm b/chromium/ui/views/controls/webview/unhandled_keyboard_event_handler_mac.mm
index 3aa97dc8fbd..e84db1650f0 100644
--- a/chromium/ui/views/controls/webview/unhandled_keyboard_event_handler_mac.mm
+++ b/chromium/ui/views/controls/webview/unhandled_keyboard_event_handler_mac.mm
@@ -4,7 +4,7 @@
#include "ui/views/controls/webview/unhandled_keyboard_event_handler.h"
-#import "ui/views/cocoa/bridged_native_widget_host_impl.h"
+#import "ui/views/cocoa/native_widget_mac_ns_window_host.h"
namespace views {
@@ -13,7 +13,7 @@ bool UnhandledKeyboardEventHandler::HandleNativeKeyboardEvent(
gfx::NativeEvent event,
FocusManager* focus_manager) {
auto* host =
- views::BridgedNativeWidgetHostImpl::GetFromNativeWindow([event window]);
+ views::NativeWidgetMacNSWindowHost::GetFromNativeWindow([event window]);
if (host)
return host->RedispatchKeyEvent(event);
return false;
diff --git a/chromium/ui/views/controls/webview/web_dialog_view.cc b/chromium/ui/views/controls/webview/web_dialog_view.cc
index fc3d4875c89..dccc4e3d21f 100644
--- a/chromium/ui/views/controls/webview/web_dialog_view.cc
+++ b/chromium/ui/views/controls/webview/web_dialog_view.cc
@@ -124,6 +124,10 @@ bool WebDialogView::CanClose() {
////////////////////////////////////////////////////////////////////////////////
// WebDialogView, views::WidgetDelegate implementation:
+bool WebDialogView::OnCloseRequested(Widget::ClosedReason close_reason) {
+ return !delegate_ || delegate_->OnDialogCloseRequested();
+}
+
bool WebDialogView::CanResize() const {
if (delegate_)
return delegate_->CanResizeDialog();
diff --git a/chromium/ui/views/controls/webview/web_dialog_view.h b/chromium/ui/views/controls/webview/web_dialog_view.h
index 3e397a508f3..f77676f6f69 100644
--- a/chromium/ui/views/controls/webview/web_dialog_view.h
+++ b/chromium/ui/views/controls/webview/web_dialog_view.h
@@ -64,6 +64,7 @@ class WEBVIEW_EXPORT WebDialogView : public views::ClientView,
bool CanClose() override;
// Overridden from views::WidgetDelegate:
+ bool OnCloseRequested(Widget::ClosedReason close_reason) override;
bool CanResize() const override;
ui::ModalType GetModalType() const override;
base::string16 GetWindowTitle() const override;
diff --git a/chromium/ui/views/controls/webview/webview.cc b/chromium/ui/views/controls/webview/webview.cc
index 85a5587f4c5..805703d5f79 100644
--- a/chromium/ui/views/controls/webview/webview.cc
+++ b/chromium/ui/views/controls/webview/webview.cc
@@ -19,7 +19,6 @@
#include "ui/accessibility/ax_enums.mojom.h"
#include "ui/accessibility/ax_node_data.h"
#include "ui/events/event.h"
-#include "ui/views/controls/native/native_view_host.h"
#include "ui/views/focus/focus_manager.h"
#include "ui/views/views_delegate.h"
@@ -46,20 +45,11 @@ WebView::ScopedWebContentsCreatorForTesting::
*GetCreatorForTesting() = WebView::WebContentsCreator();
}
-// static
-const char WebView::kViewClassName[] = "WebView";
-
////////////////////////////////////////////////////////////////////////////////
// WebView, public:
WebView::WebView(content::BrowserContext* browser_context)
- : holder_(new NativeViewHost()),
- embed_fullscreen_widget_mode_enabled_(false),
- is_embedding_fullscreen_widget_(false),
- browser_context_(browser_context),
- allow_accelerators_(false) {
- AddChildView(holder_); // Takes ownership of |holder_|.
-}
+ : browser_context_(browser_context) {}
WebView::~WebView() {
SetWebContents(nullptr); // Make sure all necessary tear-down takes place.
@@ -79,7 +69,7 @@ void WebView::SetWebContents(content::WebContents* replacement) {
if (replacement == web_contents())
return;
SetCrashedOverlayView(nullptr);
- DetachWebContents();
+ DetachWebContentsNativeView();
WebContentsObserver::Observe(replacement);
// web_contents() now returns |replacement| from here onwards.
UpdateCrashedOverlayView();
@@ -87,11 +77,12 @@ void WebView::SetWebContents(content::WebContents* replacement) {
wc_owner_.reset();
if (embed_fullscreen_widget_mode_enabled_) {
is_embedding_fullscreen_widget_ =
- web_contents() && web_contents()->GetFullscreenRenderWidgetHostView();
+ fullscreen_native_view_for_testing_ ||
+ (web_contents() && web_contents()->GetFullscreenRenderWidgetHostView());
} else {
DCHECK(!is_embedding_fullscreen_widget_);
}
- AttachWebContents();
+ AttachWebContentsNativeView();
NotifyAccessibilityWebContentsChanged();
MaybeEnableAutoResize();
@@ -148,10 +139,6 @@ void WebView::SetCrashedOverlayView(View* crashed_overlay_view) {
////////////////////////////////////////////////////////////////////////////////
// WebView, View overrides:
-const char* WebView::GetClassName() const {
- return kViewClassName;
-}
-
void WebView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
if (crashed_overlay_view_)
crashed_overlay_view_->SetBoundsRect(gfx::Rect(size()));
@@ -203,7 +190,7 @@ void WebView::OnBoundsChanged(const gfx::Rect& previous_bounds) {
void WebView::ViewHierarchyChanged(
const ViewHierarchyChangedDetails& details) {
if (details.is_add)
- AttachWebContents();
+ AttachWebContentsNativeView();
}
bool WebView::SkipDefaultKeyEventProcessing(const ui::KeyEvent& event) {
@@ -268,7 +255,7 @@ gfx::NativeViewAccessible WebView::GetNativeViewAccessible() {
////////////////////////////////////////////////////////////////////////////////
// WebView, content::WebContentsDelegate implementation:
-bool WebView::EmbedsFullscreenWidget() const {
+bool WebView::EmbedsFullscreenWidget() {
DCHECK(wc_owner_.get());
return embed_fullscreen_widget_mode_enabled_;
}
@@ -348,16 +335,23 @@ void WebView::ResizeDueToAutoResize(content::WebContents* source,
////////////////////////////////////////////////////////////////////////////////
// WebView, private:
-void WebView::AttachWebContents() {
- TRACE_EVENT0("views", "WebView::AttachWebContents");
+void WebView::AttachWebContentsNativeView() {
+ TRACE_EVENT0("views", "WebView::AttachWebContentsNativeView");
// Prevents attachment if the WebView isn't already in a Widget, or it's
// already attached.
if (!GetWidget() || !web_contents())
return;
- const gfx::NativeView view_to_attach = is_embedding_fullscreen_widget_ ?
- web_contents()->GetFullscreenRenderWidgetHostView()->GetNativeView() :
- web_contents()->GetNativeView();
+ gfx::NativeView view_to_attach;
+ if (is_embedding_fullscreen_widget_) {
+ view_to_attach = fullscreen_native_view_for_testing_
+ ? fullscreen_native_view_for_testing_
+ : web_contents()
+ ->GetFullscreenRenderWidgetHostView()
+ ->GetNativeView();
+ } else {
+ view_to_attach = web_contents()->GetNativeView();
+ }
OnBoundsChanged(bounds());
if (holder_->native_view() == view_to_attach)
return;
@@ -381,24 +375,24 @@ void WebView::AttachWebContents() {
OnWebContentsAttached();
}
-void WebView::DetachWebContents() {
- TRACE_EVENT0("views", "WebView::DetachWebContents");
- if (web_contents()) {
+void WebView::DetachWebContentsNativeView() {
+ TRACE_EVENT0("views", "WebView::DetachWebContentsNativeView");
+ if (web_contents())
holder_->Detach();
- }
}
void WebView::ReattachForFullscreenChange(bool enter_fullscreen) {
DCHECK(embed_fullscreen_widget_mode_enabled_);
const bool web_contents_has_separate_fs_widget =
- web_contents() && web_contents()->GetFullscreenRenderWidgetHostView();
+ fullscreen_native_view_for_testing_ ||
+ (web_contents() && web_contents()->GetFullscreenRenderWidgetHostView());
if (is_embedding_fullscreen_widget_ || web_contents_has_separate_fs_widget) {
// Shutting down or starting up the embedding of the separate fullscreen
// widget. Need to detach and re-attach to a different native view.
- DetachWebContents();
+ DetachWebContentsNativeView();
is_embedding_fullscreen_widget_ =
enter_fullscreen && web_contents_has_separate_fs_widget;
- AttachWebContents();
+ AttachWebContentsNativeView();
} else {
// Entering or exiting "non-Flash" fullscreen mode, where the native view is
// the same. So, do not change attachment.
@@ -454,4 +448,8 @@ void WebView::MaybeEnableAutoResize() {
render_widget_host_view->EnableAutoResize(min_size_, max_size_);
}
+BEGIN_METADATA(WebView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/controls/webview/webview.h b/chromium/ui/views/controls/webview/webview.h
index 2d358a9d028..9872ad3c2f4 100644
--- a/chromium/ui/views/controls/webview/webview.h
+++ b/chromium/ui/views/controls/webview/webview.h
@@ -14,13 +14,12 @@
#include "content/public/browser/web_contents_delegate.h"
#include "content/public/browser/web_contents_observer.h"
#include "ui/gfx/native_widget_types.h"
+#include "ui/views/controls/native/native_view_host.h"
#include "ui/views/controls/webview/webview_export.h"
#include "ui/views/view.h"
namespace views {
-class NativeViewHost;
-
// Provides a view of a WebContents instance. WebView can be used standalone,
// creating and displaying an internally-owned WebContents; or within a full
// browser where the browser swaps its own WebContents instances in/out (e.g.,
@@ -39,7 +38,7 @@ class WEBVIEW_EXPORT WebView : public View,
public content::WebContentsDelegate,
public content::WebContentsObserver {
public:
- static const char kViewClassName[];
+ METADATA_HEADER(WebView);
explicit WebView(content::BrowserContext* browser_context);
~WebView() override;
@@ -92,9 +91,6 @@ class WEBVIEW_EXPORT WebView : public View,
allow_accelerators_ = allow_accelerators;
}
- // Overridden from View:
- const char* GetClassName() const override;
-
// Overridden from content::WebContentsDelegate:
void ResizeDueToAutoResize(content::WebContents* source,
const gfx::Size& new_size) override;
@@ -138,7 +134,7 @@ class WEBVIEW_EXPORT WebView : public View,
gfx::NativeViewAccessible GetNativeViewAccessible() override;
// Overridden from content::WebContentsDelegate:
- bool EmbedsFullscreenWidget() const override;
+ bool EmbedsFullscreenWidget() override;
// Overridden from content::WebContentsObserver:
void RenderViewCreated(content::RenderViewHost* render_view_host) override;
@@ -165,8 +161,8 @@ class WEBVIEW_EXPORT WebView : public View,
private:
friend class WebViewUnitTest;
- void AttachWebContents();
- void DetachWebContents();
+ void AttachWebContentsNativeView();
+ void DetachWebContentsNativeView();
void ReattachForFullscreenChange(bool enter_fullscreen);
void UpdateCrashedOverlayView();
void NotifyAccessibilityWebContentsChanged();
@@ -181,20 +177,21 @@ class WEBVIEW_EXPORT WebView : public View,
std::unique_ptr<content::WebContents> CreateWebContents(
content::BrowserContext* browser_context);
- NativeViewHost* const holder_;
+ NativeViewHost* const holder_ =
+ AddChildView(std::make_unique<NativeViewHost>());
// Non-NULL if |web_contents()| was created and is owned by this WebView.
std::unique_ptr<content::WebContents> wc_owner_;
// When true, WebView auto-embeds fullscreen widgets as a child view.
- bool embed_fullscreen_widget_mode_enabled_;
+ bool embed_fullscreen_widget_mode_enabled_ = false;
// Set to true while WebView is embedding a fullscreen widget view as a child
// view instead of the normal WebContentsView render view. Note: This will be
// false in the case of non-Flash fullscreen.
- bool is_embedding_fullscreen_widget_;
+ bool is_embedding_fullscreen_widget_ = false;
// Set to true when |holder_| is letterboxed (scaled to be smaller than this
// view, to preserve its aspect ratio).
bool is_letterboxing_ = false;
content::BrowserContext* browser_context_;
- bool allow_accelerators_;
+ bool allow_accelerators_ = false;
View* crashed_overlay_view_ = nullptr;
// Minimum and maximum sizes to determine WebView bounds for auto-resizing.
@@ -206,6 +203,13 @@ class WEBVIEW_EXPORT WebView : public View,
// WebContents's main RenderFrameHost.
ui::AXTreeID child_ax_tree_id_;
+ // Used as the fullscreen NativeView if
+ // |embed_fullscreen_widget_mode_enabled_| is enabled. This is only set in
+ // tests as injecting a different value for
+ // WebContents::GetFullscreenRenderWidgetHostView() is rather tricky in
+ // unit-tests.
+ gfx::NativeView fullscreen_native_view_for_testing_ = nullptr;
+
DISALLOW_COPY_AND_ASSIGN(WebView);
};
diff --git a/chromium/ui/views/controls/webview/webview_unittest.cc b/chromium/ui/views/controls/webview/webview_unittest.cc
index 8950e868889..e2fc8221a19 100644
--- a/chromium/ui/views/controls/webview/webview_unittest.cc
+++ b/chromium/ui/views/controls/webview/webview_unittest.cc
@@ -111,7 +111,7 @@ class WebViewTestWebContentsDelegate : public content::WebContentsDelegate {
// content::WebContentsDelegate overrides.
bool IsFullscreenForTabOrPending(
- const content::WebContents* ignored) const override {
+ const content::WebContents* ignored) override {
return is_fullscreened_;
}
@@ -190,6 +190,10 @@ class WebViewUnitTest : public views::test::WidgetTest {
content::WebContents::CreateParams(browser_context_.get()));
}
+ void SetFullscreenNativeView(WebView* web_view, gfx::NativeView native_view) {
+ web_view->fullscreen_native_view_for_testing_ = native_view;
+ }
+
private:
std::unique_ptr<content::RenderViewHostTestEnabler> rvh_enabler_;
std::unique_ptr<content::TestBrowserContext> browser_context_;
@@ -561,4 +565,44 @@ TEST_F(WebViewUnitTest, CrashedOverlayViewOwnedbyClient) {
delete crashed_overlay_view;
}
+#if defined(USE_AURA)
+namespace {
+
+// TODO(sky): factor this for mac.
+gfx::Rect GetNativeViewBounds(gfx::NativeView native_view) {
+ return native_view->bounds();
+}
+
+} // namespace
+
+TEST_F(WebViewUnitTest, LayoutFullscreenNativeView) {
+ web_view()->SetEmbedFullscreenWidgetMode(true);
+ // WebView lazily creates WebContents. Force creation.
+ web_view()->GetWebContents();
+ // Layout is async, force a layout now to ensure bounds are set.
+ web_view()->Layout();
+ const gfx::Rect initial_bounds =
+ GetNativeViewBounds(web_view()->GetWebContents()->GetNativeView());
+ EXPECT_NE(gfx::Rect(), initial_bounds);
+
+ // Create another WebContents for a separate gfx::NativeView. The WebContent's
+ // gfx::NativeView is used as the fullscreen widget for web_view().
+ const std::unique_ptr<content::WebContents> fullscreen_web_contents(
+ CreateWebContents());
+ EXPECT_NE(initial_bounds,
+ GetNativeViewBounds(fullscreen_web_contents->GetNativeView()));
+ SetFullscreenNativeView(web_view(), fullscreen_web_contents->GetNativeView());
+
+ // Trigger going fullscreen. Once fullscreen, the fullscreen gfx::NativeView
+ // should be immediately resized.
+ static_cast<content::WebContentsObserver*>(web_view())
+ ->DidShowFullscreenWidget();
+ EXPECT_EQ(initial_bounds,
+ GetNativeViewBounds(fullscreen_web_contents->GetNativeView()));
+
+ static_cast<content::WebContentsObserver*>(web_view())
+ ->DidDestroyFullscreenWidget();
+}
+#endif
+
} // namespace views
diff --git a/chromium/ui/views/corewm/tooltip_aura.cc b/chromium/ui/views/corewm/tooltip_aura.cc
index 3bb4ca0c143..2279c53c3a3 100644
--- a/chromium/ui/views/corewm/tooltip_aura.cc
+++ b/chromium/ui/views/corewm/tooltip_aura.cc
@@ -13,6 +13,7 @@
#include "ui/display/display.h"
#include "ui/display/screen.h"
#include "ui/gfx/canvas.h"
+#include "ui/gfx/color_utils.h"
#include "ui/gfx/render_text.h"
#include "ui/gfx/text_elider.h"
#include "ui/gfx/text_utils.h"
@@ -27,15 +28,20 @@ namespace {
// Max visual tooltip width. If a tooltip is greater than this width, it will
// be wrapped.
-constexpr int kTooltipMaxWidthPixels = 400;
+constexpr int kTooltipMaxWidthPixels = 800;
// FIXME: get cursor offset from actual cursor size.
constexpr int kCursorOffsetX = 10;
constexpr int kCursorOffsetY = 15;
+// Paddings
+constexpr int kHorizontalPadding = 8;
+constexpr int kVerticalPaddingTop = 4;
+constexpr int kVerticalPaddingBottom = 5;
+
// TODO(varkha): Update if native widget can be transparent on Linux.
bool CanUseTranslucentTooltipWidget() {
-#if defined(OS_LINUX) && !defined(OS_CHROMEOS)
+#if (defined(OS_LINUX) && !defined(OS_CHROMEOS)) || defined(OS_WIN)
return false;
#else
return true;
@@ -52,7 +58,7 @@ views::Widget* CreateTooltipWidget(aura::Window* tooltip_window,
params.type = views::Widget::InitParams::TYPE_TOOLTIP;
params.context = tooltip_window;
DCHECK(params.context);
- params.keep_on_top = true;
+ params.z_order = ui::ZOrderLevel::kFloatingUIElement;
params.accept_events = false;
params.bounds = bounds;
if (CanUseTranslucentTooltipWidget())
@@ -71,9 +77,6 @@ namespace corewm {
class TooltipAura::TooltipView : public views::View {
public:
TooltipView() : render_text_(gfx::RenderText::CreateHarfBuzzInstance()) {
- constexpr int kHorizontalPadding = 8;
- constexpr int kVerticalPaddingTop = 4;
- constexpr int kVerticalPaddingBottom = 5;
SetBorder(CreateEmptyBorder(kVerticalPaddingTop, kHorizontalPadding,
kVerticalPaddingBottom, kHorizontalPadding));
@@ -122,13 +125,22 @@ class TooltipAura::TooltipView : public views::View {
}
void SetBackgroundColor(SkColor background_color) {
- // Corner radius of tooltip background.
- const float kTooltipCornerRadius = 2.f;
- SetBackground(CanUseTranslucentTooltipWidget()
- ? views::CreateBackgroundFromPainter(
- views::Painter::CreateSolidRoundRectPainter(
- background_color, kTooltipCornerRadius))
- : views::CreateSolidBackground(background_color));
+ if (CanUseTranslucentTooltipWidget()) {
+ // Corner radius of tooltip background.
+ const float kTooltipCornerRadius = 2.f;
+ SetBackground(views::CreateBackgroundFromPainter(
+ views::Painter::CreateSolidRoundRectPainter(background_color,
+ kTooltipCornerRadius)));
+ } else {
+ SetBackground(views::CreateSolidBackground(background_color));
+
+ auto border_color =
+ color_utils::GetColorWithMaxContrast(background_color);
+ SetBorder(views::CreatePaddedBorder(
+ views::CreateSolidBorder(1, border_color),
+ gfx::Insets(kVerticalPaddingTop - 1, kHorizontalPadding - 1,
+ kVerticalPaddingBottom - 1, kHorizontalPadding - 1)));
+ }
// Force the text color to be readable when |background_color| is not
// opaque.
@@ -220,10 +232,16 @@ void TooltipAura::SetText(aura::Window* window,
}
ui::NativeTheme* native_theme = widget_->GetNativeTheme();
- tooltip_view_->SetBackgroundColor(native_theme->GetSystemColor(
- ui::NativeTheme::kColorId_TooltipBackground));
- tooltip_view_->SetForegroundColor(native_theme->GetSystemColor(
- ui::NativeTheme::kColorId_TooltipText));
+ auto background_color =
+ native_theme->GetSystemColor(ui::NativeTheme::kColorId_TooltipBackground);
+ if (!CanUseTranslucentTooltipWidget())
+ background_color = SkColorSetA(background_color, 0xFF);
+ tooltip_view_->SetBackgroundColor(background_color);
+ auto foreground_color =
+ native_theme->GetSystemColor(ui::NativeTheme::kColorId_TooltipText);
+ if (!CanUseTranslucentTooltipWidget())
+ foreground_color = SkColorSetA(foreground_color, 0xFF);
+ tooltip_view_->SetForegroundColor(foreground_color);
}
void TooltipAura::Show() {
diff --git a/chromium/ui/views/corewm/tooltip_controller_unittest.cc b/chromium/ui/views/corewm/tooltip_controller_unittest.cc
index 96851116416..600f6bde5d2 100644
--- a/chromium/ui/views/corewm/tooltip_controller_unittest.cc
+++ b/chromium/ui/views/corewm/tooltip_controller_unittest.cc
@@ -629,7 +629,7 @@ class TooltipControllerTest2 : public aura::test::AuraTestBase {
std::unique_ptr<ui::test::EventGenerator> generator_;
private:
- // Needed to make sure the InputDeviceManager is cleaned up between test runs.
+ // Needed to make sure the DeviceDataManager is cleaned up between test runs.
std::unique_ptr<base::ShadowingAtExitManager> at_exit_manager_;
std::unique_ptr<TooltipController> controller_;
diff --git a/chromium/ui/views/drag_utils.h b/chromium/ui/views/drag_utils.h
index e6f778e4f31..1604d9ec0f5 100644
--- a/chromium/ui/views/drag_utils.h
+++ b/chromium/ui/views/drag_utils.h
@@ -5,7 +5,10 @@
#ifndef UI_VIEWS_DRAG_UTILS_H_
#define UI_VIEWS_DRAG_UTILS_H_
+#include <memory>
+
#include "ui/base/dragdrop/drag_drop_types.h"
+#include "ui/base/dragdrop/os_exchange_data.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/views/views_export.h"
@@ -13,16 +16,12 @@ namespace gfx {
class Point;
}
-namespace ui {
-class OSExchangeData;
-}
-
namespace views {
class Widget;
// Starts a drag operation. This blocks until the drag operation completes.
VIEWS_EXPORT void RunShellDrag(gfx::NativeView view,
- const ui::OSExchangeData& data,
+ std::unique_ptr<ui::OSExchangeData> data,
const gfx::Point& location,
int operation,
ui::DragDropTypes::DragEventSource source);
diff --git a/chromium/ui/views/drag_utils_aura.cc b/chromium/ui/views/drag_utils_aura.cc
index 27577e0eb2c..3142d9c0f56 100644
--- a/chromium/ui/views/drag_utils_aura.cc
+++ b/chromium/ui/views/drag_utils_aura.cc
@@ -12,7 +12,7 @@
namespace views {
void RunShellDrag(gfx::NativeView view,
- const ui::OSExchangeData& data,
+ std::unique_ptr<ui::OSExchangeData> data,
const gfx::Point& location,
int operation,
ui::DragDropTypes::DragEventSource source) {
@@ -20,8 +20,9 @@ void RunShellDrag(gfx::NativeView view,
wm::ConvertPointToScreen(view, &screen_location);
aura::Window* root_window = view->GetRootWindow();
if (aura::client::GetDragDropClient(root_window)) {
- aura::client::GetDragDropClient(root_window)->StartDragAndDrop(
- data, root_window, view, screen_location, operation, source);
+ aura::client::GetDragDropClient(root_window)
+ ->StartDragAndDrop(std::move(data), root_window, view, screen_location,
+ operation, source);
}
}
diff --git a/chromium/ui/views/drag_utils_mac.mm b/chromium/ui/views/drag_utils_mac.mm
index 4d512b1f97c..59dc6eae3f3 100644
--- a/chromium/ui/views/drag_utils_mac.mm
+++ b/chromium/ui/views/drag_utils_mac.mm
@@ -7,7 +7,7 @@
namespace views {
void RunShellDrag(gfx::NativeView view,
- const ui::OSExchangeData& data,
+ std::unique_ptr<ui::OSExchangeData> data,
const gfx::Point& location,
int operation,
ui::DragDropTypes::DragEventSource source) {
diff --git a/chromium/ui/views/event_utils.cc b/chromium/ui/views/event_utils.cc
deleted file mode 100644
index 83ca464f1b6..00000000000
--- a/chromium/ui/views/event_utils.cc
+++ /dev/null
@@ -1,21 +0,0 @@
-// Copyright (c) 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#include "ui/views/event_utils.h"
-
-#include "base/time/time.h"
-#include "ui/events/event.h"
-#include "ui/views/metrics.h"
-
-namespace views {
-
-bool IsPossiblyUnintendedInteraction(const base::TimeTicks& initial_timestamp,
- const ui::Event& event) {
- return (event.IsMouseEvent() || event.IsTouchEvent()) &&
- event.time_stamp() <
- initial_timestamp +
- base::TimeDelta::FromMilliseconds(GetDoubleClickInterval());
-}
-
-} // namespace views
diff --git a/chromium/ui/views/event_utils.h b/chromium/ui/views/event_utils.h
deleted file mode 100644
index cfc553ff659..00000000000
--- a/chromium/ui/views/event_utils.h
+++ /dev/null
@@ -1,28 +0,0 @@
-// Copyright (c) 2018 The Chromium Authors. All rights reserved.
-// Use of this source code is governed by a BSD-style license that can be
-// found in the LICENSE file.
-
-#ifndef UI_VIEWS_EVENT_UTILS_H_
-#define UI_VIEWS_EVENT_UTILS_H_
-
-#include "ui/views/views_export.h"
-
-namespace base {
-class TimeTicks;
-}
-
-namespace ui {
-class Event;
-}
-
-namespace views {
-
-// Returns true if the event is a mouse, touch, or pointer event that took place
-// within the double-click time interval after the |initial_timestamp|.
-VIEWS_EXPORT bool IsPossiblyUnintendedInteraction(
- const base::TimeTicks& initial_timestamp,
- const ui::Event& event);
-
-} // namespace views
-
-#endif // UI_VIEWS_EVENT_UTILS_H_
diff --git a/chromium/ui/views/examples/BUILD.gn b/chromium/ui/views/examples/BUILD.gn
index d184ac3f46a..90e1df27192 100644
--- a/chromium/ui/views/examples/BUILD.gn
+++ b/chromium/ui/views/examples/BUILD.gn
@@ -123,6 +123,7 @@ executable("views_examples_exe") {
"//build/win:default_exe_manifest",
"//components/viz/host",
"//components/viz/service",
+ "//mojo/core/embedder",
"//ui/base",
"//ui/base/ime/init",
"//ui/compositor",
diff --git a/chromium/ui/views/examples/DEPS b/chromium/ui/views/examples/DEPS
index 36a503acd46..7d637be55cc 100644
--- a/chromium/ui/views/examples/DEPS
+++ b/chromium/ui/views/examples/DEPS
@@ -3,6 +3,7 @@ include_rules = [
"+components/viz/service", # In-process viz service.
"+content/public",
"+content/shell",
+ "+mojo/core/embedder/embedder.h", # TestGpuServiceHolder needs Mojo.
"+sandbox",
"+ui/gl/gl_switches.h", # Disable Direct Composition Workaround.
"+ui/gl/init/gl_factory.h", # To initialize GL bindings.
diff --git a/chromium/ui/views/examples/animated_image_view_example.cc b/chromium/ui/views/examples/animated_image_view_example.cc
index 98959097b70..dc26fdee841 100644
--- a/chromium/ui/views/examples/animated_image_view_example.cc
+++ b/chromium/ui/views/examples/animated_image_view_example.cc
@@ -47,8 +47,8 @@ class AnimationGallery : public View,
CreateSolidSidedBorder(1, 1, 1, 1, SK_ColorBLACK));
image_view_container_ = AddChildView(std::move(image_view_container));
- BoxLayout* box = SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kVertical, gfx::Insets(10), 10));
+ BoxLayout* box = SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kVertical, gfx::Insets(10), 10));
box->SetFlexForView(image_view_container_, 1);
auto file_chooser = std::make_unique<Textfield>();
@@ -57,7 +57,7 @@ class AnimationGallery : public View,
auto file_container = std::make_unique<View>();
BoxLayout* file_box =
file_container->SetLayoutManager(std::make_unique<BoxLayout>(
- BoxLayout::kHorizontal, gfx::Insets(10), 10));
+ BoxLayout::Orientation::kHorizontal, gfx::Insets(10), 10));
file_chooser_ = file_container->AddChildView(std::move(file_chooser));
file_go_button_ = file_container->AddChildView(
MdTextButton::Create(this, base::ASCIIToUTF16("Render")));
diff --git a/chromium/ui/views/examples/bubble_example.cc b/chromium/ui/views/examples/bubble_example.cc
index a2d94d57a41..644d10592e7 100644
--- a/chromium/ui/views/examples/bubble_example.cc
+++ b/chromium/ui/views/examples/bubble_example.cc
@@ -59,8 +59,8 @@ class ExampleBubble : public BubbleDialogDelegateView {
int GetDialogButtons() const override { return ui::DIALOG_BUTTON_NONE; }
void Init() override {
- SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kVertical, gfx::Insets(50)));
+ SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kVertical, gfx::Insets(50)));
AddChildView(new Label(GetArrowName(arrow())));
}
@@ -75,10 +75,8 @@ BubbleExample::BubbleExample() : ExampleBase("Bubble") {}
BubbleExample::~BubbleExample() = default;
void BubbleExample::CreateExampleView(View* container) {
- PrintStatus("Click with optional modifiers: [Ctrl] for set_arrow(NONE), "
- "[Alt] for set_arrow(FLOAT), or [Shift] to reverse the arrow iteration.");
- container->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(), 10));
+ container->SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kHorizontal, gfx::Insets(), 10));
no_shadow_ = new LabelButton(this, ASCIIToUTF16("No Shadow"));
container->AddChildView(no_shadow_);
no_shadow_opaque_ = new LabelButton(this, ASCIIToUTF16("Opaque Border"));
@@ -123,6 +121,8 @@ void BubbleExample::ButtonPressed(Button* sender, const ui::Event& event) {
BubbleDialogDelegateView::CreateBubble(bubble);
bubble->GetWidget()->Show();
+ PrintStatus("Click with optional modifiers: [Ctrl] for set_arrow(NONE), "
+ "[Alt] for set_arrow(FLOAT), or [Shift] to reverse the arrow iteration.");
}
} // namespace examples
diff --git a/chromium/ui/views/examples/button_example.cc b/chromium/ui/views/examples/button_example.cc
index 993e0efb2de..50197395469 100644
--- a/chromium/ui/views/examples/button_example.cc
+++ b/chromium/ui/views/examples/button_example.cc
@@ -37,8 +37,8 @@ ButtonExample::~ButtonExample() = default;
void ButtonExample::CreateExampleView(View* container) {
container->SetBackground(CreateSolidBackground(SK_ColorWHITE));
- auto layout =
- std::make_unique<BoxLayout>(BoxLayout::kVertical, gfx::Insets(10), 10);
+ auto layout = std::make_unique<BoxLayout>(BoxLayout::Orientation::kVertical,
+ gfx::Insets(10), 10);
layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kCenter);
container->SetLayoutManager(std::move(layout));
diff --git a/chromium/ui/views/examples/button_sticker_sheet.cc b/chromium/ui/views/examples/button_sticker_sheet.cc
index 8e19bd6a74e..38681f7a529 100644
--- a/chromium/ui/views/examples/button_sticker_sheet.cc
+++ b/chromium/ui/views/examples/button_sticker_sheet.cc
@@ -4,6 +4,10 @@
#include "ui/views/examples/button_sticker_sheet.h"
+#include <memory>
+#include <utility>
+
+#include "base/memory/ptr_util.h"
#include "base/strings/utf_string_conversions.h"
#include "ui/views/controls/button/button.h"
#include "ui/views/controls/button/md_text_button.h"
@@ -31,7 +35,7 @@ GridLayout* MakeStretchyGridLayout(View* host, int ncols) {
const int kColumnWidth = 96;
GridLayout* layout =
- host->SetLayoutManager(std::make_unique<views::GridLayout>(host));
+ host->SetLayoutManager(std::make_unique<views::GridLayout>());
ColumnSet* columns = layout->AddColumnSet(kStretchyGridColumnSetId);
for (int i = 0; i < ncols; ++i) {
if (i != 0)
@@ -50,24 +54,24 @@ std::unique_ptr<View> MakePlainLabel(const std::string& text) {
// Add a row containing a label whose text is |label_text| and then all the
// views in |views| to the supplied GridLayout, with padding between rows.
template <typename T>
-void AddLabelledRowToGridLayout(GridLayout* layout,
- const std::string& label_text,
- std::vector<std::unique_ptr<T>> views) {
+void AddLabeledRowToGridLayout(GridLayout* layout,
+ const std::string& label_text,
+ std::vector<std::unique_ptr<T>> views) {
const float kRowDoesNotResizeVertically = 0.0;
const int kPaddingRowHeight = 8;
layout->StartRow(kRowDoesNotResizeVertically, kStretchyGridColumnSetId);
- layout->AddView(MakePlainLabel(label_text).get());
+ layout->AddView(MakePlainLabel(label_text));
for (auto& view : views)
- layout->AddView(view.release());
+ layout->AddView(std::move(view));
// This gets added extraneously after the last row, but it doesn't hurt and
// means there's no need to keep track of whether to add it or not.
layout->AddPaddingRow(kRowDoesNotResizeVertically, kPaddingRowHeight);
}
// Constructs a pair of MdTextButtons in the specified |state| with the
-// specified |listener|, and returns them in |primary| and |secondary|. The
-// button in |primary| is a call-to-action button, and the button in
-// |secondary| is a regular button.
+// specified |listener|, and returns them in |*primary| and |*secondary|. The
+// button in |*primary| is a call-to-action button, and the button in
+// |*secondary| is a regular button.
std::vector<std::unique_ptr<MdTextButton>> MakeButtonsInState(
ButtonListener* listener,
Button::ButtonState state) {
@@ -98,18 +102,18 @@ void ButtonStickerSheet::CreateExampleView(View* container) {
std::vector<std::unique_ptr<View>> plainLabel;
plainLabel.push_back(MakePlainLabel("Primary"));
plainLabel.push_back(MakePlainLabel("Secondary"));
- AddLabelledRowToGridLayout(layout, std::string(), std::move(plainLabel));
-
- AddLabelledRowToGridLayout(layout, "Default",
- MakeButtonsInState(this, Button::STATE_NORMAL));
- AddLabelledRowToGridLayout(layout, "Normal",
- MakeButtonsInState(this, Button::STATE_NORMAL));
- AddLabelledRowToGridLayout(layout, "Hovered",
- MakeButtonsInState(this, Button::STATE_HOVERED));
- AddLabelledRowToGridLayout(layout, "Pressed",
- MakeButtonsInState(this, Button::STATE_PRESSED));
- AddLabelledRowToGridLayout(layout, "Disabled",
- MakeButtonsInState(this, Button::STATE_DISABLED));
+ AddLabeledRowToGridLayout(layout, std::string(), std::move(plainLabel));
+
+ AddLabeledRowToGridLayout(layout, "Default",
+ MakeButtonsInState(this, Button::STATE_NORMAL));
+ AddLabeledRowToGridLayout(layout, "Normal",
+ MakeButtonsInState(this, Button::STATE_NORMAL));
+ AddLabeledRowToGridLayout(layout, "Hovered",
+ MakeButtonsInState(this, Button::STATE_HOVERED));
+ AddLabeledRowToGridLayout(layout, "Pressed",
+ MakeButtonsInState(this, Button::STATE_PRESSED));
+ AddLabeledRowToGridLayout(layout, "Disabled",
+ MakeButtonsInState(this, Button::STATE_DISABLED));
}
void ButtonStickerSheet::ButtonPressed(Button* button, const ui::Event& event) {
diff --git a/chromium/ui/views/examples/combobox_example.cc b/chromium/ui/views/examples/combobox_example.cc
index d8acc7b71c4..32f086700eb 100644
--- a/chromium/ui/views/examples/combobox_example.cc
+++ b/chromium/ui/views/examples/combobox_example.cc
@@ -51,8 +51,8 @@ void ComboboxExample::CreateExampleView(View* container) {
disabled_combobox->SetSelectedIndex(4);
disabled_combobox->SetEnabled(false);
- container->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kVertical, gfx::Insets(10, 0), 5));
+ container->SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kVertical, gfx::Insets(10, 0), 5));
container->AddChildView(combobox_);
container->AddChildView(disabled_combobox);
}
diff --git a/chromium/ui/views/examples/dialog_example.cc b/chromium/ui/views/examples/dialog_example.cc
index 152a8a5e1a1..21e9ab75b0d 100644
--- a/chromium/ui/views/examples/dialog_example.cc
+++ b/chromium/ui/views/examples/dialog_example.cc
@@ -59,14 +59,12 @@ class DialogExample::Delegate : public virtual DialogType {
return parent_->title_->text();
}
- // TODO(crbug.com/961660): CreateExtraView should return std::unique_ptr<View>
- // DialogDelegate:
- View* CreateExtraView() override {
+ std::unique_ptr<View> CreateExtraView() override {
if (!parent_->has_extra_button_->GetChecked())
return nullptr;
auto view = MdTextButton::CreateSecondaryUiButton(
nullptr, parent_->extra_button_label_->text());
- return view.release();
+ return view;
}
bool Cancel() override { return parent_->AllowDialogClose(false); }
@@ -135,8 +133,8 @@ void DialogExample::CreateExampleView(View* container) {
views::LayoutProvider* provider = views::LayoutProvider::Get();
const int horizontal_spacing =
provider->GetDistanceMetric(views::DISTANCE_RELATED_BUTTON_HORIZONTAL);
- GridLayout* layout = container->SetLayoutManager(
- std::make_unique<views::GridLayout>(container));
+ GridLayout* layout =
+ container->SetLayoutManager(std::make_unique<views::GridLayout>());
ColumnSet* column_set = layout->AddColumnSet(kFieldsColumnId);
column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL, kFixed,
GridLayout::USE_PREF, 0, 0);
@@ -160,10 +158,9 @@ void DialogExample::CreateExampleView(View* container) {
AddCheckbox(layout, &has_extra_button_);
StartRowWithLabel(layout, "Modal Type");
- mode_ = new Combobox(&mode_model_);
+ mode_ = layout->AddView(std::make_unique<Combobox>(&mode_model_));
mode_->set_listener(this);
mode_->SetSelectedIndex(ui::MODAL_TYPE_CHILD);
- layout->AddView(mode_);
StartRowWithLabel(layout, "Bubble");
AddCheckbox(layout, &bubble_);
@@ -177,16 +174,8 @@ void DialogExample::CreateExampleView(View* container) {
kFixed, kButtonsColumnId, kFixed,
provider->GetDistanceMetric(views::DISTANCE_UNRELATED_CONTROL_VERTICAL));
- // TODO(crbug.com/943560): Avoid this release().
- show_ =
- MdTextButton::CreateSecondaryUiButton(this, base::ASCIIToUTF16("Show"))
- .release();
- layout->AddView(show_);
-
- // Grow the dialog a bit when this example is first selected, so it all fits.
- gfx::Size dialog_size = container->GetWidget()->GetRestoredBounds().size();
- dialog_size.set_height(dialog_size.height() + 80);
- container->GetWidget()->SetSize(dialog_size);
+ show_ = layout->AddView(
+ MdTextButton::CreateSecondaryUiButton(this, base::ASCIIToUTF16("Show")));
}
void DialogExample::StartRowWithLabel(GridLayout* layout, const char* label) {
@@ -195,7 +184,7 @@ void DialogExample::StartRowWithLabel(GridLayout* layout, const char* label) {
kFixedVerticalResize,
views::LayoutProvider::Get()->GetDistanceMetric(
views::DISTANCE_RELATED_CONTROL_VERTICAL));
- layout->AddView(new Label(base::ASCIIToUTF16(label)));
+ layout->AddView(std::make_unique<Label>(base::ASCIIToUTF16(label)));
}
void DialogExample::StartTextfieldRow(GridLayout* layout,
@@ -203,18 +192,16 @@ void DialogExample::StartTextfieldRow(GridLayout* layout,
const char* label,
const char* value) {
StartRowWithLabel(layout, label);
- Textfield* textfield = new Textfield();
- layout->AddView(textfield);
+ auto textfield = std::make_unique<Textfield>();
textfield->set_controller(this);
textfield->SetText(base::ASCIIToUTF16(value));
- *member = textfield;
+ *member = layout->AddView(std::move(textfield));
}
void DialogExample::AddCheckbox(GridLayout* layout, Checkbox** member) {
- Checkbox* checkbox = new Checkbox(base::string16(), this);
+ auto checkbox = std::make_unique<Checkbox>(base::string16(), this);
checkbox->SetChecked(true);
- layout->AddView(checkbox);
- *member = checkbox;
+ *member = layout->AddView(std::move(checkbox));
}
ui::ModalType DialogExample::GetModalType() const {
@@ -272,10 +259,10 @@ void DialogExample::ButtonPressed(Button* sender, const ui::Event& event) {
// be created as MODAL_TYPE_WINDOW without specifying a parent.
gfx::NativeView parent = nullptr;
if (mode_->GetSelectedIndex() != kFakeModeless)
- parent = container()->GetWidget()->GetNativeView();
+ parent = example_view()->GetWidget()->GetNativeView();
DialogDelegate::CreateDialogWidget(
- dialog, container()->GetWidget()->GetNativeWindow(), parent);
+ dialog, example_view()->GetWidget()->GetNativeWindow(), parent);
}
last_dialog_->GetWidget()->Show();
return;
diff --git a/chromium/ui/views/examples/example_base.cc b/chromium/ui/views/examples/example_base.cc
index bc296aee322..878ac70059a 100644
--- a/chromium/ui/views/examples/example_base.cc
+++ b/chromium/ui/views/examples/example_base.cc
@@ -17,43 +17,10 @@ namespace examples {
// This function can only be called if there is a visible examples window.
void LogStatus(const std::string& status);
-namespace {
-
-// TODO(oshima): Check if this special container is still necessary.
-class ContainerView : public View {
- public:
- explicit ContainerView(ExampleBase* base)
- : example_view_created_(false),
- example_base_(base) {
- }
-
- private:
- // View:
- void ViewHierarchyChanged(
- const ViewHierarchyChangedDetails& details) override {
- View::ViewHierarchyChanged(details);
- // We're not using child == this because a Widget may not be
- // available when this is added to the hierarchy.
- if (details.is_add && GetWidget() && !example_view_created_) {
- example_view_created_ = true;
- example_base_->CreateExampleView(this);
- }
- }
-
- // True if the example view has already been created, or false otherwise.
- bool example_view_created_;
-
- ExampleBase* example_base_;
-
- DISALLOW_COPY_AND_ASSIGN(ContainerView);
-};
-
-} // namespace
-
ExampleBase::~ExampleBase() = default;
ExampleBase::ExampleBase(const char* title) : example_title_(title) {
- container_ = new ContainerView(this);
+ container_ = new View();
}
// Prints a message in the status area, at the bottom of the window.
diff --git a/chromium/ui/views/examples/example_base.h b/chromium/ui/views/examples/example_base.h
index 7a6b33d5766..e582096a50c 100644
--- a/chromium/ui/views/examples/example_base.h
+++ b/chromium/ui/views/examples/example_base.h
@@ -28,8 +28,6 @@ class VIEWS_EXAMPLES_EXPORT ExampleBase {
protected:
explicit ExampleBase(const char* title);
- View* container() { return container_; }
-
// Prints a message in the status area, at the bottom of the window.
void PrintStatus(const char* format, ...);
diff --git a/chromium/ui/views/examples/examples_main.cc b/chromium/ui/views/examples/examples_main.cc
index 00a933899b9..65ba7c824e7 100644
--- a/chromium/ui/views/examples/examples_main.cc
+++ b/chromium/ui/views/examples/examples_main.cc
@@ -20,6 +20,7 @@
#include "components/viz/host/host_frame_sink_manager.h"
#include "components/viz/service/display_embedder/server_shared_bitmap_manager.h"
#include "components/viz/service/frame_sinks/frame_sink_manager_impl.h"
+#include "mojo/core/embedder/embedder.h"
#include "ui/base/ime/init/input_method_initializer.h"
#include "ui/base/material_design/material_design_controller.h"
#include "ui/base/resource/resource_bundle.h"
@@ -55,7 +56,7 @@ base::LazyInstance<base::TestDiscardableMemoryAllocator>::DestructorAtExit
int main(int argc, char** argv) {
#if defined(OS_WIN)
- ui::ScopedOleInitializer ole_initializer_;
+ ui::ScopedOleInitializer ole_initializer;
#endif
base::CommandLine::Init(argc, argv);
@@ -68,6 +69,8 @@ int main(int argc, char** argv) {
base::AtExitManager at_exit;
+ mojo::core::Init();
+
#if defined(USE_X11)
// This demo uses InProcessContextFactory which uses X on a separate Gpu
// thread.
@@ -104,8 +107,8 @@ int main(int argc, char** argv) {
base::DiscardableMemoryAllocator::SetInstance(
g_discardable_memory_allocator.Pointer());
- base::PowerMonitor power_monitor(
- base::WrapUnique(new base::PowerMonitorDeviceSource));
+ base::PowerMonitor::Initialize(
+ std::make_unique<base::PowerMonitorDeviceSource>());
#if defined(OS_WIN)
gfx::win::InitializeDirectWrite();
diff --git a/chromium/ui/views/examples/examples_window.cc b/chromium/ui/views/examples/examples_window.cc
index d95d1431b13..2de2b7249ab 100644
--- a/chromium/ui/views/examples/examples_window.cc
+++ b/chromium/ui/views/examples/examples_window.cc
@@ -90,6 +90,9 @@ ExampleVector CreateExamples() {
examples.push_back(std::make_unique<TreeViewExample>());
examples.push_back(std::make_unique<VectorExample>());
examples.push_back(std::make_unique<WidgetExample>());
+
+ for (auto& example : examples)
+ example->CreateExampleView(example->example_view());
return examples;
}
@@ -139,20 +142,19 @@ class ExamplesWindowContents : public WidgetDelegateView,
public ComboboxListener {
public:
ExamplesWindowContents(base::OnceClosure on_close, ExampleVector examples)
- : example_shown_(new View),
- status_label_(new Label),
- on_close_(std::move(on_close)) {
+ : on_close_(std::move(on_close)) {
auto combobox_model = std::make_unique<ComboboxModelExampleList>();
combobox_model_ = combobox_model.get();
combobox_model_->SetExamples(std::move(examples));
- combobox_ = new Combobox(std::move(combobox_model));
+ auto combobox = std::make_unique<Combobox>(std::move(combobox_model));
instance_ = this;
- combobox_->set_listener(this);
+ combobox->set_listener(this);
- SetBackground(CreateStandardPanelBackground());
+ SetBackground(CreateThemedSolidBackground(
+ this, ui::NativeTheme::kColorId_DialogBackground));
GridLayout* layout =
- SetLayoutManager(std::make_unique<views::GridLayout>(this));
+ SetLayoutManager(std::make_unique<views::GridLayout>());
ColumnSet* column_set = layout->AddColumnSet(0);
column_set->AddPaddingColumn(0, 5);
column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
@@ -160,17 +162,18 @@ class ExamplesWindowContents : public WidgetDelegateView,
column_set->AddPaddingColumn(0, 5);
layout->AddPaddingRow(0, 5);
layout->StartRow(0 /* no expand */, 0);
- layout->AddView(combobox_);
+ combobox_ = layout->AddView(std::move(combobox));
if (combobox_model_->GetItemCount() > 0) {
layout->StartRow(1, 0);
- example_shown_->SetLayoutManager(std::make_unique<FillLayout>());
- example_shown_->AddChildView(combobox_model_->GetItemViewAt(0));
- layout->AddView(example_shown_);
+ auto example_shown = std::make_unique<View>();
+ example_shown->SetLayoutManager(std::make_unique<FillLayout>());
+ example_shown->AddChildView(combobox_model_->GetItemViewAt(0));
+ example_shown_ = layout->AddView(std::move(example_shown));
}
layout->StartRow(0 /* no expand */, 0);
- layout->AddView(status_label_);
+ status_label_ = layout->AddView(std::make_unique<Label>());
layout->AddPaddingRow(0, 5);
}
@@ -197,24 +200,30 @@ class ExamplesWindowContents : public WidgetDelegateView,
std::move(on_close_).Run();
}
gfx::Size CalculatePreferredSize() const override {
- return gfx::Size(800, 300);
+ gfx::Size size(800, 300);
+ for (int i = 0; i < combobox_model_->GetItemCount(); i++) {
+ size.set_height(
+ std::max(size.height(),
+ combobox_model_->GetItemViewAt(i)->GetHeightForWidth(800)));
+ }
+ return size;
}
// ComboboxListener:
void OnPerformAction(Combobox* combobox) override {
DCHECK_EQ(combobox, combobox_);
- DCHECK(combobox->GetSelectedIndex());
+ int index = combobox->GetSelectedIndex();
+ DCHECK_LT(index, combobox_model_->GetItemCount());
example_shown_->RemoveAllChildViews(false);
- example_shown_->AddChildView(
- combobox_model_->GetItemViewAt(combobox->GetSelectedIndex()));
+ example_shown_->AddChildView(combobox_model_->GetItemViewAt(index));
example_shown_->RequestFocus();
SetStatus(std::string());
InvalidateLayout();
}
static ExamplesWindowContents* instance_;
- View* example_shown_;
- Label* status_label_;
+ View* example_shown_ = nullptr;
+ Label* status_label_ = nullptr;
base::OnceClosure on_close_;
Combobox* combobox_ = nullptr;
// Owned by |combobox_|.
@@ -244,7 +253,8 @@ void ShowExamplesWindow(base::OnceClosure on_close,
}
void LogStatus(const std::string& string) {
- ExamplesWindowContents::instance()->SetStatus(string);
+ if (ExamplesWindowContents::instance())
+ ExamplesWindowContents::instance()->SetStatus(string);
}
} // namespace examples
diff --git a/chromium/ui/views/examples/flex_layout_example.cc b/chromium/ui/views/examples/flex_layout_example.cc
index 0983e30622e..7027dc172b5 100644
--- a/chromium/ui/views/examples/flex_layout_example.cc
+++ b/chromium/ui/views/examples/flex_layout_example.cc
@@ -23,6 +23,7 @@
#include "ui/views/examples/example_combobox_model.h"
#include "ui/views/layout/fill_layout.h"
#include "ui/views/view.h"
+#include "ui/views/view_class_properties.h"
namespace views {
namespace examples {
@@ -81,8 +82,8 @@ void FlexLayoutExample::ContentsChanged(Textfield* sender,
const base::string16& new_contents) {
layout_->SetInteriorMargin(
LayoutExampleBase::TextfieldsToInsets(interior_margin_));
- layout_->SetDefaultChildMargins(
- LayoutExampleBase::TextfieldsToInsets(default_child_margins_));
+ layout_->SetDefault(views::kMarginsKey, LayoutExampleBase::TextfieldsToInsets(
+ default_child_margins_));
RefreshLayoutPanel(false);
}
@@ -97,9 +98,9 @@ void FlexLayoutExample::UpdateLayoutManager() {
ChildPanel* panel = static_cast<ChildPanel*>(child);
int flex = panel->GetFlex();
if (flex < 0)
- layout_->ClearFlexForView(panel);
+ panel->ClearProperty(views::kFlexBehaviorKey);
else
- layout_->SetFlexForView(panel, GetFlexSpecification(flex));
+ panel->SetProperty(views::kFlexBehaviorKey, GetFlexSpecification(flex));
}
}
diff --git a/chromium/ui/views/examples/label_example.cc b/chromium/ui/views/examples/label_example.cc
index 82a9bd87301..c8d8ceb070a 100644
--- a/chromium/ui/views/examples/label_example.cc
+++ b/chromium/ui/views/examples/label_example.cc
@@ -62,60 +62,62 @@ LabelExample::~LabelExample() = default;
void LabelExample::CreateExampleView(View* container) {
// A very simple label example, followed by additional helpful examples.
- container->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kVertical, gfx::Insets(), 10));
- Label* label = new Label(ASCIIToUTF16("Hello world!"));
- container->AddChildView(label);
+ container->SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kVertical, gfx::Insets(), 10));
+ container->AddChildView(
+ std::make_unique<Label>(ASCIIToUTF16("Hello world!")));
const wchar_t hello_world_hebrew[] =
L"\x5e9\x5dc\x5d5\x5dd \x5d4\x5e2\x5d5\x5dc\x5dd!";
- label = new Label(WideToUTF16(hello_world_hebrew));
+ auto label = std::make_unique<Label>(WideToUTF16(hello_world_hebrew));
label->SetHorizontalAlignment(gfx::ALIGN_RIGHT);
- container->AddChildView(label);
+ container->AddChildView(std::move(label));
- label = new Label(WideToUTF16(L"A UTF16 surrogate pair: \x5d0\x5b0"));
+ label = std::make_unique<Label>(
+ WideToUTF16(L"A UTF16 surrogate pair: \x5d0\x5b0"));
label->SetHorizontalAlignment(gfx::ALIGN_RIGHT);
- container->AddChildView(label);
+ container->AddChildView(std::move(label));
- label = new Label(ASCIIToUTF16("A left-aligned blue label."));
+ label = std::make_unique<Label>(ASCIIToUTF16("A left-aligned blue label."));
label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
label->SetEnabledColor(SK_ColorBLUE);
- container->AddChildView(label);
+ container->AddChildView(std::move(label));
- label = new Label(WideToUTF16(L"Password!"));
+ label = std::make_unique<Label>(WideToUTF16(L"Password!"));
label->SetObscured(true);
- container->AddChildView(label);
+ container->AddChildView(std::move(label));
- label = new Label(ASCIIToUTF16("A Courier-18 label with shadows."));
+ label =
+ std::make_unique<Label>(ASCIIToUTF16("A Courier-18 label with shadows."));
label->SetFontList(gfx::FontList("Courier, 18px"));
gfx::ShadowValues shadows(1,
gfx::ShadowValue(gfx::Vector2d(), 1, SK_ColorRED));
constexpr gfx::ShadowValue shadow(gfx::Vector2d(2, 2), 0, SK_ColorGRAY);
shadows.push_back(shadow);
label->SetShadows(shadows);
- container->AddChildView(label);
+ container->AddChildView(std::move(label));
- label = new ExamplePreferredSizeLabel();
+ label = std::make_unique<ExamplePreferredSizeLabel>();
label->SetText(ASCIIToUTF16("A long label will elide toward its logical end "
"if the text's width exceeds the label's available width."));
- container->AddChildView(label);
+ container->AddChildView(std::move(label));
- label = new ExamplePreferredSizeLabel();
+ label = std::make_unique<ExamplePreferredSizeLabel>();
label->SetText(ASCIIToUTF16("A multi-line label will wrap onto subsequent "
"lines if the text's width exceeds the label's available width, which is "
"helpful for extemely long text used to demonstrate line wrapping."));
label->SetMultiLine(true);
- container->AddChildView(label);
+ container->AddChildView(std::move(label));
- label = new Label(ASCIIToUTF16("Label with thick border"));
+ label = std::make_unique<Label>(ASCIIToUTF16("Label with thick border"));
label->SetBorder(CreateSolidBorder(20, SK_ColorRED));
- container->AddChildView(label);
+ container->AddChildView(std::move(label));
- label = new Label(
+ label = std::make_unique<Label>(
ASCIIToUTF16("A multiline label...\n\n...which supports text selection"));
label->SetSelectable(true);
label->SetMultiLine(true);
- container->AddChildView(label);
+ container->AddChildView(std::move(label));
AddCustomLabel(container);
}
@@ -154,11 +156,11 @@ void LabelExample::ContentsChanged(Textfield* sender,
}
void LabelExample::AddCustomLabel(View* container) {
- View* control_container = new View();
+ std::unique_ptr<View> control_container = std::make_unique<View>();
control_container->SetBorder(CreateSolidBorder(2, SK_ColorGRAY));
control_container->SetBackground(CreateSolidBackground(SK_ColorLTGRAY));
GridLayout* layout = control_container->SetLayoutManager(
- std::make_unique<views::GridLayout>(control_container));
+ std::make_unique<views::GridLayout>());
ColumnSet* column_set = layout->AddColumnSet(0);
column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL,
@@ -167,13 +169,14 @@ void LabelExample::AddCustomLabel(View* container) {
1.0f, GridLayout::USE_PREF, 0, 0);
layout->StartRow(0, 0);
- layout->AddView(new Label(ASCIIToUTF16("Content: ")));
- textfield_ = new Textfield();
- textfield_->SetText(ASCIIToUTF16("Use the provided controls to configure the "
- "content and presentation of this custom label."));
- textfield_->SetEditableSelectionRange(gfx::Range());
- textfield_->set_controller(this);
- layout->AddView(textfield_);
+ layout->AddView(std::make_unique<Label>(ASCIIToUTF16("Content: ")));
+ auto textfield = std::make_unique<Textfield>();
+ textfield->SetText(
+ ASCIIToUTF16("Use the provided controls to configure the "
+ "content and presentation of this custom label."));
+ textfield->SetEditableSelectionRange(gfx::Range());
+ textfield->set_controller(this);
+ textfield_ = layout->AddView(std::move(textfield));
alignment_ =
AddCombobox(layout, "Alignment: ", kAlignments, base::size(kAlignments));
@@ -189,29 +192,29 @@ void LabelExample::AddCustomLabel(View* container) {
column_set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 0,
GridLayout::USE_PREF, 0, 0);
layout->StartRow(0, 1);
- multiline_ = new Checkbox(base::ASCIIToUTF16("Multiline"), this);
- layout->AddView(multiline_);
- shadows_ = new Checkbox(base::ASCIIToUTF16("Shadows"), this);
- layout->AddView(shadows_);
- selectable_ = new Checkbox(base::ASCIIToUTF16("Selectable"), this);
- layout->AddView(selectable_);
+ multiline_ = layout->AddView(
+ std::make_unique<Checkbox>(base::ASCIIToUTF16("Multiline"), this));
+ shadows_ = layout->AddView(
+ std::make_unique<Checkbox>(base::ASCIIToUTF16("Shadows"), this));
+ selectable_ = layout->AddView(
+ std::make_unique<Checkbox>(base::ASCIIToUTF16("Selectable"), this));
layout->AddPaddingRow(0, 8);
column_set = layout->AddColumnSet(2);
column_set->AddColumn(GridLayout::FILL, GridLayout::FILL,
1, GridLayout::USE_PREF, 0, 0);
layout->StartRow(0, 2);
- custom_label_ = new ExamplePreferredSizeLabel();
- custom_label_->SetHorizontalAlignment(gfx::ALIGN_LEFT);
- custom_label_->SetElideBehavior(gfx::NO_ELIDE);
- custom_label_->SetText(textfield_->text());
- layout->AddView(custom_label_);
+ auto custom_label = std::make_unique<ExamplePreferredSizeLabel>();
+ custom_label->SetHorizontalAlignment(gfx::ALIGN_LEFT);
+ custom_label->SetElideBehavior(gfx::NO_ELIDE);
+ custom_label->SetText(textfield_->text());
+ custom_label_ = layout->AddView(std::move(custom_label));
// Disable the text selection checkbox if |custom_label_| does not support
// text selection.
selectable_->SetEnabled(custom_label_->IsSelectionSupported());
- container->AddChildView(control_container);
+ container->AddChildView(std::move(control_container));
}
Combobox* LabelExample::AddCombobox(GridLayout* layout,
@@ -219,13 +222,12 @@ Combobox* LabelExample::AddCombobox(GridLayout* layout,
const char** strings,
int count) {
layout->StartRow(0, 0);
- layout->AddView(new Label(base::ASCIIToUTF16(name)));
- Combobox* combobox =
- new Combobox(std::make_unique<ExampleComboboxModel>(strings, count));
+ layout->AddView(std::make_unique<Label>(base::ASCIIToUTF16(name)));
+ auto combobox = std::make_unique<Combobox>(
+ std::make_unique<ExampleComboboxModel>(strings, count));
combobox->SetSelectedIndex(0);
combobox->set_listener(this);
- layout->AddView(combobox);
- return combobox;
+ return layout->AddView(std::move(combobox));
}
} // namespace examples
diff --git a/chromium/ui/views/examples/layout_example_base.cc b/chromium/ui/views/examples/layout_example_base.cc
index c763feaa3c9..fe07c1ddd17 100644
--- a/chromium/ui/views/examples/layout_example_base.cc
+++ b/chromium/ui/views/examples/layout_example_base.cc
@@ -145,7 +145,7 @@ void LayoutExampleBase::ChildPanel::ContentsChanged(
const base::string16& new_contents) {
const gfx::Insets margins = LayoutExampleBase::TextfieldsToInsets(margin_);
if (!margins.IsEmpty())
- this->SetProperty(kMarginsKey, new gfx::Insets(margins));
+ this->SetProperty(kMarginsKey, margins);
else
this->ClearProperty(kMarginsKey);
example_->RefreshLayoutPanel(sender == flex_);
diff --git a/chromium/ui/views/examples/message_box_example.cc b/chromium/ui/views/examples/message_box_example.cc
index d1837ff5d65..67ff6dc0c78 100644
--- a/chromium/ui/views/examples/message_box_example.cc
+++ b/chromium/ui/views/examples/message_box_example.cc
@@ -4,6 +4,9 @@
#include "ui/views/examples/message_box_example.h"
+#include <memory>
+#include <utility>
+
#include "base/strings/utf_string_conversions.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/message_box_view.h"
@@ -21,22 +24,19 @@ MessageBoxExample::MessageBoxExample() : ExampleBase("Message Box View") {
MessageBoxExample::~MessageBoxExample() = default;
void MessageBoxExample::CreateExampleView(View* container) {
- message_box_view_ = new MessageBoxView(
- MessageBoxView::InitParams(ASCIIToUTF16("Hello, world!")));
- status_ = new LabelButton(this, ASCIIToUTF16("Show Status"));
- toggle_ = new LabelButton(this, ASCIIToUTF16("Toggle Checkbox"));
+ GridLayout* layout =
+ container->SetLayoutManager(std::make_unique<views::GridLayout>());
- GridLayout* layout = container->SetLayoutManager(
- std::make_unique<views::GridLayout>(container));
-
- message_box_view_->SetCheckBoxLabel(ASCIIToUTF16("Check Box"));
+ auto message_box_view = std::make_unique<MessageBoxView>(
+ MessageBoxView::InitParams(ASCIIToUTF16("Hello, world!")));
+ message_box_view->SetCheckBoxLabel(ASCIIToUTF16("Check Box"));
const int message_box_column = 0;
ColumnSet* column_set = layout->AddColumnSet(message_box_column);
column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
GridLayout::USE_PREF, 0, 0);
layout->StartRow(1 /* expand */, message_box_column);
- layout->AddView(message_box_view_);
+ message_box_view_ = layout->AddView(std::move(message_box_view));
const int button_column = 1;
column_set = layout->AddColumnSet(button_column);
@@ -47,8 +47,10 @@ void MessageBoxExample::CreateExampleView(View* container) {
layout->StartRow(0 /* no expand */, button_column);
- layout->AddView(status_);
- layout->AddView(toggle_);
+ status_ = layout->AddView(
+ std::make_unique<LabelButton>(this, ASCIIToUTF16("Show Status")));
+ toggle_ = layout->AddView(
+ std::make_unique<LabelButton>(this, ASCIIToUTF16("Toggle Checkbox")));
}
void MessageBoxExample::ButtonPressed(Button* sender, const ui::Event& event) {
diff --git a/chromium/ui/views/examples/multiline_example.cc b/chromium/ui/views/examples/multiline_example.cc
index 7533fb2e5f6..9a481821475 100644
--- a/chromium/ui/views/examples/multiline_example.cc
+++ b/chromium/ui/views/examples/multiline_example.cc
@@ -130,28 +130,30 @@ void MultilineExample::CreateExampleView(View* container) {
L"\x627\x644\x631\x626\x64A\x633\x64A\x629"
L"asdfgh");
- render_text_view_ = new RenderTextView();
- render_text_view_->SetText(kTestString);
+ auto render_text_view = std::make_unique<RenderTextView>();
+ render_text_view->SetText(kTestString);
- label_ = new PreferredSizeLabel();
- label_->SetText(kTestString);
- label_->SetMultiLine(true);
- label_->SetBorder(CreateSolidBorder(2, SK_ColorCYAN));
+ auto label = std::make_unique<PreferredSizeLabel>();
+ label->SetText(kTestString);
+ label->SetMultiLine(true);
+ label->SetBorder(CreateSolidBorder(2, SK_ColorCYAN));
- label_checkbox_ = new Checkbox(ASCIIToUTF16("views::Label:"), this);
- label_checkbox_->SetChecked(true);
- label_checkbox_->set_request_focus_on_press(false);
+ auto label_checkbox =
+ std::make_unique<Checkbox>(ASCIIToUTF16("views::Label:"), this);
+ label_checkbox->SetChecked(true);
+ label_checkbox->set_request_focus_on_press(false);
- elision_checkbox_ = new Checkbox(ASCIIToUTF16("elide text?"), this);
- elision_checkbox_->SetChecked(false);
- elision_checkbox_->set_request_focus_on_press(false);
+ auto elision_checkbox =
+ std::make_unique<Checkbox>(ASCIIToUTF16("elide text?"), this);
+ elision_checkbox->SetChecked(false);
+ elision_checkbox->set_request_focus_on_press(false);
- textfield_ = new Textfield();
- textfield_->set_controller(this);
- textfield_->SetText(kTestString);
+ auto textfield = std::make_unique<Textfield>();
+ textfield->set_controller(this);
+ textfield->SetText(kTestString);
- GridLayout* layout = container->SetLayoutManager(
- std::make_unique<views::GridLayout>(container));
+ GridLayout* layout =
+ container->SetLayoutManager(std::make_unique<views::GridLayout>());
ColumnSet* column_set = layout->AddColumnSet(0);
column_set->AddColumn(GridLayout::LEADING, GridLayout::CENTER,
@@ -160,19 +162,19 @@ void MultilineExample::CreateExampleView(View* container) {
1.0f, GridLayout::FIXED, 0, 0);
layout->StartRow(0, 0);
- layout->AddView(new Label(ASCIIToUTF16("gfx::RenderText:")));
- layout->AddView(render_text_view_);
+ layout->AddView(std::make_unique<Label>(ASCIIToUTF16("gfx::RenderText:")));
+ render_text_view_ = layout->AddView(std::move(render_text_view));
layout->StartRow(0, 0);
- layout->AddView(label_checkbox_);
- layout->AddView(label_);
+ label_checkbox_ = layout->AddView(std::move(label_checkbox));
+ label_ = layout->AddView(std::move(label));
layout->StartRow(0, 0);
- layout->AddView(elision_checkbox_);
+ elision_checkbox_ = layout->AddView(std::move(elision_checkbox));
layout->StartRow(0, 0);
- layout->AddView(new Label(ASCIIToUTF16("Sample Text:")));
- layout->AddView(textfield_);
+ layout->AddView(std::make_unique<Label>(ASCIIToUTF16("Sample Text:")));
+ textfield_ = layout->AddView(std::move(textfield));
}
void MultilineExample::ContentsChanged(Textfield* sender,
@@ -180,8 +182,8 @@ void MultilineExample::ContentsChanged(Textfield* sender,
render_text_view_->SetText(new_contents);
if (label_checkbox_->GetChecked())
label_->SetText(new_contents);
- container()->InvalidateLayout();
- container()->SchedulePaint();
+ example_view()->InvalidateLayout();
+ example_view()->SchedulePaint();
}
void MultilineExample::ButtonPressed(Button* sender, const ui::Event& event) {
@@ -191,8 +193,8 @@ void MultilineExample::ButtonPressed(Button* sender, const ui::Event& event) {
} else if (sender == elision_checkbox_) {
render_text_view_->SetMaxLines(elision_checkbox_->GetChecked() ? 3 : 0);
}
- container()->InvalidateLayout();
- container()->SchedulePaint();
+ example_view()->InvalidateLayout();
+ example_view()->SchedulePaint();
}
} // namespace examples
diff --git a/chromium/ui/views/examples/native_theme_example.cc b/chromium/ui/views/examples/native_theme_example.cc
index c5d1fbb191e..680988f6cc9 100644
--- a/chromium/ui/views/examples/native_theme_example.cc
+++ b/chromium/ui/views/examples/native_theme_example.cc
@@ -56,16 +56,15 @@ void InsertColorRow(GridLayout* layout,
color_view->SetSelectable(true);
layout->StartRow(GridLayout::kFixedSize, 0);
- layout->AddView(label_view.release());
- layout->AddView(color_view.release());
+ layout->AddView(std::move(label_view));
+ layout->AddView(std::move(color_view));
}
// Returns a view of two columns where the first contains the identifier names
// of ui::NativeTheme::ColorId and the second contains the color.
std::unique_ptr<View> CreateAllColorsView() {
auto container = std::make_unique<View>();
- auto* layout = container->SetLayoutManager(
- std::make_unique<GridLayout>(container.get()));
+ auto* layout = container->SetLayoutManager(std::make_unique<GridLayout>());
auto* column_set = layout->AddColumnSet(0);
column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1.0,
GridLayout::USE_PREF, 0, 0);
@@ -157,12 +156,6 @@ std::unique_ptr<View> CreateAllColorsView() {
InsertColorRow(layout, COLOR_LABEL_ARGS(kColorId_TableHeaderText));
InsertColorRow(layout, COLOR_LABEL_ARGS(kColorId_TableHeaderBackground));
InsertColorRow(layout, COLOR_LABEL_ARGS(kColorId_TableHeaderSeparator));
- InsertColorRow(layout,
- COLOR_LABEL_ARGS(kColorId_ResultsTableNormalBackground));
- InsertColorRow(layout,
- COLOR_LABEL_ARGS(kColorId_ResultsTableHoveredBackground));
- InsertColorRow(layout, COLOR_LABEL_ARGS(kColorId_ResultsTableNormalText));
- InsertColorRow(layout, COLOR_LABEL_ARGS(kColorId_ResultsTableDimmedText));
InsertColorRow(layout, COLOR_LABEL_ARGS(kColorId_ThrobberSpinningColor));
InsertColorRow(layout, COLOR_LABEL_ARGS(kColorId_ThrobberWaitingColor));
InsertColorRow(layout, COLOR_LABEL_ARGS(kColorId_ThrobberLightColor));
diff --git a/chromium/ui/views/examples/progress_bar_example.cc b/chromium/ui/views/examples/progress_bar_example.cc
index 1f640e28c9a..4a1039335bb 100644
--- a/chromium/ui/views/examples/progress_bar_example.cc
+++ b/chromium/ui/views/examples/progress_bar_example.cc
@@ -30,8 +30,8 @@ ProgressBarExample::ProgressBarExample() : ExampleBase("Progress Bar") {}
ProgressBarExample::~ProgressBarExample() = default;
void ProgressBarExample::CreateExampleView(View* container) {
- GridLayout* layout = container->SetLayoutManager(
- std::make_unique<views::GridLayout>(container));
+ GridLayout* layout =
+ container->SetLayoutManager(std::make_unique<views::GridLayout>());
ColumnSet* column_set = layout->AddColumnSet(0);
column_set->AddColumn(GridLayout::TRAILING, GridLayout::CENTER, 0,
@@ -44,24 +44,25 @@ void ProgressBarExample::CreateExampleView(View* container) {
GridLayout::USE_PREF, 0, 0);
layout->StartRow(0, 0);
- minus_button_ = MdTextButton::Create(this, base::ASCIIToUTF16("-")).release();
- layout->AddView(minus_button_);
- progress_bar_ = new ProgressBar();
- layout->AddView(progress_bar_);
- plus_button_ = MdTextButton::Create(this, base::ASCIIToUTF16("+")).release();
- layout->AddView(plus_button_);
+ minus_button_ =
+ layout->AddView(MdTextButton::Create(this, base::ASCIIToUTF16("-")));
+ progress_bar_ = layout->AddView(std::make_unique<ProgressBar>());
+ plus_button_ =
+ layout->AddView(MdTextButton::Create(this, base::ASCIIToUTF16("+")));
+
layout->StartRowWithPadding(0, 0, 0, 10);
- layout->AddView(new Label(base::ASCIIToUTF16("Infinite loader:")));
- ProgressBar* infinite_bar = new ProgressBar();
+ layout->AddView(
+ std::make_unique<Label>(base::ASCIIToUTF16("Infinite loader:")));
+ auto infinite_bar = std::make_unique<ProgressBar>();
infinite_bar->SetValue(-1);
- layout->AddView(infinite_bar);
+ layout->AddView(std::move(infinite_bar));
layout->StartRowWithPadding(0, 0, 0, 10);
- layout->AddView(
- new Label(base::ASCIIToUTF16("Infinite loader (very short):")));
- ProgressBar* shorter_bar = new ProgressBar(2);
+ layout->AddView(std::make_unique<Label>(
+ base::ASCIIToUTF16("Infinite loader (very short):")));
+ auto shorter_bar = std::make_unique<ProgressBar>(2);
shorter_bar->SetValue(-1);
- layout->AddView(shorter_bar);
+ layout->AddView(std::move(shorter_bar));
}
void ProgressBarExample::ButtonPressed(Button* sender, const ui::Event& event) {
diff --git a/chromium/ui/views/examples/radio_button_example.cc b/chromium/ui/views/examples/radio_button_example.cc
index d1e25bebf30..0bbcc618efa 100644
--- a/chromium/ui/views/examples/radio_button_example.cc
+++ b/chromium/ui/views/examples/radio_button_example.cc
@@ -30,26 +30,26 @@ RadioButtonExample::RadioButtonExample() : ExampleBase("Radio Button") {}
RadioButtonExample::~RadioButtonExample() = default;
void RadioButtonExample::CreateExampleView(View* container) {
- GridLayout* layout = container->SetLayoutManager(
- std::make_unique<views::GridLayout>(container));
+ GridLayout* layout =
+ container->SetLayoutManager(std::make_unique<views::GridLayout>());
ColumnSet* column_set = layout->AddColumnSet(0);
column_set->AddColumn(GridLayout::FILL, GridLayout::FILL,
1.0f, GridLayout::USE_PREF, 0, 0);
-
+ const int group = 1;
for (size_t i = 0; i < 3; ++i) {
layout->StartRow(0, 0);
- radio_buttons_.push_back(new RadioButton(
- base::ASCIIToUTF16("Radio ") + base::NumberToString16(i), 1));
- layout->AddView(radio_buttons_.back());
+ radio_buttons_.push_back(layout->AddView(std::make_unique<RadioButton>(
+ base::UTF8ToUTF16(base::StringPrintf("Radio %d in group %d",
+ static_cast<int>(i) + 1, group)),
+ group)));
}
layout->StartRow(0, 0);
- select_ = new LabelButton(this, base::ASCIIToUTF16("Select"));
- layout->AddView(select_);
-
+ select_ = layout->AddView(
+ std::make_unique<LabelButton>(this, base::ASCIIToUTF16("Select")));
layout->StartRow(0, 0);
- status_ = new LabelButton(this, base::ASCIIToUTF16("Show Status"));
- layout->AddView(status_);
+ status_ = layout->AddView(
+ std::make_unique<LabelButton>(this, base::ASCIIToUTF16("Show Status")));
}
void RadioButtonExample::ButtonPressed(Button* sender, const ui::Event& event) {
diff --git a/chromium/ui/views/examples/scroll_view_example.cc b/chromium/ui/views/examples/scroll_view_example.cc
index a5d6c18a680..543f34d7550 100644
--- a/chromium/ui/views/examples/scroll_view_example.cc
+++ b/chromium/ui/views/examples/scroll_view_example.cc
@@ -75,25 +75,20 @@ ScrollViewExample::ScrollViewExample() : ExampleBase("Scroll View") {
ScrollViewExample::~ScrollViewExample() = default;
void ScrollViewExample::CreateExampleView(View* container) {
- wide_ = new LabelButton(this, ASCIIToUTF16("Wide"));
- tall_ = new LabelButton(this, ASCIIToUTF16("Tall"));
- big_square_ = new LabelButton(this, ASCIIToUTF16("Big Square"));
- small_square_ = new LabelButton(this, ASCIIToUTF16("Small Square"));
- scroll_to_ = new LabelButton(this, ASCIIToUTF16("Scroll to"));
- scroll_view_ = new ScrollView();
- scrollable_ = scroll_view_->SetContents(std::make_unique<ScrollableView>());
+ auto scroll_view = std::make_unique<ScrollView>();
+ scrollable_ = scroll_view->SetContents(std::make_unique<ScrollableView>());
scrollable_->SetBounds(0, 0, 1000, 100);
scrollable_->SetColor(SK_ColorYELLOW, SK_ColorCYAN);
- GridLayout* layout = container->SetLayoutManager(
- std::make_unique<views::GridLayout>(container));
+ GridLayout* layout =
+ container->SetLayoutManager(std::make_unique<views::GridLayout>());
// Add scroll view.
ColumnSet* column_set = layout->AddColumnSet(0);
column_set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1,
GridLayout::USE_PREF, 0, 0);
layout->StartRow(1, 0);
- layout->AddView(scroll_view_);
+ scroll_view_ = layout->AddView(std::move(scroll_view));
// Add control buttons.
column_set = layout->AddColumnSet(1);
@@ -102,11 +97,16 @@ void ScrollViewExample::CreateExampleView(View* container) {
GridLayout::USE_PREF, 0, 0);
}
layout->StartRow(0, 1);
- layout->AddView(wide_);
- layout->AddView(tall_);
- layout->AddView(big_square_);
- layout->AddView(small_square_);
- layout->AddView(scroll_to_);
+ wide_ = layout->AddView(
+ std::make_unique<LabelButton>(this, ASCIIToUTF16("Wide")));
+ tall_ = layout->AddView(
+ std::make_unique<LabelButton>(this, ASCIIToUTF16("Tall")));
+ big_square_ = layout->AddView(
+ std::make_unique<LabelButton>(this, ASCIIToUTF16("Big Square")));
+ small_square_ = layout->AddView(
+ std::make_unique<LabelButton>(this, ASCIIToUTF16("Small Square")));
+ scroll_to_ = layout->AddView(
+ std::make_unique<LabelButton>(this, ASCIIToUTF16("Scroll to")));
}
void ScrollViewExample::ButtonPressed(Button* sender, const ui::Event& event) {
diff --git a/chromium/ui/views/examples/slider_example.cc b/chromium/ui/views/examples/slider_example.cc
index edc6f843a01..a3e1ce7ec5c 100644
--- a/chromium/ui/views/examples/slider_example.cc
+++ b/chromium/ui/views/examples/slider_example.cc
@@ -25,8 +25,8 @@ void SliderExample::CreateExampleView(View* container) {
slider_->SetValue(0.5);
- container->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(3), 3));
+ container->SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kHorizontal, gfx::Insets(3), 3));
container->AddChildView(slider_);
container->AddChildView(label_);
}
diff --git a/chromium/ui/views/examples/tabbed_pane_example.cc b/chromium/ui/views/examples/tabbed_pane_example.cc
index c4b0f6cc6f3..b534d663862 100644
--- a/chromium/ui/views/examples/tabbed_pane_example.cc
+++ b/chromium/ui/views/examples/tabbed_pane_example.cc
@@ -20,21 +20,22 @@ TabbedPaneExample::TabbedPaneExample() : ExampleBase("Tabbed Pane") {
TabbedPaneExample::~TabbedPaneExample() = default;
void TabbedPaneExample::CreateExampleView(View* container) {
- tabbed_pane_ = new TabbedPane();
- tabbed_pane_->set_listener(this);
- add_ = new LabelButton(this, ASCIIToUTF16("Add"));
- add_at_ = new LabelButton(this, ASCIIToUTF16("Add At 1"));
- select_at_ = new LabelButton(this, ASCIIToUTF16("Select At 1"));
+ auto tabbed_pane = std::make_unique<TabbedPane>();
+ tabbed_pane->set_listener(this);
+ auto add = std::make_unique<LabelButton>(this, ASCIIToUTF16("Add"));
+ auto add_at = std::make_unique<LabelButton>(this, ASCIIToUTF16("Add At 1"));
+ auto select_at =
+ std::make_unique<LabelButton>(this, ASCIIToUTF16("Select At 1"));
- GridLayout* layout = container->SetLayoutManager(
- std::make_unique<views::GridLayout>(container));
+ GridLayout* layout =
+ container->SetLayoutManager(std::make_unique<views::GridLayout>());
const int tabbed_pane_column = 0;
ColumnSet* column_set = layout->AddColumnSet(tabbed_pane_column);
column_set->AddColumn(GridLayout::FILL, GridLayout::FILL,
1.0f, GridLayout::USE_PREF, 0, 0);
layout->StartRow(1 /* expand */, tabbed_pane_column);
- layout->AddView(tabbed_pane_);
+ tabbed_pane_ = layout->AddView(std::move(tabbed_pane));
// Create a few tabs with a button first.
AddButton("Tab 1");
@@ -50,9 +51,9 @@ void TabbedPaneExample::CreateExampleView(View* container) {
}
layout->StartRow(0 /* no expand */, button_column);
- layout->AddView(add_);
- layout->AddView(add_at_);
- layout->AddView(select_at_);
+ add_ = layout->AddView(std::move(add));
+ add_at_ = layout->AddView(std::move(add_at));
+ select_at_ = layout->AddView(std::move(select_at));
}
void TabbedPaneExample::ButtonPressed(Button* sender, const ui::Event& event) {
@@ -60,7 +61,8 @@ void TabbedPaneExample::ButtonPressed(Button* sender, const ui::Event& event) {
AddButton("Added");
} else if (sender == add_at_) {
const base::string16 label = ASCIIToUTF16("Added at 1");
- tabbed_pane_->AddTabAtIndex(1, label, new LabelButton(nullptr, label));
+ tabbed_pane_->AddTabAtIndex(1, label,
+ std::make_unique<LabelButton>(nullptr, label));
} else if (sender == select_at_) {
if (tabbed_pane_->GetTabCount() > 1)
tabbed_pane_->SelectTabAt(1);
@@ -80,8 +82,8 @@ void TabbedPaneExample::PrintStatus() {
}
void TabbedPaneExample::AddButton(const std::string& label) {
- LabelButton* button = new LabelButton(nullptr, ASCIIToUTF16(label));
- tabbed_pane_->AddTab(ASCIIToUTF16(label), button);
+ tabbed_pane_->AddTab(ASCIIToUTF16(label), std::make_unique<LabelButton>(
+ nullptr, ASCIIToUTF16(label)));
}
} // namespace examples
diff --git a/chromium/ui/views/examples/table_example.cc b/chromium/ui/views/examples/table_example.cc
index fc264a8c2ac..8b60316c723 100644
--- a/chromium/ui/views/examples/table_example.cc
+++ b/chromium/ui/views/examples/table_example.cc
@@ -41,21 +41,8 @@ TableExample::~TableExample() {
}
void TableExample::CreateExampleView(View* container) {
- column1_visible_checkbox_ =
- new Checkbox(ASCIIToUTF16("Fruit column visible"), this);
- column1_visible_checkbox_->SetChecked(true);
- column2_visible_checkbox_ =
- new Checkbox(ASCIIToUTF16("Color column visible"), this);
- column2_visible_checkbox_->SetChecked(true);
- column3_visible_checkbox_ =
- new Checkbox(ASCIIToUTF16("Origin column visible"), this);
- column3_visible_checkbox_->SetChecked(true);
- column4_visible_checkbox_ =
- new Checkbox(ASCIIToUTF16("Price column visible"), this);
- column4_visible_checkbox_->SetChecked(true);
-
- GridLayout* layout = container->SetLayoutManager(
- std::make_unique<views::GridLayout>(container));
+ GridLayout* layout =
+ container->SetLayoutManager(std::make_unique<views::GridLayout>());
std::vector<ui::TableColumn> columns;
columns.push_back(TestTableColumn(0, "Fruit"));
@@ -80,8 +67,7 @@ void TableExample::CreateExampleView(View* container) {
GridLayout::USE_PREF, 0, 0);
layout->StartRow(1 /* expand */, 0);
table_ = table.get();
- layout->AddView(
- TableView::CreateScrollViewWithTable(std::move(table)).release());
+ layout->AddView(TableView::CreateScrollViewWithTable(std::move(table)));
column_set = layout->AddColumnSet(1);
column_set->AddColumn(GridLayout::FILL, GridLayout::FILL,
@@ -95,10 +81,21 @@ void TableExample::CreateExampleView(View* container) {
layout->StartRow(0 /* no expand */, 1);
- layout->AddView(column1_visible_checkbox_);
- layout->AddView(column2_visible_checkbox_);
- layout->AddView(column3_visible_checkbox_);
- layout->AddView(column4_visible_checkbox_);
+ auto make_checkbox =
+ [this](base::string16 text) -> std::unique_ptr<Checkbox> {
+ auto result = std::make_unique<Checkbox>(text, this);
+ result->SetChecked(true);
+ return result;
+ };
+
+ column1_visible_checkbox_ =
+ layout->AddView(make_checkbox(ASCIIToUTF16("Fruit column visible")));
+ column2_visible_checkbox_ =
+ layout->AddView(make_checkbox(ASCIIToUTF16("Color column visible")));
+ column3_visible_checkbox_ =
+ layout->AddView(make_checkbox(ASCIIToUTF16("Origin column visible")));
+ column4_visible_checkbox_ =
+ layout->AddView(make_checkbox(ASCIIToUTF16("Price column visible")));
}
int TableExample::RowCount() {
diff --git a/chromium/ui/views/examples/text_example.cc b/chromium/ui/views/examples/text_example.cc
index 48f71158b30..4b3ed1255e3 100644
--- a/chromium/ui/views/examples/text_example.cc
+++ b/chromium/ui/views/examples/text_example.cc
@@ -130,9 +130,8 @@ TextExample::TextExample() : ExampleBase("Text Styles") {}
TextExample::~TextExample() = default;
Checkbox* TextExample::AddCheckbox(GridLayout* layout, const char* name) {
- Checkbox* checkbox = new Checkbox(base::ASCIIToUTF16(name), this);
- layout->AddView(checkbox);
- return checkbox;
+ return layout->AddView(
+ std::make_unique<Checkbox>(base::ASCIIToUTF16(name), this));
}
Combobox* TextExample::AddCombobox(GridLayout* layout,
@@ -140,20 +139,19 @@ Combobox* TextExample::AddCombobox(GridLayout* layout,
const char* const* strings,
int count) {
layout->StartRow(0, 0);
- layout->AddView(new Label(base::ASCIIToUTF16(name)));
- Combobox* combobox =
- new Combobox(std::make_unique<ExampleComboboxModel>(strings, count));
+ layout->AddView(std::make_unique<Label>(base::ASCIIToUTF16(name)));
+ auto combobox = std::make_unique<Combobox>(
+ std::make_unique<ExampleComboboxModel>(strings, count));
combobox->SetSelectedIndex(0);
combobox->set_listener(this);
- layout->AddView(combobox, kNumColumns - 1, 1);
- return combobox;
+ return layout->AddView(std::move(combobox), kNumColumns - 1, 1);
}
void TextExample::CreateExampleView(View* container) {
- text_view_ = new TextExampleView;
- text_view_->SetBorder(CreateSolidBorder(1, SK_ColorGRAY));
- GridLayout* layout = container->SetLayoutManager(
- std::make_unique<views::GridLayout>(container));
+ auto text_view = std::make_unique<TextExampleView>();
+ text_view->SetBorder(CreateSolidBorder(1, SK_ColorGRAY));
+ GridLayout* layout =
+ container->SetLayoutManager(std::make_unique<views::GridLayout>());
layout->AddPaddingRow(0, 8);
ColumnSet* column_set = layout->AddColumnSet(0);
@@ -190,7 +188,7 @@ void TextExample::CreateExampleView(View* container) {
1, GridLayout::USE_PREF, 0, 0);
column_set->AddPaddingColumn(0, 16);
layout->StartRow(1, 1);
- layout->AddView(text_view_);
+ text_view_ = layout->AddView(std::move(text_view));
layout->AddPaddingRow(0, 8);
}
diff --git a/chromium/ui/views/examples/textfield_example.cc b/chromium/ui/views/examples/textfield_example.cc
index b7a0290ecb5..6c217df53a1 100644
--- a/chromium/ui/views/examples/textfield_example.cc
+++ b/chromium/ui/views/examples/textfield_example.cc
@@ -23,37 +23,44 @@ using base::UTF16ToUTF8;
namespace views {
namespace examples {
+namespace {
+
+template <class K, class T>
+T* MakeRow(GridLayout* layout,
+ std::unique_ptr<K> view1,
+ std::unique_ptr<T> view2) {
+ layout->StartRowWithPadding(0, 0, 0, 5);
+ if (view1)
+ layout->AddView(std::move(view1));
+ return layout->AddView(std::move(view2));
+}
+
+} // namespace
+
TextfieldExample::TextfieldExample() : ExampleBase("Textfield") {}
TextfieldExample::~TextfieldExample() = default;
void TextfieldExample::CreateExampleView(View* container) {
- name_ = new Textfield();
- password_ = new Textfield();
- password_->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
- password_->set_placeholder_text(ASCIIToUTF16("password"));
- disabled_ = new Textfield();
- disabled_->SetEnabled(false);
- disabled_->SetText(ASCIIToUTF16("disabled"));
- read_only_ = new Textfield();
- read_only_->SetReadOnly(true);
- read_only_->SetText(ASCIIToUTF16("read only"));
- invalid_ = new Textfield();
- invalid_->SetInvalid(true);
- rtl_ = new Textfield();
- rtl_->ChangeTextDirectionAndLayoutAlignment(base::i18n::RIGHT_TO_LEFT);
- show_password_ = new LabelButton(this, ASCIIToUTF16("Show password"));
- set_background_ =
- new LabelButton(this, ASCIIToUTF16("Set non-default background"));
- clear_all_ = new LabelButton(this, ASCIIToUTF16("Clear All"));
- append_ = new LabelButton(this, ASCIIToUTF16("Append"));
- set_ = new LabelButton(this, ASCIIToUTF16("Set"));
- set_style_ = new LabelButton(this, ASCIIToUTF16("Set Styles"));
- name_->set_controller(this);
- password_->set_controller(this);
-
- GridLayout* layout = container->SetLayoutManager(
- std::make_unique<views::GridLayout>(container));
+ auto name = std::make_unique<Textfield>();
+ name->set_controller(this);
+ auto password = std::make_unique<Textfield>();
+ password->SetTextInputType(ui::TEXT_INPUT_TYPE_PASSWORD);
+ password->set_placeholder_text(ASCIIToUTF16("password"));
+ password->set_controller(this);
+ auto disabled = std::make_unique<Textfield>();
+ disabled->SetEnabled(false);
+ disabled->SetText(ASCIIToUTF16("disabled"));
+ auto read_only = std::make_unique<Textfield>();
+ read_only->SetReadOnly(true);
+ read_only->SetText(ASCIIToUTF16("read only"));
+ auto invalid = std::make_unique<Textfield>();
+ invalid->SetInvalid(true);
+ auto rtl = std::make_unique<Textfield>();
+ rtl->ChangeTextDirectionAndLayoutAlignment(base::i18n::RIGHT_TO_LEFT);
+
+ GridLayout* layout =
+ container->SetLayoutManager(std::make_unique<views::GridLayout>());
ColumnSet* column_set = layout->AddColumnSet(0);
column_set->AddColumn(GridLayout::LEADING, GridLayout::FILL,
@@ -61,25 +68,42 @@ void TextfieldExample::CreateExampleView(View* container) {
column_set->AddColumn(GridLayout::FILL, GridLayout::FILL,
0.8f, GridLayout::USE_PREF, 0, 0);
- auto MakeRow = [layout](View* view1, View* view2) {
- layout->StartRowWithPadding(0, 0, 0, 5);
- layout->AddView(view1);
- if (view2)
- layout->AddView(view2);
- };
- MakeRow(new Label(ASCIIToUTF16("Name:")), name_);
- MakeRow(new Label(ASCIIToUTF16("Password:")), password_);
- MakeRow(new Label(ASCIIToUTF16("Disabled:")), disabled_);
- MakeRow(new Label(ASCIIToUTF16("Read Only:")), read_only_);
- MakeRow(new Label(ASCIIToUTF16("Invalid:")), invalid_);
- MakeRow(new Label(ASCIIToUTF16("RTL:")), rtl_);
- MakeRow(new Label(ASCIIToUTF16("Name:")), nullptr);
- MakeRow(show_password_, nullptr);
- MakeRow(set_background_, nullptr);
- MakeRow(clear_all_, nullptr);
- MakeRow(append_, nullptr);
- MakeRow(set_, nullptr);
- MakeRow(set_style_, nullptr);
+ name_ = MakeRow(layout, std::make_unique<Label>(ASCIIToUTF16("Name:")),
+ std::move(name));
+ password_ =
+ MakeRow(layout, std::make_unique<Label>(ASCIIToUTF16("Password:")),
+ std::move(password));
+ disabled_ =
+ MakeRow(layout, std::make_unique<Label>(ASCIIToUTF16("Disabled:")),
+ std::move(disabled));
+ read_only_ =
+ MakeRow(layout, std::make_unique<Label>(ASCIIToUTF16("Read Only:")),
+ std::move(read_only));
+ invalid_ = MakeRow(layout, std::make_unique<Label>(ASCIIToUTF16("Invalid:")),
+ std::move(invalid));
+ rtl_ = MakeRow(layout, std::make_unique<Label>(ASCIIToUTF16("RTL:")),
+ std::move(rtl));
+ MakeRow<View, Label>(layout, nullptr,
+ std::make_unique<Label>(ASCIIToUTF16("Name:")));
+ show_password_ = MakeRow<View, LabelButton>(
+ layout, nullptr,
+ std::make_unique<LabelButton>(this, ASCIIToUTF16("Show password")));
+ set_background_ = MakeRow<View, LabelButton>(
+ layout, nullptr,
+ std::make_unique<LabelButton>(
+ this, ASCIIToUTF16("Set non-default background")));
+ clear_all_ = MakeRow<View, LabelButton>(
+ layout, nullptr,
+ std::make_unique<LabelButton>(this, ASCIIToUTF16("Clear All")));
+ append_ = MakeRow<View, LabelButton>(
+ layout, nullptr,
+ std::make_unique<LabelButton>(this, ASCIIToUTF16("Append")));
+ set_ = MakeRow<View, LabelButton>(
+ layout, nullptr,
+ std::make_unique<LabelButton>(this, ASCIIToUTF16("Set")));
+ set_style_ = MakeRow<View, LabelButton>(
+ layout, nullptr,
+ std::make_unique<LabelButton>(this, ASCIIToUTF16("Set Styles")));
}
void TextfieldExample::ContentsChanged(Textfield* sender,
diff --git a/chromium/ui/views/examples/toggle_button_example.cc b/chromium/ui/views/examples/toggle_button_example.cc
index 700edfdc3fc..fd476535188 100644
--- a/chromium/ui/views/examples/toggle_button_example.cc
+++ b/chromium/ui/views/examples/toggle_button_example.cc
@@ -19,7 +19,7 @@ ToggleButtonExample::~ToggleButtonExample() = default;
void ToggleButtonExample::CreateExampleView(View* container) {
button_ = new ToggleButton(this);
- auto layout = std::make_unique<BoxLayout>(BoxLayout::kVertical);
+ auto layout = std::make_unique<BoxLayout>(BoxLayout::Orientation::kVertical);
layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kCenter);
container->SetLayoutManager(std::move(layout));
container->AddChildView(button_);
diff --git a/chromium/ui/views/examples/tree_view_example.cc b/chromium/ui/views/examples/tree_view_example.cc
index 38cce7cb589..7496472d9f3 100644
--- a/chromium/ui/views/examples/tree_view_example.cc
+++ b/chromium/ui/views/examples/tree_view_example.cc
@@ -73,18 +73,19 @@ void TreeViewExample::CreateExampleView(View* container) {
tree_view->SetController(this);
tree_view->SetDrawingProvider(
std::make_unique<ExampleTreeViewDrawingProvider>());
- add_ = new LabelButton(this, ASCIIToUTF16("Add"));
- add_->SetFocusForPlatform();
- add_->set_request_focus_on_press(true);
- remove_ = new LabelButton(this, ASCIIToUTF16("Remove"));
- remove_->SetFocusForPlatform();
- remove_->set_request_focus_on_press(true);
- change_title_ = new LabelButton(this, ASCIIToUTF16("Change Title"));
- change_title_->SetFocusForPlatform();
- change_title_->set_request_focus_on_press(true);
-
- GridLayout* layout = container->SetLayoutManager(
- std::make_unique<views::GridLayout>(container));
+ auto add = std::make_unique<LabelButton>(this, ASCIIToUTF16("Add"));
+ add->SetFocusForPlatform();
+ add->set_request_focus_on_press(true);
+ auto remove = std::make_unique<LabelButton>(this, ASCIIToUTF16("Remove"));
+ remove->SetFocusForPlatform();
+ remove->set_request_focus_on_press(true);
+ auto change_title =
+ std::make_unique<LabelButton>(this, ASCIIToUTF16("Change Title"));
+ change_title->SetFocusForPlatform();
+ change_title->set_request_focus_on_press(true);
+
+ GridLayout* layout =
+ container->SetLayoutManager(std::make_unique<views::GridLayout>());
const int tree_view_column = 0;
ColumnSet* column_set = layout->AddColumnSet(tree_view_column);
@@ -92,8 +93,7 @@ void TreeViewExample::CreateExampleView(View* container) {
1.0f, GridLayout::USE_PREF, 0, 0);
layout->StartRow(1 /* expand */, tree_view_column);
tree_view_ = tree_view.get();
- layout->AddView(
- TreeView::CreateScrollViewWithTree(std::move(tree_view)).release());
+ layout->AddView(TreeView::CreateScrollViewWithTree(std::move(tree_view)));
// Add control buttons horizontally.
const int button_column = 1;
@@ -104,9 +104,9 @@ void TreeViewExample::CreateExampleView(View* container) {
}
layout->StartRow(0 /* no expand */, button_column);
- layout->AddView(add_);
- layout->AddView(remove_);
- layout->AddView(change_title_);
+ add_ = layout->AddView(std::move(add));
+ remove_ = layout->AddView(std::move(remove));
+ change_title_ = layout->AddView(std::move(change_title));
}
void TreeViewExample::AddNewNode() {
@@ -115,8 +115,7 @@ void TreeViewExample::AddNewNode() {
if (!selected_node)
selected_node = model_.GetRoot();
NodeType* new_node = model_.Add(
- selected_node, std::make_unique<NodeType>(selected_node->GetTitle(), 1),
- selected_node->child_count());
+ selected_node, std::make_unique<NodeType>(selected_node->GetTitle(), 1));
tree_view_->SetSelectedNode(new_node);
}
diff --git a/chromium/ui/views/examples/vector_example.cc b/chromium/ui/views/examples/vector_example.cc
index bae6772d285..f631b382b1e 100644
--- a/chromium/ui/views/examples/vector_example.cc
+++ b/chromium/ui/views/examples/vector_example.cc
@@ -39,7 +39,8 @@ class VectorIconGallery : public View,
auto image_view_container = std::make_unique<views::View>();
image_view_ =
image_view_container->AddChildView(std::make_unique<ImageView>());
- auto image_layout = std::make_unique<BoxLayout>(BoxLayout::kHorizontal);
+ auto image_layout =
+ std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal);
image_layout->set_cross_axis_alignment(
BoxLayout::CrossAxisAlignment::kCenter);
image_layout->set_main_axis_alignment(
@@ -48,8 +49,8 @@ class VectorIconGallery : public View,
image_view_->SetBorder(CreateSolidSidedBorder(1, 1, 1, 1, SK_ColorBLACK));
image_view_container_ = AddChildView(std::move(image_view_container));
- BoxLayout* box = SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kVertical, gfx::Insets(10), 10));
+ BoxLayout* box = SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kVertical, gfx::Insets(10), 10));
box->SetFlexForView(image_view_container_, 1);
auto file_chooser = std::make_unique<Textfield>();
@@ -58,7 +59,7 @@ class VectorIconGallery : public View,
auto file_container = std::make_unique<View>();
BoxLayout* file_box =
file_container->SetLayoutManager(std::make_unique<BoxLayout>(
- BoxLayout::kHorizontal, gfx::Insets(10), 10));
+ BoxLayout::Orientation::kHorizontal, gfx::Insets(10), 10));
file_chooser_ = file_container->AddChildView(std::move(file_chooser));
file_go_button_ = file_container->AddChildView(
MdTextButton::Create(this, base::ASCIIToUTF16("Render")));
diff --git a/chromium/ui/views/examples/widget_example.cc b/chromium/ui/views/examples/widget_example.cc
index 891c4e5e64d..0a36f58420d 100644
--- a/chromium/ui/views/examples/widget_example.cc
+++ b/chromium/ui/views/examples/widget_example.cc
@@ -28,8 +28,8 @@ class WidgetDialogExample : public DialogDelegateView {
WidgetDialogExample();
~WidgetDialogExample() override;
base::string16 GetWindowTitle() const override;
- View* CreateExtraView() override;
- View* CreateFootnoteView() override;
+ std::unique_ptr<View> CreateExtraView() override;
+ std::unique_ptr<View> CreateFootnoteView() override;
};
class ModalDialogExample : public WidgetDialogExample {
@@ -45,8 +45,8 @@ class ModalDialogExample : public WidgetDialogExample {
WidgetDialogExample::WidgetDialogExample() {
SetBackground(CreateSolidBackground(SK_ColorGRAY));
- SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kVertical, gfx::Insets(10), 10));
+ SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kVertical, gfx::Insets(10), 10));
AddChildView(new Label(ASCIIToUTF16("Dialog contents label!")));
}
@@ -56,15 +56,14 @@ base::string16 WidgetDialogExample::GetWindowTitle() const {
return ASCIIToUTF16("Dialog Widget Example");
}
-// TODO(crbug.com/961660): CreateExtraView should return std::unique_ptr<View>
-View* WidgetDialogExample::CreateExtraView() {
+std::unique_ptr<View> WidgetDialogExample::CreateExtraView() {
auto view = MdTextButton::CreateSecondaryUiButton(
nullptr, ASCIIToUTF16("Extra button!"));
- return view.release();
+ return view;
}
-View* WidgetDialogExample::CreateFootnoteView() {
- return new Label(ASCIIToUTF16("Footnote label!"));
+std::unique_ptr<View> WidgetDialogExample::CreateFootnoteView() {
+ return std::make_unique<Label>(ASCIIToUTF16("Footnote label!"));
}
} // namespace
@@ -75,8 +74,8 @@ WidgetExample::WidgetExample() : ExampleBase("Widget") {
WidgetExample::~WidgetExample() = default;
void WidgetExample::CreateExampleView(View* container) {
- container->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(), 10));
+ container->SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kHorizontal, gfx::Insets(), 10));
BuildButton(container, "Popup widget", POPUP);
BuildButton(container, "Dialog widget", DIALOG);
BuildButton(container, "Modal Dialog", MODAL_DIALOG);
@@ -109,7 +108,7 @@ void WidgetExample::ShowWidget(View* sender, Widget::InitParams params) {
if (!widget->GetContentsView()) {
View* contents = new View();
contents->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal));
+ std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal));
contents->SetBackground(CreateSolidBackground(SK_ColorGRAY));
BuildButton(contents, "Close", CLOSE_WIDGET);
widget->SetContentsView(contents);
diff --git a/chromium/ui/views/focus/focus_traversal_unittest.cc b/chromium/ui/views/focus/focus_traversal_unittest.cc
index 2b8285974af..3d2ef8e76ce 100644
--- a/chromium/ui/views/focus/focus_traversal_unittest.cc
+++ b/chromium/ui/views/focus/focus_traversal_unittest.cc
@@ -299,18 +299,17 @@ void FocusTraversalTest::InitContentView() {
GetContentsView()->SetBackground(CreateSolidBackground(SK_ColorWHITE));
- Checkbox* cb = new Checkbox(ASCIIToUTF16("This is a checkbox"));
- GetContentsView()->AddChildView(cb);
+ auto cb = std::make_unique<Checkbox>(ASCIIToUTF16("This is a checkbox"));
+ auto* cb_ptr = GetContentsView()->AddChildView(std::move(cb));
// In this fast paced world, who really has time for non hard-coded layout?
- cb->SetBounds(10, 10, 200, 20);
- cb->SetID(TOP_CHECKBOX_ID);
-
- left_container_ = new PaneView();
- left_container_->SetBorder(CreateSolidBorder(1, SK_ColorBLACK));
- left_container_->SetBackground(
- CreateSolidBackground(SkColorSetRGB(240, 240, 240)));
- left_container_->SetID(LEFT_CONTAINER_ID);
- GetContentsView()->AddChildView(left_container_);
+ cb_ptr->SetBounds(10, 10, 200, 20);
+ cb_ptr->SetID(TOP_CHECKBOX_ID);
+
+ auto container = std::make_unique<PaneView>();
+ container->SetBorder(CreateSolidBorder(1, SK_ColorBLACK));
+ container->SetBackground(CreateSolidBackground(SkColorSetRGB(240, 240, 240)));
+ container->SetID(LEFT_CONTAINER_ID);
+ left_container_ = GetContentsView()->AddChildView(std::move(container));
left_container_->SetBounds(10, 35, 250, 200);
int label_x = 5;
@@ -320,55 +319,55 @@ void FocusTraversalTest::InitContentView() {
int y = 10;
int gap_between_labels = 10;
- Label* label = new Label(ASCIIToUTF16("Apple:"));
+ auto label = std::make_unique<Label>(ASCIIToUTF16("Apple:"));
label->SetID(APPLE_LABEL_ID);
- left_container_->AddChildView(label);
- label->SetBounds(label_x, y, label_width, label_height);
+ auto* label_ptr = left_container_->AddChildView(std::move(label));
+ label_ptr->SetBounds(label_x, y, label_width, label_height);
- Textfield* text_field = new Textfield();
+ auto text_field = std::make_unique<Textfield>();
text_field->SetID(APPLE_TEXTFIELD_ID);
- left_container_->AddChildView(text_field);
- text_field->SetBounds(label_x + label_width + 5, y,
- text_field_width, label_height);
+ auto* text_field_ptr = left_container_->AddChildView(std::move(text_field));
+ text_field_ptr->SetBounds(label_x + label_width + 5, y, text_field_width,
+ label_height);
y += label_height + gap_between_labels;
- label = new Label(ASCIIToUTF16("Orange:"));
+ label = std::make_unique<Label>(ASCIIToUTF16("Orange:"));
label->SetID(ORANGE_LABEL_ID);
- left_container_->AddChildView(label);
- label->SetBounds(label_x, y, label_width, label_height);
+ label_ptr = left_container_->AddChildView(std::move(label));
+ label_ptr->SetBounds(label_x, y, label_width, label_height);
- text_field = new Textfield();
+ text_field = std::make_unique<Textfield>();
text_field->SetID(ORANGE_TEXTFIELD_ID);
- left_container_->AddChildView(text_field);
- text_field->SetBounds(label_x + label_width + 5, y,
- text_field_width, label_height);
+ text_field_ptr = left_container_->AddChildView(std::move(text_field));
+ text_field_ptr->SetBounds(label_x + label_width + 5, y, text_field_width,
+ label_height);
y += label_height + gap_between_labels;
- label = new Label(ASCIIToUTF16("Banana:"));
+ label = std::make_unique<Label>(ASCIIToUTF16("Banana:"));
label->SetID(BANANA_LABEL_ID);
- left_container_->AddChildView(label);
- label->SetBounds(label_x, y, label_width, label_height);
+ label_ptr = left_container_->AddChildView(std::move(label));
+ label_ptr->SetBounds(label_x, y, label_width, label_height);
- text_field = new Textfield();
+ text_field = std::make_unique<Textfield>();
text_field->SetID(BANANA_TEXTFIELD_ID);
- left_container_->AddChildView(text_field);
- text_field->SetBounds(label_x + label_width + 5, y,
- text_field_width, label_height);
+ text_field_ptr = left_container_->AddChildView(std::move(text_field));
+ text_field_ptr->SetBounds(label_x + label_width + 5, y, text_field_width,
+ label_height);
y += label_height + gap_between_labels;
- label = new Label(ASCIIToUTF16("Kiwi:"));
+ label = std::make_unique<Label>(ASCIIToUTF16("Kiwi:"));
label->SetID(KIWI_LABEL_ID);
- left_container_->AddChildView(label);
- label->SetBounds(label_x, y, label_width, label_height);
+ label_ptr = left_container_->AddChildView(std::move(label));
+ label_ptr->SetBounds(label_x, y, label_width, label_height);
- text_field = new Textfield();
+ text_field = std::make_unique<Textfield>();
text_field->SetID(KIWI_TEXTFIELD_ID);
- left_container_->AddChildView(text_field);
- text_field->SetBounds(label_x + label_width + 5, y,
- text_field_width, label_height);
+ text_field_ptr = left_container_->AddChildView(std::move(text_field));
+ text_field_ptr->SetBounds(label_x + label_width + 5, y, text_field_width,
+ label_height);
y += label_height + gap_between_labels;
@@ -378,67 +377,70 @@ void FocusTraversalTest::InitContentView() {
left_container_->AddChildView(std::move(button));
y += 40;
- cb = new Checkbox(ASCIIToUTF16("This is another check box"));
+ cb = std::make_unique<Checkbox>(ASCIIToUTF16("This is another check box"));
cb->SetBounds(label_x + label_width + 5, y, 180, 20);
cb->SetID(FRUIT_CHECKBOX_ID);
- left_container_->AddChildView(cb);
+ left_container_->AddChildView(std::move(cb));
y += 20;
- Combobox* combobox = new Combobox(&combobox_model_);
+ auto combobox = std::make_unique<Combobox>(&combobox_model_);
combobox->SetBounds(label_x + label_width + 5, y, 150, 30);
combobox->SetID(COMBOBOX_ID);
- left_container_->AddChildView(combobox);
-
- right_container_ = new PaneView();
- right_container_->SetBorder(CreateSolidBorder(1, SK_ColorBLACK));
- right_container_->SetBackground(
- CreateSolidBackground(SkColorSetRGB(240, 240, 240)));
- right_container_->SetID(RIGHT_CONTAINER_ID);
- GetContentsView()->AddChildView(right_container_);
+ left_container_->AddChildView(std::move(combobox));
+
+ container = std::make_unique<PaneView>();
+ container->SetBorder(CreateSolidBorder(1, SK_ColorBLACK));
+ container->SetBackground(CreateSolidBackground(SkColorSetRGB(240, 240, 240)));
+ container->SetID(RIGHT_CONTAINER_ID);
+ right_container_ = GetContentsView()->AddChildView(std::move(container));
right_container_->SetBounds(270, 35, 300, 200);
y = 10;
int radio_button_height = 18;
int gap_between_radio_buttons = 10;
- RadioButton* radio_button = new RadioButton(ASCIIToUTF16("Asparagus"), 1);
+ auto radio_button =
+ std::make_unique<RadioButton>(ASCIIToUTF16("Asparagus"), 1);
radio_button->SetID(ASPARAGUS_BUTTON_ID);
- right_container_->AddChildView(radio_button);
- radio_button->SetBounds(5, y, 70, radio_button_height);
- radio_button->SetGroup(1);
+ auto* radio_button_ptr =
+ right_container_->AddChildView(std::move(radio_button));
+ radio_button_ptr->SetBounds(5, y, 70, radio_button_height);
+ radio_button_ptr->SetGroup(1);
y += radio_button_height + gap_between_radio_buttons;
- radio_button = new RadioButton(ASCIIToUTF16("Broccoli"), 1);
+ radio_button = std::make_unique<RadioButton>(ASCIIToUTF16("Broccoli"), 1);
radio_button->SetID(BROCCOLI_BUTTON_ID);
- right_container_->AddChildView(radio_button);
- radio_button->SetBounds(5, y, 70, radio_button_height);
- radio_button->SetGroup(1);
- RadioButton* radio_button_to_check = radio_button;
+ radio_button_ptr = right_container_->AddChildView(std::move(radio_button));
+ radio_button_ptr->SetBounds(5, y, 70, radio_button_height);
+ radio_button_ptr->SetGroup(1);
+ RadioButton* radio_button_to_check = radio_button_ptr;
y += radio_button_height + gap_between_radio_buttons;
- radio_button = new RadioButton(ASCIIToUTF16("Cauliflower"), 1);
+ radio_button = std::make_unique<RadioButton>(ASCIIToUTF16("Cauliflower"), 1);
radio_button->SetID(CAULIFLOWER_BUTTON_ID);
- right_container_->AddChildView(radio_button);
- radio_button->SetBounds(5, y, 70, radio_button_height);
- radio_button->SetGroup(1);
+ radio_button_ptr = right_container_->AddChildView(std::move(radio_button));
+ radio_button_ptr->SetBounds(5, y, 70, radio_button_height);
+ radio_button_ptr->SetGroup(1);
y += radio_button_height + gap_between_radio_buttons;
- View* inner_container = new View();
+ auto inner_container = std::make_unique<View>();
inner_container->SetBorder(CreateSolidBorder(1, SK_ColorBLACK));
inner_container->SetBackground(
CreateSolidBackground(SkColorSetRGB(230, 230, 230)));
inner_container->SetID(INNER_CONTAINER_ID);
- right_container_->AddChildView(inner_container);
- inner_container->SetBounds(100, 10, 150, 180);
+ auto* inner_container_ptr =
+ right_container_->AddChildView(std::move(inner_container));
+ inner_container_ptr->SetBounds(100, 10, 150, 180);
- ScrollView* scroll_view = new ScrollView();
+ auto scroll_view = std::make_unique<ScrollView>();
scroll_view->SetID(SCROLL_VIEW_ID);
- inner_container->AddChildView(scroll_view);
- scroll_view->SetBounds(1, 1, 148, 178);
+ auto* scroll_view_ptr =
+ inner_container_ptr->AddChildView(std::move(scroll_view));
+ scroll_view_ptr->SetBounds(1, 1, 148, 178);
auto scroll_content = std::make_unique<View>();
scroll_content->SetBounds(0, 0, 200, 200);
scroll_content->SetBackground(
CreateSolidBackground(SkColorSetRGB(200, 200, 200)));
auto* scroll_content_ptr =
- scroll_view->SetContents(std::move(scroll_content));
+ scroll_view_ptr->SetContents(std::move(scroll_content));
static const char* const kTitles[] = {
"Rosetta", "Stupeur et tremblement", "The diner game",
@@ -458,11 +460,11 @@ void FocusTraversalTest::InitContentView() {
y = 5;
for (size_t i = 0; i < base::size(kTitles); ++i) {
- Link* link = new Link(ASCIIToUTF16(kTitles[i]));
+ auto link = std::make_unique<Link>(ASCIIToUTF16(kTitles[i]));
link->SetHorizontalAlignment(gfx::ALIGN_LEFT);
link->SetID(kIDs[i]);
- scroll_content_ptr->AddChildView(link);
- link->SetBounds(5, y, 300, 15);
+ auto* link_ptr = scroll_content_ptr->AddChildView(std::move(link));
+ link_ptr->SetBounds(5, y, 300, 15);
y += 15;
}
@@ -486,72 +488,70 @@ void FocusTraversalTest::InitContentView() {
y += 40;
- View* contents = nullptr;
- Link* link = nullptr;
-
// Left bottom box with style checkboxes.
- contents = new View();
+ auto contents = std::make_unique<View>();
contents->SetBackground(CreateSolidBackground(SK_ColorWHITE));
- cb = new Checkbox(ASCIIToUTF16("Bold"));
- contents->AddChildView(cb);
- cb->SetBounds(10, 10, 50, 20);
- cb->SetID(BOLD_CHECKBOX_ID);
-
- cb = new Checkbox(ASCIIToUTF16("Italic"));
- contents->AddChildView(cb);
- cb->SetBounds(70, 10, 50, 20);
- cb->SetID(ITALIC_CHECKBOX_ID);
-
- cb = new Checkbox(ASCIIToUTF16("Underlined"));
- contents->AddChildView(cb);
- cb->SetBounds(130, 10, 70, 20);
- cb->SetID(UNDERLINED_CHECKBOX_ID);
-
- link = new Link(ASCIIToUTF16("Help"));
- contents->AddChildView(link);
- link->SetBounds(10, 35, 70, 10);
- link->SetID(STYLE_HELP_LINK_ID);
-
- text_field = new Textfield();
- contents->AddChildView(text_field);
- text_field->SetBounds(10, 50, 100, 20);
- text_field->SetID(STYLE_TEXT_EDIT_ID);
-
- style_tab_ = new TabbedPane();
- GetContentsView()->AddChildView(style_tab_);
+ cb = std::make_unique<Checkbox>(ASCIIToUTF16("Bold"));
+ cb_ptr = contents->AddChildView(std::move(cb));
+ cb_ptr->SetBounds(10, 10, 50, 20);
+ cb_ptr->SetID(BOLD_CHECKBOX_ID);
+
+ cb = std::make_unique<Checkbox>(ASCIIToUTF16("Italic"));
+ cb_ptr = contents->AddChildView(std::move(cb));
+ cb_ptr->SetBounds(70, 10, 50, 20);
+ cb_ptr->SetID(ITALIC_CHECKBOX_ID);
+
+ cb = std::make_unique<Checkbox>(ASCIIToUTF16("Underlined"));
+ cb_ptr = contents->AddChildView(std::move(cb));
+ cb_ptr->SetBounds(130, 10, 70, 20);
+ cb_ptr->SetID(UNDERLINED_CHECKBOX_ID);
+
+ auto link = std::make_unique<Link>(ASCIIToUTF16("Help"));
+ auto* link_ptr = contents->AddChildView(std::move(link));
+ link_ptr->SetBounds(10, 35, 70, 10);
+ link_ptr->SetID(STYLE_HELP_LINK_ID);
+
+ text_field = std::make_unique<Textfield>();
+ text_field_ptr = contents->AddChildView(std::move(text_field));
+ text_field_ptr->SetBounds(10, 50, 100, 20);
+ text_field_ptr->SetID(STYLE_TEXT_EDIT_ID);
+
+ auto style_tab = std::make_unique<TabbedPane>();
+ style_tab_ = GetContentsView()->AddChildView(std::move(style_tab));
style_tab_->SetBounds(10, y, 210, 100);
- style_tab_->AddTab(ASCIIToUTF16("Style"), contents);
+ style_tab_->AddTab(ASCIIToUTF16("Style"), std::move(contents));
style_tab_->GetSelectedTab()->SetID(STYLE_CONTAINER_ID);
- style_tab_->AddTab(ASCIIToUTF16("Other"), new View());
+ style_tab_->AddTab(ASCIIToUTF16("Other"), std::make_unique<View>());
// Right bottom box with search.
- contents = new View();
+ contents = std::make_unique<View>();
contents->SetBackground(CreateSolidBackground(SK_ColorWHITE));
- text_field = new Textfield();
- contents->AddChildView(text_field);
- text_field->SetBounds(10, 10, 100, 20);
- text_field->SetID(SEARCH_TEXTFIELD_ID);
+ text_field = std::make_unique<Textfield>();
+ text_field_ptr = contents->AddChildView(std::move(text_field));
+ text_field_ptr->SetBounds(10, 10, 100, 20);
+ text_field_ptr->SetID(SEARCH_TEXTFIELD_ID);
button = MdTextButton::Create(nullptr, ASCIIToUTF16("Search"));
button->SetBounds(112, 5, 60, 30);
button->SetID(SEARCH_BUTTON_ID);
contents->AddChildView(std::move(button));
- link = new Link(ASCIIToUTF16("Help"));
+ link = std::make_unique<Link>(ASCIIToUTF16("Help"));
link->SetHorizontalAlignment(gfx::ALIGN_LEFT);
link->SetID(HELP_LINK_ID);
- contents->AddChildView(link);
- link->SetBounds(175, 10, 30, 20);
+ link_ptr = contents->AddChildView(std::move(link));
+ link_ptr->SetBounds(175, 10, 30, 20);
- search_border_view_ = new BorderView(contents);
- search_border_view_->SetID(SEARCH_CONTAINER_ID);
+ auto search_border_view = std::make_unique<BorderView>(contents.release());
+ search_border_view->SetID(SEARCH_CONTAINER_ID);
- GetContentsView()->AddChildView(search_border_view_);
+ search_border_view_ =
+ GetContentsView()->AddChildView(std::move(search_border_view));
search_border_view_->SetBounds(300, y, 240, 50);
y += 60;
- contents = new View();
+ contents = std::make_unique<View>();
contents->SetFocusBehavior(View::FocusBehavior::ALWAYS);
contents->SetBackground(CreateSolidBackground(SK_ColorBLUE));
contents->SetID(THUMBNAIL_CONTAINER_ID);
@@ -564,8 +564,8 @@ void FocusTraversalTest::InitContentView() {
button->SetID(THUMBNAIL_SUPER_STAR_ID);
contents->AddChildView(std::move(button));
- GetContentsView()->AddChildView(contents);
- contents->SetBounds(250, y, 200, 50);
+ auto* contents_ptr = GetContentsView()->AddChildView(std::move(contents));
+ contents_ptr->SetBounds(250, y, 200, 50);
// We can only call RadioButton::SetChecked() on the radio-button is part of
// the view hierarchy.
radio_button_to_check->SetChecked(true);
diff --git a/chromium/ui/views/input_event_activation_protector.cc b/chromium/ui/views/input_event_activation_protector.cc
new file mode 100644
index 00000000000..887b5e6d962
--- /dev/null
+++ b/chromium/ui/views/input_event_activation_protector.cc
@@ -0,0 +1,50 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/input_event_activation_protector.h"
+
+#include "ui/events/event.h"
+#include "ui/views/metrics.h"
+
+namespace views {
+
+void InputEventActivationProtector::VisibilityChanged(bool is_visible) {
+ if (is_visible)
+ view_shown_time_stamp_ = base::TimeTicks::Now();
+}
+
+bool InputEventActivationProtector::IsPossiblyUnintendedInteraction(
+ const ui::Event& event) {
+ if (view_shown_time_stamp_ == base::TimeTicks()) {
+ // The UI was never shown, ignore. This can happen in tests.
+ return false;
+ }
+
+ if (!event.IsMouseEvent() && !event.IsTouchEvent())
+ return false;
+
+ const base::TimeDelta kShortInterval =
+ base::TimeDelta::FromMilliseconds(GetDoubleClickInterval());
+ const bool short_event_after_last_event =
+ event.time_stamp() < last_event_timestamp_ + kShortInterval;
+ last_event_timestamp_ = event.time_stamp();
+
+ // Unintended if the user has been clicking with short intervals.
+ if (short_event_after_last_event) {
+ repeated_event_count_++;
+ return true;
+ }
+ repeated_event_count_ = 0;
+
+ // Unintended if the user clicked right after the UI showed.
+ return event.time_stamp() < view_shown_time_stamp_ + kShortInterval;
+}
+
+void InputEventActivationProtector::ResetForTesting() {
+ view_shown_time_stamp_ = base::TimeTicks();
+ last_event_timestamp_ = base::TimeTicks();
+ repeated_event_count_ = 0;
+}
+
+} // namespace views
diff --git a/chromium/ui/views/input_event_activation_protector.h b/chromium/ui/views/input_event_activation_protector.h
new file mode 100644
index 00000000000..24a0d5b9bd2
--- /dev/null
+++ b/chromium/ui/views/input_event_activation_protector.h
@@ -0,0 +1,49 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_INPUT_EVENT_ACTIVATION_PROTECTOR_H_
+#define UI_VIEWS_INPUT_EVENT_ACTIVATION_PROTECTOR_H_
+
+#include "base/macros.h"
+#include "base/time/time.h"
+#include "ui/views/views_export.h"
+
+namespace ui {
+class Event;
+}
+
+namespace views {
+
+// The goal of this class is to prevent potentially unintentional user
+// interaction with a UI element.
+class VIEWS_EXPORT InputEventActivationProtector {
+ public:
+ InputEventActivationProtector() = default;
+ ~InputEventActivationProtector() = default;
+
+ // Updates the state of the protector based off of visibility changes. This
+ // method must be called when the visibility of the view is changed.
+ void VisibilityChanged(bool is_visible);
+
+ // Returns true if the event is a mouse, touch, or pointer event that took
+ // place within the double-click time interval after |view_shown_time_stamp_|.
+ bool IsPossiblyUnintendedInteraction(const ui::Event& event);
+
+ // Resets the state for click tracking.
+ void ResetForTesting();
+
+ private:
+ // Timestamp of when the view being tracked is first shown.
+ base::TimeTicks view_shown_time_stamp_;
+ // Timestamp of the last event.
+ base::TimeTicks last_event_timestamp_;
+ // Number of repeated UI events with short intervals.
+ size_t repeated_event_count_ = 0;
+
+ DISALLOW_COPY_AND_ASSIGN(InputEventActivationProtector);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_INPUT_EVENT_ACTIVATION_PROTECTOR_H_
diff --git a/chromium/ui/views/layout/box_layout.cc b/chromium/ui/views/layout/box_layout.cc
index 94322109cf6..b8466099f9c 100644
--- a/chromium/ui/views/layout/box_layout.cc
+++ b/chromium/ui/views/layout/box_layout.cc
@@ -201,10 +201,11 @@ void BoxLayout::Layout(View* host) {
gfx::Rect min_child_area(child_area);
gfx::Insets child_margins;
if (collapse_margins_spacing_) {
- child_margins = MaxAxisInsets(
- orientation_ == kVertical ? HORIZONTAL_AXIS : VERTICAL_AXIS,
- child.margins(), inside_border_insets_, child.margins(),
- inside_border_insets_);
+ child_margins =
+ MaxAxisInsets(orientation_ == Orientation::kVertical ? HORIZONTAL_AXIS
+ : VERTICAL_AXIS,
+ child.margins(), inside_border_insets_, child.margins(),
+ inside_border_insets_);
} else {
child_margins = child.margins();
}
@@ -289,7 +290,7 @@ gfx::Size BoxLayout::GetPreferredSize(const View* host) const {
DCHECK_EQ(host_, host);
// Calculate the child views' preferred width.
int width = 0;
- if (orientation_ == kVertical) {
+ if (orientation_ == Orientation::kVertical) {
// Calculating the child views' overall preferred width is a little involved
// because of the way the margins interact with |cross_axis_alignment_|.
int leading = 0;
@@ -371,49 +372,51 @@ int BoxLayout::GetMinimumSizeForView(const View* view) const {
if (it == flex_map_.end() || !it->second.use_min_size)
return 0;
- return (orientation_ == kHorizontal) ? view->GetMinimumSize().width()
- : view->GetMinimumSize().height();
+ return (orientation_ == Orientation::kHorizontal)
+ ? view->GetMinimumSize().width()
+ : view->GetMinimumSize().height();
}
int BoxLayout::MainAxisSize(const gfx::Rect& rect) const {
- return orientation_ == kHorizontal ? rect.width() : rect.height();
+ return orientation_ == Orientation::kHorizontal ? rect.width()
+ : rect.height();
}
int BoxLayout::MainAxisPosition(const gfx::Rect& rect) const {
- return orientation_ == kHorizontal ? rect.x() : rect.y();
+ return orientation_ == Orientation::kHorizontal ? rect.x() : rect.y();
}
void BoxLayout::SetMainAxisSize(int size, gfx::Rect* rect) const {
- if (orientation_ == kHorizontal)
+ if (orientation_ == Orientation::kHorizontal)
rect->set_width(size);
else
rect->set_height(size);
}
void BoxLayout::SetMainAxisPosition(int position, gfx::Rect* rect) const {
- if (orientation_ == kHorizontal)
+ if (orientation_ == Orientation::kHorizontal)
rect->set_x(position);
else
rect->set_y(position);
}
int BoxLayout::CrossAxisSize(const gfx::Rect& rect) const {
- return orientation_ == kVertical ? rect.width() : rect.height();
+ return orientation_ == Orientation::kVertical ? rect.width() : rect.height();
}
int BoxLayout::CrossAxisPosition(const gfx::Rect& rect) const {
- return orientation_ == kVertical ? rect.x() : rect.y();
+ return orientation_ == Orientation::kVertical ? rect.x() : rect.y();
}
void BoxLayout::SetCrossAxisSize(int size, gfx::Rect* rect) const {
- if (orientation_ == kVertical)
+ if (orientation_ == Orientation::kVertical)
rect->set_width(size);
else
rect->set_height(size);
}
void BoxLayout::SetCrossAxisPosition(int position, gfx::Rect* rect) const {
- if (orientation_ == kVertical)
+ if (orientation_ == Orientation::kVertical)
rect->set_x(position);
else
rect->set_y(position);
@@ -421,7 +424,7 @@ void BoxLayout::SetCrossAxisPosition(int position, gfx::Rect* rect) const {
int BoxLayout::MainAxisSizeForView(const ViewWrapper& view,
int child_area_width) const {
- return orientation_ == kHorizontal
+ return orientation_ == Orientation::kHorizontal
? view.GetPreferredSize().width()
: view.GetHeightForWidth(cross_axis_alignment_ ==
CrossAxisAlignment::kStretch
@@ -430,23 +433,26 @@ int BoxLayout::MainAxisSizeForView(const ViewWrapper& view,
}
int BoxLayout::MainAxisLeadingInset(const gfx::Insets& insets) const {
- return orientation_ == kHorizontal ? insets.left() : insets.top();
+ return orientation_ == Orientation::kHorizontal ? insets.left()
+ : insets.top();
}
int BoxLayout::MainAxisTrailingInset(const gfx::Insets& insets) const {
- return orientation_ == kHorizontal ? insets.right() : insets.bottom();
+ return orientation_ == Orientation::kHorizontal ? insets.right()
+ : insets.bottom();
}
int BoxLayout::CrossAxisLeadingEdge(const gfx::Rect& rect) const {
- return orientation_ == kVertical ? rect.x() : rect.y();
+ return orientation_ == Orientation::kVertical ? rect.x() : rect.y();
}
int BoxLayout::CrossAxisLeadingInset(const gfx::Insets& insets) const {
- return orientation_ == kVertical ? insets.left() : insets.top();
+ return orientation_ == Orientation::kVertical ? insets.left() : insets.top();
}
int BoxLayout::CrossAxisTrailingInset(const gfx::Insets& insets) const {
- return orientation_ == kVertical ? insets.right() : insets.bottom();
+ return orientation_ == Orientation::kVertical ? insets.right()
+ : insets.bottom();
}
int BoxLayout::MainAxisMarginBetweenViews(const ViewWrapper& leading,
@@ -462,15 +468,17 @@ gfx::Insets BoxLayout::MainAxisOuterMargin() const {
if (collapse_margins_spacing_) {
const ViewWrapper first(this, FirstVisibleView());
const ViewWrapper last(this, LastVisibleView());
- return MaxAxisInsets(
- orientation_ == kHorizontal ? HORIZONTAL_AXIS : VERTICAL_AXIS,
- inside_border_insets_, first.margins(), inside_border_insets_,
- last.margins());
+ return MaxAxisInsets(orientation_ == Orientation::kHorizontal
+ ? HORIZONTAL_AXIS
+ : VERTICAL_AXIS,
+ inside_border_insets_, first.margins(),
+ inside_border_insets_, last.margins());
}
- return MaxAxisInsets(
- orientation_ == kHorizontal ? HORIZONTAL_AXIS : VERTICAL_AXIS,
- inside_border_insets_, gfx::Insets(), inside_border_insets_,
- gfx::Insets());
+ return MaxAxisInsets(orientation_ == Orientation::kHorizontal
+ ? HORIZONTAL_AXIS
+ : VERTICAL_AXIS,
+ inside_border_insets_, gfx::Insets(),
+ inside_border_insets_, gfx::Insets());
}
gfx::Insets BoxLayout::CrossAxisMaxViewMargin() const {
@@ -503,15 +511,15 @@ void BoxLayout::AdjustCrossAxisForInsets(gfx::Rect* rect) const {
int BoxLayout::CrossAxisSizeForView(const ViewWrapper& view) const {
// TODO(bruthig): For horizontal case use the available width and not the
// preferred width. See https://crbug.com/682266.
- return orientation_ == kVertical
+ return orientation_ == Orientation::kVertical
? view.GetPreferredSize().width()
: view.GetHeightForWidth(view.GetPreferredSize().width());
}
int BoxLayout::CrossAxisMarginSizeForView(const ViewWrapper& view) const {
- return collapse_margins_spacing_
- ? 0
- : (orientation_ == kVertical ? view.margins().width()
+ return collapse_margins_spacing_ ? 0
+ : (orientation_ == Orientation::kVertical
+ ? view.margins().width()
: view.margins().height());
}
@@ -522,7 +530,7 @@ int BoxLayout::CrossAxisLeadingMarginForView(const ViewWrapper& view) const {
void BoxLayout::InsetCrossAxis(gfx::Rect* rect,
int leading,
int trailing) const {
- if (orientation_ == kVertical)
+ if (orientation_ == Orientation::kVertical)
rect->Inset(leading, 0, trailing, 0);
else
rect->Inset(0, leading, 0, trailing);
@@ -533,7 +541,7 @@ gfx::Size BoxLayout::GetPreferredSizeForChildWidth(const View* host,
DCHECK_EQ(host, host_);
gfx::Rect child_area_bounds;
- if (orientation_ == kHorizontal) {
+ if (orientation_ == Orientation::kHorizontal) {
// Horizontal layouts ignore |child_area_width|, meaning they mimic the
// default behavior of GridLayout::GetPreferredHeightForWidth().
// TODO(estade|bruthig): Fix this See // https://crbug.com/682266.
diff --git a/chromium/ui/views/layout/box_layout.h b/chromium/ui/views/layout/box_layout.h
index f91486cf76f..63567e762af 100644
--- a/chromium/ui/views/layout/box_layout.h
+++ b/chromium/ui/views/layout/box_layout.h
@@ -27,7 +27,7 @@ namespace views {
// Excess space will not be distributed.
class VIEWS_EXPORT BoxLayout : public LayoutManager {
public:
- enum Orientation {
+ enum class Orientation {
kHorizontal,
kVertical,
};
@@ -58,7 +58,7 @@ class VIEWS_EXPORT BoxLayout : public LayoutManager {
// Use |inside_border_insets| to add additional space between the child
// view area and the host view border. |between_child_spacing| controls the
// space in between child views. Use view->SetProperty(kMarginsKey,
- // new gfx::Insets(xxx)) to add additional margins on a per-view basis. The
+ // gfx::Insets(xxx)) to add additional margins on a per-view basis. The
// |collapse_margins_spacing| parameter controls whether or not adjacent
// spacing/margins are collapsed based on the max of the two values. For the
// cross axis, |collapse_margins_spacing| will collapse to the max of
diff --git a/chromium/ui/views/layout/box_layout_unittest.cc b/chromium/ui/views/layout/box_layout_unittest.cc
index 21e806582ec..9e7702f73aa 100644
--- a/chromium/ui/views/layout/box_layout_unittest.cc
+++ b/chromium/ui/views/layout/box_layout_unittest.cc
@@ -34,14 +34,14 @@ class BoxLayoutTest : public testing::Test {
} // namespace
TEST_F(BoxLayoutTest, Empty) {
- BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(10), 20));
+ BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kHorizontal, gfx::Insets(10), 20));
EXPECT_EQ(gfx::Size(20, 20), layout->GetPreferredSize(host_.get()));
}
TEST_F(BoxLayoutTest, AlignmentHorizontal) {
BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal));
+ std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal));
View* v1 = new StaticSizedView(gfx::Size(10, 20));
host_->AddChildView(v1);
View* v2 = new StaticSizedView(gfx::Size(10, 10));
@@ -55,7 +55,7 @@ TEST_F(BoxLayoutTest, AlignmentHorizontal) {
TEST_F(BoxLayoutTest, AlignmentVertical) {
BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kVertical));
+ std::make_unique<BoxLayout>(BoxLayout::Orientation::kVertical));
View* v1 = new StaticSizedView(gfx::Size(20, 10));
host_->AddChildView(v1);
View* v2 = new StaticSizedView(gfx::Size(10, 10));
@@ -68,8 +68,8 @@ TEST_F(BoxLayoutTest, AlignmentVertical) {
}
TEST_F(BoxLayoutTest, SetInsideBorderInsets) {
- BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(20, 10)));
+ BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kHorizontal, gfx::Insets(20, 10)));
View* v1 = new StaticSizedView(gfx::Size(10, 20));
host_->AddChildView(v1);
View* v2 = new StaticSizedView(gfx::Size(10, 10));
@@ -90,8 +90,8 @@ TEST_F(BoxLayoutTest, SetInsideBorderInsets) {
}
TEST_F(BoxLayoutTest, Spacing) {
- BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(7), 8));
+ BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kHorizontal, gfx::Insets(7), 8));
View* v1 = new StaticSizedView(gfx::Size(10, 20));
host_->AddChildView(v1);
View* v2 = new StaticSizedView(gfx::Size(10, 20));
@@ -105,7 +105,7 @@ TEST_F(BoxLayoutTest, Spacing) {
TEST_F(BoxLayoutTest, Overflow) {
BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal));
+ std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal));
View* v1 = new StaticSizedView(gfx::Size(20, 20));
host_->AddChildView(v1);
View* v2 = new StaticSizedView(gfx::Size(10, 20));
@@ -137,8 +137,8 @@ TEST_F(BoxLayoutTest, Overflow) {
}
TEST_F(BoxLayoutTest, NoSpace) {
- host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(10), 10));
+ host_->SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kHorizontal, gfx::Insets(10), 10));
View* childView = new StaticSizedView(gfx::Size(20, 20));
host_->AddChildView(childView);
host_->SetBounds(0, 0, 10, 10);
@@ -147,8 +147,8 @@ TEST_F(BoxLayoutTest, NoSpace) {
}
TEST_F(BoxLayoutTest, InvisibleChild) {
- BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(10), 10));
+ BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kHorizontal, gfx::Insets(10), 10));
View* v1 = new StaticSizedView(gfx::Size(20, 20));
v1->SetVisible(false);
host_->AddChildView(v1);
@@ -162,7 +162,7 @@ TEST_F(BoxLayoutTest, InvisibleChild) {
TEST_F(BoxLayoutTest, UseHeightForWidth) {
BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kVertical));
+ std::make_unique<BoxLayout>(BoxLayout::Orientation::kVertical));
View* v1 = new StaticSizedView(gfx::Size(20, 10));
host_->AddChildView(v1);
ProportionallySizedView* v2 = new ProportionallySizedView(2);
@@ -192,8 +192,9 @@ TEST_F(BoxLayoutTest, UseHeightForWidth) {
TEST_F(BoxLayoutTest, EmptyPreferredSize) {
for (size_t i = 0; i < 2; i++) {
- BoxLayout::Orientation orientation = i == 0 ? BoxLayout::kHorizontal :
- BoxLayout::kVertical;
+ BoxLayout::Orientation orientation =
+ i == 0 ? BoxLayout::Orientation::kHorizontal
+ : BoxLayout::Orientation::kVertical;
host_->RemoveAllChildViews(true);
host_->SetLayoutManager(
std::make_unique<BoxLayout>(orientation, gfx::Insets(), 5));
@@ -217,8 +218,8 @@ TEST_F(BoxLayoutTest, EmptyPreferredSize) {
// empty preferred size, simultaneously.
TEST_F(BoxLayoutTest, EmptyPreferredSizeWithFlexLayoutAndChildSpacing) {
host_->RemoveAllChildViews(true);
- BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(), 5));
+ BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kHorizontal, gfx::Insets(), 5));
View* v1 = new StaticSizedView(gfx::Size());
host_->AddChildView(v1);
View* v2 = new StaticSizedView(gfx::Size(10, 10));
@@ -233,8 +234,8 @@ TEST_F(BoxLayoutTest, EmptyPreferredSizeWithFlexLayoutAndChildSpacing) {
}
TEST_F(BoxLayoutTest, MainAxisAlignmentHorizontal) {
- BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(10), 10));
+ BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kHorizontal, gfx::Insets(10), 10));
View* v1 = new StaticSizedView(gfx::Size(20, 20));
host_->AddChildView(v1);
@@ -269,8 +270,8 @@ TEST_F(BoxLayoutTest, MainAxisAlignmentHorizontal) {
}
TEST_F(BoxLayoutTest, MainAxisAlignmentVertical) {
- BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kVertical, gfx::Insets(10), 10));
+ BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kVertical, gfx::Insets(10), 10));
View* v1 = new StaticSizedView(gfx::Size(20, 20));
host_->AddChildView(v1);
@@ -305,8 +306,8 @@ TEST_F(BoxLayoutTest, MainAxisAlignmentVertical) {
}
TEST_F(BoxLayoutTest, CrossAxisAlignmentHorizontal) {
- BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(10), 10));
+ BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kHorizontal, gfx::Insets(10), 10));
View* v1 = new StaticSizedView(gfx::Size(20, 20));
host_->AddChildView(v1);
@@ -347,8 +348,8 @@ TEST_F(BoxLayoutTest, CrossAxisAlignmentHorizontal) {
}
TEST_F(BoxLayoutTest, CrossAxisAlignmentVertical) {
- BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kVertical, gfx::Insets(10), 10));
+ BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kVertical, gfx::Insets(10), 10));
View* v1 = new StaticSizedView(gfx::Size(20, 20));
host_->AddChildView(v1);
@@ -389,8 +390,8 @@ TEST_F(BoxLayoutTest, CrossAxisAlignmentVertical) {
}
TEST_F(BoxLayoutTest, FlexAll) {
- BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(10), 10));
+ BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kHorizontal, gfx::Insets(10), 10));
layout->SetDefaultFlex(1);
View* v1 = new StaticSizedView(gfx::Size(20, 20));
@@ -409,8 +410,8 @@ TEST_F(BoxLayoutTest, FlexAll) {
}
TEST_F(BoxLayoutTest, FlexGrowVertical) {
- BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kVertical, gfx::Insets(10), 10));
+ BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kVertical, gfx::Insets(10), 10));
View* v1 = new StaticSizedView(gfx::Size(20, 20));
host_->AddChildView(v1);
@@ -462,7 +463,7 @@ TEST_F(BoxLayoutTest, FlexGrowVertical) {
TEST_F(BoxLayoutTest, FlexGrowHorizontalWithRemainder) {
BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal));
+ std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal));
layout->SetDefaultFlex(1);
std::vector<View*> views;
for (int i = 0; i < 5; ++i) {
@@ -486,7 +487,7 @@ TEST_F(BoxLayoutTest, FlexGrowHorizontalWithRemainder) {
TEST_F(BoxLayoutTest, FlexGrowHorizontalWithRemainder2) {
BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal));
+ std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal));
layout->SetDefaultFlex(1);
std::vector<View*> views;
for (int i = 0; i < 4; ++i) {
@@ -508,8 +509,8 @@ TEST_F(BoxLayoutTest, FlexGrowHorizontalWithRemainder2) {
}
TEST_F(BoxLayoutTest, FlexShrinkHorizontal) {
- BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets(10), 10));
+ BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kHorizontal, gfx::Insets(10), 10));
View* v1 = new StaticSizedView(gfx::Size(20, 20));
host_->AddChildView(v1);
@@ -563,7 +564,7 @@ TEST_F(BoxLayoutTest, FlexShrinkHorizontal) {
TEST_F(BoxLayoutTest, FlexShrinkVerticalWithRemainder) {
BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kVertical));
+ std::make_unique<BoxLayout>(BoxLayout::Orientation::kVertical));
View* v1 = new StaticSizedView(gfx::Size(20, 10));
host_->AddChildView(v1);
View* v2 = new StaticSizedView(gfx::Size(20, 20));
@@ -608,7 +609,7 @@ TEST_F(BoxLayoutTest, FlexShrinkVerticalWithRemainder) {
TEST_F(BoxLayoutTest, MinimumCrossAxisVertical) {
BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kVertical));
+ std::make_unique<BoxLayout>(BoxLayout::Orientation::kVertical));
View* v1 = new StaticSizedView(gfx::Size(20, 10));
host_->AddChildView(v1);
layout->set_minimum_cross_axis_size(30);
@@ -618,7 +619,7 @@ TEST_F(BoxLayoutTest, MinimumCrossAxisVertical) {
TEST_F(BoxLayoutTest, MinimumCrossAxisHorizontal) {
BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal));
+ std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal));
View* v1 = new StaticSizedView(gfx::Size(20, 10));
host_->AddChildView(v1);
layout->set_minimum_cross_axis_size(30);
@@ -628,12 +629,12 @@ TEST_F(BoxLayoutTest, MinimumCrossAxisHorizontal) {
TEST_F(BoxLayoutTest, MarginsUncollapsedHorizontal) {
BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal));
+ std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal));
View* v1 = new StaticSizedView(gfx::Size(20, 10));
- v1->SetProperty(kMarginsKey, new gfx::Insets(5, 5, 5, 5));
+ v1->SetProperty(kMarginsKey, gfx::Insets(5, 5, 5, 5));
host_->AddChildView(v1);
View* v2 = new StaticSizedView(gfx::Size(20, 10));
- v2->SetProperty(kMarginsKey, new gfx::Insets(6, 4, 6, 4));
+ v2->SetProperty(kMarginsKey, gfx::Insets(6, 4, 6, 4));
host_->AddChildView(v2);
EXPECT_EQ(gfx::Size(58, 22), layout->GetPreferredSize(host_.get()));
@@ -645,12 +646,12 @@ TEST_F(BoxLayoutTest, MarginsUncollapsedHorizontal) {
TEST_F(BoxLayoutTest, MarginsCollapsedHorizontal) {
BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
- BoxLayout::kHorizontal, gfx::Insets(0, 0), 0, true));
+ BoxLayout::Orientation::kHorizontal, gfx::Insets(0, 0), 0, true));
View* v1 = new StaticSizedView(gfx::Size(20, 10));
- v1->SetProperty(kMarginsKey, new gfx::Insets(5, 5, 5, 5));
+ v1->SetProperty(kMarginsKey, gfx::Insets(5, 5, 5, 5));
host_->AddChildView(v1);
View* v2 = new StaticSizedView(gfx::Size(20, 10));
- v2->SetProperty(kMarginsKey, new gfx::Insets(6, 4, 6, 4));
+ v2->SetProperty(kMarginsKey, gfx::Insets(6, 4, 6, 4));
host_->AddChildView(v2);
EXPECT_EQ(gfx::Size(54, 22), layout->GetPreferredSize(host_.get()));
@@ -662,12 +663,12 @@ TEST_F(BoxLayoutTest, MarginsCollapsedHorizontal) {
TEST_F(BoxLayoutTest, MarginsUncollapsedVertical) {
BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kVertical));
+ std::make_unique<BoxLayout>(BoxLayout::Orientation::kVertical));
View* v1 = new StaticSizedView(gfx::Size(20, 10));
- v1->SetProperty(kMarginsKey, new gfx::Insets(5, 5, 5, 5));
+ v1->SetProperty(kMarginsKey, gfx::Insets(5, 5, 5, 5));
host_->AddChildView(v1);
View* v2 = new StaticSizedView(gfx::Size(20, 10));
- v2->SetProperty(kMarginsKey, new gfx::Insets(6, 4, 6, 4));
+ v2->SetProperty(kMarginsKey, gfx::Insets(6, 4, 6, 4));
host_->AddChildView(v2);
EXPECT_EQ(gfx::Size(30, 42), layout->GetPreferredSize(host_.get()));
@@ -679,12 +680,12 @@ TEST_F(BoxLayoutTest, MarginsUncollapsedVertical) {
TEST_F(BoxLayoutTest, MarginsCollapsedVertical) {
BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
- BoxLayout::kVertical, gfx::Insets(0, 0), 0, true));
+ BoxLayout::Orientation::kVertical, gfx::Insets(0, 0), 0, true));
View* v1 = new StaticSizedView(gfx::Size(20, 10));
- v1->SetProperty(kMarginsKey, new gfx::Insets(5, 5, 5, 5));
+ v1->SetProperty(kMarginsKey, gfx::Insets(5, 5, 5, 5));
host_->AddChildView(v1);
View* v2 = new StaticSizedView(gfx::Size(20, 10));
- v2->SetProperty(kMarginsKey, new gfx::Insets(6, 4, 6, 4));
+ v2->SetProperty(kMarginsKey, gfx::Insets(6, 4, 6, 4));
host_->AddChildView(v2);
EXPECT_EQ(gfx::Size(30, 37), layout->GetPreferredSize(host_.get()));
@@ -695,15 +696,16 @@ TEST_F(BoxLayoutTest, MarginsCollapsedVertical) {
}
TEST_F(BoxLayoutTest, UnbalancedMarginsUncollapsedHorizontal) {
- auto layout_owner = std::make_unique<BoxLayout>(BoxLayout::kHorizontal);
+ auto layout_owner =
+ std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal);
layout_owner->set_cross_axis_alignment(
BoxLayout::CrossAxisAlignment::kCenter);
BoxLayout* layout = host_->SetLayoutManager(std::move(layout_owner));
View* v1 = new StaticSizedView(gfx::Size(20, 10));
- v1->SetProperty(kMarginsKey, new gfx::Insets(5, 5, 4, 4));
+ v1->SetProperty(kMarginsKey, gfx::Insets(5, 5, 4, 4));
host_->AddChildView(v1);
View* v2 = new StaticSizedView(gfx::Size(20, 10));
- v2->SetProperty(kMarginsKey, new gfx::Insets(6, 4, 3, 6));
+ v2->SetProperty(kMarginsKey, gfx::Insets(6, 4, 3, 6));
host_->AddChildView(v2);
EXPECT_EQ(gfx::Size(59, 20), layout->GetPreferredSize(host_.get()));
@@ -714,16 +716,16 @@ TEST_F(BoxLayoutTest, UnbalancedMarginsUncollapsedHorizontal) {
}
TEST_F(BoxLayoutTest, UnbalancedMarginsCollapsedHorizontal) {
- auto layout_owner = std::make_unique<BoxLayout>(BoxLayout::kHorizontal,
- gfx::Insets(0, 0), 0, true);
+ auto layout_owner = std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kHorizontal, gfx::Insets(0, 0), 0, true);
layout_owner->set_cross_axis_alignment(
BoxLayout::CrossAxisAlignment::kCenter);
BoxLayout* layout = host_->SetLayoutManager(std::move(layout_owner));
View* v1 = new StaticSizedView(gfx::Size(20, 10));
- v1->SetProperty(kMarginsKey, new gfx::Insets(5, 5, 4, 4));
+ v1->SetProperty(kMarginsKey, gfx::Insets(5, 5, 4, 4));
host_->AddChildView(v1);
View* v2 = new StaticSizedView(gfx::Size(20, 10));
- v2->SetProperty(kMarginsKey, new gfx::Insets(6, 4, 3, 6));
+ v2->SetProperty(kMarginsKey, gfx::Insets(6, 4, 3, 6));
host_->AddChildView(v2);
EXPECT_EQ(gfx::Size(55, 20), layout->GetPreferredSize(host_.get()));
@@ -734,15 +736,16 @@ TEST_F(BoxLayoutTest, UnbalancedMarginsCollapsedHorizontal) {
}
TEST_F(BoxLayoutTest, UnbalancedMarginsUncollapsedVertical) {
- auto layout_owner = std::make_unique<BoxLayout>(BoxLayout::kVertical);
+ auto layout_owner =
+ std::make_unique<BoxLayout>(BoxLayout::Orientation::kVertical);
layout_owner->set_cross_axis_alignment(
BoxLayout::CrossAxisAlignment::kCenter);
BoxLayout* layout = host_->SetLayoutManager(std::move(layout_owner));
View* v1 = new StaticSizedView(gfx::Size(20, 10));
- v1->SetProperty(kMarginsKey, new gfx::Insets(4, 5, 5, 3));
+ v1->SetProperty(kMarginsKey, gfx::Insets(4, 5, 5, 3));
host_->AddChildView(v1);
View* v2 = new StaticSizedView(gfx::Size(20, 10));
- v2->SetProperty(kMarginsKey, new gfx::Insets(6, 4, 3, 5));
+ v2->SetProperty(kMarginsKey, gfx::Insets(6, 4, 3, 5));
host_->AddChildView(v2);
EXPECT_EQ(gfx::Size(30, 38), layout->GetPreferredSize(host_.get()));
@@ -753,16 +756,16 @@ TEST_F(BoxLayoutTest, UnbalancedMarginsUncollapsedVertical) {
}
TEST_F(BoxLayoutTest, UnbalancedMarginsCollapsedVertical) {
- auto layout_owner = std::make_unique<BoxLayout>(BoxLayout::kVertical,
- gfx::Insets(0, 0), 0, true);
+ auto layout_owner = std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kVertical, gfx::Insets(0, 0), 0, true);
layout_owner->set_cross_axis_alignment(
BoxLayout::CrossAxisAlignment::kCenter);
BoxLayout* layout = host_->SetLayoutManager(std::move(layout_owner));
View* v1 = new StaticSizedView(gfx::Size(20, 10));
- v1->SetProperty(kMarginsKey, new gfx::Insets(4, 5, 5, 3));
+ v1->SetProperty(kMarginsKey, gfx::Insets(4, 5, 5, 3));
host_->AddChildView(v1);
View* v2 = new StaticSizedView(gfx::Size(20, 10));
- v2->SetProperty(kMarginsKey, new gfx::Insets(6, 4, 3, 5));
+ v2->SetProperty(kMarginsKey, gfx::Insets(6, 4, 3, 5));
host_->AddChildView(v2);
EXPECT_EQ(gfx::Size(30, 33), layout->GetPreferredSize(host_.get()));
@@ -775,13 +778,13 @@ TEST_F(BoxLayoutTest, UnbalancedMarginsCollapsedVertical) {
TEST_F(BoxLayoutTest, OverlappingCrossMarginsAlignEnd) {
{
BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal));
+ std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal));
layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kEnd);
View* v1 = new StaticSizedView(gfx::Size(20, 4));
- v1->SetProperty(kMarginsKey, new gfx::Insets(3, 0, 0, 0));
+ v1->SetProperty(kMarginsKey, gfx::Insets(3, 0, 0, 0));
host_->AddChildView(v1);
View* v2 = new StaticSizedView(gfx::Size(20, 5));
- v2->SetProperty(kMarginsKey, new gfx::Insets(0, 0, 2, 0));
+ v2->SetProperty(kMarginsKey, gfx::Insets(0, 0, 2, 0));
host_->AddChildView(v2);
EXPECT_EQ(9, layout->GetPreferredSize(host_.get()).height());
@@ -789,13 +792,13 @@ TEST_F(BoxLayoutTest, OverlappingCrossMarginsAlignEnd) {
host_->RemoveAllChildViews(true);
{
BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
- BoxLayout::kHorizontal, gfx::Insets(0, 0), 0, true));
+ BoxLayout::Orientation::kHorizontal, gfx::Insets(0, 0), 0, true));
layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kEnd);
View* v1 = new StaticSizedView(gfx::Size(20, 4));
- v1->SetProperty(kMarginsKey, new gfx::Insets(3, 0, 0, 0));
+ v1->SetProperty(kMarginsKey, gfx::Insets(3, 0, 0, 0));
host_->AddChildView(v1);
View* v2 = new StaticSizedView(gfx::Size(20, 5));
- v2->SetProperty(kMarginsKey, new gfx::Insets(0, 0, 2, 0));
+ v2->SetProperty(kMarginsKey, gfx::Insets(0, 0, 2, 0));
host_->AddChildView(v2);
EXPECT_EQ(9, layout->GetPreferredSize(host_.get()).height());
@@ -805,13 +808,13 @@ TEST_F(BoxLayoutTest, OverlappingCrossMarginsAlignEnd) {
TEST_F(BoxLayoutTest, OverlappingCrossMarginsAlignStretch) {
{
BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal));
+ std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal));
layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kStretch);
View* v1 = new StaticSizedView(gfx::Size(20, 4));
- v1->SetProperty(kMarginsKey, new gfx::Insets(3, 0, 0, 0));
+ v1->SetProperty(kMarginsKey, gfx::Insets(3, 0, 0, 0));
host_->AddChildView(v1);
View* v2 = new StaticSizedView(gfx::Size(20, 5));
- v2->SetProperty(kMarginsKey, new gfx::Insets(0, 0, 2, 0));
+ v2->SetProperty(kMarginsKey, gfx::Insets(0, 0, 2, 0));
host_->AddChildView(v2);
EXPECT_EQ(10, layout->GetPreferredSize(host_.get()).height());
@@ -819,13 +822,13 @@ TEST_F(BoxLayoutTest, OverlappingCrossMarginsAlignStretch) {
host_->RemoveAllChildViews(true);
{
BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
- BoxLayout::kHorizontal, gfx::Insets(0, 0), 0, true));
+ BoxLayout::Orientation::kHorizontal, gfx::Insets(0, 0), 0, true));
layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kStretch);
View* v1 = new StaticSizedView(gfx::Size(20, 4));
- v1->SetProperty(kMarginsKey, new gfx::Insets(3, 0, 0, 0));
+ v1->SetProperty(kMarginsKey, gfx::Insets(3, 0, 0, 0));
host_->AddChildView(v1);
View* v2 = new StaticSizedView(gfx::Size(20, 5));
- v2->SetProperty(kMarginsKey, new gfx::Insets(0, 0, 2, 0));
+ v2->SetProperty(kMarginsKey, gfx::Insets(0, 0, 2, 0));
host_->AddChildView(v2);
EXPECT_EQ(10, layout->GetPreferredSize(host_.get()).height());
@@ -835,13 +838,13 @@ TEST_F(BoxLayoutTest, OverlappingCrossMarginsAlignStretch) {
TEST_F(BoxLayoutTest, OverlappingCrossMarginsAlignStart) {
{
BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal));
+ std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal));
layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kStart);
View* v1 = new StaticSizedView(gfx::Size(20, 4));
- v1->SetProperty(kMarginsKey, new gfx::Insets(0, 0, 3, 0));
+ v1->SetProperty(kMarginsKey, gfx::Insets(0, 0, 3, 0));
host_->AddChildView(v1);
View* v2 = new StaticSizedView(gfx::Size(20, 5));
- v2->SetProperty(kMarginsKey, new gfx::Insets(2, 0, 0, 0));
+ v2->SetProperty(kMarginsKey, gfx::Insets(2, 0, 0, 0));
host_->AddChildView(v2);
EXPECT_EQ(9, layout->GetPreferredSize(host_.get()).height());
@@ -849,13 +852,13 @@ TEST_F(BoxLayoutTest, OverlappingCrossMarginsAlignStart) {
host_->RemoveAllChildViews(true);
{
BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
- BoxLayout::kHorizontal, gfx::Insets(0, 0), 0, true));
+ BoxLayout::Orientation::kHorizontal, gfx::Insets(0, 0), 0, true));
layout->set_cross_axis_alignment(BoxLayout::CrossAxisAlignment::kStart);
View* v1 = new StaticSizedView(gfx::Size(20, 4));
- v1->SetProperty(kMarginsKey, new gfx::Insets(0, 0, 3, 0));
+ v1->SetProperty(kMarginsKey, gfx::Insets(0, 0, 3, 0));
host_->AddChildView(v1);
View* v2 = new StaticSizedView(gfx::Size(20, 5));
- v2->SetProperty(kMarginsKey, new gfx::Insets(2, 0, 0, 0));
+ v2->SetProperty(kMarginsKey, gfx::Insets(2, 0, 0, 0));
host_->AddChildView(v2);
EXPECT_EQ(9, layout->GetPreferredSize(host_.get()).height());
@@ -863,8 +866,8 @@ TEST_F(BoxLayoutTest, OverlappingCrossMarginsAlignStart) {
}
TEST_F(BoxLayoutTest, NegativeBetweenChildSpacing) {
- BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kVertical, gfx::Insets(), -10));
+ BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kVertical, gfx::Insets(), -10));
View* v1 = new StaticSizedView(gfx::Size(20, 20));
host_->AddChildView(v1);
View* v2 = new StaticSizedView(gfx::Size(20, 15));
@@ -879,8 +882,8 @@ TEST_F(BoxLayoutTest, NegativeBetweenChildSpacing) {
}
TEST_F(BoxLayoutTest, MinimumChildSize) {
- BoxLayout* layout = host_->SetLayoutManager(
- std::make_unique<BoxLayout>(BoxLayout::kHorizontal, gfx::Insets()));
+ BoxLayout* layout = host_->SetLayoutManager(std::make_unique<BoxLayout>(
+ BoxLayout::Orientation::kHorizontal, gfx::Insets()));
StaticSizedView* v1 = new StaticSizedView(gfx::Size(20, 20));
host_->AddChildView(v1);
StaticSizedView* v2 = new StaticSizedView(gfx::Size(20, 20));
diff --git a/chromium/ui/views/layout/flex_layout.cc b/chromium/ui/views/layout/flex_layout.cc
index b8e2d10255e..91ad5ce2669 100644
--- a/chromium/ui/views/layout/flex_layout.cc
+++ b/chromium/ui/views/layout/flex_layout.cc
@@ -28,131 +28,57 @@
namespace views {
-namespace internal {
+using internal::NormalizedInsets;
+using internal::NormalizedPoint;
+using internal::NormalizedRect;
+using internal::NormalizedSize;
+using internal::NormalizedSizeBounds;
+
+using internal::Denormalize;
+using internal::Normalize;
namespace {
// Layout information for a specific child view in a proposed layout.
-struct ChildLayout {
- ChildLayout(View* view, const FlexSpecification& flex)
- : view(view), flex(flex) {}
- ChildLayout(ChildLayout&& other) = default;
-
- View* view = nullptr;
- bool excluded = false;
- // Indicates whether external code has called SetVisible(false) on the view.
- bool hidden_by_owner = false;
- // Indicates whether the layout has chosen to display this child view.
- bool visible = false;
+struct FlexChildData {
+ explicit FlexChildData(const FlexSpecification& flex) : flex(flex) {}
+ FlexChildData(FlexChildData&& other) = default;
+
// Start with zero size rather than unspecified size bounds because we start
// all layouts with controls at their minimum allowed sizes.
NormalizedSizeBounds available_size{0, 0};
NormalizedSize preferred_size;
NormalizedSize current_size;
- NormalizedRect actual_bounds;
NormalizedInsets margins;
NormalizedInsets internal_padding;
+ NormalizedRect actual_bounds;
FlexSpecification flex;
private:
// Copying this struct would be expensive and they only ever live in a vector
// in Layout (see below) so we'll only allow move semantics.
- DISALLOW_COPY_AND_ASSIGN(ChildLayout);
+ DISALLOW_COPY_AND_ASSIGN(FlexChildData);
};
-// Represents a specific stored layout given a set of size bounds.
-struct Layout {
- explicit Layout(int64_t layout_counter) : layout_id(layout_counter) {}
-
- // Indicates which layout pass this layout was created/last validated on. If
- // this number disagrees with FlexLayoutInternal::layout_counter_, we need to
- // re-validate the layout before using it.
- mutable uint32_t layout_id;
- std::vector<ChildLayout> child_layouts;
- NormalizedInsets interior_margin;
- NormalizedSizeBounds available_size;
- NormalizedSize total_size;
-
- private:
- DISALLOW_COPY_AND_ASSIGN(Layout);
-};
-
-// Preserves layouts for common layout requests, because we may be asked to
-// recompute them many times but don't want to repeat the calculation.
-//
-// Specifically, we will be asked for:
-// - The layout's minimum size (bounds = {0, 0})
-// - The layout's preferred size (neither bound specified)
-// - The final layout at the dimensions of the host view (both bounds nonzero)
-//
-// There is also the possibility of a view with a flex layout being embedded in
-// a view with a flex layout, where the inner view has a nontrivial flex
-// specification. In that case, in order to handle e.g. labels in the inner
-// view, the outer layout manager will ask for the inner view's preferred height
-// for its width, which potentially involves another layout calculation.
-// However, these calculations are transient - they only happen when the layout
-// is recalculated or validated, and in the latter case only one set of bounds
-// is evaluated. So we will keep exactly one of these layouts around.
-//
-// As a first pass, we'll store all of these specifically. In the future we can
-// switch to using something more sophisticated, like an MRU cache, if we find
-// we're thrashing for some other reason.
-class LayoutCache {
- public:
- // Removes all saved layouts.
- void Clear() {
- minimum_.reset();
- preferred_.reset();
- intermediate_.layout.reset();
- current_.layout.reset();
- }
-
- // Gets a cached layout, or nullptr if no layout is cached for the specified
- // bounds.
- Layout* Get(const NormalizedSizeBounds& bounds) const {
- if (bounds == NormalizedSizeBounds(0, 0))
- return minimum_.get();
- if (bounds == NormalizedSizeBounds())
- return preferred_.get();
- if (bounds == intermediate_.bounds)
- return intermediate_.layout.get();
- if (bounds == current_.bounds)
- return current_.layout.get();
- return nullptr;
- }
+template <typename T>
+T GetViewProperty(const View* view,
+ const ui::PropertyHandler& defaults,
+ const ui::ClassProperty<T*>* property) {
+ T* found_value = view->GetProperty(property);
+ if (found_value)
+ return *found_value;
+ found_value = defaults.GetProperty(property);
+ if (found_value)
+ return *found_value;
+ return T();
+}
- // Caches a layout associated with the specified bounds.
- void Put(const NormalizedSizeBounds& bounds, std::unique_ptr<Layout> layout) {
- if (bounds == NormalizedSizeBounds(0, 0)) {
- minimum_ = std::move(layout);
- } else if (bounds == NormalizedSizeBounds()) {
- preferred_ = std::move(layout);
- } else if (!bounds.cross() || !bounds.main()) {
- intermediate_.bounds = bounds;
- intermediate_.layout = std::move(layout);
- } else {
- current_.bounds = bounds;
- current_.layout = std::move(layout);
- }
- }
+} // anonymous namespace
- private:
- struct CacheEntry {
- NormalizedSizeBounds bounds;
- std::unique_ptr<Layout> layout;
- };
-
- std::unique_ptr<Layout> minimum_;
- std::unique_ptr<Layout> preferred_;
-
- // TODO(dfried): consider replacing these with an MRUCache if this ends up
- // thrashing a lot (see note above).
- CacheEntry intermediate_;
- CacheEntry current_;
-};
+// Private implementation ------------------------------------------------------
// Calculates and maintains 1D spacing between a sequence of child views.
-class ChildViewSpacing {
+class FlexLayout::ChildViewSpacing {
public:
// Given the indices of two child views, returns the amount of space that
// should be placed between them if they were adjacent. If the first index is
@@ -195,16 +121,18 @@ class ChildViewSpacing {
int trailing_space_;
};
-ChildViewSpacing::ChildViewSpacing(GetViewSpacingCallback get_view_spacing)
+FlexLayout::ChildViewSpacing::ChildViewSpacing(
+ GetViewSpacingCallback get_view_spacing)
: get_view_spacing_(std::move(get_view_spacing)),
trailing_space_(get_view_spacing_.Run(base::nullopt, base::nullopt)) {}
-ChildViewSpacing::ChildViewSpacing(ChildViewSpacing&& other)
+FlexLayout::ChildViewSpacing::ChildViewSpacing(ChildViewSpacing&& other)
: get_view_spacing_(std::move(other.get_view_spacing_)),
leading_spacings_(std::move(other.leading_spacings_)),
trailing_space_(other.trailing_space_) {}
-ChildViewSpacing& ChildViewSpacing::operator=(ChildViewSpacing&& other) {
+FlexLayout::ChildViewSpacing& FlexLayout::ChildViewSpacing::operator=(
+ ChildViewSpacing&& other) {
if (this != &other) {
get_view_spacing_ = std::move(other.get_view_spacing_);
leading_spacings_ = std::move(other.leading_spacings_);
@@ -213,33 +141,33 @@ ChildViewSpacing& ChildViewSpacing::operator=(ChildViewSpacing&& other) {
return *this;
}
-bool ChildViewSpacing::HasViewIndex(size_t view_index) const {
+bool FlexLayout::ChildViewSpacing::HasViewIndex(size_t view_index) const {
return leading_spacings_.find(view_index) != leading_spacings_.end();
}
-int ChildViewSpacing::GetLeadingInset() const {
+int FlexLayout::ChildViewSpacing::GetLeadingInset() const {
if (leading_spacings_.empty())
return 0;
return leading_spacings_.begin()->second;
}
-int ChildViewSpacing::GetTrailingInset() const {
+int FlexLayout::ChildViewSpacing::GetTrailingInset() const {
return trailing_space_;
}
-int ChildViewSpacing::GetLeadingSpace(size_t view_index) const {
+int FlexLayout::ChildViewSpacing::GetLeadingSpace(size_t view_index) const {
auto it = leading_spacings_.find(view_index);
DCHECK(it != leading_spacings_.end());
return it->second;
}
-int ChildViewSpacing::GetTotalSpace() const {
+int FlexLayout::ChildViewSpacing::GetTotalSpace() const {
return std::accumulate(
leading_spacings_.cbegin(), leading_spacings_.cend(), trailing_space_,
[](int total, const auto& value) { return total + value.second; });
}
-int ChildViewSpacing::GetAddDelta(size_t view_index) const {
+int FlexLayout::ChildViewSpacing::GetAddDelta(size_t view_index) const {
DCHECK(!HasViewIndex(view_index));
base::Optional<size_t> prev = GetPreviousViewIndex(view_index);
base::Optional<size_t> next = GetNextViewIndex(view_index);
@@ -249,9 +177,9 @@ int ChildViewSpacing::GetAddDelta(size_t view_index) const {
return new_spacing - old_spacing;
}
-void ChildViewSpacing::AddViewIndex(size_t view_index,
- int* new_leading,
- int* new_trailing) {
+void FlexLayout::ChildViewSpacing::AddViewIndex(size_t view_index,
+ int* new_leading,
+ int* new_trailing) {
DCHECK(!HasViewIndex(view_index));
base::Optional<size_t> prev = GetPreviousViewIndex(view_index);
base::Optional<size_t> next = GetNextViewIndex(view_index);
@@ -270,7 +198,7 @@ void ChildViewSpacing::AddViewIndex(size_t view_index,
*new_trailing = trailing_space;
}
-base::Optional<size_t> ChildViewSpacing::GetPreviousViewIndex(
+base::Optional<size_t> FlexLayout::ChildViewSpacing::GetPreviousViewIndex(
size_t view_index) const {
const auto it = leading_spacings_.lower_bound(view_index);
if (it == leading_spacings_.begin())
@@ -278,7 +206,7 @@ base::Optional<size_t> ChildViewSpacing::GetPreviousViewIndex(
return std::prev(it)->first;
}
-base::Optional<size_t> ChildViewSpacing::GetNextViewIndex(
+base::Optional<size_t> FlexLayout::ChildViewSpacing::GetNextViewIndex(
size_t view_index) const {
const auto it = leading_spacings_.upper_bound(view_index);
if (it == leading_spacings_.end())
@@ -286,153 +214,210 @@ base::Optional<size_t> ChildViewSpacing::GetNextViewIndex(
return it->first;
}
-// Utility functions -----------------------------------------------------------
+// Represents a specific stored layout given a set of size bounds.
+struct FlexLayout::FlexLayoutData {
+ FlexLayoutData() {}
+ ~FlexLayoutData() = default;
-gfx::Insets GetInternalPadding(const View* view) {
- const gfx::Insets* const margins =
- view->GetProperty(views::kInternalPaddingKey);
- return margins ? *margins : gfx::Insets();
-}
+ size_t num_children() const { return child_data.size(); }
-} // anonymous namespace
+ ProposedLayout layout;
-// Private implementation ------------------------------------------------------
+ // Holds additional information about the child views of this layout.
+ std::vector<FlexChildData> child_data;
+
+ // The total size of the layout (minus parent insets).
+ NormalizedSize total_size;
+ NormalizedInsets interior_margin;
+ NormalizedInsets host_insets;
-// Holds child-view-specific layout parameters that are not stored in the
-// properties system.
-//
-// We should consider storing some or all of these in the properites system.
-struct ChildLayoutParams {
- bool excluded = false;
- bool hidden_by_owner = false;
- base::Optional<FlexSpecification> flex_specification;
+ private:
+ DISALLOW_COPY_AND_ASSIGN(FlexLayoutData);
};
-// Internal data structure and functionality for FlexLayout so we don't have to
-// declare a bunch of classes and data in the .h file.
-class FlexLayoutInternal {
- public:
- explicit FlexLayoutInternal(FlexLayout* layout)
- : layout_(*layout) {} //, cached_layouts_(kMaxCachedLayouts) {}
+FlexLayout::PropertyHandler::PropertyHandler(FlexLayout* layout)
+ : layout_(layout) {}
- // Suggests that the current layout needs to be recalculated. Setting |force|
- // to true indicates that we know all of the cached layouts are invalid and we
- // should discard them; otherwise we will keep them and re-validate on the
- // next layout pass.
- void InvalidateLayout(bool force);
+void FlexLayout::PropertyHandler::AfterPropertyChange(const void* key,
+ int64_t old_value) {
+ layout_->InvalidateLayout();
+}
- // Gets the proposed layout for a set of size bounds. Returns a cached layout
- // if one is present and valid.
- const Layout& CalculateLayout(const SizeBounds& bounds);
+// FlexLayout
+// -------------------------------------------------------------------
- // Applies an existing layout to all child views, with the appropriate
- // current alignment.
- void DoLayout(const Layout& layout, const gfx::Rect& bounds);
+FlexLayout::FlexLayout() {}
+FlexLayout::~FlexLayout() = default;
- private:
- // Maps a flex order (lower = allocated first, and therefore higher priority)
- // to the indices of child views within that order that can flex.
- // See FlexSpecification::order().
- using FlexOrderToViewIndexMap = std::map<int, std::vector<size_t>>;
+FlexLayout& FlexLayout::SetOrientation(LayoutOrientation orientation) {
+ if (orientation != orientation_) {
+ orientation_ = orientation;
+ InvalidateLayout();
+ }
+ return *this;
+}
- LayoutOrientation orientation() const { return layout_.orientation(); }
+FlexLayout& FlexLayout::SetCollapseMargins(bool collapse_margins) {
+ if (collapse_margins != collapse_margins_) {
+ collapse_margins_ = collapse_margins;
+ InvalidateLayout();
+ }
+ return *this;
+}
- // Determines whether a layout is still valid.
- bool IsLayoutValid(const Layout& cached_layout) const;
+FlexLayout& FlexLayout::SetMainAxisAlignment(
+ LayoutAlignment main_axis_alignment) {
+ DCHECK_NE(main_axis_alignment, LayoutAlignment::kStretch)
+ << "Main axis stretch/justify is not yet supported.";
+ if (main_axis_alignment_ != main_axis_alignment) {
+ main_axis_alignment_ = main_axis_alignment;
+ InvalidateLayout();
+ }
+ return *this;
+}
- // Creates a brand new layout from the available |bounds|.
- // Call DoLayout() to actually apply the layout.
- const Layout& CalculateNewLayout(const NormalizedSizeBounds& bounds);
+FlexLayout& FlexLayout::SetCrossAxisAlignment(
+ LayoutAlignment cross_axis_alignment) {
+ if (cross_axis_alignment_ != cross_axis_alignment) {
+ cross_axis_alignment_ = cross_axis_alignment;
+ InvalidateLayout();
+ }
+ return *this;
+}
- // Applies flex rules to each view in a layout, updating |layout| and
- // |child_spacing|.
- //
- // If |expandable_views| is specified, any view requesting more than its
- // preferred size will be clamped to its preferred size and be added to
- // |expandable_views| for later processing after all other flex space has been
- // allocated.
- //
- // Typically, this method will be called once with |expandable_views| set and
- // then again with it null to allocate the remaining space.
- void AllocateFlexSpace(
- Layout* layout,
- ChildViewSpacing* child_spacing,
- const NormalizedSizeBounds& bounds,
- const FlexOrderToViewIndexMap& order_to_index,
- FlexOrderToViewIndexMap* expandable_views = nullptr) const;
-
- // Calculates the position of each child view and the size of the overall
- // layout based on tentative visibilities and sizes for each child.
- void UpdateLayoutFromChildren(Layout* layout,
- ChildViewSpacing* child_spacing,
- const NormalizedSizeBounds& bounds) const;
-
- // Calculates the cross-layout space available to a view based on the
- // available space and margins.
- base::Optional<int> GetAvailableCrossAxisSize(
- const Layout& layout,
- size_t child_index,
- const NormalizedSizeBounds& bounds) const;
-
- // Calculates a margin between two child views based on each's margin and any
- // internal padding present in one or both elements. Uses properties of the
- // layout, like whether adjacent margins should be collapsed.
- int CalculateMargin(int margin1, int margin2, int internal_padding) const;
-
- // Calculates the preferred spacing between two child views, or between a
- // view edge and the first or last visible child views.
- int CalculateChildSpacing(const Layout& layout,
- base::Optional<size_t> child1_index,
- base::Optional<size_t> child2_index) const;
-
- const gfx::Insets& GetMargins(const View* view) const;
-
- FlexLayout& layout_;
-
- // Instead of marking each layout as dirty/needing validation, we instead keep
- // a value that changes every time InvalidateLayout() is called. If the value
- // stored in a cached layout doesn't match this value, we validate it and
- // update the value. We use an int64_t because the odds of spurious collision
- // (i.e. the counter wrapping back around to the *exact* same value before
- // validating) are effectively zero.
- uint32_t layout_counter_ = 0;
- LayoutCache layout_cache_;
-
- DISALLOW_COPY_AND_ASSIGN(FlexLayoutInternal);
-};
+FlexLayout& FlexLayout::SetInteriorMargin(const gfx::Insets& interior_margin) {
+ if (interior_margin_ != interior_margin) {
+ interior_margin_ = interior_margin;
+ InvalidateLayout();
+ }
+ return *this;
+}
-void FlexLayoutInternal::InvalidateLayout(bool force) {
- ++layout_counter_;
- if (force)
- layout_cache_.Clear();
+FlexLayout& FlexLayout::SetMinimumCrossAxisSize(int size) {
+ if (minimum_cross_axis_size_ != size) {
+ minimum_cross_axis_size_ = size;
+ InvalidateLayout();
+ }
+ return *this;
}
-const Layout& FlexLayoutInternal::CalculateLayout(const SizeBounds& bounds) {
- // If bounds are smaller than the minimum cross axis size, expand them.
- NormalizedSizeBounds normalized_bounds = Normalize(orientation(), bounds);
- if (normalized_bounds.cross() &&
- *normalized_bounds.cross() < layout_.minimum_cross_axis_size()) {
- normalized_bounds = NormalizedSizeBounds{normalized_bounds.main(),
- layout_.minimum_cross_axis_size()};
+LayoutManagerBase::ProposedLayout FlexLayout::CalculateProposedLayout(
+ const SizeBounds& size_bounds) const {
+ FlexLayoutData data;
+
+ data.host_insets = Normalize(orientation(), host_view()->GetInsets());
+ data.interior_margin = Normalize(orientation(), interior_margin());
+ NormalizedSizeBounds bounds = Normalize(orientation(), size_bounds);
+ bounds.Inset(data.host_insets);
+ if (bounds.cross() && *bounds.cross() < minimum_cross_axis_size())
+ bounds.set_cross(minimum_cross_axis_size());
+
+ // Populate the child layout data vectors and the order-to-index map.
+ FlexOrderToViewIndexMap order_to_view_index;
+ InitializeChildData(bounds, &data, &order_to_view_index);
+
+ // Do the initial layout update, calculating spacing between children.
+ ChildViewSpacing child_spacing(
+ base::BindRepeating(&FlexLayout::CalculateChildSpacing,
+ base::Unretained(this), std::cref(data)));
+ UpdateLayoutFromChildren(bounds, &data, &child_spacing);
+
+ if (bounds.main().has_value() && !order_to_view_index.empty()) {
+ // Flex up to preferred size.
+ FlexOrderToViewIndexMap expandable_views;
+ AllocateFlexSpace(bounds, order_to_view_index, &data, &child_spacing,
+ &expandable_views);
+
+ // Flex views that can exceed their preferred size.
+ if (!expandable_views.empty())
+ AllocateFlexSpace(bounds, expandable_views, &data, &child_spacing);
}
- // See if we have a cached layout already that is still valid.
- Layout* const cached_layout = layout_cache_.Get(normalized_bounds);
- if (cached_layout && IsLayoutValid(*cached_layout))
- return *cached_layout;
+ // Calculate the size of the host view.
+ NormalizedSize host_size = data.total_size;
+ host_size.Enlarge(data.host_insets.main_size(),
+ data.host_insets.cross_size());
+ data.layout.host_size = Denormalize(orientation(), host_size);
+
+ // Size and position the children in screen space.
+ CalculateChildBounds(size_bounds, &data);
- // Calculate a new layout from scratch.
- return CalculateNewLayout(normalized_bounds);
+ return data.layout;
}
-void FlexLayoutInternal::DoLayout(const Layout& layout,
- const gfx::Rect& bounds) {
- NormalizedPoint start = Normalize(orientation(), bounds.origin());
+void FlexLayout::InitializeChildData(
+ const internal::NormalizedSizeBounds& bounds,
+ FlexLayoutData* data,
+ FlexOrderToViewIndexMap* flex_order_to_index) const {
+ // Step through the children, creating placeholder layout view elements
+ // and setting up initial minimal visibility.
+ const bool main_axis_bounded = bounds.main().has_value();
+ for (auto it = host_view()->children().begin();
+ it != host_view()->children().end(); ++it) {
+ View* const child = *it;
+ if (!IsChildIncludedInLayout(child))
+ continue;
+ const size_t view_index = data->num_children();
+ data->layout.child_layouts.emplace_back(ChildLayout{child});
+ ChildLayout& child_layout = data->layout.child_layouts.back();
+ data->child_data.emplace_back(
+ GetViewProperty(child, layout_defaults_, views::kFlexBehaviorKey));
+ FlexChildData& flex_child = data->child_data.back();
+
+ flex_child.margins =
+ Normalize(orientation(),
+ GetViewProperty(child, layout_defaults_, views::kMarginsKey));
+ flex_child.internal_padding = Normalize(
+ orientation(),
+ GetViewProperty(child, layout_defaults_, views::kInternalPaddingKey));
+ flex_child.preferred_size =
+ Normalize(orientation(), child->GetPreferredSize());
+
+ // gfx::Size calculation depends on whether flex is allowed.
+ if (main_axis_bounded) {
+ flex_child.available_size = {
+ 0, GetAvailableCrossAxisSize(*data, view_index, bounds)};
+ flex_child.current_size = Normalize(
+ orientation(),
+ flex_child.flex.rule().Run(
+ child, Denormalize(orientation(), flex_child.available_size)));
- // Apply main axis alignment.
- const int excess_main =
- Normalize(orientation(), bounds.size()).main() - layout.total_size.main();
- switch (layout_.main_axis_alignment()) {
+ // We should revisit whether this is a valid assumption for text views
+ // in vertical layouts.
+ DCHECK_GE(flex_child.preferred_size.main(),
+ flex_child.current_size.main());
+
+ // Keep track of non-hidden flex controls.
+ const bool can_flex =
+ (flex_child.flex.weight() > 0 &&
+ flex_child.preferred_size.main() > 0) ||
+ flex_child.current_size.main() < flex_child.preferred_size.main();
+ if (can_flex)
+ (*flex_order_to_index)[flex_child.flex.order()].push_back(view_index);
+
+ } else {
+ // All non-flex or unbounded controls get preferred size.
+ flex_child.current_size = flex_child.preferred_size;
+ }
+
+ child_layout.visible = flex_child.current_size.main() > 0;
+ }
+}
+
+void FlexLayout::CalculateChildBounds(const SizeBounds& size_bounds,
+ FlexLayoutData* data) const {
+ // Apply main axis alignment (we've already done cross-axis alignment above).
+ const NormalizedSizeBounds normalized_bounds =
+ Normalize(orientation(), size_bounds);
+ const NormalizedSize normalized_host_size =
+ Normalize(orientation(), data->layout.host_size);
+ int available_main = (normalized_bounds.main() ? *normalized_bounds.main()
+ : normalized_host_size.main());
+ available_main = std::max(0, available_main - data->host_insets.main_size());
+ const int excess_main = available_main - data->total_size.main();
+ NormalizedPoint start(data->host_insets.main_leading(),
+ data->host_insets.cross_leading());
+ switch (main_axis_alignment()) {
case LayoutAlignment::kStart:
break;
case LayoutAlignment::kCenter:
@@ -446,29 +431,34 @@ void FlexLayoutInternal::DoLayout(const Layout& layout,
break;
}
- // Position controls within the client area.
- for (const ChildLayout& child_layout : layout.child_layouts) {
- if (child_layout.excluded)
- continue;
- if (child_layout.visible != child_layout.view->GetVisible())
- layout_.SetViewVisibility(child_layout.view, child_layout.visible);
+ // Calculate the actual child bounds.
+ for (size_t i = 0; i < data->num_children(); ++i) {
+ ChildLayout& child_layout = data->layout.child_layouts[i];
if (child_layout.visible) {
- NormalizedRect actual = child_layout.actual_bounds;
+ FlexChildData& flex_child = data->child_data[i];
+ NormalizedRect actual = flex_child.actual_bounds;
actual.Offset(start.main(), start.cross());
- gfx::Rect denormalized = Denormalize(orientation(), actual);
- child_layout.view->SetBoundsRect(denormalized);
+ child_layout.bounds = Denormalize(orientation(), actual);
}
}
}
-base::Optional<int> FlexLayoutInternal::GetAvailableCrossAxisSize(
- const Layout& layout,
+int FlexLayout::CalculateMargin(int margin1,
+ int margin2,
+ int internal_padding) const {
+ const int result =
+ collapse_margins() ? std::max(margin1, margin2) : margin1 + margin2;
+ return std::max(0, result - internal_padding);
+}
+
+base::Optional<int> FlexLayout::GetAvailableCrossAxisSize(
+ const FlexLayoutData& layout,
size_t child_index,
const NormalizedSizeBounds& bounds) const {
if (!bounds.cross())
return base::nullopt;
- const ChildLayout& child_layout = layout.child_layouts[child_index];
+ const FlexChildData& child_layout = layout.child_data[child_index];
const int leading_margin =
CalculateMargin(layout.interior_margin.cross_leading(),
child_layout.margins.cross_leading(),
@@ -480,84 +470,71 @@ base::Optional<int> FlexLayoutInternal::GetAvailableCrossAxisSize(
return std::max(0, *bounds.cross() - (leading_margin + trailing_margin));
}
-int FlexLayoutInternal::CalculateMargin(int margin1,
- int margin2,
- int internal_padding) const {
- const int result = layout_.collapse_margins() ? std::max(margin1, margin2)
- : margin1 + margin2;
- return std::max(0, result - internal_padding);
-}
-
-int FlexLayoutInternal::CalculateChildSpacing(
- const Layout& layout,
+int FlexLayout::CalculateChildSpacing(
+ const FlexLayoutData& layout,
base::Optional<size_t> child1_index,
base::Optional<size_t> child2_index) const {
const int left_margin =
- child1_index ? layout.child_layouts[*child1_index].margins.main_trailing()
+ child1_index ? layout.child_data[*child1_index].margins.main_trailing()
: layout.interior_margin.main_leading();
const int right_margin =
- child2_index ? layout.child_layouts[*child2_index].margins.main_leading()
+ child2_index ? layout.child_data[*child2_index].margins.main_leading()
: layout.interior_margin.main_trailing();
const int left_padding =
child1_index
- ? layout.child_layouts[*child1_index].internal_padding.main_trailing()
+ ? layout.child_data[*child1_index].internal_padding.main_trailing()
: 0;
const int right_padding =
child2_index
- ? layout.child_layouts[*child2_index].internal_padding.main_leading()
+ ? layout.child_data[*child2_index].internal_padding.main_leading()
: 0;
return CalculateMargin(left_margin, right_margin,
left_padding + right_padding);
}
-const gfx::Insets& FlexLayoutInternal::GetMargins(const View* view) const {
- const gfx::Insets* const margins = view->GetProperty(views::kMarginsKey);
- return margins ? *margins : layout_.default_child_margins();
-}
-
-void FlexLayoutInternal::UpdateLayoutFromChildren(
- Layout* layout,
- ChildViewSpacing* child_spacing,
- const NormalizedSizeBounds& bounds) const {
+void FlexLayout::UpdateLayoutFromChildren(
+ const NormalizedSizeBounds& bounds,
+ FlexLayoutData* data,
+ ChildViewSpacing* child_spacing) const {
// Calculate starting minimum for cross-axis size.
int min_cross_size =
- std::max(layout_.minimum_cross_axis_size(),
- CalculateMargin(layout->interior_margin.cross_leading(),
- layout->interior_margin.cross_trailing(), 0));
- layout->total_size = NormalizedSize(0, min_cross_size);
+ std::max(minimum_cross_axis_size(),
+ CalculateMargin(data->interior_margin.cross_leading(),
+ data->interior_margin.cross_trailing(), 0));
+ data->total_size = NormalizedSize(0, min_cross_size);
// For cases with a non-zero cross-axis bound, the objective is to fit the
// layout into that precise size, not to determine what size we need.
bool force_cross_size = false;
if (bounds.cross() && *bounds.cross() > 0) {
- layout->total_size.SetToMax(0, *bounds.cross());
+ data->total_size.SetToMax(0, *bounds.cross());
force_cross_size = true;
}
- std::vector<Inset1D> cross_spacings(layout->child_layouts.size());
- for (size_t i = 0; i < layout->child_layouts.size(); ++i) {
- ChildLayout& child_layout = layout->child_layouts[i];
+ std::vector<Inset1D> cross_spacings(data->num_children());
+ for (size_t i = 0; i < data->num_children(); ++i) {
+ FlexChildData& flex_child = data->child_data[i];
- // We don't have to deal with excluded or invisible children.
- if (child_layout.excluded || !child_layout.visible)
+ // We don't have to deal with invisible children.
+ if (!data->layout.child_layouts[i].visible)
continue;
// Update the cross-axis margins and if necessary, the size.
Inset1D& cross_spacing = cross_spacings[i];
cross_spacing.set_leading(
- CalculateMargin(layout->interior_margin.cross_leading(),
- child_layout.margins.cross_leading(),
- child_layout.internal_padding.cross_leading()));
+ CalculateMargin(data->interior_margin.cross_leading(),
+ flex_child.margins.cross_leading(),
+ flex_child.internal_padding.cross_leading()));
cross_spacing.set_trailing(
- CalculateMargin(layout->interior_margin.cross_trailing(),
- child_layout.margins.cross_trailing(),
- child_layout.internal_padding.cross_trailing()));
+ CalculateMargin(data->interior_margin.cross_trailing(),
+ flex_child.margins.cross_trailing(),
+ flex_child.internal_padding.cross_trailing()));
if (!force_cross_size) {
- const int cross_size = std::min(child_layout.current_size.cross(),
- child_layout.preferred_size.cross());
- layout->total_size.SetToMax(0, cross_spacing.size() + cross_size);
+ const int cross_size = std::min(flex_child.current_size.cross(),
+ flex_child.preferred_size.cross());
+ data->total_size.SetToMax(0, cross_spacing.size() + cross_size);
}
// Calculate main-axis size and upper-left main axis coordinate.
@@ -566,50 +543,46 @@ void FlexLayoutInternal::UpdateLayoutFromChildren(
leading_space = child_spacing->GetLeadingSpace(i);
else
child_spacing->AddViewIndex(i, &leading_space);
- layout->total_size.Enlarge(leading_space, 0);
+ data->total_size.Enlarge(leading_space, 0);
- const int size_main = child_layout.current_size.main();
- child_layout.actual_bounds.set_origin_main(layout->total_size.main());
- child_layout.actual_bounds.set_size_main(size_main);
- layout->total_size.Enlarge(size_main, 0);
+ const int size_main = flex_child.current_size.main();
+ flex_child.actual_bounds.set_origin_main(data->total_size.main());
+ flex_child.actual_bounds.set_size_main(size_main);
+ data->total_size.Enlarge(size_main, 0);
}
// Add the end margin.
- layout->total_size.Enlarge(child_spacing->GetTrailingInset(), 0);
+ data->total_size.Enlarge(child_spacing->GetTrailingInset(), 0);
// Calculate cross-axis positioning based on the cross margins and size that
// were calculated above.
- const Span cross_span(0, layout->total_size.cross());
- for (size_t i = 0; i < layout->child_layouts.size(); ++i) {
- ChildLayout& child_layout = layout->child_layouts[i];
-
- // We don't have to deal with excluded or invisible children.
- if (child_layout.excluded || !child_layout.visible)
- continue;
+ const Span cross_span(0, data->total_size.cross());
+ for (size_t i = 0; i < data->num_children(); ++i) {
+ FlexChildData& flex_child = data->child_data[i];
// Start with a size appropriate for the child view. For child views which
// can become larger than the preferred size, start with the preferred size
// and let the alignment operation (specifically, if the alignment is set to
// kStretch) grow the child view.
- const int starting_cross_size = std::min(
- child_layout.current_size.cross(), child_layout.preferred_size.cross());
- child_layout.actual_bounds.set_size_cross(starting_cross_size);
- child_layout.actual_bounds.AlignCross(
- cross_span, layout_.cross_axis_alignment(), cross_spacings[i]);
+ const int starting_cross_size = std::min(flex_child.current_size.cross(),
+ flex_child.preferred_size.cross());
+ flex_child.actual_bounds.set_size_cross(starting_cross_size);
+ flex_child.actual_bounds.AlignCross(cross_span, cross_axis_alignment(),
+ cross_spacings[i]);
}
}
-void FlexLayoutInternal::AllocateFlexSpace(
- Layout* layout,
- ChildViewSpacing* child_spacing,
+void FlexLayout::AllocateFlexSpace(
const NormalizedSizeBounds& bounds,
const FlexOrderToViewIndexMap& order_to_index,
+ FlexLayoutData* data,
+ ChildViewSpacing* child_spacing,
FlexOrderToViewIndexMap* expandable_views) const {
// Step through each flex priority allocating as much remaining space as
// possible to each flex view.
for (const auto& flex_elem : order_to_index) {
// Check to see we haven't filled available space.
- int remaining = *bounds.main() - layout->total_size.main();
+ int remaining = *bounds.main() - data->total_size.main();
if (remaining <= 0)
break;
const int flex_order = flex_elem.first;
@@ -639,11 +612,11 @@ void FlexLayoutInternal::AllocateFlexSpace(
// reasonable margins and by using flex order).
// Flex children at this priority order.
- int flex_total = std::accumulate(
- flex_elem.second.begin(), flex_elem.second.end(), 0,
- [layout](int total, size_t index) {
- return total + layout->child_layouts[index].flex.weight();
- });
+ int flex_total =
+ std::accumulate(flex_elem.second.begin(), flex_elem.second.end(), 0,
+ [data](int total, size_t index) {
+ return total + data->child_data[index].flex.weight();
+ });
// Note: because the child views are evaluated in order, if preferred
// minimum sizes are not consistent across a single priority expanding
@@ -655,12 +628,13 @@ void FlexLayoutInternal::AllocateFlexSpace(
remaining >= 0 && index_it != flex_elem.second.end(); ++index_it) {
const size_t view_index = *index_it;
- ChildLayout& child_layout = layout->child_layouts[view_index];
+ ChildLayout& child_layout = data->layout.child_layouts[view_index];
+ FlexChildData& flex_child = data->child_data[view_index];
// Offer a share of the remaining space to the view.
int flex_amount;
- if (child_layout.flex.weight() > 0) {
- const int flex_weight = child_layout.flex.weight();
+ if (flex_child.flex.weight() > 0) {
+ const int flex_weight = flex_child.flex.weight();
// Round up so we give slightly greater weight to earlier views.
flex_amount =
int{std::ceil((float{remaining} * flex_weight) / flex_total)};
@@ -690,17 +664,17 @@ void FlexLayoutInternal::AllocateFlexSpace(
// view since it is considered a fixed overhead of the layout if it is
// nonzero.
const int old_size =
- child_layout.visible ? child_layout.current_size.main() : 0;
+ child_layout.visible ? flex_child.current_size.main() : 0;
// Offer the modified flex space to the child view and see how large it
// wants to be (or if it wants to be visible at that size at all).
const NormalizedSizeBounds available(
flex_amount + old_size - margin_delta,
- child_layout.available_size.cross());
+ flex_child.available_size.cross());
NormalizedSize new_size = Normalize(
orientation(),
- child_layout.flex.rule().Run(child_layout.view,
- Denormalize(orientation(), available)));
+ flex_child.flex.rule().Run(child_layout.child_view,
+ Denormalize(orientation(), available)));
if (new_size.main() <= 0)
continue;
@@ -709,9 +683,9 @@ void FlexLayoutInternal::AllocateFlexSpace(
// them to |expandable_views| so that the remaining space can be allocated
// later.
if (expandable_views &&
- new_size.main() >= child_layout.preferred_size.main()) {
+ new_size.main() >= flex_child.preferred_size.main()) {
(*expandable_views)[flex_order].push_back(view_index);
- new_size.set_main(child_layout.preferred_size.main());
+ new_size.set_main(flex_child.preferred_size.main());
}
// If the amount of space claimed increases (but is still within
@@ -720,8 +694,8 @@ void FlexLayoutInternal::AllocateFlexSpace(
const int to_deduct = (new_size.main() - old_size) + margin_delta;
DCHECK_GE(to_deduct, 0);
if (to_deduct > 0 && to_deduct <= remaining) {
- child_layout.available_size = available;
- child_layout.current_size = new_size;
+ flex_child.available_size = available;
+ flex_child.current_size = new_size;
child_layout.visible = true;
remaining -= to_deduct;
if (!child_spacing->HasViewIndex(view_index))
@@ -733,380 +707,8 @@ void FlexLayoutInternal::AllocateFlexSpace(
// Reposition the child controls (taking margins into account) and
// calculate remaining space.
if (dirty)
- UpdateLayoutFromChildren(layout, child_spacing, bounds);
- }
-}
-
-const Layout& FlexLayoutInternal::CalculateNewLayout(
- const NormalizedSizeBounds& bounds) {
- DCHECK(!bounds.cross() ||
- *bounds.cross() >= layout_.minimum_cross_axis_size());
- std::unique_ptr<Layout> layout = std::make_unique<Layout>(layout_counter_);
- layout->interior_margin = Normalize(orientation(), layout_.interior_margin());
- FlexOrderToViewIndexMap order_to_view_index;
- const bool main_axis_bounded = bounds.main().has_value();
-
- // Step through the children, creating placeholder layout view elements
- // and setting up initial minimal visibility.
- View* const view = layout_.host();
- for (size_t i = 0; i < view->children().size(); ++i) {
- View* child = view->children()[i];
- layout->child_layouts.emplace_back(child, layout_.GetFlexForView(child));
- ChildLayout& child_layout = layout->child_layouts.back();
-
- child_layout.excluded = layout_.IsViewExcluded(child);
- if (child_layout.excluded)
- continue;
-
- child_layout.margins = Normalize(orientation(), GetMargins(child));
- child_layout.internal_padding =
- Normalize(orientation(), GetInternalPadding(child));
- child_layout.preferred_size =
- Normalize(orientation(), child->GetPreferredSize());
-
- child_layout.hidden_by_owner = layout_.IsHiddenByOwner(child);
- child_layout.visible = !child_layout.hidden_by_owner;
- if (child_layout.hidden_by_owner)
- continue;
-
- // gfx::Size calculation depends on whether flex is allowed.
- if (main_axis_bounded) {
- child_layout.available_size = {
- 0, GetAvailableCrossAxisSize(*layout, i, bounds)};
- child_layout.current_size = Normalize(
- orientation(),
- child_layout.flex.rule().Run(
- child, Denormalize(orientation(), child_layout.available_size)));
-
- // We should revisit whether this is a valid assumption for text views
- // in vertical layouts.
- DCHECK_GE(child_layout.preferred_size.main(),
- child_layout.current_size.main());
-
- // Keep track of non-hidden flex controls.
- const bool can_flex =
- (child_layout.flex.weight() > 0 &&
- child_layout.preferred_size.main() > 0) ||
- child_layout.current_size.main() < child_layout.preferred_size.main();
- if (can_flex)
- order_to_view_index[child_layout.flex.order()].push_back(i);
-
- } else {
- // All non-flex or unbounded controls get preferred size.
- child_layout.current_size = child_layout.preferred_size;
- }
-
- child_layout.visible = child_layout.current_size.main() > 0;
-
- // Actual size and positioning will be set during the final layout
- // calculation.
- }
-
- // Do the initial layout update, calculating spacing between children.
- ChildViewSpacing child_spacing(
- base::BindRepeating(&FlexLayoutInternal::CalculateChildSpacing,
- base::Unretained(this), std::cref(*layout)));
- UpdateLayoutFromChildren(layout.get(), &child_spacing, bounds);
-
- if (main_axis_bounded && !order_to_view_index.empty()) {
- // Flex up to preferred size.
- FlexOrderToViewIndexMap expandable_views;
- AllocateFlexSpace(layout.get(), &child_spacing, bounds, order_to_view_index,
- &expandable_views);
-
- // Flex views that can exceed their preferred size.
- if (!expandable_views.empty())
- AllocateFlexSpace(layout.get(), &child_spacing, bounds, expandable_views);
- }
-
- const Layout& result = *layout;
- layout_cache_.Put(bounds, std::move(layout));
- return result;
-}
-
-bool FlexLayoutInternal::IsLayoutValid(const Layout& cached_layout) const {
- // If we've already evaluated a layout for this size and not been
- // invalidated since then, then this is a valid layout.
- if (cached_layout.layout_id == layout_counter_)
- return true;
-
- // Need to compare preferred child sizes with what we're seeing.
- View* const view = layout_.host();
- auto iter = view->children().cbegin();
- for (const ChildLayout& proposed_view_layout : cached_layout.child_layouts) {
- // Check that there is another child and that it's the view we expect.
- DCHECK(iter != view->children().cend())
- << "Child views should not be removed without clearing the cache.";
-
- const View* child = *iter++;
-
- // Ensure child views have not been reordered.
- if (child != proposed_view_layout.view)
- return false;
-
- // Ignore hidden and excluded views, unless their status has changed.
- const bool excluded = layout_.IsViewExcluded(child);
- if (proposed_view_layout.excluded != excluded)
- return false;
- if (excluded)
- continue;
-
- const bool hidden_by_owner = layout_.IsHiddenByOwner(child);
- if (proposed_view_layout.hidden_by_owner != hidden_by_owner)
- return false;
- if (hidden_by_owner)
- continue;
-
- // Sanity check that a child's visibility hasn't been modified outside
- // the layout manager.
- if (proposed_view_layout.visible != child->GetVisible())
- return false;
-
- if (proposed_view_layout.visible) {
- // Check that view margins haven't changed for visible controls.
- if (GetMargins(child) !=
- Denormalize(orientation(), proposed_view_layout.margins))
- return false;
-
- // Same for internal padding.
- if (GetInternalPadding(child) !=
- Denormalize(orientation(), proposed_view_layout.internal_padding))
- return false;
- }
-
- // Check that the control still has the same preferred size given its
- // flex and visibility.
- if (child->GetPreferredSize() !=
- Denormalize(orientation(), proposed_view_layout.preferred_size))
- return false;
-
- const gfx::Size preferred = proposed_view_layout.flex.rule().Run(
- child, Denormalize(orientation(), proposed_view_layout.available_size));
- if (preferred !=
- Denormalize(orientation(), proposed_view_layout.current_size))
- return false;
- }
-
- DCHECK(iter == view->children().cend())
- << "Child views should not be added without clearing the cache.";
-
- // This layout is still valid. Update the layout counter to show it's valid
- // in the current layout context.
- cached_layout.layout_id = layout_counter_;
- return true;
-}
-
-} // namespace internal
-
-// FlexLayout
-// -------------------------------------------------------------------
-
-FlexLayout::FlexLayout()
- : internal_(std::make_unique<internal::FlexLayoutInternal>(this)) {}
-
-FlexLayout::~FlexLayout() = default;
-
-FlexLayout& FlexLayout::SetOrientation(LayoutOrientation orientation) {
- if (orientation != orientation_) {
- orientation_ = orientation;
- internal_->InvalidateLayout(true);
- }
- return *this;
-}
-
-FlexLayout& FlexLayout::SetCollapseMargins(bool collapse_margins) {
- if (collapse_margins != collapse_margins_) {
- collapse_margins_ = collapse_margins;
- internal_->InvalidateLayout(true);
- }
- return *this;
-}
-
-FlexLayout& FlexLayout::SetMainAxisAlignment(
- LayoutAlignment main_axis_alignment) {
- DCHECK_NE(main_axis_alignment, LayoutAlignment::kStretch)
- << "Main axis stretch/justify is not yet supported.";
- if (main_axis_alignment_ != main_axis_alignment) {
- main_axis_alignment_ = main_axis_alignment;
- internal_->InvalidateLayout(true);
- }
- return *this;
-}
-
-FlexLayout& FlexLayout::SetCrossAxisAlignment(
- LayoutAlignment cross_axis_alignment) {
- if (cross_axis_alignment_ != cross_axis_alignment) {
- cross_axis_alignment_ = cross_axis_alignment;
- internal_->InvalidateLayout(true);
+ UpdateLayoutFromChildren(bounds, data, child_spacing);
}
- return *this;
-}
-
-FlexLayout& FlexLayout::SetInteriorMargin(const gfx::Insets& interior_margin) {
- if (interior_margin_ != interior_margin) {
- interior_margin_ = interior_margin;
- internal_->InvalidateLayout(true);
- }
- return *this;
-}
-
-FlexLayout& FlexLayout::SetMinimumCrossAxisSize(int size) {
- if (minimum_cross_axis_size_ != size) {
- minimum_cross_axis_size_ = size;
- internal_->InvalidateLayout(true);
- }
- return *this;
-}
-
-FlexLayout& FlexLayout::SetDefaultChildMargins(const gfx::Insets& margins) {
- if (default_child_margins_ != margins) {
- default_child_margins_ = margins;
- internal_->InvalidateLayout(true);
- }
- return *this;
-}
-
-FlexLayout& FlexLayout::SetFlexForView(
- const View* view,
- const FlexSpecification& flex_specification) {
- auto it = child_params_.find(view);
- DCHECK(it != child_params_.end());
- it->second.flex_specification = flex_specification;
- internal_->InvalidateLayout(true);
- return *this;
-}
-
-FlexLayout& FlexLayout::ClearFlexForView(const View* view) {
- auto it = child_params_.find(view);
- DCHECK(it != child_params_.end());
- it->second.flex_specification.reset();
- internal_->InvalidateLayout(true);
- return *this;
-}
-
-FlexLayout& FlexLayout::SetViewExcluded(const View* view, bool excluded) {
- auto it = child_params_.find(view);
- DCHECK(it != child_params_.end());
- if (excluded != it->second.excluded) {
- it->second.excluded = excluded;
- InvalidateLayout();
- }
- return *this;
-}
-
-FlexLayout& FlexLayout::SetDefaultFlex(
- const FlexSpecification& flex_specification) {
- default_flex_ = flex_specification;
- internal_->InvalidateLayout(true);
- return *this;
-}
-
-const FlexSpecification& FlexLayout::GetFlexForView(const View* view) const {
- auto it = child_params_.find(view);
- DCHECK(it != child_params_.end());
- const base::Optional<FlexSpecification>& spec = it->second.flex_specification;
- return spec ? *spec : default_flex_;
-}
-
-bool FlexLayout::IsViewExcluded(const View* view) const {
- auto it = child_params_.find(view);
- DCHECK(it != child_params_.end());
- return it->second.excluded;
-}
-
-bool FlexLayout::IsHiddenByOwner(const View* view) const {
- auto it = child_params_.find(view);
- DCHECK(it != child_params_.end());
- return it->second.hidden_by_owner;
-}
-
-gfx::Size FlexLayout::GetPreferredSize(const View* host) const {
- DCHECK_EQ(host_, host);
- return GetPreferredSize(SizeBounds());
-}
-
-int FlexLayout::GetPreferredHeightForWidth(const View* host, int width) const {
- DCHECK_EQ(host_, host);
- return GetPreferredSize(SizeBounds{width, base::nullopt}).height();
-}
-
-gfx::Size FlexLayout::GetMinimumSize(const View* host) const {
- DCHECK_EQ(host_, host);
- return GetPreferredSize(SizeBounds{0, 0});
-}
-
-void FlexLayout::InvalidateLayout() {
- internal_->InvalidateLayout(false);
-}
-
-void FlexLayout::Installed(View* host) {
- DCHECK(!host_);
- host_ = host;
- // Add all the existing children when the layout manager is installed.
- // If new children are added, ViewAdded() will be called and we'll add data
- // there.
- for (View* child : host->children()) {
- internal::ChildLayoutParams child_layout_params;
- child_layout_params.hidden_by_owner = !child->GetVisible();
- child_params_.emplace(child, child_layout_params);
- }
-}
-
-void FlexLayout::ViewAdded(View* host, View* view) {
- DCHECK_EQ(host_, host);
- internal::ChildLayoutParams child_layout_params;
- child_layout_params.hidden_by_owner = !view->GetVisible();
- child_params_.emplace(view, child_layout_params);
- internal_->InvalidateLayout(true);
-}
-
-void FlexLayout::ViewRemoved(View* host, View* view) {
- child_params_.erase(view);
- internal_->InvalidateLayout(true);
-}
-
-void FlexLayout::ViewVisibilitySet(View* host, View* view, bool visible) {
- DCHECK_EQ(host, host_);
- DCHECK_EQ(view->parent(), host);
- auto it = child_params_.find(view);
- DCHECK(it != child_params_.end());
- const bool hide = !visible;
- if (it->second.hidden_by_owner != hide) {
- it->second.hidden_by_owner = hide;
- if (!it->second.excluded) {
- // It's not always obvious to our host that an owner of a child view
- // changing its visibility could change a layout. So we'll notify the host
- // view that its layout is potentially invalid, and it will in turn call
- // InvalidateLayout() on the layout manager (i.e. this object).
- host_->InvalidateLayout();
- }
- }
-}
-
-// Retrieve the preferred size for the control in the given bounds.
-gfx::Size FlexLayout::GetPreferredSize(const SizeBounds& bounds) const {
- if (!host_)
- return gfx::Size();
-
- const gfx::Insets insets = host_->GetInsets();
- SizeBounds content_bounds = bounds;
- content_bounds.Enlarge(-insets.width(), -insets.height());
- const internal::Layout& proposed_layout =
- internal_->CalculateLayout(content_bounds);
- gfx::Size result = Denormalize(orientation(), proposed_layout.total_size);
- result.Enlarge(insets.width(), insets.height());
- return result;
-}
-
-void FlexLayout::Layout(View* host) {
- DCHECK_EQ(host, host_);
- // TODO(dfried): for a handful of views which override GetInsets(), the way
- // this method is implemented in View may be incorrect. Please revisit.
- gfx::Rect bounds = host_->GetContentsBounds();
- const internal::Layout& layout =
- internal_->CalculateLayout(SizeBounds(bounds.size()));
-
- internal_->DoLayout(layout, bounds);
}
} // namespace views
diff --git a/chromium/ui/views/layout/flex_layout.h b/chromium/ui/views/layout/flex_layout.h
index 45c518133f0..5ca0ab23ae1 100644
--- a/chromium/ui/views/layout/flex_layout.h
+++ b/chromium/ui/views/layout/flex_layout.h
@@ -9,27 +9,25 @@
#include <memory>
#include <set>
#include <string>
+#include <vector>
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/optional.h"
+#include "ui/base/class_property.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/layout/flex_layout_types.h"
-#include "ui/views/layout/layout_manager.h"
-
-namespace gfx {
-class Size;
-} // namespace gfx
+#include "ui/views/layout/layout_manager_base.h"
+#include "ui/views/views_export.h"
namespace views {
-namespace internal {
-struct ChildLayoutParams;
-class FlexLayoutInternal;
-} // namespace internal
-
class View;
+namespace internal {
+class NormalizedSizeBounds;
+}
+
// Provides CSS-like layout for a one-dimensional (vertical or horizontal)
// arrangement of child views. Independent alignment can be specified for the
// main and cross axes.
@@ -69,11 +67,11 @@ class View;
// take up its preferred size in the layout.
//
// The core function of this class is contained in
-// GetPreferredSize(maximum_size) and Layout(host). In both cases, a layout will
+// GetPreferredSize(maximum_size) and Layout(). In both cases, a layout will
// be cached and typically not recalculated as long as none of the layout's
// properties or the preferred size or visibility of any of its children has
// changed.
-class VIEWS_EXPORT FlexLayout : public LayoutManager {
+class VIEWS_EXPORT FlexLayout : public LayoutManagerBase {
public:
FlexLayout();
~FlexLayout() override;
@@ -88,50 +86,124 @@ class VIEWS_EXPORT FlexLayout : public LayoutManager {
FlexLayout& SetCrossAxisAlignment(LayoutAlignment cross_axis_alignment);
FlexLayout& SetInteriorMargin(const gfx::Insets& interior_margin);
FlexLayout& SetMinimumCrossAxisSize(int size);
- FlexLayout& SetDefaultChildMargins(const gfx::Insets& margins);
- FlexLayout& SetFlexForView(const View* view,
- const FlexSpecification& flex_specification);
- FlexLayout& ClearFlexForView(const View* view);
- FlexLayout& SetDefaultFlex(const FlexSpecification& flex_specification);
-
- // Set whether a view should be excluded from the layout. Excluded views will
- // be completely ignored and must be explicitly placed by the host view.
- FlexLayout& SetViewExcluded(const View* view, bool excluded);
-
- View* host() { return host_; }
- const View* host() const { return host_; }
+
LayoutOrientation orientation() const { return orientation_; }
bool collapse_margins() const { return collapse_margins_; }
LayoutAlignment main_axis_alignment() const { return main_axis_alignment_; }
LayoutAlignment cross_axis_alignment() const { return cross_axis_alignment_; }
const gfx::Insets& interior_margin() const { return interior_margin_; }
int minimum_cross_axis_size() const { return minimum_cross_axis_size_; }
- const gfx::Insets& default_child_margins() const {
- return default_child_margins_;
- }
- const FlexSpecification& default_flex() const { return default_flex_; }
- const FlexSpecification& GetFlexForView(const View* view) const;
- bool IsViewExcluded(const View* view) const;
- bool IsHiddenByOwner(const View* view) const;
+ // Moves and uses |value| as the default value for layout property |key|.
+ template <class T, class U>
+ FlexLayout& SetDefault(const ui::ClassProperty<T>* key, U&& value) {
+ layout_defaults_.SetProperty(key, std::forward<U>(value));
+ return *this;
+ }
- // Retrieve the preferred size for the control in the given bounds.
- gfx::Size GetPreferredSize(const SizeBounds& maximum_size) const;
+ // Copies and uses |value| as the default value for layout property |key|.
+ template <class T, class U>
+ FlexLayout& SetDefault(const ui::ClassProperty<T>* key, const U& value) {
+ layout_defaults_.SetProperty(key, value);
+ return *this;
+ }
protected:
- // views::LayoutManager:
- void Installed(View* host) override;
- void InvalidateLayout() override;
- void ViewAdded(View* host, View* view) override;
- void ViewRemoved(View* host, View* view) override;
- void ViewVisibilitySet(View* host, View* view, bool visible) override;
- void Layout(View* host) override;
- gfx::Size GetPreferredSize(const View* host) const override;
- gfx::Size GetMinimumSize(const View* host) const override;
- int GetPreferredHeightForWidth(const View* host, int width) const override;
+ // LayoutManagerBase:
+ ProposedLayout CalculateProposedLayout(
+ const SizeBounds& size_bounds) const override;
private:
- friend class internal::FlexLayoutInternal;
+ struct ChildLayoutParams;
+ class ChildViewSpacing;
+ struct FlexLayoutData;
+
+ class PropertyHandler : public ui::PropertyHandler {
+ public:
+ explicit PropertyHandler(FlexLayout* layout);
+
+ protected:
+ // ui::PropertyHandler:
+ void AfterPropertyChange(const void* key, int64_t old_value) override;
+
+ private:
+ FlexLayout* const layout_;
+ };
+
+ // Maps a flex order (lower = allocated first, and therefore higher priority)
+ // to the indices of child views within that order that can flex.
+ // See FlexSpecification::order().
+ using FlexOrderToViewIndexMap = std::map<int, std::vector<size_t>>;
+
+ // Calculates a margin between two child views based on each's margin and any
+ // internal padding present in one or both elements. Uses properties of the
+ // layout, like whether adjacent margins should be collapsed.
+ int CalculateMargin(int margin1, int margin2, int internal_padding) const;
+
+ // Calculates the cross-layout space available to a view based on the
+ // available space and margins.
+ base::Optional<int> GetAvailableCrossAxisSize(
+ const FlexLayoutData& layout,
+ size_t child_index,
+ const internal::NormalizedSizeBounds& bounds) const;
+
+ // Calculates the preferred spacing between two child views, or between a
+ // view edge and the first or last visible child views.
+ int CalculateChildSpacing(const FlexLayoutData& layout,
+ base::Optional<size_t> child1_index,
+ base::Optional<size_t> child2_index) const;
+
+ // Calculates the position of each child view and the size of the overall
+ // layout based on tentative visibilities and sizes for each child.
+ void UpdateLayoutFromChildren(const internal::NormalizedSizeBounds& bounds,
+ FlexLayoutData* data,
+ ChildViewSpacing* child_spacing) const;
+
+ // Applies flex rules to each view in a layout, updating |data| and
+ // |child_spacing|.
+ //
+ // If |expandable_views| is specified, any view requesting more than its
+ // preferred size will be clamped to its preferred size and be added to
+ // |expandable_views| for later processing after all other flex space has been
+ // allocated.
+ //
+ // Typically, this method will be called once with |expandable_views| set and
+ // then again with it null to allocate the remaining space.
+ void AllocateFlexSpace(
+ const internal::NormalizedSizeBounds& bounds,
+ const FlexOrderToViewIndexMap& order_to_index,
+ FlexLayoutData* data,
+ ChildViewSpacing* child_spacing,
+ FlexOrderToViewIndexMap* expandable_views = nullptr) const;
+
+ // Fills out the child entries for |data| and generates some initial size
+ // and visibility data, and stores off information about which views can
+ // expand in |flex_order_to_index|.
+ void InitializeChildData(const internal::NormalizedSizeBounds& bounds,
+ FlexLayoutData* data,
+ FlexOrderToViewIndexMap* flex_order_to_index) const;
+
+ // Caclulates the child bounds (in screen coordinates) for each visible child
+ // in the layout.
+ void CalculateChildBounds(const SizeBounds& size_bounds,
+ FlexLayoutData* data) const;
+
+ // Gets the default value for a particular layout property, which will be used
+ // if the property is not set on a child view being laid out (e.g.
+ // kMarginsKey).
+ template <class T>
+ T* GetDefault(const ui::ClassProperty<T>* key) const {
+ return layout_defaults_.GetProperty(key);
+ }
+
+ // Clears the default value for a particular layout property, which will be
+ // used if the property is not set on a child view being laid out (e.g.
+ // kMarginsKey).
+ template <class T>
+ FlexLayout& ClearDefault(const ui::ClassProperty<T>* key) {
+ layout_defaults_.ClearProperty(key);
+ return *this;
+ }
LayoutOrientation orientation_ = LayoutOrientation::kHorizontal;
@@ -141,12 +213,6 @@ class VIEWS_EXPORT FlexLayout : public LayoutManager {
// Spacing between child views and host view border.
gfx::Insets interior_margin_;
- // Default spacing to put around child views.
- gfx::Insets default_child_margins_;
-
- // Child-view-specific details (e.g. hidden status, flex rules, etc.)
- std::map<const View*, internal::ChildLayoutParams> child_params_;
-
// The alignment of children in the main axis. This is start by default.
LayoutAlignment main_axis_alignment_ = LayoutAlignment::kStart;
@@ -156,15 +222,9 @@ class VIEWS_EXPORT FlexLayout : public LayoutManager {
// The minimum cross axis size for the layout.
int minimum_cross_axis_size_ = 0;
- // Flex specification for components with no flex set.
- FlexSpecification default_flex_;
-
- // The view that this FlexLayout is managing the layout for.
- views::View* host_ = nullptr;
-
- // Internal data used to cache layout information, etc. All definitions and
- // data are module-private.
- std::unique_ptr<internal::FlexLayoutInternal> internal_;
+ // Default properties for any views that don't have them explicitly set for
+ // this layout.
+ PropertyHandler layout_defaults_{this};
DISALLOW_COPY_AND_ASSIGN(FlexLayout);
};
diff --git a/chromium/ui/views/layout/flex_layout_types.cc b/chromium/ui/views/layout/flex_layout_types.cc
index 7100e688053..6950570972d 100644
--- a/chromium/ui/views/layout/flex_layout_types.cc
+++ b/chromium/ui/views/layout/flex_layout_types.cc
@@ -9,7 +9,6 @@
#include <utility>
#include "base/bind.h"
-#include "base/strings/stringprintf.h"
#include "ui/gfx/geometry/size.h"
#include "ui/views/view.h"
@@ -17,12 +16,6 @@ namespace views {
namespace {
-std::string OptionalToString(const base::Optional<int>& opt) {
- if (!opt.has_value())
- return "_";
- return base::StringPrintf("%d", opt.value());
-}
-
// Default Flex Rules ----------------------------------------------------------
// Interpolates a size between minimum, preferred size, and upper bound based on
@@ -97,7 +90,9 @@ gfx::Size GetPreferredSize(MinimumFlexSizeRule minimum_size_rule,
// Note that this is an adjustment made for practical considerations, and may
// not be "correct" in some absolute sense. Let's revisit at some point.
const int preferred_height =
- std::max(preferred.height(), view->GetHeightForWidth(width));
+ width >= preferred.width()
+ ? preferred.height()
+ : std::max(preferred.height(), view->GetHeightForWidth(width));
if (!maximum_size.height()) {
// Not having a maximum size is different from having a large available
@@ -120,44 +115,6 @@ FlexRule GetDefaultFlexRule(
} // namespace
-// SizeBounds ------------------------------------------------------------------
-
-SizeBounds::SizeBounds() = default;
-
-SizeBounds::SizeBounds(const base::Optional<int>& width,
- const base::Optional<int>& height)
- : width_(width), height_(height) {}
-
-SizeBounds::SizeBounds(const SizeBounds& other)
- : width_(other.width()), height_(other.height()) {}
-
-SizeBounds::SizeBounds(const gfx::Size& other)
- : width_(other.width()), height_(other.height()) {}
-
-void SizeBounds::Enlarge(int width, int height) {
- if (width_)
- width_ = std::max(0, *width_ + width);
- if (height_)
- height_ = std::max(0, *height_ + height);
-}
-
-bool SizeBounds::operator==(const SizeBounds& other) const {
- return width_ == other.width_ && height_ == other.height_;
-}
-
-bool SizeBounds::operator!=(const SizeBounds& other) const {
- return !(*this == other);
-}
-
-bool SizeBounds::operator<(const SizeBounds& other) const {
- return std::tie(height_, width_) < std::tie(other.height_, other.width_);
-}
-
-std::string SizeBounds::ToString() const {
- return base::StringPrintf("%s x %s", OptionalToString(width()).c_str(),
- OptionalToString(height()).c_str());
-}
-
// FlexSpecification -----------------------------------------------------------
FlexSpecification::FlexSpecification() : rule_(GetDefaultFlexRule()) {}
@@ -193,4 +150,112 @@ FlexSpecification FlexSpecification::WithOrder(int order) const {
return FlexSpecification(rule_, order, weight_);
}
+// Inset1D ---------------------------------------------------------------------
+
+void Inset1D::SetInsets(int leading, int trailing) {
+ leading_ = leading;
+ trailing_ = trailing;
+}
+
+void Inset1D::Expand(int leading, int trailing) {
+ leading_ += leading;
+ trailing_ += trailing;
+}
+
+bool Inset1D::operator==(const Inset1D& other) const {
+ return leading_ == other.leading_ && trailing_ == other.trailing_;
+}
+
+bool Inset1D::operator!=(const Inset1D& other) const {
+ return !(*this == other);
+}
+
+bool Inset1D::operator<(const Inset1D& other) const {
+ return std::tie(leading_, trailing_) <
+ std::tie(other.leading_, other.trailing_);
+}
+
+std::string Inset1D::ToString() const {
+ return base::StringPrintf("%d, %d", leading(), trailing());
+}
+
+// Span ------------------------------------------------------------------------
+
+void Span::SetSpan(int start, int length) {
+ start_ = start;
+ length_ = std::max(0, length);
+}
+
+void Span::Expand(int leading, int trailing) {
+ const int end = this->end();
+ set_start(start_ - leading);
+ set_end(end + trailing);
+}
+
+void Span::Inset(int leading, int trailing) {
+ Expand(-leading, -trailing);
+}
+
+void Span::Inset(const Inset1D& insets) {
+ Inset(insets.leading(), insets.trailing());
+}
+
+void Span::Center(const Span& container, const Inset1D& margins) {
+ int remaining = container.length() - length();
+
+ // Case 1: no room for any margins. Just center the span in the container,
+ // with equal overflow on each side.
+ if (remaining <= 0) {
+ set_start(container.start() + std::ceil(remaining * 0.5f));
+ return;
+ }
+
+ // Case 2: room for only part of the margins.
+ if (margins.size() > remaining) {
+ float scale = float{remaining} / float{margins.size()};
+ set_start(container.start() + std::roundf(scale * margins.leading()));
+ return;
+ }
+
+ // Case 3: room for both span and margins. Center the whole unit.
+ remaining -= margins.size();
+ set_start(container.start() + remaining / 2 + margins.leading());
+}
+
+void Span::Align(const Span& container,
+ LayoutAlignment alignment,
+ const Inset1D& margins) {
+ switch (alignment) {
+ case LayoutAlignment::kStart:
+ set_start(container.start() + margins.leading());
+ break;
+ case LayoutAlignment::kEnd:
+ set_start(container.end() - (margins.trailing() + length()));
+ break;
+ case LayoutAlignment::kCenter:
+ Center(container, margins);
+ break;
+ case LayoutAlignment::kStretch:
+ SetSpan(container.start() + margins.leading(),
+ std::max(0, container.length() - margins.size()));
+ break;
+ }
+}
+
+bool Span::operator==(const Span& other) const {
+ return start_ == other.start_ && length_ == other.length_;
+}
+
+bool Span::operator!=(const Span& other) const {
+ return !(*this == other);
+}
+
+bool Span::operator<(const Span& other) const {
+ return std::tie(start_, length_) < std::tie(other.start_, other.length_);
+}
+
+std::string Span::ToString() const {
+ return base::StringPrintf("%d [%d]", start(), length());
+}
+
} // namespace views
diff --git a/chromium/ui/views/layout/flex_layout_types.h b/chromium/ui/views/layout/flex_layout_types.h
index f018d6ab166..d74f11ad023 100644
--- a/chromium/ui/views/layout/flex_layout_types.h
+++ b/chromium/ui/views/layout/flex_layout_types.h
@@ -5,11 +5,13 @@
#ifndef UI_VIEWS_LAYOUT_FLEX_LAYOUT_TYPES_H_
#define UI_VIEWS_LAYOUT_FLEX_LAYOUT_TYPES_H_
+#include <algorithm>
#include <memory>
#include <string>
#include "base/callback.h"
#include "base/optional.h"
+#include "ui/views/layout/layout_types.h"
#include "ui/views/views_export.h"
namespace gfx {
@@ -20,46 +22,9 @@ namespace views {
class View;
-// Whether a layout is oriented horizontally or vertically.
-enum class LayoutOrientation {
- kHorizontal,
- kVertical,
-};
-
// Describes how elements should be aligned within a layout.
enum class LayoutAlignment { kStart, kCenter, kEnd, kStretch };
-// Stores an optional width and height upper bound. Used when calculating the
-// preferred size of a layout pursuant to a maximum available size.
-class VIEWS_EXPORT SizeBounds {
- public:
- SizeBounds();
- SizeBounds(const base::Optional<int>& width,
- const base::Optional<int>& height);
- explicit SizeBounds(const gfx::Size& size);
- SizeBounds(const SizeBounds& other);
-
- const base::Optional<int>& width() const { return width_; }
- void set_width(const base::Optional<int>& width) { width_ = width; }
-
- const base::Optional<int>& height() const { return height_; }
- void set_height(const base::Optional<int>& height) { height_ = height; }
-
- // Enlarges (or shrinks, if negative) each upper bound that is present by the
- // specified amounts.
- void Enlarge(int width, int height);
-
- bool operator==(const SizeBounds& other) const;
- bool operator!=(const SizeBounds& other) const;
- bool operator<(const SizeBounds& other) const;
-
- std::string ToString() const;
-
- private:
- base::Optional<int> width_;
- base::Optional<int> height_;
-};
-
// Callback used to specify the size of a child view based on its size bounds.
// Create your own custom rules, or use the Minimum|MaximumFlexSizeRule
// constants below for common behaviors.
@@ -159,6 +124,85 @@ class VIEWS_EXPORT FlexSpecification {
int weight_ = 0;
};
+// Represents insets in a single dimension.
+class Inset1D {
+ public:
+ constexpr Inset1D() = default;
+ constexpr explicit Inset1D(int all) : leading_(all), trailing_(all) {}
+ constexpr Inset1D(int leading, int trailing)
+ : leading_(leading), trailing_(trailing) {}
+
+ constexpr int leading() const { return leading_; }
+ void set_leading(int leading) { leading_ = leading; }
+
+ constexpr int trailing() const { return trailing_; }
+ void set_trailing(int trailing) { trailing_ = trailing; }
+
+ constexpr int size() const { return leading_ + trailing_; }
+
+ void SetInsets(int leading, int trailing);
+ void Expand(int delta_leading, int delta_trailing);
+
+ constexpr bool is_empty() const { return leading_ == 0 && trailing_ == 0; }
+ bool operator==(const Inset1D& other) const;
+ bool operator!=(const Inset1D& other) const;
+ bool operator<(const Inset1D& other) const;
+
+ std::string ToString() const;
+
+ private:
+ int leading_ = 0;
+ int trailing_ = 0;
+};
+
+// Represents a line segment in one dimension with a starting point and length.
+class Span {
+ public:
+ constexpr Span() = default;
+ constexpr Span(int start, int length) : start_(start), length_(length) {}
+
+ constexpr int start() const { return start_; }
+ void set_start(int start) { start_ = start; }
+
+ constexpr int length() const { return length_; }
+ void set_length(int length) { length_ = std::max(0, length); }
+
+ constexpr int end() const { return start_ + length_; }
+ void set_end(int end) { set_length(end - start_); }
+
+ void SetSpan(int start, int length);
+
+ // Expands the span by |leading| at the front (reducing the value of start()
+ // if |leading| is positive) and by |trailing| at the end (increasing the
+ // value of end() if |trailing| is positive).
+ void Expand(int leading, int trailing);
+
+ // Opposite of Expand(). Shrinks each end of the span by the specified amount.
+ void Inset(int leading, int trailing);
+ void Inset(const Inset1D& insets);
+
+ // Centers the span in another span, with optional margins.
+ // Overflow is handled gracefully.
+ void Center(const Span& container, const Inset1D& margins = Inset1D());
+
+ // Aligns the span in another span, with optional margins, using the specified
+ // alignment. Overflow is handled gracefully.
+ void Align(const Span& container,
+ LayoutAlignment alignment,
+ const Inset1D& margins = Inset1D());
+
+ constexpr bool is_empty() const { return length_ == 0; }
+ bool operator==(const Span& other) const;
+ bool operator!=(const Span& other) const;
+ bool operator<(const Span& other) const;
+
+ std::string ToString() const;
+
+ private:
+ int start_ = 0;
+ int length_ = 0;
+};
+
} // namespace views
#endif // UI_VIEWS_LAYOUT_FLEX_LAYOUT_TYPES_H_
diff --git a/chromium/ui/views/layout/flex_layout_types_internal.cc b/chromium/ui/views/layout/flex_layout_types_internal.cc
index aef1542f5bd..f6c636a7b8a 100644
--- a/chromium/ui/views/layout/flex_layout_types_internal.cc
+++ b/chromium/ui/views/layout/flex_layout_types_internal.cc
@@ -27,114 +27,6 @@ std::string OptionalToString(const base::Optional<int>& opt) {
} // namespace
-// Span ------------------------------------------------------------------------
-
-void Span::SetSpan(int start, int length) {
- start_ = start;
- length_ = std::max(0, length);
-}
-
-void Span::Expand(int leading, int trailing) {
- const int end = this->end();
- set_start(start_ - leading);
- set_end(end + trailing);
-}
-
-void Span::Inset(int leading, int trailing) {
- Expand(-leading, -trailing);
-}
-
-void Span::Inset(const Inset1D& insets) {
- Inset(insets.leading(), insets.trailing());
-}
-
-void Span::Center(const Span& container, const Inset1D& margins) {
- int remaining = container.length() - length();
-
- // Case 1: no room for any margins. Just center the span in the container,
- // with equal overflow on each side.
- if (remaining <= 0) {
- set_start(std::ceil(remaining * 0.5f));
- return;
- }
-
- // Case 2: room for only part of the margins.
- if (margins.size() > remaining) {
- float scale = float{remaining} / float{margins.size()};
- set_start(std::roundf(scale * margins.leading()));
- return;
- }
-
- // Case 3: room for both span and margins. Center the whole unit.
- remaining -= margins.size();
- set_start(remaining / 2 + margins.leading());
-}
-
-void Span::Align(const Span& container,
- LayoutAlignment alignment,
- const Inset1D& margins) {
- switch (alignment) {
- case LayoutAlignment::kStart:
- set_start(container.start() + margins.leading());
- break;
- case LayoutAlignment::kEnd:
- set_start(container.end() - (margins.trailing() + length()));
- break;
- case LayoutAlignment::kCenter:
- Center(container, margins);
- break;
- case LayoutAlignment::kStretch:
- SetSpan(container.start() + margins.leading(),
- std::max(0, container.length() - margins.size()));
- break;
- }
-}
-
-bool Span::operator==(const Span& other) const {
- return start_ == other.start_ && length_ == other.length_;
-}
-
-bool Span::operator!=(const Span& other) const {
- return !(*this == other);
-}
-
-bool Span::operator<(const Span& other) const {
- return std::tie(start_, length_) < std::tie(other.start_, other.length_);
-}
-
-std::string Span::ToString() const {
- return base::StringPrintf("%d [%d]", start(), length());
-}
-
-// Inset1D ---------------------------------------------------------------------
-
-void Inset1D::SetInsets(int leading, int trailing) {
- leading_ = leading;
- trailing_ = trailing;
-}
-
-void Inset1D::Expand(int delta_leading, int delta_trailing) {
- leading_ += delta_leading;
- trailing_ += delta_trailing;
-}
-
-bool Inset1D::operator==(const Inset1D& other) const {
- return leading_ == other.leading_ && trailing_ == other.trailing_;
-}
-
-bool Inset1D::operator!=(const Inset1D& other) const {
- return !(*this == other);
-}
-
-bool Inset1D::operator<(const Inset1D& other) const {
- return std::tie(leading_, trailing_) <
- std::tie(other.leading_, other.trailing_);
-}
-
-std::string Inset1D::ToString() const {
- return base::StringPrintf("%d, %d", leading(), trailing());
-}
-
// NormalizedPoint -------------------------------------------------------------
void NormalizedPoint::SetPoint(int main, int cross) {
@@ -250,6 +142,10 @@ void NormalizedSizeBounds::Expand(int main, int cross) {
cross_ = std::max(0, *cross_ + cross);
}
+void NormalizedSizeBounds::Inset(const NormalizedInsets& insets) {
+ Expand(-insets.main_size(), -insets.cross_size());
+}
+
bool NormalizedSizeBounds::operator==(const NormalizedSizeBounds& other) const {
return main_ == other.main_ && cross_ == other.cross_;
}
@@ -310,6 +206,7 @@ void NormalizedRect::SetRect(int origin_main,
origin_.SetPoint(origin_main, origin_cross);
size_.SetSize(size_main, size_cross);
}
+
void NormalizedRect::SetByBounds(int origin_main,
int origin_cross,
int max_main,
@@ -318,17 +215,25 @@ void NormalizedRect::SetByBounds(int origin_main,
size_.SetSize(std::max(0, max_main - origin_main),
std::max(0, max_cross - origin_cross));
}
+
void NormalizedRect::Inset(const NormalizedInsets& insets) {
Inset(insets.main_leading(), insets.cross_leading(), insets.main_trailing(),
insets.cross_trailing());
}
+
void NormalizedRect::Inset(int main, int cross) {
Inset(main, cross, main, cross);
}
+
void NormalizedRect::Inset(int main_leading,
int cross_leading,
int main_trailing,
- int cross_trailing) {}
+ int cross_trailing) {
+ origin_.Offset(main_leading, cross_leading);
+ size_.Enlarge(-(main_leading + main_trailing),
+ -(cross_leading + cross_trailing));
+}
+
void NormalizedRect::Offset(int main, int cross) {
origin_.Offset(main, cross);
}
diff --git a/chromium/ui/views/layout/flex_layout_types_internal.h b/chromium/ui/views/layout/flex_layout_types_internal.h
index 80b0231fda0..b52361bd390 100644
--- a/chromium/ui/views/layout/flex_layout_types_internal.h
+++ b/chromium/ui/views/layout/flex_layout_types_internal.h
@@ -9,6 +9,7 @@
#include "base/optional.h"
#include "ui/views/layout/flex_layout_types.h"
+#include "ui/views/views_export.h"
namespace gfx {
class Insets;
@@ -23,95 +24,13 @@ class SizeBounds;
namespace internal {
-// Represents insets in a single dimension.
-class Inset1D {
- public:
- constexpr Inset1D() = default;
- constexpr explicit Inset1D(int all) : leading_(all), trailing_(all) {}
- constexpr Inset1D(int leading, int trailing)
- : leading_(leading), trailing_(trailing) {}
-
- constexpr int leading() const { return leading_; }
- void set_leading(int leading) { leading_ = leading; }
-
- constexpr int trailing() const { return trailing_; }
- void set_trailing(int trailing) { trailing_ = trailing; }
-
- constexpr int size() const { return leading_ + trailing_; }
-
- void SetInsets(int leading, int trailing);
- void Expand(int delta_leading, int delta_trailing);
-
- constexpr bool is_empty() const { return leading_ == 0 && trailing_ == 0; }
- bool operator==(const Inset1D& other) const;
- bool operator!=(const Inset1D& other) const;
- bool operator<(const Inset1D& other) const;
-
- std::string ToString() const;
-
- private:
- int leading_ = 0;
- int trailing_ = 0;
-};
-
-// Represents a line segment in one dimension with a starting point and length.
-class Span {
- public:
- constexpr Span() = default;
- constexpr Span(int start, int length) : start_(start), length_(length) {}
-
- constexpr int start() const { return start_; }
- void set_start(int start) { start_ = start; }
-
- constexpr int length() const { return length_; }
- void set_length(int length) {
- DCHECK_GE(length, 0);
- length_ = length;
- }
-
- constexpr int end() const { return start_ + length_; }
- void set_end(int end) {
- DCHECK_GE(end, start_);
- length_ = end - start_;
- }
-
- void SetSpan(int start, int length);
-
- // Expands the span by |leading| at the front (reducing the value of start()
- // if |leading| is positive) and by |trailing| at the end (increasing the
- // value of end() if |trailing| is positive).
- void Expand(int leading, int trailing);
-
- // Opposite of Expand(). Shrinks each end of the span by the specified amount.
- void Inset(int leading, int trailing);
- void Inset(const Inset1D& insets);
-
- // Centers the span in another span, with optional margins.
- // Overflow is handled gracefully.
- void Center(const Span& container, const Inset1D& margins = Inset1D());
-
- // Aligns the span in another span, with optional margins, using the specified
- // alignment. Overflow is handled gracefully.
- void Align(const Span& container,
- LayoutAlignment alignment,
- const Inset1D& margins = Inset1D());
-
- constexpr bool is_empty() const { return length_ == 0; }
- bool operator==(const Span& other) const;
- bool operator!=(const Span& other) const;
- bool operator<(const Span& other) const;
-
- std::string ToString() const;
-
- private:
- int start_ = 0;
- int length_ = 0;
-};
+// NOTE: classes in this namespace are marked as VIEWS_EXPORT for unit testing
+// purposes only and should not be used outside the views library.
// Represents a point in layout space - that is, a point on the main and cross
// axes of the layout (regardless of whether it is vertically or horizontally
// oriented.
-class NormalizedPoint {
+class VIEWS_EXPORT NormalizedPoint {
public:
constexpr NormalizedPoint() = default;
constexpr NormalizedPoint(int main, int cross) : main_(main), cross_(cross) {}
@@ -139,7 +58,7 @@ class NormalizedPoint {
// Represents a size in layout space - that is, a size on the main and cross
// axes of the layout (regardless of whether it is vertically or horizontally
// oriented.
-class NormalizedSize {
+class VIEWS_EXPORT NormalizedSize {
public:
constexpr NormalizedSize() = default;
constexpr NormalizedSize(int main, int cross) : main_(main), cross_(cross) {}
@@ -173,7 +92,7 @@ class NormalizedSize {
// Represents insets in layout space - that is, insets on the main and cross
// axes of the layout (regardless of whether it is vertically or horizontally
// oriented.
-class NormalizedInsets {
+class VIEWS_EXPORT NormalizedInsets {
public:
constexpr NormalizedInsets() = default;
constexpr explicit NormalizedInsets(int all) : main_(all), cross_(all) {}
@@ -230,7 +149,7 @@ class NormalizedInsets {
// Represents size bounds in layout space - that is, a set of size bounds using
// the main and cross axes of the layout (regardless of whether it is vertically
// or horizontally oriented).
-class NormalizedSizeBounds {
+class VIEWS_EXPORT NormalizedSizeBounds {
public:
NormalizedSizeBounds();
NormalizedSizeBounds(const base::Optional<int>& main,
@@ -245,6 +164,7 @@ class NormalizedSizeBounds {
void set_cross(const base::Optional<int>& cross) { cross_ = cross; }
void Expand(int main, int cross);
+ void Inset(const NormalizedInsets& insets);
bool operator==(const NormalizedSizeBounds& other) const;
bool operator!=(const NormalizedSizeBounds& other) const;
@@ -260,7 +180,7 @@ class NormalizedSizeBounds {
// Represents a rectangle in layout space - that is, a rectangle whose
// dimensions align with the main and cross axis of the layout (regardless of
// whether the layout is vertically or horizontally oriented).
-class NormalizedRect {
+class VIEWS_EXPORT NormalizedRect {
public:
constexpr NormalizedRect() = default;
constexpr NormalizedRect(const NormalizedPoint& origin,
diff --git a/chromium/ui/views/layout/flex_layout_types_internal_unittest.cc b/chromium/ui/views/layout/flex_layout_types_internal_unittest.cc
new file mode 100644
index 00000000000..8dceb4e515c
--- /dev/null
+++ b/chromium/ui/views/layout/flex_layout_types_internal_unittest.cc
@@ -0,0 +1,50 @@
+// Copyright (c) 2018 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/layout/flex_layout_types_internal.h"
+
+#include "testing/gtest/include/gtest/gtest.h"
+
+namespace views {
+namespace internal {
+
+TEST(NormalizedRectTest, Inset_NormalizedInsets) {
+ NormalizedRect rect(1, 2, 10, 11);
+ constexpr NormalizedInsets kInsets(1, 2, 3, 4);
+ rect.Inset(kInsets);
+ EXPECT_EQ(2, rect.origin_main());
+ EXPECT_EQ(4, rect.origin_cross());
+ EXPECT_EQ(6, rect.size_main());
+ EXPECT_EQ(5, rect.size_cross());
+}
+
+TEST(NormalizedRectTest, Inset_FourValue) {
+ NormalizedRect rect(1, 2, 10, 11);
+ rect.Inset(1, 2, 3, 4);
+ EXPECT_EQ(2, rect.origin_main());
+ EXPECT_EQ(4, rect.origin_cross());
+ EXPECT_EQ(6, rect.size_main());
+ EXPECT_EQ(5, rect.size_cross());
+}
+
+TEST(NormalizedRectTest, Inset_TwoValue) {
+ NormalizedRect rect(1, 2, 10, 11);
+ rect.Inset(3, 4);
+ EXPECT_EQ(4, rect.origin_main());
+ EXPECT_EQ(6, rect.origin_cross());
+ EXPECT_EQ(4, rect.size_main());
+ EXPECT_EQ(3, rect.size_cross());
+}
+
+TEST(NormalizedRectTest, Inset_Negative) {
+ NormalizedRect rect(1, 2, 10, 11);
+ rect.Inset(-1, -2, -3, -4);
+ EXPECT_EQ(0, rect.origin_main());
+ EXPECT_EQ(0, rect.origin_cross());
+ EXPECT_EQ(14, rect.size_main());
+ EXPECT_EQ(17, rect.size_cross());
+}
+
+} // namespace internal
+} // namespace views
diff --git a/chromium/ui/views/layout/flex_layout_unittest.cc b/chromium/ui/views/layout/flex_layout_unittest.cc
index f32ba75608c..48ba06cb200 100644
--- a/chromium/ui/views/layout/flex_layout_unittest.cc
+++ b/chromium/ui/views/layout/flex_layout_unittest.cc
@@ -7,6 +7,7 @@
#include <stddef.h>
#include <algorithm>
+#include <utility>
#include <vector>
#include "base/bind.h"
@@ -116,6 +117,7 @@ class FlexLayoutTest : public testing::Test {
protected:
// Constants re-used in many tests.
+ static const Insets kSmallInsets;
static const Insets kLayoutInsets;
static const Insets kLargeInsets;
static const Size kChild1Size;
@@ -147,6 +149,7 @@ class FlexLayoutTest : public testing::Test {
FlexLayout* layout_;
};
+const Insets FlexLayoutTest::kSmallInsets{1, 2, 3, 4};
const Insets FlexLayoutTest::kLayoutInsets{5, 6, 7, 9};
const Insets FlexLayoutTest::kLargeInsets{10, 11, 12, 13};
const Size FlexLayoutTest::kChild1Size{12, 10};
@@ -209,13 +212,20 @@ TEST_F(FlexLayoutTest, GetMinimumSize_Empty) {
EXPECT_EQ(Size(0, 0), host_->GetMinimumSize());
}
-TEST_F(FlexLayoutTest, GetMinimumSize_Empty_ViewInsets) {
+TEST_F(FlexLayoutTest, GetMinimumSize_Empty_ViewInsets_Horizontal) {
layout_->SetOrientation(LayoutOrientation::kHorizontal);
layout_->SetCollapseMargins(false);
host_->SetBorder(CreateEmptyBorder(kLayoutInsets));
EXPECT_EQ(Size(15, 12), host_->GetMinimumSize());
}
+TEST_F(FlexLayoutTest, GetMinimumSize_Empty_ViewInsets_Vertical) {
+ layout_->SetOrientation(LayoutOrientation::kVertical);
+ layout_->SetCollapseMargins(false);
+ host_->SetBorder(CreateEmptyBorder(kLayoutInsets));
+ EXPECT_EQ(Size(15, 12), host_->GetMinimumSize());
+}
+
TEST_F(FlexLayoutTest, GetMinimumSize_Empty_InternalMargin_Collapsed) {
layout_->SetOrientation(LayoutOrientation::kHorizontal);
layout_->SetCollapseMargins(true);
@@ -235,7 +245,7 @@ TEST_F(FlexLayoutTest,
layout_->SetOrientation(LayoutOrientation::kHorizontal);
layout_->SetCollapseMargins(false);
layout_->SetInteriorMargin(kLayoutInsets);
- layout_->SetDefaultChildMargins(gfx::Insets(11, 11));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(11, 11));
EXPECT_EQ(Size(15, 12), host_->GetMinimumSize());
}
@@ -247,8 +257,8 @@ TEST_F(FlexLayoutTest, GetMinimumSize_MinimumCross_Horizontal) {
EXPECT_EQ(Size(9, 7), host_->GetMinimumSize());
layout_->SetMinimumCrossAxisSize(10);
EXPECT_EQ(Size(9, 10), host_->GetMinimumSize());
- host_->SetBorder(CreateEmptyBorder(2, 2, 2, 2));
- EXPECT_EQ(Size(13, 14), host_->GetMinimumSize());
+ host_->SetBorder(CreateEmptyBorder(kSmallInsets));
+ EXPECT_EQ(Size(15, 14), host_->GetMinimumSize());
}
TEST_F(FlexLayoutTest, GetMinimumSize_MinimumCross_Vertical) {
@@ -259,8 +269,8 @@ TEST_F(FlexLayoutTest, GetMinimumSize_MinimumCross_Vertical) {
EXPECT_EQ(Size(9, 7), host_->GetMinimumSize());
layout_->SetMinimumCrossAxisSize(10);
EXPECT_EQ(Size(10, 7), host_->GetMinimumSize());
- host_->SetBorder(CreateEmptyBorder(2, 2, 2, 2));
- EXPECT_EQ(Size(14, 11), host_->GetMinimumSize());
+ host_->SetBorder(CreateEmptyBorder(kSmallInsets));
+ EXPECT_EQ(Size(16, 11), host_->GetMinimumSize());
}
// Visibility and Inclusion Tests ----------------------------------------------
@@ -315,7 +325,6 @@ TEST_F(FlexLayoutTest, Layout_VisibilitySetBeforeAdd) {
View* child3 = AddChild(kChild3Size);
host_->Layout();
- EXPECT_EQ(true, layout_->IsHiddenByOwner(child2));
EXPECT_FALSE(child2->GetVisible());
EXPECT_EQ(Rect(6, 5, 12, 10), child1->bounds());
EXPECT_EQ(Rect(18, 5, 17, 13), child3->bounds());
@@ -324,7 +333,6 @@ TEST_F(FlexLayoutTest, Layout_VisibilitySetBeforeAdd) {
// This should have no additional effect since the child is already invisible.
child2->SetVisible(false);
host_->Layout();
- EXPECT_EQ(true, layout_->IsHiddenByOwner(child2));
EXPECT_FALSE(child2->GetVisible());
EXPECT_EQ(Rect(6, 5, 12, 10), child1->bounds());
EXPECT_EQ(Rect(18, 5, 17, 13), child3->bounds());
@@ -334,7 +342,6 @@ TEST_F(FlexLayoutTest, Layout_VisibilitySetBeforeAdd) {
host_->Layout();
std::vector<Rect> expected{Rect(6, 5, 12, 10), Rect(18, 5, 13, 11),
Rect(31, 5, 17, 13)};
- EXPECT_EQ(false, layout_->IsHiddenByOwner(child2));
EXPECT_TRUE(child2->GetVisible());
EXPECT_EQ(expected, GetChildBounds());
EXPECT_EQ(Size(57, 25), host_->GetPreferredSize());
@@ -351,7 +358,6 @@ TEST_F(FlexLayoutTest, Layout_VisibilitySetAfterAdd) {
child2->SetVisible(false);
host_->Layout();
- EXPECT_EQ(true, layout_->IsHiddenByOwner(child2));
EXPECT_FALSE(child2->GetVisible());
EXPECT_EQ(Rect(6, 5, 12, 10), child1->bounds());
EXPECT_EQ(Rect(18, 5, 17, 13), child3->bounds());
@@ -361,7 +367,6 @@ TEST_F(FlexLayoutTest, Layout_VisibilitySetAfterAdd) {
host_->Layout();
std::vector<Rect> expected{Rect(6, 5, 12, 10), Rect(18, 5, 13, 11),
Rect(31, 5, 17, 13)};
- EXPECT_EQ(false, layout_->IsHiddenByOwner(child2));
EXPECT_TRUE(child2->GetVisible());
EXPECT_EQ(expected, GetChildBounds());
EXPECT_EQ(Size(57, 25), host_->GetPreferredSize());
@@ -376,12 +381,11 @@ TEST_F(FlexLayoutTest,
View* child1 = AddChild(kChild1Size);
View* child2 = AddChild(kChild2Size);
View* child3 = AddChild(kChild3Size);
- layout_->SetFlexForView(child2, kDropOut);
+ child2->SetProperty(views::kFlexBehaviorKey, kDropOut);
// Layout makes child view invisible due to flex rule.
host_->SetSize(Size(40, 25));
host_->Layout();
- EXPECT_EQ(false, layout_->IsHiddenByOwner(child2));
EXPECT_FALSE(child2->GetVisible());
EXPECT_EQ(Rect(6, 5, 12, 10), child1->bounds());
EXPECT_EQ(Rect(18, 5, 17, 13), child3->bounds());
@@ -390,11 +394,7 @@ TEST_F(FlexLayoutTest,
// Now we will make child explicitly hidden.
child2->SetVisible(false);
- EXPECT_EQ(true, layout_->IsHiddenByOwner(child2));
-
- // Layout is the same, but we should report that the view is hidden by owner.
host_->Layout();
- EXPECT_EQ(true, layout_->IsHiddenByOwner(child2));
EXPECT_FALSE(child2->GetVisible());
EXPECT_EQ(Rect(6, 5, 12, 10), child1->bounds());
EXPECT_EQ(Rect(18, 5, 17, 13), child3->bounds());
@@ -410,20 +410,18 @@ TEST_F(FlexLayoutTest, Layout_Exlcude) {
View* child2 = AddChild(kChild2Size);
const View* child3 = AddChild(kChild3Size);
- layout_->SetViewExcluded(child2, true);
+ layout_->SetChildViewIgnoredByLayout(child2, true);
child2->SetBounds(3, 3, 3, 3);
host_->Layout();
- EXPECT_EQ(true, layout_->IsViewExcluded(child2));
EXPECT_EQ(Rect(3, 3, 3, 3), child2->bounds());
EXPECT_EQ(Rect(6, 5, 12, 10), child1->bounds());
EXPECT_EQ(Rect(18, 5, 17, 13), child3->bounds());
EXPECT_EQ(Size(44, 25), host_->GetPreferredSize());
- layout_->SetViewExcluded(child2, false);
+ layout_->SetChildViewIgnoredByLayout(child2, false);
host_->Layout();
std::vector<Rect> expected{Rect(6, 5, 12, 10), Rect(18, 5, 13, 11),
Rect(31, 5, 17, 13)};
- EXPECT_EQ(false, layout_->IsViewExcluded(child2));
EXPECT_EQ(expected, GetChildBounds());
EXPECT_EQ(Size(57, 25), host_->GetPreferredSize());
}
@@ -585,7 +583,7 @@ TEST_F(FlexLayoutTest,
EXPECT_EQ(expected, GetChildBounds());
EXPECT_EQ(Size(57, 25), host_->GetPreferredSize());
- child1->SetProperty(views::kMarginsKey, new Insets(20, 21, 22, 23));
+ child1->SetProperty(views::kMarginsKey, Insets(20, 21, 22, 23));
host_->InvalidateLayout();
host_->Layout();
expected = std::vector<Rect>{Rect(27, 25, 12, 10), Rect(62, 5, 13, 11),
@@ -593,16 +591,16 @@ TEST_F(FlexLayoutTest,
EXPECT_EQ(expected, GetChildBounds());
EXPECT_EQ(Size(101, 64), host_->GetPreferredSize());
- child2->SetProperty(views::kMarginsKey, new Insets(1, 1, 1, 1));
+ child2->SetProperty(views::kMarginsKey, Insets(1, 1, 1, 1));
host_->InvalidateLayout();
- layout_->SetDefaultChildMargins(gfx::Insets(0, 3));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(0, 3));
host_->Layout();
expected = std::vector<Rect>{Rect(27, 25, 12, 10), Rect(63, 6, 13, 11),
Rect(80, 5, 17, 13)};
EXPECT_EQ(expected, GetChildBounds());
EXPECT_EQ(Size(109, 64), host_->GetPreferredSize());
- child3->SetProperty(views::kMarginsKey, new Insets(2, 2, 2, 2));
+ child3->SetProperty(views::kMarginsKey, Insets(2, 2, 2, 2));
host_->InvalidateLayout();
host_->Layout();
expected = std::vector<Rect>{Rect(27, 25, 12, 10), Rect(63, 6, 13, 11),
@@ -617,13 +615,13 @@ TEST_F(FlexLayoutTest,
layout_->SetCollapseMargins(false);
layout_->SetInteriorMargin(kLayoutInsets);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(3));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(3));
View* child1 = AddChild(kChild1Size);
View* child2 = AddChild(kChild2Size);
View* child3 = AddChild(kChild3Size);
- child1->SetProperty(views::kMarginsKey, new Insets(20, 21, 22, 23));
- child2->SetProperty(views::kMarginsKey, new Insets(1, 1, 1, 1));
- child3->SetProperty(views::kMarginsKey, new Insets(2, 2, 2, 2));
+ child1->SetProperty(views::kMarginsKey, Insets(20, 21, 22, 23));
+ child2->SetProperty(views::kMarginsKey, Insets(1, 1, 1, 1));
+ child3->SetProperty(views::kMarginsKey, Insets(2, 2, 2, 2));
host_->InvalidateLayout();
host_->Layout();
std::vector<Rect> expected{Rect(27, 25, 12, 10), Rect(7, 58, 13, 11),
@@ -638,13 +636,13 @@ TEST_F(FlexLayoutTest,
layout_->SetCollapseMargins(true);
layout_->SetInteriorMargin(kLayoutInsets);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(3));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(3));
View* child1 = AddChild(kChild1Size);
View* child2 = AddChild(kChild2Size);
View* child3 = AddChild(kChild3Size);
- child1->SetProperty(views::kMarginsKey, new Insets(20, 21, 22, 23));
- child2->SetProperty(views::kMarginsKey, new Insets(1, 1, 1, 1));
- child3->SetProperty(views::kMarginsKey, new Insets(2, 2, 2, 2));
+ child1->SetProperty(views::kMarginsKey, Insets(20, 21, 22, 23));
+ child2->SetProperty(views::kMarginsKey, Insets(1, 1, 1, 1));
+ child3->SetProperty(views::kMarginsKey, Insets(2, 2, 2, 2));
host_->InvalidateLayout();
host_->Layout();
std::vector<Rect> expected{Rect(21, 20, 12, 10), Rect(56, 5, 13, 11),
@@ -658,13 +656,13 @@ TEST_F(FlexLayoutTest, LayoutMultipleViews_MarginAndSpacing_Collapse_Vertical) {
layout_->SetCollapseMargins(true);
layout_->SetInteriorMargin(kLayoutInsets);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(3));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(3));
View* child1 = AddChild(kChild1Size);
View* child2 = AddChild(kChild2Size);
View* child3 = AddChild(kChild3Size);
- child1->SetProperty(views::kMarginsKey, new Insets(20, 21, 22, 23));
- child2->SetProperty(views::kMarginsKey, new Insets(1, 1, 1, 1));
- child3->SetProperty(views::kMarginsKey, new Insets(2, 2, 2, 2));
+ child1->SetProperty(views::kMarginsKey, Insets(20, 21, 22, 23));
+ child2->SetProperty(views::kMarginsKey, Insets(1, 1, 1, 1));
+ child3->SetProperty(views::kMarginsKey, Insets(2, 2, 2, 2));
host_->InvalidateLayout();
host_->Layout();
std::vector<Rect> expected{Rect(21, 20, 12, 10), Rect(6, 52, 13, 11),
@@ -678,10 +676,10 @@ TEST_F(FlexLayoutTest, LayoutMultipleViews_InteriorPadding) {
layout_->SetCollapseMargins(true);
layout_->SetInteriorMargin(kLayoutInsets);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(10));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(10));
View* child = AddChild(Size(13, 15));
AddChild(kChild3Size);
- child->SetProperty(views::kInternalPaddingKey, new Insets(1, 2, 4, 8));
+ child->SetProperty(views::kInternalPaddingKey, Insets(1, 2, 4, 8));
host_->InvalidateLayout();
host_->Layout();
std::vector<Rect> expected{
@@ -697,11 +695,11 @@ TEST_F(FlexLayoutTest, LayoutMultipleViews_InteriorPadding_Margins) {
layout_->SetCollapseMargins(true);
layout_->SetInteriorMargin(kLayoutInsets);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(2));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(2));
View* child = AddChild(Size(13, 15));
View* child2 = AddChild(kChild3Size);
- child->SetProperty(views::kInternalPaddingKey, new Insets(1, 2, 4, 8));
- child2->SetProperty(views::kMarginsKey, new Insets(5, 5, 5, 5));
+ child->SetProperty(views::kInternalPaddingKey, Insets(1, 2, 4, 8));
+ child2->SetProperty(views::kMarginsKey, Insets(5, 5, 5, 5));
host_->InvalidateLayout();
host_->Layout();
std::vector<Rect> expected{
@@ -717,11 +715,11 @@ TEST_F(FlexLayoutTest, LayoutMultipleViews_InteriorPadding_Additive) {
layout_->SetCollapseMargins(true);
layout_->SetInteriorMargin(kLayoutInsets);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(20));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(20));
View* child = AddChild(Size(13, 15));
View* child2 = AddChild(kChild3Size);
- child->SetProperty(views::kInternalPaddingKey, new Insets(1, 2, 4, 8));
- child2->SetProperty(views::kInternalPaddingKey, new Insets(5, 5, 5, 5));
+ child->SetProperty(views::kInternalPaddingKey, Insets(1, 2, 4, 8));
+ child2->SetProperty(views::kInternalPaddingKey, Insets(5, 5, 5, 5));
host_->InvalidateLayout();
host_->Layout();
std::vector<Rect> expected{
@@ -732,6 +730,97 @@ TEST_F(FlexLayoutTest, LayoutMultipleViews_InteriorPadding_Additive) {
EXPECT_EQ(Size(70, 50), host_->GetPreferredSize());
}
+// Host insets tests -----------------------------------------------------------
+
+TEST_F(FlexLayoutTest, Layout_HostInsets_Horizontal) {
+ layout_->SetOrientation(LayoutOrientation::kHorizontal);
+ host_->SetBorder(CreateEmptyBorder(kLayoutInsets));
+ View* child = AddChild(kChild1Size);
+ host_->Layout();
+ EXPECT_EQ(Rect(6, 5, 12, 10), child->bounds());
+}
+
+TEST_F(FlexLayoutTest, Layout_HostInsets_Vertical) {
+ layout_->SetOrientation(LayoutOrientation::kVertical);
+ host_->SetBorder(CreateEmptyBorder(kLayoutInsets));
+ View* child = AddChild(kChild1Size);
+ host_->Layout();
+ EXPECT_EQ(Rect(6, 5, 12, 10), child->bounds());
+}
+
+TEST_F(FlexLayoutTest, Layout_HostInsets_Horizontal_Leading) {
+ layout_->SetOrientation(LayoutOrientation::kHorizontal);
+ layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
+ layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
+ host_->SetBorder(CreateEmptyBorder(kLayoutInsets));
+ View* child = AddChild(kChild1Size);
+ host_->SetSize({100, 100});
+ EXPECT_EQ(Rect(6, 5, 12, 10), child->bounds());
+}
+
+TEST_F(FlexLayoutTest, Layout_HostInsets_Vertical_Leading) {
+ layout_->SetOrientation(LayoutOrientation::kVertical);
+ layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
+ layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
+ host_->SetBorder(CreateEmptyBorder(kLayoutInsets));
+ View* child = AddChild(kChild1Size);
+ host_->SetSize({100, 100});
+ EXPECT_EQ(Rect(6, 5, 12, 10), child->bounds());
+}
+
+TEST_F(FlexLayoutTest, Layout_HostInsets_Horizontal_Center) {
+ layout_->SetOrientation(LayoutOrientation::kHorizontal);
+ layout_->SetMainAxisAlignment(LayoutAlignment::kCenter);
+ layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
+ host_->SetBorder(CreateEmptyBorder(kLayoutInsets));
+ View* child = AddChild(kChild1Size);
+ host_->SetSize({100, 100});
+ const int expected_x =
+ kLayoutInsets.left() +
+ (host_->size().width() - kChild1Size.width() - kLayoutInsets.width()) / 2;
+ EXPECT_EQ(Rect(expected_x, 5, 12, 10), child->bounds());
+}
+
+TEST_F(FlexLayoutTest, Layout_HostInsets_Vertical_Center) {
+ layout_->SetOrientation(LayoutOrientation::kVertical);
+ layout_->SetMainAxisAlignment(LayoutAlignment::kCenter);
+ layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
+ host_->SetBorder(CreateEmptyBorder(kLayoutInsets));
+ View* child = AddChild(kChild1Size);
+ host_->SetSize({100, 100});
+ const int expected_y =
+ kLayoutInsets.top() +
+ (host_->size().height() - kChild1Size.height() - kLayoutInsets.height()) /
+ 2;
+ EXPECT_EQ(Rect(6, expected_y, 12, 10), child->bounds());
+}
+
+TEST_F(FlexLayoutTest, Layout_HostInsets_Horizontal_End) {
+ layout_->SetOrientation(LayoutOrientation::kHorizontal);
+ layout_->SetMainAxisAlignment(LayoutAlignment::kEnd);
+ layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
+ host_->SetBorder(CreateEmptyBorder(kLayoutInsets));
+ View* child = AddChild(kChild1Size);
+ host_->SetSize({100, 100});
+ const int expected_x =
+ kLayoutInsets.left() +
+ (host_->size().width() - kChild1Size.width() - kLayoutInsets.width());
+ EXPECT_EQ(Rect(expected_x, 5, 12, 10), child->bounds());
+}
+
+TEST_F(FlexLayoutTest, Layout_HostInsets_Vertical_End) {
+ layout_->SetOrientation(LayoutOrientation::kVertical);
+ layout_->SetMainAxisAlignment(LayoutAlignment::kEnd);
+ layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
+ host_->SetBorder(CreateEmptyBorder(kLayoutInsets));
+ View* child = AddChild(kChild1Size);
+ host_->SetSize({100, 100});
+ const int expected_y =
+ kLayoutInsets.top() +
+ (host_->size().height() - kChild1Size.height() - kLayoutInsets.height());
+ EXPECT_EQ(Rect(6, expected_y, 12, 10), child->bounds());
+}
+
// Alignment Tests -------------------------------------------------------------
TEST_F(FlexLayoutTest, Layout_CrossStart) {
@@ -743,9 +832,9 @@ TEST_F(FlexLayoutTest, Layout_CrossStart) {
View* child1 = AddChild(kChild1Size);
View* child2 = AddChild(kChild2Size);
View* child3 = AddChild(kChild3Size);
- child1->SetProperty(views::kMarginsKey, new Insets(kLargeInsets));
- child2->SetProperty(views::kMarginsKey, new Insets(1, 1, 1, 1));
- child3->SetProperty(views::kMarginsKey, new Insets(2, 2, 2, 2));
+ child1->SetProperty(views::kMarginsKey, Insets(kLargeInsets));
+ child2->SetProperty(views::kMarginsKey, Insets(1, 1, 1, 1));
+ child3->SetProperty(views::kMarginsKey, Insets(2, 2, 2, 2));
host_->SetSize(Size(200, 200));
host_->Layout();
EXPECT_EQ(10, child1->origin().y());
@@ -762,9 +851,9 @@ TEST_F(FlexLayoutTest, Layout_CrossCenter) {
View* child1 = AddChild(kChild1Size);
View* child2 = AddChild(kChild2Size);
View* child3 = AddChild(kChild3Size);
- child1->SetProperty(views::kMarginsKey, new Insets(kLargeInsets));
- child2->SetProperty(views::kMarginsKey, new Insets(1, 1, 1, 1));
- child3->SetProperty(views::kMarginsKey, new Insets(2, 2, 2, 2));
+ child1->SetProperty(views::kMarginsKey, Insets(kLargeInsets));
+ child2->SetProperty(views::kMarginsKey, Insets(1, 1, 1, 1));
+ child3->SetProperty(views::kMarginsKey, Insets(2, 2, 2, 2));
host_->SetSize(Size(200, 200));
host_->Layout();
EXPECT_EQ(94, child1->origin().y());
@@ -781,9 +870,9 @@ TEST_F(FlexLayoutTest, Layout_CrossEnd) {
View* child1 = AddChild(kChild1Size);
View* child2 = AddChild(kChild2Size);
View* child3 = AddChild(kChild3Size);
- child1->SetProperty(views::kMarginsKey, new Insets(kLargeInsets));
- child2->SetProperty(views::kMarginsKey, new Insets(1, 1, 1, 1));
- child3->SetProperty(views::kMarginsKey, new Insets(2, 2, 2, 2));
+ child1->SetProperty(views::kMarginsKey, Insets(kLargeInsets));
+ child2->SetProperty(views::kMarginsKey, Insets(1, 1, 1, 1));
+ child3->SetProperty(views::kMarginsKey, Insets(2, 2, 2, 2));
host_->SetSize(Size(200, 200));
host_->Layout();
EXPECT_EQ(178, child1->origin().y());
@@ -800,9 +889,9 @@ TEST_F(FlexLayoutTest, Layout_CrossStretch) {
View* child1 = AddChild(kChild1Size);
View* child2 = AddChild(kChild2Size);
View* child3 = AddChild(kChild3Size);
- child1->SetProperty(views::kMarginsKey, new Insets(kLargeInsets));
- child2->SetProperty(views::kMarginsKey, new Insets(1, 1, 1, 1));
- child3->SetProperty(views::kMarginsKey, new Insets(2, 2, 2, 2));
+ child1->SetProperty(views::kMarginsKey, Insets(kLargeInsets));
+ child2->SetProperty(views::kMarginsKey, Insets(1, 1, 1, 1));
+ child3->SetProperty(views::kMarginsKey, Insets(2, 2, 2, 2));
host_->SetSize(Size(200, 200));
host_->Layout();
EXPECT_EQ(10, child1->origin().y());
@@ -819,13 +908,13 @@ TEST_F(FlexLayoutTest, Layout_AlignStart) {
layout_->SetInteriorMargin(kLayoutInsets);
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(3));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(3));
View* child1 = AddChild(kChild1Size);
View* child2 = AddChild(kChild2Size);
View* child3 = AddChild(kChild3Size);
- child1->SetProperty(views::kMarginsKey, new Insets(20, 21, 22, 23));
- child2->SetProperty(views::kMarginsKey, new Insets(1, 1, 1, 1));
- child3->SetProperty(views::kMarginsKey, new Insets(2, 2, 2, 2));
+ child1->SetProperty(views::kMarginsKey, Insets(20, 21, 22, 23));
+ child2->SetProperty(views::kMarginsKey, Insets(1, 1, 1, 1));
+ child3->SetProperty(views::kMarginsKey, Insets(2, 2, 2, 2));
host_->SetSize(Size(105, 50));
host_->Layout();
std::vector<Rect> expected{Rect(21, 20, 12, 10), Rect(56, 5, 13, 11),
@@ -839,13 +928,13 @@ TEST_F(FlexLayoutTest, Layout_AlignCenter) {
layout_->SetInteriorMargin(kLayoutInsets);
layout_->SetMainAxisAlignment(LayoutAlignment::kCenter);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(3));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(3));
View* child1 = AddChild(kChild1Size);
View* child2 = AddChild(kChild2Size);
View* child3 = AddChild(kChild3Size);
- child1->SetProperty(views::kMarginsKey, new Insets(20, 21, 22, 23));
- child2->SetProperty(views::kMarginsKey, new Insets(1, 1, 1, 1));
- child3->SetProperty(views::kMarginsKey, new Insets(2, 2, 2, 2));
+ child1->SetProperty(views::kMarginsKey, Insets(20, 21, 22, 23));
+ child2->SetProperty(views::kMarginsKey, Insets(1, 1, 1, 1));
+ child3->SetProperty(views::kMarginsKey, Insets(2, 2, 2, 2));
host_->SetSize(Size(105, 50));
host_->Layout();
std::vector<Rect> expected{Rect(25, 20, 12, 10), Rect(60, 5, 13, 11),
@@ -859,13 +948,13 @@ TEST_F(FlexLayoutTest, Layout_AlignEnd) {
layout_->SetInteriorMargin(kLayoutInsets);
layout_->SetMainAxisAlignment(LayoutAlignment::kEnd);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(3));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(3));
View* child1 = AddChild(kChild1Size);
View* child2 = AddChild(kChild2Size);
View* child3 = AddChild(kChild3Size);
- child1->SetProperty(views::kMarginsKey, new Insets(20, 21, 22, 23));
- child2->SetProperty(views::kMarginsKey, new Insets(1, 1, 1, 1));
- child3->SetProperty(views::kMarginsKey, new Insets(2, 2, 2, 2));
+ child1->SetProperty(views::kMarginsKey, Insets(20, 21, 22, 23));
+ child2->SetProperty(views::kMarginsKey, Insets(1, 1, 1, 1));
+ child3->SetProperty(views::kMarginsKey, Insets(2, 2, 2, 2));
host_->SetSize(Size(105, 50));
host_->Layout();
std::vector<Rect> expected{Rect(29, 20, 12, 10), Rect(64, 5, 13, 11),
@@ -882,8 +971,8 @@ TEST_F(FlexLayoutTest, Layout_AddDroppedMargins) {
View* child1 = AddChild(Size(10, 10));
View* child2 = AddChild(Size(10, 10));
View* child3 = AddChild(Size(10, 10));
- child2->SetProperty(views::kMarginsKey, new Insets(1, 1, 1, 1));
- layout_->SetFlexForView(child2, kDropOut);
+ child2->SetProperty(views::kMarginsKey, Insets(1, 1, 1, 1));
+ child2->SetProperty(views::kFlexBehaviorKey, kDropOut);
EXPECT_EQ(Size(30, 20), host_->GetMinimumSize());
host_->SetSize(Size(100, 50));
@@ -899,6 +988,30 @@ TEST_F(FlexLayoutTest, Layout_AddDroppedMargins) {
EXPECT_EQ(Rect(15, 5, 10, 10), child3->bounds());
}
+TEST_F(FlexLayoutTest, Layout_VerticalAlign_WiderThanTall) {
+ // This test ensures we do not regress http://crbug.com/983941
+ // Previously, the width of the host view was erroneously used when
+ // calculating excess main-axis size, causing center-alignment in vertical
+ // layouts in host views that were much wider than tall to be incorrect.
+ layout_->SetOrientation(LayoutOrientation::kVertical);
+ layout_->SetCollapseMargins(true);
+ layout_->SetInteriorMargin(kLayoutInsets);
+ layout_->SetMainAxisAlignment(LayoutAlignment::kCenter);
+ layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(3));
+ View* child1 = AddChild(kChild1Size);
+ View* child2 = AddChild(kChild2Size);
+ View* child3 = AddChild(kChild3Size);
+ child1->SetProperty(views::kMarginsKey, Insets(20, 21, 22, 23));
+ child2->SetProperty(views::kMarginsKey, Insets(1, 1, 1, 1));
+ child3->SetProperty(views::kMarginsKey, Insets(2, 2, 2, 2));
+ host_->SetSize(Size(1000, 100));
+ host_->Layout();
+ std::vector<Rect> expected{Rect(21, 27, 12, 10), Rect(6, 59, 13, 11),
+ Rect(6, 72, 17, 13)};
+ EXPECT_EQ(expected, GetChildBounds());
+}
+
// Flex Tests ------------------------------------------------------------------
TEST_F(FlexLayoutTest, Layout_IgnoreMinimumSize_DropViews) {
@@ -907,20 +1020,21 @@ TEST_F(FlexLayoutTest, Layout_IgnoreMinimumSize_DropViews) {
layout_->SetInteriorMargin(kLayoutInsets);
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(3));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(3));
View* child1 = AddChild(kChild1Size);
View* child2 = AddChild(kChild2Size);
View* child3 = AddChild(kChild3Size);
- child1->SetProperty(views::kMarginsKey, new Insets(kLargeInsets));
- child2->SetProperty(views::kMarginsKey, new Insets(1, 1, 1, 1));
- child3->SetProperty(views::kMarginsKey, new Insets(2, 2, 2, 2));
+ child1->SetProperty(views::kMarginsKey, Insets(kLargeInsets));
+ child2->SetProperty(views::kMarginsKey, Insets(1, 1, 1, 1));
+ child3->SetProperty(views::kMarginsKey, Insets(2, 2, 2, 2));
host_->SetSize(Size(55, 50));
host_->Layout();
std::vector<Rect> expected{Rect(11, 10, 12, 10), Rect(36, 5, 13, 11),
Rect(51, 5, 17, 13)};
EXPECT_EQ(expected, GetChildBounds());
- layout_->SetFlexForView(child1, kDropOut);
+ child1->SetProperty(views::kFlexBehaviorKey, kDropOut);
+ host_->InvalidateLayout();
EXPECT_EQ(Size(77, 32), host_->GetPreferredSize());
EXPECT_EQ(Size(47, 25), host_->GetMinimumSize());
host_->Layout();
@@ -930,8 +1044,9 @@ TEST_F(FlexLayoutTest, Layout_IgnoreMinimumSize_DropViews) {
EXPECT_EQ(Rect(6, 5, 13, 11), child2->bounds());
EXPECT_EQ(Rect(21, 5, 17, 13), child3->bounds());
- layout_->ClearFlexForView(child1);
- layout_->SetFlexForView(child2, kDropOut);
+ child1->ClearProperty(views::kFlexBehaviorKey);
+ child2->SetProperty(views::kFlexBehaviorKey, kDropOut);
+ host_->InvalidateLayout();
EXPECT_EQ(Size(77, 32), host_->GetPreferredSize());
EXPECT_EQ(Size(62, 32), host_->GetMinimumSize());
host_->Layout();
@@ -941,8 +1056,9 @@ TEST_F(FlexLayoutTest, Layout_IgnoreMinimumSize_DropViews) {
EXPECT_EQ(Rect(11, 10, 12, 10), child1->bounds());
EXPECT_EQ(Rect(36, 5, 17, 13), child3->bounds());
- layout_->ClearFlexForView(child2);
- layout_->SetFlexForView(child3, kDropOut);
+ child2->ClearProperty(views::kFlexBehaviorKey);
+ child3->SetProperty(views::kFlexBehaviorKey, kDropOut);
+ host_->InvalidateLayout();
EXPECT_EQ(Size(77, 32), host_->GetPreferredSize());
EXPECT_EQ(Size(58, 32), host_->GetMinimumSize());
host_->Layout();
@@ -959,17 +1075,17 @@ TEST_F(FlexLayoutTest, Layout_IgnoreMinimumSize_DropInOrder) {
layout_->SetInteriorMargin(kLayoutInsets);
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(3));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(3));
View* child1 = AddChild(kChild1Size);
View* child2 = AddChild(kChild2Size);
View* child3 = AddChild(kChild3Size);
- child1->SetProperty(views::kMarginsKey, new Insets(kLargeInsets));
- child2->SetProperty(views::kMarginsKey, new Insets(1, 1, 1, 1));
- child3->SetProperty(views::kMarginsKey, new Insets(2, 2, 2, 2));
+ child1->SetProperty(views::kMarginsKey, Insets(kLargeInsets));
+ child2->SetProperty(views::kMarginsKey, Insets(1, 1, 1, 1));
+ child3->SetProperty(views::kMarginsKey, Insets(2, 2, 2, 2));
// Set flex separately; we'll test default flex later.
- layout_->SetFlexForView(child1, kDropOut);
- layout_->SetFlexForView(child2, kDropOut);
- layout_->SetFlexForView(child3, kDropOut);
+ child1->SetProperty(views::kFlexBehaviorKey, kDropOut);
+ child2->SetProperty(views::kFlexBehaviorKey, kDropOut);
+ child3->SetProperty(views::kFlexBehaviorKey, kDropOut);
EXPECT_EQ(Size(9, 7), host_->GetMinimumSize());
host_->SetSize(Size(100, 50));
@@ -1011,14 +1127,14 @@ TEST_F(FlexLayoutTest, Layout_IgnoreMinimumSize_DropInOrder_DefaultFlex) {
layout_->SetInteriorMargin(kLayoutInsets);
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(3));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(3));
View* child1 = AddChild(kChild1Size);
View* child2 = AddChild(kChild2Size);
View* child3 = AddChild(kChild3Size);
- child1->SetProperty(views::kMarginsKey, new Insets(kLargeInsets));
- child2->SetProperty(views::kMarginsKey, new Insets(1, 1, 1, 1));
- child3->SetProperty(views::kMarginsKey, new Insets(2, 2, 2, 2));
- layout_->SetDefaultFlex(kDropOut);
+ child1->SetProperty(views::kMarginsKey, Insets(kLargeInsets));
+ child2->SetProperty(views::kMarginsKey, Insets(1, 1, 1, 1));
+ child3->SetProperty(views::kMarginsKey, Insets(2, 2, 2, 2));
+ layout_->SetDefault(views::kFlexBehaviorKey, kDropOut);
EXPECT_EQ(Size(9, 7), host_->GetMinimumSize());
host_->SetSize(Size(100, 50));
@@ -1059,15 +1175,15 @@ TEST_F(FlexLayoutTest, Layout_IgnoreMinimumSize_DropByPriority) {
layout_->SetInteriorMargin(kLayoutInsets);
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(3));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(3));
View* child1 = AddChild(kChild1Size);
View* child2 = AddChild(kChild2Size);
View* child3 = AddChild(kChild3Size);
- child1->SetProperty(views::kMarginsKey, new Insets(kLargeInsets));
- child2->SetProperty(views::kMarginsKey, new Insets(1, 1, 1, 1));
- child3->SetProperty(views::kMarginsKey, new Insets(2, 2, 2, 2));
- layout_->SetDefaultFlex(kDropOut);
- layout_->SetFlexForView(child3, kDropOutHighPriority);
+ child1->SetProperty(views::kMarginsKey, Insets(kLargeInsets));
+ child2->SetProperty(views::kMarginsKey, Insets(1, 1, 1, 1));
+ child3->SetProperty(views::kMarginsKey, Insets(2, 2, 2, 2));
+ layout_->SetDefault(views::kFlexBehaviorKey, kDropOut);
+ child3->SetProperty(views::kFlexBehaviorKey, kDropOutHighPriority);
EXPECT_EQ(Size(9, 7), host_->GetMinimumSize());
host_->SetSize(Size(100, 50));
@@ -1101,10 +1217,10 @@ TEST_F(FlexLayoutTest, Layout_Flex_OneViewScales) {
layout_->SetInteriorMargin(Insets(5));
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(5));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(5));
View* child1 = AddChild(Size(10, 20), Size(5, 5));
View* child2 = AddChild(Size(10, 10));
- layout_->SetFlexForView(child1, kFlex1ScaleToMinimum);
+ child1->SetProperty(views::kFlexBehaviorKey, kFlex1ScaleToMinimum);
host_->SetSize(Size(20, 50));
host_->Layout();
@@ -1128,10 +1244,10 @@ TEST_F(FlexLayoutTest, Layout_Flex_OneViewScales_BelowMinimum) {
layout_->SetInteriorMargin(Insets(5));
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(5));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(5));
View* child1 = AddChild(Size(10, 20), Size(5, 5));
View* child2 = AddChild(Size(10, 10));
- layout_->SetFlexForView(child1, kFlex1ScaleToMinimum);
+ child1->SetProperty(views::kFlexBehaviorKey, kFlex1ScaleToMinimum);
host_->SetSize(Size(20, 20));
host_->Layout();
@@ -1146,11 +1262,11 @@ TEST_F(FlexLayoutTest,
layout_->SetInteriorMargin(Insets(5));
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(5));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(5));
View* child1 = AddChild(Size(10, 20), Size(5, 5));
View* child2 = AddChild(Size(10, 10), Size(5, 5));
- layout_->SetFlexForView(child1, kFlex1ScaleToMinimum);
- layout_->SetFlexForView(child2, kDropOut);
+ child1->SetProperty(views::kFlexBehaviorKey, kFlex1ScaleToMinimum);
+ child2->SetProperty(views::kFlexBehaviorKey, kDropOut);
host_->SetSize(Size(20, 20));
host_->Layout();
@@ -1165,11 +1281,11 @@ TEST_F(FlexLayoutTest,
layout_->SetInteriorMargin(Insets(5));
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(5));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(5));
View* child1 = AddChild(Size(10, 20), Size(5, 5));
View* child2 = AddChild(Size(10, 10), Size(5, 5));
- layout_->SetFlexForView(child1, kFlex1ScaleToMinimum);
- layout_->SetFlexForView(child2, kFlex1ScaleToZero);
+ child1->SetProperty(views::kFlexBehaviorKey, kFlex1ScaleToMinimum);
+ child2->SetProperty(views::kFlexBehaviorKey, kFlex1ScaleToZero);
host_->SetSize(Size(20, 19));
host_->Layout();
@@ -1185,8 +1301,8 @@ TEST_F(FlexLayoutTest, Layout_Flex_TwoChildViews_EqualWeight) {
layout_->SetInteriorMargin(Insets(5));
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(5));
- layout_->SetDefaultFlex(kFlex1ScaleToMinimum);
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(5));
+ layout_->SetDefault(views::kFlexBehaviorKey, kFlex1ScaleToMinimum);
View* child1 = AddChild(Size(20, 10), Size(5, 5));
View* child2 = AddChild(Size(20, 10), Size(5, 5));
@@ -1207,8 +1323,8 @@ TEST_F(FlexLayoutTest, Layout_Flex_TwoChildViews_DefaultFlex) {
layout_->SetInteriorMargin(Insets(5));
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(5));
- layout_->SetDefaultFlex(kFlex1ScaleToMinimum);
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(5));
+ layout_->SetDefault(views::kFlexBehaviorKey, kFlex1ScaleToMinimum);
View* child1 = AddChild(Size(20, 10), Size(5, 5));
View* child2 = AddChild(Size(20, 10), Size(5, 5));
@@ -1229,11 +1345,11 @@ TEST_F(FlexLayoutTest, Layout_Flex_TwoChildViews_UnequalWeight) {
layout_->SetInteriorMargin(Insets(5));
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(5));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(5));
View* child1 = AddChild(Size(20, 10), Size(5, 5));
View* child2 = AddChild(Size(20, 10), Size(5, 5));
- layout_->SetFlexForView(child1, kFlex1ScaleToMinimum);
- layout_->SetFlexForView(child2, kFlex2ScaleToMinimum);
+ child1->SetProperty(views::kFlexBehaviorKey, kFlex1ScaleToMinimum);
+ child2->SetProperty(views::kFlexBehaviorKey, kFlex2ScaleToMinimum);
host_->SetSize(Size(45, 20));
host_->Layout();
@@ -1247,11 +1363,11 @@ TEST_F(FlexLayoutTest, Layout_Flex_TwoChildViews_UnequalWeight_FirstAtMax) {
layout_->SetInteriorMargin(Insets(5));
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(5));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(5));
View* child1 = AddChild(Size(20, 10), Size(5, 5));
View* child2 = AddChild(Size(20, 10), Size(5, 5));
- layout_->SetFlexForView(child1, kFlex2ScaleToMinimum);
- layout_->SetFlexForView(child2, kFlex1ScaleToMinimum);
+ child1->SetProperty(views::kFlexBehaviorKey, kFlex2ScaleToMinimum);
+ child2->SetProperty(views::kFlexBehaviorKey, kFlex1ScaleToMinimum);
host_->SetSize(Size(50, 20));
host_->Layout();
@@ -1265,11 +1381,11 @@ TEST_F(FlexLayoutTest, Layout_Flex_TwoChildViews_UnequalWeight_SecondAtMax) {
layout_->SetInteriorMargin(Insets(5));
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(5));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(5));
View* child1 = AddChild(Size(20, 10), Size(5, 5));
View* child2 = AddChild(Size(20, 10), Size(5, 5));
- layout_->SetFlexForView(child1, kFlex1ScaleToMinimum);
- layout_->SetFlexForView(child2, kFlex2ScaleToMinimum);
+ child1->SetProperty(views::kFlexBehaviorKey, kFlex1ScaleToMinimum);
+ child2->SetProperty(views::kFlexBehaviorKey, kFlex2ScaleToMinimum);
host_->SetSize(Size(50, 20));
host_->Layout();
@@ -1286,11 +1402,12 @@ TEST_F(FlexLayoutTest, Layout_Flex_TwoChildViews_Priority) {
layout_->SetInteriorMargin(Insets(5));
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(5));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(5));
View* child1 = AddChild(Size(20, 10), Size(5, 5));
View* child2 = AddChild(Size(20, 10), Size(5, 5));
- layout_->SetFlexForView(child1, kFlex1ScaleToMinimum);
- layout_->SetFlexForView(child2, kFlex1ScaleToMinimumHighPriority);
+ child1->SetProperty(views::kFlexBehaviorKey, kFlex1ScaleToMinimum);
+ child2->SetProperty(views::kFlexBehaviorKey,
+ kFlex1ScaleToMinimumHighPriority);
host_->SetSize(Size(50, 20));
host_->Layout();
@@ -1310,11 +1427,12 @@ TEST_F(FlexLayoutTest,
layout_->SetInteriorMargin(Insets(5));
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(5));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(5));
View* child1 = AddChild(Size(20, 10), Size(5, 5));
View* child2 = AddChild(Size(20, 10), Size(5, 5));
- layout_->SetFlexForView(child1, kFlex1ScaleToZero);
- layout_->SetFlexForView(child2, kFlex1ScaleToMinimumHighPriority);
+ child1->SetProperty(views::kFlexBehaviorKey, kFlex1ScaleToZero);
+ child2->SetProperty(views::kFlexBehaviorKey,
+ kFlex1ScaleToMinimumHighPriority);
host_->SetSize(Size(35, 20));
host_->Layout();
@@ -1328,9 +1446,9 @@ TEST_F(FlexLayoutTest, Layout_FlexRule_UnboundedSnapToMinimum) {
layout_->SetInteriorMargin(Insets(5));
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(5));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(5));
View* child = AddChild(Size(20, 10), Size(5, 5));
- layout_->SetFlexForView(child, kUnboundedSnapToMinimum);
+ child->SetProperty(views::kFlexBehaviorKey, kUnboundedSnapToMinimum);
host_->SetSize(Size(35, 25));
host_->Layout();
@@ -1361,9 +1479,10 @@ TEST_F(FlexLayoutTest, Layout_FlexRule_UnboundedScaleToMinimumSnapToZero) {
layout_->SetInteriorMargin(Insets(5));
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(5));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(5));
View* child = AddChild(Size(20, 10), Size(5, 5));
- layout_->SetFlexForView(child, kUnboundedScaleToMinimumSnapToZero);
+ child->SetProperty(views::kFlexBehaviorKey,
+ kUnboundedScaleToMinimumSnapToZero);
host_->SetSize(Size(35, 25));
host_->Layout();
@@ -1403,11 +1522,11 @@ TEST_F(FlexLayoutTest, Layout_FlexRule_UnboundedScaleToZero) {
layout_->SetInteriorMargin(Insets(5));
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(5));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(5));
// Because we are using a flex rule that scales all the way to zero, ensure
// that the child view's minimum size is *not* respected.
View* child = AddChild(Size(20, 10), Size(5, 5));
- layout_->SetFlexForView(child, kUnboundedScaleToZero);
+ child->SetProperty(views::kFlexBehaviorKey, kUnboundedScaleToZero);
host_->SetSize(Size(35, 25));
host_->Layout();
@@ -1456,9 +1575,10 @@ TEST_F(FlexLayoutTest,
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
View* child1 = AddChild(kLargeSize, kSmallSize);
- layout_->SetFlexForView(child1, kUnboundedScaleToMinimumHighPriority);
+ child1->SetProperty(views::kFlexBehaviorKey,
+ kUnboundedScaleToMinimumHighPriority);
View* child2 = AddChild(kSmallSize);
- layout_->SetFlexForView(child2, kDropOut);
+ child2->SetProperty(views::kFlexBehaviorKey, kDropOut);
// When there is no room for the second view, it drops out.
host_->SetSize(Size(4, 5));
@@ -1494,9 +1614,10 @@ TEST_F(FlexLayoutTest, Layout_FlexRule_TwoPassScaling_StopAtPreferredSize) {
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
View* child1 = AddChild(kLargeSize, kSmallSize);
- layout_->SetFlexForView(child1, kUnboundedScaleToMinimumHighPriority);
+ child1->SetProperty(views::kFlexBehaviorKey,
+ kUnboundedScaleToMinimumHighPriority);
View* child2 = AddChild(kSmallSize);
- layout_->SetFlexForView(child2, kDropOut);
+ child2->SetProperty(views::kFlexBehaviorKey, kDropOut);
constexpr Size kEnoughSpace(kSmallSize.width() + kLargeSize.width(),
kLargeSize.height());
@@ -1517,9 +1638,10 @@ TEST_F(FlexLayoutTest, Layout_FlexRule_TwoPassScaling_GrowPastPreferredSize) {
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
View* child1 = AddChild(kLargeSize, kSmallSize);
- layout_->SetFlexForView(child1, kUnboundedScaleToMinimumHighPriority);
+ child1->SetProperty(views::kFlexBehaviorKey,
+ kUnboundedScaleToMinimumHighPriority);
View* child2 = AddChild(kSmallSize);
- layout_->SetFlexForView(child2, kDropOut);
+ child2->SetProperty(views::kFlexBehaviorKey, kDropOut);
constexpr int kExtra = 7;
constexpr Size kExtraSpace(kSmallSize.width() + kLargeSize.width() + kExtra,
@@ -1544,9 +1666,11 @@ TEST_F(FlexLayoutTest,
// Because we are using a flex rule that scales all the way to zero, ensure
// that the child view's minimum size is *not* respected.
View* child1 = AddChild(kLargeSize, kSmallSize);
- layout_->SetFlexForView(child1, kUnboundedScaleToMinimumHighPriority);
+ child1->SetProperty(views::kFlexBehaviorKey,
+ kUnboundedScaleToMinimumHighPriority);
View* child2 = AddChild(kLargeSize, kSmallSize);
- layout_->SetFlexForView(child2, kUnboundedScaleToMinimumHighPriority);
+ child2->SetProperty(views::kFlexBehaviorKey,
+ kUnboundedScaleToMinimumHighPriority);
constexpr int kExtra = 8;
constexpr Size kExtraSpace(2 * kLargeSize.width() + kExtra,
@@ -1572,9 +1696,10 @@ TEST_F(FlexLayoutTest,
// Because we are using a flex rule that scales all the way to zero, ensure
// that the child view's minimum size is *not* respected.
View* child1 = AddChild(kLargeSize, kSmallSize);
- layout_->SetFlexForView(child1, kUnboundedScaleToMinimumHighPriority);
+ child1->SetProperty(views::kFlexBehaviorKey,
+ kUnboundedScaleToMinimumHighPriority);
View* child2 = AddChild(kLargeSize, kSmallSize);
- layout_->SetFlexForView(child2, kUnboundedScaleToMinimum);
+ child2->SetProperty(views::kFlexBehaviorKey, kUnboundedScaleToMinimum);
constexpr int kExtra = 8;
constexpr Size kExtraSpace(2 * kLargeSize.width() + kExtra,
@@ -1594,9 +1719,9 @@ TEST_F(FlexLayoutTest, Layout_FlexRule_CustomFlexRule) {
layout_->SetInteriorMargin(Insets(5));
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(5));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(5));
View* child = AddChild(Size(kFullSize, kFullSize));
- layout_->SetFlexForView(child, kCustomFlex);
+ child->SetProperty(views::kFlexBehaviorKey, kCustomFlex);
host_->SetSize(Size(100, 100));
host_->Layout();
@@ -1629,10 +1754,10 @@ TEST_F(FlexLayoutTest, Layout_FlexRule_CustomFlexRule_WithNonFlex) {
layout_->SetInteriorMargin(Insets(5));
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(5));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(5));
View* child = AddChild(Size(kFullSize, kFullSize));
AddChild(Size(10, 10));
- layout_->SetFlexForView(child, kCustomFlex);
+ child->SetProperty(views::kFlexBehaviorKey, kCustomFlex);
host_->SetSize(Size(100, 100));
host_->Layout();
@@ -1660,9 +1785,9 @@ TEST_F(FlexLayoutTest, Layout_FlexRule_CustomFlexRule_ShrinkToZero) {
layout_->SetInteriorMargin(Insets(5));
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(5));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(5));
View* child = AddChild(Size(kFullSize, kFullSize));
- layout_->SetFlexForView(child, kCustomFlexSnapToZero);
+ child->SetProperty(views::kFlexBehaviorKey, kCustomFlexSnapToZero);
host_->SetSize(Size(100, 100));
host_->Layout();
@@ -1691,11 +1816,12 @@ TEST_F(FlexLayoutTest, Layout_OnlyCallsSetViewVisibilityWhenNecessary) {
layout_->SetInteriorMargin(Insets(5));
layout_->SetMainAxisAlignment(LayoutAlignment::kStart);
layout_->SetCrossAxisAlignment(LayoutAlignment::kStart);
- layout_->SetDefaultChildMargins(gfx::Insets(5));
+ layout_->SetDefault(views::kMarginsKey, gfx::Insets(5));
MockView* child1 = AddChild(Size(20, 10), Size(5, 5));
MockView* child2 = AddChild(Size(20, 10), Size(5, 5));
- layout_->SetFlexForView(child1, kFlex1ScaleToZero);
- layout_->SetFlexForView(child2, kFlex1ScaleToMinimumHighPriority);
+ child1->SetProperty(views::kFlexBehaviorKey, kFlex1ScaleToZero);
+ child2->SetProperty(views::kFlexBehaviorKey,
+ kFlex1ScaleToMinimumHighPriority);
child1->ResetCounts();
child2->ResetCounts();
@@ -1747,7 +1873,7 @@ class FlexLayoutCrossAxisFitTest : public FlexLayoutTest {
for (size_t i = 0; i < kNumChildren; ++i) {
View* const child = AddChild(kChildSizes[i]);
- child->SetProperty(kMarginsKey, new gfx::Insets(kChildMargins[i]));
+ child->SetProperty(kMarginsKey, gfx::Insets(kChildMargins[i]));
child_views_.push_back(child);
}
@@ -1889,19 +2015,19 @@ TEST_F(NestedFlexLayoutTest, Layout_OppositeOrientation) {
layout_->SetOrientation(LayoutOrientation::kHorizontal)
.SetCollapseMargins(false)
.SetCrossAxisAlignment(LayoutAlignment::kStart)
- .SetDefaultChildMargins(gfx::Insets(2, 3, 4, 5))
+ .SetDefault(views::kMarginsKey, gfx::Insets(2, 3, 4, 5))
.SetInteriorMargin(gfx::Insets(4, 3, 2, 1));
layout(1)
->SetOrientation(LayoutOrientation::kVertical)
.SetCollapseMargins(true)
- .SetDefaultChildMargins(gfx::Insets(2))
+ .SetDefault(views::kMarginsKey, gfx::Insets(2))
.SetInteriorMargin(gfx::Insets(1));
layout(2)
->SetOrientation(LayoutOrientation::kVertical)
.SetCollapseMargins(true)
- .SetDefaultChildMargins(gfx::Insets(1))
+ .SetDefault(views::kMarginsKey, gfx::Insets(1))
.SetInteriorMargin(gfx::Insets(2));
EXPECT_EQ(gfx::Size(39, 29), host_->GetPreferredSize());
@@ -1925,19 +2051,19 @@ TEST_F(NestedFlexLayoutTest, Layout_SameOrientation) {
layout_->SetOrientation(LayoutOrientation::kHorizontal)
.SetCollapseMargins(false)
.SetCrossAxisAlignment(LayoutAlignment::kStart)
- .SetDefaultChildMargins(gfx::Insets(2, 3, 4, 5))
+ .SetDefault(views::kMarginsKey, gfx::Insets(2, 3, 4, 5))
.SetInteriorMargin(gfx::Insets(4, 3, 2, 1));
layout(1)
->SetOrientation(LayoutOrientation::kHorizontal)
.SetCollapseMargins(true)
- .SetDefaultChildMargins(gfx::Insets(2))
+ .SetDefault(views::kMarginsKey, gfx::Insets(2))
.SetInteriorMargin(gfx::Insets(1));
layout(2)
->SetOrientation(LayoutOrientation::kHorizontal)
.SetCollapseMargins(true)
- .SetDefaultChildMargins(gfx::Insets(1))
+ .SetDefault(views::kMarginsKey, gfx::Insets(1))
.SetInteriorMargin(gfx::Insets(2));
EXPECT_EQ(gfx::Size(53, 22), host_->GetPreferredSize());
@@ -1964,26 +2090,26 @@ TEST_F(NestedFlexLayoutTest, Layout_Flex) {
layout_->SetOrientation(LayoutOrientation::kHorizontal)
.SetCollapseMargins(true)
.SetCrossAxisAlignment(LayoutAlignment::kStart)
- .SetDefaultChildMargins(gfx::Insets(2))
- .SetInteriorMargin(gfx::Insets(2))
- .SetFlexForView(child(1), flex_specification)
- .SetFlexForView(child(2), flex_specification);
+ .SetDefault(views::kMarginsKey, gfx::Insets(2))
+ .SetInteriorMargin(gfx::Insets(2));
+ child(1)->SetProperty(views::kFlexBehaviorKey, flex_specification);
+ child(2)->SetProperty(views::kFlexBehaviorKey, flex_specification);
layout(1)
->SetOrientation(LayoutOrientation::kHorizontal)
.SetCollapseMargins(true)
- .SetDefaultChildMargins(gfx::Insets(2))
- .SetInteriorMargin(gfx::Insets(2))
- .SetFlexForView(grandchild(1, 1), flex_specification)
- .SetFlexForView(grandchild(1, 2), flex_specification);
+ .SetDefault(views::kMarginsKey, gfx::Insets(2))
+ .SetInteriorMargin(gfx::Insets(2));
+ grandchild(1, 1)->SetProperty(views::kFlexBehaviorKey, flex_specification);
+ grandchild(1, 2)->SetProperty(views::kFlexBehaviorKey, flex_specification);
layout(2)
->SetOrientation(LayoutOrientation::kHorizontal)
.SetCollapseMargins(true)
- .SetDefaultChildMargins(gfx::Insets(2))
- .SetInteriorMargin(gfx::Insets(2))
- .SetFlexForView(grandchild(2, 1), flex_specification)
- .SetFlexForView(grandchild(2, 2), flex_specification);
+ .SetDefault(views::kMarginsKey, gfx::Insets(2))
+ .SetInteriorMargin(gfx::Insets(2));
+ grandchild(2, 1)->SetProperty(views::kFlexBehaviorKey, flex_specification);
+ grandchild(2, 2)->SetProperty(views::kFlexBehaviorKey, flex_specification);
EXPECT_EQ(gfx::Size(40, 14), host_->GetPreferredSize());
host_->SetSize(gfx::Size(20, 15));
diff --git a/chromium/ui/views/layout/grid_layout.cc b/chromium/ui/views/layout/grid_layout.cc
index c556543755b..9056d526f79 100644
--- a/chromium/ui/views/layout/grid_layout.cc
+++ b/chromium/ui/views/layout/grid_layout.cc
@@ -516,7 +516,7 @@ void ColumnSet::AccumulateMasterColumns() {
DCHECK(master_columns_.empty());
for (const auto& column : columns_) {
Column* master_column = column->GetLastMasterColumn();
- if (master_column && !base::ContainsValue(master_columns_, master_column)) {
+ if (master_column && !base::Contains(master_columns_, master_column)) {
master_columns_.push_back(master_column);
}
// At this point, GetLastMasterColumn may not == master_column
@@ -772,9 +772,7 @@ bool ColumnSet::CanUseMinimum(const ViewState& view_state) const {
// GridLayout -------------------------------------------------------------
-GridLayout::GridLayout(View* host) : host_(host) {
- DCHECK(host);
-}
+GridLayout::GridLayout() = default;
GridLayout::~GridLayout() = default;
@@ -818,32 +816,64 @@ void GridLayout::SkipColumns(int col_count) {
SkipPaddingColumns();
}
-void GridLayout::AddView(View* view) {
- AddView(view, 1, 1);
+void GridLayout::AddExistingView(View* view, int col_span, int row_span) {
+ DCHECK(view->parent() && view->parent() == host_)
+ << "Use AddView() to add a new View that isn't already parented to "
+ "|host_|.";
+ DCHECK(current_row_col_set_ &&
+ next_column_ < current_row_col_set_->num_columns());
+ Column* column = current_row_col_set_->columns_[next_column_].get();
+ AddExistingView(view, col_span, row_span, column->h_align(),
+ column->v_align());
}
-void GridLayout::AddView(View* view, int col_span, int row_span) {
+void GridLayout::AddViewImpl(std::unique_ptr<View> view,
+ int col_span,
+ int row_span) {
DCHECK(current_row_col_set_ &&
next_column_ < current_row_col_set_->num_columns());
Column* column = current_row_col_set_->columns_[next_column_].get();
- AddView(view, col_span, row_span, column->h_align(), column->v_align());
+ AddViewImpl(std::move(view), col_span, row_span, column->h_align(),
+ column->v_align(), 0, 0);
}
-void GridLayout::AddView(View* view, int col_span, int row_span,
- Alignment h_align, Alignment v_align) {
- AddView(view, col_span, row_span, h_align, v_align, 0, 0);
+void GridLayout::AddExistingView(View* view,
+ int col_span,
+ int row_span,
+ Alignment h_align,
+ Alignment v_align,
+ int pref_width,
+ int pref_height) {
+ DCHECK(view->parent() && view->parent() == host_)
+ << "Use AddView() to add a new View that isn't already parented to "
+ "|host_|.";
+ DCHECK(current_row_col_set_ && col_span > 0 && row_span > 0 &&
+ (next_column_ + col_span) <= current_row_col_set_->num_columns());
+ // We don't support baseline alignment of views spanning rows. Please add if
+ // you need it.
+ DCHECK(v_align != BASELINE || row_span == 1);
+ AddViewState(std::make_unique<ViewState>(
+ current_row_col_set_, view, next_column_, current_row_, col_span,
+ row_span, h_align, v_align, pref_width, pref_height));
}
-void GridLayout::AddView(View* view, int col_span, int row_span,
- Alignment h_align, Alignment v_align,
- int pref_width, int pref_height) {
+void GridLayout::AddViewImpl(std::unique_ptr<View> view,
+ int col_span,
+ int row_span,
+ Alignment h_align,
+ Alignment v_align,
+ int pref_width,
+ int pref_height) {
DCHECK(current_row_col_set_ && col_span > 0 && row_span > 0 &&
(next_column_ + col_span) <= current_row_col_set_->num_columns());
// We don't support baseline alignment of views spanning rows. Please add if
// you need it.
DCHECK(v_align != BASELINE || row_span == 1);
+ adding_view_ = true;
+ View* view_ptr = host_->AddChildView(std::move(view));
+ adding_view_ = false;
AddViewState(std::make_unique<ViewState>(
- current_row_col_set_, view, next_column_, current_row_, col_span,
+ current_row_col_set_, view_ptr, next_column_, current_row_, col_span,
row_span, h_align, v_align, pref_width, pref_height));
}
@@ -872,7 +902,7 @@ static void CalculateSize(int pref_size, GridLayout::Alignment alignment,
}
void GridLayout::Installed(View* host) {
- DCHECK(host_ == host);
+ host_ = host;
}
void GridLayout::ViewAdded(View* host, View* view) {
@@ -1047,13 +1077,7 @@ void GridLayout::CalculateMasterColumnsIfNecessary() const {
}
void GridLayout::AddViewState(std::unique_ptr<ViewState> view_state) {
- DCHECK(view_state->view && (view_state->view->parent() == nullptr ||
- view_state->view->parent() == host_));
- if (!view_state->view->parent()) {
- adding_view_ = true;
- host_->AddChildView(view_state->view);
- adding_view_ = false;
- }
+ DCHECK(view_state->view && view_state->view->parent() == host_);
remaining_row_span_ = std::max(remaining_row_span_, view_state->row_span);
next_column_ += view_state->col_span;
current_row_col_set_->AddViewState(view_state.get());
diff --git a/chromium/ui/views/layout/grid_layout.h b/chromium/ui/views/layout/grid_layout.h
index cd046c70163..3d591436a53 100644
--- a/chromium/ui/views/layout/grid_layout.h
+++ b/chromium/ui/views/layout/grid_layout.h
@@ -111,7 +111,7 @@ class VIEWS_EXPORT GridLayout : public LayoutManager {
USE_PREF
};
- explicit GridLayout(View* host);
+ GridLayout();
~GridLayout() override;
// See class description for what this does.
@@ -145,31 +145,50 @@ class VIEWS_EXPORT GridLayout : public LayoutManager {
// contain any views.
void SkipColumns(int col_count);
- // Adds a view using the default alignment from the column. The added
- // view has a column and row span of 1.
- // As a convenience this adds the view to the host. The view becomes owned
- // by the host, and NOT this GridLayout.
- void AddView(View* view);
-
// Adds a view using the default alignment from the column.
// As a convenience this adds the view to the host. The view becomes owned
// by the host, and NOT this GridLayout.
- void AddView(View* view, int col_span, int row_span);
+ template <typename T>
+ T* AddView(std::unique_ptr<T> view, int col_span = 1, int row_span = 1) {
+ T* result = view.get();
+ AddViewImpl(std::move(view), col_span, row_span);
+ return result;
+ }
- // Adds a view with the specified alignment and spans.
- // As a convenience this adds the view to the host. The view becomes owned
- // by the host, and NOT this GridLayout.
- void AddView(View* view, int col_span, int row_span, Alignment h_align,
- Alignment v_align);
+ // Adds a view to the layout using the default alignment from the column.
+ // NOTE: The |view| must already be present and owned by the host.
+ void AddExistingView(View* view, int col_span = 1, int row_span = 1);
// Adds a view with the specified alignment and spans. If
// pref_width/pref_height is > 0 then the preferred width/height of the view
// is fixed to the specified value.
// As a convenience this adds the view to the host. The view becomes owned
// by the host, and NOT this GridLayout.
- void AddView(View* view, int col_span, int row_span,
- Alignment h_align, Alignment v_align,
- int pref_width, int pref_height);
+ template <typename T>
+ T* AddView(std::unique_ptr<T> view,
+ int col_span,
+ int row_span,
+ Alignment h_align,
+ Alignment v_align,
+ int pref_width = 0,
+ int pref_height = 0) {
+ T* result = view.get();
+ AddViewImpl(std::move(view), col_span, row_span, h_align, v_align,
+ pref_width, pref_height);
+ return result;
+ }
+
+ // Adds a view to the layout with the specified alignment and spans. If
+ // pref_width/pref_height is > 0 then the preferred width/height of the view
+ // is fixed to the specified value.
+ // NOTE: The |view| must already be present and owned by the host;
+ void AddExistingView(View* view,
+ int col_span,
+ int row_span,
+ Alignment h_align,
+ Alignment v_align,
+ int pref_width = 0,
+ int pref_height = 0);
// Notification we've been installed on a particular host. Checks that host
// is the same as the View supplied in the constructor.
@@ -205,8 +224,20 @@ class VIEWS_EXPORT GridLayout : public LayoutManager {
// a description of what a master column is.
void CalculateMasterColumnsIfNecessary() const;
- // This is called internally from AddView. It adds the ViewState to the
- // appropriate structures, and updates internal fields such as next_column_.
+ // These are called internally from AddView<T>.
+ void AddViewImpl(std::unique_ptr<View> view, int col_span, int row_span);
+
+ void AddViewImpl(std::unique_ptr<View> view,
+ int col_span,
+ int row_span,
+ Alignment h_align,
+ Alignment v_align,
+ int pref_width,
+ int pref_height);
+
+ // This is called internally from AddView & AddViewState above. It adds the
+ // ViewState to the appropriate structures and updates the internal fields
+ // such as next_column_.
void AddViewState(std::unique_ptr<ViewState> view_state);
// Adds the Row to rows_, as well as updating next_column_,
@@ -228,8 +259,8 @@ class VIEWS_EXPORT GridLayout : public LayoutManager {
// Returns the column set of the last non-padding row.
ColumnSet* GetLastValidColumnSet();
- // The view we were created with. We don't own this.
- View* const host_;
+ // The View this is installed on.
+ View* host_ = nullptr;
// Whether or not we've calculated the master/linked columns.
mutable bool calculated_master_columns_ = false;
diff --git a/chromium/ui/views/layout/grid_layout_unittest.cc b/chromium/ui/views/layout/grid_layout_unittest.cc
index b35944a52b2..8b4dc47fba7 100644
--- a/chromium/ui/views/layout/grid_layout_unittest.cc
+++ b/chromium/ui/views/layout/grid_layout_unittest.cc
@@ -4,6 +4,9 @@
#include "ui/views/layout/grid_layout.h"
+#include <memory>
+#include <utility>
+
#include "base/compiler_specific.h"
#include "base/test/gtest_util.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -21,8 +24,8 @@ void ExpectViewBoundsEquals(int x, int y, int w, int h,
EXPECT_EQ(h, view->height());
}
-View* CreateSizedView(const gfx::Size& size) {
- auto* view = new View();
+std::unique_ptr<View> CreateSizedView(const gfx::Size& size) {
+ auto view = std::make_unique<View>();
view->SetPreferredSize(size);
return view;
}
@@ -42,8 +45,9 @@ class MinSizeView : public View {
DISALLOW_COPY_AND_ASSIGN(MinSizeView);
};
-View* CreateViewWithMinAndPref(const gfx::Size& min, const gfx::Size& pref) {
- MinSizeView* view = new MinSizeView(min);
+std::unique_ptr<MinSizeView> CreateViewWithMinAndPref(const gfx::Size& min,
+ const gfx::Size& pref) {
+ auto view = std::make_unique<MinSizeView>(min);
view->SetPreferredSize(pref);
return view;
}
@@ -99,52 +103,47 @@ class FlexibleView : public View {
class GridLayoutTest : public testing::Test {
public:
- GridLayoutTest() {
- layout_ =
- host_.SetLayoutManager(std::make_unique<views::GridLayout>(&host_));
+ GridLayoutTest() : host_(std::make_unique<View>()) {
+ layout_ = host_->SetLayoutManager(std::make_unique<views::GridLayout>());
}
- void RemoveAll() { host_.RemoveAllChildViews(false); }
-
- gfx::Size GetPreferredSize() { return layout_->GetPreferredSize(&host_); }
+ gfx::Size GetPreferredSize() {
+ return layout_->GetPreferredSize(host_.get());
+ }
- View& host() { return host_; }
+ View* host() { return host_.get(); }
GridLayout* layout() { return layout_; }
private:
- View host_;
+ std::unique_ptr<View> host_;
GridLayout* layout_;
};
class GridLayoutAlignmentTest : public testing::Test {
public:
- GridLayoutAlignmentTest() {
- layout_ =
- host_.SetLayoutManager(std::make_unique<views::GridLayout>(&host_));
- v1_.SetPreferredSize(gfx::Size(10, 20));
+ GridLayoutAlignmentTest() : host_(std::make_unique<View>()) {
+ layout_ = host_->SetLayoutManager(std::make_unique<views::GridLayout>());
}
- void RemoveAll() { host_.RemoveAllChildViews(false); }
-
void TestAlignment(GridLayout::Alignment alignment, gfx::Rect* bounds) {
+ auto v1 = std::make_unique<View>();
+ v1->SetPreferredSize(gfx::Size(10, 20));
ColumnSet* c1 = layout_->AddColumnSet(0);
c1->AddColumn(alignment, alignment, 1, GridLayout::USE_PREF, 0, 0);
layout_->StartRow(1, 0);
- layout_->AddView(&v1_);
- gfx::Size pref = layout_->GetPreferredSize(&host_);
+ auto* v1_ptr = layout_->AddView(std::move(v1));
+ gfx::Size pref = layout_->GetPreferredSize(host_.get());
EXPECT_EQ(gfx::Size(10, 20), pref);
- host_.SetBounds(0, 0, 100, 100);
- layout_->Layout(&host_);
- *bounds = v1_.bounds();
- RemoveAll();
+ host_->SetBounds(0, 0, 100, 100);
+ layout_->Layout(host_.get());
+ *bounds = v1_ptr->bounds();
}
- View& host() { return host_; }
+ View* host() { return host_.get(); }
GridLayout* layout() { return layout_; }
private:
- View host_;
- View v1_;
+ std::unique_ptr<View> host_;
GridLayout* layout_;
};
@@ -173,38 +172,28 @@ TEST_F(GridLayoutAlignmentTest, Trailing) {
}
TEST_F(GridLayoutTest, TwoColumns) {
- View v1;
- v1.SetPreferredSize(gfx::Size(10, 20));
- View v2;
- v2.SetPreferredSize(gfx::Size(20, 20));
+ auto v1 = CreateSizedView(gfx::Size(10, 20));
+ auto v2 = CreateSizedView(gfx::Size(20, 20));
ColumnSet* c1 = layout()->AddColumnSet(0);
c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
0, GridLayout::USE_PREF, 0, 0);
c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
0, GridLayout::USE_PREF, 0, 0);
layout()->StartRow(0, 0);
- layout()->AddView(&v1);
- layout()->AddView(&v2);
+ auto* v1_ptr = layout()->AddView(std::move(v1));
+ auto* v2_ptr = layout()->AddView(std::move(v2));
gfx::Size pref = GetPreferredSize();
EXPECT_EQ(gfx::Size(30, 20), pref);
- host().SetBounds(0, 0, pref.width(), pref.height());
- layout()->Layout(&host());
- ExpectViewBoundsEquals(0, 0, 10, 20, &v1);
- ExpectViewBoundsEquals(10, 0, 20, 20, &v2);
-
- RemoveAll();
+ host()->SetBounds(0, 0, pref.width(), pref.height());
+ layout()->Layout(host());
+ ExpectViewBoundsEquals(0, 0, 10, 20, v1_ptr);
+ ExpectViewBoundsEquals(10, 0, 20, 20, v2_ptr);
}
// Test linked column sizes, and the column size limit.
TEST_F(GridLayoutTest, LinkedSizes) {
- View v1;
- v1.SetPreferredSize(gfx::Size(10, 20));
- View v2;
- v2.SetPreferredSize(gfx::Size(20, 20));
- View v3;
- v3.SetPreferredSize(gfx::Size(0, 20));
ColumnSet* c1 = layout()->AddColumnSet(0);
// Fill widths.
@@ -216,9 +205,9 @@ TEST_F(GridLayoutTest, LinkedSizes) {
0, 0);
layout()->StartRow(0, 0);
- layout()->AddView(&v1);
- layout()->AddView(&v2);
- layout()->AddView(&v3);
+ auto* v1 = layout()->AddView(CreateSizedView(gfx::Size(10, 20)));
+ auto* v2 = layout()->AddView(CreateSizedView(gfx::Size(20, 20)));
+ auto* v3 = layout()->AddView(CreateSizedView(gfx::Size(0, 20)));
// Link all the columns.
c1->LinkColumnSizes(0, 1, 2, -1);
@@ -227,130 +216,108 @@ TEST_F(GridLayoutTest, LinkedSizes) {
// |v1| and |v3| should obtain the same width as |v2|, since |v2| is largest.
pref = GetPreferredSize();
EXPECT_EQ(gfx::Size(20 + 20 + 20, 20), pref);
- host().SetBounds(0, 0, pref.width(), pref.height());
- layout()->Layout(&host());
- ExpectViewBoundsEquals(0, 0, 20, 20, &v1);
- ExpectViewBoundsEquals(20, 0, 20, 20, &v2);
- ExpectViewBoundsEquals(40, 0, 20, 20, &v3);
+ host()->SetBounds(0, 0, pref.width(), pref.height());
+ layout()->Layout(host());
+ ExpectViewBoundsEquals(0, 0, 20, 20, v1);
+ ExpectViewBoundsEquals(20, 0, 20, 20, v2);
+ ExpectViewBoundsEquals(40, 0, 20, 20, v3);
// If the limit is zero, behaves as though the columns are not linked.
c1->set_linked_column_size_limit(0);
pref = GetPreferredSize();
EXPECT_EQ(gfx::Size(10 + 20 + 0, 20), pref);
- host().SetBounds(0, 0, pref.width(), pref.height());
- layout()->Layout(&host());
- ExpectViewBoundsEquals(0, 0, 10, 20, &v1);
- ExpectViewBoundsEquals(10, 0, 20, 20, &v2);
- ExpectViewBoundsEquals(30, 0, 0, 20, &v3);
+ host()->SetBounds(0, 0, pref.width(), pref.height());
+ layout()->Layout(host());
+ ExpectViewBoundsEquals(0, 0, 10, 20, v1);
+ ExpectViewBoundsEquals(10, 0, 20, 20, v2);
+ ExpectViewBoundsEquals(30, 0, 0, 20, v3);
// Set a size limit.
c1->set_linked_column_size_limit(40);
- v1.SetPreferredSize(gfx::Size(35, 20));
+ v1->SetPreferredSize(gfx::Size(35, 20));
// |v1| now dominates, but it is still below the limit.
pref = GetPreferredSize();
EXPECT_EQ(gfx::Size(35 + 35 + 35, 20), pref);
- host().SetBounds(0, 0, pref.width(), pref.height());
- layout()->Layout(&host());
- ExpectViewBoundsEquals(0, 0, 35, 20, &v1);
- ExpectViewBoundsEquals(35, 0, 35, 20, &v2);
- ExpectViewBoundsEquals(70, 0, 35, 20, &v3);
+ host()->SetBounds(0, 0, pref.width(), pref.height());
+ layout()->Layout(host());
+ ExpectViewBoundsEquals(0, 0, 35, 20, v1);
+ ExpectViewBoundsEquals(35, 0, 35, 20, v2);
+ ExpectViewBoundsEquals(70, 0, 35, 20, v3);
// Go over the limit. |v1| shouldn't influence size at all, but the others
// should still be linked to the next largest width.
- v1.SetPreferredSize(gfx::Size(45, 20));
+ v1->SetPreferredSize(gfx::Size(45, 20));
pref = GetPreferredSize();
EXPECT_EQ(gfx::Size(45 + 20 + 20, 20), pref);
- host().SetBounds(0, 0, pref.width(), pref.height());
- layout()->Layout(&host());
- ExpectViewBoundsEquals(0, 0, 45, 20, &v1);
- ExpectViewBoundsEquals(45, 0, 20, 20, &v2);
- ExpectViewBoundsEquals(65, 0, 20, 20, &v3);
-
- RemoveAll();
+ host()->SetBounds(0, 0, pref.width(), pref.height());
+ layout()->Layout(host());
+ ExpectViewBoundsEquals(0, 0, 45, 20, v1);
+ ExpectViewBoundsEquals(45, 0, 20, 20, v2);
+ ExpectViewBoundsEquals(65, 0, 20, 20, v3);
}
TEST_F(GridLayoutTest, ColSpan1) {
- View v1;
- v1.SetPreferredSize(gfx::Size(100, 20));
- View v2;
- v2.SetPreferredSize(gfx::Size(10, 40));
ColumnSet* c1 = layout()->AddColumnSet(0);
c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
0, GridLayout::USE_PREF, 0, 0);
c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
1, GridLayout::USE_PREF, 0, 0);
layout()->StartRow(0, 0);
- layout()->AddView(&v1, 2, 1);
+ auto* v1 = layout()->AddView(CreateSizedView(gfx::Size(100, 20)), 2, 1);
layout()->StartRow(0, 0);
- layout()->AddView(&v2);
+ auto* v2 = layout()->AddView(CreateSizedView(gfx::Size(10, 40)));
gfx::Size pref = GetPreferredSize();
EXPECT_EQ(gfx::Size(100, 60), pref);
- host().SetBounds(0, 0, pref.width(), pref.height());
- layout()->Layout(&host());
- ExpectViewBoundsEquals(0, 0, 100, 20, &v1);
- ExpectViewBoundsEquals(0, 20, 10, 40, &v2);
-
- RemoveAll();
+ host()->SetBounds(0, 0, pref.width(), pref.height());
+ layout()->Layout(host());
+ ExpectViewBoundsEquals(0, 0, 100, 20, v1);
+ ExpectViewBoundsEquals(0, 20, 10, 40, v2);
}
TEST_F(GridLayoutTest, ColSpan2) {
- View v1;
- v1.SetPreferredSize(gfx::Size(100, 20));
- View v2;
- v2.SetPreferredSize(gfx::Size(10, 20));
ColumnSet* c1 = layout()->AddColumnSet(0);
c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
1, GridLayout::USE_PREF, 0, 0);
c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
0, GridLayout::USE_PREF, 0, 0);
layout()->StartRow(0, 0);
- layout()->AddView(&v1, 2, 1);
+ auto* v1 = layout()->AddView(CreateSizedView(gfx::Size(100, 20)), 2, 1);
layout()->StartRow(0, 0);
layout()->SkipColumns(1);
- layout()->AddView(&v2);
+ auto* v2 = layout()->AddView(CreateSizedView(gfx::Size(10, 20)));
gfx::Size pref = GetPreferredSize();
EXPECT_EQ(gfx::Size(100, 40), pref);
- host().SetBounds(0, 0, pref.width(), pref.height());
- layout()->Layout(&host());
- ExpectViewBoundsEquals(0, 0, 100, 20, &v1);
- ExpectViewBoundsEquals(90, 20, 10, 20, &v2);
-
- RemoveAll();
+ host()->SetBounds(0, 0, pref.width(), pref.height());
+ layout()->Layout(host());
+ ExpectViewBoundsEquals(0, 0, 100, 20, v1);
+ ExpectViewBoundsEquals(90, 20, 10, 20, v2);
}
TEST_F(GridLayoutTest, ColSpan3) {
- View v1;
- v1.SetPreferredSize(gfx::Size(100, 20));
- View v2;
- v2.SetPreferredSize(gfx::Size(10, 20));
- View v3;
- v3.SetPreferredSize(gfx::Size(10, 20));
ColumnSet* c1 = layout()->AddColumnSet(0);
c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
0, GridLayout::USE_PREF, 0, 0);
c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
0, GridLayout::USE_PREF, 0, 0);
layout()->StartRow(0, 0);
- layout()->AddView(&v1, 2, 1);
+ auto* v1 = layout()->AddView(CreateSizedView(gfx::Size(100, 20)), 2, 1);
layout()->StartRow(0, 0);
- layout()->AddView(&v2);
- layout()->AddView(&v3);
+ auto* v2 = layout()->AddView(CreateSizedView(gfx::Size(10, 20)));
+ auto* v3 = layout()->AddView(CreateSizedView(gfx::Size(10, 20)));
gfx::Size pref = GetPreferredSize();
EXPECT_EQ(gfx::Size(100, 40), pref);
- host().SetBounds(0, 0, pref.width(), pref.height());
- layout()->Layout(&host());
- ExpectViewBoundsEquals(0, 0, 100, 20, &v1);
- ExpectViewBoundsEquals(0, 20, 10, 20, &v2);
- ExpectViewBoundsEquals(50, 20, 10, 20, &v3);
-
- RemoveAll();
+ host()->SetBounds(0, 0, pref.width(), pref.height());
+ layout()->Layout(host());
+ ExpectViewBoundsEquals(0, 0, 100, 20, v1);
+ ExpectViewBoundsEquals(0, 20, 10, 20, v2);
+ ExpectViewBoundsEquals(50, 20, 10, 20, v3);
}
@@ -362,28 +329,20 @@ TEST_F(GridLayoutTest, ColSpan4) {
set->AddColumn(GridLayout::LEADING, GridLayout::LEADING, 0,
GridLayout::USE_PREF, 0, 0);
- View v1;
- v1.SetPreferredSize(gfx::Size(10, 10));
- View v2;
- v2.SetPreferredSize(gfx::Size(10, 10));
- View v3;
- v3.SetPreferredSize(gfx::Size(25, 20));
layout()->StartRow(0, 0);
- layout()->AddView(&v1);
- layout()->AddView(&v2);
+ auto* v1 = layout()->AddView(CreateSizedView(gfx::Size(10, 10)));
+ auto* v2 = layout()->AddView(CreateSizedView(gfx::Size(10, 10)));
layout()->StartRow(0, 0);
- layout()->AddView(&v3, 2, 1);
+ auto* v3 = layout()->AddView(CreateSizedView(gfx::Size(25, 20)), 2, 1);
gfx::Size pref = GetPreferredSize();
EXPECT_EQ(gfx::Size(25, 30), pref);
- host().SetBounds(0, 0, pref.width(), pref.height());
- layout()->Layout(&host());
- ExpectViewBoundsEquals(0, 0, 10, 10, &v1);
- ExpectViewBoundsEquals(12, 0, 10, 10, &v2);
- ExpectViewBoundsEquals(0, 10, 25, 20, &v3);
-
- RemoveAll();
+ host()->SetBounds(0, 0, pref.width(), pref.height());
+ layout()->Layout(host());
+ ExpectViewBoundsEquals(0, 0, 10, 10, v1);
+ ExpectViewBoundsEquals(12, 0, 10, 10, v2);
+ ExpectViewBoundsEquals(0, 10, 25, 20, v3);
}
// Verifies the sizing of a view that doesn't start in the first column
@@ -398,31 +357,20 @@ TEST_F(GridLayoutTest, ColSpanStartSecondColumn) {
set->AddColumn(GridLayout::FILL, GridLayout::FILL, 0,
GridLayout::FIXED, 10, 0);
- View v1;
- v1.SetPreferredSize(gfx::Size(10, 10));
- View v2;
- v2.SetPreferredSize(gfx::Size(20, 10));
-
layout()->StartRow(0, 0);
- layout()->AddView(&v1);
- layout()->AddView(&v2, 2, 1);
+ auto* v1 = layout()->AddView(CreateSizedView(gfx::Size(10, 10)));
+ auto* v2 = layout()->AddView(CreateSizedView(gfx::Size(20, 10)), 2, 1);
gfx::Size pref = GetPreferredSize();
EXPECT_EQ(gfx::Size(30, 10), pref);
- host().SetBounds(0, 0, pref.width(), pref.height());
- layout()->Layout(&host());
- ExpectViewBoundsEquals(0, 0, 10, 10, &v1);
- ExpectViewBoundsEquals(10, 0, 20, 10, &v2);
-
- RemoveAll();
+ host()->SetBounds(0, 0, pref.width(), pref.height());
+ layout()->Layout(host());
+ ExpectViewBoundsEquals(0, 0, 10, 10, v1);
+ ExpectViewBoundsEquals(10, 0, 20, 10, v2);
}
TEST_F(GridLayoutTest, SameSizeColumns) {
- View v1;
- v1.SetPreferredSize(gfx::Size(50, 20));
- View v2;
- v2.SetPreferredSize(gfx::Size(10, 10));
ColumnSet* c1 = layout()->AddColumnSet(0);
c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
0, GridLayout::USE_PREF, 0, 0);
@@ -430,73 +378,53 @@ TEST_F(GridLayoutTest, SameSizeColumns) {
0, GridLayout::USE_PREF, 0, 0);
c1->LinkColumnSizes(0, 1, -1);
layout()->StartRow(0, 0);
- layout()->AddView(&v1);
- layout()->AddView(&v2);
+ auto* v1 = layout()->AddView(CreateSizedView(gfx::Size(50, 20)));
+ auto* v2 = layout()->AddView(CreateSizedView(gfx::Size(10, 10)));
gfx::Size pref = GetPreferredSize();
EXPECT_EQ(gfx::Size(100, 20), pref);
- host().SetBounds(0, 0, pref.width(), pref.height());
- layout()->Layout(&host());
- ExpectViewBoundsEquals(0, 0, 50, 20, &v1);
- ExpectViewBoundsEquals(50, 0, 10, 10, &v2);
-
- RemoveAll();
+ host()->SetBounds(0, 0, pref.width(), pref.height());
+ layout()->Layout(host());
+ ExpectViewBoundsEquals(0, 0, 50, 20, v1);
+ ExpectViewBoundsEquals(50, 0, 10, 10, v2);
}
TEST_F(GridLayoutTest, HorizontalResizeTest1) {
- View v1;
- v1.SetPreferredSize(gfx::Size(50, 20));
- View v2;
- v2.SetPreferredSize(gfx::Size(10, 10));
ColumnSet* c1 = layout()->AddColumnSet(0);
c1->AddColumn(GridLayout::FILL, GridLayout::LEADING,
1, GridLayout::USE_PREF, 0, 0);
c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
0, GridLayout::USE_PREF, 0, 0);
layout()->StartRow(0, 0);
- layout()->AddView(&v1);
- layout()->AddView(&v2);
+ auto* v1 = layout()->AddView(CreateSizedView(gfx::Size(50, 20)));
+ auto* v2 = layout()->AddView(CreateSizedView(gfx::Size(10, 10)));
- host().SetBounds(0, 0, 110, 20);
- layout()->Layout(&host());
- ExpectViewBoundsEquals(0, 0, 100, 20, &v1);
- ExpectViewBoundsEquals(100, 0, 10, 10, &v2);
-
- RemoveAll();
+ host()->SetBounds(0, 0, 110, 20);
+ layout()->Layout(host());
+ ExpectViewBoundsEquals(0, 0, 100, 20, v1);
+ ExpectViewBoundsEquals(100, 0, 10, 10, v2);
}
TEST_F(GridLayoutTest, HorizontalResizeTest2) {
- View v1;
- v1.SetPreferredSize(gfx::Size(50, 20));
- View v2;
- v2.SetPreferredSize(gfx::Size(10, 10));
ColumnSet* c1 = layout()->AddColumnSet(0);
c1->AddColumn(GridLayout::FILL, GridLayout::LEADING,
1, GridLayout::USE_PREF, 0, 0);
c1->AddColumn(GridLayout::TRAILING, GridLayout::LEADING,
1, GridLayout::USE_PREF, 0, 0);
layout()->StartRow(0, 0);
- layout()->AddView(&v1);
- layout()->AddView(&v2);
-
- host().SetBounds(0, 0, 120, 20);
- layout()->Layout(&host());
- ExpectViewBoundsEquals(0, 0, 80, 20, &v1);
- ExpectViewBoundsEquals(110, 0, 10, 10, &v2);
+ auto* v1 = layout()->AddView(CreateSizedView(gfx::Size(50, 20)));
+ auto* v2 = layout()->AddView(CreateSizedView(gfx::Size(10, 10)));
- RemoveAll();
+ host()->SetBounds(0, 0, 120, 20);
+ layout()->Layout(host());
+ ExpectViewBoundsEquals(0, 0, 80, 20, v1);
+ ExpectViewBoundsEquals(110, 0, 10, 10, v2);
}
// Tests that space leftover due to rounding is distributed to the last
// resizable column.
TEST_F(GridLayoutTest, HorizontalResizeTest3) {
- View v1;
- v1.SetPreferredSize(gfx::Size(10, 10));
- View v2;
- v2.SetPreferredSize(gfx::Size(10, 10));
- View v3;
- v3.SetPreferredSize(gfx::Size(10, 10));
ColumnSet* c1 = layout()->AddColumnSet(0);
c1->AddColumn(GridLayout::FILL, GridLayout::LEADING,
1, GridLayout::USE_PREF, 0, 0);
@@ -505,65 +433,53 @@ TEST_F(GridLayoutTest, HorizontalResizeTest3) {
c1->AddColumn(GridLayout::TRAILING, GridLayout::LEADING,
0, GridLayout::USE_PREF, 0, 0);
layout()->StartRow(0, 0);
- layout()->AddView(&v1);
- layout()->AddView(&v2);
- layout()->AddView(&v3);
-
- host().SetBounds(0, 0, 31, 10);
- layout()->Layout(&host());
- ExpectViewBoundsEquals(0, 0, 10, 10, &v1);
- ExpectViewBoundsEquals(10, 0, 11, 10, &v2);
- ExpectViewBoundsEquals(21, 0, 10, 10, &v3);
+ auto* v1 = layout()->AddView(CreateSizedView(gfx::Size(10, 10)));
+ auto* v2 = layout()->AddView(CreateSizedView(gfx::Size(10, 10)));
+ auto* v3 = layout()->AddView(CreateSizedView(gfx::Size(10, 10)));
- RemoveAll();
+ host()->SetBounds(0, 0, 31, 10);
+ layout()->Layout(host());
+ ExpectViewBoundsEquals(0, 0, 10, 10, v1);
+ ExpectViewBoundsEquals(10, 0, 11, 10, v2);
+ ExpectViewBoundsEquals(21, 0, 10, 10, v3);
}
TEST_F(GridLayoutTest, TestVerticalResize1) {
- View v1;
- v1.SetPreferredSize(gfx::Size(50, 20));
- View v2;
- v2.SetPreferredSize(gfx::Size(10, 10));
ColumnSet* c1 = layout()->AddColumnSet(0);
c1->AddColumn(GridLayout::FILL, GridLayout::FILL,
1, GridLayout::USE_PREF, 0, 0);
layout()->StartRow(1, 0);
- layout()->AddView(&v1);
+ auto* v1 = layout()->AddView(CreateSizedView(gfx::Size(50, 20)));
layout()->StartRow(0, 0);
- layout()->AddView(&v2);
+ auto* v2 = layout()->AddView(CreateSizedView(gfx::Size(10, 10)));
gfx::Size pref = GetPreferredSize();
EXPECT_EQ(gfx::Size(50, 30), pref);
- host().SetBounds(0, 0, 50, 100);
- layout()->Layout(&host());
- ExpectViewBoundsEquals(0, 0, 50, 90, &v1);
- ExpectViewBoundsEquals(0, 90, 50, 10, &v2);
-
- RemoveAll();
+ host()->SetBounds(0, 0, 50, 100);
+ layout()->Layout(host());
+ ExpectViewBoundsEquals(0, 0, 50, 90, v1);
+ ExpectViewBoundsEquals(0, 90, 50, 10, v2);
}
TEST_F(GridLayoutTest, Border) {
- host().SetBorder(CreateEmptyBorder(1, 2, 3, 4));
- View v1;
- v1.SetPreferredSize(gfx::Size(10, 20));
+ host()->SetBorder(CreateEmptyBorder(1, 2, 3, 4));
ColumnSet* c1 = layout()->AddColumnSet(0);
c1->AddColumn(GridLayout::LEADING, GridLayout::LEADING,
0, GridLayout::USE_PREF, 0, 0);
layout()->StartRow(0, 0);
- layout()->AddView(&v1);
+ auto* v1 = layout()->AddView(CreateSizedView(gfx::Size(10, 20)));
gfx::Size pref = GetPreferredSize();
EXPECT_EQ(gfx::Size(16, 24), pref);
- host().SetBounds(0, 0, pref.width(), pref.height());
- layout()->Layout(&host());
- ExpectViewBoundsEquals(2, 1, 10, 20, &v1);
-
- RemoveAll();
+ host()->SetBounds(0, 0, pref.width(), pref.height());
+ layout()->Layout(host());
+ ExpectViewBoundsEquals(2, 1, 10, 20, v1);
}
TEST_F(GridLayoutTest, FixedSize) {
- host().SetBorder(CreateEmptyBorder(2, 2, 2, 2));
+ host()->SetBorder(CreateEmptyBorder(2, 2, 2, 2));
ColumnSet* set = layout()->AddColumnSet(0);
@@ -584,9 +500,9 @@ TEST_F(GridLayoutTest, FixedSize) {
layout()->AddView(CreateSizedView(gfx::Size(kPrefWidth, kPrefHeight)));
}
- layout()->Layout(&host());
+ layout()->Layout(host());
- auto i = host().children().cbegin();
+ auto i = host()->children().cbegin();
for (size_t row = 0; row < kRowCount; ++row) {
for (size_t column = 0; column < kColumnCount; ++column, ++i) {
ExpectViewBoundsEquals(
@@ -635,14 +551,13 @@ TEST_F(GridLayoutTest, RowSpan) {
layout()->AddView(CreateSizedView(gfx::Size(20, 10)));
layout()->AddView(CreateSizedView(gfx::Size(20, 40)), 1, 2);
layout()->StartRow(1, 0);
- View* s3 = CreateSizedView(gfx::Size(20, 10));
- layout()->AddView(s3);
+ auto* s3 = layout()->AddView(CreateSizedView(gfx::Size(20, 10)));
gfx::Size pref = GetPreferredSize();
EXPECT_EQ(gfx::Size(40, 40), pref);
- host().SetBounds(0, 0, pref.width(), pref.height());
- layout()->Layout(&host());
+ host()->SetBounds(0, 0, pref.width(), pref.height());
+ layout()->Layout(host());
ExpectViewBoundsEquals(0, 10, 20, 10, s3);
}
@@ -656,8 +571,7 @@ TEST_F(GridLayoutTest, RowSpan2) {
layout()->StartRow(0, 0);
layout()->AddView(CreateSizedView(gfx::Size(20, 20)));
- View* s3 = CreateSizedView(gfx::Size(64, 64));
- layout()->AddView(s3, 1, 3);
+ auto* s3 = layout()->AddView(CreateSizedView(gfx::Size(64, 64)), 1, 3);
layout()->AddPaddingRow(0, 10);
@@ -667,8 +581,8 @@ TEST_F(GridLayoutTest, RowSpan2) {
gfx::Size pref = GetPreferredSize();
EXPECT_EQ(gfx::Size(84, 64), pref);
- host().SetBounds(0, 0, pref.width(), pref.height());
- layout()->Layout(&host());
+ host()->SetBounds(0, 0, pref.width(), pref.height());
+ layout()->Layout(host());
ExpectViewBoundsEquals(20, 0, 64, 64, s3);
}
@@ -681,16 +595,16 @@ TEST_F(GridLayoutTest, FixedViewWidth) {
0,GridLayout::USE_PREF, 0, 0);
layout()->StartRow(0, 0);
- View* view = CreateSizedView(gfx::Size(30, 40));
- layout()->AddView(view, 1, 1, GridLayout::LEADING, GridLayout::LEADING, 10,
- 0);
+ auto* view =
+ layout()->AddView(CreateSizedView(gfx::Size(30, 40)), 1, 1,
+ GridLayout::LEADING, GridLayout::LEADING, 10, 0);
gfx::Size pref = GetPreferredSize();
EXPECT_EQ(10, pref.width());
EXPECT_EQ(40, pref.height());
- host().SetBounds(0, 0, pref.width(), pref.height());
- layout()->Layout(&host());
+ host()->SetBounds(0, 0, pref.width(), pref.height());
+ layout()->Layout(host());
ExpectViewBoundsEquals(0, 0, 10, 40, view);
}
@@ -703,16 +617,16 @@ TEST_F(GridLayoutTest, FixedViewHeight) {
0,GridLayout::USE_PREF, 0, 0);
layout()->StartRow(0, 0);
- View* view = CreateSizedView(gfx::Size(30, 40));
- layout()->AddView(view, 1, 1, GridLayout::LEADING, GridLayout::LEADING, 0,
- 10);
+ auto* view =
+ layout()->AddView(CreateSizedView(gfx::Size(30, 40)), 1, 1,
+ GridLayout::LEADING, GridLayout::LEADING, 0, 10);
gfx::Size pref = GetPreferredSize();
EXPECT_EQ(30, pref.width());
EXPECT_EQ(10, pref.height());
- host().SetBounds(0, 0, pref.width(), pref.height());
- layout()->Layout(&host());
+ host()->SetBounds(0, 0, pref.width(), pref.height());
+ layout()->Layout(host());
ExpectViewBoundsEquals(0, 0, 30, 10, view);
}
@@ -728,17 +642,15 @@ TEST_F(GridLayoutTest, ColumnSpanResizing) {
layout()->StartRow(0, 0);
// span_view spans two columns and is twice as big the views added below.
- View* span_view = CreateSizedView(gfx::Size(12, 40));
- layout()->AddView(span_view, 2, 1, GridLayout::LEADING, GridLayout::LEADING);
+ View* span_view = layout()->AddView(CreateSizedView(gfx::Size(12, 40)), 2, 1,
+ GridLayout::LEADING, GridLayout::LEADING);
layout()->StartRow(0, 0);
- View* view1 = CreateSizedView(gfx::Size(2, 40));
- View* view2 = CreateSizedView(gfx::Size(4, 40));
- layout()->AddView(view1);
- layout()->AddView(view2);
+ auto* view1 = layout()->AddView(CreateSizedView(gfx::Size(2, 40)));
+ auto* view2 = layout()->AddView(CreateSizedView(gfx::Size(4, 40)));
- host().SetBounds(0, 0, 12, 80);
- layout()->Layout(&host());
+ host()->SetBounds(0, 0, 12, 80);
+ layout()->Layout(host());
ExpectViewBoundsEquals(0, 0, 12, 40, span_view);
@@ -770,20 +682,20 @@ TEST_F(GridLayoutTest, ColumnResizingOnGetPreferredSize) {
// Make a row containing a flexible view that trades width for height.
layout()->StartRow(0, 0);
- View* view1 = new FlexibleView(100);
- layout()->AddView(view1, 1, 1, GridLayout::FILL, GridLayout::LEADING);
+ layout()->AddView(std::make_unique<FlexibleView>(100), 1, 1, GridLayout::FILL,
+ GridLayout::LEADING);
// The second row contains a view of fixed size that will enforce a column
// width of 20 pixels.
layout()->StartRow(0, 1);
- View* view2 = CreateSizedView(gfx::Size(20, 20));
- layout()->AddView(view2, 1, 1, GridLayout::FILL, GridLayout::LEADING);
+ layout()->AddView(CreateSizedView(gfx::Size(20, 20)), 1, 1, GridLayout::FILL,
+ GridLayout::LEADING);
// Add another flexible view in row three in order to ensure column set
// ordering doesn't influence sizing behaviour.
layout()->StartRow(0, 2);
- View* view3 = new FlexibleView(40);
- layout()->AddView(view3, 1, 1, GridLayout::FILL, GridLayout::LEADING);
+ layout()->AddView(std::make_unique<FlexibleView>(40), 1, 1, GridLayout::FILL,
+ GridLayout::LEADING);
// We expect a height of 50: 30 from the variable width view in the first row
// plus 20 from the statically sized view in the second row. The flexible
@@ -792,13 +704,11 @@ TEST_F(GridLayoutTest, ColumnResizingOnGetPreferredSize) {
}
TEST_F(GridLayoutTest, MinimumPreferredSize) {
- View v1;
- v1.SetPreferredSize(gfx::Size(10, 20));
ColumnSet* set = layout()->AddColumnSet(0);
set->AddColumn(GridLayout::FILL, GridLayout::FILL,
0, GridLayout::USE_PREF, 0, 0);
layout()->StartRow(0, 0);
- layout()->AddView(&v1);
+ layout()->AddView(CreateSizedView(gfx::Size(10, 20)));
gfx::Size pref = GetPreferredSize();
EXPECT_EQ(gfx::Size(10, 20), pref);
@@ -806,8 +716,6 @@ TEST_F(GridLayoutTest, MinimumPreferredSize) {
layout()->set_minimum_size(gfx::Size(40, 40));
pref = GetPreferredSize();
EXPECT_EQ(gfx::Size(40, 40), pref);
-
- RemoveAll();
}
// Test that attempting a Layout() while nested in AddView() causes a DCHECK.
@@ -818,17 +726,15 @@ TEST_F(GridLayoutTest, LayoutOnAddDeath) {
set->AddColumn(GridLayout::FILL, GridLayout::FILL, 0, GridLayout::USE_PREF, 0,
0);
layout()->StartRow(0, 0);
- LayoutOnAddView view;
- EXPECT_DCHECK_DEATH(layout()->AddView(&view));
+ auto view = std::make_unique<LayoutOnAddView>();
+ EXPECT_DCHECK_DEATH(layout()->AddView(std::move(view)));
// Death tests use fork(), so nothing should be added here.
- EXPECT_FALSE(view.parent());
+ EXPECT_FALSE(view->parent());
// If the View has nothing to change, adding should succeed.
- view.set_target_size(view.GetPreferredSize());
- layout()->AddView(&view);
- EXPECT_TRUE(view.parent());
-
- RemoveAll();
+ view->set_target_size(view->GetPreferredSize());
+ auto* view_ptr = layout()->AddView(std::move(view));
+ EXPECT_TRUE(view_ptr->parent());
}
TEST_F(GridLayoutTest, ColumnMinForcesPreferredWidth) {
@@ -838,8 +744,7 @@ TEST_F(GridLayoutTest, ColumnMinForcesPreferredWidth) {
set->AddColumn(GridLayout::FILL, GridLayout::FILL, 5, GridLayout::USE_PREF, 0,
100);
layout()->StartRow(0, 0);
- View* view1 = CreateSizedView(gfx::Size(20, 10));
- layout()->AddView(view1);
+ layout()->AddView(CreateSizedView(gfx::Size(20, 10)));
EXPECT_EQ(gfx::Size(100, 10), GetPreferredSize());
}
@@ -855,26 +760,25 @@ TEST_F(GridLayoutTest, HonorsColumnMin) {
set->AddColumn(GridLayout::FILL, GridLayout::FILL, 5, GridLayout::USE_PREF, 0,
0);
layout()->StartRow(0, 0);
- View* view1 = CreateViewWithMinAndPref(gfx::Size(10, 10), gfx::Size(125, 10));
- layout()->AddView(view1);
-
- View* view2 = CreateViewWithMinAndPref(gfx::Size(10, 10), gfx::Size(50, 10));
- layout()->AddView(view2);
+ View* view1 = layout()->AddView(
+ CreateViewWithMinAndPref(gfx::Size(10, 10), gfx::Size(125, 10)));
+ View* view2 = layout()->AddView(
+ CreateViewWithMinAndPref(gfx::Size(10, 10), gfx::Size(50, 10)));
EXPECT_EQ(gfx::Size(175, 10), GetPreferredSize());
- host().SetBounds(0, 0, 175, 0);
- layout()->Layout(&host());
+ host()->SetBounds(0, 0, 175, 0);
+ layout()->Layout(host());
EXPECT_EQ(gfx::Rect(0, 0, 125, 10), view1->bounds());
EXPECT_EQ(gfx::Rect(125, 0, 50, 10), view2->bounds());
- host().SetBounds(0, 0, 125, 0);
- layout()->Layout(&host());
+ host()->SetBounds(0, 0, 125, 0);
+ layout()->Layout(host());
EXPECT_EQ(gfx::Rect(0, 0, 100, 10), view1->bounds());
EXPECT_EQ(gfx::Rect(100, 0, 25, 10), view2->bounds());
- host().SetBounds(0, 0, 120, 0);
- layout()->Layout(&host());
+ host()->SetBounds(0, 0, 120, 0);
+ layout()->Layout(host());
EXPECT_EQ(gfx::Rect(0, 0, 100, 10), view1->bounds());
EXPECT_EQ(gfx::Rect(100, 0, 20, 10), view2->bounds());
}
@@ -889,15 +793,13 @@ TEST_F(GridLayoutTest, TwoViewsOneSizeSmallerThanMinimum) {
set->AddColumn(GridLayout::FILL, GridLayout::FILL, 5, GridLayout::USE_PREF, 0,
0);
layout()->StartRow(0, 0);
- View* view1 = CreateViewWithMinAndPref(gfx::Size(20, 10), gfx::Size(100, 10));
- layout()->AddView(view1);
-
- View* view2 =
- CreateViewWithMinAndPref(gfx::Size(100, 10), gfx::Size(100, 10));
- layout()->AddView(view2);
+ View* view1 = layout()->AddView(
+ CreateViewWithMinAndPref(gfx::Size(20, 10), gfx::Size(100, 10)));
+ View* view2 = layout()->AddView(
+ CreateViewWithMinAndPref(gfx::Size(100, 10), gfx::Size(100, 10)));
- host().SetBounds(0, 0, 110, 0);
- layout()->Layout(&host());
+ host()->SetBounds(0, 0, 110, 0);
+ layout()->Layout(host());
EXPECT_EQ(gfx::Rect(0, 0, 20, 10), view1->bounds());
EXPECT_EQ(gfx::Rect(20, 0, 100, 10), view2->bounds());
}
@@ -912,44 +814,43 @@ TEST_F(GridLayoutTest, TwoViewsBothSmallerThanMinimumDifferentResizeWeights) {
set->AddColumn(GridLayout::FILL, GridLayout::FILL, 2, GridLayout::USE_PREF, 0,
0);
layout()->StartRow(0, 0);
- View* view1 = CreateViewWithMinAndPref(gfx::Size(91, 10), gfx::Size(100, 10));
- layout()->AddView(view1);
-
- View* view2 = CreateViewWithMinAndPref(gfx::Size(10, 10), gfx::Size(100, 10));
- layout()->AddView(view2);
+ View* view1 = layout()->AddView(
+ CreateViewWithMinAndPref(gfx::Size(91, 10), gfx::Size(100, 10)));
+ View* view2 = layout()->AddView(
+ CreateViewWithMinAndPref(gfx::Size(10, 10), gfx::Size(100, 10)));
// 200 is the preferred, each should get their preferred width.
- host().SetBounds(0, 0, 200, 0);
- layout()->Layout(&host());
+ host()->SetBounds(0, 0, 200, 0);
+ layout()->Layout(host());
EXPECT_EQ(gfx::Rect(0, 0, 100, 10), view1->bounds());
EXPECT_EQ(gfx::Rect(100, 0, 100, 10), view2->bounds());
// 1 pixel smaller than pref.
- host().SetBounds(0, 0, 199, 0);
- layout()->Layout(&host());
+ host()->SetBounds(0, 0, 199, 0);
+ layout()->Layout(host());
EXPECT_EQ(gfx::Rect(0, 0, 99, 10), view1->bounds());
EXPECT_EQ(gfx::Rect(99, 0, 100, 10), view2->bounds());
// 10 pixels smaller than pref.
- host().SetBounds(0, 0, 190, 0);
- layout()->Layout(&host());
+ host()->SetBounds(0, 0, 190, 0);
+ layout()->Layout(host());
EXPECT_EQ(gfx::Rect(0, 0, 92, 10), view1->bounds());
EXPECT_EQ(gfx::Rect(92, 0, 98, 10), view2->bounds());
// 11 pixels smaller than pref.
- host().SetBounds(0, 0, 189, 0);
- layout()->Layout(&host());
+ host()->SetBounds(0, 0, 189, 0);
+ layout()->Layout(host());
EXPECT_EQ(gfx::Rect(0, 0, 91, 10), view1->bounds());
EXPECT_EQ(gfx::Rect(91, 0, 98, 10), view2->bounds());
// 12 pixels smaller than pref.
- host().SetBounds(0, 0, 188, 0);
- layout()->Layout(&host());
+ host()->SetBounds(0, 0, 188, 0);
+ layout()->Layout(host());
EXPECT_EQ(gfx::Rect(0, 0, 91, 10), view1->bounds());
EXPECT_EQ(gfx::Rect(91, 0, 97, 10), view2->bounds());
- host().SetBounds(0, 0, 5, 0);
- layout()->Layout(&host());
+ host()->SetBounds(0, 0, 5, 0);
+ layout()->Layout(host());
EXPECT_EQ(gfx::Rect(0, 0, 91, 10), view1->bounds());
EXPECT_EQ(gfx::Rect(91, 0, 10, 10), view2->bounds());
}
@@ -962,19 +863,19 @@ TEST_F(GridLayoutTest, TwoViewsOneColumnUsePrefOtherFixed) {
set->AddColumn(GridLayout::FILL, GridLayout::FILL, 2, GridLayout::FIXED, 100,
0);
layout()->StartRow(0, 0);
- View* view1 = CreateViewWithMinAndPref(gfx::Size(10, 10), gfx::Size(100, 10));
- layout()->AddView(view1);
- View* view2 = CreateViewWithMinAndPref(gfx::Size(10, 10), gfx::Size(100, 10));
- layout()->AddView(view2);
+ View* view1 = layout()->AddView(
+ CreateViewWithMinAndPref(gfx::Size(10, 10), gfx::Size(100, 10)));
+ View* view2 = layout()->AddView(
+ CreateViewWithMinAndPref(gfx::Size(10, 10), gfx::Size(100, 10)));
- host().SetBounds(0, 0, 120, 0);
- layout()->Layout(&host());
+ host()->SetBounds(0, 0, 120, 0);
+ layout()->Layout(host());
EXPECT_EQ(gfx::Rect(0, 0, 20, 10), view1->bounds());
// Even though column 2 has a resize percent, it's FIXED, so it won't shrink.
EXPECT_EQ(gfx::Rect(20, 0, 100, 10), view2->bounds());
- host().SetBounds(0, 0, 10, 0);
- layout()->Layout(&host());
+ host()->SetBounds(0, 0, 10, 0);
+ layout()->Layout(host());
EXPECT_EQ(gfx::Rect(0, 0, 10, 10), view1->bounds());
EXPECT_EQ(gfx::Rect(10, 0, 100, 10), view2->bounds());
}
@@ -987,23 +888,24 @@ TEST_F(GridLayoutTest, TwoViewsBothColumnsResizableOneViewFixedWidthMin) {
set->AddColumn(GridLayout::FILL, GridLayout::FILL, 1, GridLayout::USE_PREF, 0,
0);
layout()->StartRow(0, 0);
- View* view1 = CreateViewWithMinAndPref(gfx::Size(10, 10), gfx::Size(100, 10));
- layout()->AddView(view1);
- View* view2 = CreateViewWithMinAndPref(gfx::Size(10, 10), gfx::Size(100, 10));
- layout()->AddView(view2, 1, 1, GridLayout::FILL, GridLayout::FILL, 50, 10);
+ View* view1 = layout()->AddView(
+ CreateViewWithMinAndPref(gfx::Size(10, 10), gfx::Size(100, 10)));
+ View* view2 = layout()->AddView(
+ CreateViewWithMinAndPref(gfx::Size(10, 10), gfx::Size(100, 10)), 1, 1,
+ GridLayout::FILL, GridLayout::FILL, 50, 10);
- host().SetBounds(0, 0, 80, 0);
- layout()->Layout(&host());
+ host()->SetBounds(0, 0, 80, 0);
+ layout()->Layout(host());
EXPECT_EQ(gfx::Rect(0, 0, 30, 10), view1->bounds());
EXPECT_EQ(gfx::Rect(30, 0, 50, 10), view2->bounds());
- host().SetBounds(0, 0, 70, 0);
- layout()->Layout(&host());
+ host()->SetBounds(0, 0, 70, 0);
+ layout()->Layout(host());
EXPECT_EQ(gfx::Rect(0, 0, 20, 10), view1->bounds());
EXPECT_EQ(gfx::Rect(20, 0, 50, 10), view2->bounds());
- host().SetBounds(0, 0, 10, 0);
- layout()->Layout(&host());
+ host()->SetBounds(0, 0, 10, 0);
+ layout()->Layout(host());
EXPECT_EQ(gfx::Rect(0, 0, 10, 10), view1->bounds());
EXPECT_EQ(gfx::Rect(10, 0, 50, 10), view2->bounds());
}
@@ -1028,15 +930,13 @@ TEST_F(GridLayoutTest, HeightForWidthCalledWhenNotGivenPreferredWidth) {
0, 0);
layout()->StartRow(0, 0);
const int pref_height = 100;
- // |view| is owned by parent.
- SettablePreferredHeightView* view =
- new SettablePreferredHeightView(pref_height);
+ auto view = std::make_unique<SettablePreferredHeightView>(pref_height);
const gfx::Size pref(10, 20);
view->SetPreferredSize(pref);
- layout()->AddView(view);
+ layout()->AddView(std::move(view));
EXPECT_EQ(pref, GetPreferredSize());
- EXPECT_EQ(pref_height, host().GetHeightForWidth(5));
+ EXPECT_EQ(pref_height, host()->GetHeightForWidth(5));
}
} // namespace views
diff --git a/chromium/ui/views/layout/interpolating_layout_manager.cc b/chromium/ui/views/layout/interpolating_layout_manager.cc
new file mode 100644
index 00000000000..496b934a108
--- /dev/null
+++ b/chromium/ui/views/layout/interpolating_layout_manager.cc
@@ -0,0 +1,251 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/layout/interpolating_layout_manager.h"
+
+#include <memory>
+#include <utility>
+
+#include "ui/gfx/animation/tween.h"
+#include "ui/views/view.h"
+
+namespace views {
+
+namespace {
+
+using ChildLayout = LayoutManagerBase::ChildLayout;
+using ProposedLayout = LayoutManagerBase::ProposedLayout;
+
+// Returns a layout that's linearly interpolated between |first_layout| and
+// |second_layout| by |percent|. See gfx::Tween::LinearIntValueBetween() for
+// the exact math involved.
+ProposedLayout Interpolate(double value,
+ const ProposedLayout& start,
+ const ProposedLayout& target) {
+ ProposedLayout layout;
+ const size_t num_children = start.child_layouts.size();
+ DCHECK_EQ(num_children, target.child_layouts.size());
+
+ // Interpolate the host size.
+ // TODO(dfried): Add direct gfx::Size interpolation to gfx::Tween.
+ const gfx::Size size =
+ gfx::Tween::SizeValueBetween(value, start.host_size, target.host_size);
+ layout.host_size = gfx::Size(size.width(), size.height());
+
+ // Interpolate the child bounds.
+ for (size_t i = 0; i < num_children; ++i) {
+ const ChildLayout& start_child = start.child_layouts[i];
+ const ChildLayout& target_child = target.child_layouts[i];
+ DCHECK_EQ(start_child.child_view, target_child.child_view);
+ layout.child_layouts.emplace_back(
+ ChildLayout{start_child.child_view,
+ gfx::Tween::RectValueBetween(value, start_child.bounds,
+ target_child.bounds),
+ start_child.visible && target_child.visible});
+ }
+ return layout;
+}
+
+} // namespace
+
+InterpolatingLayoutManager::InterpolatingLayoutManager() {}
+InterpolatingLayoutManager::~InterpolatingLayoutManager() = default;
+
+InterpolatingLayoutManager& InterpolatingLayoutManager::SetOrientation(
+ LayoutOrientation orientation) {
+ if (orientation_ != orientation) {
+ orientation_ = orientation;
+ InvalidateLayout();
+ }
+ return *this;
+}
+
+void InterpolatingLayoutManager::AddLayoutInternal(
+ std::unique_ptr<LayoutManagerBase> engine,
+ const Span& interpolation_range) {
+ DCHECK(engine);
+
+ SyncStateTo(engine.get());
+ auto result = embedded_layouts_.emplace(
+ std::make_pair(interpolation_range, std::move(engine)));
+ DCHECK(result.second) << "Cannot replace existing layout manager for "
+ << interpolation_range.ToString();
+
+#if DCHECK_IS_ON()
+ // Sanity checking to ensure interpolation ranges do not overlap (we can only
+ // interpolate between two layouts currently).
+ auto next = result.first;
+ ++next;
+ if (next != embedded_layouts_.end())
+ DCHECK_GE(next->first.start(), interpolation_range.end());
+ if (result.first != embedded_layouts_.begin()) {
+ auto prev = result.first;
+ --prev;
+ DCHECK_LE(prev->first.end(), interpolation_range.start());
+ }
+#endif // DCHECK_IS_ON()
+}
+
+InterpolatingLayoutManager::LayoutInterpolation
+InterpolatingLayoutManager::GetInterpolation(
+ const SizeBounds& size_bounds) const {
+ DCHECK(!embedded_layouts_.empty());
+
+ LayoutInterpolation result;
+
+ const base::Optional<int> dimension =
+ orientation_ == LayoutOrientation::kHorizontal ? size_bounds.width()
+ : size_bounds.height();
+
+ // Find the larger layout that overlaps the target size.
+ auto match = dimension ? embedded_layouts_.upper_bound({*dimension, 0})
+ : embedded_layouts_.end();
+ DCHECK(match != embedded_layouts_.begin())
+ << "No layout set for primary dimension size "
+ << (dimension ? *dimension : -1) << "; first layout starts at "
+ << match->first.ToString();
+ result.first = (--match)->second.get();
+
+ // If the target size falls in an interpolation range, get the other layout.
+ const Span& first_span = match->first;
+ if (dimension && first_span.end() > *dimension) {
+ DCHECK(match != embedded_layouts_.begin())
+ << "Primary dimension size " << (dimension ? *dimension : -1)
+ << " falls into interpolation range " << match->first.ToString()
+ << " but there is no smaller layout to interpolate with.";
+ result.second = (--match)->second.get();
+ result.percent_second =
+ float{first_span.end() - *dimension} / float{first_span.length()};
+ }
+
+ return result;
+}
+
+LayoutManagerBase::ProposedLayout
+InterpolatingLayoutManager::CalculateProposedLayout(
+ const SizeBounds& size_bounds) const {
+ // For interpolating layout we will never call this method except for fully-
+ // specified sizes.
+ DCHECK(size_bounds.width());
+ DCHECK(size_bounds.height());
+ const gfx::Size size(*size_bounds.width(), *size_bounds.height());
+
+ const LayoutInterpolation interpolation = GetInterpolation(size_bounds);
+ const ProposedLayout first = interpolation.first->GetProposedLayout(size);
+
+ if (!interpolation.second)
+ return first;
+
+ // If the target size falls in an interpolation range, get the other layout.
+ const ProposedLayout second = interpolation.second->GetProposedLayout(size);
+ return Interpolate(interpolation.percent_second, first, second);
+}
+
+void InterpolatingLayoutManager::SetDefaultLayout(
+ LayoutManagerBase* default_layout) {
+ if (default_layout_ == default_layout)
+ return;
+
+ // Make sure we already own the layout.
+ DCHECK(embedded_layouts_.end() !=
+ std::find_if(embedded_layouts_.begin(), embedded_layouts_.end(),
+ [=](const auto& pair) {
+ return pair.second.get() == default_layout;
+ }));
+ default_layout_ = default_layout;
+ InvalidateLayout();
+}
+
+gfx::Size InterpolatingLayoutManager::GetPreferredSize(const View* host) const {
+ DCHECK_EQ(host_view(), host);
+ DCHECK(host);
+ return GetDefaultLayout()->GetPreferredSize(host);
+}
+
+gfx::Size InterpolatingLayoutManager::GetMinimumSize(const View* host) const {
+ DCHECK_EQ(host_view(), host);
+ DCHECK(host);
+ return GetSmallestLayout()->GetMinimumSize(host);
+}
+
+int InterpolatingLayoutManager::GetPreferredHeightForWidth(const View* host,
+ int width) const {
+ // It is in general not possible to determine what the correct
+ // height-for-width trade-off is while interpolating between two already-
+ // generated layouts because the values tend to rely on the behavior of
+ // individual child views at specific dimensions.
+ //
+ // The two reasonable choices are to use the larger of the two values (with
+ // the understanding that the height of the view may "pop" at the edge of the
+ // interpolation range), or to interpolate between the heights and hope that
+ // the result is fairly close to what we would want.
+ //
+ // We have opted for the second approach because it provides a smoother visual
+ // experience; if this doesn't work in practice we can look at other options.
+
+ const LayoutInterpolation interpolation =
+ GetInterpolation({width, base::nullopt});
+ const int first =
+ interpolation.first->GetPreferredHeightForWidth(host, width);
+ if (!interpolation.second)
+ return first;
+
+ const int second =
+ interpolation.second->GetPreferredHeightForWidth(host, width);
+ return gfx::Tween::LinearIntValueBetween(interpolation.percent_second, first,
+ second);
+}
+
+void InterpolatingLayoutManager::InvalidateLayout() {
+ LayoutManagerBase::InvalidateLayout();
+ for (auto& embedded : embedded_layouts_)
+ embedded.second->InvalidateLayout();
+}
+
+void InterpolatingLayoutManager::SetChildViewIgnoredByLayout(View* child_view,
+ bool ignored) {
+ LayoutManagerBase::SetChildViewIgnoredByLayout(child_view, ignored);
+ for (auto& embedded : embedded_layouts_)
+ embedded.second->SetChildViewIgnoredByLayout(child_view, ignored);
+}
+
+void InterpolatingLayoutManager::Installed(View* host_view) {
+ LayoutManagerBase::Installed(host_view);
+ for (auto& embedded : embedded_layouts_)
+ embedded.second->Installed(host_view);
+}
+
+void InterpolatingLayoutManager::ViewAdded(View* host_view, View* child_view) {
+ LayoutManagerBase::ViewAdded(host_view, child_view);
+ for (auto& embedded : embedded_layouts_)
+ embedded.second->ViewAdded(host_view, child_view);
+}
+
+void InterpolatingLayoutManager::ViewRemoved(View* host_view,
+ View* child_view) {
+ LayoutManagerBase::ViewRemoved(host_view, child_view);
+ for (auto& embedded : embedded_layouts_)
+ embedded.second->ViewRemoved(host_view, child_view);
+}
+
+void InterpolatingLayoutManager::ViewVisibilitySet(View* host,
+ View* view,
+ bool visible) {
+ LayoutManagerBase::ViewVisibilitySet(host, view, visible);
+ for (auto& embedded : embedded_layouts_)
+ embedded.second->ViewVisibilitySet(host, view, visible);
+}
+
+const LayoutManagerBase* InterpolatingLayoutManager::GetDefaultLayout() const {
+ DCHECK(!embedded_layouts_.empty());
+ return default_layout_ ? default_layout_
+ : embedded_layouts_.rbegin()->second.get();
+}
+
+const LayoutManagerBase* InterpolatingLayoutManager::GetSmallestLayout() const {
+ DCHECK(!embedded_layouts_.empty());
+ return embedded_layouts_.begin()->second.get();
+}
+
+} // namespace views
diff --git a/chromium/ui/views/layout/interpolating_layout_manager.h b/chromium/ui/views/layout/interpolating_layout_manager.h
new file mode 100644
index 00000000000..0cc084cafa8
--- /dev/null
+++ b/chromium/ui/views/layout/interpolating_layout_manager.h
@@ -0,0 +1,132 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_LAYOUT_INTERPOLATING_LAYOUT_MANAGER_H_
+#define UI_VIEWS_LAYOUT_INTERPOLATING_LAYOUT_MANAGER_H_
+
+#include <map>
+#include <memory>
+#include <utility>
+
+#include "ui/views/layout/flex_layout_types.h"
+#include "ui/views/layout/layout_manager_base.h"
+
+namespace views {
+
+// Layout which interpolates between multiple embedded LayoutManagerBase
+// layouts.
+//
+// An InterpolatingLayoutManager has a default layout, which applies at the
+// smallest layout size along the layout's major axis (defined by |orientation|)
+// and additional layouts, which phase in at some larger size. If only the
+// default layout is set, the layout is functionally equivalent to the default
+// layout.
+//
+// An example:
+//
+// InterpolatingLayoutManager* e =
+// new InterpolatingLayoutManager(LayoutOrientation::kHorizontal);
+// e->AddLayout(std::make_unique<CompactLayout>());
+// e->AddLayout(std::make_unique<NormalLayout>(), {50, 0});
+// e->AddLayout(std::make_unique<SpaciousLayout>(), {100, 50});
+//
+// Now as the view expands, the different layouts are used:
+//
+// 0 50 100 150
+// | Compact | Normal | Norm <~> Spa | Spacious ->
+//
+// In the range from 100 to 150 (exclusive), an interpolation of the Normal and
+// Spacious layouts is used. When interpolation happens in this way, the
+// visibility of views is the conjunction of the visibilities in each layout, so
+// if either layout hides a view then the interpolated layout also hides it.
+// Since this can produce some unwanted visual results, we recommend making sure
+// that over the interpolation range, visibility matches up between the layouts
+// on either side.
+//
+// Note that behavior when interpolation ranges overlap is undefined, but will
+// be guaranteed to at least be the result of mixing two adjacent layouts that
+// fall over the range in a way that is not completely irrational.
+class VIEWS_EXPORT InterpolatingLayoutManager : public LayoutManagerBase {
+ public:
+ InterpolatingLayoutManager();
+ ~InterpolatingLayoutManager() override;
+
+ InterpolatingLayoutManager& SetOrientation(LayoutOrientation orientation);
+ LayoutOrientation orientation() const { return orientation_; }
+
+ // Adds a layout which starts and finished phasing in at |start_interpolation|
+ // and |end_interpolation|, respectively. Currently, having more than one
+ // layout's interpolation range overlapping results in undefined behavior.
+ //
+ // This object retains ownership of the layout engine, but the method returns
+ // a typed raw pointer to the added layout engine.
+ template <class T>
+ T* AddLayout(std::unique_ptr<T> layout_manager,
+ const Span& interpolation_range = Span()) {
+ T* const temp = layout_manager.get();
+ AddLayoutInternal(std::move(layout_manager), interpolation_range);
+ return temp;
+ }
+
+ // Specifies which layout is default (i.e. will be used for determining
+ // preferred layout size). If you do not set this, the largest layout will be
+ // used.
+ void SetDefaultLayout(LayoutManagerBase* default_layout);
+
+ // LayoutManagerBase:
+ gfx::Size GetPreferredSize(const View* host) const override;
+ gfx::Size GetMinimumSize(const View* host) const override;
+ int GetPreferredHeightForWidth(const View* host, int width) const override;
+ void InvalidateLayout() override;
+ void SetChildViewIgnoredByLayout(View* child_view, bool ignored) override;
+
+ protected:
+ // LayoutManagerBase:
+ void Installed(View* host_view) override;
+ void ViewAdded(View* host_view, View* child_view) override;
+ void ViewRemoved(View* host_view, View* child_view) override;
+ void ViewVisibilitySet(View* host, View* view, bool visible) override;
+ ProposedLayout CalculateProposedLayout(
+ const SizeBounds& size_bounds) const override;
+
+ private:
+ // Describes an interpolation between two layouts as a pointer to each and
+ // a percentage of distance between them to interpolate linearly to.
+ struct LayoutInterpolation {
+ LayoutManagerBase* first = nullptr;
+ LayoutManagerBase* second = nullptr;
+
+ // The closer this number is to zero, the more of |first| is used; the
+ // closer to 1.0f, the more of |second|. If the value is 0, |second| may be
+ // null.
+ float percent_second = 0.0f;
+ };
+
+ void AddLayoutInternal(std::unique_ptr<LayoutManagerBase> layout,
+ const Span& interpolation_range);
+
+ // Given a set of size bounds and the current layout's orientation, returns
+ // a LayoutInterpolation providing the two layouts to interpolate between.
+ // If only one layout applies, only |right| is set and |percent| is set to 1.
+ LayoutInterpolation GetInterpolation(const SizeBounds& bounds) const;
+
+ // Returns the default layout, or the largest layout if the default has not
+ // been set.
+ const LayoutManagerBase* GetDefaultLayout() const;
+
+ // Returns the smallest layout; useful for calculating minimum layout size.
+ const LayoutManagerBase* GetSmallestLayout() const;
+
+ LayoutOrientation orientation_ = LayoutOrientation::kHorizontal;
+
+ // Maps from interpolation range to embedded layout.
+ std::map<Span, std::unique_ptr<LayoutManagerBase>> embedded_layouts_;
+ LayoutManagerBase* default_layout_ = nullptr;
+
+ DISALLOW_COPY_AND_ASSIGN(InterpolatingLayoutManager);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_LAYOUT_INTERPOLATING_LAYOUT_MANAGER_H_
diff --git a/chromium/ui/views/layout/interpolating_layout_manager_unittest.cc b/chromium/ui/views/layout/interpolating_layout_manager_unittest.cc
new file mode 100644
index 00000000000..cf44cda7c8a
--- /dev/null
+++ b/chromium/ui/views/layout/interpolating_layout_manager_unittest.cc
@@ -0,0 +1,323 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/layout/interpolating_layout_manager.h"
+
+#include <memory>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/gfx/animation/tween.h"
+#include "ui/views/test/test_views.h"
+#include "ui/views/view.h"
+
+namespace views {
+
+namespace {
+
+class TestLayout : public LayoutManagerBase {
+ public:
+ explicit TestLayout(int size = 0) : size_(size) {}
+
+ int num_layouts_generated() const { return num_layouts_generated_; }
+
+ ProposedLayout CalculateProposedLayout(
+ const SizeBounds& size_bounds) const override {
+ ++num_layouts_generated_;
+ ProposedLayout layout;
+ int x = size_;
+ for (auto it = host_view()->children().begin();
+ it != host_view()->children().end(); ++it) {
+ if (!IsChildIncludedInLayout(*it))
+ continue;
+ ChildLayout child_layout;
+ child_layout.child_view = *it;
+ child_layout.visible = true;
+ child_layout.bounds = gfx::Rect(x, 1, size_, size_);
+ layout.child_layouts.push_back(child_layout);
+ x += size_ + 1;
+ }
+ layout.host_size = {x, 2 + size_};
+ return layout;
+ }
+
+ private:
+ const int size_;
+ mutable int num_layouts_generated_ = 0;
+};
+
+void CompareProposedLayouts(const LayoutManagerBase::ProposedLayout& left,
+ const LayoutManagerBase::ProposedLayout& right) {
+ EXPECT_EQ(left.host_size, right.host_size);
+ EXPECT_EQ(left.child_layouts.size(), right.child_layouts.size());
+ for (auto left_it = left.child_layouts.begin(),
+ right_it = right.child_layouts.begin();
+ left_it != left.child_layouts.end() &&
+ right_it != right.child_layouts.end();
+ ++left_it, ++right_it) {
+ EXPECT_EQ(left_it->child_view, right_it->child_view);
+ EXPECT_EQ(left_it->visible, right_it->visible);
+ if (left_it->visible)
+ EXPECT_EQ(left_it->bounds, right_it->bounds);
+ }
+}
+
+} // anonymous namespace
+
+class InterpolatingLayoutManagerTest : public testing::Test {
+ public:
+ void SetUp() override {
+ host_view_ = std::make_unique<View>();
+ layout_manager_ = host_view_->SetLayoutManager(
+ std::make_unique<InterpolatingLayoutManager>());
+ }
+
+ InterpolatingLayoutManager* layout_manager() { return layout_manager_; }
+ View* host_view() { return host_view_.get(); }
+
+ private:
+ InterpolatingLayoutManager* layout_manager_ = nullptr;
+ std::unique_ptr<View> host_view_;
+};
+
+TEST_F(InterpolatingLayoutManagerTest, AddLayout) {
+ TestLayout* const first_layout =
+ layout_manager()->AddLayout(std::make_unique<TestLayout>());
+ EXPECT_EQ(0, first_layout->num_layouts_generated());
+ layout_manager()->GetProposedLayout({0, 0});
+ EXPECT_EQ(1, first_layout->num_layouts_generated());
+}
+
+TEST_F(InterpolatingLayoutManagerTest, AddLayout_CheckZeroAndUnbounded) {
+ TestLayout* const first_layout =
+ layout_manager()->AddLayout(std::make_unique<TestLayout>());
+ TestLayout* const second_layout =
+ layout_manager()->AddLayout(std::make_unique<TestLayout>(), {5, 0});
+ EXPECT_EQ(0, first_layout->num_layouts_generated());
+ EXPECT_EQ(0, second_layout->num_layouts_generated());
+ layout_manager()->GetPreferredSize(host_view());
+ EXPECT_EQ(0, first_layout->num_layouts_generated());
+ EXPECT_EQ(1, second_layout->num_layouts_generated());
+ layout_manager()->GetMinimumSize(host_view());
+ EXPECT_EQ(1, first_layout->num_layouts_generated());
+ EXPECT_EQ(1, second_layout->num_layouts_generated());
+}
+
+TEST_F(InterpolatingLayoutManagerTest, GetProposedLayout_HardBoundary) {
+ TestLayout* const first_layout =
+ layout_manager()->AddLayout(std::make_unique<TestLayout>());
+ TestLayout* const second_layout =
+ layout_manager()->AddLayout(std::make_unique<TestLayout>(), {5, 0});
+ EXPECT_EQ(0, first_layout->num_layouts_generated());
+ EXPECT_EQ(0, second_layout->num_layouts_generated());
+ layout_manager()->GetProposedLayout({5, 2});
+ EXPECT_EQ(0, first_layout->num_layouts_generated());
+ EXPECT_EQ(1, second_layout->num_layouts_generated());
+ layout_manager()->GetProposedLayout({4, 2});
+ EXPECT_EQ(1, first_layout->num_layouts_generated());
+ EXPECT_EQ(1, second_layout->num_layouts_generated());
+}
+
+TEST_F(InterpolatingLayoutManagerTest, GetProposedLayout_SoftBoudnary) {
+ TestLayout* const first_layout =
+ layout_manager()->AddLayout(std::make_unique<TestLayout>());
+ TestLayout* const second_layout =
+ layout_manager()->AddLayout(std::make_unique<TestLayout>(), {4, 2});
+ EXPECT_EQ(0, first_layout->num_layouts_generated());
+ EXPECT_EQ(0, second_layout->num_layouts_generated());
+ layout_manager()->GetProposedLayout({5, 2});
+ EXPECT_EQ(1, first_layout->num_layouts_generated());
+ EXPECT_EQ(1, second_layout->num_layouts_generated());
+ layout_manager()->GetProposedLayout({4, 2});
+ EXPECT_EQ(2, first_layout->num_layouts_generated());
+ EXPECT_EQ(1, second_layout->num_layouts_generated());
+ layout_manager()->GetProposedLayout({6, 6});
+ EXPECT_EQ(2, first_layout->num_layouts_generated());
+ EXPECT_EQ(2, second_layout->num_layouts_generated());
+}
+
+TEST_F(InterpolatingLayoutManagerTest, GetProposedLayout_MultipleLayouts) {
+ TestLayout* const first_layout =
+ layout_manager()->AddLayout(std::make_unique<TestLayout>());
+ TestLayout* const second_layout =
+ layout_manager()->AddLayout(std::make_unique<TestLayout>(), {4, 2});
+ TestLayout* const third_layout =
+ layout_manager()->AddLayout(std::make_unique<TestLayout>(), {6, 2});
+ EXPECT_EQ(0, first_layout->num_layouts_generated());
+ EXPECT_EQ(0, second_layout->num_layouts_generated());
+ EXPECT_EQ(0, third_layout->num_layouts_generated());
+ layout_manager()->GetProposedLayout({5, 2});
+ EXPECT_EQ(1, first_layout->num_layouts_generated());
+ EXPECT_EQ(1, second_layout->num_layouts_generated());
+ EXPECT_EQ(0, third_layout->num_layouts_generated());
+ layout_manager()->GetProposedLayout({6, 3});
+ EXPECT_EQ(1, first_layout->num_layouts_generated());
+ EXPECT_EQ(2, second_layout->num_layouts_generated());
+ EXPECT_EQ(0, third_layout->num_layouts_generated());
+ layout_manager()->GetProposedLayout({7, 6});
+ EXPECT_EQ(1, first_layout->num_layouts_generated());
+ EXPECT_EQ(3, second_layout->num_layouts_generated());
+ EXPECT_EQ(1, third_layout->num_layouts_generated());
+ layout_manager()->GetProposedLayout({20, 3});
+ EXPECT_EQ(1, first_layout->num_layouts_generated());
+ EXPECT_EQ(3, second_layout->num_layouts_generated());
+ EXPECT_EQ(2, third_layout->num_layouts_generated());
+}
+
+TEST_F(InterpolatingLayoutManagerTest, InvalidateLayout) {
+ static const gfx::Size kLayoutSize(5, 5);
+
+ TestLayout* const first_layout =
+ layout_manager()->AddLayout(std::make_unique<TestLayout>());
+ TestLayout* const second_layout =
+ layout_manager()->AddLayout(std::make_unique<TestLayout>(), {4, 2});
+ host_view()->SetSize(kLayoutSize);
+ EXPECT_EQ(1, first_layout->num_layouts_generated());
+ EXPECT_EQ(1, second_layout->num_layouts_generated());
+ host_view()->Layout();
+ EXPECT_EQ(1, first_layout->num_layouts_generated());
+ EXPECT_EQ(1, second_layout->num_layouts_generated());
+ layout_manager()->InvalidateLayout();
+ host_view()->Layout();
+ EXPECT_EQ(2, first_layout->num_layouts_generated());
+ EXPECT_EQ(2, second_layout->num_layouts_generated());
+ host_view()->Layout();
+ EXPECT_EQ(2, first_layout->num_layouts_generated());
+ EXPECT_EQ(2, second_layout->num_layouts_generated());
+}
+
+TEST_F(InterpolatingLayoutManagerTest, SetOrientation) {
+ TestLayout* const first_layout =
+ layout_manager()->AddLayout(std::make_unique<TestLayout>());
+ TestLayout* const second_layout =
+ layout_manager()->AddLayout(std::make_unique<TestLayout>(), {4, 2});
+ layout_manager()->SetOrientation(LayoutOrientation::kVertical);
+ EXPECT_EQ(0, first_layout->num_layouts_generated());
+ EXPECT_EQ(0, second_layout->num_layouts_generated());
+ layout_manager()->GetProposedLayout({2, 6});
+ EXPECT_EQ(0, first_layout->num_layouts_generated());
+ EXPECT_EQ(1, second_layout->num_layouts_generated());
+ layout_manager()->GetProposedLayout({3, 5});
+ EXPECT_EQ(1, first_layout->num_layouts_generated());
+ EXPECT_EQ(2, second_layout->num_layouts_generated());
+ layout_manager()->GetProposedLayout({10, 3});
+ EXPECT_EQ(2, first_layout->num_layouts_generated());
+ EXPECT_EQ(2, second_layout->num_layouts_generated());
+}
+
+TEST_F(InterpolatingLayoutManagerTest, GetMinimumSize) {
+ TestLayout* const first_layout =
+ layout_manager()->AddLayout(std::make_unique<TestLayout>(5));
+ layout_manager()->AddLayout(std::make_unique<TestLayout>(10), {5, 5});
+
+ // Minimum size should be equal to the default layout.
+ EXPECT_EQ(first_layout->GetMinimumSize(host_view()),
+ layout_manager()->GetMinimumSize(host_view()));
+}
+
+TEST_F(InterpolatingLayoutManagerTest, GetPreferredSize_NoDefaultLayout) {
+ layout_manager()->AddLayout(std::make_unique<TestLayout>(5));
+ TestLayout* const second_layout =
+ layout_manager()->AddLayout(std::make_unique<TestLayout>(10), {5, 5});
+
+ // Preferred size should be equal to the largest layout.
+ EXPECT_EQ(second_layout->GetPreferredSize(host_view()),
+ layout_manager()->GetPreferredSize(host_view()));
+}
+
+TEST_F(InterpolatingLayoutManagerTest, GetPreferredSize_UsesDefaultLayout) {
+ TestLayout* const first_layout =
+ layout_manager()->AddLayout(std::make_unique<TestLayout>(5));
+ layout_manager()->AddLayout(std::make_unique<TestLayout>(10), {5, 5});
+ layout_manager()->SetDefaultLayout(first_layout);
+
+ // Preferred size should be equal to the largest layout.
+ EXPECT_EQ(first_layout->GetPreferredSize(host_view()),
+ layout_manager()->GetPreferredSize(host_view()));
+}
+
+TEST_F(InterpolatingLayoutManagerTest, GetPreferredHeightForWidth_Vertical) {
+ layout_manager()->SetOrientation(LayoutOrientation::kVertical);
+ layout_manager()->AddLayout(std::make_unique<TestLayout>(5));
+ TestLayout* const second_layout =
+ layout_manager()->AddLayout(std::make_unique<TestLayout>(10), {5, 5});
+
+ // Vertical means preferred height for width applies to largest layout.
+ EXPECT_EQ(second_layout->GetPreferredHeightForWidth(host_view(), 7),
+ layout_manager()->GetPreferredHeightForWidth(host_view(), 7));
+ EXPECT_EQ(second_layout->GetPreferredHeightForWidth(host_view(), 3),
+ layout_manager()->GetPreferredHeightForWidth(host_view(), 3));
+ EXPECT_EQ(second_layout->GetPreferredHeightForWidth(host_view(), 10),
+ layout_manager()->GetPreferredHeightForWidth(host_view(), 10));
+}
+
+TEST_F(InterpolatingLayoutManagerTest, GetPreferredHeightForWidth_Horizontal) {
+ layout_manager()->SetOrientation(LayoutOrientation::kHorizontal);
+ TestLayout* const first_layout =
+ layout_manager()->AddLayout(std::make_unique<TestLayout>(5));
+ TestLayout* const second_layout =
+ layout_manager()->AddLayout(std::make_unique<TestLayout>(10), {5, 5});
+
+ // Horizontal means preferred height for width is interpolated.
+ // Note that the layout doesn't actually flex height with varying width, so we
+ // can use constant reference values.
+ const int default_height =
+ first_layout->GetPreferredHeightForWidth(host_view(), 7);
+ const int other_height =
+ second_layout->GetPreferredHeightForWidth(host_view(), 7);
+ EXPECT_EQ(default_height,
+ layout_manager()->GetPreferredHeightForWidth(host_view(), 5));
+ EXPECT_EQ(other_height,
+ layout_manager()->GetPreferredHeightForWidth(host_view(), 10));
+ EXPECT_EQ(int{default_height * 0.4f + other_height * 0.6f},
+ layout_manager()->GetPreferredHeightForWidth(host_view(), 8));
+}
+
+TEST_F(InterpolatingLayoutManagerTest, GetProposedLayout) {
+ View* const child_view = host_view()->AddChildView(std::make_unique<View>());
+ TestLayout* const first_layout =
+ layout_manager()->AddLayout(std::make_unique<TestLayout>(5));
+ TestLayout* const second_layout =
+ layout_manager()->AddLayout(std::make_unique<TestLayout>(10), {5, 6});
+
+ constexpr gfx::Size kSmallSize{5, 10};
+ constexpr gfx::Size kLargeSize{11, 10};
+ constexpr gfx::Size kOneThirdSize{7, 10};
+ constexpr gfx::Size kOneHalfSize{8, 10};
+ const LayoutManagerBase::ProposedLayout expected_default =
+ first_layout->GetProposedLayout(kSmallSize);
+ const LayoutManagerBase::ProposedLayout expected_other =
+ second_layout->GetProposedLayout(kLargeSize);
+
+ CompareProposedLayouts(expected_default,
+ layout_manager()->GetProposedLayout(kSmallSize));
+ CompareProposedLayouts(expected_other,
+ layout_manager()->GetProposedLayout(kLargeSize));
+
+ LayoutManagerBase::ProposedLayout actual =
+ layout_manager()->GetProposedLayout(kOneThirdSize);
+ EXPECT_EQ(gfx::Tween::SizeValueBetween(0.3333, expected_default.host_size,
+ expected_other.host_size),
+ actual.host_size);
+ ASSERT_EQ(1U, actual.child_layouts.size());
+ EXPECT_EQ(child_view, actual.child_layouts[0].child_view);
+ EXPECT_EQ(true, actual.child_layouts[0].visible);
+ EXPECT_EQ(gfx::Tween::RectValueBetween(
+ 0.3333, expected_default.child_layouts[0].bounds,
+ expected_other.child_layouts[0].bounds),
+ actual.child_layouts[0].bounds);
+
+ actual = layout_manager()->GetProposedLayout(kOneHalfSize);
+ EXPECT_EQ(gfx::Tween::SizeValueBetween(0.5, expected_default.host_size,
+ expected_other.host_size),
+ actual.host_size);
+ ASSERT_EQ(1U, actual.child_layouts.size());
+ EXPECT_EQ(child_view, actual.child_layouts[0].child_view);
+ EXPECT_EQ(true, actual.child_layouts[0].visible);
+ EXPECT_EQ(gfx::Tween::RectValueBetween(
+ 0.5, expected_default.child_layouts[0].bounds,
+ expected_other.child_layouts[0].bounds),
+ actual.child_layouts[0].bounds);
+}
+
+} // namespace views
diff --git a/chromium/ui/views/layout/layout_manager_base.cc b/chromium/ui/views/layout/layout_manager_base.cc
new file mode 100644
index 00000000000..1992d5cbd9f
--- /dev/null
+++ b/chromium/ui/views/layout/layout_manager_base.cc
@@ -0,0 +1,171 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/layout/layout_manager_base.h"
+
+#include <utility>
+
+#include "base/logging.h"
+#include "ui/views/view.h"
+
+namespace views {
+
+LayoutManagerBase::ProposedLayout::ProposedLayout() = default;
+LayoutManagerBase::ProposedLayout::ProposedLayout(const ProposedLayout& other) =
+ default;
+LayoutManagerBase::ProposedLayout::ProposedLayout(ProposedLayout&& other) =
+ default;
+LayoutManagerBase::ProposedLayout::~ProposedLayout() = default;
+LayoutManagerBase::ProposedLayout& LayoutManagerBase::ProposedLayout::operator=(
+ const ProposedLayout& other) = default;
+LayoutManagerBase::ProposedLayout& LayoutManagerBase::ProposedLayout::operator=(
+ ProposedLayout&& other) = default;
+
+LayoutManagerBase::~LayoutManagerBase() = default;
+
+gfx::Size LayoutManagerBase::GetPreferredSize(const View* host) const {
+ DCHECK_EQ(host_view_, host);
+ if (!preferred_size_)
+ preferred_size_ = CalculateProposedLayout(SizeBounds()).host_size;
+ return *preferred_size_;
+}
+
+gfx::Size LayoutManagerBase::GetMinimumSize(const View* host) const {
+ DCHECK_EQ(host_view_, host);
+ if (!minimum_size_)
+ minimum_size_ = CalculateProposedLayout(SizeBounds(0, 0)).host_size;
+ return *minimum_size_;
+}
+
+int LayoutManagerBase::GetPreferredHeightForWidth(const View* host,
+ int width) const {
+ if (!last_height_for_width_ || last_height_for_width_->width() != width) {
+ const int height = CalculateProposedLayout(SizeBounds(width, base::nullopt))
+ .host_size.height();
+ last_height_for_width_ = gfx::Size(width, height);
+ }
+
+ return last_height_for_width_->height();
+}
+
+void LayoutManagerBase::Layout(View* host) {
+ DCHECK_EQ(host_view_, host);
+ const gfx::Size size = host->size();
+ ApplyLayout(GetProposedLayout(size));
+}
+
+void LayoutManagerBase::InvalidateLayout() {
+ minimum_size_.reset();
+ preferred_size_.reset();
+ last_height_for_width_.reset();
+ last_requested_size_.reset();
+}
+
+LayoutManagerBase::ProposedLayout LayoutManagerBase::GetProposedLayout(
+ const gfx::Size& host_size) const {
+ if (!last_requested_size_ || *last_requested_size_ != host_size) {
+ last_requested_size_ = host_size;
+ last_layout_ = CalculateProposedLayout(SizeBounds(host_size));
+ }
+ return last_layout_;
+}
+
+void LayoutManagerBase::SetChildViewIgnoredByLayout(View* child_view,
+ bool ignored) {
+ auto it = child_infos_.find(child_view);
+ DCHECK(it != child_infos_.end());
+ if (it->second.ignored == ignored)
+ return;
+
+ it->second.ignored = ignored;
+ InvalidateLayout();
+}
+
+bool LayoutManagerBase::IsChildViewIgnoredByLayout(
+ const View* child_view) const {
+ auto it = child_infos_.find(child_view);
+ DCHECK(it != child_infos_.end());
+ return it->second.ignored;
+}
+
+void LayoutManagerBase::Installed(View* host_view) {
+ DCHECK(host_view);
+ DCHECK(!host_view_);
+ DCHECK(child_infos_.empty());
+
+ host_view_ = host_view;
+ for (auto it = host_view->children().begin();
+ it != host_view->children().end(); ++it) {
+ child_infos_.emplace(*it, ChildInfo{(*it)->GetVisible(), false});
+ }
+}
+
+void LayoutManagerBase::ViewAdded(View* host, View* view) {
+ DCHECK_EQ(host_view_, host);
+ DCHECK(!base::Contains(child_infos_, view));
+ ChildInfo to_add{view->GetVisible(), false};
+ child_infos_.emplace(view, to_add);
+ if (to_add.can_be_visible)
+ InvalidateLayout();
+}
+
+void LayoutManagerBase::ViewRemoved(View* host, View* view) {
+ DCHECK_EQ(host_view_, host);
+ auto it = child_infos_.find(view);
+ DCHECK(it != child_infos_.end());
+ const bool removed_visible = it->second.can_be_visible && !it->second.ignored;
+ child_infos_.erase(it);
+ if (removed_visible)
+ InvalidateLayout();
+}
+
+void LayoutManagerBase::ViewVisibilitySet(View* host,
+ View* view,
+ bool visible) {
+ DCHECK_EQ(host_view_, host);
+ auto it = child_infos_.find(view);
+ DCHECK(it != child_infos_.end());
+ if (it->second.can_be_visible == visible)
+ return;
+
+ it->second.can_be_visible = visible;
+ if (!it->second.ignored)
+ InvalidateLayout();
+}
+
+LayoutManagerBase::LayoutManagerBase() = default;
+
+bool LayoutManagerBase::IsChildIncludedInLayout(const View* child) const {
+ const auto it = child_infos_.find(child);
+ DCHECK(it != child_infos_.end());
+ return !it->second.ignored && it->second.can_be_visible;
+}
+
+void LayoutManagerBase::ApplyLayout(const ProposedLayout& layout) {
+ for (auto& child_layout : layout.child_layouts) {
+ DCHECK_EQ(host_view_, child_layout.child_view->parent());
+
+ // Since we have a non-const reference to the parent here, we can safely use
+ // a non-const reference to the child.
+ View* const child_view = child_layout.child_view;
+ if (child_view->GetVisible() != child_layout.visible)
+ SetViewVisibility(child_view, child_layout.visible);
+ if (child_layout.visible)
+ child_view->SetBoundsRect(child_layout.bounds);
+ }
+}
+
+void LayoutManagerBase::SyncStateTo(LayoutManagerBase* other) const {
+ if (host_view_) {
+ other->Installed(host_view_);
+ for (View* child_view : host_view_->children()) {
+ const ChildInfo& child_info = child_infos_.find(child_view)->second;
+ other->SetChildViewIgnoredByLayout(child_view, child_info.ignored);
+ other->ViewVisibilitySet(host_view_, child_view,
+ child_info.can_be_visible);
+ }
+ }
+}
+
+} // namespace views
diff --git a/chromium/ui/views/layout/layout_manager_base.h b/chromium/ui/views/layout/layout_manager_base.h
new file mode 100644
index 00000000000..5ff97926bc5
--- /dev/null
+++ b/chromium/ui/views/layout/layout_manager_base.h
@@ -0,0 +1,125 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_LAYOUT_LAYOUT_MANAGER_BASE_H_
+#define UI_VIEWS_LAYOUT_LAYOUT_MANAGER_BASE_H_
+
+#include <map>
+#include <memory>
+#include <set>
+#include <utility>
+#include <vector>
+
+#include "base/optional.h"
+#include "ui/gfx/geometry/insets.h"
+#include "ui/gfx/geometry/rect.h"
+#include "ui/gfx/geometry/size.h"
+#include "ui/views/layout/layout_manager.h"
+#include "ui/views/layout/layout_types.h"
+#include "ui/views/views_export.h"
+
+namespace views {
+
+class View;
+
+// Base class for layout managers that can do layout calculation separately
+// from layout application. Derived classes must implement
+// CalculateProposedLayout(). Used in interpolating and animating layouts.
+class VIEWS_EXPORT LayoutManagerBase : public LayoutManager {
+ public:
+ // Represents layout information for a child view within a host being laid
+ // out.
+ struct VIEWS_EXPORT ChildLayout {
+ View* child_view = nullptr;
+ gfx::Rect bounds;
+ bool visible = false;
+ };
+
+ // Contains a full layout specification for the children of the host view.
+ struct VIEWS_EXPORT ProposedLayout {
+ ProposedLayout();
+ ~ProposedLayout();
+ ProposedLayout(const ProposedLayout& other);
+ ProposedLayout(ProposedLayout&& other);
+ ProposedLayout& operator=(const ProposedLayout& other);
+ ProposedLayout& operator=(ProposedLayout&& other);
+
+ // The size of the host view given the size bounds for this layout. If both
+ // dimensions of the size bounds are specified, this will be the same size.
+ gfx::Size host_size;
+
+ // Contains an entry for each child view included in the layout.
+ std::vector<ChildLayout> child_layouts;
+ };
+
+ ~LayoutManagerBase() override;
+
+ View* host_view() { return host_view_; }
+ const View* host_view() const { return host_view_; }
+
+ // Fetches a proposed layout for a host view with size |host_size|. If the
+ // result had already been calculated, a cached value may be returned.
+ ProposedLayout GetProposedLayout(const gfx::Size& host_size) const;
+
+ // Excludes a specific view from the layout when doing layout calculations.
+ // Useful when a child view is meant to be displayed but has its size and
+ // position managed elsewhere in code. By default, all child views are
+ // included in the layout unless they are hidden.
+ virtual void SetChildViewIgnoredByLayout(View* child_view, bool ignored);
+ virtual bool IsChildViewIgnoredByLayout(const View* child_view) const;
+
+ // LayoutManager:
+ gfx::Size GetPreferredSize(const View* host) const override;
+ gfx::Size GetMinimumSize(const View* host) const override;
+ int GetPreferredHeightForWidth(const View* host, int width) const override;
+ void Layout(View* host) override;
+ void InvalidateLayout() override;
+ void Installed(View* host) override;
+ void ViewAdded(View* host, View* view) override;
+ void ViewRemoved(View* host, View* view) override;
+ void ViewVisibilitySet(View* host, View* view, bool visible) override;
+
+ protected:
+ LayoutManagerBase();
+
+ bool IsChildIncludedInLayout(const View* child) const;
+
+ // Creates a proposed layout for the host view, including bounds and
+ // visibility for all children currently included in the layout.
+ virtual ProposedLayout CalculateProposedLayout(
+ const SizeBounds& size_bounds) const = 0;
+
+ // Applies |layout| to the children of the host view.
+ void ApplyLayout(const ProposedLayout& layout);
+
+ // Can be used by derived classes to ensure that state is correctly
+ // transferred to child LayoutManagerBase instances in a composite layout
+ // (interpolating or animating layouts, etc.)
+ void SyncStateTo(LayoutManagerBase* other) const;
+
+ private:
+ // Holds bookkeeping data used to determine inclusion of children in the
+ // layout.
+ struct ChildInfo {
+ bool can_be_visible = true;
+ bool ignored = false;
+ };
+
+ View* host_view_ = nullptr;
+ std::map<const View*, ChildInfo> child_infos_;
+
+ // Do some really simple caching because layout generation can cost as much
+ // as 1ms or more for complex views.
+ mutable base::Optional<gfx::Size> minimum_size_;
+ mutable base::Optional<gfx::Size> preferred_size_;
+ mutable base::Optional<gfx::Size> last_height_for_width_;
+ mutable base::Optional<gfx::Size> last_requested_size_;
+ mutable ProposedLayout last_layout_;
+
+ DISALLOW_COPY_AND_ASSIGN(LayoutManagerBase);
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_LAYOUT_LAYOUT_MANAGER_BASE_H_
diff --git a/chromium/ui/views/layout/layout_manager_base_unittest.cc b/chromium/ui/views/layout/layout_manager_base_unittest.cc
new file mode 100644
index 00000000000..36e39551ad7
--- /dev/null
+++ b/chromium/ui/views/layout/layout_manager_base_unittest.cc
@@ -0,0 +1,479 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/layout/layout_manager_base.h"
+
+#include <algorithm>
+
+#include "testing/gtest/include/gtest/gtest.h"
+#include "ui/views/test/test_layout_manager.h"
+#include "ui/views/test/test_views.h"
+#include "ui/views/view.h"
+
+namespace views {
+
+// Test LayoutManagerBase-specific functionality:
+
+namespace {
+
+constexpr gfx::Size kMinimumSize(40, 50);
+constexpr gfx::Size kPreferredSize(100, 90);
+
+// Dummy class that minimally implements LayoutManagerBase for basic
+// functionality testing.
+class TestLayoutManagerBase : public LayoutManagerBase {
+ public:
+ std::vector<const View*> GetIncludedChildViews() const {
+ std::vector<const View*> included;
+ std::copy_if(host_view()->children().begin(), host_view()->children().end(),
+ std::back_inserter(included), [=](const View* child) {
+ return IsChildIncludedInLayout(child);
+ });
+ return included;
+ }
+
+ // LayoutManagerBase:
+ ProposedLayout CalculateProposedLayout(
+ const SizeBounds& size_bounds) const override {
+ ProposedLayout layout;
+ layout.host_size.set_width(
+ std::max(kMinimumSize.width(),
+ size_bounds.width().value_or(kPreferredSize.width())));
+ layout.host_size.set_height(
+ std::max(kMinimumSize.height(),
+ size_bounds.height().value_or(kPreferredSize.height())));
+ return layout;
+ }
+};
+
+void ExpectSameViews(const std::vector<const View*>& expected,
+ const std::vector<const View*>& actual) {
+ EXPECT_EQ(expected.size(), actual.size());
+ for (size_t i = 0; i < expected.size(); ++i) {
+ EXPECT_EQ(expected[i], actual[i]);
+ }
+}
+
+} // namespace
+
+TEST(LayoutManagerBaseTest, GetMinimumSize) {
+ TestLayoutManagerBase layout;
+ EXPECT_EQ(kMinimumSize, layout.GetMinimumSize(nullptr));
+}
+
+TEST(LayoutManagerBaseTest, GetPreferredSize) {
+ TestLayoutManagerBase layout;
+ EXPECT_EQ(kPreferredSize, layout.GetPreferredSize(nullptr));
+}
+
+TEST(LayoutManagerBaseTest, GetPreferredHeightForWidth) {
+ constexpr int kWidth = 45;
+ TestLayoutManagerBase layout;
+ EXPECT_EQ(kPreferredSize.height(),
+ layout.GetPreferredHeightForWidth(nullptr, kWidth));
+}
+
+TEST(LayoutManagerBaseTest, Installed) {
+ TestLayoutManagerBase layout;
+ EXPECT_EQ(nullptr, layout.host_view());
+
+ View view;
+ layout.Installed(&view);
+ EXPECT_EQ(&view, layout.host_view());
+}
+
+TEST(LayoutManagerBaseTest, SetChildIncludedInLayout) {
+ View view;
+ View* const child1 = view.AddChildView(std::make_unique<View>());
+ View* const child2 = view.AddChildView(std::make_unique<View>());
+ View* const child3 = view.AddChildView(std::make_unique<View>());
+
+ TestLayoutManagerBase layout;
+ layout.Installed(&view);
+
+ // All views should be present.
+ ExpectSameViews({child1, child2, child3}, layout.GetIncludedChildViews());
+
+ // Remove one.
+ layout.SetChildViewIgnoredByLayout(child2, true);
+ ExpectSameViews({child1, child3}, layout.GetIncludedChildViews());
+
+ // Remove another.
+ layout.SetChildViewIgnoredByLayout(child1, true);
+ ExpectSameViews({child3}, layout.GetIncludedChildViews());
+
+ // Removing it again should have no effect.
+ layout.SetChildViewIgnoredByLayout(child1, true);
+ ExpectSameViews({child3}, layout.GetIncludedChildViews());
+
+ // Add one back.
+ layout.SetChildViewIgnoredByLayout(child1, false);
+ ExpectSameViews({child1, child3}, layout.GetIncludedChildViews());
+
+ // Adding it back again should have no effect.
+ layout.SetChildViewIgnoredByLayout(child1, false);
+ ExpectSameViews({child1, child3}, layout.GetIncludedChildViews());
+
+ // Add the other view back.
+ layout.SetChildViewIgnoredByLayout(child2, false);
+ ExpectSameViews({child1, child2, child3}, layout.GetIncludedChildViews());
+}
+
+// Test LayoutManager functionality of LayoutManagerBase:
+
+namespace {
+
+constexpr int kChildViewPadding = 5;
+constexpr gfx::Size kSquarishSize(10, 11);
+constexpr gfx::Size kLongSize(20, 8);
+constexpr gfx::Size kTallSize(4, 22);
+constexpr gfx::Size kLargeSize(30, 28);
+
+// This layout layout lays out included child views in the upper-left of the
+// host view with kChildViewPadding around them. Views that will not fit are
+// made invisible. Child views are expected to overlap as they all have the
+// same top-left corner.
+class MockLayoutManagerBase : public LayoutManagerBase {
+ public:
+ int num_invalidations() const { return num_invalidations_; }
+ int num_layouts_generated() const { return num_layouts_generated_; }
+
+ // LayoutManagerBase:
+ ProposedLayout CalculateProposedLayout(
+ const SizeBounds& size_bounds) const override {
+ ProposedLayout layout;
+ layout.host_size = {kChildViewPadding, kChildViewPadding};
+ for (auto it = host_view()->children().begin();
+ it != host_view()->children().end(); ++it) {
+ if (!IsChildIncludedInLayout(*it))
+ continue;
+ const gfx::Size preferred_size = (*it)->GetPreferredSize();
+ bool visible = false;
+ gfx::Rect bounds;
+ const int required_width = preferred_size.width() + 2 * kChildViewPadding;
+ const int required_height =
+ preferred_size.height() + 2 * kChildViewPadding;
+ if ((!size_bounds.width() || required_width <= *size_bounds.width()) &&
+ (!size_bounds.height() || required_height <= *size_bounds.height())) {
+ visible = true;
+ bounds = gfx::Rect(kChildViewPadding, kChildViewPadding,
+ preferred_size.width(), preferred_size.height());
+ layout.host_size.set_width(std::max(
+ layout.host_size.width(), bounds.right() + kChildViewPadding));
+ layout.host_size.set_height(std::max(
+ layout.host_size.height(), bounds.bottom() + kChildViewPadding));
+ }
+ layout.child_layouts.push_back({*it, bounds, visible});
+ }
+ ++num_layouts_generated_;
+ return layout;
+ }
+
+ void InvalidateLayout() override {
+ LayoutManagerBase::InvalidateLayout();
+ ++num_invalidations_;
+ }
+
+ using LayoutManagerBase::ApplyLayout;
+
+ private:
+ mutable int num_layouts_generated_ = 0;
+ mutable int num_invalidations_ = 0;
+};
+
+// Base for tests that evaluate the LayoutManager functionality of
+// LayoutManagerBase (rather than the LayoutManagerBase-specific behavior).
+class LayoutManagerBaseManagerTest : public testing::Test {
+ public:
+ void SetUp() override {
+ host_view_ = std::make_unique<View>();
+ layout_manager_ =
+ host_view_->SetLayoutManager(std::make_unique<MockLayoutManagerBase>());
+ }
+
+ View* AddChildView(gfx::Size preferred_size) {
+ auto child = std::make_unique<StaticSizedView>(preferred_size);
+ return host_view_->AddChildView(std::move(child));
+ }
+
+ View* host_view() { return host_view_.get(); }
+ MockLayoutManagerBase* layout_manager() { return layout_manager_; }
+ View* child(int index) { return host_view_->children().at(index); }
+
+ private:
+ std::unique_ptr<View> host_view_;
+ MockLayoutManagerBase* layout_manager_;
+};
+
+} // namespace
+
+TEST_F(LayoutManagerBaseManagerTest, ApplyLayout) {
+ AddChildView(gfx::Size());
+ AddChildView(gfx::Size());
+ AddChildView(gfx::Size());
+
+ // We don't want to set the size of the host view because it will trigger a
+ // superfluous layout, so we'll just keep the old size and make sure it
+ // doesn't change.
+ const gfx::Size old_size = host_view()->size();
+
+ LayoutManagerBase::ProposedLayout layout;
+ // This should be ignored.
+ layout.host_size = {123, 456};
+
+ // Set the child visibility and bounds.
+ constexpr gfx::Rect kChild1Bounds(3, 4, 10, 15);
+ constexpr gfx::Rect kChild3Bounds(20, 21, 12, 14);
+ layout.child_layouts.push_back(
+ LayoutManagerBase::ChildLayout{child(0), kChild1Bounds, true});
+ layout.child_layouts.push_back(
+ LayoutManagerBase::ChildLayout{child(1), gfx::Rect(), false});
+ layout.child_layouts.push_back(
+ LayoutManagerBase::ChildLayout{child(2), kChild3Bounds, true});
+
+ layout_manager()->ApplyLayout(layout);
+
+ EXPECT_TRUE(child(0)->GetVisible());
+ EXPECT_EQ(kChild1Bounds, child(0)->bounds());
+ EXPECT_FALSE(child(1)->GetVisible());
+ EXPECT_TRUE(child(2)->GetVisible());
+ EXPECT_EQ(kChild3Bounds, child(2)->bounds());
+ EXPECT_EQ(old_size, host_view()->size());
+}
+
+TEST_F(LayoutManagerBaseManagerTest, ApplyLayout_SkipsOmittedViews) {
+ AddChildView(gfx::Size());
+ AddChildView(gfx::Size());
+ AddChildView(gfx::Size());
+
+ LayoutManagerBase::ProposedLayout layout;
+ // Set the child visibility and bounds.
+ constexpr gfx::Rect kChild1Bounds(3, 4, 10, 15);
+ constexpr gfx::Rect kChild2Bounds(1, 2, 3, 4);
+ layout.child_layouts.push_back(
+ LayoutManagerBase::ChildLayout{child(0), kChild1Bounds, true});
+ layout.child_layouts.push_back(
+ LayoutManagerBase::ChildLayout{child(2), gfx::Rect(), false});
+
+ // We'll set the second child separately.
+ child(1)->SetVisible(true);
+ child(1)->SetBoundsRect(kChild2Bounds);
+
+ layout_manager()->ApplyLayout(layout);
+
+ EXPECT_TRUE(child(0)->GetVisible());
+ EXPECT_EQ(kChild1Bounds, child(0)->bounds());
+ EXPECT_TRUE(child(1)->GetVisible());
+ EXPECT_EQ(kChild2Bounds, child(1)->bounds());
+ EXPECT_FALSE(child(2)->GetVisible());
+}
+
+TEST_F(LayoutManagerBaseManagerTest, Install) {
+ EXPECT_EQ(host_view(), layout_manager()->host_view());
+}
+
+TEST_F(LayoutManagerBaseManagerTest, GetMinimumSize) {
+ AddChildView(kSquarishSize);
+ AddChildView(kLongSize);
+ AddChildView(kTallSize);
+ EXPECT_EQ(gfx::Size(kChildViewPadding, kChildViewPadding),
+ host_view()->GetMinimumSize());
+}
+
+TEST_F(LayoutManagerBaseManagerTest, GetPreferredSize) {
+ AddChildView(kSquarishSize);
+ AddChildView(kLongSize);
+ AddChildView(kTallSize);
+ const gfx::Size expected(kLongSize.width() + 2 * kChildViewPadding,
+ kTallSize.height() + 2 * kChildViewPadding);
+ EXPECT_EQ(expected, host_view()->GetPreferredSize());
+}
+
+TEST_F(LayoutManagerBaseManagerTest, GetPreferredHeightForWidth) {
+ AddChildView(kSquarishSize);
+ AddChildView(kLargeSize);
+ const int expected = kSquarishSize.height() + 2 * kChildViewPadding;
+ EXPECT_EQ(expected,
+ layout_manager()->GetPreferredHeightForWidth(host_view(), 20));
+ EXPECT_EQ(1, layout_manager()->num_layouts_generated());
+ layout_manager()->GetPreferredHeightForWidth(host_view(), 20);
+ EXPECT_EQ(1, layout_manager()->num_layouts_generated());
+ layout_manager()->GetPreferredHeightForWidth(host_view(), 25);
+ EXPECT_EQ(2, layout_manager()->num_layouts_generated());
+}
+
+TEST_F(LayoutManagerBaseManagerTest, InvalidateLayout) {
+ // Some invalidation could have been triggered during setup.
+ const int old_num_invalidations = layout_manager()->num_invalidations();
+
+ host_view()->InvalidateLayout();
+ EXPECT_EQ(old_num_invalidations + 1, layout_manager()->num_invalidations());
+}
+
+TEST_F(LayoutManagerBaseManagerTest, Layout) {
+ constexpr gfx::Point kUpperLeft(kChildViewPadding, kChildViewPadding);
+ AddChildView(kSquarishSize);
+ AddChildView(kLongSize);
+ AddChildView(kTallSize);
+
+ // This should fit all of the child views and trigger layout.
+ host_view()->SetSize({40, 40});
+ EXPECT_EQ(1, layout_manager()->num_layouts_generated());
+ EXPECT_EQ(gfx::Rect(kUpperLeft, child(0)->GetPreferredSize()),
+ child(0)->bounds());
+ EXPECT_TRUE(child(0)->GetVisible());
+ EXPECT_EQ(gfx::Rect(kUpperLeft, child(1)->GetPreferredSize()),
+ child(1)->bounds());
+ EXPECT_TRUE(child(1)->GetVisible());
+ EXPECT_EQ(gfx::Rect(kUpperLeft, child(2)->GetPreferredSize()),
+ child(2)->bounds());
+ EXPECT_TRUE(child(2)->GetVisible());
+
+ // This should drop out some children.
+ host_view()->SetSize({25, 25});
+ EXPECT_EQ(2, layout_manager()->num_layouts_generated());
+ EXPECT_EQ(gfx::Rect(kUpperLeft, child(0)->GetPreferredSize()),
+ child(0)->bounds());
+ EXPECT_TRUE(child(0)->GetVisible());
+ EXPECT_FALSE(child(1)->GetVisible());
+ EXPECT_FALSE(child(2)->GetVisible());
+}
+
+TEST_F(LayoutManagerBaseManagerTest, ChildViewIgnoredByLayout) {
+ AddChildView(kSquarishSize);
+ AddChildView(kLongSize);
+ AddChildView(kTallSize);
+
+ EXPECT_FALSE(layout_manager()->IsChildViewIgnoredByLayout(child(0)));
+ EXPECT_FALSE(layout_manager()->IsChildViewIgnoredByLayout(child(1)));
+ EXPECT_FALSE(layout_manager()->IsChildViewIgnoredByLayout(child(2)));
+
+ layout_manager()->SetChildViewIgnoredByLayout(child(1), true);
+
+ EXPECT_FALSE(layout_manager()->IsChildViewIgnoredByLayout(child(0)));
+ EXPECT_TRUE(layout_manager()->IsChildViewIgnoredByLayout(child(1)));
+ EXPECT_FALSE(layout_manager()->IsChildViewIgnoredByLayout(child(2)));
+}
+
+TEST_F(LayoutManagerBaseManagerTest,
+ ChildViewIgnoredByLayout_IgnoresChildView) {
+ AddChildView(kSquarishSize);
+ AddChildView(kLongSize);
+ AddChildView(kTallSize);
+
+ layout_manager()->SetChildViewIgnoredByLayout(child(1), true);
+
+ child(1)->SetSize(kLargeSize);
+
+ // Makes enough room for all views, and triggers layout.
+ host_view()->SetSize({50, 50});
+
+ EXPECT_EQ(child(0)->GetPreferredSize(), child(0)->size());
+ EXPECT_EQ(kLargeSize, child(1)->size());
+ EXPECT_EQ(child(2)->GetPreferredSize(), child(2)->size());
+}
+
+TEST_F(LayoutManagerBaseManagerTest, ViewVisibilitySet) {
+ AddChildView(kSquarishSize);
+ AddChildView(kLongSize);
+ AddChildView(kTallSize);
+
+ child(1)->SetVisible(false);
+
+ // Makes enough room for all views, and triggers layout.
+ host_view()->SetSize({50, 50});
+
+ EXPECT_TRUE(child(0)->GetVisible());
+ EXPECT_EQ(child(0)->GetPreferredSize(), child(0)->size());
+ EXPECT_FALSE(child(1)->GetVisible());
+ EXPECT_TRUE(child(2)->GetVisible());
+ EXPECT_EQ(child(2)->GetPreferredSize(), child(2)->size());
+
+ // Turn the second child view back on and verify it's present in the layout
+ // again.
+ child(1)->SetVisible(true);
+ host_view()->Layout();
+
+ EXPECT_TRUE(child(0)->GetVisible());
+ EXPECT_EQ(child(0)->GetPreferredSize(), child(0)->size());
+ EXPECT_TRUE(child(1)->GetVisible());
+ EXPECT_EQ(child(1)->GetPreferredSize(), child(1)->size());
+ EXPECT_TRUE(child(2)->GetVisible());
+ EXPECT_EQ(child(2)->GetPreferredSize(), child(2)->size());
+}
+
+TEST_F(LayoutManagerBaseManagerTest, ViewAdded) {
+ AddChildView(kLongSize);
+ AddChildView(kTallSize);
+
+ // Makes enough room for all views, and triggers layout.
+ host_view()->SetSize({50, 50});
+
+ EXPECT_TRUE(child(0)->GetVisible());
+ EXPECT_EQ(child(0)->GetPreferredSize(), child(0)->size());
+ EXPECT_TRUE(child(1)->GetVisible());
+ EXPECT_EQ(child(1)->GetPreferredSize(), child(1)->size());
+
+ // Add a new view and verify it is being laid out.
+ View* new_view = AddChildView(kSquarishSize);
+ host_view()->Layout();
+
+ EXPECT_TRUE(new_view->GetVisible());
+ EXPECT_EQ(new_view->GetPreferredSize(), new_view->size());
+}
+
+TEST_F(LayoutManagerBaseManagerTest, ViewAdded_NotVisible) {
+ AddChildView(kLongSize);
+ AddChildView(kTallSize);
+
+ // Makes enough room for all views, and triggers layout.
+ host_view()->SetSize({50, 50});
+
+ EXPECT_TRUE(child(0)->GetVisible());
+ EXPECT_EQ(child(0)->GetPreferredSize(), child(0)->size());
+ EXPECT_TRUE(child(1)->GetVisible());
+ EXPECT_EQ(child(1)->GetPreferredSize(), child(1)->size());
+
+ // Add a new view that is not visible and ensure that the layout manager
+ // doesn't touch it during layout.
+ View* new_view = new StaticSizedView(kSquarishSize);
+ new_view->SetVisible(false);
+ host_view()->AddChildView(new_view);
+ host_view()->Layout();
+
+ EXPECT_FALSE(new_view->GetVisible());
+}
+
+TEST_F(LayoutManagerBaseManagerTest, ViewRemoved) {
+ AddChildView(kSquarishSize);
+ View* const child_view = AddChildView(kLongSize);
+ AddChildView(kTallSize);
+
+ // Makes enough room for all views, and triggers layout.
+ host_view()->SetSize({50, 50});
+
+ EXPECT_TRUE(child(0)->GetVisible());
+ EXPECT_EQ(child(0)->GetPreferredSize(), child(0)->size());
+ EXPECT_TRUE(child(1)->GetVisible());
+ EXPECT_EQ(child(1)->GetPreferredSize(), child(1)->size());
+ EXPECT_TRUE(child(2)->GetVisible());
+ EXPECT_EQ(child(2)->GetPreferredSize(), child(2)->size());
+
+ host_view()->RemoveChildView(child_view);
+ child_view->SetSize(kLargeSize);
+ host_view()->Layout();
+
+ EXPECT_TRUE(child(0)->GetVisible());
+ EXPECT_EQ(child(0)->GetPreferredSize(), child(0)->size());
+ EXPECT_TRUE(child(1)->GetVisible());
+ EXPECT_EQ(child(1)->GetPreferredSize(), child(1)->size());
+
+ EXPECT_TRUE(child_view->GetVisible());
+ EXPECT_EQ(kLargeSize, child_view->size());
+
+ // Required since we removed it from the parent view.
+ delete child_view;
+}
+
+} // namespace views
diff --git a/chromium/ui/views/layout/layout_types.cc b/chromium/ui/views/layout/layout_types.cc
new file mode 100644
index 00000000000..67e4a776b04
--- /dev/null
+++ b/chromium/ui/views/layout/layout_types.cc
@@ -0,0 +1,62 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#include "ui/views/layout/layout_types.h"
+
+#include <algorithm>
+
+#include "base/strings/stringprintf.h"
+#include "ui/gfx/geometry/size.h"
+
+namespace views {
+
+namespace {
+
+std::string OptionalToString(const base::Optional<int>& opt) {
+ if (!opt.has_value())
+ return "_";
+ return base::StringPrintf("%d", opt.value());
+}
+
+} // namespace
+
+// SizeBounds ------------------------------------------------------------------
+
+SizeBounds::SizeBounds() = default;
+
+SizeBounds::SizeBounds(const base::Optional<int>& width,
+ const base::Optional<int>& height)
+ : width_(width), height_(height) {}
+
+SizeBounds::SizeBounds(const SizeBounds& other)
+ : width_(other.width()), height_(other.height()) {}
+
+SizeBounds::SizeBounds(const gfx::Size& other)
+ : width_(other.width()), height_(other.height()) {}
+
+void SizeBounds::Enlarge(int width, int height) {
+ if (width_)
+ width_ = std::max(0, *width_ + width);
+ if (height_)
+ height_ = std::max(0, *height_ + height);
+}
+
+bool SizeBounds::operator==(const SizeBounds& other) const {
+ return width_ == other.width_ && height_ == other.height_;
+}
+
+bool SizeBounds::operator!=(const SizeBounds& other) const {
+ return !(*this == other);
+}
+
+bool SizeBounds::operator<(const SizeBounds& other) const {
+ return std::tie(height_, width_) < std::tie(other.height_, other.width_);
+}
+
+std::string SizeBounds::ToString() const {
+ return base::StringPrintf("%s x %s", OptionalToString(width()).c_str(),
+ OptionalToString(height()).c_str());
+}
+
+} // namespace views
diff --git a/chromium/ui/views/layout/layout_types.h b/chromium/ui/views/layout/layout_types.h
new file mode 100644
index 00000000000..24b3383f530
--- /dev/null
+++ b/chromium/ui/views/layout/layout_types.h
@@ -0,0 +1,58 @@
+// Copyright 2019 The Chromium Authors. All rights reserved.
+// Use of this source code is governed by a BSD-style license that can be
+// found in the LICENSE file.
+
+#ifndef UI_VIEWS_LAYOUT_LAYOUT_TYPES_H_
+#define UI_VIEWS_LAYOUT_LAYOUT_TYPES_H_
+
+#include <string>
+
+#include "base/optional.h"
+#include "ui/views/views_export.h"
+
+namespace gfx {
+class Size;
+} // namespace gfx
+
+namespace views {
+
+// Whether a layout is oriented horizontally or vertically.
+enum class LayoutOrientation {
+ kHorizontal,
+ kVertical,
+};
+
+// Stores an optional width and height upper bound. Used when calculating the
+// preferred size of a layout pursuant to a maximum available size.
+class VIEWS_EXPORT SizeBounds {
+ public:
+ SizeBounds();
+ SizeBounds(const base::Optional<int>& width,
+ const base::Optional<int>& height);
+ explicit SizeBounds(const gfx::Size& size);
+ SizeBounds(const SizeBounds& other);
+
+ const base::Optional<int>& width() const { return width_; }
+ void set_width(const base::Optional<int>& width) { width_ = width; }
+
+ const base::Optional<int>& height() const { return height_; }
+ void set_height(const base::Optional<int>& height) { height_ = height; }
+
+ // Enlarges (or shrinks, if negative) each upper bound that is present by the
+ // specified amounts.
+ void Enlarge(int width, int height);
+
+ bool operator==(const SizeBounds& other) const;
+ bool operator!=(const SizeBounds& other) const;
+ bool operator<(const SizeBounds& other) const;
+
+ std::string ToString() const;
+
+ private:
+ base::Optional<int> width_;
+ base::Optional<int> height_;
+};
+
+} // namespace views
+
+#endif // UI_VIEWS_LAYOUT_LAYOUT_TYPES_H_
diff --git a/chromium/ui/views/linux_ui/status_icon_linux.cc b/chromium/ui/views/linux_ui/status_icon_linux.cc
index c3d1ce17864..e861e15761a 100644
--- a/chromium/ui/views/linux_ui/status_icon_linux.cc
+++ b/chromium/ui/views/linux_ui/status_icon_linux.cc
@@ -12,7 +12,13 @@ StatusIconLinux::StatusIconLinux() = default;
StatusIconLinux::~StatusIconLinux() = default;
-void StatusIconLinux::RefreshPlatformContextMenu() {
+void StatusIconLinux::RefreshPlatformContextMenu() {}
+
+void StatusIconLinux::OnSetDelegate() {}
+
+void StatusIconLinux::SetDelegate(Delegate* delegate) {
+ delegate_ = delegate;
+ OnSetDelegate();
}
} // namespace views
diff --git a/chromium/ui/views/linux_ui/status_icon_linux.h b/chromium/ui/views/linux_ui/status_icon_linux.h
index a6132695cbd..6bfa71ac022 100644
--- a/chromium/ui/views/linux_ui/status_icon_linux.h
+++ b/chromium/ui/views/linux_ui/status_icon_linux.h
@@ -29,6 +29,13 @@ class VIEWS_EXPORT StatusIconLinux {
virtual void OnClick() = 0;
virtual bool HasClickAction() = 0;
+ virtual const gfx::ImageSkia& GetImage() const = 0;
+ virtual const base::string16& GetToolTip() const = 0;
+ virtual ui::MenuModel* GetMenuModel() const = 0;
+
+ // This should be called at most once by the implementation.
+ virtual void OnImplInitializationFailed() = 0;
+
protected:
virtual ~Delegate();
};
@@ -36,7 +43,7 @@ class VIEWS_EXPORT StatusIconLinux {
StatusIconLinux();
virtual ~StatusIconLinux();
- virtual void SetImage(const gfx::ImageSkia& image) = 0;
+ virtual void SetIcon(const gfx::ImageSkia& image) = 0;
virtual void SetToolTip(const base::string16& tool_tip) = 0;
// Invoked after a call to SetContextMenu() to let the platform-specific
@@ -49,10 +56,13 @@ class VIEWS_EXPORT StatusIconLinux {
// need to manually refresh it when the menu model changes.
virtual void RefreshPlatformContextMenu();
+ virtual void OnSetDelegate();
+
+ void SetDelegate(Delegate* delegate);
+
Delegate* delegate() { return delegate_; }
- void set_delegate(Delegate* delegate) { delegate_ = delegate; }
- private:
+ protected:
Delegate* delegate_ = nullptr;
};
diff --git a/chromium/ui/views/metadata/metadata_header_macros.h b/chromium/ui/views/metadata/metadata_header_macros.h
index 532c01ad42c..c10bc2c2d83 100644
--- a/chromium/ui/views/metadata/metadata_header_macros.h
+++ b/chromium/ui/views/metadata/metadata_header_macros.h
@@ -13,4 +13,10 @@
METADATA_ACCESSORS_INTERNAL(class_name) \
METADATA_CLASS_INTERNAL(class_name)
+// A version of METADATA_HEADER for View, the root of the metadata hierarchy.
+// Here METADATA_ACCESSORS_INTERNAL_BASE is called.
+#define METADATA_HEADER_BASE(class_name) \
+ METADATA_ACCESSORS_INTERNAL_BASE(class_name) \
+ METADATA_CLASS_INTERNAL(class_name)
+
#endif // UI_VIEWS_METADATA_METADATA_HEADER_MACROS_H_
diff --git a/chromium/ui/views/metadata/metadata_impl_macros.h b/chromium/ui/views/metadata/metadata_impl_macros.h
index 215750e3e5a..2eedd00f50e 100644
--- a/chromium/ui/views/metadata/metadata_impl_macros.h
+++ b/chromium/ui/views/metadata/metadata_impl_macros.h
@@ -11,6 +11,7 @@
// Generate the implementation of the metadata accessors and internal class with
// additional macros for defining the class' properties.
+
#define BEGIN_METADATA(class_name) \
views::metadata::ClassMetaData* class_name::METADATA_CLASS_NAME_INTERNAL( \
class_name)::meta_data_ = nullptr; \
@@ -27,6 +28,11 @@
return MetaData(); \
} \
\
+ const char* class_name::GetClassName() const { \
+ return class_name::kViewClassName; \
+ } \
+ const char class_name::kViewClassName[] = #class_name; \
+ \
void METADATA_FUNCTION_PREFIX_INTERNAL(class_name)::BuildMetaData() { \
SetTypeName(std::string(#class_name));
diff --git a/chromium/ui/views/metadata/metadata_macros_internal.h b/chromium/ui/views/metadata/metadata_macros_internal.h
index d29da827175..6f283f956d7 100644
--- a/chromium/ui/views/metadata/metadata_macros_internal.h
+++ b/chromium/ui/views/metadata/metadata_macros_internal.h
@@ -18,6 +18,16 @@
// Metadata Accessors ---------------------------------------------------------
#define METADATA_ACCESSORS_INTERNAL(class_name) \
+ static const char kViewClassName[]; \
+ const char* GetClassName() const override; \
+ static views::metadata::ClassMetaData* MetaData(); \
+ views::metadata::ClassMetaData* GetClassMetaData() override;
+
+// A version of METADATA_ACCESSORS_INTERNAL for View, the root of the metadata
+// hierarchy; here GetClassName() is not declared as an override.
+#define METADATA_ACCESSORS_INTERNAL_BASE(class_name) \
+ static const char kViewClassName[]; \
+ virtual const char* GetClassName() const; \
static views::metadata::ClassMetaData* MetaData(); \
views::metadata::ClassMetaData* GetClassMetaData() override;
diff --git a/chromium/ui/views/metadata/metadata_types.cc b/chromium/ui/views/metadata/metadata_types.cc
index 7a900603427..34cbd933a7a 100644
--- a/chromium/ui/views/metadata/metadata_types.cc
+++ b/chromium/ui/views/metadata/metadata_types.cc
@@ -40,10 +40,22 @@ ClassMetaData::ClassMemberIterator::ClassMemberIterator(
}
ClassMetaData::ClassMemberIterator::~ClassMemberIterator() = default;
+// If starting_container's members vector is empty, set current_collection_
+// to its parent until parent class has members. Base parent class View
+// will always have members, even if all other parent classes do not.
ClassMetaData::ClassMemberIterator::ClassMemberIterator(
ClassMetaData* starting_container) {
current_collection_ = starting_container;
- current_vector_index_ = (current_collection_ ? 0 : SIZE_MAX);
+ if (!current_collection_) {
+ current_vector_index_ = SIZE_MAX;
+ } else if (current_collection_->members().size() == 0) {
+ do {
+ current_collection_ = current_collection_->parent_class_meta_data();
+ } while (current_collection_ && current_collection_->members().empty());
+ current_vector_index_ = (current_collection_ ? 0 : SIZE_MAX);
+ } else {
+ current_vector_index_ = 0;
+ }
}
bool ClassMetaData::ClassMemberIterator::operator==(
@@ -65,6 +77,15 @@ operator++(int) {
return tmp;
}
+bool ClassMetaData::ClassMemberIterator::IsLastMember() const {
+ return current_vector_index_ == current_collection_->members().size() - 1;
+}
+
+std::string ClassMetaData::ClassMemberIterator::GetCurrentCollectionName()
+ const {
+ return current_collection_->type_name();
+}
+
void ClassMetaData::ClassMemberIterator::IncrementHelper() {
DCHECK_LT(current_vector_index_, SIZE_MAX);
++current_vector_index_;
diff --git a/chromium/ui/views/metadata/metadata_types.h b/chromium/ui/views/metadata/metadata_types.h
index bdf4fa08c8e..90cf1324808 100644
--- a/chromium/ui/views/metadata/metadata_types.h
+++ b/chromium/ui/views/metadata/metadata_types.h
@@ -90,6 +90,12 @@ class VIEWS_EXPORT ClassMetaData {
return current_collection_->members()[current_vector_index_];
}
+ // Returns true if iterator currently on last member for that current
+ // collection.
+ bool IsLastMember() const;
+
+ std::string GetCurrentCollectionName() const;
+
private:
friend class ClassMetaData;
explicit ClassMemberIterator(ClassMetaData* starting_container);
diff --git a/chromium/ui/views/metadata/metadata_unittest.cc b/chromium/ui/views/metadata/metadata_unittest.cc
index 73529c1fe9c..8fad27f3adf 100644
--- a/chromium/ui/views/metadata/metadata_unittest.cc
+++ b/chromium/ui/views/metadata/metadata_unittest.cc
@@ -109,7 +109,6 @@ TEST_F(MetadataTest, TestFloatMetadataPropertyAccess) {
GetMemberMetaData(&test_obj, "FloatProperty");
ASSERT_TRUE(member_data);
-
base::string16 member_value = member_data->GetValueAsString(&test_obj);
CHECK_EQ(member_value, base::NumberToString16(start_value));
}
diff --git a/chromium/ui/views/mouse_watcher.cc b/chromium/ui/views/mouse_watcher.cc
index 9cc403da342..c13daf49a08 100644
--- a/chromium/ui/views/mouse_watcher.cc
+++ b/chromium/ui/views/mouse_watcher.cc
@@ -27,7 +27,7 @@ constexpr int kNotifyListenerTimeMs = 300;
class MouseWatcher::Observer : public ui::EventObserver {
public:
Observer(MouseWatcher* mouse_watcher, gfx::NativeWindow window)
- : mouse_watcher_(mouse_watcher), notify_listener_factory_(this) {
+ : mouse_watcher_(mouse_watcher) {
event_monitor_ = EventMonitor::CreateApplicationMonitor(
this, window,
{ui::ET_MOUSE_PRESSED, ui::ET_MOUSE_MOVED, ui::ET_MOUSE_EXITED,
@@ -92,7 +92,7 @@ class MouseWatcher::Observer : public ui::EventObserver {
std::unique_ptr<views::EventMonitor> event_monitor_;
// A factory that is used to construct a delayed callback to the listener.
- base::WeakPtrFactory<Observer> notify_listener_factory_;
+ base::WeakPtrFactory<Observer> notify_listener_factory_{this};
DISALLOW_COPY_AND_ASSIGN(Observer);
};
diff --git a/chromium/ui/views/resources/default_100_percent/common/blue_button.png b/chromium/ui/views/resources/default_100_percent/common/blue_button.png
deleted file mode 100644
index ada819b1f6d..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/blue_button.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/blue_button_focused.png b/chromium/ui/views/resources/default_100_percent/common/blue_button_focused.png
deleted file mode 100644
index efbf1518fd9..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/blue_button_focused.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/blue_button_focused_hover.png b/chromium/ui/views/resources/default_100_percent/common/blue_button_focused_hover.png
deleted file mode 100644
index e3ead548f45..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/blue_button_focused_hover.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/blue_button_focused_pressed.png b/chromium/ui/views/resources/default_100_percent/common/blue_button_focused_pressed.png
deleted file mode 100644
index 83a08848f19..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/blue_button_focused_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/blue_button_hover.png b/chromium/ui/views/resources/default_100_percent/common/blue_button_hover.png
deleted file mode 100644
index 99a23d24e2b..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/blue_button_hover.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/blue_button_inactive.png b/chromium/ui/views/resources/default_100_percent/common/blue_button_inactive.png
deleted file mode 100644
index 4f4e1ae9df0..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/blue_button_inactive.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/blue_button_pressed.png b/chromium/ui/views/resources/default_100_percent/common/blue_button_pressed.png
deleted file mode 100644
index 0ab01706bdf..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/blue_button_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/button.png b/chromium/ui/views/resources/default_100_percent/common/button.png
deleted file mode 100644
index 698c17bb600..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/button.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/button_focused.png b/chromium/ui/views/resources/default_100_percent/common/button_focused.png
deleted file mode 100644
index e77fe42efb7..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/button_focused.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/button_focused_hover.png b/chromium/ui/views/resources/default_100_percent/common/button_focused_hover.png
deleted file mode 100644
index ec427d09307..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/button_focused_hover.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/button_focused_pressed.png b/chromium/ui/views/resources/default_100_percent/common/button_focused_pressed.png
deleted file mode 100644
index fcbd008f985..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/button_focused_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/button_hover.png b/chromium/ui/views/resources/default_100_percent/common/button_hover.png
deleted file mode 100644
index 91905b3b622..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/button_hover.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/button_inactive.png b/chromium/ui/views/resources/default_100_percent/common/button_inactive.png
deleted file mode 100644
index 0748403983f..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/button_inactive.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/button_pressed.png b/chromium/ui/views/resources/default_100_percent/common/button_pressed.png
deleted file mode 100644
index 6610da3a9e2..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/button_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/checkbox.png b/chromium/ui/views/resources/default_100_percent/common/checkbox.png
deleted file mode 100644
index b61b33b6fae..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/checkbox.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/checkbox_checked.png b/chromium/ui/views/resources/default_100_percent/common/checkbox_checked.png
deleted file mode 100644
index 332e980e414..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/checkbox_checked.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/checkbox_checked_hover.png b/chromium/ui/views/resources/default_100_percent/common/checkbox_checked_hover.png
deleted file mode 100644
index eac00a2d07d..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/checkbox_checked_hover.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/checkbox_checked_inactive.png b/chromium/ui/views/resources/default_100_percent/common/checkbox_checked_inactive.png
deleted file mode 100644
index 1512c305aa1..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/checkbox_checked_inactive.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/checkbox_checked_pressed.png b/chromium/ui/views/resources/default_100_percent/common/checkbox_checked_pressed.png
deleted file mode 100644
index 36338ba6c12..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/checkbox_checked_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/checkbox_focused.png b/chromium/ui/views/resources/default_100_percent/common/checkbox_focused.png
deleted file mode 100644
index 90d87598ec3..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/checkbox_focused.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/checkbox_focused_checked.png b/chromium/ui/views/resources/default_100_percent/common/checkbox_focused_checked.png
deleted file mode 100644
index 0ba79b5b396..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/checkbox_focused_checked.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/checkbox_focused_checked_hover.png b/chromium/ui/views/resources/default_100_percent/common/checkbox_focused_checked_hover.png
deleted file mode 100644
index 97d13b7c5c3..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/checkbox_focused_checked_hover.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/checkbox_focused_checked_pressed.png b/chromium/ui/views/resources/default_100_percent/common/checkbox_focused_checked_pressed.png
deleted file mode 100644
index a1e335c58f2..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/checkbox_focused_checked_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/checkbox_focused_hover.png b/chromium/ui/views/resources/default_100_percent/common/checkbox_focused_hover.png
deleted file mode 100644
index dc935b18c58..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/checkbox_focused_hover.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/checkbox_focused_pressed.png b/chromium/ui/views/resources/default_100_percent/common/checkbox_focused_pressed.png
deleted file mode 100644
index 83cd62fe605..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/checkbox_focused_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/checkbox_hover.png b/chromium/ui/views/resources/default_100_percent/common/checkbox_hover.png
deleted file mode 100644
index 9a5db8485d7..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/checkbox_hover.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/checkbox_inactive.png b/chromium/ui/views/resources/default_100_percent/common/checkbox_inactive.png
deleted file mode 100644
index 4d964ee523c..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/checkbox_inactive.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/checkbox_pressed.png b/chromium/ui/views/resources/default_100_percent/common/checkbox_pressed.png
deleted file mode 100644
index 3a1cba338f3..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/checkbox_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/folder_open.png b/chromium/ui/views/resources/default_100_percent/common/folder_open.png
deleted file mode 100644
index a4a9922b765..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/folder_open.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_100_percent/common/folder_open_rtl.png b/chromium/ui/views/resources/default_100_percent/common/folder_open_rtl.png
deleted file mode 100644
index 40b4c665d84..00000000000
--- a/chromium/ui/views/resources/default_100_percent/common/folder_open_rtl.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/blue_button.png b/chromium/ui/views/resources/default_200_percent/common/blue_button.png
deleted file mode 100644
index 9798989d328..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/blue_button.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/blue_button_focused.png b/chromium/ui/views/resources/default_200_percent/common/blue_button_focused.png
deleted file mode 100644
index e0a65b76d4b..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/blue_button_focused.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/blue_button_focused_hover.png b/chromium/ui/views/resources/default_200_percent/common/blue_button_focused_hover.png
deleted file mode 100644
index 5516ba92265..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/blue_button_focused_hover.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/blue_button_focused_pressed.png b/chromium/ui/views/resources/default_200_percent/common/blue_button_focused_pressed.png
deleted file mode 100644
index 7e1ad4c35a6..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/blue_button_focused_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/blue_button_hover.png b/chromium/ui/views/resources/default_200_percent/common/blue_button_hover.png
deleted file mode 100644
index f725d4ec79f..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/blue_button_hover.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/blue_button_inactive.png b/chromium/ui/views/resources/default_200_percent/common/blue_button_inactive.png
deleted file mode 100644
index 63065b8f9a7..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/blue_button_inactive.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/blue_button_pressed.png b/chromium/ui/views/resources/default_200_percent/common/blue_button_pressed.png
deleted file mode 100644
index 8d54141b31e..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/blue_button_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/button.png b/chromium/ui/views/resources/default_200_percent/common/button.png
deleted file mode 100644
index 9845946c0f1..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/button.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/button_focused.png b/chromium/ui/views/resources/default_200_percent/common/button_focused.png
deleted file mode 100644
index 72089d7edcd..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/button_focused.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/button_focused_hover.png b/chromium/ui/views/resources/default_200_percent/common/button_focused_hover.png
deleted file mode 100644
index 7b4f421074c..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/button_focused_hover.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/button_focused_pressed.png b/chromium/ui/views/resources/default_200_percent/common/button_focused_pressed.png
deleted file mode 100644
index c5e258b132b..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/button_focused_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/button_hover.png b/chromium/ui/views/resources/default_200_percent/common/button_hover.png
deleted file mode 100644
index 81aa8ff7e67..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/button_hover.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/button_inactive.png b/chromium/ui/views/resources/default_200_percent/common/button_inactive.png
deleted file mode 100644
index 34cb7827922..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/button_inactive.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/button_pressed.png b/chromium/ui/views/resources/default_200_percent/common/button_pressed.png
deleted file mode 100644
index 3353d8c1807..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/button_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/checkbox.png b/chromium/ui/views/resources/default_200_percent/common/checkbox.png
deleted file mode 100644
index 2192a7f7dcf..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/checkbox.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/checkbox_checked.png b/chromium/ui/views/resources/default_200_percent/common/checkbox_checked.png
deleted file mode 100644
index 1d66001c440..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/checkbox_checked.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/checkbox_checked_hover.png b/chromium/ui/views/resources/default_200_percent/common/checkbox_checked_hover.png
deleted file mode 100644
index c88df15b35d..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/checkbox_checked_hover.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/checkbox_checked_inactive.png b/chromium/ui/views/resources/default_200_percent/common/checkbox_checked_inactive.png
deleted file mode 100644
index 85c314fd934..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/checkbox_checked_inactive.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/checkbox_checked_pressed.png b/chromium/ui/views/resources/default_200_percent/common/checkbox_checked_pressed.png
deleted file mode 100644
index 00a7bf4cb31..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/checkbox_checked_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/checkbox_focused.png b/chromium/ui/views/resources/default_200_percent/common/checkbox_focused.png
deleted file mode 100644
index c4d04aaf531..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/checkbox_focused.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/checkbox_focused_checked.png b/chromium/ui/views/resources/default_200_percent/common/checkbox_focused_checked.png
deleted file mode 100644
index 91152f2adb0..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/checkbox_focused_checked.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/checkbox_focused_checked_hover.png b/chromium/ui/views/resources/default_200_percent/common/checkbox_focused_checked_hover.png
deleted file mode 100644
index 0b5130506e9..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/checkbox_focused_checked_hover.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/checkbox_focused_checked_pressed.png b/chromium/ui/views/resources/default_200_percent/common/checkbox_focused_checked_pressed.png
deleted file mode 100644
index 2a529005b72..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/checkbox_focused_checked_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/checkbox_focused_hover.png b/chromium/ui/views/resources/default_200_percent/common/checkbox_focused_hover.png
deleted file mode 100644
index 91ec9f8aea8..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/checkbox_focused_hover.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/checkbox_focused_pressed.png b/chromium/ui/views/resources/default_200_percent/common/checkbox_focused_pressed.png
deleted file mode 100644
index f22c98e948b..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/checkbox_focused_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/checkbox_hover.png b/chromium/ui/views/resources/default_200_percent/common/checkbox_hover.png
deleted file mode 100644
index 610d864aa0b..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/checkbox_hover.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/checkbox_inactive.png b/chromium/ui/views/resources/default_200_percent/common/checkbox_inactive.png
deleted file mode 100644
index 4b6933c7a9f..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/checkbox_inactive.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/checkbox_pressed.png b/chromium/ui/views/resources/default_200_percent/common/checkbox_pressed.png
deleted file mode 100644
index 0e23c5a77a7..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/checkbox_pressed.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/folder_open.png b/chromium/ui/views/resources/default_200_percent/common/folder_open.png
deleted file mode 100644
index 76938cab788..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/folder_open.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/default_200_percent/common/folder_open_rtl.png b/chromium/ui/views/resources/default_200_percent/common/folder_open_rtl.png
deleted file mode 100644
index 2d285a35a60..00000000000
--- a/chromium/ui/views/resources/default_200_percent/common/folder_open_rtl.png
+++ /dev/null
Binary files differ
diff --git a/chromium/ui/views/resources/views_resources.grd b/chromium/ui/views/resources/views_resources.grd
index dbd023deaf3..f1429ef2c27 100644
--- a/chromium/ui/views/resources/views_resources.grd
+++ b/chromium/ui/views/resources/views_resources.grd
@@ -15,27 +15,6 @@
<structure type="chrome_scaled_image" name="IDR_APP_TOP_CENTER" file="app_top_center.png" />
<structure type="chrome_scaled_image" name="IDR_APP_TOP_LEFT" file="app_top_left.png" />
<structure type="chrome_scaled_image" name="IDR_APP_TOP_RIGHT" file="app_top_right.png" />
- <structure type="chrome_scaled_image" name="IDR_BUTTON_DISABLED" file="common/button_inactive.png" />
- <structure type="chrome_scaled_image" name="IDR_BUTTON_FOCUSED_HOVER" file="common/button_focused_hover.png" />
- <structure type="chrome_scaled_image" name="IDR_BUTTON_FOCUSED_NORMAL" file="common/button_focused.png" />
- <structure type="chrome_scaled_image" name="IDR_BUTTON_FOCUSED_PRESSED" file="common/button_focused_pressed.png" />
- <structure type="chrome_scaled_image" name="IDR_BUTTON_HOVER" file="common/button_hover.png" />
- <structure type="chrome_scaled_image" name="IDR_BUTTON_NORMAL" file="common/button.png" />
- <structure type="chrome_scaled_image" name="IDR_BUTTON_PRESSED" file="common/button_pressed.png" />
- <structure type="chrome_scaled_image" name="IDR_CHECKBOX" file="common/checkbox.png" />
- <structure type="chrome_scaled_image" name="IDR_CHECKBOX_CHECKED" file="common/checkbox_checked.png" />
- <structure type="chrome_scaled_image" name="IDR_CHECKBOX_CHECKED_DISABLED" file="common/checkbox_checked_inactive.png" />
- <structure type="chrome_scaled_image" name="IDR_CHECKBOX_CHECKED_HOVER" file="common/checkbox_checked_hover.png" />
- <structure type="chrome_scaled_image" name="IDR_CHECKBOX_CHECKED_PRESSED" file="common/checkbox_checked_pressed.png" />
- <structure type="chrome_scaled_image" name="IDR_CHECKBOX_DISABLED" file="common/checkbox_inactive.png" />
- <structure type="chrome_scaled_image" name="IDR_CHECKBOX_FOCUSED" file="common/checkbox_focused.png" />
- <structure type="chrome_scaled_image" name="IDR_CHECKBOX_FOCUSED_CHECKED" file="common/checkbox_focused_checked.png" />
- <structure type="chrome_scaled_image" name="IDR_CHECKBOX_FOCUSED_CHECKED_HOVER" file="common/checkbox_focused_checked_hover.png" />
- <structure type="chrome_scaled_image" name="IDR_CHECKBOX_FOCUSED_CHECKED_PRESSED" file="common/checkbox_focused_checked_pressed.png" />
- <structure type="chrome_scaled_image" name="IDR_CHECKBOX_FOCUSED_HOVER" file="common/checkbox_focused_hover.png" />
- <structure type="chrome_scaled_image" name="IDR_CHECKBOX_FOCUSED_PRESSED" file="common/checkbox_focused_pressed.png" />
- <structure type="chrome_scaled_image" name="IDR_CHECKBOX_HOVER" file="common/checkbox_hover.png" />
- <structure type="chrome_scaled_image" name="IDR_CHECKBOX_PRESSED" file="common/checkbox_pressed.png" />
<structure type="chrome_scaled_image" name="IDR_CLOSE" file="close.png" />
<structure type="chrome_scaled_image" name="IDR_CLOSE_H" file="close_hover.png" />
<structure type="chrome_scaled_image" name="IDR_CLOSE_P" file="close_pressed.png" />
@@ -44,8 +23,6 @@
<structure type="chrome_scaled_image" name="IDR_CONTENT_BOTTOM_RIGHT_CORNER" file="content_bottom_right_corner.png" />
<structure type="chrome_scaled_image" name="IDR_CONTENT_LEFT_SIDE" file="content_left_side.png" />
<structure type="chrome_scaled_image" name="IDR_CONTENT_RIGHT_SIDE" file="content_right_side.png" />
- <structure type="chrome_scaled_image" name="IDR_FOLDER_OPEN" file="common/folder_open.png" />
- <structure type="chrome_scaled_image" name="IDR_FOLDER_OPEN_RTL" file="common/folder_open_rtl.png" />
<structure type="chrome_scaled_image" name="IDR_FRAME" file="frame_default.png" />
<structure type="chrome_scaled_image" name="IDR_FRAME_INACTIVE" file="frame_default_inactive.png" />
<structure type="chrome_scaled_image" name="IDR_MAXIMIZE" file="maximize.png" />
diff --git a/chromium/ui/views/touchui/touch_selection_controller_impl.cc b/chromium/ui/views/touchui/touch_selection_controller_impl.cc
index 43d84d109d8..4162361509c 100644
--- a/chromium/ui/views/touchui/touch_selection_controller_impl.cc
+++ b/chromium/ui/views/touchui/touch_selection_controller_impl.cc
@@ -219,8 +219,7 @@ class TouchSelectionControllerImpl::EditingHandleView
: controller_(controller),
image_(GetCenterHandleImage()),
is_cursor_handle_(is_cursor_handle),
- draw_invisible_(false),
- weak_ptr_factory_(this) {
+ draw_invisible_(false) {
widget_.reset(CreateTouchSelectionPopupWidget(parent, this));
targeter_ = new aura::WindowTargeter();
@@ -394,7 +393,7 @@ class TouchSelectionControllerImpl::EditingHandleView
// handle.
bool draw_invisible_;
- base::WeakPtrFactory<EditingHandleView> weak_ptr_factory_;
+ base::WeakPtrFactory<EditingHandleView> weak_ptr_factory_{this};
DISALLOW_COPY_AND_ASSIGN(EditingHandleView);
};
diff --git a/chromium/ui/views/touchui/touch_selection_menu_views.cc b/chromium/ui/views/touchui/touch_selection_menu_views.cc
index aea8ce84282..1081c830172 100644
--- a/chromium/ui/views/touchui/touch_selection_menu_views.cc
+++ b/chromium/ui/views/touchui/touch_selection_menu_views.cc
@@ -54,8 +54,9 @@ TouchSelectionMenuViews::TouchSelectionMenuViews(
set_adjust_if_offscreen(true);
EnableCanvasFlippingForRTLUI(true);
- SetLayoutManager(std::make_unique<BoxLayout>(
- BoxLayout::kHorizontal, gfx::Insets(), kSpacingBetweenButtons));
+ SetLayoutManager(
+ std::make_unique<BoxLayout>(BoxLayout::Orientation::kHorizontal,
+ gfx::Insets(), kSpacingBetweenButtons));
}
void TouchSelectionMenuViews::ShowMenu(const gfx::Rect& anchor_rect,
@@ -183,4 +184,8 @@ void TouchSelectionMenuViews::ButtonPressed(Button* sender,
client_->RunContextMenu();
}
+BEGIN_METADATA(TouchSelectionMenuViews)
+METADATA_PARENT_CLASS(BubbleDialogDelegateView)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/touchui/touch_selection_menu_views.h b/chromium/ui/views/touchui/touch_selection_menu_views.h
index a9882f269a0..b396471e366 100644
--- a/chromium/ui/views/touchui/touch_selection_menu_views.h
+++ b/chromium/ui/views/touchui/touch_selection_menu_views.h
@@ -22,6 +22,8 @@ class LabelButton;
class VIEWS_EXPORT TouchSelectionMenuViews : public BubbleDialogDelegateView,
public ButtonListener {
public:
+ METADATA_HEADER(TouchSelectionMenuViews);
+
TouchSelectionMenuViews(TouchSelectionMenuRunnerViews* owner,
ui::TouchSelectionMenuClient* client,
aura::Window* context);
diff --git a/chromium/ui/views/view.cc b/chromium/ui/views/view.cc
index 4e71a3d75c2..ff14cec5521 100644
--- a/chromium/ui/views/view.cc
+++ b/chromium/ui/views/view.cc
@@ -25,7 +25,6 @@
#include "ui/base/ime/input_method.h"
#include "ui/compositor/clip_recorder.h"
#include "ui/compositor/compositor.h"
-#include "ui/compositor/dip_util.h"
#include "ui/compositor/layer.h"
#include "ui/compositor/layer_animator.h"
#include "ui/compositor/paint_context.h"
@@ -115,9 +114,6 @@ class ScopedChildrenLock {
} // namespace internal
-// static
-const char View::kViewClassName[] = "View";
-
////////////////////////////////////////////////////////////////////////////////
// View, public:
@@ -546,8 +542,7 @@ void View::DestroyLayer() {
void View::AddLayerBeneathView(ui::Layer* new_layer) {
DCHECK(new_layer);
- DCHECK(!base::ContainsValue(layers_beneath_, new_layer))
- << "Layer already added.";
+ DCHECK(!base::Contains(layers_beneath_, new_layer)) << "Layer already added.";
new_layer->AddObserver(this);
new_layer->SetVisible(GetVisible());
@@ -557,7 +552,9 @@ void View::AddLayerBeneathView(ui::Layer* new_layer) {
// correctly. If not, this will happen on layer creation.
if (layer()) {
ui::Layer* parent_layer = layer()->parent();
- if (parent_layer)
+ // Note that |new_layer| may have already been added to the parent, for
+ // example when the layer of a LayerOwner is recreated.
+ if (parent_layer && parent_layer != new_layer->parent())
parent_layer->Add(new_layer);
new_layer->SetBounds(gfx::Rect(new_layer->size()) +
layer()->bounds().OffsetFromOrigin());
@@ -571,18 +568,37 @@ void View::AddLayerBeneathView(ui::Layer* new_layer) {
}
void View::RemoveLayerBeneathView(ui::Layer* old_layer) {
+ RemoveLayerBeneathViewKeepInLayerTree(old_layer);
+
+ // Note that |old_layer| may have already been removed from its parent.
+ ui::Layer* parent_layer = layer()->parent();
+ if (parent_layer && parent_layer == old_layer->parent())
+ parent_layer->Remove(old_layer);
+
+ CreateOrDestroyLayer();
+}
+
+void View::RemoveLayerBeneathViewKeepInLayerTree(ui::Layer* old_layer) {
auto layer_pos =
std::find(layers_beneath_.begin(), layers_beneath_.end(), old_layer);
DCHECK(layer_pos != layers_beneath_.end())
<< "Attempted to remove a layer that was never added.";
layers_beneath_.erase(layer_pos);
old_layer->RemoveObserver(this);
+}
- ui::Layer* parent_layer = layer()->parent();
- if (parent_layer)
- parent_layer->Remove(old_layer);
+std::vector<ui::Layer*> View::GetLayersInOrder() {
+ // If not painting to a layer, there are no layers immediately related to this
+ // view.
+ if (!layer())
+ return {};
- CreateOrDestroyLayer();
+ std::vector<ui::Layer*> result;
+ for (ui::Layer* layer_beneath : layers_beneath_)
+ result.push_back(layer_beneath);
+ result.push_back(layer());
+
+ return result;
}
void View::LayerDestroyed(ui::Layer* layer) {
@@ -684,10 +700,6 @@ void View::SetLayoutManager(std::nullptr_t) {
// Attributes ------------------------------------------------------------------
-const char* View::GetClassName() const {
- return kViewClassName;
-}
-
const View* View::GetAncestorWithClassName(const std::string& name) const {
for (const View* view = this; view; view = view->parent_) {
if (!strcmp(view->GetClassName(), name.c_str()))
@@ -980,8 +992,9 @@ void View::Paint(const PaintInfo& parent_paint_info) {
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_);
+ gfx::ScopedCanvas scoped_canvas(canvas);
+ if (flip_canvas_on_paint_for_rtl_ui_)
+ scoped_canvas.FlipIfRTL(width());
// Delegate painting the contents of the View to the virtual OnPaint method.
OnPaint(canvas);
@@ -998,6 +1011,17 @@ void View::SetBackground(std::unique_ptr<Background> b) {
void View::SetBorder(std::unique_ptr<Border> b) {
border_ = std::move(b);
+
+ // Conceptually, this should be PreferredSizeChanged(), but for some view
+ // hierarchies that triggers synchronous add/remove operations that are unsafe
+ // in some contexts where SetBorder is called.
+ //
+ // InvalidateLayout() still triggers a re-layout of the view, which should
+ // include re-querying its preferred size so in practice this is both safe and
+ // has the intended effect.
+ InvalidateLayout();
+
+ SchedulePaint();
}
const ui::ThemeProvider* View::GetThemeProvider() const {
@@ -1264,7 +1288,7 @@ void View::AddAccelerator(const ui::Accelerator& accelerator) {
if (!accelerators_)
accelerators_ = std::make_unique<std::vector<ui::Accelerator>>();
- if (!base::ContainsValue(*accelerators_, accelerator))
+ if (!base::Contains(*accelerators_, accelerator))
accelerators_->push_back(accelerator);
RegisterPendingAccelerators();
@@ -1675,14 +1699,11 @@ void View::UpdateParentLayer() {
return;
ui::Layer* parent_layer = nullptr;
- gfx::Vector2d offset(GetMirroredX(), y());
- if (parent_) {
- offset +=
- parent_->CalculateOffsetToAncestorWithLayer(&parent_layer).offset();
- }
+ if (parent_)
+ parent_->CalculateOffsetToAncestorWithLayer(&parent_layer);
- ReparentLayer(offset, parent_layer);
+ ReparentLayer(parent_layer);
}
void View::MoveLayerToParent(ui::Layer* parent_layer,
@@ -1963,6 +1984,7 @@ void View::HandlePropertyChangeEffects(PropertyEffects effects) {
InvalidateLayout();
if (effects & kPropertyEffectsPaint)
SchedulePaint();
+ OnHandlePropertyChangeEffects(effects);
}
PropertyChangedSubscription View::AddPropertyChangedCallback(
@@ -2168,6 +2190,11 @@ void View::AddChildViewAtImpl(View* view, int index) {
view->PropagateThemeChanged();
}
+ // Need to notify the layout manager because one of the callbacks below might
+ // want to know the view's new preferred size, minimum size, etc.
+ if (layout_manager_)
+ layout_manager_->ViewAdded(this, view);
+
ViewHierarchyChangedDetails details(true, this, view, parent);
for (View* v = this; v; v = v->parent_)
@@ -2184,9 +2211,6 @@ void View::AddChildViewAtImpl(View* view, int index) {
view->SchedulePaint();
}
- if (layout_manager_)
- layout_manager_->ViewAdded(this, view);
-
for (ViewObserver& observer : observers_)
observer.OnChildViewAdded(this, view);
}
@@ -2230,6 +2254,11 @@ void View::DoRemoveChildView(View* view,
if (widget)
widget->LayerTreeChanged();
+ // Need to notify the layout manager because one of the callbacks below might
+ // want to know the view's new preferred size, minimum size, etc.
+ if (layout_manager_)
+ layout_manager_->ViewRemoved(this, view);
+
view->PropagateRemoveNotifications(this, new_parent, is_removed_from_widget);
view->parent_ = nullptr;
@@ -2244,9 +2273,6 @@ void View::DoRemoveChildView(View* view,
if (update_tool_tip)
UpdateTooltip();
- if (layout_manager_)
- layout_manager_->ViewRemoved(this, view);
-
for (ViewObserver& observer : observers_)
observer.OnChildViewRemoved(this, view);
}
@@ -2353,10 +2379,6 @@ void View::SnapLayerToPixelBoundary(const LayerOffsetData& offset_data) {
for (ui::Layer* layer_beneath : layers_beneath_)
layer_beneath->SetSubpixelPositionOffset(
offset_data.GetSubpixelOffset());
- } else {
- ui::SnapLayerToPhysicalPixelBoundary(layer()->parent(), layer());
- for (ui::Layer* layer_beneath : layers_beneath_)
- ui::SnapLayerToPhysicalPixelBoundary(layer()->parent(), layer_beneath);
}
} else {
// Reset the offset.
@@ -2432,12 +2454,17 @@ void View::SetLayoutManagerImpl(std::unique_ptr<LayoutManager> layout_manager) {
void View::SetLayerBounds(const gfx::Size& size,
const LayerOffsetData& offset_data) {
const gfx::Rect bounds = gfx::Rect(size) + offset_data.offset();
+ const bool bounds_changed = (bounds != layer()->GetTargetBounds());
layer()->SetBounds(bounds);
for (ui::Layer* layer_beneath : layers_beneath_) {
layer_beneath->SetBounds(gfx::Rect(layer_beneath->size()) +
bounds.OffsetFromOrigin());
}
SnapLayerToPixelBoundary(offset_data);
+ if (bounds_changed) {
+ for (ViewObserver& observer : observers_)
+ observer.OnLayerTargetBoundsChanged(this);
+ }
}
// Transformations -------------------------------------------------------------
@@ -2572,11 +2599,7 @@ void View::OrphanLayers() {
child->OrphanLayers();
}
-void View::ReparentLayer(const gfx::Vector2d& offset, ui::Layer* parent_layer) {
- layer()->SetBounds(GetLocalBounds() + offset);
- for (ui::Layer* layer_beneath : layers_beneath_)
- layer_beneath->SetBounds(gfx::Rect(layer_beneath->size()) + offset);
-
+void View::ReparentLayer(ui::Layer* parent_layer) {
DCHECK_NE(layer(), parent_layer);
if (parent_layer) {
// Adding the main layer can trigger a call to |SnapLayerToPixelBoundary()|.
@@ -2586,6 +2609,13 @@ void View::ReparentLayer(const gfx::Vector2d& offset, ui::Layer* parent_layer) {
parent_layer->Add(layer_beneath);
parent_layer->Add(layer());
}
+ // Update the layer bounds; this needs to be called after this layer is added
+ // to the new parent layer since snapping to pixel boundary will be affected
+ // by the layer hierarchy.
+ LayerOffsetData offset =
+ parent_ ? parent_->CalculateOffsetToAncestorWithLayer(nullptr)
+ : LayerOffsetData(layer()->device_scale_factor());
+ SetLayerBounds(size(), offset + GetMirroredBounds().OffsetFromOrigin());
layer()->SchedulePaint(GetLocalBounds());
MoveLayerToParent(layer(), LayerOffsetData(layer()->device_scale_factor()));
}
@@ -2830,14 +2860,15 @@ bool View::DoDrag(const ui::LocatedEvent& event,
if (widget->dragged_view())
return false;
- OSExchangeData data;
- WriteDragData(press_pt, &data);
+ std::unique_ptr<OSExchangeData> data(std::make_unique<OSExchangeData>());
+ WriteDragData(press_pt, data.get());
// Message the RootView to do the drag and drop. That way if we're removed
// the RootView can detect it and avoid calling us back.
gfx::Point widget_location(event.location());
ConvertPointToWidget(this, &widget_location);
- widget->RunShellDrag(this, data, widget_location, drag_operations, source);
+ widget->RunShellDrag(this, std::move(data), widget_location, drag_operations,
+ source);
// WARNING: we may have been deleted.
return true;
}
diff --git a/chromium/ui/views/view.h b/chromium/ui/views/view.h
index 3d90ae1c174..75eecfb67d0 100644
--- a/chromium/ui/views/view.h
+++ b/chromium/ui/views/view.h
@@ -44,6 +44,7 @@
#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/views/metadata/metadata_header_macros.h"
+#include "ui/views/metadata/metadata_impl_macros.h"
#include "ui/views/paint_info.h"
#include "ui/views/view_targeter.h"
#include "ui/views/views_export.h"
@@ -278,7 +279,7 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
public:
using Views = std::vector<View*>;
- METADATA_HEADER(View);
+ METADATA_HEADER_BASE(View);
enum class FocusBehavior {
// Use when the View is never focusable. Default.
@@ -630,6 +631,21 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
virtual void AddLayerBeneathView(ui::Layer* new_layer);
virtual void RemoveLayerBeneathView(ui::Layer* old_layer);
+ // This is like RemoveLayerBeneathView() but doesn't remove |old_layer| from
+ // its parent. This is useful for when a layer beneth this view is owned by a
+ // ui::LayerOwner which just recreated it (by calling RecreateLayer()). In
+ // this case, this function can be called to remove it from |layers_beneath_|,
+ // and to stop observing it, but it remains in the layer tree since the
+ // expectation of ui::LayerOwner::RecreateLayer() is that the old layer
+ // remains under the same parent, and stacked above the newly cloned layer.
+ void RemoveLayerBeneathViewKeepInLayerTree(ui::Layer* old_layer);
+
+ // Gets the layers associated with this view that should be immediate children
+ // of the parent layer. They are returned in bottom-to-top order. This
+ // includes |this->layer()| and any layers added with |AddLayerBeneathView()|.
+ // Returns an empty vector if this view doesn't paint to a layer.
+ std::vector<ui::Layer*> GetLayersInOrder();
+
// ui::LayerObserver:
void LayerDestroyed(ui::Layer* layer) override;
@@ -723,15 +739,6 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
// Attributes ----------------------------------------------------------------
- // The view class name.
- static const char kViewClassName[];
-
- // Return the receiving view's class name. A view class is a string which
- // uniquely identifies the view class. It is intended to be used as a way to
- // find out during run time if a view can be safely cast to a specific view
- // subclass. The default implementation returns kViewClassName.
- virtual const char* GetClassName() const;
-
// Returns the first ancestor, starting at this, whose class name is |name|.
// Returns null if no ancestor has the class name |name|.
const View* GetAncestorWithClassName(const std::string& name) const;
@@ -1580,6 +1587,11 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
void OnPropertyChanged(PropertyKey property,
PropertyEffects property_effects);
+ // Empty function called in HandlePropertyChangeEffects to be overridden in
+ // subclasses if they have custom functions for property changes.
+ virtual void OnHandlePropertyChangeEffects(PropertyEffects property_effects) {
+ }
+
private:
friend class internal::PreEventDispatchHandler;
friend class internal::PostEventDispatchHandler;
@@ -1746,9 +1758,8 @@ class VIEWS_EXPORT View : public ui::LayerDelegate,
bool UpdateParentLayers();
// Parents this view's layer to |parent_layer|, and sets its bounds and other
- // properties in accordance to |offset|, the view's offset from the
- // |parent_layer|.
- void ReparentLayer(const gfx::Vector2d& offset, ui::Layer* parent_layer);
+ // properties in accordance to the layer hierarchy.
+ void ReparentLayer(ui::Layer* parent_layer);
// Called to update the layer visibility. The layer will be visible if the
// View itself, and all its parent Views are visible. This also updates
diff --git a/chromium/ui/views/view_class_properties.cc b/chromium/ui/views/view_class_properties.cc
index 3a840009300..f226564cded 100644
--- a/chromium/ui/views/view_class_properties.cc
+++ b/chromium/ui/views/view_class_properties.cc
@@ -7,6 +7,7 @@
#include "ui/base/hit_test.h"
#include "ui/gfx/geometry/insets.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
+#include "ui/views/layout/flex_layout_types.h"
#if !defined(USE_AURA)
// aura_constants.cc also declared the bool and int[32_t]
@@ -21,6 +22,7 @@ DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT,
views::BubbleDialogDelegateView*)
DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT, SkPath*)
+DEFINE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT, views::FlexSpecification*)
namespace views {
@@ -31,5 +33,6 @@ DEFINE_UI_CLASS_PROPERTY_KEY(views::BubbleDialogDelegateView*,
kAnchoredDialogKey,
nullptr)
DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(SkPath, kHighlightPathKey, nullptr)
+DEFINE_OWNED_UI_CLASS_PROPERTY_KEY(FlexSpecification, kFlexBehaviorKey, nullptr)
} // namespace views
diff --git a/chromium/ui/views/view_class_properties.h b/chromium/ui/views/view_class_properties.h
index e6f67826fb7..a92096e9b85 100644
--- a/chromium/ui/views/view_class_properties.h
+++ b/chromium/ui/views/view_class_properties.h
@@ -17,6 +17,7 @@ class Insets;
namespace views {
class BubbleDialogDelegateView;
+class FlexSpecification;
// The hit test component (e.g. HTCLIENT) for a View in a window frame. Defaults
// to HTNOWHERE.
@@ -49,6 +50,11 @@ VIEWS_EXPORT extern const ui::ClassProperty<BubbleDialogDelegateView*>* const
// the view in different ways.
VIEWS_EXPORT extern const ui::ClassProperty<SkPath*>* const kHighlightPathKey;
+// A property to store how a view should flex when placed in a layout.
+// Currently only supported by FlexLayout.
+VIEWS_EXPORT extern const ui::ClassProperty<FlexSpecification*>* const
+ kFlexBehaviorKey;
+
} // namespace views
// Declaring the template specialization here to make sure that the
@@ -60,4 +66,5 @@ DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT, gfx::Insets*)
DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT,
views::BubbleDialogDelegateView*)
DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT, SkPath*)
+DECLARE_EXPORTED_UI_CLASS_PROPERTY_TYPE(VIEWS_EXPORT, views::FlexSpecification*)
#endif // UI_VIEWS_VIEW_CLASS_PROPERTIES_H_
diff --git a/chromium/ui/views/view_observer.h b/chromium/ui/views/view_observer.h
index a33f177eb8f..f8ea6c4be4c 100644
--- a/chromium/ui/views/view_observer.h
+++ b/chromium/ui/views/view_observer.h
@@ -34,6 +34,9 @@ class VIEWS_EXPORT ViewObserver {
// Called when the bounds of |observed_view| change.
virtual void OnViewBoundsChanged(View* observed_view) {}
+ // Called when the bounds of |observed_view|'s layer change.
+ virtual void OnLayerTargetBoundsChanged(View* observed_view) {}
+
// Called when View::ViewHierarchyChanged() is called.
virtual void OnViewHierarchyChanged(
View* observed_view,
diff --git a/chromium/ui/views/view_unittest.cc b/chromium/ui/views/view_unittest.cc
index dbca39a1ba7..93549b36eda 100644
--- a/chromium/ui/views/view_unittest.cc
+++ b/chromium/ui/views/view_unittest.cc
@@ -1998,21 +1998,21 @@ TEST_F(ViewTest, TextfieldCutCopyPaste) {
normal->SelectAll(false);
normal->ExecuteCommand(IDS_APP_CUT, 0);
base::string16 result;
- clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
+ clipboard->ReadText(ui::ClipboardType::kCopyPaste, &result);
EXPECT_EQ(kNormalText, result);
normal->SetText(kNormalText); // Let's revert to the original content.
read_only->SelectAll(false);
read_only->ExecuteCommand(IDS_APP_CUT, 0);
result.clear();
- clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
+ clipboard->ReadText(ui::ClipboardType::kCopyPaste, &result);
// Cut should have failed, so the clipboard content should not have changed.
EXPECT_EQ(kNormalText, result);
password->SelectAll(false);
password->ExecuteCommand(IDS_APP_CUT, 0);
result.clear();
- clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
+ clipboard->ReadText(ui::ClipboardType::kCopyPaste, &result);
// Cut should have failed, so the clipboard content should not have changed.
EXPECT_EQ(kNormalText, result);
@@ -2024,19 +2024,19 @@ TEST_F(ViewTest, TextfieldCutCopyPaste) {
read_only->SelectAll(false);
read_only->ExecuteCommand(IDS_APP_COPY, 0);
result.clear();
- clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
+ clipboard->ReadText(ui::ClipboardType::kCopyPaste, &result);
EXPECT_EQ(kReadOnlyText, result);
normal->SelectAll(false);
normal->ExecuteCommand(IDS_APP_COPY, 0);
result.clear();
- clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
+ clipboard->ReadText(ui::ClipboardType::kCopyPaste, &result);
EXPECT_EQ(kNormalText, result);
password->SelectAll(false);
password->ExecuteCommand(IDS_APP_COPY, 0);
result.clear();
- clipboard->ReadText(ui::CLIPBOARD_TYPE_COPY_PASTE, &result);
+ clipboard->ReadText(ui::ClipboardType::kCopyPaste, &result);
// Text cannot be copied from an obscured field; the clipboard won't change.
EXPECT_EQ(kNormalText, result);
@@ -3648,8 +3648,8 @@ TEST_F(ViewTest, GetViewByID) {
View::Views views;
v1.GetViewsInGroup(kGroup, &views);
EXPECT_EQ(2U, views.size());
- EXPECT_TRUE(base::ContainsValue(views, &v3));
- EXPECT_TRUE(base::ContainsValue(views, &v4));
+ EXPECT_TRUE(base::Contains(views, &v3));
+ EXPECT_TRUE(base::Contains(views, &v4));
}
TEST_F(ViewTest, AddExistingChild) {
@@ -3778,6 +3778,31 @@ void TestLayerAnimator::SetBounds(const gfx::Rect& bounds) {
last_bounds_ = bounds;
}
+class TestingLayerViewObserver : public ViewObserver {
+ public:
+ explicit TestingLayerViewObserver(View* view) : view_(view) {
+ view_->AddObserver(this);
+ }
+ ~TestingLayerViewObserver() override { view_->RemoveObserver(this); }
+
+ gfx::Rect GetLastLayerBoundsAndReset() {
+ gfx::Rect value = last_layer_bounds_;
+ last_layer_bounds_ = gfx::Rect();
+ return value;
+ }
+
+ private:
+ // ViewObserver:
+ void OnLayerTargetBoundsChanged(View* view) override {
+ last_layer_bounds_ = view->layer()->bounds();
+ }
+
+ gfx::Rect last_layer_bounds_;
+ View* view_;
+
+ DISALLOW_COPY_AND_ASSIGN(TestingLayerViewObserver);
+};
+
} // namespace
class ViewLayerTest : public ViewsTestBase {
@@ -3905,6 +3930,7 @@ TEST_F(ViewLayerTest, LayerToggling) {
// Create v2 as a child of v1 and do basic assertion testing.
View* v2 = new View;
+ TestingLayerViewObserver v2_observer(v2);
v1->AddChildView(v2);
EXPECT_TRUE(v2->layer() == nullptr);
v2->SetBoundsRect(gfx::Rect(10, 20, 30, 40));
@@ -3912,6 +3938,7 @@ TEST_F(ViewLayerTest, LayerToggling) {
ASSERT_TRUE(v2->layer() != nullptr);
EXPECT_EQ(v1->layer(), v2->layer()->parent());
EXPECT_EQ(gfx::Rect(10, 20, 30, 40), v2->layer()->bounds());
+ EXPECT_EQ(v2->layer()->bounds(), v2_observer.GetLastLayerBoundsAndReset());
// Turn off v1s layer. v2 should still have a layer but its parent should have
// changed.
@@ -3924,6 +3951,7 @@ TEST_F(ViewLayerTest, LayerToggling) {
// The bounds of the layer should have changed to be relative to the root view
// now.
EXPECT_EQ(gfx::Rect(30, 50, 30, 40), v2->layer()->bounds());
+ EXPECT_EQ(v2->layer()->bounds(), v2_observer.GetLastLayerBoundsAndReset());
// Make v1 have a layer again and verify v2s layer is wired up correctly.
gfx::Transform transform;
@@ -3938,6 +3966,7 @@ TEST_F(ViewLayerTest, LayerToggling) {
ASSERT_EQ(1u, v1->layer()->children().size());
EXPECT_EQ(v1->layer()->children()[0], v2->layer());
EXPECT_EQ(gfx::Rect(10, 20, 30, 40), v2->layer()->bounds());
+ EXPECT_EQ(v2->layer()->bounds(), v2_observer.GetLastLayerBoundsAndReset());
}
// Verifies turning on a layer wires up children correctly.
@@ -3950,15 +3979,20 @@ TEST_F(ViewLayerTest, NestedLayerToggling) {
v1->SetBoundsRect(gfx::Rect(20, 30, 140, 150));
View* v2 = v1->AddChildView(std::make_unique<View>());
+ v2->SetBoundsRect(gfx::Rect(10, 10, 100, 100));
View* v3 = v2->AddChildView(std::make_unique<View>());
+ TestingLayerViewObserver v3_observer(v3);
+ v3->SetBoundsRect(gfx::Rect(0, 0, 100, 100));
v3->SetPaintToLayer();
ASSERT_TRUE(v3->layer() != nullptr);
+ EXPECT_EQ(v3->layer()->bounds(), v3_observer.GetLastLayerBoundsAndReset());
// At this point we have v1-v2-v3. v3 has a layer, v1 and v2 don't.
v1->SetPaintToLayer();
EXPECT_EQ(v1->layer(), v3->layer()->parent());
+ EXPECT_EQ(v3->layer()->bounds(), v3_observer.GetLastLayerBoundsAndReset());
}
TEST_F(ViewLayerTest, LayerAnimator) {
@@ -3989,25 +4023,31 @@ TEST_F(ViewLayerTest, BoundsChangeWithLayer) {
v1->SetBoundsRect(gfx::Rect(20, 30, 140, 150));
View* v2 = v1->AddChildView(std::make_unique<View>());
+ TestingLayerViewObserver v2_observer(v2);
v2->SetBoundsRect(gfx::Rect(10, 11, 40, 50));
v2->SetPaintToLayer();
ASSERT_TRUE(v2->layer() != nullptr);
EXPECT_EQ(gfx::Rect(30, 41, 40, 50), v2->layer()->bounds());
+ EXPECT_EQ(v2->layer()->bounds(), v2_observer.GetLastLayerBoundsAndReset());
v1->SetPosition(gfx::Point(25, 36));
EXPECT_EQ(gfx::Rect(35, 47, 40, 50), v2->layer()->bounds());
+ EXPECT_EQ(v2->layer()->bounds(), v2_observer.GetLastLayerBoundsAndReset());
v2->SetPosition(gfx::Point(11, 12));
EXPECT_EQ(gfx::Rect(36, 48, 40, 50), v2->layer()->bounds());
+ EXPECT_EQ(v2->layer()->bounds(), v2_observer.GetLastLayerBoundsAndReset());
// Bounds of the layer should change even if the view is not invisible.
v1->SetVisible(false);
v1->SetPosition(gfx::Point(20, 30));
EXPECT_EQ(gfx::Rect(31, 42, 40, 50), v2->layer()->bounds());
+ EXPECT_EQ(v2->layer()->bounds(), v2_observer.GetLastLayerBoundsAndReset());
v2->SetVisible(false);
v2->SetBoundsRect(gfx::Rect(10, 11, 20, 30));
EXPECT_EQ(gfx::Rect(30, 41, 20, 30), v2->layer()->bounds());
+ EXPECT_EQ(v2->layer()->bounds(), v2_observer.GetLastLayerBoundsAndReset());
}
// Make sure layers are positioned correctly in RTL.
@@ -4523,31 +4563,31 @@ TEST_F(ViewLayerTest, SnapLayerToPixel) {
v1->SetBoundsRect(gfx::Rect(1, 1, 10, 10));
v11->SetPaintToLayer();
- EXPECT_EQ("0.40 0.40", ToString(v11->layer()->subpixel_position_offset()));
+ EXPECT_EQ("0.40 0.40", ToString(v11->layer()->GetSubpixelOffset()));
// Creating a layer in parent should update the child view's layer offset.
v1->SetPaintToLayer();
- EXPECT_EQ("-0.20 -0.20", ToString(v1->layer()->subpixel_position_offset()));
- EXPECT_EQ("-0.20 -0.20", ToString(v11->layer()->subpixel_position_offset()));
+ EXPECT_EQ("-0.20 -0.20", ToString(v1->layer()->GetSubpixelOffset()));
+ EXPECT_EQ("-0.20 -0.20", ToString(v11->layer()->GetSubpixelOffset()));
// DSF change should get propagated and update offsets.
GetRootLayer()->GetCompositor()->SetScaleAndSize(
1.5f, size, allocator.GetCurrentLocalSurfaceIdAllocation());
- EXPECT_EQ("0.33 0.33", ToString(v1->layer()->subpixel_position_offset()));
- EXPECT_EQ("0.33 0.33", ToString(v11->layer()->subpixel_position_offset()));
+ EXPECT_EQ("0.33 0.33", ToString(v1->layer()->GetSubpixelOffset()));
+ EXPECT_EQ("0.33 0.33", ToString(v11->layer()->GetSubpixelOffset()));
// Deleting parent's layer should update the child view's layer's offset.
v1->DestroyLayer();
- EXPECT_EQ("0.00 0.00", ToString(v11->layer()->subpixel_position_offset()));
+ EXPECT_EQ("0.00 0.00", ToString(v11->layer()->GetSubpixelOffset()));
// Setting parent view should update the child view's layer's offset.
v1->SetBoundsRect(gfx::Rect(2, 2, 10, 10));
- EXPECT_EQ("0.33 0.33", ToString(v11->layer()->subpixel_position_offset()));
+ EXPECT_EQ("0.33 0.33", ToString(v11->layer()->GetSubpixelOffset()));
// Setting integral DSF should reset the offset.
GetRootLayer()->GetCompositor()->SetScaleAndSize(
2.0f, size, allocator.GetCurrentLocalSurfaceIdAllocation());
- EXPECT_EQ("0.00 0.00", ToString(v11->layer()->subpixel_position_offset()));
+ EXPECT_EQ("0.00 0.00", ToString(v11->layer()->GetSubpixelOffset()));
}
TEST_F(ViewLayerTest, LayerBeneathTriggersPaintToLayer) {
@@ -4601,9 +4641,8 @@ TEST_F(ViewLayerTest, LayerBeneathAtFractionalScale) {
view->AddLayerBeneathView(&layer);
view->SetBoundsRect(gfx::Rect(1, 1, 10, 10));
- EXPECT_NE(gfx::Vector2dF(), view->layer()->subpixel_position_offset());
- EXPECT_EQ(view->layer()->subpixel_position_offset(),
- layer.subpixel_position_offset());
+ EXPECT_NE(gfx::Vector2dF(), view->layer()->GetSubpixelOffset());
+ EXPECT_EQ(view->layer()->GetSubpixelOffset(), layer.GetSubpixelOffset());
view->RemoveLayerBeneathView(&layer);
}
@@ -4873,19 +4912,19 @@ TEST_F(ViewLayerPixelCanvasTest, SnapLayerToPixel) {
v1->SetBoundsRect(gfx::Rect(9, 9, 100, 100));
PaintRecordingSizeTest(v3, gfx::Size(21, 8)); // Enclosing Rect = (21, 8)
- EXPECT_EQ("-0.63 -0.25", ToString(v3->layer()->subpixel_position_offset()));
+ EXPECT_EQ("-0.63 -0.25", ToString(v3->layer()->GetSubpixelOffset()));
// 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.00", ToString(v3->layer()->subpixel_position_offset()));
+ EXPECT_EQ("-0.25 -0.25", ToString(v1->layer()->GetSubpixelOffset()));
+ EXPECT_EQ("-0.37 -0.00", ToString(v3->layer()->GetSubpixelOffset()));
// DSF change should get propagated and update offsets.
GetRootLayer()->GetCompositor()->SetScaleAndSize(
1.5f, size, allocator.GetCurrentLocalSurfaceIdAllocation());
- EXPECT_EQ("0.33 0.33", ToString(v1->layer()->subpixel_position_offset()));
- EXPECT_EQ("0.33 0.67", ToString(v3->layer()->subpixel_position_offset()));
+ EXPECT_EQ("0.33 0.33", ToString(v1->layer()->GetSubpixelOffset()));
+ EXPECT_EQ("0.33 0.67", ToString(v3->layer()->GetSubpixelOffset()));
v1->DestroyLayer();
PaintRecordingSizeTest(v3, gfx::Size(20, 7)); // Enclosing Rect = (20, 8)
@@ -4894,23 +4933,23 @@ TEST_F(ViewLayerPixelCanvasTest, SnapLayerToPixel) {
GetRootLayer()->GetCompositor()->SetScaleAndSize(
1.33f, size, allocator.GetCurrentLocalSurfaceIdAllocation());
- EXPECT_EQ("0.02 0.02", ToString(v1->layer()->subpixel_position_offset()));
- EXPECT_EQ("0.05 -0.45", ToString(v3->layer()->subpixel_position_offset()));
+ EXPECT_EQ("0.02 0.02", ToString(v1->layer()->GetSubpixelOffset()));
+ EXPECT_EQ("0.05 -0.45", ToString(v3->layer()->GetSubpixelOffset()));
v1->DestroyLayer();
PaintRecordingSizeTest(v3, gfx::Size(17, 7)); // Enclosing Rect = (18, 7)
// Deleting parent's layer should update the child view's layer's offset.
- EXPECT_EQ("0.08 -0.43", ToString(v3->layer()->subpixel_position_offset()));
+ EXPECT_EQ("0.08 -0.43", ToString(v3->layer()->GetSubpixelOffset()));
// Setting parent view should update the child view's layer's offset.
v1->SetBoundsRect(gfx::Rect(3, 3, 10, 10));
- EXPECT_EQ("0.06 -0.44", ToString(v3->layer()->subpixel_position_offset()));
+ EXPECT_EQ("0.06 -0.44", ToString(v3->layer()->GetSubpixelOffset()));
// Setting integral DSF should reset the offset.
GetRootLayer()->GetCompositor()->SetScaleAndSize(
2.0f, size, allocator.GetCurrentLocalSurfaceIdAllocation());
- EXPECT_EQ("0.00 0.00", ToString(v3->layer()->subpixel_position_offset()));
+ EXPECT_EQ("0.00 0.00", ToString(v3->layer()->GetSubpixelOffset()));
}
TEST_F(ViewLayerPixelCanvasTest, LayerBeneathOnPixelCanvas) {
@@ -4929,9 +4968,8 @@ TEST_F(ViewLayerPixelCanvasTest, LayerBeneathOnPixelCanvas) {
view->AddLayerBeneathView(&layer);
view->SetBoundsRect(gfx::Rect(1, 1, 10, 10));
- EXPECT_NE(gfx::Vector2dF(), view->layer()->subpixel_position_offset());
- EXPECT_EQ(view->layer()->subpixel_position_offset(),
- layer.subpixel_position_offset());
+ EXPECT_NE(gfx::Vector2dF(), view->layer()->GetSubpixelOffset());
+ EXPECT_EQ(view->layer()->GetSubpixelOffset(), layer.GetSubpixelOffset());
view->RemoveLayerBeneathView(&layer);
}
diff --git a/chromium/ui/views/views_features.cc b/chromium/ui/views/views_features.cc
index 500931f755d..442002849ee 100644
--- a/chromium/ui/views/views_features.cc
+++ b/chromium/ui/views/views_features.cc
@@ -11,6 +11,12 @@ namespace features {
// Please keep alphabetized.
+#if defined(OS_WIN)
+// Uses aura tooltips instead of the native comctl32 tooltips on Windows.
+const base::Feature kEnableAuraTooltipsOnWindows{
+ "EnableAuraTooltipsOnWindows", base::FEATURE_ENABLED_BY_DEFAULT};
+#endif // OS_WIN
+
// Increases corner radius on Dialogs for the material design refresh.
// TODO(sajadm): Remove this feature flag when platform inconsistencies
// have been fixed as recorded on: https://crbug.com/932970
diff --git a/chromium/ui/views/views_features.h b/chromium/ui/views/views_features.h
index 0df9cff6a38..629df274b11 100644
--- a/chromium/ui/views/views_features.h
+++ b/chromium/ui/views/views_features.h
@@ -6,12 +6,17 @@
#define UI_VIEWS_VIEWS_FEATURES_H_
#include "base/feature_list.h"
+#include "build/build_config.h"
#include "ui/views/views_export.h"
namespace views {
namespace features {
// Please keep alphabetized.
+#if defined(OS_WIN)
+VIEWS_EXPORT extern const base::Feature kEnableAuraTooltipsOnWindows;
+#endif // OS_WIN
+
VIEWS_EXPORT extern const base::Feature kEnableMDRoundedCornersOnDialogs;
} // namespace features
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 ecd4604482b..121481d6e9a 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
@@ -24,12 +24,12 @@
#include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h"
#include "ui/base/layout.h"
#include "ui/base/x/selection_utils.h"
-#include "ui/base/x/x11_window_event_manager.h"
#include "ui/display/screen.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/events/platform/platform_event_source.h"
#include "ui/events/platform_event.h"
+#include "ui/events/x/x11_window_event_manager.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/x/x11.h"
#include "ui/gfx/x/x11_atom_cache.h"
@@ -679,11 +679,11 @@ void DesktopDragDropClientAuraX11::OnXdndDrop(
aura::client::DragDropDelegate* delegate =
aura::client::GetDragDropDelegate(target_window_);
if (delegate) {
- ui::OSExchangeData data(
+ auto data(std::make_unique<ui::OSExchangeData>(
std::make_unique<ui::OSExchangeDataProviderAuraX11>(
- xwindow_, target_current_context_->fetched_targets()));
+ xwindow_, target_current_context_->fetched_targets())));
- ui::DropTargetEvent event(data,
+ ui::DropTargetEvent event(*data.get(),
gfx::PointF(target_window_location_),
gfx::PointF(target_window_root_location_),
target_current_context_->GetDragOperation());
@@ -698,7 +698,7 @@ void DesktopDragDropClientAuraX11::OnXdndDrop(
UMA_HISTOGRAM_COUNTS_1M("Event.DragDrop.ExternalOriginDrop", 1);
}
- drag_operation = delegate->OnPerformDrop(event);
+ drag_operation = delegate->OnPerformDrop(event, std::move(data));
}
target_window_->RemoveObserver(this);
@@ -729,7 +729,7 @@ void DesktopDragDropClientAuraX11::OnSelectionNotify(
}
int DesktopDragDropClientAuraX11::StartDragAndDrop(
- const ui::OSExchangeData& data,
+ std::unique_ptr<ui::OSExchangeData> data,
aura::Window* root_window,
aura::Window* source_window,
const gfx::Point& screen_location,
@@ -748,7 +748,7 @@ int DesktopDragDropClientAuraX11::StartDragAndDrop(
drag_operation_ = operation;
negotiated_operation_ = ui::DragDropTypes::DRAG_NONE;
- const ui::OSExchangeData::Provider* provider = &data.provider();
+ const ui::OSExchangeData::Provider* provider = &data->provider();
source_provider_ = static_cast<const ui::OSExchangeDataProviderAuraX11*>(
provider);
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 de855088d25..fea36f36f46 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
@@ -82,7 +82,7 @@ class VIEWS_EXPORT DesktopDragDropClientAuraX11
void OnSelectionNotify(const XSelectionEvent& xselection);
// Overridden from aura::client::DragDropClient:
- int StartDragAndDrop(const ui::OSExchangeData& data,
+ int StartDragAndDrop(std::unique_ptr<ui::OSExchangeData> data,
aura::Window* root_window,
aura::Window* source_window,
const gfx::Point& screen_location,
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc
index ef13a2b4382..df0755982e0 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_aurax11_unittest.cc
@@ -361,20 +361,17 @@ class DesktopDragDropClientAuraX11Test : public ViewsTestBase {
~DesktopDragDropClientAuraX11Test() override = default;
int StartDragAndDrop() {
- ui::OSExchangeData data;
- data.SetString(base::ASCIIToUTF16("Test"));
+ auto data(std::make_unique<ui::OSExchangeData>());
+ data->SetString(base::ASCIIToUTF16("Test"));
SkBitmap drag_bitmap;
drag_bitmap.allocN32Pixels(10, 10);
drag_bitmap.eraseARGB(0xFF, 0, 0, 0);
gfx::ImageSkia drag_image(gfx::ImageSkia::CreateFrom1xBitmap(drag_bitmap));
- data.provider().SetDragImage(drag_image, gfx::Vector2d());
+ data->provider().SetDragImage(drag_image, gfx::Vector2d());
return client_->StartDragAndDrop(
- data,
- widget_->GetNativeWindow()->GetRootWindow(),
- widget_->GetNativeWindow(),
- gfx::Point(),
- ui::DragDropTypes::DRAG_COPY,
+ std::move(data), widget_->GetNativeWindow()->GetRootWindow(),
+ widget_->GetNativeWindow(), gfx::Point(), ui::DragDropTypes::DRAG_COPY,
ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
}
@@ -806,7 +803,8 @@ class TestDragDropDelegate : public aura::client::DragDropDelegate {
++num_exits_;
}
- int OnPerformDrop(const ui::DropTargetEvent& event) override {
+ int OnPerformDrop(const ui::DropTargetEvent& event,
+ std::unique_ptr<OSExchangeData> data) override {
++num_drops_;
last_event_mouse_position_ = event.location();
last_event_flags_ = event.flags();
@@ -836,15 +834,12 @@ class DesktopDragDropClientAuraX11ChromeSourceTargetTest
~DesktopDragDropClientAuraX11ChromeSourceTargetTest() override = default;
int StartDragAndDrop() {
- ui::OSExchangeData data;
- data.SetString(base::ASCIIToUTF16("Test"));
+ auto data(std::make_unique<ui::OSExchangeData>());
+ data->SetString(base::ASCIIToUTF16("Test"));
return client_->StartDragAndDrop(
- data,
- widget_->GetNativeWindow()->GetRootWindow(),
- widget_->GetNativeWindow(),
- gfx::Point(),
- ui::DragDropTypes::DRAG_COPY,
+ std::move(data), widget_->GetNativeWindow()->GetRootWindow(),
+ widget_->GetNativeWindow(), gfx::Point(), ui::DragDropTypes::DRAG_COPY,
ui::DragDropTypes::DRAG_EVENT_SOURCE_MOUSE);
}
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc
index dfe5f9a9f70..7f08e6a6141 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.cc
@@ -53,7 +53,7 @@ DesktopDragDropClientOzone::~DesktopDragDropClientOzone() {
}
int DesktopDragDropClientOzone::StartDragAndDrop(
- const ui::OSExchangeData& data,
+ std::unique_ptr<ui::OSExchangeData> data,
aura::Window* root_window,
aura::Window* source_window,
const gfx::Point& root_location,
@@ -81,7 +81,7 @@ int DesktopDragDropClientOzone::StartDragAndDrop(
cursor_manager_->GetInitializedCursor(ui::CursorType::kGrabbing));
drag_handler_->StartDrag(
- data, operation, cursor_client->GetCursor(),
+ *data.get(), operation, cursor_client->GetCursor(),
base::BindOnce(&DesktopDragDropClientOzone::OnDragSessionClosed,
base::Unretained(this)));
in_move_loop_ = true;
@@ -234,7 +234,8 @@ void DesktopDragDropClientOzone::PerformDrop() {
std::unique_ptr<ui::DropTargetEvent> event =
CreateDropTargetEvent(last_drag_point_);
if (drag_drop_delegate_ && event)
- drag_operation_ = drag_drop_delegate_->OnPerformDrop(*event);
+ drag_operation_ = drag_drop_delegate_->OnPerformDrop(
+ *event, std::move(os_exchange_data_));
DragDropSessionCompleted();
}
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h
index e31f41ba49e..05b2fd24af6 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone.h
@@ -40,7 +40,7 @@ class VIEWS_EXPORT DesktopDragDropClientOzone
~DesktopDragDropClientOzone() override;
// Overridden from aura::client::DragDropClient:
- int StartDragAndDrop(const ui::OSExchangeData& data,
+ int StartDragAndDrop(std::unique_ptr<ui::OSExchangeData> data,
aura::Window* root_window,
aura::Window* source_window,
const gfx::Point& root_location,
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc
index bcc003f2a2b..336258bb0ae 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_drag_drop_client_ozone_unittest.cc
@@ -45,14 +45,13 @@ class FakePlatformWindow : public ui::PlatformWindow, public ui::WmDragHandler {
void Minimize() override {}
void Restore() override {}
ui::PlatformWindowState GetPlatformWindowState() const override {
- return ui::PlatformWindowState::PLATFORM_WINDOW_STATE_NORMAL;
+ return ui::PlatformWindowState::kNormal;
}
+ void Activate() override {}
+ void Deactivate() override {}
void SetCursor(ui::PlatformCursor cursor) override {}
void MoveCursorTo(const gfx::Point& location) override {}
void ConfineCursorToBounds(const gfx::Rect& bounds) override {}
- ui::PlatformImeController* GetPlatformImeController() override {
- return nullptr;
- }
void SetRestoredBoundsInPixels(const gfx::Rect& bounds) override {}
gfx::Rect GetRestoredBoundsInPixels() const override { return gfx::Rect(); }
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 2c829dca0ee..b2c6b75837d 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
@@ -30,7 +30,7 @@ DesktopDragDropClientWin::~DesktopDragDropClientWin() {
}
int DesktopDragDropClientWin::StartDragAndDrop(
- const ui::OSExchangeData& data,
+ std::unique_ptr<ui::OSExchangeData> data,
aura::Window* root_window,
aura::Window* source_window,
const gfx::Point& screen_location,
@@ -43,8 +43,8 @@ int DesktopDragDropClientWin::StartDragAndDrop(
drag_source_ = ui::DragSourceWin::Create();
Microsoft::WRL::ComPtr<ui::DragSourceWin> drag_source_copy = drag_source_;
- drag_source_copy->set_data(&data);
- ui::OSExchangeDataProviderWin::GetDataObjectImpl(data)
+ drag_source_copy->set_data(data.get());
+ ui::OSExchangeDataProviderWin::GetDataObjectImpl(*data.get())
->set_in_drag_loop(true);
DWORD effect;
@@ -53,7 +53,8 @@ int DesktopDragDropClientWin::StartDragAndDrop(
ui::DragDropTypes::DRAG_EVENT_SOURCE_COUNT);
HRESULT result = DoDragDrop(
- ui::OSExchangeDataProviderWin::GetIDataObject(data), drag_source_.Get(),
+ ui::OSExchangeDataProviderWin::GetIDataObject(*data.get()),
+ drag_source_.Get(),
ui::DragDropTypes::DragOperationToDropEffect(operation), &effect);
drag_source_copy->set_data(nullptr);
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 25845e08f22..70e5950f3d6 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
@@ -34,7 +34,7 @@ class VIEWS_EXPORT DesktopDragDropClientWin
~DesktopDragDropClientWin() override;
// Overridden from aura::client::DragDropClient:
- int StartDragAndDrop(const ui::OSExchangeData& data,
+ int StartDragAndDrop(std::unique_ptr<ui::OSExchangeData> data,
aura::Window* root_window,
aura::Window* source_window,
const gfx::Point& screen_location,
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_drop_target_win.cc b/chromium/ui/views/widget/desktop_aura/desktop_drop_target_win.cc
index 898eacdecac..052d82cbea1 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_drop_target_win.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_drop_target_win.cc
@@ -98,7 +98,7 @@ DWORD DesktopDropTargetWin::OnDrop(IDataObject* data_object,
DragDropDelegate* delegate;
Translate(data_object, key_state, position, effect, &data, &event, &delegate);
if (delegate) {
- drag_operation = delegate->OnPerformDrop(*event);
+ drag_operation = delegate->OnPerformDrop(*event, std::move(data));
DragDropClient* client = aura::client::GetDragDropClient(root_window_);
if (client && !client->IsDragDropInProgress() &&
drag_operation != ui::DragDropTypes::DRAG_NONE) {
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_focus_rules.cc b/chromium/ui/views/widget/desktop_aura/desktop_focus_rules.cc
index 6e823cdd63a..ec25062629a 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_focus_rules.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_focus_rules.cc
@@ -17,6 +17,10 @@ DesktopFocusRules::DesktopFocusRules(aura::Window* content_window)
DesktopFocusRules::~DesktopFocusRules() = default;
bool DesktopFocusRules::CanActivateWindow(const aura::Window* window) const {
+ // The RootWindow is not activatable, only |content_window_| and children of
+ // the RootWindow are considered activatable.
+ if (window && window->IsRootWindow())
+ return false;
if (window && IsToplevelWindow(window) &&
content_window_->GetRootWindow()->Contains(window) &&
wm::WindowStateIs(window->GetRootWindow(), ui::SHOW_STATE_MINIMIZED)) {
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_focus_rules_unittest.cc b/chromium/ui/views/widget/desktop_aura/desktop_focus_rules_unittest.cc
index 8717379bfa3..597e57744f0 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_focus_rules_unittest.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_focus_rules_unittest.cc
@@ -40,4 +40,14 @@ TEST_F(DesktopFocusRulesTest, DontFocusWindowsInOtherHierarchies) {
w2->CloseNow();
}
+// Verifies root windows are not activatable.
+TEST_F(DesktopFocusRulesTest, CanActivateWindowForRootWindow) {
+ Widget* w1 = CreateTopLevelNativeWidget();
+ aura::Window* content_window = w1->GetNativeWindow();
+ aura::Window* root_window = content_window->GetRootWindow();
+ EXPECT_TRUE(wm::CanActivateWindow(content_window));
+ EXPECT_FALSE(wm::CanActivateWindow(root_window));
+ w1->CloseNow();
+}
+
} // namespace views
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 85569403055..e7d20b83506 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
@@ -86,7 +86,7 @@ class DesktopNativeWidgetTopLevelHandler : public aura::WindowObserver {
const gfx::Rect& bounds,
bool full_screen,
bool is_menu,
- bool root_is_always_on_top) {
+ ui::ZOrderLevel root_z_order) {
// This instance will get deleted when the widget is destroyed.
DesktopNativeWidgetTopLevelHandler* top_level_handler =
new DesktopNativeWidgetTopLevelHandler;
@@ -103,7 +103,7 @@ class DesktopNativeWidgetTopLevelHandler : public aura::WindowObserver {
init_params.activatable = full_screen ?
Widget::InitParams::ACTIVATABLE_YES :
Widget::InitParams::ACTIVATABLE_NO;
- init_params.keep_on_top = root_is_always_on_top;
+ init_params.z_order = root_z_order;
// This widget instance will get deleted when the window is
// destroyed.
@@ -193,14 +193,14 @@ class DesktopNativeWidgetAuraWindowParentingClient
bool is_menu = window->type() == aura::client::WINDOW_TYPE_MENU;
if (is_fullscreen || is_menu) {
- bool root_is_always_on_top = false;
+ ui::ZOrderLevel root_z_order = ui::ZOrderLevel::kNormal;
internal::NativeWidgetPrivate* native_widget =
DesktopNativeWidgetAura::ForWindow(root_window_);
if (native_widget)
- root_is_always_on_top = native_widget->IsAlwaysOnTop();
+ root_z_order = native_widget->GetZOrderLevel();
return DesktopNativeWidgetTopLevelHandler::CreateParentWindow(
- window, bounds, is_fullscreen, is_menu, root_is_always_on_top);
+ window, bounds, is_fullscreen, is_menu, root_z_order);
}
return root_window_;
}
@@ -249,8 +249,7 @@ DesktopNativeWidgetAura::DesktopNativeWidgetAura(
last_drop_operation_(ui::DragDropTypes::DRAG_NONE),
restore_focus_on_activate_(false),
cursor_(gfx::kNullCursor),
- widget_type_(Widget::InitParams::TYPE_WINDOW),
- close_widget_factory_(this) {
+ widget_type_(Widget::InitParams::TYPE_WINDOW) {
aura::client::SetFocusChangeObserver(content_window_, this);
wm::SetActivationChangeObserver(content_window_, this);
}
@@ -814,13 +813,15 @@ bool DesktopNativeWidgetAura::IsActive() const {
return content_window_ && desktop_window_tree_host_->IsActive();
}
-void DesktopNativeWidgetAura::SetAlwaysOnTop(bool always_on_top) {
+void DesktopNativeWidgetAura::SetZOrderLevel(ui::ZOrderLevel order) {
if (content_window_)
- desktop_window_tree_host_->SetAlwaysOnTop(always_on_top);
+ desktop_window_tree_host_->SetZOrderLevel(order);
}
-bool DesktopNativeWidgetAura::IsAlwaysOnTop() const {
- return content_window_ && desktop_window_tree_host_->IsAlwaysOnTop();
+ui::ZOrderLevel DesktopNativeWidgetAura::GetZOrderLevel() const {
+ if (content_window_)
+ return desktop_window_tree_host_->GetZOrderLevel();
+ return ui::ZOrderLevel::kNormal;
}
void DesktopNativeWidgetAura::SetVisibleOnAllWorkspaces(bool always_visible) {
@@ -888,11 +889,12 @@ void DesktopNativeWidgetAura::FlashFrame(bool flash_frame) {
void DesktopNativeWidgetAura::RunShellDrag(
View* view,
- const ui::OSExchangeData& data,
+ std::unique_ptr<ui::OSExchangeData> data,
const gfx::Point& location,
int operation,
ui::DragDropTypes::DragEventSource source) {
- views::RunShellDrag(content_window_, data, location, operation, source);
+ views::RunShellDrag(content_window_, std::move(data), location, operation,
+ source);
}
void DesktopNativeWidgetAura::SchedulePaintInRect(const gfx::Rect& rect) {
@@ -1005,10 +1007,6 @@ void DesktopNativeWidgetAura::OnSizeConstraintsChanged() {
desktop_window_tree_host_->SizeConstraintsChanged();
}
-void DesktopNativeWidgetAura::OnCanActivateChanged() {
- desktop_window_tree_host_->OnCanActivateChanged();
-}
-
std::string DesktopNativeWidgetAura::GetName() const {
return name_;
}
@@ -1196,7 +1194,9 @@ void DesktopNativeWidgetAura::OnDragExited() {
drop_helper_->OnDragExit();
}
-int DesktopNativeWidgetAura::OnPerformDrop(const ui::DropTargetEvent& event) {
+int DesktopNativeWidgetAura::OnPerformDrop(
+ const ui::DropTargetEvent& event,
+ std::unique_ptr<ui::OSExchangeData> data) {
DCHECK(drop_helper_.get() != nullptr);
if (ShouldActivate())
Activate();
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 5d45002399b..8b038de0c5b 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
@@ -151,8 +151,8 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
void Activate() override;
void Deactivate() override;
bool IsActive() const override;
- void SetAlwaysOnTop(bool always_on_top) override;
- bool IsAlwaysOnTop() const override;
+ void SetZOrderLevel(ui::ZOrderLevel order) override;
+ ui::ZOrderLevel GetZOrderLevel() const override;
void SetVisibleOnAllWorkspaces(bool always_visible) override;
bool IsVisibleOnAllWorkspaces() const override;
void Maximize() override;
@@ -168,7 +168,7 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
void SetAspectRatio(const gfx::SizeF& aspect_ratio) override;
void FlashFrame(bool flash_frame) override;
void RunShellDrag(View* view,
- const ui::OSExchangeData& data,
+ std::unique_ptr<ui::OSExchangeData> data,
const gfx::Point& location,
int operation,
ui::DragDropTypes::DragEventSource source) override;
@@ -191,7 +191,6 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
bool IsTranslucentWindowOpacitySupported() const override;
ui::GestureRecognizer* GetGestureRecognizer() override;
void OnSizeConstraintsChanged() override;
- void OnCanActivateChanged() override;
std::string GetName() const override;
// Overridden from aura::WindowDelegate:
@@ -238,7 +237,8 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
void OnDragEntered(const ui::DropTargetEvent& event) override;
int OnDragUpdated(const ui::DropTargetEvent& event) override;
void OnDragExited() override;
- int OnPerformDrop(const ui::DropTargetEvent& event) override;
+ int OnPerformDrop(const ui::DropTargetEvent& event,
+ std::unique_ptr<ui::OSExchangeData> data) override;
// Overridden from aura::WindowTreeHostObserver:
void OnHostCloseRequested(aura::WindowTreeHost* host) override;
@@ -323,7 +323,7 @@ class VIEWS_EXPORT DesktopNativeWidgetAura
// The following factory is used for calls to close the NativeWidgetAura
// instance.
- base::WeakPtrFactory<DesktopNativeWidgetAura> close_widget_factory_;
+ base::WeakPtrFactory<DesktopNativeWidgetAura> close_widget_factory_{this};
DISALLOW_COPY_AND_ASSIGN(DesktopNativeWidgetAura);
};
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 5fc1220919c..69c9e7324c2 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.cc
@@ -23,8 +23,7 @@
#include "ui/events/platform/platform_event_source.h"
#include "ui/events/platform/x11/x11_event_source.h"
#include "ui/gfx/font_render_params.h"
-#include "ui/gfx/geometry/point_conversions.h"
-#include "ui/gfx/geometry/size_conversions.h"
+#include "ui/gfx/geometry/dip_util.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/switches.h"
#include "ui/gfx/x/x11.h"
@@ -50,14 +49,6 @@ float GetDeviceScaleFactor() {
return device_scale_factor;
}
-gfx::Point PixelToDIPPoint(const gfx::Point& pixel_point) {
- return gfx::ScaleToFlooredPoint(pixel_point, 1.0f / GetDeviceScaleFactor());
-}
-
-gfx::Point DIPToPixelPoint(const gfx::Point& dip_point) {
- return gfx::ScaleToFlooredPoint(dip_point, GetDeviceScaleFactor());
-}
-
} // namespace
namespace views {
@@ -68,8 +59,7 @@ namespace views {
DesktopScreenX11::DesktopScreenX11()
: xdisplay_(gfx::GetXDisplay()),
x_root_window_(DefaultRootWindow(xdisplay_)),
- xrandr_version_(ui::GetXrandrVersion(xdisplay_)),
- weak_factory_(this) {
+ xrandr_version_(ui::GetXrandrVersion(xdisplay_)) {
if (views::LinuxUI::instance())
views::LinuxUI::instance()->AddDeviceScaleFactorObserver(this);
float scale = GetDeviceScaleFactor();
@@ -111,7 +101,7 @@ gfx::Point DesktopScreenX11::GetCursorScreenPoint() {
auto point = ui::X11EventSource::GetInstance()
->GetRootCursorLocationFromCurrentEvent();
if (point)
- return PixelToDIPPoint(point.value());
+ return gfx::ConvertPointToDIP(GetDeviceScaleFactor(), point.value());
}
::Window root, child;
@@ -120,7 +110,8 @@ gfx::Point DesktopScreenX11::GetCursorScreenPoint() {
XQueryPointer(xdisplay_, x_root_window_, &root, &child, &root_x, &root_y,
&win_x, &win_y, &mask);
- return PixelToDIPPoint(gfx::Point(root_x, root_y));
+ return gfx::ConvertPointToDIP(GetDeviceScaleFactor(),
+ gfx::Point(root_x, root_y));
}
bool DesktopScreenX11::IsWindowUnderCursor(gfx::NativeWindow window) {
@@ -131,7 +122,7 @@ gfx::NativeWindow DesktopScreenX11::GetWindowAtScreenPoint(
const gfx::Point& point) {
X11TopmostWindowFinder finder;
return finder.FindLocalProcessWindowAt(
- DIPToPixelPoint(point), std::set<aura::Window*>());
+ gfx::ConvertPointToPixel(GetDeviceScaleFactor(), point), {});
}
int DesktopScreenX11::GetNumDisplays() const {
@@ -161,11 +152,10 @@ display::Display DesktopScreenX11::GetDisplayNearestWindow(
DesktopWindowTreeHostX11* rwh = DesktopWindowTreeHostX11::GetHostForXID(
host->GetAcceleratedWidget());
if (rwh) {
- const float scale = 1.0f / GetDeviceScaleFactor();
const gfx::Rect pixel_rect = rwh->GetX11RootWindowBounds();
- return GetDisplayMatching(
- gfx::Rect(gfx::ScaleToFlooredPoint(pixel_rect.origin(), scale),
- gfx::ScaleToCeiledSize(pixel_rect.size(), scale)));
+ const gfx::Rect dip_rect =
+ gfx::ConvertRectToDIP(GetDeviceScaleFactor(), pixel_rect);
+ return GetDisplayMatching(dip_rect);
}
}
@@ -176,25 +166,13 @@ display::Display DesktopScreenX11::GetDisplayNearestPoint(
const gfx::Point& point) const {
if (displays_.size() <= 1)
return GetPrimaryDisplay();
- for (const auto& display : displays_) {
- if (display.bounds().Contains(point))
- return display;
- }
return *FindDisplayNearestPoint(displays_, point);
}
display::Display DesktopScreenX11::GetDisplayMatching(
const gfx::Rect& match_rect) const {
- int max_area = 0;
- const display::Display* matching = nullptr;
- for (const auto& display : displays_) {
- gfx::Rect intersect = gfx::IntersectRects(display.bounds(), match_rect);
- int area = intersect.width() * intersect.height();
- if (area > max_area) {
- max_area = area;
- matching = &display;
- }
- }
+ const display::Display* matching =
+ display::FindDisplayWithBiggestIntersection(displays_, match_rect);
// Fallback to the primary display if there is no matching display.
return matching ? *matching : GetPrimaryDisplay();
}
@@ -254,8 +232,7 @@ DesktopScreenX11::DesktopScreenX11(
: xdisplay_(gfx::GetXDisplay()),
x_root_window_(DefaultRootWindow(xdisplay_)),
xrandr_version_(ui::GetXrandrVersion(xdisplay_)),
- displays_(test_displays),
- weak_factory_(this) {
+ displays_(test_displays) {
if (views::LinuxUI::instance())
views::LinuxUI::instance()->AddDeviceScaleFactorObserver(this);
}
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.h b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.h
index 877d4ae3cb1..beb698efa63 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11.h
@@ -102,7 +102,7 @@ class VIEWS_EXPORT DesktopScreenX11 : public display::Screen,
display::DisplayChangeNotifier change_notifier_;
- base::WeakPtrFactory<DesktopScreenX11> weak_factory_;
+ base::WeakPtrFactory<DesktopScreenX11> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(DesktopScreenX11);
};
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11_unittest.cc b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11_unittest.cc
index abd96f43f46..c40d24755cc 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_screen_x11_unittest.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_screen_x11_unittest.cc
@@ -7,6 +7,7 @@
#include <stdint.h>
#include <memory>
+#include <vector>
#include "base/macros.h"
#include "testing/gtest/include/gtest/gtest.h"
@@ -14,6 +15,8 @@
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/base/hit_test.h"
+#include "ui/base/x/x11_util.h"
+#include "ui/display/display.h"
#include "ui/display/display_observer.h"
#include "ui/events/test/event_generator.h"
#include "ui/gfx/font_render_params.h"
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 eff14bc37bc..c4fa6859b4a 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
@@ -130,8 +130,8 @@ class VIEWS_EXPORT DesktopWindowTreeHost {
virtual bool HasCapture() const = 0;
- virtual void SetAlwaysOnTop(bool always_on_top) = 0;
- virtual bool IsAlwaysOnTop() const = 0;
+ virtual void SetZOrderLevel(ui::ZOrderLevel order) = 0;
+ virtual ui::ZOrderLevel GetZOrderLevel() const = 0;
virtual void SetVisibleOnAllWorkspaces(bool always_visible) = 0;
virtual bool IsVisibleOnAllWorkspaces() const = 0;
@@ -197,9 +197,6 @@ class VIEWS_EXPORT DesktopWindowTreeHost {
// Sets the bounds in screen coordinate DIPs (WindowTreeHost generally
// operates in pixels). This function is implemented in terms of Screen.
virtual void SetBoundsInDIP(const gfx::Rect& bounds);
-
- // See description in Widget::OnCanActivateChanged().
- virtual void OnCanActivateChanged() {}
};
} // namespace views
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
index ac7c92db83a..c8021f125d6 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.cc
@@ -50,6 +50,8 @@ ui::PlatformWindowInitProperties ConvertWidgetInitParamsToInitProperties(
}
properties.bounds = params.bounds;
+ properties.activatable =
+ params.activatable == Widget::InitParams::ACTIVATABLE_YES;
if (params.parent && params.parent->GetHost())
properties.parent_widget = params.parent->GetHost()->GetAcceleratedWidget();
@@ -306,13 +308,11 @@ void DesktopWindowTreeHostPlatform::SetShape(
}
void DesktopWindowTreeHostPlatform::Activate() {
- // TODO: needs PlatformWindow support.
- NOTIMPLEMENTED_LOG_ONCE();
+ platform_window()->Activate();
}
void DesktopWindowTreeHostPlatform::Deactivate() {
- // TODO: needs PlatformWindow support.
- NOTIMPLEMENTED_LOG_ONCE();
+ platform_window()->Deactivate();
}
bool DesktopWindowTreeHostPlatform::IsActive() const {
@@ -333,26 +333,26 @@ void DesktopWindowTreeHostPlatform::Restore() {
bool DesktopWindowTreeHostPlatform::IsMaximized() const {
return platform_window()->GetPlatformWindowState() ==
- ui::PlatformWindowState::PLATFORM_WINDOW_STATE_MAXIMIZED;
+ ui::PlatformWindowState::kMaximized;
}
bool DesktopWindowTreeHostPlatform::IsMinimized() const {
return platform_window()->GetPlatformWindowState() ==
- ui::PlatformWindowState::PLATFORM_WINDOW_STATE_MINIMIZED;
+ ui::PlatformWindowState::kMinimized;
}
bool DesktopWindowTreeHostPlatform::HasCapture() const {
return platform_window()->HasCapture();
}
-void DesktopWindowTreeHostPlatform::SetAlwaysOnTop(bool always_on_top) {
+void DesktopWindowTreeHostPlatform::SetZOrderLevel(ui::ZOrderLevel order) {
// TODO: needs PlatformWindow support.
NOTIMPLEMENTED_LOG_ONCE();
}
-bool DesktopWindowTreeHostPlatform::IsAlwaysOnTop() const {
+ui::ZOrderLevel DesktopWindowTreeHostPlatform::GetZOrderLevel() const {
// TODO: needs PlatformWindow support.
- return false;
+ return ui::ZOrderLevel::kNormal;
}
void DesktopWindowTreeHostPlatform::SetVisibleOnAllWorkspaces(
@@ -419,7 +419,7 @@ void DesktopWindowTreeHostPlatform::SetFullscreen(bool fullscreen) {
bool DesktopWindowTreeHostPlatform::IsFullscreen() const {
return platform_window()->GetPlatformWindowState() ==
- ui::PlatformWindowState::PLATFORM_WINDOW_STATE_FULLSCREEN;
+ ui::PlatformWindowState::kFullScreen;
}
void DesktopWindowTreeHostPlatform::SetOpacity(float opacity) {
@@ -519,8 +519,7 @@ void DesktopWindowTreeHostPlatform::OnWindowStateChanged(
// Propagate minimization/restore to compositor to avoid drawing 'blank'
// frames that could be treated as previews, which show content even if a
// window is minimized.
- bool visible =
- new_state != ui::PlatformWindowState::PLATFORM_WINDOW_STATE_MINIMIZED;
+ bool visible = new_state != ui::PlatformWindowState::kMinimized;
if (visible != compositor()->IsVisible()) {
compositor()->SetVisible(visible);
native_widget_delegate_->OnNativeWidgetVisibilityChanged(visible);
diff --git a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h
index 02f30ef40ca..8760639632c 100644
--- a/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h
+++ b/chromium/ui/views/widget/desktop_aura/desktop_window_tree_host_platform.h
@@ -59,8 +59,8 @@ class VIEWS_EXPORT DesktopWindowTreeHostPlatform
bool IsMaximized() const override;
bool IsMinimized() const override;
bool HasCapture() const override;
- void SetAlwaysOnTop(bool always_on_top) override;
- bool IsAlwaysOnTop() const override;
+ void SetZOrderLevel(ui::ZOrderLevel order) override;
+ ui::ZOrderLevel GetZOrderLevel() const override;
void SetVisibleOnAllWorkspaces(bool always_visible) override;
bool IsVisibleOnAllWorkspaces() const override;
bool SetWindowTitle(const base::string16& title) override;
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 c18d5fb9ea5..0eedc266531 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
@@ -8,6 +8,7 @@
#include "base/containers/flat_set.h"
#include "base/memory/ptr_util.h"
#include "base/metrics/histogram_macros.h"
+#include "base/win/win_util.h"
#include "third_party/skia/include/core/SkPath.h"
#include "third_party/skia/include/core/SkRegion.h"
#include "ui/aura/client/aura_constants.h"
@@ -29,7 +30,9 @@
#include "ui/gfx/geometry/vector2d.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/gfx/path_win.h"
+#include "ui/views/corewm/tooltip_aura.h"
#include "ui/views/corewm/tooltip_win.h"
+#include "ui/views/views_features.h"
#include "ui/views/views_switches.h"
#include "ui/views/widget/desktop_aura/desktop_drag_drop_client_win.h"
#include "ui/views/widget/desktop_aura/desktop_native_cursor_manager.h"
@@ -130,6 +133,7 @@ void DesktopWindowTreeHostWin::Init(const Widget::InitParams& params) {
remove_standard_frame_ = params.remove_standard_frame;
has_non_client_view_ = Widget::RequiresNonClientView(params.type);
+ z_order_ = params.EffectiveZOrderLevel();
// We don't have an HWND yet, so scale relative to the nearest screen.
gfx::Rect pixel_bounds =
@@ -165,6 +169,9 @@ void DesktopWindowTreeHostWin::OnActiveWindowChanged(bool active) {}
void DesktopWindowTreeHostWin::OnWidgetInitDone() {}
std::unique_ptr<corewm::Tooltip> DesktopWindowTreeHostWin::CreateTooltip() {
+ if (base::FeatureList::IsEnabled(features::kEnableAuraTooltipsOnWindows))
+ return std::make_unique<corewm::TooltipAura>();
+
DCHECK(!tooltip_);
tooltip_ = new corewm::TooltipWin(GetAcceleratedWidget());
return base::WrapUnique(tooltip_);
@@ -361,12 +368,25 @@ bool DesktopWindowTreeHostWin::HasCapture() const {
return message_handler_->HasCapture();
}
-void DesktopWindowTreeHostWin::SetAlwaysOnTop(bool always_on_top) {
- message_handler_->SetAlwaysOnTop(always_on_top);
+void DesktopWindowTreeHostWin::SetZOrderLevel(ui::ZOrderLevel order) {
+ z_order_ = order;
+ // Emulate the multiple window levels provided by other platforms by
+ // collapsing the z-order enum into kNormal = normal, everything else = always
+ // on top.
+ message_handler_->SetAlwaysOnTop(order != ui::ZOrderLevel::kNormal);
}
-bool DesktopWindowTreeHostWin::IsAlwaysOnTop() const {
- return message_handler_->IsAlwaysOnTop();
+ui::ZOrderLevel DesktopWindowTreeHostWin::GetZOrderLevel() const {
+ bool window_always_on_top = message_handler_->IsAlwaysOnTop();
+ bool level_always_on_top = z_order_ != ui::ZOrderLevel::kNormal;
+
+ if (window_always_on_top == level_always_on_top)
+ return z_order_;
+
+ // If something external has forced a window to be always-on-top, map it to
+ // kFloatingWindow as a reasonable equivalent.
+ return window_always_on_top ? ui::ZOrderLevel::kFloatingWindow
+ : ui::ZOrderLevel::kNormal;
}
void DesktopWindowTreeHostWin::SetVisibleOnAllWorkspaces(bool always_visible) {
@@ -900,6 +920,16 @@ bool DesktopWindowTreeHostWin::HandleMouseEvent(ui::MouseEvent* event) {
}
void DesktopWindowTreeHostWin::HandleKeyEvent(ui::KeyEvent* event) {
+ // Bypass normal handling of alt-space, which would otherwise consume the
+ // corresponding WM_SYSCHAR. This allows HandleIMEMessage() to show the
+ // system menu in this case. If we instead showed the system menu here, the
+ // WM_SYSCHAR would trigger a beep when processed by the native event handler.
+ if ((event->type() == ui::ET_KEY_PRESSED) &&
+ (event->key_code() == ui::VKEY_SPACE) &&
+ (event->flags() & ui::EF_ALT_DOWN) && GetWidget()->non_client_view()) {
+ return;
+ }
+
SendEventToSink(event);
}
@@ -935,6 +965,15 @@ bool DesktopWindowTreeHostWin::HandleIMEMessage(UINT message,
WPARAM w_param,
LPARAM l_param,
LRESULT* result) {
+ // Show the system menu at an appropriate location on alt-space.
+ if ((message == WM_SYSCHAR) && (w_param == VK_SPACE) &&
+ GetWidget()->non_client_view()) {
+ const auto* frame = GetWidget()->non_client_view()->frame_view();
+ ShowSystemMenuAtScreenPixelLocation(
+ GetHWND(), frame->GetSystemMenuScreenPixelLocation());
+ return true;
+ }
+
MSG msg = {};
msg.hwnd = GetHWND();
msg.message = message;
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 8ac960b083c..335db0db49b 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
@@ -95,8 +95,8 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin
bool IsMaximized() const override;
bool IsMinimized() const override;
bool HasCapture() const override;
- void SetAlwaysOnTop(bool always_on_top) override;
- bool IsAlwaysOnTop() const override;
+ void SetZOrderLevel(ui::ZOrderLevel order) override;
+ ui::ZOrderLevel GetZOrderLevel() const override;
void SetVisibleOnAllWorkspaces(bool always_visible) override;
bool IsVisibleOnAllWorkspaces() const override;
bool SetWindowTitle(const base::string16& title) override;
@@ -307,6 +307,10 @@ class VIEWS_EXPORT DesktopWindowTreeHostWin
// become activated.
bool wants_mouse_events_when_inactive_ = false;
+ // The z-order level of the window; the window exhibits "always on top"
+ // behavior if > 0.
+ ui::ZOrderLevel z_order_ = ui::ZOrderLevel::kNormal;
+
DISALLOW_COPY_AND_ASSIGN(DesktopWindowTreeHostWin);
};
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 2c502b3a533..7c4f1e88e42 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
@@ -4,8 +4,13 @@
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_x11.h"
+#include <algorithm>
+#include <list>
#include <memory>
+#include <set>
+#include <string>
#include <utility>
+#include <vector>
#include "base/bind.h"
#include "base/command_line.h"
@@ -19,13 +24,13 @@
#include "base/threading/thread_task_runner_handle.h"
#include "base/trace_event/trace_event.h"
#include "third_party/skia/include/core/SkPath.h"
-#include "ui/accessibility/platform/atk_util_auralinux.h"
#include "ui/aura/client/aura_constants.h"
#include "ui/aura/client/cursor_client.h"
#include "ui/aura/client/focus_client.h"
#include "ui/aura/null_window_targeter.h"
#include "ui/aura/window.h"
#include "ui/aura/window_event_dispatcher.h"
+#include "ui/base/buildflags.h"
#include "ui/base/class_property.h"
#include "ui/base/dragdrop/os_exchange_data_provider_aurax11.h"
#include "ui/base/hit_test.h"
@@ -34,16 +39,15 @@
#include "ui/base/x/x11_pointer_grab.h"
#include "ui/base/x/x11_util.h"
#include "ui/base/x/x11_util_internal.h"
-#include "ui/base/x/x11_window_event_manager.h"
#include "ui/display/screen.h"
-#include "ui/events/devices/x11/device_data_manager_x11.h"
#include "ui/events/devices/x11/device_list_cache_x11.h"
-#include "ui/events/devices/x11/touch_factory_x11.h"
+#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/events/keyboard_hook.h"
#include "ui/events/keycodes/dom/dom_code.h"
#include "ui/events/platform/platform_event_source.h"
-#include "ui/gfx/geometry/insets.h"
+#include "ui/events/x/events_x_utils.h"
+#include "ui/events/x/x11_window_event_manager.h"
#include "ui/gfx/geometry/size_conversions.h"
#include "ui/gfx/image/image_skia.h"
#include "ui/gfx/image/image_skia_rep.h"
@@ -65,6 +69,10 @@
#include "ui/wm/core/compound_event_filter.h"
#include "ui/wm/core/window_util.h"
+#if BUILDFLAG(USE_ATK)
+#include "ui/accessibility/platform/atk_util_auralinux.h"
+#endif
+
DEFINE_UI_CLASS_PROPERTY_TYPE(views::DesktopWindowTreeHostX11*)
namespace views {
@@ -80,12 +88,60 @@ DEFINE_UI_CLASS_PROPERTY_KEY(DesktopWindowTreeHostX11*,
namespace {
-// Special value of the _NET_WM_DESKTOP property which indicates that the window
-// should appear on all desktops.
-const int kAllDesktops = 0xFFFFFFFF;
+ui::XWindow::Configuration ConvertInitParamsToX11WindowConfig(
+ const Widget::InitParams& params) {
+ using WindowType = ui::XWindow::WindowType;
+ using WindowOpacity = ui::XWindow::WindowOpacity;
+ ui::XWindow::Configuration config;
-const char kX11WindowRolePopup[] = "popup";
-const char kX11WindowRoleBubble[] = "bubble";
+ switch (params.type) {
+ case Widget::InitParams::TYPE_WINDOW:
+ config.type = WindowType::kWindow;
+ break;
+ case Widget::InitParams::TYPE_MENU:
+ config.type = WindowType::kMenu;
+ break;
+ case Widget::InitParams::TYPE_TOOLTIP:
+ config.type = WindowType::kTooltip;
+ break;
+ case Widget::InitParams::TYPE_DRAG:
+ config.type = WindowType::kDrag;
+ break;
+ case Widget::InitParams::TYPE_BUBBLE:
+ config.type = WindowType::kBubble;
+ break;
+ default:
+ config.type = WindowType::kPopup;
+ break;
+ }
+
+ switch (params.opacity) {
+ case Widget::InitParams::WindowOpacity::INFER_OPACITY:
+ config.opacity = WindowOpacity::kInferOpacity;
+ break;
+ case Widget::InitParams::WindowOpacity::OPAQUE_WINDOW:
+ config.opacity = WindowOpacity::kOpaqueWindow;
+ break;
+ case Widget::InitParams::WindowOpacity::TRANSLUCENT_WINDOW:
+ config.opacity = WindowOpacity::kTranslucentWindow;
+ break;
+ }
+
+ config.activatable =
+ params.activatable == Widget::InitParams::ACTIVATABLE_YES;
+ config.force_show_in_taskbar = params.force_show_in_taskbar;
+ config.keep_on_top =
+ params.EffectiveZOrderLevel() != ui::ZOrderLevel::kNormal;
+ config.visible_on_all_workspaces = params.visible_on_all_workspaces;
+ config.remove_standard_frame = params.remove_standard_frame;
+
+ config.workspace = params.workspace;
+ config.wm_class_name = params.wm_class_name;
+ config.wm_class_class = params.wm_class_class;
+ config.wm_role_name = params.wm_role_name;
+
+ return config;
+}
// Returns the whole path from |window| to the root.
std::vector<::Window> GetParentsList(XDisplay* xdisplay, ::Window window) {
@@ -106,34 +162,6 @@ std::vector<::Window> GetParentsList(XDisplay* xdisplay, ::Window window) {
return result;
}
-int XI2ModeToXMode(int xi2_mode) {
- switch (xi2_mode) {
- case XINotifyNormal:
- return NotifyNormal;
- case XINotifyGrab:
- case XINotifyPassiveGrab:
- return NotifyGrab;
- case XINotifyUngrab:
- case XINotifyPassiveUngrab:
- return NotifyUngrab;
- case XINotifyWhileGrabbed:
- return NotifyWhileGrabbed;
- default:
- NOTREACHED();
- return NotifyNormal;
- }
-}
-
-int IgnoreX11Errors(XDisplay* display, XErrorEvent* error) {
- return 0;
-}
-
-bool SyncSetCounter(XDisplay* display, XID counter, int64_t value) {
- XSyncValue sync_value;
- XSyncIntsToValue(&sync_value, value & 0xFFFFFFFF, value >> 32);
- return XSyncSetCounter(display, counter, sync_value) == x11::True;
-}
-
class SwapWithNewSizeObserverHelper : public ui::CompositorObserver {
public:
using HelperCallback = base::RepeatingCallback<void(const gfx::Size&)>;
@@ -166,18 +194,25 @@ class SwapWithNewSizeObserverHelper : public ui::CompositorObserver {
DISALLOW_COPY_AND_ASSIGN(SwapWithNewSizeObserverHelper);
};
+bool ShouldDiscardKeyEvent(XEvent* xev) {
+#if BUILDFLAG(USE_ATK)
+ return ui::AtkUtilAuraLinux::HandleKeyEvent(xev) ==
+ ui::DiscardAtkKeyEvent::Discard;
+#else
+ return false;
+#endif
+}
+
} // namespace
////////////////////////////////////////////////////////////////////////////////
// DesktopWindowTreeHostX11, public:
-
DesktopWindowTreeHostX11::DesktopWindowTreeHostX11(
internal::NativeWidgetDelegate* native_widget_delegate,
DesktopNativeWidgetAura* desktop_native_widget_aura)
- : xdisplay_(gfx::GetXDisplay()),
- x_root_window_(DefaultRootWindow(xdisplay_)),
- native_widget_delegate_(native_widget_delegate),
- desktop_native_widget_aura_(desktop_native_widget_aura) {}
+ : native_widget_delegate_(native_widget_delegate),
+ desktop_native_widget_aura_(desktop_native_widget_aura),
+ x11_window_(std::make_unique<ui::XWindow>(this)) {}
DesktopWindowTreeHostX11::~DesktopWindowTreeHostX11() {
window()->ClearProperty(kHostForRootWindow);
@@ -211,160 +246,15 @@ std::vector<aura::Window*> DesktopWindowTreeHostX11::GetAllOpenWindows() {
}
gfx::Rect DesktopWindowTreeHostX11::GetX11RootWindowBounds() const {
- return bounds_in_pixels_;
+ return x11_window_->bounds();
}
gfx::Rect DesktopWindowTreeHostX11::GetX11RootWindowOuterBounds() const {
- gfx::Rect outer_bounds(bounds_in_pixels_);
- outer_bounds.Inset(-native_window_frame_borders_in_pixels_);
- return outer_bounds;
+ return x11_window_->GetOutterBounds();
}
::Region DesktopWindowTreeHostX11::GetWindowShape() const {
- return window_shape_.get();
-}
-
-void DesktopWindowTreeHostX11::BeforeActivationStateChanged() {
- was_active_ = IsActive();
- had_pointer_ = has_pointer_;
- had_pointer_grab_ = has_pointer_grab_;
- had_window_focus_ = has_window_focus_;
-}
-
-void DesktopWindowTreeHostX11::AfterActivationStateChanged() {
- if (had_pointer_grab_ && !has_pointer_grab_)
- dispatcher()->OnHostLostMouseGrab();
-
- bool had_pointer_capture = had_pointer_ || had_pointer_grab_;
- bool has_pointer_capture = has_pointer_ || has_pointer_grab_;
- if (had_pointer_capture && !has_pointer_capture)
- OnHostLostWindowCapture();
-
- if (!was_active_ && IsActive()) {
- FlashFrame(false);
- // TODO(thomasanderson): Remove this window shuffling and use XWindowCache
- // instead.
- open_windows().remove(xwindow_);
- open_windows().insert(open_windows().begin(), xwindow_);
- }
-
- if (was_active_ != IsActive()) {
- desktop_native_widget_aura_->HandleActivationChanged(IsActive());
- native_widget_delegate_->AsWidget()->GetRootView()->SchedulePaint();
- }
-}
-
-void DesktopWindowTreeHostX11::OnCrossingEvent(bool enter,
- bool focus_in_window_or_ancestor,
- int mode,
- int detail) {
- // NotifyInferior on a crossing event means the pointer moved into or out of a
- // child window, but the pointer is still within |xwindow_|.
- if (detail == NotifyInferior)
- return;
-
- BeforeActivationStateChanged();
-
- if (mode == NotifyGrab)
- has_pointer_grab_ = enter;
- else if (mode == NotifyUngrab)
- has_pointer_grab_ = false;
-
- has_pointer_ = enter;
- if (focus_in_window_or_ancestor && !has_window_focus_) {
- // If we reach this point, we know the focus is in an ancestor or the
- // pointer root. The definition of |has_pointer_focus_| is (An ancestor
- // window or the PointerRoot is focused) && |has_pointer_|. Therefore, we
- // can just use |has_pointer_| in the assignment. The transitions for when
- // the focus changes are handled in OnFocusEvent().
- has_pointer_focus_ = has_pointer_;
- }
-
- AfterActivationStateChanged();
-}
-
-void DesktopWindowTreeHostX11::OnFocusEvent(bool focus_in,
- int mode,
- int detail) {
- // NotifyInferior on a focus event means the focus moved into or out of a
- // child window, but the focus is still within |xwindow_|.
- if (detail == NotifyInferior)
- return;
-
- bool notify_grab = mode == NotifyGrab || mode == NotifyUngrab;
-
- BeforeActivationStateChanged();
-
- // For every focus change, the X server sends normal focus events which are
- // useful for tracking |has_window_focus_|, but supplements these events with
- // NotifyPointer events which are only useful for tracking pointer focus.
-
- // For |has_pointer_focus_| and |has_window_focus_|, we continue tracking
- // state during a grab, but ignore grab/ungrab events themselves.
- if (!notify_grab && detail != NotifyPointer)
- has_window_focus_ = focus_in;
-
- if (!notify_grab && has_pointer_) {
- switch (detail) {
- case NotifyAncestor:
- case NotifyVirtual:
- // If we reach this point, we know |has_pointer_| was true before and
- // after this event. Since the definition of |has_pointer_focus_| is
- // (An ancestor window or the PointerRoot is focused) && |has_pointer_|,
- // we only need to worry about transitions on the first conjunct.
- // Therefore, |has_pointer_focus_| will become true when:
- // 1. Focus moves from |xwindow_| to an ancestor
- // (FocusOut with NotifyAncestor)
- // 2. Focus moves from a decendant of |xwindow_| to an ancestor
- // (FocusOut with NotifyVirtual)
- // |has_pointer_focus_| will become false when:
- // 1. Focus moves from an ancestor to |xwindow_|
- // (FocusIn with NotifyAncestor)
- // 2. Focus moves from an ancestor to a child of |xwindow_|
- // (FocusIn with NotifyVirtual)
- has_pointer_focus_ = !focus_in;
- break;
- case NotifyPointer:
- // The remaining cases for |has_pointer_focus_| becoming true are:
- // 3. Focus moves from |xwindow_| to the PointerRoot
- // 4. Focus moves from a decendant of |xwindow_| to the PointerRoot
- // 5. Focus moves from None to the PointerRoot
- // 6. Focus moves from Other to the PointerRoot
- // 7. Focus moves from None to an ancestor of |xwindow_|
- // 8. Focus moves from Other to an ancestor fo |xwindow_|
- // In each case, we will get a FocusIn with a detail of NotifyPointer.
- // The remaining cases for |has_pointer_focus_| becoming false are:
- // 3. Focus moves from the PointerRoot to |xwindow_|
- // 4. Focus moves from the PointerRoot to a decendant of |xwindow|
- // 5. Focus moves from the PointerRoot to None
- // 6. Focus moves from an ancestor of |xwindow_| to None
- // 7. Focus moves from the PointerRoot to Other
- // 8. Focus moves from an ancestor of |xwindow_| to Other
- // In each case, we will get a FocusOut with a detail of NotifyPointer.
- has_pointer_focus_ = focus_in;
- break;
- case NotifyNonlinear:
- case NotifyNonlinearVirtual:
- // We get Nonlinear(Virtual) events when
- // 1. Focus moves from Other to |xwindow_|
- // (FocusIn with NotifyNonlinear)
- // 2. Focus moves from Other to a decendant of |xwindow_|
- // (FocusIn with NotifyNonlinearVirtual)
- // 3. Focus moves from |xwindow_| to Other
- // (FocusOut with NotifyNonlinear)
- // 4. Focus moves from a decendant of |xwindow_| to Other
- // (FocusOut with NotifyNonlinearVirtual)
- // |has_pointer_focus_| should be false before and after this event.
- has_pointer_focus_ = false;
- break;
- default:
- break;
- }
- }
-
- ignore_keyboard_input_ = false;
-
- AfterActivationStateChanged();
+ return x11_window_->shape();
}
void DesktopWindowTreeHostX11::AddObserver(
@@ -406,23 +296,10 @@ void DesktopWindowTreeHostX11::CleanUpWindowList(
// DesktopWindowTreeHostX11, DesktopWindowTreeHost implementation:
void DesktopWindowTreeHostX11::Init(const Widget::InitParams& params) {
- activatable_ = (params.activatable == Widget::InitParams::ACTIVATABLE_YES);
-
if (params.type == Widget::InitParams::TYPE_WINDOW)
content_window()->SetProperty(aura::client::kAnimationsDisabledKey, true);
- // TODO(erg): Check whether we *should* be building a WindowTreeHost here, or
- // whether we should be proxying requests to another DRWHL.
-
- // In some situations, views tries to make a zero sized window, and that
- // makes us crash. Make sure we have valid sizes.
- Widget::InitParams sanitized_params = params;
- if (sanitized_params.bounds.width() == 0)
- sanitized_params.bounds.set_width(100);
- if (sanitized_params.bounds.height() == 0)
- sanitized_params.bounds.set_height(100);
-
- InitX11Window(sanitized_params);
+ InitX11Window(params);
InitHost();
window()->Show();
}
@@ -462,7 +339,7 @@ std::unique_ptr<aura::client::DragDropClient>
DesktopWindowTreeHostX11::CreateDragDropClient(
DesktopNativeCursorManager* cursor_manager) {
drag_drop_client_ = new DesktopDragDropClientAuraX11(
- window(), cursor_manager, xdisplay_, xwindow_);
+ window(), cursor_manager, x11_window_->display(), x11_window_->window());
drag_drop_client_->Init();
return base::WrapUnique(drag_drop_client_);
}
@@ -471,7 +348,7 @@ void DesktopWindowTreeHostX11::Close() {
content_window()->Hide();
// TODO(erg): Might need to do additional hiding tasks here.
- delayed_resize_task_.Cancel();
+ x11_window_->CancelResize();
if (!close_widget_factory_.HasWeakPtrs()) {
// And we delay the close so that if we are called from an ATL callback,
@@ -485,7 +362,7 @@ void DesktopWindowTreeHostX11::Close() {
}
void DesktopWindowTreeHostX11::CloseNow() {
- if (xwindow_ == x11::None)
+ if (x11_window_->window() == x11::None)
return;
ReleaseCapture();
@@ -515,20 +392,12 @@ void DesktopWindowTreeHostX11::CloseNow() {
// causes a crash with in-process renderer.
DestroyCompositor();
- open_windows().remove(xwindow_);
+ open_windows().remove(x11_window_->window());
// Actually free our native resources.
- if (ui::PlatformEventSource::GetInstance())
- ui::PlatformEventSource::GetInstance()->RemovePlatformEventDispatcher(this);
- XDestroyWindow(xdisplay_, xwindow_);
- xwindow_ = x11::None;
-
- if (update_counter_ != x11::None) {
- XSyncDestroyCounter(xdisplay_, update_counter_);
- XSyncDestroyCounter(xdisplay_, extended_update_counter_);
- update_counter_ = x11::None;
- extended_update_counter_ = x11::None;
- }
+ if (auto* source = ui::PlatformEventSource::GetInstance())
+ source->RemovePlatformEventDispatcher(this);
+ x11_window_->Close();
desktop_native_widget_aura_->OnHostClosed();
}
@@ -541,7 +410,7 @@ void DesktopWindowTreeHostX11::Show(ui::WindowShowState show_state,
if (compositor())
SetVisible(true);
- if (!window_mapped_in_client_ || IsMinimized())
+ if (!x11_window_->mapped_in_client() || IsMinimized())
MapWindow(show_state);
switch (show_state) {
@@ -552,7 +421,6 @@ void DesktopWindowTreeHostX11::Show(ui::WindowShowState show_state,
// have reset it.
restored_bounds_in_pixels_ = ToPixelRect(restore_bounds);
}
-
break;
case ui::SHOW_STATE_MINIMIZED:
Minimize();
@@ -570,19 +438,17 @@ void DesktopWindowTreeHostX11::Show(ui::WindowShowState show_state,
}
bool DesktopWindowTreeHostX11::IsVisible() const {
- // On Windows, IsVisible() returns true for minimized windows. On X11, a
- // minimized window is not mapped, so an explicit IsMinimized() check is
- // necessary.
- return window_mapped_in_client_ || IsMinimized();
+ return x11_window_->IsVisible();
}
void DesktopWindowTreeHostX11::SetSize(const gfx::Size& requested_size) {
gfx::Size size_in_pixels = ToPixelRect(gfx::Rect(requested_size)).size();
size_in_pixels = AdjustSize(size_in_pixels);
- bool size_changed = bounds_in_pixels_.size() != size_in_pixels;
- XResizeWindow(xdisplay_, xwindow_, size_in_pixels.width(),
- size_in_pixels.height());
- bounds_in_pixels_.set_size(size_in_pixels);
+
+ bool size_changed = x11_window_->bounds().size() != size_in_pixels;
+
+ x11_window_->SetSize(size_in_pixels);
+
if (size_changed) {
OnHostResizedInPixels(size_in_pixels);
ResetWindowRegion();
@@ -590,13 +456,16 @@ void DesktopWindowTreeHostX11::SetSize(const gfx::Size& requested_size) {
}
void DesktopWindowTreeHostX11::StackAbove(aura::Window* window) {
+ XDisplay* display = x11_window_->display();
+ ::Window xwindow = x11_window_->window();
+
if (window && window->GetRootWindow()) {
::Window window_below = window->GetHost()->GetAcceleratedWidget();
// Find all parent windows up to the root.
std::vector<::Window> window_below_parents =
- GetParentsList(xdisplay_, window_below);
+ GetParentsList(display, window_below);
std::vector<::Window> window_above_parents =
- GetParentsList(xdisplay_, xwindow_);
+ GetParentsList(display, xwindow);
// Find their common ancestor.
auto it_below_window = window_below_parents.rbegin();
@@ -609,19 +478,19 @@ void DesktopWindowTreeHostX11::StackAbove(aura::Window* window) {
if (it_below_window != window_below_parents.rend() &&
it_above_window != window_above_parents.rend()) {
- // First stack |xwindow_| below so Z-order of |window| stays the same.
+ // First stack |xwindow| below so Z-order of |window| stays the same.
::Window windows[] = {*it_below_window, *it_above_window};
- if (XRestackWindows(xdisplay_, windows, 2) == 0) {
+ if (XRestackWindows(display, windows, 2) == 0) {
// Now stack them properly.
std::swap(windows[0], windows[1]);
- XRestackWindows(xdisplay_, windows, 2);
+ XRestackWindows(display, windows, 2);
}
}
}
}
void DesktopWindowTreeHostX11::StackAtTop() {
- XRaiseWindow(xdisplay_, xwindow_);
+ x11_window_->StackAtTop();
}
void DesktopWindowTreeHostX11::CenterWindow(const gfx::Size& size) {
@@ -671,7 +540,8 @@ void DesktopWindowTreeHostX11::GetWindowPlacement(
}
gfx::Rect DesktopWindowTreeHostX11::GetWindowBoundsInScreen() const {
- return ToDIPRect(bounds_in_pixels_);
+ gfx::Rect bounds_in_pixels = x11_window_->bounds();
+ return ToDIPRect(bounds_in_pixels);
}
gfx::Rect DesktopWindowTreeHostX11::GetClientAreaBoundsInScreen() const {
@@ -698,15 +568,8 @@ gfx::Rect DesktopWindowTreeHostX11::GetRestoredBounds() const {
}
std::string DesktopWindowTreeHostX11::GetWorkspace() const {
- return workspace_ ? base::NumberToString(workspace_.value()) : std::string();
-}
-
-void DesktopWindowTreeHostX11::UpdateWorkspace() {
- int workspace;
- if (ui::GetWindowDesktop(xwindow_, &workspace))
- workspace_ = workspace;
- else
- workspace_ = base::nullopt;
+ base::Optional<int> workspace = x11_window_->workspace();
+ return workspace ? base::NumberToString(workspace.value()) : std::string();
}
gfx::Rect DesktopWindowTreeHostX11::GetWorkAreaBoundsInScreen() const {
@@ -717,9 +580,7 @@ gfx::Rect DesktopWindowTreeHostX11::GetWorkAreaBoundsInScreen() const {
void DesktopWindowTreeHostX11::SetShape(
std::unique_ptr<Widget::ShapeRects> native_shape) {
- custom_window_shape_ = false;
- window_shape_.reset();
-
+ _XRegion* xregion = nullptr;
if (native_shape) {
SkRegion native_region;
for (const gfx::Rect& rect : *native_shape)
@@ -730,171 +591,102 @@ void DesktopWindowTreeHostX11::SetShape(
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));
+ xregion = gfx::CreateRegionFromSkPath(path_in_pixels);
} else {
- window_shape_.reset(XCreateRegion());
+ xregion = XCreateRegion();
}
} else {
- window_shape_.reset(gfx::CreateRegionFromSkRegion(native_region));
+ xregion = gfx::CreateRegionFromSkRegion(native_region);
}
-
- custom_window_shape_ = true;
}
+ x11_window_->SetShape(xregion);
ResetWindowRegion();
}
void DesktopWindowTreeHostX11::Activate() {
- if (!IsVisible() || !activatable_)
- return;
-
- BeforeActivationStateChanged();
-
- ignore_keyboard_input_ = false;
-
- // wmii says that it supports _NET_ACTIVE_WINDOW but does not.
- // https://code.google.com/p/wmii/issues/detail?id=266
- static bool wm_supports_active_window =
- ui::GuessWindowManager() != ui::WM_WMII &&
- ui::WmSupportsHint(gfx::GetAtom("_NET_ACTIVE_WINDOW"));
-
- Time timestamp = ui::X11EventSource::GetInstance()->GetTimestamp();
-
- // override_redirect windows ignore _NET_ACTIVE_WINDOW.
- // https://crbug.com/940924
- if (wm_supports_active_window && !override_redirect_) {
- XEvent xclient;
- memset(&xclient, 0, sizeof(xclient));
- xclient.type = ClientMessage;
- xclient.xclient.window = xwindow_;
- xclient.xclient.message_type = gfx::GetAtom("_NET_ACTIVE_WINDOW");
- xclient.xclient.format = 32;
- xclient.xclient.data.l[0] = 1; // Specified we are an app.
- xclient.xclient.data.l[1] = timestamp;
- // TODO(thomasanderson): if another chrome window is active, specify that in
- // data.l[2]. The EWMH spec claims this may make the WM more likely to
- // service our _NET_ACTIVE_WINDOW request.
- xclient.xclient.data.l[2] = x11::None;
- xclient.xclient.data.l[3] = 0;
- xclient.xclient.data.l[4] = 0;
-
- XSendEvent(xdisplay_, x_root_window_, x11::False,
- SubstructureRedirectMask | SubstructureNotifyMask, &xclient);
- } else {
- XRaiseWindow(xdisplay_, xwindow_);
- // Directly ask the X server to give focus to the window. Note that the call
- // would have raised an X error if the window is not mapped.
- auto old_error_handler = XSetErrorHandler(IgnoreX11Errors);
- XSetInputFocus(xdisplay_, xwindow_, RevertToParent, timestamp);
- // At this point, we know we will receive focus, and some
- // webdriver tests depend on a window being IsActive() immediately
- // after an Activate(), so just set this state now.
- has_pointer_focus_ = false;
- has_window_focus_ = true;
- window_mapped_in_server_ = true;
- XSetErrorHandler(old_error_handler);
- }
- AfterActivationStateChanged();
+ x11_window_->Activate();
}
void DesktopWindowTreeHostX11::Deactivate() {
- BeforeActivationStateChanged();
-
- // Ignore future input events.
- ignore_keyboard_input_ = true;
-
ReleaseCapture();
- XLowerWindow(xdisplay_, xwindow_);
-
- AfterActivationStateChanged();
+ x11_window_->Deactivate();
}
bool DesktopWindowTreeHostX11::IsActive() const {
- // Focus and stacking order are independent in X11. Since we cannot guarantee
- // a window is topmost iff it has focus, just use the focus state to determine
- // if a window is active. Note that Activate() and Deactivate() change the
- // stacking order in addition to changing the focus state.
- bool is_active =
- (has_window_focus_ || has_pointer_focus_) && !ignore_keyboard_input_;
-
- // is_active => window_mapped_in_server_
- // !window_mapped_in_server_ => !is_active
- DCHECK(!is_active || window_mapped_in_server_);
-
- // |has_window_focus_| and |has_pointer_focus_| are mutually exclusive.
- DCHECK(!has_window_focus_ || !has_pointer_focus_);
-
- return is_active;
+ return x11_window_->IsActive();
}
void DesktopWindowTreeHostX11::Maximize() {
- if (ui::HasWMSpecProperty(window_properties_,
- gfx::GetAtom("_NET_WM_STATE_FULLSCREEN"))) {
+ // TODO(nickdiego): Move into XWindow. For now, it is kept outside
+ // it due to |AdjustSize|, which depends on display::Display, which is not
+ // accessible at Ozone layer.
+ if (x11_window_->IsFullscreen()) {
// Unfullscreen the window if it is fullscreen.
- SetWMSpecState(false, gfx::GetAtom("_NET_WM_STATE_FULLSCREEN"), x11::None);
+ x11_window_->SetFullscreen(false);
// Resize the window so that it does not have the same size as a monitor.
// (Otherwise, some window managers immediately put the window back in
// fullscreen mode).
- gfx::Rect adjusted_bounds_in_pixels(bounds_in_pixels_.origin(),
- AdjustSize(bounds_in_pixels_.size()));
- if (adjusted_bounds_in_pixels != bounds_in_pixels_)
+ gfx::Rect bounds = x11_window_->bounds();
+ gfx::Rect adjusted_bounds_in_pixels(bounds.origin(),
+ AdjustSize(bounds.size()));
+ if (adjusted_bounds_in_pixels != bounds)
SetBoundsInPixels(adjusted_bounds_in_pixels);
}
- // Some WMs do not respect maximization hints on unmapped windows, so we
- // save this one for later too.
- should_maximize_after_map_ = !window_mapped_in_client_;
-
// When we are in the process of requesting to maximize a window, we can
// accurately keep track of our restored bounds instead of relying on the
// heuristics that are in the PropertyNotify and ConfigureNotify handlers.
- restored_bounds_in_pixels_ = bounds_in_pixels_;
+ restored_bounds_in_pixels_ = x11_window_->bounds();
- SetWMSpecState(true, gfx::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT"),
- gfx::GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ"));
+ x11_window_->Maximize();
if (IsMinimized())
Show(ui::SHOW_STATE_NORMAL, gfx::Rect());
}
void DesktopWindowTreeHostX11::Minimize() {
ReleaseCapture();
- if (window_mapped_in_client_)
- XIconifyWindow(xdisplay_, xwindow_, 0);
- else
- SetWMSpecState(true, gfx::GetAtom("_NET_WM_STATE_HIDDEN"), x11::None);
+ x11_window_->Minimize();
}
void DesktopWindowTreeHostX11::Restore() {
- should_maximize_after_map_ = false;
- SetWMSpecState(false, gfx::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT"),
- gfx::GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ"));
+ x11_window_->Unmaximize();
Show(ui::SHOW_STATE_NORMAL, gfx::Rect());
- SetWMSpecState(false, gfx::GetAtom("_NET_WM_STATE_HIDDEN"), x11::None);
+ x11_window_->Unhide();
}
bool DesktopWindowTreeHostX11::IsMaximized() const {
- return (ui::HasWMSpecProperty(window_properties_,
- gfx::GetAtom("_NET_WM_STATE_MAXIMIZED_VERT")) &&
- ui::HasWMSpecProperty(window_properties_,
- gfx::GetAtom("_NET_WM_STATE_MAXIMIZED_HORZ")));
+ return x11_window_->IsMaximized();
}
bool DesktopWindowTreeHostX11::IsMinimized() const {
- return ui::HasWMSpecProperty(window_properties_,
- gfx::GetAtom("_NET_WM_STATE_HIDDEN"));
+ return x11_window_->IsMinimized();
}
bool DesktopWindowTreeHostX11::HasCapture() const {
return g_current_capture == this;
}
-void DesktopWindowTreeHostX11::SetAlwaysOnTop(bool always_on_top) {
- is_always_on_top_ = always_on_top;
- SetWMSpecState(always_on_top, gfx::GetAtom("_NET_WM_STATE_ABOVE"), x11::None);
+void DesktopWindowTreeHostX11::SetZOrderLevel(ui::ZOrderLevel order) {
+ z_order_ = order;
+
+ // Emulate the multiple window levels provided by other platforms by
+ // collapsing the z-order enum into kNormal = normal, everything else = always
+ // on top.
+ x11_window_->SetAlwaysOnTop(order != ui::ZOrderLevel::kNormal);
}
-bool DesktopWindowTreeHostX11::IsAlwaysOnTop() const {
- return is_always_on_top_;
+ui::ZOrderLevel DesktopWindowTreeHostX11::GetZOrderLevel() const {
+ bool window_always_on_top = x11_window_->is_always_on_top();
+ bool level_always_on_top = z_order_ != ui::ZOrderLevel::kNormal;
+
+ if (window_always_on_top == level_always_on_top)
+ return z_order_;
+
+ // If something external has forced a window to be always-on-top, map it to
+ // kFloatingWindow as a reasonable equivalent.
+ return window_always_on_top ? ui::ZOrderLevel::kFloatingWindow
+ : ui::ZOrderLevel::kNormal;
}
void DesktopWindowTreeHostX11::SetVisible(bool visible) {
@@ -904,62 +696,20 @@ void DesktopWindowTreeHostX11::SetVisible(bool visible) {
is_compositor_set_visible_ = visible;
if (compositor())
compositor()->SetVisible(visible);
+
native_widget_delegate_->OnNativeWidgetVisibilityChanged(visible);
}
void DesktopWindowTreeHostX11::SetVisibleOnAllWorkspaces(bool always_visible) {
- SetWMSpecState(always_visible, gfx::GetAtom("_NET_WM_STATE_STICKY"),
- x11::None);
-
- int new_desktop = 0;
- if (always_visible) {
- new_desktop = kAllDesktops;
- } else {
- if (!ui::GetCurrentDesktop(&new_desktop))
- return;
- }
-
- workspace_ = kAllDesktops;
- XEvent xevent;
- memset (&xevent, 0, sizeof (xevent));
- xevent.type = ClientMessage;
- xevent.xclient.window = xwindow_;
- xevent.xclient.message_type = gfx::GetAtom("_NET_WM_DESKTOP");
- xevent.xclient.format = 32;
- xevent.xclient.data.l[0] = new_desktop;
- xevent.xclient.data.l[1] = 0;
- xevent.xclient.data.l[2] = 0;
- xevent.xclient.data.l[3] = 0;
- xevent.xclient.data.l[4] = 0;
- XSendEvent(xdisplay_, x_root_window_, x11::False,
- SubstructureRedirectMask | SubstructureNotifyMask, &xevent);
+ x11_window_->SetVisibleOnAllWorkspaces(always_visible);
}
bool DesktopWindowTreeHostX11::IsVisibleOnAllWorkspaces() const {
- // We don't need a check for _NET_WM_STATE_STICKY because that would specify
- // that the window remain in a fixed position even if the viewport scrolls.
- // This is different from the type of workspace that's associated with
- // _NET_WM_DESKTOP.
- return GetWorkspace() == base::NumberToString(kAllDesktops);
+ return x11_window_->IsVisibleOnAllWorkspaces();
}
bool DesktopWindowTreeHostX11::SetWindowTitle(const base::string16& title) {
- if (window_title_ == title)
- return false;
- window_title_ = title;
- std::string utf8str = base::UTF16ToUTF8(title);
- XChangeProperty(xdisplay_, xwindow_, gfx::GetAtom("_NET_WM_NAME"),
- gfx::GetAtom("UTF8_STRING"), 8, PropModeReplace,
- reinterpret_cast<const unsigned char*>(utf8str.c_str()),
- utf8str.size());
- XTextProperty xtp;
- char* c_utf8_str = const_cast<char*>(utf8str.c_str());
- if (Xutf8TextListToTextProperty(xdisplay_, &c_utf8_str, 1, XUTF8StringStyle,
- &xtp) == x11::Success) {
- XSetWMName(xdisplay_, xwindow_, &xtp);
- XFree(xtp.value);
- }
- return true;
+ return x11_window_->SetTitle(title);
}
void DesktopWindowTreeHostX11::ClearNativeFocus() {
@@ -1005,11 +755,11 @@ NonClientFrameView* DesktopWindowTreeHostX11::CreateNonClientFrameView() {
}
bool DesktopWindowTreeHostX11::ShouldUseNativeFrame() const {
- return use_native_frame_;
+ return x11_window_->use_native_frame();
}
bool DesktopWindowTreeHostX11::ShouldWindowContentsBeTransparent() const {
- return use_argb_visual_;
+ return x11_window_->has_alpha();
}
void DesktopWindowTreeHostX11::FrameTypeChanged() {
@@ -1034,9 +784,10 @@ void DesktopWindowTreeHostX11::FrameTypeChanged() {
void DesktopWindowTreeHostX11::SetFullscreen(bool fullscreen) {
if (is_fullscreen_ == fullscreen)
return;
+
is_fullscreen_ = fullscreen;
if (is_fullscreen_)
- delayed_resize_task_.Cancel();
+ x11_window_->CancelResize();
// Work around a bug where if we try to unfullscreen, metacity immediately
// fullscreens us again. This is a little flickery and not necessary if
@@ -1047,8 +798,9 @@ void DesktopWindowTreeHostX11::SetFullscreen(bool fullscreen) {
if (unmaximize_and_remaximize)
Restore();
- SetWMSpecState(fullscreen, gfx::GetAtom("_NET_WM_STATE_FULLSCREEN"),
- x11::None);
+
+ x11_window_->SetFullscreen(fullscreen);
+
if (unmaximize_and_remaximize)
Maximize();
@@ -1057,20 +809,21 @@ void DesktopWindowTreeHostX11::SetFullscreen(bool fullscreen) {
// - works around Flash content which expects to have the size updated
// synchronously.
// See https://crbug.com/361408
+ gfx::Rect bounds = x11_window_->bounds();
if (fullscreen) {
- restored_bounds_in_pixels_ = bounds_in_pixels_;
- const display::Display display =
- display::Screen::GetScreen()->GetDisplayNearestWindow(window());
- bounds_in_pixels_ = ToPixelRect(display.bounds());
+ display::Screen* screen = display::Screen::GetScreen();
+ const display::Display display = screen->GetDisplayNearestWindow(window());
+ restored_bounds_in_pixels_ = bounds;
+ bounds = ToPixelRect(display.bounds());
} else {
- bounds_in_pixels_ = restored_bounds_in_pixels_;
+ bounds = restored_bounds_in_pixels_;
}
- OnHostMovedInPixels(bounds_in_pixels_.origin());
- OnHostResizedInPixels(bounds_in_pixels_.size());
+ x11_window_->set_bounds(bounds);
+
+ OnHostMovedInPixels(bounds.origin());
+ OnHostResizedInPixels(bounds.size());
- if (ui::HasWMSpecProperty(window_properties_,
- gfx::GetAtom("_NET_WM_STATE_FULLSCREEN")) ==
- fullscreen) {
+ if (x11_window_->IsFullscreen() == fullscreen) {
Relayout();
ResetWindowRegion();
}
@@ -1083,59 +836,16 @@ bool DesktopWindowTreeHostX11::IsFullscreen() const {
}
void DesktopWindowTreeHostX11::SetOpacity(float opacity) {
- // X server opacity is in terms of 32 bit unsigned int space, and counts from
- // the opposite direction.
- // XChangeProperty() expects "cardinality" to be long.
-
- // Scale opacity to [0 .. 255] range.
- unsigned long opacity_8bit =
- static_cast<unsigned long>(opacity * 255.0f) & 0xFF;
- // Use opacity value for all channels.
- const unsigned long channel_multiplier = 0x1010101;
- unsigned long cardinality = opacity_8bit * channel_multiplier;
-
- if (cardinality == 0xffffffff) {
- XDeleteProperty(xdisplay_, xwindow_,
- gfx::GetAtom("_NET_WM_WINDOW_OPACITY"));
- } else {
- XChangeProperty(xdisplay_, xwindow_, gfx::GetAtom("_NET_WM_WINDOW_OPACITY"),
- XA_CARDINAL, 32, PropModeReplace,
- reinterpret_cast<unsigned char*>(&cardinality), 1);
- }
+ x11_window_->SetOpacity(opacity);
}
void DesktopWindowTreeHostX11::SetAspectRatio(const gfx::SizeF& aspect_ratio) {
- XSizeHints size_hints;
- size_hints.flags = 0;
- long supplied_return;
-
- XGetWMNormalHints(xdisplay_, xwindow_, &size_hints, &supplied_return);
- size_hints.flags |= PAspect;
- size_hints.min_aspect.x = size_hints.max_aspect.x = aspect_ratio.width();
- size_hints.min_aspect.y = size_hints.max_aspect.y = aspect_ratio.height();
- XSetWMNormalHints(xdisplay_, xwindow_, &size_hints);
+ x11_window_->SetAspectRatio(aspect_ratio);
}
void DesktopWindowTreeHostX11::SetWindowIcons(
const gfx::ImageSkia& window_icon, const gfx::ImageSkia& app_icon) {
- // TODO(erg): The way we handle icons across different versions of chrome
- // could be substantially improved. The Windows version does its own thing
- // and only sometimes comes down this code path. The icon stuff in
- // ChromeViewsDelegate is hard coded to use HICONs. Likewise, we're hard
- // coded to be given two images instead of an arbitrary collection of images
- // so that we can pass to the WM.
- //
- // All of this could be made much, much better.
- std::vector<unsigned long> data;
-
- if (!window_icon.isNull())
- SerializeImageRepresentation(window_icon.GetRepresentation(1.0f), &data);
-
- if (!app_icon.isNull())
- SerializeImageRepresentation(app_icon.GetRepresentation(1.0f), &data);
-
- if (!data.empty())
- ui::SetAtomArrayProperty(xwindow_, "_NET_WM_ICON", "CARDINAL", data);
+ x11_window_->SetWindowIcons(window_icon, app_icon);
}
void DesktopWindowTreeHostX11::InitModalType(ui::ModalType modal_type) {
@@ -1151,23 +861,7 @@ void DesktopWindowTreeHostX11::InitModalType(ui::ModalType modal_type) {
}
void DesktopWindowTreeHostX11::FlashFrame(bool flash_frame) {
- if (urgency_hint_set_ == flash_frame)
- return;
-
- gfx::XScopedPtr<XWMHints> hints(XGetWMHints(xdisplay_, xwindow_));
- if (!hints) {
- // The window hasn't had its hints set yet.
- hints.reset(XAllocWMHints());
- }
-
- if (flash_frame)
- hints->flags |= XUrgencyHint;
- else
- hints->flags &= ~XUrgencyHint;
-
- XSetWMHints(xdisplay_, xwindow_, hints.get());
-
- urgency_hint_set_ = flash_frame;
+ x11_window_->FlashFrame(flash_frame);
}
bool DesktopWindowTreeHostX11::IsAnimatingClosed() const {
@@ -1176,13 +870,13 @@ bool DesktopWindowTreeHostX11::IsAnimatingClosed() const {
bool DesktopWindowTreeHostX11::IsTranslucentWindowOpacitySupported() const {
// This function may be called before InitX11Window() (which
- // initializes |use_argb_visual_|), so we cannot simply return
- // |use_argb_visual_|.
+ // initializes |visual_has_alpha_|), so we cannot simply return
+ // |visual_has_alpha_|.
return ui::XVisualManager::GetInstance()->ArgbVisualAvailable();
}
void DesktopWindowTreeHostX11::SizeConstraintsChanged() {
- UpdateMinAndMaxSize();
+ x11_window_->UpdateMinAndMaxSize();
}
bool DesktopWindowTreeHostX11::ShouldUpdateWindowTransparency() const {
@@ -1218,7 +912,7 @@ ui::EventSource* DesktopWindowTreeHostX11::GetEventSource() {
}
gfx::AcceleratedWidget DesktopWindowTreeHostX11::GetAcceleratedWidget() {
- return xwindow_;
+ return x11_window_->window();
}
void DesktopWindowTreeHostX11::ShowImpl() {
@@ -1226,69 +920,34 @@ void DesktopWindowTreeHostX11::ShowImpl() {
}
void DesktopWindowTreeHostX11::HideImpl() {
- if (window_mapped_in_client_) {
- XWithdrawWindow(xdisplay_, xwindow_, 0);
- window_mapped_in_client_ = false;
+ if (x11_window_->Hide())
SetVisible(false);
- }
}
gfx::Rect DesktopWindowTreeHostX11::GetBoundsInPixels() const {
- return bounds_in_pixels_;
+ return x11_window_->bounds();
}
void DesktopWindowTreeHostX11::SetBoundsInPixels(
const gfx::Rect& requested_bounds_in_pixel) {
+ gfx::Rect bounds = x11_window_->bounds();
gfx::Rect bounds_in_pixels(requested_bounds_in_pixel.origin(),
AdjustSize(requested_bounds_in_pixel.size()));
- bool origin_changed = bounds_in_pixels_.origin() != bounds_in_pixels.origin();
- bool size_changed = bounds_in_pixels_.size() != bounds_in_pixels.size();
- XWindowChanges changes = {0};
- unsigned value_mask = 0;
+ bool origin_changed = bounds.origin() != bounds_in_pixels.origin();
+ bool size_changed = bounds.size() != bounds_in_pixels.size();
if (size_changed) {
// Only cancel the delayed resize task if we're already about to call
// OnHostResized in this function.
- delayed_resize_task_.Cancel();
-
- // Update the minimum and maximum sizes in case they have changed.
- UpdateMinAndMaxSize();
-
- if (bounds_in_pixels.width() < min_size_in_pixels_.width() ||
- bounds_in_pixels.height() < min_size_in_pixels_.height() ||
- (!max_size_in_pixels_.IsEmpty() &&
- (bounds_in_pixels.width() > max_size_in_pixels_.width() ||
- bounds_in_pixels.height() > max_size_in_pixels_.height()))) {
- gfx::Size size_in_pixels = bounds_in_pixels.size();
- if (!max_size_in_pixels_.IsEmpty())
- size_in_pixels.SetToMin(max_size_in_pixels_);
- size_in_pixels.SetToMax(min_size_in_pixels_);
- bounds_in_pixels.set_size(size_in_pixels);
- }
-
- changes.width = bounds_in_pixels.width();
- changes.height = bounds_in_pixels.height();
- value_mask |= CWHeight | CWWidth;
+ x11_window_->CancelResize();
}
- if (origin_changed) {
- changes.x = bounds_in_pixels.x();
- changes.y = bounds_in_pixels.y();
- value_mask |= CWX | CWY;
- }
- if (value_mask)
- XConfigureWindow(xdisplay_, xwindow_, value_mask, &changes);
-
- // Assume that the resize will go through as requested, which should be the
- // case if we're running without a window manager. If there's a window
- // manager, it can modify or ignore the request, but (per ICCCM) we'll get a
- // (possibly synthetic) ConfigureNotify about the actual size and correct
- // |bounds_in_pixels_| later.
- bounds_in_pixels_ = bounds_in_pixels;
+ x11_window_->SetBounds(bounds_in_pixels);
if (origin_changed)
native_widget_delegate_->AsWidget()->OnNativeWidgetMove();
+
if (size_changed) {
OnHostResizedInPixels(bounds_in_pixels.size());
ResetWindowRegion();
@@ -1296,7 +955,7 @@ void DesktopWindowTreeHostX11::SetBoundsInPixels(
}
gfx::Point DesktopWindowTreeHostX11::GetLocationOnScreenInPixels() const {
- return bounds_in_pixels_.origin();
+ return x11_window_->bounds().origin();
}
void DesktopWindowTreeHostX11::SetCapture() {
@@ -1318,9 +977,7 @@ void DesktopWindowTreeHostX11::SetCapture() {
if (old_capturer)
old_capturer->OnHostLostWindowCapture();
- // If the pointer is already in |xwindow_|, we will not get a crossing event
- // with a mode of NotifyGrab, so we must record the grab state manually.
- has_pointer_grab_ |= !ui::GrabPointer(xwindow_, true, x11::None);
+ x11_window_->GrabPointer();
}
void DesktopWindowTreeHostX11::ReleaseCapture() {
@@ -1329,8 +986,7 @@ void DesktopWindowTreeHostX11::ReleaseCapture() {
// the topmost window underneath the mouse so the capture release being
// asynchronous is likely inconsequential.
g_current_capture = nullptr;
- ui::UngrabPointer();
- has_pointer_grab_ = false;
+ x11_window_->ReleasePointerGrab();
OnHostLostWindowCapture();
}
@@ -1359,14 +1015,12 @@ bool DesktopWindowTreeHostX11::IsKeyLocked(ui::DomCode dom_code) {
}
void DesktopWindowTreeHostX11::SetCursorNative(gfx::NativeCursor cursor) {
- XDefineCursor(xdisplay_, xwindow_, cursor.platform());
+ x11_window_->SetCursor(cursor.platform());
}
void DesktopWindowTreeHostX11::MoveCursorToScreenLocationInPixels(
const gfx::Point& location_in_pixels) {
- XWarpPointer(xdisplay_, x11::None, x_root_window_, 0, 0, 0, 0,
- bounds_in_pixels_.x() + location_in_pixels.x(),
- bounds_in_pixels_.y() + location_in_pixels.y());
+ x11_window_->MoveCursorTo(location_in_pixels);
}
void DesktopWindowTreeHostX11::OnCursorVisibilityChangedNative(bool show) {
@@ -1390,357 +1044,29 @@ void DesktopWindowTreeHostX11::OnDisplayMetricsChanged(
// compositor redraw will be scheduled. This is weird, but works.
// TODO(thomasanderson): Figure out a more direct way of doing
// this.
- RestartDelayedResizeTask();
+ x11_window_->DispatchResize();
}
}
-////////////////////////////////////////////////////////////////////////////////
-// DesktopWindowTreeHostX11, private:
-
-void DesktopWindowTreeHostX11::InitX11Window(
- const Widget::InitParams& params) {
- unsigned long attribute_mask = CWBackPixel | CWBitGravity;
- XSetWindowAttributes swa;
- memset(&swa, 0, sizeof(swa));
- swa.background_pixmap = x11::None;
- swa.bit_gravity = NorthWestGravity;
-
- // Set the background color on startup to make the initial flickering
- // happening between the XWindow is mapped and the first expose event
- // is completely handled less annoying. If possible, we use the content
- // window's background color, otherwise we fallback to white.
- int background_color;
-
- const views::LinuxUI* linux_ui = views::LinuxUI::instance();
- if (linux_ui && content_window()) {
- ui::NativeTheme::ColorId target_color;
- switch (params.type) {
- case Widget::InitParams::TYPE_BUBBLE:
- target_color = ui::NativeTheme::kColorId_BubbleBackground;
- break;
- case Widget::InitParams::TYPE_TOOLTIP:
- target_color = ui::NativeTheme::kColorId_TooltipBackground;
- break;
- default:
- target_color = ui::NativeTheme::kColorId_WindowBackground;
- break;
- }
-
- ui::NativeTheme* theme = linux_ui->GetNativeTheme(content_window());
- background_color = theme->GetSystemColor(target_color);
- } else {
- background_color = WhitePixel(xdisplay_, DefaultScreen(xdisplay_));
- }
- swa.background_pixel = background_color;
-
- XAtom window_type;
- switch (params.type) {
- case Widget::InitParams::TYPE_MENU:
- swa.override_redirect = x11::True;
- window_type = gfx::GetAtom("_NET_WM_WINDOW_TYPE_MENU");
- break;
- case Widget::InitParams::TYPE_TOOLTIP:
- swa.override_redirect = x11::True;
- window_type = gfx::GetAtom("_NET_WM_WINDOW_TYPE_TOOLTIP");
- break;
- case Widget::InitParams::TYPE_POPUP:
- swa.override_redirect = x11::True;
- window_type = gfx::GetAtom("_NET_WM_WINDOW_TYPE_NOTIFICATION");
- break;
- case Widget::InitParams::TYPE_DRAG:
- swa.override_redirect = x11::True;
- window_type = gfx::GetAtom("_NET_WM_WINDOW_TYPE_DND");
- break;
- default:
- window_type = gfx::GetAtom("_NET_WM_WINDOW_TYPE_NORMAL");
- break;
- }
- // An in-activatable window should not interact with the system wm.
- if (!activatable_)
- swa.override_redirect = x11::True;
-
- override_redirect_ = swa.override_redirect == x11::True;
- if (override_redirect_)
- attribute_mask |= CWOverrideRedirect;
+void DesktopWindowTreeHostX11::OnXWindowCreated() {
+ if (auto* source = ui::PlatformEventSource::GetInstance())
+ source->AddPlatformEventDispatcher(this);
- bool enable_transparent_visuals;
- switch (params.opacity) {
- case Widget::InitParams::OPAQUE_WINDOW:
- enable_transparent_visuals = false;
- break;
- case Widget::InitParams::TRANSLUCENT_WINDOW:
- enable_transparent_visuals = true;
- break;
- case Widget::InitParams::INFER_OPACITY:
- default:
- enable_transparent_visuals = params.type == Widget::InitParams::TYPE_DRAG;
- }
-
- Visual* visual = CopyFromParent;
- int depth = CopyFromParent;
- Colormap colormap = CopyFromParent;
- ui::XVisualManager::GetInstance()->ChooseVisualForWindow(
- enable_transparent_visuals, &visual, &depth, &colormap,
- &use_argb_visual_);
-
- if (colormap != CopyFromParent) {
- attribute_mask |= CWColormap;
- swa.colormap = colormap;
- }
-
- // x.org will BadMatch if we don't set a border when the depth isn't the
- // same as the parent depth.
- attribute_mask |= CWBorderPixel;
- swa.border_pixel = 0;
-
- bounds_in_pixels_ = ToPixelRect(params.bounds);
- bounds_in_pixels_.set_size(AdjustSize(bounds_in_pixels_.size()));
- xwindow_ = XCreateWindow(xdisplay_, x_root_window_, bounds_in_pixels_.x(),
- bounds_in_pixels_.y(), bounds_in_pixels_.width(),
- bounds_in_pixels_.height(),
- 0, // border width
- depth, InputOutput, visual, attribute_mask, &swa);
- if (ui::PlatformEventSource::GetInstance())
- ui::PlatformEventSource::GetInstance()->AddPlatformEventDispatcher(this);
- open_windows().push_front(xwindow_);
-
- // TODO(erg): Maybe need to set a ViewProp here like in RWHL::RWHL().
-
- long event_mask = ButtonPressMask | ButtonReleaseMask | FocusChangeMask |
- KeyPressMask | KeyReleaseMask |
- EnterWindowMask | LeaveWindowMask |
- ExposureMask | VisibilityChangeMask |
- StructureNotifyMask | PropertyChangeMask |
- PointerMotionMask;
- xwindow_events_ =
- std::make_unique<ui::XScopedEventSelector>(xwindow_, event_mask);
- XFlush(xdisplay_);
-
- if (ui::IsXInput2Available())
- ui::TouchFactory::GetInstance()->SetupXI2ForXWindow(xwindow_);
-
- // TODO(erg): We currently only request window deletion events. We also
- // should listen for activation events and anything else that GTK+ listens
- // for, and do something useful.
- // Request the _NET_WM_SYNC_REQUEST protocol which is used for synchronizing
- // between chrome and desktop compositor (or WM) during resizing.
- // The resizing behavior with _NET_WM_SYNC_REQUEST is:
- // 1. Desktop compositor (or WM) sends client message _NET_WM_SYNC_REQUEST
- // with a 64 bits counter to notify about an incoming resize.
- // 2. Desktop compositor resizes chrome browser window.
- // 3. Desktop compositor waits on an alert on value change of XSyncCounter on
- // chrome window.
- // 4. Chrome handles the ConfigureNotify event, and renders a new frame with
- // the new size.
- // 5. Chrome increases the XSyncCounter on chrome window
- // 6. Desktop compositor gets the alert of counter change, and draws a new
- // frame with new content from chrome.
- // 7. Desktop compositor responses user mouse move events, and starts a new
- // resize process, go to step 1.
- XAtom protocols[] = {
- gfx::GetAtom("WM_DELETE_WINDOW"),
- gfx::GetAtom("_NET_WM_PING"),
- gfx::GetAtom("_NET_WM_SYNC_REQUEST"),
- };
- XSetWMProtocols(xdisplay_, xwindow_, protocols, base::size(protocols));
-
- // We need a WM_CLIENT_MACHINE and WM_LOCALE_NAME value so we integrate with
- // the desktop environment.
- XSetWMProperties(xdisplay_, xwindow_, nullptr, nullptr, nullptr, 0, nullptr,
- nullptr, nullptr);
-
- // Likewise, the X server needs to know this window's pid so it knows which
- // program to kill if the window hangs.
- // XChangeProperty() expects "pid" to be long.
- static_assert(sizeof(long) >= sizeof(pid_t),
- "pid_t should not be larger than long");
- long pid = getpid();
- XChangeProperty(xdisplay_, xwindow_, gfx::GetAtom("_NET_WM_PID"), XA_CARDINAL,
- 32, PropModeReplace, reinterpret_cast<unsigned char*>(&pid),
- 1);
-
- XChangeProperty(xdisplay_, xwindow_, gfx::GetAtom("_NET_WM_WINDOW_TYPE"),
- XA_ATOM, 32, PropModeReplace,
- reinterpret_cast<unsigned char*>(&window_type), 1);
-
- // The changes to |window_properties_| here will be sent to the X server just
- // before the window is mapped.
-
- // Remove popup windows from taskbar unless overridden.
- if ((params.type == Widget::InitParams::TYPE_POPUP ||
- params.type == Widget::InitParams::TYPE_BUBBLE) &&
- !params.force_show_in_taskbar) {
- window_properties_.insert(gfx::GetAtom("_NET_WM_STATE_SKIP_TASKBAR"));
- }
-
- // If the window should stay on top of other windows, add the
- // _NET_WM_STATE_ABOVE property.
- is_always_on_top_ = params.keep_on_top;
- if (is_always_on_top_)
- window_properties_.insert(gfx::GetAtom("_NET_WM_STATE_ABOVE"));
-
- workspace_ = base::nullopt;
- if (params.visible_on_all_workspaces) {
- window_properties_.insert(gfx::GetAtom("_NET_WM_STATE_STICKY"));
- ui::SetIntProperty(xwindow_, "_NET_WM_DESKTOP", "CARDINAL", kAllDesktops);
- } else if (!params.workspace.empty()) {
- int workspace;
- if (base::StringToInt(params.workspace, &workspace))
- ui::SetIntProperty(xwindow_, "_NET_WM_DESKTOP", "CARDINAL", workspace);
- }
-
- if (!params.wm_class_name.empty() || !params.wm_class_class.empty()) {
- ui::SetWindowClassHint(
- xdisplay_, xwindow_, params.wm_class_name, params.wm_class_class);
- }
-
- const char* wm_role_name = nullptr;
- // If the widget isn't overriding the role, provide a default value for popup
- // and bubble types.
- if (!params.wm_role_name.empty()) {
- wm_role_name = params.wm_role_name.c_str();
- } else {
- switch (params.type) {
- case Widget::InitParams::TYPE_POPUP:
- wm_role_name = kX11WindowRolePopup;
- break;
- case Widget::InitParams::TYPE_BUBBLE:
- wm_role_name = kX11WindowRoleBubble;
- break;
- default:
- break;
- }
- }
- if (wm_role_name)
- ui::SetWindowRole(xdisplay_, xwindow_, std::string(wm_role_name));
-
- if (params.remove_standard_frame) {
- // Setting _GTK_HIDE_TITLEBAR_WHEN_MAXIMIZED tells gnome-shell to not force
- // fullscreen on the window when it matches the desktop size.
- ui::SetHideTitlebarWhenMaximizedProperty(xwindow_,
- ui::HIDE_TITLEBAR_WHEN_MAXIMIZED);
- }
-
- if (views::LinuxUI::instance() &&
- views::LinuxUI::instance()->PreferDarkTheme()) {
- const unsigned char kDarkGtkThemeVariant[] = "dark";
- XChangeProperty(xdisplay_, xwindow_, gfx::GetAtom("_GTK_THEME_VARIANT"),
- gfx::GetAtom("UTF8_STRING"), 8, PropModeReplace,
- kDarkGtkThemeVariant, base::size(kDarkGtkThemeVariant) - 1);
- }
-
- if (ui::IsSyncExtensionAvailable()) {
- XSyncValue value;
- XSyncIntToValue(&value, 0);
- update_counter_ = XSyncCreateCounter(xdisplay_, value);
- extended_update_counter_ = XSyncCreateCounter(xdisplay_, value);
- XID counters[2] = {
- update_counter_,
- extended_update_counter_,
- };
-
- // Set XSyncCounter as window property _NET_WM_SYNC_REQUEST_COUNTER. the
- // compositor will listen on them during resizing.
- XChangeProperty(
- xdisplay_, xwindow_, gfx::GetAtom("_NET_WM_SYNC_REQUEST_COUNTER"),
- XA_CARDINAL, 32, PropModeReplace,
- reinterpret_cast<const unsigned char*>(counters), base::size(counters));
- }
-
- // Always composite Chromium windows if a compositing WM is used. Sometimes,
- // WMs will not composite fullscreen windows as an optimization, but this can
- // lead to tearing of fullscreen videos.
- ui::SetIntProperty(xwindow_, "_NET_WM_BYPASS_COMPOSITOR", "CARDINAL", 2);
-
- // If we have a parent, record the parent/child relationship. We use this
- // data during destruction to make sure that when we try to close a parent
- // window, we also destroy all child windows.
- if (params.parent && params.parent->GetHost()) {
- XID parent_xid =
- params.parent->GetHost()->GetAcceleratedWidget();
- window_parent_ = GetHostForXID(parent_xid);
- DCHECK(window_parent_);
- window_parent_->window_children_.insert(this);
- }
-
- // If we have a delegate which is providing a default window icon, use that
- // icon.
- gfx::ImageSkia* window_icon =
- ViewsDelegate::GetInstance()->GetDefaultWindowIcon();
- if (window_icon) {
- SetWindowIcons(gfx::ImageSkia(), *window_icon);
- }
- // Disable compositing on tooltips as a workaround for
- // https://crbug.com/442111.
- CreateCompositor(viz::FrameSinkId(),
- params.type == Widget::InitParams::TYPE_TOOLTIP);
-
- if (ui::IsSyncExtensionAvailable()) {
- compositor_observer_ = std::make_unique<SwapWithNewSizeObserverHelper>(
- compositor(), base::BindRepeating(
- &DesktopWindowTreeHostX11::OnCompleteSwapWithNewSize,
- base::Unretained(this)));
- }
- OnAcceleratedWidgetAvailable();
+ open_windows().push_front(x11_window_->window());
}
-gfx::Size DesktopWindowTreeHostX11::AdjustSize(
- const gfx::Size& requested_size_in_pixels) {
- std::vector<display::Display> displays =
- display::Screen::GetScreen()->GetAllDisplays();
- // Compare against all monitor sizes. The window manager can move the window
- // to whichever monitor it wants.
- for (const auto& display : displays) {
- if (requested_size_in_pixels == display.GetSizeInPixel()) {
- return gfx::Size(requested_size_in_pixels.width() - 1,
- requested_size_in_pixels.height() - 1);
- }
- }
-
- // Do not request a 0x0 window size. It causes an XError.
- gfx::Size size_in_pixels = requested_size_in_pixels;
- size_in_pixels.SetToMax(gfx::Size(1, 1));
- return size_in_pixels;
-}
-
-void DesktopWindowTreeHostX11::SetWMSpecState(bool enabled,
- XAtom state1,
- XAtom state2) {
- if (window_mapped_in_client_) {
- ui::SetWMSpecState(xwindow_, enabled, state1, state2);
- } else {
- // The updated state will be set when the window is (re)mapped.
- base::flat_set<XAtom> new_window_properties = window_properties_;
- for (XAtom atom : {state1, state2}) {
- if (enabled)
- new_window_properties.insert(atom);
- else
- new_window_properties.erase(atom);
- }
- UpdateWindowProperties(new_window_properties);
- }
+void DesktopWindowTreeHostX11::OnXWindowMapped() {
+ for (DesktopWindowTreeHostObserverX11& observer : observer_list_)
+ observer.OnWindowMapped(x11_window_->window());
}
-void DesktopWindowTreeHostX11::OnWMStateUpdated() {
- // The EWMH spec requires window managers to remove the _NET_WM_STATE property
- // when a window is unmapped. However, Chromium code wants the state to
- // persist across a Hide() and Show(). So if the window is currently
- // unmapped, leave the state unchanged so it will be restored when the window
- // is remapped.
- std::vector<XAtom> atom_list;
- if (ui::GetAtomArrayProperty(xwindow_, "_NET_WM_STATE", &atom_list) ||
- window_mapped_in_client_) {
- UpdateWindowProperties(
- base::flat_set<XAtom>(std::begin(atom_list), std::end(atom_list)));
- }
+void DesktopWindowTreeHostX11::OnXWindowUnmapped() {
+ for (DesktopWindowTreeHostObserverX11& observer : observer_list_)
+ observer.OnWindowUnmapped(x11_window_->window());
}
-void DesktopWindowTreeHostX11::UpdateWindowProperties(
- const base::flat_set<XAtom>& new_window_properties) {
- bool was_minimized = IsMinimized();
-
- window_properties_ = new_window_properties;
-
+void DesktopWindowTreeHostX11::OnXWindowStateChanged() {
+ bool was_minimized = x11_window_->was_minimized();
bool is_minimized = IsMinimized();
// Propagate the window minimization information to the content window, so
@@ -1772,7 +1098,7 @@ void DesktopWindowTreeHostX11::UpdateWindowProperties(
// a best effort attempt to get restored bounds by setting it to our
// previously set bounds (and if we get this wrong, we aren't any worse
// off since we'd otherwise be returning our maximized bounds).
- restored_bounds_in_pixels_ = previous_bounds_in_pixels_;
+ restored_bounds_in_pixels_ = x11_window_->previous_bounds();
}
} else if (!IsMaximized() && !IsFullscreen()) {
// If we have restored bounds, but WM_STATE no longer claims to be
@@ -1780,14 +1106,6 @@ void DesktopWindowTreeHostX11::UpdateWindowProperties(
restored_bounds_in_pixels_ = gfx::Rect();
}
- // Ignore requests by the window manager to enter or exit fullscreen (e.g. as
- // a result of pressing a window manager accelerator key). Chrome does not
- // handle window manager initiated fullscreen. In particular, Chrome needs to
- // do preprocessing before the x window's fullscreen state is toggled.
-
- is_always_on_top_ = ui::HasWMSpecProperty(
- window_properties_, gfx::GetAtom("_NET_WM_STATE_ABOVE"));
-
// 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.)
@@ -1795,75 +1113,212 @@ void DesktopWindowTreeHostX11::UpdateWindowProperties(
ResetWindowRegion();
}
-void DesktopWindowTreeHostX11::OnFrameExtentsUpdated() {
- std::vector<int> insets;
- if (ui::GetIntArrayProperty(xwindow_, "_NET_FRAME_EXTENTS", &insets) &&
- insets.size() == 4) {
- // |insets| are returned in the order: [left, right, top, bottom].
- native_window_frame_borders_in_pixels_ =
- gfx::Insets(insets[2], insets[0], insets[3], insets[1]);
- } else {
- native_window_frame_borders_in_pixels_ = gfx::Insets();
- }
+void DesktopWindowTreeHostX11::OnXWindowWorkspaceChanged() {
+ OnHostWorkspaceChanged();
}
-void DesktopWindowTreeHostX11::UpdateMinAndMaxSize() {
- gfx::Size minimum_in_pixels =
- ToPixelRect(gfx::Rect(native_widget_delegate_->GetMinimumSize())).size();
- gfx::Size maximum_in_pixels =
- ToPixelRect(gfx::Rect(native_widget_delegate_->GetMaximumSize())).size();
- if (min_size_in_pixels_ == minimum_in_pixels &&
- max_size_in_pixels_ == maximum_in_pixels)
- return;
+void DesktopWindowTreeHostX11::OnXWindowDamageEvent(
+ const gfx::Rect& damage_rect_in_pixels) {
+ compositor()->ScheduleRedrawRect(damage_rect_in_pixels);
+}
+
+void DesktopWindowTreeHostX11::OnXWindowKeyEvent(ui::KeyEvent* key_event) {
+ DispatchKeyEvent(key_event);
+}
- min_size_in_pixels_ = minimum_in_pixels;
- max_size_in_pixels_ = maximum_in_pixels;
+void DesktopWindowTreeHostX11::OnXWindowMouseEvent(ui::MouseEvent* mouseev) {
+ DispatchMouseEvent(mouseev);
+}
- XSizeHints hints;
- hints.flags = 0;
- long supplied_return;
- XGetWMNormalHints(xdisplay_, xwindow_, &hints, &supplied_return);
+void DesktopWindowTreeHostX11::OnXWindowTouchEvent(
+ ui::TouchEvent* touch_event) {
+ DispatchTouchEvent(touch_event);
+}
- if (minimum_in_pixels.IsEmpty()) {
- hints.flags &= ~PMinSize;
- } else {
- hints.flags |= PMinSize;
- hints.min_width = min_size_in_pixels_.width();
- hints.min_height = min_size_in_pixels_.height();
+void DesktopWindowTreeHostX11::OnXWindowScrollEvent(
+ ui::ScrollEvent* scroll_event) {
+ SendEventToSink(scroll_event);
+}
+
+void DesktopWindowTreeHostX11::OnXWindowSelectionEvent(XEvent* xev) {
+ DCHECK(xev);
+ DCHECK(drag_drop_client_);
+ drag_drop_client_->OnSelectionNotify(xev->xselection);
+}
+
+void DesktopWindowTreeHostX11::OnXWindowDragDropEvent(XEvent* xev) {
+ DCHECK(xev);
+ DCHECK(drag_drop_client_);
+
+ ::Atom message_type = xev->xclient.message_type;
+ if (message_type == gfx::GetAtom("XdndEnter")) {
+ drag_drop_client_->OnXdndEnter(xev->xclient);
+ } else if (message_type == gfx::GetAtom("XdndLeave")) {
+ drag_drop_client_->OnXdndLeave(xev->xclient);
+ } else if (message_type == gfx::GetAtom("XdndPosition")) {
+ drag_drop_client_->OnXdndPosition(xev->xclient);
+ } else if (message_type == gfx::GetAtom("XdndStatus")) {
+ drag_drop_client_->OnXdndStatus(xev->xclient);
+ } else if (message_type == gfx::GetAtom("XdndFinished")) {
+ drag_drop_client_->OnXdndFinished(xev->xclient);
+ } else if (message_type == gfx::GetAtom("XdndDrop")) {
+ drag_drop_client_->OnXdndDrop(xev->xclient);
}
+}
- if (maximum_in_pixels.IsEmpty()) {
- hints.flags &= ~PMaxSize;
- } else {
- hints.flags |= PMaxSize;
- hints.max_width = max_size_in_pixels_.width();
- hints.max_height = max_size_in_pixels_.height();
+void DesktopWindowTreeHostX11::OnXWindowRawKeyEvent(XEvent* xev) {
+ switch (xev->type) {
+ case KeyPress:
+ if (!ShouldDiscardKeyEvent(xev)) {
+ ui::KeyEvent keydown_event(xev);
+ DispatchKeyEvent(&keydown_event);
+ }
+ break;
+ case KeyRelease:
+
+ // There is no way to deactivate a window in X11 so ignore input if
+ // window is supposed to be 'inactive'.
+ if (!IsActive() && !HasCapture())
+ break;
+
+ if (!ShouldDiscardKeyEvent(xev)) {
+ ui::KeyEvent keyup_event(xev);
+ DispatchKeyEvent(&keyup_event);
+ }
+ break;
+ default:
+ NOTREACHED() << xev->type;
+ break;
}
+}
- XSetWMNormalHints(xdisplay_, xwindow_, &hints);
+void DesktopWindowTreeHostX11::OnXWindowChildCrossingEvent(XEvent* xev) {
+ DCHECK(xev);
+ ui::MouseEvent mouse_event(xev);
+ DispatchMouseEvent(&mouse_event);
}
-void DesktopWindowTreeHostX11::UpdateWMUserTime(
- const ui::PlatformEvent& event) {
- if (!IsActive())
- return;
+void DesktopWindowTreeHostX11::OnXWindowSizeChanged(
+ const gfx::Size& size_in_pixels) {
+ OnHostResizedInPixels(size_in_pixels);
+ ResetWindowRegion();
+}
+
+void DesktopWindowTreeHostX11::OnXWindowCloseRequested() {
+ OnHostCloseRequested();
+}
+
+void DesktopWindowTreeHostX11::OnXWindowMoved(const gfx::Point& window_origin) {
+ OnHostMovedInPixels(window_origin);
+}
+
+void DesktopWindowTreeHostX11::OnXWindowLostPointerGrab() {
+ dispatcher()->OnHostLostMouseGrab();
+}
+
+void DesktopWindowTreeHostX11::OnXWindowLostCapture() {
+ OnHostLostWindowCapture();
+}
+
+void DesktopWindowTreeHostX11::OnXWindowIsActiveChanged(bool active) {
+ if (active) {
+ // TODO(thomasanderson): Remove this window shuffling and use XWindowCache
+ // instead.
+ ::Window xwindow = x11_window_->window();
+ open_windows().remove(xwindow);
+ open_windows().insert(open_windows().begin(), xwindow);
+ }
+ desktop_native_widget_aura_->HandleActivationChanged(active);
+ native_widget_delegate_->AsWidget()->GetRootView()->SchedulePaint();
+}
+
+gfx::Size DesktopWindowTreeHostX11::GetMinimumSizeForXWindow() {
+ return ToPixelRect(gfx::Rect(native_widget_delegate_->GetMinimumSize()))
+ .size();
+}
+
+gfx::Size DesktopWindowTreeHostX11::GetMaximumSizeForXWindow() {
+ return ToPixelRect(gfx::Rect(native_widget_delegate_->GetMaximumSize()))
+ .size();
+}
+
+////////////////////////////////////////////////////////////////////////////////
+// DesktopWindowTreeHostX11, private:
+
+void DesktopWindowTreeHostX11::InitX11Window(const Widget::InitParams& params) {
+ // Calculate initial bounds
+ gfx::Rect bounds_in_pixels = ToPixelRect(params.bounds);
+ gfx::Size adjusted_size = AdjustSize(bounds_in_pixels.size());
+ bounds_in_pixels.set_size(adjusted_size);
+
+ // Set the background color on startup to make the initial flickering
+ // happening between the XWindow is mapped and the first expose event
+ // is completely handled less annoying. If possible, we use the content
+ // window's background color, otherwise we fallback to white.
+ base::Optional<int> background_color;
+ const views::LinuxUI* linux_ui = views::LinuxUI::instance();
+ if (linux_ui && content_window()) {
+ ui::NativeTheme::ColorId target_color;
+ switch (params.type) {
+ case Widget::InitParams::TYPE_BUBBLE:
+ target_color = ui::NativeTheme::kColorId_BubbleBackground;
+ break;
+ case Widget::InitParams::TYPE_TOOLTIP:
+ target_color = ui::NativeTheme::kColorId_TooltipBackground;
+ break;
+ default:
+ target_color = ui::NativeTheme::kColorId_WindowBackground;
+ break;
+ }
+ ui::NativeTheme* theme = linux_ui->GetNativeTheme(content_window());
+ background_color = theme->GetSystemColor(target_color);
+ }
+
+ // Create window configuration and initialize it
+ ui::XWindow::Configuration config =
+ ConvertInitParamsToX11WindowConfig(params);
+ config.bounds = bounds_in_pixels;
+ config.background_color = background_color;
+ config.prefer_dark_theme = linux_ui && linux_ui->PreferDarkTheme();
+ config.icon = ViewsDelegate::GetInstance()->GetDefaultWindowIcon();
+ x11_window_->Init(config);
+
+ // Disable compositing on tooltips as a workaround for
+ // https://crbug.com/442111.
+ CreateCompositor(viz::FrameSinkId(),
+ params.force_software_compositing ||
+ params.type == Widget::InitParams::TYPE_TOOLTIP);
+
+ if (ui::IsSyncExtensionAvailable()) {
+ compositor_observer_ = std::make_unique<SwapWithNewSizeObserverHelper>(
+ compositor(), base::BindRepeating(
+ &DesktopWindowTreeHostX11::OnCompleteSwapWithNewSize,
+ base::Unretained(this)));
+ }
+ OnAcceleratedWidgetAvailable();
+}
- ui::EventType type = ui::EventTypeFromNative(event);
- if (type == ui::ET_MOUSE_PRESSED ||
- type == ui::ET_KEY_PRESSED ||
- type == ui::ET_TOUCH_PRESSED) {
- unsigned long wm_user_time_ms = static_cast<unsigned long>(
- (ui::EventTimeFromNative(event) - base::TimeTicks()).InMilliseconds());
- XChangeProperty(xdisplay_, xwindow_, gfx::GetAtom("_NET_WM_USER_TIME"),
- XA_CARDINAL, 32, PropModeReplace,
- reinterpret_cast<const unsigned char*>(&wm_user_time_ms),
- 1);
+gfx::Size DesktopWindowTreeHostX11::AdjustSize(
+ const gfx::Size& requested_size_in_pixels) {
+ std::vector<display::Display> displays =
+ display::Screen::GetScreen()->GetAllDisplays();
+ // Compare against all monitor sizes. The window manager can move the window
+ // to whichever monitor it wants.
+ for (const auto& display : displays) {
+ if (requested_size_in_pixels == display.GetSizeInPixel()) {
+ return gfx::Size(requested_size_in_pixels.width() - 1,
+ requested_size_in_pixels.height() - 1);
+ }
}
+
+ // Do not request a 0x0 window size. It causes an XError.
+ gfx::Size size_in_pixels = requested_size_in_pixels;
+ size_in_pixels.SetToMax(gfx::Size(1, 1));
+ return size_in_pixels;
}
void DesktopWindowTreeHostX11::SetUseNativeFrame(bool use_native_frame) {
- use_native_frame_ = use_native_frame;
- ui::SetUseOSWindowFrame(xwindow_, use_native_frame);
+ x11_window_->SetUseNativeFrame(use_native_frame);
ResetWindowRegion();
}
@@ -1934,71 +1389,23 @@ void DesktopWindowTreeHostX11::DispatchKeyEvent(ui::KeyEvent* event) {
}
void DesktopWindowTreeHostX11::ResetWindowRegion() {
- // If a custom window shape was supplied then apply it.
- if (custom_window_shape_) {
- XShapeCombineRegion(xdisplay_, xwindow_, ShapeBounding, 0, 0,
- window_shape_.get(), false);
- return;
- }
-
- window_shape_.reset();
-
- if (!IsMaximized() && !IsFullscreen()) {
+ _XRegion* xregion = nullptr;
+ if (!x11_window_->use_custom_shape() && !IsMaximized() && !IsFullscreen()) {
SkPath window_mask;
Widget* widget = native_widget_delegate_->AsWidget();
if (widget->non_client_view()) {
// Some frame views define a custom (non-rectangular) window mask. If
// so, use it to define the window shape. If not, fall through.
- widget->non_client_view()->GetWindowMask(bounds_in_pixels_.size(),
+ widget->non_client_view()->GetWindowMask(x11_window_->bounds().size(),
&window_mask);
if (window_mask.countPoints() > 0) {
- window_shape_.reset(gfx::CreateRegionFromSkPath(window_mask));
- XShapeCombineRegion(xdisplay_, xwindow_, ShapeBounding, 0, 0,
- window_shape_.get(), false);
- return;
+ xregion = gfx::CreateRegionFromSkPath(window_mask);
}
}
}
-
- // If we didn't set the shape for any reason, reset the shaping information.
- // How this is done depends on the border style, due to quirks and bugs in
- // various window managers.
- if (ShouldUseNativeFrame()) {
- // If the window has system borders, the mask must be set to null (not a
- // rectangle), because several window managers (eg, KDE, XFCE, XMonad) will
- // not put borders on a window with a custom shape.
- XShapeCombineMask(xdisplay_, xwindow_, ShapeBounding, 0, 0, x11::None,
- ShapeSet);
- } else {
- // Conversely, if the window does not have system borders, the mask must be
- // manually set to a rectangle that covers the whole window (not null). This
- // is due to a bug in KWin <= 4.11.5 (KDE bug #330573) where setting a null
- // shape causes the hint to disable system borders to be ignored (resulting
- // in a double border).
- XRectangle r = {0,
- 0,
- static_cast<unsigned short>(bounds_in_pixels_.width()),
- static_cast<unsigned short>(bounds_in_pixels_.height())};
- XShapeCombineRectangles(
- xdisplay_, xwindow_, ShapeBounding, 0, 0, &r, 1, ShapeSet, YXBanded);
- }
+ x11_window_->UpdateWindowRegion(xregion);
}
-void DesktopWindowTreeHostX11::SerializeImageRepresentation(
- const gfx::ImageSkiaRep& rep,
- std::vector<unsigned long>* data) {
- int width = rep.GetWidth();
- data->push_back(width);
-
- int height = rep.GetHeight();
- data->push_back(height);
-
- const SkBitmap& bitmap = rep.GetBitmap();
-
- for (int y = 0; y < height; ++y)
- for (int x = 0; x < width; ++x)
- data->push_back(bitmap.getColor(x, y));
-}
std::list<XID>& DesktopWindowTreeHostX11::open_windows() {
if (!open_windows_)
@@ -2015,51 +1422,20 @@ void DesktopWindowTreeHostX11::MapWindow(ui::WindowShowState show_state) {
NOTIMPLEMENTED_LOG_ONCE();
}
- // Before we map the window, set size hints. Otherwise, some window managers
- // will ignore toplevel XMoveWindow commands.
- XSizeHints size_hints;
- size_hints.flags = 0;
- long supplied_return;
- XGetWMNormalHints(xdisplay_, xwindow_, &size_hints, &supplied_return);
- size_hints.flags |= PPosition;
- size_hints.x = bounds_in_pixels_.x();
- size_hints.y = bounds_in_pixels_.y();
- XSetWMNormalHints(xdisplay_, xwindow_, &size_hints);
-
// If SHOW_STATE_INACTIVE, tell the window manager not to focus the window
// when mapping. This is done by setting the _NET_WM_USER_TIME to 0. See e.g.
// http://standards.freedesktop.org/wm-spec/latest/ar01s05.html
- ignore_keyboard_input_ = show_state == ui::SHOW_STATE_INACTIVE;
- unsigned long wm_user_time_ms =
- ignore_keyboard_input_
- ? 0
- : ui::X11EventSource::GetInstance()->GetTimestamp();
- if (show_state == ui::SHOW_STATE_INACTIVE || wm_user_time_ms != 0) {
- XChangeProperty(xdisplay_, xwindow_, gfx::GetAtom("_NET_WM_USER_TIME"),
- XA_CARDINAL, 32, PropModeReplace,
- reinterpret_cast<const unsigned char*>(&wm_user_time_ms),
- 1);
- }
-
- UpdateMinAndMaxSize();
+ bool inactive = show_state == ui::SHOW_STATE_INACTIVE;
- if (window_properties_.empty()) {
- XDeleteProperty(xdisplay_, xwindow_, gfx::GetAtom("_NET_WM_STATE"));
- } else {
- ui::SetAtomArrayProperty(xwindow_, "_NET_WM_STATE", "ATOM",
- std::vector<XAtom>(std::begin(window_properties_),
- std::end(window_properties_)));
- }
-
- XMapWindow(xdisplay_, xwindow_);
- window_mapped_in_client_ = true;
+ x11_window_->Map(inactive);
}
void DesktopWindowTreeHostX11::SetWindowTransparency() {
- compositor()->SetBackgroundColor(use_argb_visual_ ? SK_ColorTRANSPARENT
- : SK_ColorWHITE);
- window()->SetTransparent(use_argb_visual_);
- content_window()->SetTransparent(use_argb_visual_);
+ bool has_alpha = x11_window_->has_alpha();
+ compositor()->SetBackgroundColor(has_alpha ? SK_ColorTRANSPARENT
+ : SK_ColorWHITE);
+ window()->SetTransparent(has_alpha);
+ content_window()->SetTransparent(has_alpha);
}
void DesktopWindowTreeHostX11::Relayout() {
@@ -2077,9 +1453,7 @@ void DesktopWindowTreeHostX11::Relayout() {
bool DesktopWindowTreeHostX11::CanDispatchEvent(
const ui::PlatformEvent& event) {
- return event->xany.window == xwindow_ ||
- (event->type == GenericEvent &&
- static_cast<XIDeviceEvent*>(event->xcookie.data)->event == xwindow_);
+ return x11_window_->IsTargetedBy(*event);
}
uint32_t DesktopWindowTreeHostX11::DispatchEvent(
@@ -2089,349 +1463,10 @@ uint32_t DesktopWindowTreeHostX11::DispatchEvent(
TRACE_EVENT1("views", "DesktopWindowTreeHostX11::Dispatch",
"event->type", event->type);
- UpdateWMUserTime(event);
-
- // May want to factor CheckXEventForConsistency(xev); into a common location
- // since it is called here.
- switch (xev->type) {
- case EnterNotify:
- case LeaveNotify: {
- OnCrossingEvent(xev->type == EnterNotify, xev->xcrossing.focus,
- xev->xcrossing.mode, xev->xcrossing.detail);
-
- // Ignore EventNotify and LeaveNotify events from children of |xwindow_|.
- // NativeViewGLSurfaceGLX adds a child to |xwindow_|.
- if (xev->xcrossing.detail != NotifyInferior) {
- ui::MouseEvent mouse_event(xev);
- DispatchMouseEvent(&mouse_event);
- }
- break;
- }
- case Expose: {
- gfx::Rect damage_rect_in_pixels(xev->xexpose.x, xev->xexpose.y,
- xev->xexpose.width, xev->xexpose.height);
- compositor()->ScheduleRedrawRect(damage_rect_in_pixels);
- break;
- }
- case KeyPress: {
- if (ui::AtkUtilAuraLinux::HandleKeyEvent(xev) !=
- ui::DiscardAtkKeyEvent::Discard) {
- ui::KeyEvent keydown_event(xev);
- DispatchKeyEvent(&keydown_event);
- }
- break;
- }
- case KeyRelease: {
- // There is no way to deactivate a window in X11 so ignore input if
- // window is supposed to be 'inactive'.
- if (!IsActive() && !HasCapture())
- break;
-
- if (ui::AtkUtilAuraLinux::HandleKeyEvent(xev) !=
- ui::DiscardAtkKeyEvent::Discard) {
- ui::KeyEvent key_event(xev);
- DispatchKeyEvent(&key_event);
- }
- break;
- }
- case ButtonPress:
- case ButtonRelease: {
- ui::EventType event_type = ui::EventTypeFromNative(xev);
- switch (event_type) {
- case ui::ET_MOUSEWHEEL: {
- ui::MouseWheelEvent mouseev(xev);
- DispatchMouseEvent(&mouseev);
- break;
- }
- case ui::ET_MOUSE_PRESSED:
- case ui::ET_MOUSE_RELEASED: {
- ui::MouseEvent mouseev(xev);
- DispatchMouseEvent(&mouseev);
- break;
- }
- case ui::ET_UNKNOWN:
- // No event is created for X11-release events for mouse-wheel buttons.
- break;
- default:
- NOTREACHED() << event_type;
- }
- break;
- }
- case x11::FocusIn:
- case x11::FocusOut:
- OnFocusEvent(xev->type == x11::FocusIn, event->xfocus.mode,
- event->xfocus.detail);
- break;
- case ConfigureNotify: {
- DCHECK_EQ(xwindow_, xev->xconfigure.window);
- DCHECK_EQ(xwindow_, xev->xconfigure.event);
-
- if (pending_counter_value_) {
- DCHECK(!configure_counter_value_);
- configure_counter_value_ = pending_counter_value_;
- configure_counter_value_is_extended_ =
- pending_counter_value_is_extended_;
- pending_counter_value_is_extended_ = 0;
- pending_counter_value_ = 0;
- }
-
- // It's possible that the X window may be resized by some other means than
- // from within aura (e.g. the X window manager can change the size). Make
- // sure the root window size is maintained properly.
- int translated_x_in_pixels = xev->xconfigure.x;
- int translated_y_in_pixels = xev->xconfigure.y;
- if (!xev->xconfigure.send_event && !xev->xconfigure.override_redirect) {
- Window unused;
- XTranslateCoordinates(xdisplay_, xwindow_, x_root_window_, 0, 0,
- &translated_x_in_pixels, &translated_y_in_pixels,
- &unused);
- }
- gfx::Rect bounds_in_pixels(translated_x_in_pixels, translated_y_in_pixels,
- xev->xconfigure.width, xev->xconfigure.height);
- bool size_changed = bounds_in_pixels_.size() != bounds_in_pixels.size();
- bool origin_changed =
- bounds_in_pixels_.origin() != bounds_in_pixels.origin();
- previous_bounds_in_pixels_ = bounds_in_pixels_;
- bounds_in_pixels_ = bounds_in_pixels;
-
- if (origin_changed)
- OnHostMovedInPixels(bounds_in_pixels_.origin());
-
- if (size_changed)
- RestartDelayedResizeTask();
- break;
- }
- case GenericEvent: {
- ui::TouchFactory* factory = ui::TouchFactory::GetInstance();
- if (!factory->ShouldProcessXI2Event(xev))
- break;
-
- XIEnterEvent* enter_event = static_cast<XIEnterEvent*>(xev->xcookie.data);
- switch (static_cast<XIEvent*>(xev->xcookie.data)->evtype) {
- case XI_Enter:
- case XI_Leave:
- OnCrossingEvent(enter_event->evtype == XI_Enter, enter_event->focus,
- XI2ModeToXMode(enter_event->mode),
- enter_event->detail);
- return ui::POST_DISPATCH_STOP_PROPAGATION;
- case XI_FocusIn:
- case XI_FocusOut:
- OnFocusEvent(enter_event->evtype == XI_FocusIn,
- XI2ModeToXMode(enter_event->mode), enter_event->detail);
- return ui::POST_DISPATCH_STOP_PROPAGATION;
- default:
- break;
- }
-
- ui::EventType type = ui::EventTypeFromNative(xev);
- XEvent last_event;
- int num_coalesced = 0;
-
- switch (type) {
- case ui::ET_TOUCH_MOVED:
- num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event);
- if (num_coalesced > 0)
- xev = &last_event;
- FALLTHROUGH;
- case ui::ET_TOUCH_PRESSED:
- case ui::ET_TOUCH_RELEASED: {
- ui::TouchEvent touchev(xev);
- DispatchTouchEvent(&touchev);
- break;
- }
- case ui::ET_MOUSE_MOVED:
- case ui::ET_MOUSE_DRAGGED:
- case ui::ET_MOUSE_PRESSED:
- case ui::ET_MOUSE_RELEASED:
- case ui::ET_MOUSE_ENTERED:
- case ui::ET_MOUSE_EXITED: {
- if (type == ui::ET_MOUSE_MOVED || type == ui::ET_MOUSE_DRAGGED) {
- // If this is a motion event, we want to coalesce all pending motion
- // events that are at the top of the queue.
- num_coalesced = ui::CoalescePendingMotionEvents(xev, &last_event);
- if (num_coalesced > 0)
- xev = &last_event;
- }
- ui::MouseEvent mouseev(xev);
- // If after CoalescePendingMotionEvents the type of xev is resolved to
- // UNKNOWN, don't dispatch the event.
- // TODO(804418): investigate why ColescePendingMotionEvents can
- // include mouse wheel events as well. Investigation showed that
- // events on Linux are checked with cmt-device path, and can include
- // DT_CMT_SCROLL_ data. See more discussion in
- // https://crrev.com/c/853953
- if (mouseev.type() != ui::ET_UNKNOWN)
- DispatchMouseEvent(&mouseev);
- break;
- }
- case ui::ET_MOUSEWHEEL: {
- ui::MouseWheelEvent mouseev(xev);
- DispatchMouseEvent(&mouseev);
- break;
- }
- case ui::ET_SCROLL_FLING_START:
- case ui::ET_SCROLL_FLING_CANCEL:
- case ui::ET_SCROLL: {
- ui::ScrollEvent scrollev(xev);
- // We need to filter zero scroll offset here. Because
- // MouseWheelEventQueue assumes we'll never get a zero scroll offset
- // event and we need delta to determine which element to scroll on
- // phaseBegan.
- if (scrollev.x_offset() != 0.0 || scrollev.y_offset() != 0.0)
- SendEventToSink(&scrollev);
- break;
- }
- case ui::ET_KEY_PRESSED:
- case ui::ET_KEY_RELEASED: {
- ui::KeyEvent key_event(xev);
- DispatchKeyEvent(&key_event);
- break;
- }
- case ui::ET_UNKNOWN:
- break;
- default:
- NOTREACHED();
- }
-
- // If we coalesced an event we need to free its cookie.
- if (num_coalesced > 0)
- XFreeEventData(xev->xgeneric.display, &last_event.xcookie);
- break;
- }
- case MapNotify: {
- window_mapped_in_server_ = true;
-
- for (DesktopWindowTreeHostObserverX11& observer : observer_list_)
- observer.OnWindowMapped(xwindow_);
-
- // Some WMs only respect maximize hints after the window has been mapped.
- // Check whether we need to re-do a maximization.
- if (should_maximize_after_map_) {
- Maximize();
- should_maximize_after_map_ = false;
- }
-
- break;
- }
- case UnmapNotify: {
- window_mapped_in_server_ = false;
- has_pointer_ = false;
- has_pointer_grab_ = false;
- has_pointer_focus_ = false;
- has_window_focus_ = false;
- for (DesktopWindowTreeHostObserverX11& observer : observer_list_)
- observer.OnWindowUnmapped(xwindow_);
- break;
- }
- case ClientMessage: {
- Atom message_type = xev->xclient.message_type;
- if (message_type == gfx::GetAtom("WM_PROTOCOLS")) {
- Atom protocol = static_cast<Atom>(xev->xclient.data.l[0]);
- if (protocol == gfx::GetAtom("WM_DELETE_WINDOW")) {
- // We have received a close message from the window manager.
- OnHostCloseRequested();
- } else if (protocol == gfx::GetAtom("_NET_WM_PING")) {
- XEvent reply_event = *xev;
- reply_event.xclient.window = x_root_window_;
-
- XSendEvent(xdisplay_, reply_event.xclient.window, x11::False,
- SubstructureRedirectMask | SubstructureNotifyMask,
- &reply_event);
- } else if (protocol == gfx::GetAtom("_NET_WM_SYNC_REQUEST")) {
- pending_counter_value_ =
- xev->xclient.data.l[2] +
- (static_cast<int64_t>(xev->xclient.data.l[3]) << 32);
- pending_counter_value_is_extended_ = xev->xclient.data.l[4] != 0;
- }
- } else if (message_type == gfx::GetAtom("XdndEnter")) {
- drag_drop_client_->OnXdndEnter(xev->xclient);
- } else if (message_type == gfx::GetAtom("XdndLeave")) {
- drag_drop_client_->OnXdndLeave(xev->xclient);
- } else if (message_type == gfx::GetAtom("XdndPosition")) {
- drag_drop_client_->OnXdndPosition(xev->xclient);
- } else if (message_type == gfx::GetAtom("XdndStatus")) {
- drag_drop_client_->OnXdndStatus(xev->xclient);
- } else if (message_type == gfx::GetAtom("XdndFinished")) {
- drag_drop_client_->OnXdndFinished(xev->xclient);
- } else if (message_type == gfx::GetAtom("XdndDrop")) {
- drag_drop_client_->OnXdndDrop(xev->xclient);
- }
- break;
- }
- case MappingNotify: {
- switch (xev->xmapping.request) {
- case MappingModifier:
- case MappingKeyboard:
- XRefreshKeyboardMapping(&xev->xmapping);
- break;
- case MappingPointer:
- ui::DeviceDataManagerX11::GetInstance()->UpdateButtonMap();
- break;
- default:
- NOTIMPLEMENTED() << " Unknown request: " << xev->xmapping.request;
- break;
- }
- break;
- }
- case MotionNotify: {
- // Discard all but the most recent motion event that targets the same
- // window with unchanged state.
- XEvent last_event;
- while (XPending(xev->xany.display)) {
- XEvent next_event;
- XPeekEvent(xev->xany.display, &next_event);
- if (next_event.type == MotionNotify &&
- next_event.xmotion.window == xev->xmotion.window &&
- next_event.xmotion.subwindow == xev->xmotion.subwindow &&
- next_event.xmotion.state == xev->xmotion.state) {
- XNextEvent(xev->xany.display, &last_event);
- xev = &last_event;
- } else {
- break;
- }
- }
-
- ui::MouseEvent mouseev(xev);
- DispatchMouseEvent(&mouseev);
- break;
- }
- case PropertyNotify: {
- XAtom changed_atom = xev->xproperty.atom;
- if (changed_atom == gfx::GetAtom("_NET_WM_STATE")) {
- OnWMStateUpdated();
- } else if (changed_atom == gfx::GetAtom("_NET_FRAME_EXTENTS")) {
- OnFrameExtentsUpdated();
- } else if (changed_atom == gfx::GetAtom("_NET_WM_DESKTOP")) {
- base::Optional<int> old_workspace = workspace_;
- UpdateWorkspace();
- if (workspace_ != old_workspace)
- OnHostWorkspaceChanged();
- }
- break;
- }
- case SelectionNotify: {
- drag_drop_client_->OnSelectionNotify(xev->xselection);
- break;
- }
- }
+ x11_window_->ProcessEvent(xev);
return ui::POST_DISPATCH_STOP_PROPAGATION;
}
-void DesktopWindowTreeHostX11::DelayedResize(const gfx::Size& size_in_pixels) {
- if (configure_counter_value_is_extended_ &&
- (current_counter_value_ % 2) == 0) {
- // Increase the |extended_update_counter_|, so the compositor will know we
- // are not frozen and re-enable _NET_WM_SYNC_REQUEST, if it was disabled.
- // Increase the |extended_update_counter_| to an odd number will not trigger
- // a new resize.
- SyncSetCounter(xdisplay_, extended_update_counter_,
- ++current_counter_value_);
- }
- OnHostResizedInPixels(size_in_pixels);
- ResetWindowRegion();
- delayed_resize_task_.Cancel();
-}
-
void DesktopWindowTreeHostX11::DelayedChangeFrameType(Widget::FrameType type) {
SetUseNativeFrame(type == Widget::FRAME_TYPE_FORCE_NATIVE);
// Replace the frame and layout the contents. Even though we don't have a
@@ -2474,56 +1509,13 @@ void DesktopWindowTreeHostX11::EnableEventListening() {
targeter_for_modal_.reset();
}
-void DesktopWindowTreeHostX11::RestartDelayedResizeTask() {
- if (update_counter_ == x11::None || configure_counter_value_ == 0) {
- // WM doesn't support _NET_WM_SYNC_REQUEST.
- // Or we are too slow, so _NET_WM_SYNC_REQUEST is disabled by the
- // compositor.
- delayed_resize_task_.Reset(base::BindOnce(
- &DesktopWindowTreeHostX11::DelayedResize,
- close_widget_factory_.GetWeakPtr(), bounds_in_pixels_.size()));
- base::ThreadTaskRunnerHandle::Get()->PostTask(
- FROM_HERE, delayed_resize_task_.callback());
- return;
- }
-
- if (configure_counter_value_is_extended_) {
- current_counter_value_ = configure_counter_value_;
- configure_counter_value_ = 0;
- // Make sure the counter is even number.
- if ((current_counter_value_ % 2) == 1)
- ++current_counter_value_;
- }
-
- // If _NET_WM_SYNC_REQUEST is used to synchronize with compositor during
- // resizing, the compositor will not resize the window, until last resize is
- // handled, so we don't need accumulate resize events.
- DelayedResize(bounds_in_pixels_.size());
-}
-
aura::Window* DesktopWindowTreeHostX11::content_window() {
return desktop_native_widget_aura_->content_window();
}
void DesktopWindowTreeHostX11::OnCompleteSwapWithNewSize(
const gfx::Size& size) {
- if (configure_counter_value_is_extended_) {
- if ((current_counter_value_ % 2) == 1) {
- // An increase 3 means that the frame was not drawn as fast as possible.
- // This can trigger different handling from the compositor.
- // Setting an even number to |extended_update_counter_| will trigger a
- // new resize.
- current_counter_value_ += 3;
- SyncSetCounter(xdisplay_, extended_update_counter_,
- current_counter_value_);
- }
- return;
- }
-
- if (configure_counter_value_ != 0) {
- SyncSetCounter(xdisplay_, update_counter_, configure_counter_value_);
- configure_counter_value_ = 0;
- }
+ x11_window_->NotifySwapAfterResize();
}
base::flat_map<std::string, std::string>
@@ -2533,6 +1525,11 @@ DesktopWindowTreeHostX11::GetKeyboardLayoutMap() {
return {};
}
+void DesktopWindowTreeHostX11::SetVisualId(VisualID visual_id) {
+ DCHECK_EQ(x11_window_->window(), x11::None);
+ x11_window_->set_visual_id(visual_id);
+}
+
////////////////////////////////////////////////////////////////////////////////
// DesktopWindowTreeHost, public:
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 92f49c677d6..e32726ad461 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
@@ -8,32 +8,38 @@
#include <stddef.h>
#include <stdint.h>
-#include "base/cancelable_callback.h"
+#include <list>
+#include <memory>
+#include <set>
+#include <string>
+#include <vector>
+
#include "base/containers/flat_set.h"
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
#include "base/observer_list.h"
#include "ui/aura/scoped_window_targeter.h"
#include "ui/aura/window_tree_host.h"
-#include "ui/base/cursor/cursor_loader_x11.h"
+#include "ui/base/x/x11_window.h"
#include "ui/events/platform/platform_event_dispatcher.h"
-#include "ui/gfx/geometry/insets.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/geometry/size.h"
-#include "ui/gfx/x/x11.h"
+#include "ui/gfx/x/x11_types.h"
#include "ui/views/views_export.h"
#include "ui/views/widget/desktop_aura/desktop_window_tree_host.h"
namespace gfx {
class ImageSkia;
-class ImageSkiaRep;
}
namespace ui {
enum class DomCode;
class EventHandler;
class KeyboardHook;
-class XScopedEventSelector;
+class KeyEvent;
+class MouseEvent;
+class TouchEvent;
+class ScrollEvent;
}
namespace views {
@@ -45,7 +51,8 @@ class X11DesktopWindowMoveClient;
class VIEWS_EXPORT DesktopWindowTreeHostX11
: public DesktopWindowTreeHost,
public aura::WindowTreeHost,
- public ui::PlatformEventDispatcher {
+ public ui::PlatformEventDispatcher,
+ public ui::XWindow::Delegate {
public:
DesktopWindowTreeHostX11(
internal::NativeWidgetDelegate* native_widget_delegate,
@@ -91,6 +98,10 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11
// Returns a map of KeyboardEvent code to KeyboardEvent key values.
base::flat_map<std::string, std::string> GetKeyboardLayoutMap() override;
+ // This must be called before the window is created, because the visual cannot
+ // be changed after.
+ void SetVisualId(VisualID visual_id);
+
protected:
// Overridden from DesktopWindowTreeHost:
void Init(const Widget::InitParams& params) override;
@@ -127,8 +138,8 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11
bool IsMaximized() const override;
bool IsMinimized() const override;
bool HasCapture() const override;
- void SetAlwaysOnTop(bool always_on_top) override;
- bool IsAlwaysOnTop() const override;
+ void SetZOrderLevel(ui::ZOrderLevel order) override;
+ ui::ZOrderLevel GetZOrderLevel() const override;
void SetVisibleOnAllWorkspaces(bool always_visible) override;
bool IsVisibleOnAllWorkspaces() const override;
bool SetWindowTitle(const base::string16& title) override;
@@ -182,6 +193,30 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11
void OnDisplayMetricsChanged(const display::Display& display,
uint32_t changed_metrics) override;
+ // Overridden from ui::XWindow::Delegate
+ void OnXWindowCreated() override;
+ void OnXWindowMapped() override;
+ void OnXWindowUnmapped() override;
+ void OnXWindowStateChanged() override;
+ void OnXWindowWorkspaceChanged() override;
+ void OnXWindowKeyEvent(ui::KeyEvent* key_event) override;
+ void OnXWindowMouseEvent(ui::MouseEvent* mouseev) override;
+ void OnXWindowTouchEvent(ui::TouchEvent* touch_event) override;
+ void OnXWindowScrollEvent(ui::ScrollEvent* scroll_event) override;
+ void OnXWindowSelectionEvent(XEvent* xev) override;
+ void OnXWindowDragDropEvent(XEvent* xev) override;
+ void OnXWindowChildCrossingEvent(XEvent* xev) override;
+ void OnXWindowRawKeyEvent(XEvent* xev) override;
+ void OnXWindowSizeChanged(const gfx::Size& size) override;
+ void OnXWindowCloseRequested() override;
+ void OnXWindowMoved(const gfx::Point& window_origin) override;
+ void OnXWindowDamageEvent(const gfx::Rect& damage_rect) override;
+ void OnXWindowLostPointerGrab() override;
+ void OnXWindowLostCapture() override;
+ void OnXWindowIsActiveChanged(bool active) override;
+ gfx::Size GetMinimumSizeForXWindow() override;
+ gfx::Size GetMaximumSizeForXWindow() override;
+
private:
friend class DesktopWindowTreeHostX11HighDPITest;
@@ -198,53 +233,6 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11
// fullscreen.
gfx::Size AdjustSize(const gfx::Size& requested_size);
- // If mapped, sends a message to the window manager to enable or disable the
- // states |state1| and |state2|. Otherwise, the states will be enabled or
- // disabled on the next map. It's the caller's responsibility to make sure
- // atoms are set and unset in the appropriate pairs. For example, if a caller
- // sets (_NET_WM_STATE_MAXIMIZED_VERT, _NET_WM_STATE_MAXIMIZED_HORZ), it would
- // be invalid to unset the maximized state by making two calls like
- // (_NET_WM_STATE_MAXIMIZED_VERT, x11::None), (_NET_WM_STATE_MAXIMIZED_HORZ,
- // x11::None).
- void SetWMSpecState(bool enabled, XAtom state1, XAtom state2);
-
- // Called when |xwindow_|'s _NET_WM_STATE property is updated.
- void OnWMStateUpdated();
-
- // Updates |window_properties_| with |new_window_properties|.
- void UpdateWindowProperties(
- const base::flat_set<XAtom>& new_window_properties);
-
- // Called when |xwindow_|'s _NET_FRAME_EXTENTS property is updated.
- void OnFrameExtentsUpdated();
-
- // Record the activation state.
- void BeforeActivationStateChanged();
-
- // Handle the state change since BeforeActivationStateChanged().
- void AfterActivationStateChanged();
-
- // Called on an XEnterWindowEvent, XLeaveWindowEvent, XIEnterEvent, or an
- // XILeaveEvent.
- void OnCrossingEvent(bool enter,
- bool focus_in_window_or_ancestor,
- int mode,
- int detail);
-
- // Called on an XFocusInEvent, XFocusOutEvent, XIFocusInEvent, or an
- // XIFocusOutEvent.
- void OnFocusEvent(bool focus_in, int mode, int detail);
-
- // Makes a round trip to the X server to get the enclosing workspace for this
- // window.
- void UpdateWorkspace();
-
- // Updates |xwindow_|'s minimum and maximum size.
- void UpdateMinAndMaxSize();
-
- // Updates |xwindow_|'s _NET_WM_USER_TIME if |xwindow_| is active.
- void UpdateWMUserTime(const ui::PlatformEvent& event);
-
// Sets whether the window's borders are provided by the window manager.
void SetUseNativeFrame(bool use_native_frame);
@@ -264,10 +252,6 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11
// Resets the window region for the current widget bounds if necessary.
void ResetWindowRegion();
- // Serializes an image to the format used by _NET_WM_ICON.
- void SerializeImageRepresentation(const gfx::ImageSkiaRep& rep,
- std::vector<unsigned long>* data);
-
// See comment for variable open_windows_.
static std::list<XID>& open_windows();
@@ -283,7 +267,6 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11
bool CanDispatchEvent(const ui::PlatformEvent& event) override;
uint32_t DispatchEvent(const ui::PlatformEvent& event) override;
- void DelayedResize(const gfx::Size& size_in_pixels);
void DelayedChangeFrameType(Widget::FrameType new_type);
gfx::Rect ToDIPRect(const gfx::Rect& rect_in_pixels) const;
@@ -292,10 +275,6 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11
// Enables event listening after closing |dialog|.
void EnableEventListening();
- // Removes |delayed_resize_task_| from the task queue (if it's in
- // the queue) and adds it back at the end of the queue.
- void RestartDelayedResizeTask();
-
// Set visibility and fire OnNativeWidgetVisibilityChanged() if it changed.
void SetVisible(bool visible);
@@ -305,65 +284,15 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11
// Callback for a swapbuffer after resize.
void OnCompleteSwapWithNewSize(const gfx::Size& size);
- // X11 things
- // The display and the native X window hosting the root window.
- XDisplay* xdisplay_;
- ::Window xwindow_ = 0;
-
- // Events selected on |xwindow_|.
- std::unique_ptr<ui::XScopedEventSelector> xwindow_events_;
-
- // The native root window.
- ::Window x_root_window_;
-
- // Whether the window is mapped with respect to the X server.
- bool window_mapped_in_server_ = false;
-
- // Whether the window is visible with respect to Aura.
- bool window_mapped_in_client_ = false;
-
- // The bounds of |xwindow_|.
- gfx::Rect bounds_in_pixels_;
-
- // Whenever the bounds are set, we keep the previous set of bounds around so
- // we can have a better chance of getting the real
- // |restored_bounds_in_pixels_|. Window managers tend to send a Configure
- // message with the maximized bounds, and then set the window maximized
- // property. (We don't rely on this for when we request that the window be
- // maximized, only when we detect that some other process has requested that
- // we become the maximized window.)
- gfx::Rect previous_bounds_in_pixels_;
-
// The bounds of our window before we were maximized.
gfx::Rect restored_bounds_in_pixels_;
- // |xwindow_|'s minimum size.
- gfx::Size min_size_in_pixels_;
-
- // |xwindow_|'s maximum size.
- gfx::Size max_size_in_pixels_;
-
- // The workspace containing |xwindow_|. This will be base::nullopt when
- // _NET_WM_DESKTOP is unset.
- base::Optional<int> workspace_;
-
- // The window manager state bits.
- base::flat_set<XAtom> window_properties_;
-
// Whether |xwindow_| was requested to be fullscreen via SetFullscreen().
bool is_fullscreen_ = false;
- // True if the window should stay on top of most other windows.
- bool is_always_on_top_ = false;
-
- // True if the window has title-bar / borders provided by the window manager.
- bool use_native_frame_ = false;
-
- // True if a Maximize() call should be done after mapping the window.
- bool should_maximize_after_map_ = false;
-
- // Whether we used an ARGB visual for our window.
- bool use_argb_visual_ = false;
+ // The z-order level of the window; the window exhibits "always on top"
+ // behavior if > 0.
+ ui::ZOrderLevel z_order_ = ui::ZOrderLevel::kNormal;
DesktopDragDropClientAuraX11* drag_drop_client_ = nullptr;
@@ -384,16 +313,6 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11
base::ObserverList<DesktopWindowTreeHostObserverX11>::Unchecked
observer_list_;
- // The window shape if the window is non-rectangular.
- gfx::XScopedPtr<_XRegion, gfx::XObjectDeleter<_XRegion, int, XDestroyRegion>>
- window_shape_;
-
- // Whether |window_shape_| was set via SetShape().
- bool custom_window_shape_ = false;
-
- // The size of the window manager provided borders (if any).
- gfx::Insets native_window_frame_borders_in_pixels_;
-
// The current DesktopWindowTreeHostX11 which has capture. Set synchronously
// when capture is requested via SetCapture().
static DesktopWindowTreeHostX11* g_current_capture;
@@ -402,76 +321,21 @@ class VIEWS_EXPORT DesktopWindowTreeHostX11
// destroyed.
static std::list<XID>* open_windows_;
- base::string16 window_title_;
-
- // Whether we currently are flashing our frame. This feature is implemented
- // by setting the urgency hint with the window manager, which can draw
- // attention to the window or completely ignore the hint. We stop flashing
- // the frame when |xwindow_| gains focus or handles a mouse button event.
- bool urgency_hint_set_ = false;
-
- // Does |xwindow_| have the pointer grab (XI2 or normal)?
- bool has_pointer_grab_ = false;
-
- // Is this window able to receive focus?
- bool activatable_ = true;
-
- // Was this window initialized with the override_redirect window attribute?
- bool override_redirect_ = false;
-
- // The focus-tracking state variables are as described in
- // gtk/docs/focus_tracking.txt
- //
- // |xwindow_| is active iff:
- // (|has_window_focus_| || |has_pointer_focus_|) &&
- // !|ignore_keyboard_input_|
-
- // Is the pointer in |xwindow_| or one of its children?
- bool has_pointer_ = false;
-
- // Is |xwindow_| or one of its children focused?
- bool has_window_focus_ = false;
-
- // (An ancestor window or the PointerRoot is focused) && |has_pointer_|.
- // |has_pointer_focus_| == true is the odd case where we will receive keyboard
- // input when |has_window_focus_| == false. |has_window_focus_| and
- // |has_pointer_focus_| are mutually exclusive.
- bool has_pointer_focus_ = false;
-
- // X11 does not support defocusing windows; you can only focus a different
- // window. If we would like to be defocused, we just ignore keyboard input we
- // no longer care about.
- bool ignore_keyboard_input_ = false;
-
- // Used for tracking activation state in {Before|After}ActivationStateChanged.
- bool was_active_ = false;
- bool had_pointer_ = false;
- bool had_pointer_grab_ = false;
- bool had_window_focus_ = false;
-
// Cached value for SetVisible. Not the same as the IsVisible public API.
bool is_compositor_set_visible_ = false;
// Captures system key events when keyboard lock is requested.
std::unique_ptr<ui::KeyboardHook> keyboard_hook_;
- base::CancelableOnceCallback<void()> delayed_resize_task_;
-
std::unique_ptr<aura::ScopedWindowTargeter> targeter_for_modal_;
uint32_t modal_dialog_counter_ = 0;
- // Used for synchronizing between |xwindow_| between desktop compositor during
- // resizing.
- XID update_counter_ = x11::None;
- XID extended_update_counter_ = x11::None;
- int64_t pending_counter_value_ = 0;
- int64_t configure_counter_value_ = 0;
- int64_t current_counter_value_ = 0;
- bool pending_counter_value_is_extended_ = false;
- bool configure_counter_value_is_extended_ = false;
std::unique_ptr<CompositorObserver> compositor_observer_;
+ std::unique_ptr<ui::XWindow> x11_window_;
+
+ // The display and the native X window hosting the root window.
base::WeakPtrFactory<DesktopWindowTreeHostX11> close_widget_factory_{this};
base::WeakPtrFactory<DesktopWindowTreeHostX11> weak_factory_{this};
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 2578d410387..702502cff05 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
@@ -52,7 +52,7 @@ class WMStateWaiter : public X11PropertyChangeWaiter {
bool ShouldKeepOnWaiting(const ui::PlatformEvent& event) override {
std::vector<Atom> hints;
if (ui::GetAtomArrayProperty(xwindow(), "_NET_WM_STATE", &hints))
- return base::ContainsValue(hints, gfx::GetAtom(hint_)) != wait_till_set_;
+ return base::Contains(hints, gfx::GetAtom(hint_)) != wait_till_set_;
return true;
}
diff --git a/chromium/ui/views/widget/desktop_aura/x11_desktop_handler.cc b/chromium/ui/views/widget/desktop_aura/x11_desktop_handler.cc
index 144f0ba0c1c..cfe62d62144 100644
--- a/chromium/ui/views/widget/desktop_aura/x11_desktop_handler.cc
+++ b/chromium/ui/views/widget/desktop_aura/x11_desktop_handler.cc
@@ -10,8 +10,9 @@
#include "ui/aura/env.h"
#include "ui/aura/window_event_dispatcher.h"
#include "ui/base/x/x11_menu_list.h"
-#include "ui/base/x/x11_window_event_manager.h"
+#include "ui/base/x/x11_util.h"
#include "ui/events/platform/platform_event_source.h"
+#include "ui/events/x/x11_window_event_manager.h"
#include "ui/gfx/x/x11.h"
#include "ui/gfx/x/x11_atom_cache.h"
#include "ui/gfx/x/x11_error_tracker.h"
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 784577da76d..100a1e856aa 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
@@ -41,8 +41,7 @@ class MinimizeWaiter : public X11PropertyChangeWaiter {
bool ShouldKeepOnWaiting(const ui::PlatformEvent& event) override {
std::vector<Atom> wm_states;
if (ui::GetAtomArrayProperty(xwindow(), "_NET_WM_STATE", &wm_states)) {
- return !base::ContainsValue(wm_states,
- gfx::GetAtom("_NET_WM_STATE_HIDDEN"));
+ return !base::Contains(wm_states, gfx::GetAtom("_NET_WM_STATE_HIDDEN"));
}
return true;
}
@@ -79,7 +78,7 @@ class StackingClientListWaiter : public X11PropertyChangeWaiter {
ui::GetXWindowStack(ui::GetX11RootWindow(), &stack);
return !std::all_of(
expected_windows_.cbegin(), expected_windows_.cend(),
- [&stack](XID window) { return base::ContainsValue(stack, window); });
+ [&stack](XID window) { return base::Contains(stack, window); });
}
std::vector<XID> expected_windows_;
diff --git a/chromium/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc b/chromium/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc
index eaf642aa5ba..cbeea44f3da 100644
--- a/chromium/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc
+++ b/chromium/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.cc
@@ -23,13 +23,13 @@
#include "ui/aura/window_tree_host.h"
#include "ui/base/x/x11_pointer_grab.h"
#include "ui/base/x/x11_util.h"
-#include "ui/base/x/x11_window_event_manager.h"
#include "ui/events/event.h"
#include "ui/events/event_utils.h"
#include "ui/events/keycodes/keyboard_code_conversion_x.h"
#include "ui/events/platform/platform_event_source.h"
#include "ui/events/platform/scoped_event_dispatcher.h"
#include "ui/events/platform/x11/x11_event_source.h"
+#include "ui/events/x/x11_window_event_manager.h"
#include "ui/gfx/x/x11.h"
namespace views {
@@ -53,8 +53,7 @@ X11WholeScreenMoveLoop::X11WholeScreenMoveLoop(X11MoveLoopDelegate* delegate)
should_reset_mouse_flags_(false),
grab_input_window_(x11::None),
grabbed_pointer_(false),
- canceled_(false),
- weak_factory_(this) {}
+ canceled_(false) {}
X11WholeScreenMoveLoop::~X11WholeScreenMoveLoop() = default;
diff --git a/chromium/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h b/chromium/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h
index 62631fa24e2..529cb62bac6 100644
--- a/chromium/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h
+++ b/chromium/ui/views/widget/desktop_aura/x11_whole_screen_move_loop.h
@@ -91,7 +91,7 @@ class X11WholeScreenMoveLoop : public X11MoveLoop,
bool canceled_;
std::unique_ptr<ui::MouseEvent> last_motion_in_screen_;
- base::WeakPtrFactory<X11WholeScreenMoveLoop> weak_factory_;
+ base::WeakPtrFactory<X11WholeScreenMoveLoop> weak_factory_{this};
DISALLOW_COPY_AND_ASSIGN(X11WholeScreenMoveLoop);
};
diff --git a/chromium/ui/views/widget/native_widget_aura.cc b/chromium/ui/views/widget/native_widget_aura.cc
index 6c45f99e96e..e160ccebd32 100644
--- a/chromium/ui/views/widget/native_widget_aura.cc
+++ b/chromium/ui/views/widget/native_widget_aura.cc
@@ -34,7 +34,6 @@
#include "ui/display/screen.h"
#include "ui/events/event.h"
#include "ui/gfx/canvas.h"
-#include "ui/gfx/font_list.h"
#include "ui/native_theme/native_theme_aura.h"
#include "ui/views/drag_utils.h"
#include "ui/views/views_delegate.h"
@@ -57,7 +56,6 @@
#if defined(OS_WIN)
#include "base/win/scoped_gdi_object.h"
-#include "ui/gfx/system_fonts_win.h"
#include "ui/views/widget/desktop_aura/desktop_window_tree_host_win.h"
#endif
@@ -82,7 +80,7 @@ DEFINE_UI_CLASS_PROPERTY_KEY(internal::NativeWidgetPrivate*,
nullptr)
void SetRestoreBounds(aura::Window* window, const gfx::Rect& bounds) {
- window->SetProperty(aura::client::kRestoreBoundsKey, new gfx::Rect(bounds));
+ window->SetProperty(aura::client::kRestoreBoundsKey, bounds);
}
void SetIcon(aura::Window* window,
@@ -91,7 +89,7 @@ void SetIcon(aura::Window* window,
if (value.isNull())
window->ClearProperty(key);
else
- window->SetProperty(key, new gfx::ImageSkia(value));
+ window->SetProperty(key, value);
}
} // namespace
@@ -104,8 +102,7 @@ NativeWidgetAura::NativeWidgetAura(internal::NativeWidgetDelegate* delegate)
window_(new aura::Window(this, aura::client::WINDOW_TYPE_UNKNOWN)),
ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET),
destroying_(false),
- cursor_(gfx::kNullCursor),
- close_widget_factory_(this) {
+ cursor_(gfx::kNullCursor) {
aura::client::SetFocusChangeObserver(window_, this);
wm::SetActivationChangeObserver(window_, this);
}
@@ -207,8 +204,8 @@ void NativeWidgetAura::InitNativeWidget(const Widget::InitParams& params) {
->set_parent_controls_visibility(true);
}
}
- // SetAlwaysOnTop before SetParent so that always-on-top container is used.
- SetAlwaysOnTop(params.keep_on_top);
+ // SetZOrderLevel before SetParent so that always-on-top container is used.
+ SetZOrderLevel(params.EffectiveZOrderLevel());
// Make sure we have a real |window_bounds|.
aura::Window* parent_or_context = parent ? parent : context;
@@ -365,7 +362,7 @@ void NativeWidgetAura::CenterWindow(const gfx::Size& size) {
if (!window_)
return;
- window_->SetProperty(aura::client::kPreferredSize, new gfx::Size(size));
+ window_->SetProperty(aura::client::kPreferredSize, size);
gfx::Rect parent_bounds(window_->parent()->GetBoundsInRootWindow());
// When centering window, we take the intersection of the host and
@@ -613,13 +610,16 @@ bool NativeWidgetAura::IsActive() const {
return window_ && wm::IsActiveWindow(window_);
}
-void NativeWidgetAura::SetAlwaysOnTop(bool on_top) {
+void NativeWidgetAura::SetZOrderLevel(ui::ZOrderLevel order) {
if (window_)
- window_->SetProperty(aura::client::kAlwaysOnTopKey, on_top);
+ window_->SetProperty(aura::client::kZOrderingKey, order);
}
-bool NativeWidgetAura::IsAlwaysOnTop() const {
- return window_ && window_->GetProperty(aura::client::kAlwaysOnTopKey);
+ui::ZOrderLevel NativeWidgetAura::GetZOrderLevel() const {
+ if (window_)
+ return window_->GetProperty(aura::client::kZOrderingKey);
+
+ return ui::ZOrderLevel::kNormal;
}
void NativeWidgetAura::SetVisibleOnAllWorkspaces(bool always_visible) {
@@ -691,12 +691,12 @@ void NativeWidgetAura::FlashFrame(bool flash) {
}
void NativeWidgetAura::RunShellDrag(View* view,
- const ui::OSExchangeData& data,
+ std::unique_ptr<ui::OSExchangeData> data,
const gfx::Point& location,
int operation,
ui::DragDropTypes::DragEventSource source) {
if (window_)
- views::RunShellDrag(window_, data, location, operation, source);
+ views::RunShellDrag(window_, std::move(data), location, operation, source);
}
void NativeWidgetAura::SchedulePaintInRect(const gfx::Rect& rect) {
@@ -1034,7 +1034,8 @@ void NativeWidgetAura::OnDragExited() {
drop_helper_->OnDragExit();
}
-int NativeWidgetAura::OnPerformDrop(const ui::DropTargetEvent& event) {
+int NativeWidgetAura::OnPerformDrop(const ui::DropTargetEvent& event,
+ std::unique_ptr<ui::OSExchangeData> data) {
DCHECK(drop_helper_.get() != nullptr);
return drop_helper_->OnDrop(event.data(), event.location(),
last_drop_operation_);
@@ -1224,15 +1225,6 @@ void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView native_view,
}
// static
-gfx::FontList NativeWidgetPrivate::GetWindowTitleFontList() {
-#if defined(OS_WIN)
- return gfx::FontList(gfx::win::GetSystemFont(gfx::win::SystemFont::kCaption));
-#else
- return gfx::FontList();
-#endif
-}
-
-// static
gfx::NativeView NativeWidgetPrivate::GetGlobalCapture(
gfx::NativeView native_view) {
aura::client::CaptureClient* capture_client =
diff --git a/chromium/ui/views/widget/native_widget_aura.h b/chromium/ui/views/widget/native_widget_aura.h
index e9bd036faf8..8fea00d5680 100644
--- a/chromium/ui/views/widget/native_widget_aura.h
+++ b/chromium/ui/views/widget/native_widget_aura.h
@@ -9,6 +9,7 @@
#include "base/macros.h"
#include "base/memory/weak_ptr.h"
+#include "build/build_config.h"
#include "ui/aura/client/drag_drop_delegate.h"
#include "ui/aura/client/focus_change_observer.h"
#include "ui/aura/window_delegate.h"
@@ -20,6 +21,10 @@
#include "ui/wm/public/activation_change_observer.h"
#include "ui/wm/public/activation_delegate.h"
+#if defined(OS_MACOSX)
+#error This file must not be included on macOS; Chromium Mac doesn't use Aura.
+#endif
+
namespace aura {
class Window;
}
@@ -111,8 +116,8 @@ class VIEWS_EXPORT NativeWidgetAura : public internal::NativeWidgetPrivate,
void Activate() override;
void Deactivate() override;
bool IsActive() const override;
- void SetAlwaysOnTop(bool always_on_top) override;
- bool IsAlwaysOnTop() const override;
+ void SetZOrderLevel(ui::ZOrderLevel order) override;
+ ui::ZOrderLevel GetZOrderLevel() const override;
void SetVisibleOnAllWorkspaces(bool always_visible) override;
bool IsVisibleOnAllWorkspaces() const override;
void Maximize() override;
@@ -128,7 +133,7 @@ class VIEWS_EXPORT NativeWidgetAura : public internal::NativeWidgetPrivate,
void SetAspectRatio(const gfx::SizeF& aspect_ratio) override;
void FlashFrame(bool flash_frame) override;
void RunShellDrag(View* view,
- const ui::OSExchangeData& data,
+ std::unique_ptr<ui::OSExchangeData> data,
const gfx::Point& location,
int operation,
ui::DragDropTypes::DragEventSource source) override;
@@ -204,7 +209,8 @@ class VIEWS_EXPORT NativeWidgetAura : public internal::NativeWidgetPrivate,
void OnDragEntered(const ui::DropTargetEvent& event) override;
int OnDragUpdated(const ui::DropTargetEvent& event) override;
void OnDragExited() override;
- int OnPerformDrop(const ui::DropTargetEvent& event) override;
+ int OnPerformDrop(const ui::DropTargetEvent& event,
+ std::unique_ptr<ui::OSExchangeData> data) override;
protected:
~NativeWidgetAura() override;
@@ -243,7 +249,7 @@ class VIEWS_EXPORT NativeWidgetAura : public internal::NativeWidgetPrivate,
// The following factory is used for calls to close the NativeWidgetAura
// instance.
- base::WeakPtrFactory<NativeWidgetAura> close_widget_factory_;
+ base::WeakPtrFactory<NativeWidgetAura> close_widget_factory_{this};
DISALLOW_COPY_AND_ASSIGN(NativeWidgetAura);
};
diff --git a/chromium/ui/views/widget/native_widget_mac.h b/chromium/ui/views/widget/native_widget_mac.h
index 8733e1b1775..e64872d3357 100644
--- a/chromium/ui/views/widget/native_widget_mac.h
+++ b/chromium/ui/views/widget/native_widget_mac.h
@@ -18,10 +18,12 @@ class NativeWidgetMacNSWindow;
namespace remote_cocoa {
namespace mojom {
-class BridgedNativeWidget;
class CreateWindowParams;
+class NativeWidgetNSWindow;
class ValidateUserInterfaceItemResult;
} // namespace mojom
+class ApplicationHost;
+class NativeWidgetNSWindowBridge;
} // namespace remote_cocoa
namespace views {
@@ -30,10 +32,7 @@ class HitTestNativeWidgetMac;
class MockNativeWidgetMac;
class WidgetTest;
}
-
-class BridgeFactoryHost;
-class BridgedNativeWidgetImpl;
-class BridgedNativeWidgetHostImpl;
+class NativeWidgetMacNSWindowHost;
class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate {
public:
@@ -41,7 +40,7 @@ class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate {
~NativeWidgetMac() override;
// Informs |delegate_| that the native widget is about to be destroyed.
- // BridgedNativeWidgetImpl::OnWindowWillClose() invokes this early when the
+ // NativeWidgetNSWindowBridge::OnWindowWillClose() invokes this early when the
// NSWindowDelegate informs the bridge that the window is being closed (later,
// invoking OnWindowDestroyed()).
void WindowDestroying();
@@ -134,8 +133,8 @@ class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate {
void Activate() override;
void Deactivate() override;
bool IsActive() const override;
- void SetAlwaysOnTop(bool always_on_top) override;
- bool IsAlwaysOnTop() const override;
+ void SetZOrderLevel(ui::ZOrderLevel order) override;
+ ui::ZOrderLevel GetZOrderLevel() const override;
void SetVisibleOnAllWorkspaces(bool always_visible) override;
bool IsVisibleOnAllWorkspaces() const override;
void Maximize() override;
@@ -151,7 +150,7 @@ class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate {
void SetAspectRatio(const gfx::SizeF& aspect_ratio) override;
void FlashFrame(bool flash_frame) override;
void RunShellDrag(View* view,
- const ui::OSExchangeData& data,
+ std::unique_ptr<ui::OSExchangeData> data,
const gfx::Point& location,
int operation,
ui::DragDropTypes::DragEventSource source) override;
@@ -187,7 +186,7 @@ class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate {
const Widget::InitParams& widget_params,
remote_cocoa::mojom::CreateWindowParams* params) {}
- // Creates the NSWindow that will be passed to the BridgedNativeWidgetImpl.
+ // Creates the NSWindow that will be passed to the NativeWidgetNSWindowBridge.
// Called by InitNativeWidget. The return value will be autoreleased.
// Note that some tests (in particular, views_unittests that interact
// with ScopedFakeNSWindowFullscreen, on 10.10) assume that these windows
@@ -199,7 +198,7 @@ class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate {
// Return the BridgeFactoryHost that is to be used for creating this window
// and all of its child windows. This will return nullptr if the native
// windows are to be created in the current process.
- virtual BridgeFactoryHost* GetBridgeFactoryHost();
+ virtual remote_cocoa::ApplicationHost* GetRemoteCocoaApplicationHost();
// Called after the window has been initialized. Allows subclasses to perform
// additional initialization.
@@ -209,10 +208,16 @@ class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate {
virtual void OnWindowDestroying(gfx::NativeWindow window) {}
internal::NativeWidgetDelegate* delegate() { return delegate_; }
- remote_cocoa::mojom::BridgedNativeWidget* bridge() const;
- BridgedNativeWidgetImpl* bridge_impl() const;
- BridgedNativeWidgetHostImpl* bridge_host() const {
- return bridge_host_.get();
+
+ // Return the mojo interface for the NSWindow. The interface may be
+ // implemented in-process or out-of-process.
+ remote_cocoa::mojom::NativeWidgetNSWindow* GetNSWindowMojo() const;
+
+ // Return the bridge structure only if this widget is in-process.
+ remote_cocoa::NativeWidgetNSWindowBridge* GetInProcessNSWindowBridge() const;
+
+ NativeWidgetMacNSWindowHost* GetNSWindowHost() const {
+ return ns_window_host_.get();
}
private:
@@ -221,13 +226,15 @@ class VIEWS_EXPORT NativeWidgetMac : public internal::NativeWidgetPrivate {
friend class views::test::WidgetTest;
internal::NativeWidgetDelegate* delegate_;
- std::unique_ptr<BridgedNativeWidgetHostImpl> bridge_host_;
+ std::unique_ptr<NativeWidgetMacNSWindowHost> ns_window_host_;
Widget::InitParams::Ownership ownership_;
// Internal name.
std::string name_;
+ Widget::InitParams::Type type_;
+
DISALLOW_COPY_AND_ASSIGN(NativeWidgetMac);
};
diff --git a/chromium/ui/views/widget/native_widget_mac.mm b/chromium/ui/views/widget/native_widget_mac.mm
index 0d7c1c9aada..9043f5bb363 100644
--- a/chromium/ui/views/widget/native_widget_mac.mm
+++ b/chromium/ui/views/widget/native_widget_mac.mm
@@ -11,12 +11,13 @@
#include "base/bind.h"
#include "base/lazy_instance.h"
#include "base/mac/scoped_nsobject.h"
+#include "base/no_destructor.h"
#include "base/strings/sys_string_conversions.h"
#include "base/threading/thread_task_runner_handle.h"
#include "components/crash/core/common/crash_key.h"
#import "components/remote_cocoa/app_shim/bridged_content_view.h"
-#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h"
#import "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h"
+#import "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h"
#import "components/remote_cocoa/app_shim/views_nswindow_delegate.h"
#import "ui/base/cocoa/constrained_window/constrained_window_animation.h"
#import "ui/base/cocoa/window_size_constants.h"
@@ -25,11 +26,10 @@
#include "ui/events/gestures/gesture_recognizer_impl_mac.h"
#include "ui/gfx/font_list.h"
#import "ui/gfx/mac/coordinate_conversion.h"
-#import "ui/gfx/mac/nswindow_frame_controls.h"
#include "ui/native_theme/native_theme.h"
#include "ui/native_theme/native_theme_mac.h"
-#import "ui/views/cocoa/bridged_native_widget_host_impl.h"
#import "ui/views/cocoa/drag_drop_client_mac.h"
+#import "ui/views/cocoa/native_widget_mac_ns_window_host.h"
#include "ui/views/widget/drop_helper.h"
#include "ui/views/widget/widget_delegate.h"
#include "ui/views/window/native_frame_view.h"
@@ -37,6 +37,7 @@
using remote_cocoa::mojom::WindowVisibilityState;
namespace views {
+
namespace {
base::LazyInstance<ui::GestureRecognizerImplMac>::Leaky
@@ -65,6 +66,42 @@ NSInteger StyleMaskForParams(const Widget::InitParams& params) {
return NSBorderlessWindowMask;
}
+CGWindowLevel CGWindowLevelForZOrderLevel(ui::ZOrderLevel level,
+ Widget::InitParams::Type type) {
+ switch (level) {
+ case ui::ZOrderLevel::kNormal:
+ return kCGNormalWindowLevel;
+ case ui::ZOrderLevel::kFloatingWindow:
+ if (type == Widget::InitParams::TYPE_MENU)
+ return kCGPopUpMenuWindowLevel;
+ else
+ return kCGFloatingWindowLevel;
+ case ui::ZOrderLevel::kFloatingUIElement:
+ if (type == Widget::InitParams::TYPE_DRAG)
+ return kCGDraggingWindowLevel;
+ else
+ return kCGStatusWindowLevel;
+ case ui::ZOrderLevel::kSecuritySurface:
+ return kCGScreenSaverWindowLevel - 1;
+ }
+}
+
+ui::ZOrderLevel ZOrderLevelForCGWindowLevel(CGWindowLevel level) {
+ switch (level) {
+ case kCGNormalWindowLevel:
+ return ui::ZOrderLevel::kNormal;
+ case kCGFloatingWindowLevel:
+ case kCGPopUpMenuWindowLevel:
+ default:
+ return ui::ZOrderLevel::kFloatingWindow;
+ case kCGStatusWindowLevel:
+ case kCGDraggingWindowLevel:
+ return ui::ZOrderLevel::kFloatingUIElement;
+ case kCGScreenSaverWindowLevel - 1:
+ return ui::ZOrderLevel::kSecuritySurface;
+ }
+}
+
} // namespace
////////////////////////////////////////////////////////////////////////////////
@@ -72,7 +109,7 @@ NSInteger StyleMaskForParams(const Widget::InitParams& params) {
NativeWidgetMac::NativeWidgetMac(internal::NativeWidgetDelegate* delegate)
: delegate_(delegate),
- bridge_host_(new BridgedNativeWidgetHostImpl(this)),
+ ns_window_host_(new NativeWidgetMacNSWindowHost(this)),
ownership_(Widget::InitParams::NATIVE_WIDGET_OWNS_WIDGET) {}
NativeWidgetMac::~NativeWidgetMac() {
@@ -88,8 +125,8 @@ void NativeWidgetMac::WindowDestroying() {
}
void NativeWidgetMac::WindowDestroyed() {
- DCHECK(bridge());
- bridge_host_.reset();
+ DCHECK(GetNSWindowMojo());
+ ns_window_host_.reset();
// |OnNativeWidgetDestroyed| may delete |this| if the object does not own
// itself.
bool should_delete_this =
@@ -125,12 +162,14 @@ bool NativeWidgetMac::ExecuteCommand(
void NativeWidgetMac::InitNativeWidget(const Widget::InitParams& params) {
ownership_ = params.ownership;
name_ = params.name;
- BridgedNativeWidgetHostImpl* parent_host =
- BridgedNativeWidgetHostImpl::GetFromNativeView(params.parent);
+ type_ = params.type;
+ NativeWidgetMacNSWindowHost* parent_host =
+ NativeWidgetMacNSWindowHost::GetFromNativeView(params.parent);
// Determine the factory through which to create the bridge
- BridgeFactoryHost* bridge_factory_host =
- parent_host ? parent_host->bridge_factory_host() : GetBridgeFactoryHost();
+ remote_cocoa::ApplicationHost* application_host =
+ parent_host ? parent_host->application_host()
+ : GetRemoteCocoaApplicationHost();
// Compute the parameters to describe the NSWindow.
auto create_window_params = remote_cocoa::mojom::CreateWindowParams::New();
@@ -141,35 +180,35 @@ void NativeWidgetMac::InitNativeWidget(const Widget::InitParams& params) {
create_window_params->window_title_hidden = false;
PopulateCreateWindowParams(params, create_window_params.get());
- if (bridge_factory_host) {
- bridge_host_->CreateRemoteBridge(bridge_factory_host,
- std::move(create_window_params));
+ if (application_host) {
+ ns_window_host_->CreateRemoteNSWindow(application_host,
+ std::move(create_window_params));
} else {
base::scoped_nsobject<NativeWidgetMacNSWindow> window(
[CreateNSWindow(create_window_params.get()) retain]);
- bridge_host_->CreateLocalBridge(std::move(window));
+ ns_window_host_->CreateInProcessNSWindowBridge(std::move(window));
}
- bridge_host_->SetParent(parent_host);
- bridge_host_->InitWindow(params);
+ ns_window_host_->SetParent(parent_host);
+ ns_window_host_->InitWindow(params);
OnWindowInitialized();
- // Only set always-on-top here if it is true since setting it may affect how
- // the window is treated by Expose.
- if (params.keep_on_top)
- SetAlwaysOnTop(true);
+ // Only set the z-order here if it is non-default since setting it may affect
+ // how the window is treated by Expose.
+ if (params.EffectiveZOrderLevel() != ui::ZOrderLevel::kNormal)
+ SetZOrderLevel(params.EffectiveZOrderLevel());
delegate_->OnNativeWidgetCreated();
DCHECK(GetWidget()->GetRootView());
- bridge_host_->SetRootView(GetWidget()->GetRootView());
- bridge()->CreateContentView(bridge_host_->GetRootViewNSViewId(),
- GetWidget()->GetRootView()->bounds());
+ ns_window_host_->SetRootView(GetWidget()->GetRootView());
+ GetNSWindowMojo()->CreateContentView(ns_window_host_->GetRootViewNSViewId(),
+ GetWidget()->GetRootView()->bounds());
if (auto* focus_manager = GetWidget()->GetFocusManager()) {
- bridge()->MakeFirstResponder();
- bridge_host_->SetFocusManager(focus_manager);
+ GetNSWindowMojo()->MakeFirstResponder();
+ ns_window_host_->SetFocusManager(focus_manager);
}
- bridge_host_->CreateCompositor(params);
+ ns_window_host_->CreateCompositor(params);
if (g_init_native_widget_callback)
g_init_native_widget_callback->Run(this);
@@ -177,7 +216,7 @@ void NativeWidgetMac::InitNativeWidget(const Widget::InitParams& params) {
void NativeWidgetMac::OnWidgetInitDone() {
OnSizeConstraintsChanged();
- bridge_host_->OnWidgetInitDone();
+ ns_window_host_->OnWidgetInitDone();
}
NonClientFrameView* NativeWidgetMac::CreateNonClientFrameView() {
@@ -215,7 +254,7 @@ gfx::NativeView NativeWidgetMac::GetNativeView() const {
}
gfx::NativeWindow NativeWidgetMac::GetNativeWindow() const {
- return bridge_host_ ? bridge_host_->GetLocalNSWindow() : nil;
+ return ns_window_host_ ? ns_window_host_->GetInProcessNSWindow() : nil;
}
Widget* NativeWidgetMac::GetTopLevelWidget() {
@@ -224,66 +263,66 @@ Widget* NativeWidgetMac::GetTopLevelWidget() {
}
const ui::Compositor* NativeWidgetMac::GetCompositor() const {
- return bridge_host_ && bridge_host_->layer()
- ? bridge_host_->layer()->GetCompositor()
+ return ns_window_host_ && ns_window_host_->layer()
+ ? ns_window_host_->layer()->GetCompositor()
: nullptr;
}
const ui::Layer* NativeWidgetMac::GetLayer() const {
- return bridge_host_ ? bridge_host_->layer() : nullptr;
+ return ns_window_host_ ? ns_window_host_->layer() : nullptr;
}
void NativeWidgetMac::ReorderNativeViews() {
- if (bridge_host_)
- bridge_host_->ReorderChildViews();
+ if (ns_window_host_)
+ ns_window_host_->ReorderChildViews();
}
void NativeWidgetMac::ViewRemoved(View* view) {
DragDropClientMac* client =
- bridge_host_ ? bridge_host_->drag_drop_client() : nullptr;
+ ns_window_host_ ? ns_window_host_->drag_drop_client() : nullptr;
if (client)
client->drop_helper()->ResetTargetViewIfEquals(view);
}
void NativeWidgetMac::SetNativeWindowProperty(const char* name, void* value) {
- if (bridge_host_)
- bridge_host_->SetNativeWindowProperty(name, value);
+ if (ns_window_host_)
+ ns_window_host_->SetNativeWindowProperty(name, value);
}
void* NativeWidgetMac::GetNativeWindowProperty(const char* name) const {
- if (bridge_host_)
- return bridge_host_->GetNativeWindowProperty(name);
+ if (ns_window_host_)
+ return ns_window_host_->GetNativeWindowProperty(name);
return nullptr;
}
TooltipManager* NativeWidgetMac::GetTooltipManager() const {
- if (bridge_host_)
- return bridge_host_->tooltip_manager();
+ if (ns_window_host_)
+ return ns_window_host_->tooltip_manager();
return nullptr;
}
void NativeWidgetMac::SetCapture() {
- if (bridge())
- bridge()->AcquireCapture();
+ if (GetNSWindowMojo())
+ GetNSWindowMojo()->AcquireCapture();
}
void NativeWidgetMac::ReleaseCapture() {
- if (bridge())
- bridge()->ReleaseCapture();
+ if (GetNSWindowMojo())
+ GetNSWindowMojo()->ReleaseCapture();
}
bool NativeWidgetMac::HasCapture() const {
- return bridge_host_ && bridge_host_->IsMouseCaptureActive();
+ return ns_window_host_ && ns_window_host_->IsMouseCaptureActive();
}
ui::InputMethod* NativeWidgetMac::GetInputMethod() {
- return bridge_host_ ? bridge_host_->GetInputMethod() : nullptr;
+ return ns_window_host_ ? ns_window_host_->GetInputMethod() : nullptr;
}
void NativeWidgetMac::CenterWindow(const gfx::Size& size) {
- bridge()->SetSizeAndCenter(size, GetWidget()->GetMinimumSize());
+ GetNSWindowMojo()->SetSizeAndCenter(size, GetWidget()->GetMinimumSize());
}
void NativeWidgetMac::GetWindowPlacement(
@@ -299,9 +338,9 @@ void NativeWidgetMac::GetWindowPlacement(
}
bool NativeWidgetMac::SetWindowTitle(const base::string16& title) {
- if (!bridge_host_)
+ if (!ns_window_host_)
return false;
- return bridge_host_->SetWindowTitle(title);
+ return ns_window_host_->SetWindowTitle(title);
}
void NativeWidgetMac::SetWindowIcons(const gfx::ImageSkia& window_icon,
@@ -321,21 +360,23 @@ void NativeWidgetMac::InitModalType(ui::ModalType modal_type) {
// A peculiarity of the constrained window framework is that it permits a
// dialog of MODAL_TYPE_WINDOW to have a null parent window; falling back to
// a non-modal window in this case.
- DCHECK(bridge_host_->parent() || modal_type == ui::MODAL_TYPE_WINDOW);
+ DCHECK(ns_window_host_->parent() || modal_type == ui::MODAL_TYPE_WINDOW);
// Everything happens upon show.
}
gfx::Rect NativeWidgetMac::GetWindowBoundsInScreen() const {
- return bridge_host_ ? bridge_host_->GetWindowBoundsInScreen() : gfx::Rect();
+ return ns_window_host_ ? ns_window_host_->GetWindowBoundsInScreen()
+ : gfx::Rect();
}
gfx::Rect NativeWidgetMac::GetClientAreaBoundsInScreen() const {
- return bridge_host_ ? bridge_host_->GetContentBoundsInScreen() : gfx::Rect();
+ return ns_window_host_ ? ns_window_host_->GetContentBoundsInScreen()
+ : gfx::Rect();
}
gfx::Rect NativeWidgetMac::GetRestoredBounds() const {
- return bridge_host_ ? bridge_host_->GetRestoredBounds() : gfx::Rect();
+ return ns_window_host_ ? ns_window_host_->GetRestoredBounds() : gfx::Rect();
}
std::string NativeWidgetMac::GetWorkspace() const {
@@ -343,17 +384,17 @@ std::string NativeWidgetMac::GetWorkspace() const {
}
void NativeWidgetMac::SetBounds(const gfx::Rect& bounds) {
- if (bridge_host_)
- bridge_host_->SetBounds(bounds);
+ if (ns_window_host_)
+ ns_window_host_->SetBounds(bounds);
}
void NativeWidgetMac::SetBoundsConstrained(const gfx::Rect& bounds) {
- if (!bridge_host_)
+ if (!ns_window_host_)
return;
gfx::Rect new_bounds(bounds);
- if (bridge_host_->parent()) {
+ if (ns_window_host_->parent()) {
new_bounds.AdjustToFit(
- gfx::Rect(bridge_host_->parent()->GetWindowBoundsInScreen().size()));
+ gfx::Rect(ns_window_host_->parent()->GetWindowBoundsInScreen().size()));
} else {
new_bounds = ConstrainBoundsToDisplayWorkArea(new_bounds);
}
@@ -367,36 +408,35 @@ void NativeWidgetMac::SetSize(const gfx::Size& size) {
}
void NativeWidgetMac::StackAbove(gfx::NativeView native_view) {
- if (!bridge())
+ if (!GetNSWindowMojo())
return;
auto* sibling_host =
- BridgedNativeWidgetHostImpl::GetFromNativeView(native_view);
+ NativeWidgetMacNSWindowHost::GetFromNativeView(native_view);
if (!sibling_host) {
// This will only work if |this| is in-process.
- DCHECK(!bridge_host_->bridge_factory_host());
+ DCHECK(!ns_window_host_->application_host());
NSInteger view_parent = native_view.GetNativeNSView().window.windowNumber;
[GetNativeWindow().GetNativeNSWindow() orderWindow:NSWindowAbove
relativeTo:view_parent];
return;
}
- if (bridge_host_->bridge_factory_host() ==
- sibling_host->bridge_factory_host()) {
- // Check if |native_view|'s BridgedNativeWidgetHostImpl corresponds to the
+ if (ns_window_host_->application_host() == sibling_host->application_host()) {
+ // Check if |native_view|'s NativeWidgetMacNSWindowHost corresponds to the
// same process as |this|.
- bridge()->StackAbove(sibling_host->bridged_native_widget_id());
+ GetNSWindowMojo()->StackAbove(sibling_host->bridged_native_widget_id());
return;
}
- NOTREACHED() << "|native_view|'s BridgedNativeWidgetHostImpl isn't same "
+ NOTREACHED() << "|native_view|'s NativeWidgetMacNSWindowHost isn't same "
"process |this|";
}
void NativeWidgetMac::StackAtTop() {
- if (bridge())
- bridge()->StackAtTop();
+ if (GetNSWindowMojo())
+ GetNSWindowMojo()->StackAtTop();
}
void NativeWidgetMac::SetShape(std::unique_ptr<Widget::ShapeRects> shape) {
@@ -404,20 +444,20 @@ void NativeWidgetMac::SetShape(std::unique_ptr<Widget::ShapeRects> shape) {
}
void NativeWidgetMac::Close() {
- if (bridge())
- bridge()->CloseWindow();
+ if (GetNSWindowMojo())
+ GetNSWindowMojo()->CloseWindow();
}
void NativeWidgetMac::CloseNow() {
- if (bridge_host_)
- bridge_host_->CloseWindowNow();
- // Note: |bridge_host_| will be deleted here, and |this| will be deleted here
- // when ownership_ == NATIVE_WIDGET_OWNS_WIDGET,
+ if (ns_window_host_)
+ ns_window_host_->CloseWindowNow();
+ // Note: |ns_window_host_| will be deleted here, and |this| will be deleted
+ // here when ownership_ == NATIVE_WIDGET_OWNS_WIDGET,
}
void NativeWidgetMac::Show(ui::WindowShowState show_state,
const gfx::Rect& restore_bounds) {
- if (!bridge())
+ if (!GetNSWindowMojo())
return;
switch (show_state) {
@@ -439,7 +479,7 @@ void NativeWidgetMac::Show(ui::WindowShowState show_state,
window_state = WindowVisibilityState::kShowInactive;
else if (show_state == ui::SHOW_STATE_MINIMIZED)
window_state = WindowVisibilityState::kHideWindow;
- bridge()->SetVisibilityState(window_state);
+ GetNSWindowMojo()->SetVisibilityState(window_state);
// Ignore the SetInitialFocus() result. BridgedContentView should get
// firstResponder status regardless.
@@ -447,19 +487,20 @@ void NativeWidgetMac::Show(ui::WindowShowState show_state,
}
void NativeWidgetMac::Hide() {
- if (!bridge())
+ if (!GetNSWindowMojo())
return;
- bridge()->SetVisibilityState(WindowVisibilityState::kHideWindow);
+ GetNSWindowMojo()->SetVisibilityState(WindowVisibilityState::kHideWindow);
}
bool NativeWidgetMac::IsVisible() const {
- return bridge_host_ && bridge_host_->IsVisible();
+ return ns_window_host_ && ns_window_host_->IsVisible();
}
void NativeWidgetMac::Activate() {
- if (!bridge())
+ if (!GetNSWindowMojo())
return;
- bridge()->SetVisibilityState(WindowVisibilityState::kShowAndActivateWindow);
+ GetNSWindowMojo()->SetVisibilityState(
+ WindowVisibilityState::kShowAndActivateWindow);
}
void NativeWidgetMac::Deactivate() {
@@ -467,22 +508,30 @@ void NativeWidgetMac::Deactivate() {
}
bool NativeWidgetMac::IsActive() const {
- return bridge_host_ ? bridge_host_->IsWindowKey() : false;
+ return ns_window_host_ ? ns_window_host_->IsWindowKey() : false;
}
-void NativeWidgetMac::SetAlwaysOnTop(bool always_on_top) {
- gfx::SetNSWindowAlwaysOnTop(GetNativeWindow().GetNativeNSWindow(),
- always_on_top);
+void NativeWidgetMac::SetZOrderLevel(ui::ZOrderLevel order) {
+ NSWindow* window = GetNativeWindow().GetNativeNSWindow();
+ [window setLevel:CGWindowLevelForZOrderLevel(order, type_)];
+
+ // Windows that have a higher window level than NSNormalWindowLevel default to
+ // NSWindowCollectionBehaviorTransient. Set the value explicitly here to match
+ // normal windows.
+ NSWindowCollectionBehavior behavior =
+ [window collectionBehavior] | NSWindowCollectionBehaviorManaged;
+ [window setCollectionBehavior:behavior];
}
-bool NativeWidgetMac::IsAlwaysOnTop() const {
- return gfx::IsNSWindowAlwaysOnTop(GetNativeWindow().GetNativeNSWindow());
+ui::ZOrderLevel NativeWidgetMac::GetZOrderLevel() const {
+ return ZOrderLevelForCGWindowLevel(
+ [GetNativeWindow().GetNativeNSWindow() level]);
}
void NativeWidgetMac::SetVisibleOnAllWorkspaces(bool always_visible) {
- if (!bridge())
+ if (!GetNSWindowMojo())
return;
- bridge()->SetVisibleOnAllSpaces(always_visible);
+ GetNSWindowMojo()->SetVisibleOnAllSpaces(always_visible);
}
bool NativeWidgetMac::IsVisibleOnAllWorkspaces() const {
@@ -494,9 +543,9 @@ void NativeWidgetMac::Maximize() {
}
void NativeWidgetMac::Minimize() {
- if (!bridge())
+ if (!GetNSWindowMojo())
return;
- bridge()->SetMiniaturized(true);
+ GetNSWindowMojo()->SetMiniaturized(true);
}
bool NativeWidgetMac::IsMaximized() const {
@@ -506,46 +555,46 @@ bool NativeWidgetMac::IsMaximized() const {
}
bool NativeWidgetMac::IsMinimized() const {
- if (!bridge_host_)
+ if (!ns_window_host_)
return false;
- return bridge_host_->IsMiniaturized();
+ return ns_window_host_->IsMiniaturized();
}
void NativeWidgetMac::Restore() {
- if (!bridge())
+ if (!GetNSWindowMojo())
return;
- bridge()->SetFullscreen(false);
- bridge()->SetMiniaturized(false);
+ GetNSWindowMojo()->SetFullscreen(false);
+ GetNSWindowMojo()->SetMiniaturized(false);
}
void NativeWidgetMac::SetFullscreen(bool fullscreen) {
- if (!bridge_host_)
+ if (!ns_window_host_)
return;
- bridge_host_->SetFullscreen(fullscreen);
+ ns_window_host_->SetFullscreen(fullscreen);
}
bool NativeWidgetMac::IsFullscreen() const {
- return bridge_host_ && bridge_host_->target_fullscreen_state();
+ return ns_window_host_ && ns_window_host_->target_fullscreen_state();
}
void NativeWidgetMac::SetCanAppearInExistingFullscreenSpaces(
bool can_appear_in_existing_fullscreen_spaces) {
- if (!bridge())
+ if (!GetNSWindowMojo())
return;
- bridge()->SetCanAppearInExistingFullscreenSpaces(
+ GetNSWindowMojo()->SetCanAppearInExistingFullscreenSpaces(
can_appear_in_existing_fullscreen_spaces);
}
void NativeWidgetMac::SetOpacity(float opacity) {
- if (!bridge())
+ if (!GetNSWindowMojo())
return;
- bridge()->SetOpacity(opacity);
+ GetNSWindowMojo()->SetOpacity(opacity);
}
void NativeWidgetMac::SetAspectRatio(const gfx::SizeF& aspect_ratio) {
- if (!bridge())
+ if (!GetNSWindowMojo())
return;
- bridge()->SetContentAspectRatio(aspect_ratio);
+ GetNSWindowMojo()->SetContentAspectRatio(aspect_ratio);
}
void NativeWidgetMac::FlashFrame(bool flash_frame) {
@@ -553,12 +602,12 @@ void NativeWidgetMac::FlashFrame(bool flash_frame) {
}
void NativeWidgetMac::RunShellDrag(View* view,
- const ui::OSExchangeData& data,
+ std::unique_ptr<ui::OSExchangeData> data,
const gfx::Point& location,
int operation,
ui::DragDropTypes::DragEventSource source) {
- bridge_host_->drag_drop_client()->StartDragAndDrop(view, data, operation,
- source);
+ ns_window_host_->drag_drop_client()->StartDragAndDrop(view, std::move(data),
+ operation, source);
}
void NativeWidgetMac::SchedulePaintInRect(const gfx::Rect& rect) {
@@ -571,8 +620,8 @@ void NativeWidgetMac::SchedulePaintInRect(const gfx::Rect& rect) {
target_rect.origin.y =
NSHeight(client_rect) - target_rect.origin.y - NSHeight(target_rect);
[GetNativeView().GetNativeNSView() setNeedsDisplayInRect:target_rect];
- if (bridge_host_ && bridge_host_->layer())
- bridge_host_->layer()->SchedulePaint(rect);
+ if (ns_window_host_ && ns_window_host_->layer())
+ ns_window_host_->layer()->SchedulePaint(rect);
}
void NativeWidgetMac::ScheduleLayout() {
@@ -582,15 +631,15 @@ void NativeWidgetMac::ScheduleLayout() {
}
void NativeWidgetMac::SetCursor(gfx::NativeCursor cursor) {
- if (bridge_impl())
- bridge_impl()->SetCursor(cursor);
+ if (GetInProcessNSWindowBridge())
+ GetInProcessNSWindowBridge()->SetCursor(cursor);
}
void NativeWidgetMac::ShowEmojiPanel() {
// We must plumb the call to ui::ShowEmojiPanel() over the bridge so that it
// is called from the correct process.
- if (bridge())
- bridge()->ShowEmojiPanel();
+ if (GetNSWindowMojo())
+ GetNSWindowMojo()->ShowEmojiPanel();
}
bool NativeWidgetMac::IsMouseEventsEnabled() const {
@@ -608,36 +657,37 @@ void NativeWidgetMac::ClearNativeFocus() {
// To quote DesktopWindowTreeHostX11, "This method is weird and misnamed."
// The goal is to set focus to the content window, thereby removing focus from
// any NSView in the window that doesn't belong to toolkit-views.
- if (!bridge())
+ if (!GetNSWindowMojo())
return;
- bridge()->MakeFirstResponder();
+ GetNSWindowMojo()->MakeFirstResponder();
}
gfx::Rect NativeWidgetMac::GetWorkAreaBoundsInScreen() const {
- return bridge_host_ ? bridge_host_->GetCurrentDisplay().work_area()
- : gfx::Rect();
+ return ns_window_host_ ? ns_window_host_->GetCurrentDisplay().work_area()
+ : gfx::Rect();
}
Widget::MoveLoopResult NativeWidgetMac::RunMoveLoop(
const gfx::Vector2d& drag_offset,
Widget::MoveLoopSource source,
Widget::MoveLoopEscapeBehavior escape_behavior) {
- if (!bridge_impl())
+ if (!GetInProcessNSWindowBridge())
return Widget::MOVE_LOOP_CANCELED;
ReleaseCapture();
- return bridge_impl()->RunMoveLoop(drag_offset) ? Widget::MOVE_LOOP_SUCCESSFUL
- : Widget::MOVE_LOOP_CANCELED;
+ return GetInProcessNSWindowBridge()->RunMoveLoop(drag_offset)
+ ? Widget::MOVE_LOOP_SUCCESSFUL
+ : Widget::MOVE_LOOP_CANCELED;
}
void NativeWidgetMac::EndMoveLoop() {
- if (bridge_impl())
- bridge_impl()->EndMoveLoop();
+ if (GetInProcessNSWindowBridge())
+ GetInProcessNSWindowBridge()->EndMoveLoop();
}
void NativeWidgetMac::SetVisibilityChangedAnimationsEnabled(bool value) {
- if (bridge())
- bridge()->SetAnimationEnabled(value);
+ if (GetNSWindowMojo())
+ GetNSWindowMojo()->SetAnimationEnabled(value);
}
void NativeWidgetMac::SetVisibilityAnimationDuration(
@@ -663,8 +713,8 @@ void NativeWidgetMac::SetVisibilityAnimationTransition(
transitions = remote_cocoa::mojom::VisibilityTransition::kBoth;
break;
}
- if (bridge())
- bridge()->SetTransitionsToAnimate(transitions);
+ if (GetNSWindowMojo())
+ GetNSWindowMojo()->SetTransitionsToAnimate(transitions);
}
bool NativeWidgetMac::IsTranslucentWindowOpacitySupported() const {
@@ -677,10 +727,10 @@ ui::GestureRecognizer* NativeWidgetMac::GetGestureRecognizer() {
void NativeWidgetMac::OnSizeConstraintsChanged() {
Widget* widget = GetWidget();
- bridge()->SetSizeConstraints(widget->GetMinimumSize(),
- widget->GetMaximumSize(),
- widget->widget_delegate()->CanResize(),
- widget->widget_delegate()->CanMaximize());
+ GetNSWindowMojo()->SetSizeConstraints(
+ widget->GetMinimumSize(), widget->GetMaximumSize(),
+ widget->widget_delegate()->CanResize(),
+ widget->widget_delegate()->CanMaximize());
}
std::string NativeWidgetMac::GetName() const {
@@ -707,19 +757,24 @@ void NativeWidgetMac::SetInitNativeWidgetCallback(
NativeWidgetMacNSWindow* NativeWidgetMac::CreateNSWindow(
const remote_cocoa::mojom::CreateWindowParams* params) {
- return BridgedNativeWidgetImpl::CreateNSWindow(params).autorelease();
+ return remote_cocoa::NativeWidgetNSWindowBridge::CreateNSWindow(params)
+ .autorelease();
}
-BridgeFactoryHost* NativeWidgetMac::GetBridgeFactoryHost() {
+remote_cocoa::ApplicationHost*
+NativeWidgetMac::GetRemoteCocoaApplicationHost() {
return nullptr;
}
-remote_cocoa::mojom::BridgedNativeWidget* NativeWidgetMac::bridge() const {
- return bridge_host_ ? bridge_host_->bridge() : nullptr;
+remote_cocoa::mojom::NativeWidgetNSWindow* NativeWidgetMac::GetNSWindowMojo()
+ const {
+ return ns_window_host_ ? ns_window_host_->GetNSWindowMojo() : nullptr;
}
-BridgedNativeWidgetImpl* NativeWidgetMac::bridge_impl() const {
- return bridge_host_ ? bridge_host_->bridge_impl() : nullptr;
+remote_cocoa::NativeWidgetNSWindowBridge*
+NativeWidgetMac::GetInProcessNSWindowBridge() const {
+ return ns_window_host_ ? ns_window_host_->GetInProcessNSWindowBridge()
+ : nullptr;
}
////////////////////////////////////////////////////////////////////////////////
@@ -776,9 +831,9 @@ NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeView(
// static
NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeWindow(
gfx::NativeWindow window) {
- if (BridgedNativeWidgetHostImpl* bridge_host_impl =
- BridgedNativeWidgetHostImpl::GetFromNativeWindow(window)) {
- return bridge_host_impl->native_widget_mac();
+ if (NativeWidgetMacNSWindowHost* ns_window_host_impl =
+ NativeWidgetMacNSWindowHost::GetFromNativeWindow(window)) {
+ return ns_window_host_impl->native_widget_mac();
}
return nullptr; // Not created by NativeWidgetMac.
}
@@ -786,21 +841,21 @@ NativeWidgetPrivate* NativeWidgetPrivate::GetNativeWidgetForNativeWindow(
// static
NativeWidgetPrivate* NativeWidgetPrivate::GetTopLevelNativeWidget(
gfx::NativeView native_view) {
- BridgedNativeWidgetHostImpl* bridge_host =
- BridgedNativeWidgetHostImpl::GetFromNativeView(native_view);
- if (!bridge_host)
+ NativeWidgetMacNSWindowHost* window_host =
+ NativeWidgetMacNSWindowHost::GetFromNativeView(native_view);
+ if (!window_host)
return nullptr;
- while (bridge_host->parent())
- bridge_host = bridge_host->parent();
- return bridge_host->native_widget_mac();
+ while (window_host->parent())
+ window_host = window_host->parent();
+ return window_host->native_widget_mac();
}
// static
void NativeWidgetPrivate::GetAllChildWidgets(gfx::NativeView native_view,
Widget::Widgets* children) {
- BridgedNativeWidgetHostImpl* bridge_host =
- BridgedNativeWidgetHostImpl::GetFromNativeView(native_view);
- if (!bridge_host) {
+ NativeWidgetMacNSWindowHost* window_host =
+ NativeWidgetMacNSWindowHost::GetFromNativeView(native_view);
+ if (!window_host) {
NSView* ns_view = native_view.GetNativeNSView();
// The NSWindow is not itself a views::Widget, but it may have children that
// are. Support returning Widgets that are parented to the NSWindow, except:
@@ -824,37 +879,37 @@ void NativeWidgetPrivate::GetAllChildWidgets(gfx::NativeView native_view,
// If |native_view| is a subview of the contentView, it will share an
// NSWindow, but will itself be a native child of the Widget. That is, adding
- // bridge_host->..->GetWidget() to |children| would be adding the _parent_ of
+ // window_host->..->GetWidget() to |children| would be adding the _parent_ of
// |native_view|, not the Widget for |native_view|. |native_view| doesn't have
// a corresponding Widget of its own in this case (and so can't have Widget
// children of its own on Mac).
- if (bridge_host->native_widget_mac()->GetNativeView() != native_view)
+ if (window_host->native_widget_mac()->GetNativeView() != native_view)
return;
// Code expects widget for |native_view| to be added to |children|.
- if (bridge_host->native_widget_mac()->GetWidget())
- children->insert(bridge_host->native_widget_mac()->GetWidget());
+ if (window_host->native_widget_mac()->GetWidget())
+ children->insert(window_host->native_widget_mac()->GetWidget());
// When the NSWindow *is* a Widget, only consider children(). I.e. do not
- // look through -[NSWindow childWindows] as done for the (!bridge_host) case
+ // look through -[NSWindow childWindows] as done for the (!window_host) case
// above. -childWindows does not support hidden windows, and anything in there
// which is not in children() would have been added by AppKit.
- for (BridgedNativeWidgetHostImpl* child : bridge_host->children())
+ for (NativeWidgetMacNSWindowHost* child : window_host->children())
GetAllChildWidgets(child->native_widget_mac()->GetNativeView(), children);
}
// static
void NativeWidgetPrivate::GetAllOwnedWidgets(gfx::NativeView native_view,
Widget::Widgets* owned) {
- BridgedNativeWidgetHostImpl* bridge_host =
- BridgedNativeWidgetHostImpl::GetFromNativeView(native_view);
- if (!bridge_host) {
+ NativeWidgetMacNSWindowHost* window_host =
+ NativeWidgetMacNSWindowHost::GetFromNativeView(native_view);
+ if (!window_host) {
GetAllChildWidgets(native_view, owned);
return;
}
- if (bridge_host->native_widget_mac()->GetNativeView() != native_view)
+ if (window_host->native_widget_mac()->GetNativeView() != native_view)
return;
- for (BridgedNativeWidgetHostImpl* child : bridge_host->children())
+ for (NativeWidgetMacNSWindowHost* child : window_host->children())
GetAllChildWidgets(child->native_widget_mac()->GetNativeView(), owned);
}
@@ -869,25 +924,25 @@ void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView native_view,
return;
}
- BridgedNativeWidgetHostImpl* bridge_host =
- BridgedNativeWidgetHostImpl::GetFromNativeView(native_view);
- DCHECK(bridge_host);
+ NativeWidgetMacNSWindowHost* window_host =
+ NativeWidgetMacNSWindowHost::GetFromNativeView(native_view);
+ DCHECK(window_host);
gfx::NativeView bridge_view =
- bridge_host->native_widget_mac()->GetNativeView();
+ window_host->native_widget_mac()->GetNativeView();
gfx::NativeWindow bridge_window =
- bridge_host->native_widget_mac()->GetNativeWindow();
+ window_host->native_widget_mac()->GetNativeWindow();
bool bridge_is_top_level =
- bridge_host->native_widget_mac()->GetWidget()->is_top_level();
+ window_host->native_widget_mac()->GetWidget()->is_top_level();
DCHECK([native_view.GetNativeNSView()
isDescendantOf:bridge_view.GetNativeNSView()]);
DCHECK(bridge_window && ![bridge_window.GetNativeNSWindow() isSheet]);
- BridgedNativeWidgetHostImpl* parent_bridge_host =
- BridgedNativeWidgetHostImpl::GetFromNativeView(new_parent);
+ NativeWidgetMacNSWindowHost* parent_window_host =
+ NativeWidgetMacNSWindowHost::GetFromNativeView(new_parent);
// Early out for no-op changes.
if (native_view == bridge_view && bridge_is_top_level &&
- bridge_host->parent() == parent_bridge_host) {
+ window_host->parent() == parent_window_host) {
return;
}
@@ -899,13 +954,13 @@ void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView native_view,
child->NotifyNativeViewHierarchyWillChange();
// Update |brige_host|'s parent only if
- // BridgedNativeWidgetImpl::ReparentNativeView will.
+ // NativeWidgetNSWindowBridge::ReparentNativeView will.
if (native_view == bridge_view) {
- bridge_host->SetParent(parent_bridge_host);
+ window_host->SetParent(parent_window_host);
if (!bridge_is_top_level) {
- // Make |bridge_host|'s NSView be a child of |new_parent| by adding it as
+ // Make |window_host|'s NSView be a child of |new_parent| by adding it as
// a subview. Note that this will have the effect of removing
- // |bridge_host|'s NSView from its NSWindow. The |NSWindow| must remain
+ // |window_host|'s NSView from its NSWindow. The |NSWindow| must remain
// visible because it controls the bounds and visibility of the ui::Layer,
// so just hide it by setting alpha value to zero.
// TODO(ccameron): This path likely violates assumptions. Verify that this
@@ -930,15 +985,9 @@ void NativeWidgetPrivate::ReparentNativeView(gfx::NativeView native_view,
}
// static
-gfx::FontList NativeWidgetPrivate::GetWindowTitleFontList() {
- NOTIMPLEMENTED();
- return gfx::FontList();
-}
-
-// static
gfx::NativeView NativeWidgetPrivate::GetGlobalCapture(
gfx::NativeView native_view) {
- return BridgedNativeWidgetHostImpl::GetGlobalCaptureView();
+ return NativeWidgetMacNSWindowHost::GetGlobalCaptureView();
}
} // namespace internal
diff --git a/chromium/ui/views/widget/native_widget_mac_unittest.mm b/chromium/ui/views/widget/native_widget_mac_unittest.mm
index 94a6c99e4e3..5974ae32fbe 100644
--- a/chromium/ui/views/widget/native_widget_mac_unittest.mm
+++ b/chromium/ui/views/widget/native_widget_mac_unittest.mm
@@ -20,8 +20,8 @@
#include "base/test/test_timeouts.h"
#include "base/threading/thread_task_runner_handle.h"
#import "components/remote_cocoa/app_shim/bridged_content_view.h"
-#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h"
#import "components/remote_cocoa/app_shim/native_widget_mac_nswindow.h"
+#import "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h"
#import "testing/gtest_mac.h"
#include "third_party/skia/include/core/SkBitmap.h"
#include "third_party/skia/include/core/SkCanvas.h"
@@ -33,7 +33,7 @@
#include "ui/events/test/event_generator.h"
#import "ui/gfx/mac/coordinate_conversion.h"
#include "ui/views/bubble/bubble_dialog_delegate_view.h"
-#include "ui/views/cocoa/bridged_native_widget_host_impl.h"
+#include "ui/views/cocoa/native_widget_mac_ns_window_host.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/label.h"
#include "ui/views/controls/native/native_view_host.h"
@@ -92,12 +92,12 @@
namespace views {
namespace test {
-// BridgedNativeWidgetImpl friend to access private members.
+// NativeWidgetNSWindowBridge friend to access private members.
class BridgedNativeWidgetTestApi {
public:
explicit BridgedNativeWidgetTestApi(NSWindow* window) {
- bridge_ =
- BridgedNativeWidgetHostImpl::GetFromNativeWindow(window)->bridge_impl();
+ bridge_ = NativeWidgetMacNSWindowHost::GetFromNativeWindow(window)
+ ->GetInProcessNSWindowBridge();
}
// Simulate a frame swap from the compositor.
@@ -116,7 +116,7 @@ class BridgedNativeWidgetTestApi {
}
private:
- BridgedNativeWidgetImpl* bridge_;
+ remote_cocoa::NativeWidgetNSWindowBridge* bridge_;
DISALLOW_COPY_AND_ASSIGN(BridgedNativeWidgetTestApi);
};
@@ -152,7 +152,7 @@ class TestWindowNativeWidgetMac : public NativeWidgetMac {
DISALLOW_COPY_AND_ASSIGN(TestWindowNativeWidgetMac);
};
-// Tests for parts of NativeWidgetMac not covered by BridgedNativeWidgetImpl,
+// Tests for parts of NativeWidgetMac not covered by NativeWidgetNSWindowBridge,
// which need access to Cocoa APIs.
class NativeWidgetMacTest : public WidgetTest {
public:
@@ -782,8 +782,8 @@ TEST_F(NativeWidgetMacTest, NonWidgetParent) {
EXPECT_NE(child, top_level_widget->GetWidget());
// To verify the parent, we need to use NativeWidgetMac APIs.
- BridgedNativeWidgetHostImpl* bridged_native_widget_host =
- BridgedNativeWidgetHostImpl::GetFromNativeWindow(
+ NativeWidgetMacNSWindowHost* bridged_native_widget_host =
+ NativeWidgetMacNSWindowHost::GetFromNativeWindow(
child->GetNativeWindow());
EXPECT_EQ(bridged_native_widget_host->parent()
->native_widget_mac()
@@ -1331,7 +1331,7 @@ TEST_F(NativeWidgetMacTest, ShowAnimationControl) {
EXPECT_TRUE([retained_animation isAnimating]);
// Hide without waiting for the animation to complete. Animation should cancel
- // and clear references from BridgedNativeWidgetImpl.
+ // and clear references from NativeWidgetNSWindowBridge.
modal_dialog_widget->Hide();
EXPECT_FALSE([retained_animation isAnimating]);
EXPECT_FALSE(test_api.show_animation());
@@ -1434,12 +1434,12 @@ TEST_F(NativeWidgetMacTest, WindowModalSheet) {
// TODO(tapted): Ideally [native_parent orderOut:nil] would also work here.
// But it does not. AppKit's childWindow management breaks down after an
- // -orderOut: (see BridgedNativeWidgetImpl::OnVisibilityChanged()). For
- // regular child windows, BridgedNativeWidgetImpl fixes the behavior with its
- // own management. However, it can't do that for sheets without encountering
- // http://crbug.com/605098 and http://crbug.com/667602. -[NSApp hide:] makes
- // the NSWindow hidden in a different way, which does not break like
- // -orderOut: does. Which is good, because a user can always do -[NSApp
+ // -orderOut: (see NativeWidgetNSWindowBridge::OnVisibilityChanged()). For
+ // regular child windows, NativeWidgetNSWindowBridge fixes the behavior with
+ // its own management. However, it can't do that for sheets without
+ // encountering http://crbug.com/605098 and http://crbug.com/667602. -[NSApp
+ // hide:] makes the NSWindow hidden in a different way, which does not break
+ // like -orderOut: does. Which is good, because a user can always do -[NSApp
// hide:], e.g., with Cmd+h, and that needs to work correctly.
[NSApp hide:nil];
@@ -1620,14 +1620,14 @@ TEST_F(NativeWidgetMacTest, NoopReparentNativeView) {
NSWindow* parent = MakeBorderlessNativeParent();
Widget* dialog = views::DialogDelegate::CreateDialogWidget(
new DialogDelegateView, nullptr, [parent contentView]);
- BridgedNativeWidgetHostImpl* bridge_host =
- BridgedNativeWidgetHostImpl::GetFromNativeWindow(
+ NativeWidgetMacNSWindowHost* window_host =
+ NativeWidgetMacNSWindowHost::GetFromNativeWindow(
dialog->GetNativeWindow());
- EXPECT_EQ(bridge_host->parent()->native_widget_mac()->GetNativeWindow(),
+ EXPECT_EQ(window_host->parent()->native_widget_mac()->GetNativeWindow(),
parent);
Widget::ReparentNativeView(dialog->GetNativeView(), [parent contentView]);
- EXPECT_EQ(bridge_host->parent()->native_widget_mac()->GetNativeWindow(),
+ EXPECT_EQ(window_host->parent()->native_widget_mac()->GetNativeWindow(),
parent);
[parent close];
@@ -1636,13 +1636,13 @@ TEST_F(NativeWidgetMacTest, NoopReparentNativeView) {
parent = parent_widget->GetNativeWindow().GetNativeNSWindow();
dialog = views::DialogDelegate::CreateDialogWidget(
new DialogDelegateView, nullptr, [parent contentView]);
- bridge_host = BridgedNativeWidgetHostImpl::GetFromNativeWindow(
+ window_host = NativeWidgetMacNSWindowHost::GetFromNativeWindow(
dialog->GetNativeWindow());
- EXPECT_EQ(bridge_host->parent()->native_widget_mac()->GetNativeWindow(),
+ EXPECT_EQ(window_host->parent()->native_widget_mac()->GetNativeWindow(),
parent);
Widget::ReparentNativeView(dialog->GetNativeView(), [parent contentView]);
- EXPECT_EQ(bridge_host->parent()->native_widget_mac()->GetNativeWindow(),
+ EXPECT_EQ(window_host->parent()->native_widget_mac()->GetNativeWindow(),
parent);
parent_widget->CloseNow();
@@ -2202,9 +2202,9 @@ class NativeWidgetMacFullKeyboardAccessTest : public NativeWidgetMacTest {
NativeWidgetMacTest::SetUp();
widget_ = CreateTopLevelPlatformWidget();
- bridge_ = BridgedNativeWidgetHostImpl::GetFromNativeWindow(
+ bridge_ = NativeWidgetMacNSWindowHost::GetFromNativeWindow(
widget_->GetNativeWindow())
- ->bridge_impl();
+ ->GetInProcessNSWindowBridge();
fake_full_keyboard_access_ =
ui::test::ScopedFakeFullKeyboardAccess::GetInstance();
DCHECK(fake_full_keyboard_access_);
@@ -2217,7 +2217,7 @@ class NativeWidgetMacFullKeyboardAccessTest : public NativeWidgetMacTest {
}
Widget* widget_ = nullptr;
- BridgedNativeWidgetImpl* bridge_ = nullptr;
+ remote_cocoa::NativeWidgetNSWindowBridge* bridge_ = nullptr;
ui::test::ScopedFakeFullKeyboardAccess* fake_full_keyboard_access_ = nullptr;
};
diff --git a/chromium/ui/views/widget/native_widget_private.cc b/chromium/ui/views/widget/native_widget_private.cc
index 1983a9cdbc6..a5933a86da9 100644
--- a/chromium/ui/views/widget/native_widget_private.cc
+++ b/chromium/ui/views/widget/native_widget_private.cc
@@ -26,7 +26,5 @@ void NativeWidgetPrivate::ShowEmojiPanel() {
ui::ShowEmojiPanel();
}
-void NativeWidgetPrivate::OnCanActivateChanged() {}
-
} // namespace internal
} // namespace views
diff --git a/chromium/ui/views/widget/native_widget_private.h b/chromium/ui/views/widget/native_widget_private.h
index 27f114fb516..84acc003c84 100644
--- a/chromium/ui/views/widget/native_widget_private.h
+++ b/chromium/ui/views/widget/native_widget_private.h
@@ -15,7 +15,6 @@
#include "ui/views/widget/widget.h"
namespace gfx {
-class FontList;
class ImageSkia;
class Rect;
}
@@ -70,8 +69,6 @@ class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget {
static void ReparentNativeView(gfx::NativeView native_view,
gfx::NativeView new_parent);
- static gfx::FontList GetWindowTitleFontList();
-
// Returns the NativeView with capture, otherwise NULL if there is no current
// capture set, or if |native_view| has no root.
static gfx::NativeView GetGlobalCapture(gfx::NativeView native_view);
@@ -190,8 +187,8 @@ class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget {
virtual void Activate() = 0;
virtual void Deactivate() = 0;
virtual bool IsActive() const = 0;
- virtual void SetAlwaysOnTop(bool always_on_top) = 0;
- virtual bool IsAlwaysOnTop() const = 0;
+ virtual void SetZOrderLevel(ui::ZOrderLevel order) = 0;
+ virtual ui::ZOrderLevel GetZOrderLevel() const = 0;
virtual void SetVisibleOnAllWorkspaces(bool always_visible) = 0;
virtual bool IsVisibleOnAllWorkspaces() const = 0;
virtual void Maximize() = 0;
@@ -207,7 +204,7 @@ class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget {
virtual void SetAspectRatio(const gfx::SizeF& aspect_ratio) = 0;
virtual void FlashFrame(bool flash) = 0;
virtual void RunShellDrag(View* view,
- const ui::OSExchangeData& data,
+ std::unique_ptr<ui::OSExchangeData> data,
const gfx::Point& location,
int operation,
ui::DragDropTypes::DragEventSource source) = 0;
@@ -233,7 +230,6 @@ class VIEWS_EXPORT NativeWidgetPrivate : public NativeWidget {
virtual bool IsTranslucentWindowOpacitySupported() const = 0;
virtual ui::GestureRecognizer* GetGestureRecognizer() = 0;
virtual void OnSizeConstraintsChanged() = 0;
- virtual void OnCanActivateChanged();
// Returns an internal name that matches the name of the associated Widget.
virtual std::string GetName() const = 0;
diff --git a/chromium/ui/views/widget/root_view.cc b/chromium/ui/views/widget/root_view.cc
index 9a79e764159..836fb739a14 100644
--- a/chromium/ui/views/widget/root_view.cc
+++ b/chromium/ui/views/widget/root_view.cc
@@ -141,9 +141,6 @@ class PostEventDispatchHandler : public ui::EventHandler {
DISALLOW_COPY_AND_ASSIGN(PostEventDispatchHandler);
};
-// static
-const char RootView::kViewClassName[] = "RootView";
-
////////////////////////////////////////////////////////////////////////////////
// RootView, public:
@@ -175,8 +172,7 @@ RootView::RootView(Widget* widget)
RootView::~RootView() {
// If we have children remove them explicitly so to make sure a remove
// notification is sent for each one of them.
- if (!children().empty())
- RemoveAllChildViews(true);
+ RemoveAllChildViews(true);
}
// Tree operations -------------------------------------------------------------
@@ -319,10 +315,6 @@ bool RootView::IsDrawn() const {
return GetVisible();
}
-const char* RootView::GetClassName() const {
- return kViewClassName;
-}
-
void RootView::SchedulePaintInRect(const gfx::Rect& rect) {
if (layer()) {
layer()->SchedulePaint(rect);
@@ -616,7 +608,7 @@ void RootView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
void RootView::UpdateParentLayer() {
if (layer())
- ReparentLayer(gfx::Vector2d(GetMirroredX(), y()), widget_->GetLayer());
+ ReparentLayer(widget_->GetLayer());
}
////////////////////////////////////////////////////////////////////////////////
@@ -767,5 +759,8 @@ ui::EventDispatchDetails RootView::PostDispatchEvent(ui::EventTarget* target,
return details;
}
+BEGIN_METADATA(RootView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
} // namespace internal
} // namespace views
diff --git a/chromium/ui/views/widget/root_view.h b/chromium/ui/views/widget/root_view.h
index 224a1a4db6c..02d38107754 100644
--- a/chromium/ui/views/widget/root_view.h
+++ b/chromium/ui/views/widget/root_view.h
@@ -52,7 +52,7 @@ class VIEWS_EXPORT RootView : public View,
public FocusTraversable,
public ui::EventProcessor {
public:
- static const char kViewClassName[];
+ METADATA_HEADER(RootView);
// Creation and lifetime -----------------------------------------------------
explicit RootView(Widget* widget);
@@ -107,7 +107,6 @@ class VIEWS_EXPORT RootView : public View,
const Widget* GetWidget() const override;
Widget* GetWidget() override;
bool IsDrawn() const override;
- const char* GetClassName() const override;
void SchedulePaintInRect(const gfx::Rect& rect) override;
bool OnMousePressed(const ui::MouseEvent& event) override;
bool OnMouseDragged(const ui::MouseEvent& event) override;
diff --git a/chromium/ui/views/widget/widget.cc b/chromium/ui/views/widget/widget.cc
index 0f01bf0c73c..0cb75272c2c 100644
--- a/chromium/ui/views/widget/widget.cc
+++ b/chromium/ui/views/widget/widget.cc
@@ -13,7 +13,6 @@
#include "base/macros.h"
#include "base/strings/utf_string_conversions.h"
#include "base/trace_event/trace_event.h"
-#include "ui/aura/window.h"
#include "ui/base/cursor/cursor.h"
#include "ui/base/default_style.h"
#include "ui/base/default_theme_provider.h"
@@ -150,7 +149,6 @@ Widget::InitParams::InitParams(Type type)
opacity(INFER_OPACITY),
accept_events(true),
activatable(ACTIVATABLE_DEFAULT),
- keep_on_top(type == TYPE_MENU || type == TYPE_DRAG),
visible_on_all_workspaces(false),
ownership(NATIVE_WIDGET_OWNS_WIDGET),
mirror_origin_in_rtl(false),
@@ -178,6 +176,22 @@ bool Widget::InitParams::CanActivate() const {
type != InitParams::TYPE_DRAG;
}
+ui::ZOrderLevel Widget::InitParams::EffectiveZOrderLevel() const {
+ if (z_order.has_value())
+ return z_order.value();
+
+ switch (type) {
+ case TYPE_MENU:
+ return ui::ZOrderLevel::kFloatingWindow;
+ break;
+ case TYPE_DRAG:
+ return ui::ZOrderLevel::kFloatingUIElement;
+ break;
+ default:
+ return ui::ZOrderLevel::kNormal;
+ }
+}
+
////////////////////////////////////////////////////////////////////////////////
// Widget, public:
@@ -629,6 +643,8 @@ void Widget::Show() {
const ui::Layer* layer = GetLayer();
TRACE_EVENT1("views", "Widget::Show", "layer",
layer ? layer->name() : "none");
+ ui::WindowShowState preferred_show_state =
+ CanActivate() ? ui::SHOW_STATE_NORMAL : ui::SHOW_STATE_INACTIVE;
if (non_client_view_) {
// While initializing, the kiosk mode will go to full screen before the
// widget gets shown. In that case we stay in full screen mode, regardless
@@ -645,11 +661,9 @@ void Widget::Show() {
// |saved_show_state_| only applies the first time the window is shown.
// If we don't reset the value the window may be shown maximized every time
// it is subsequently shown after being hidden.
- saved_show_state_ = ui::SHOW_STATE_NORMAL;
+ saved_show_state_ = preferred_show_state;
} else {
- native_widget_->Show(
- CanActivate() ? ui::SHOW_STATE_NORMAL : ui::SHOW_STATE_INACTIVE,
- gfx::Rect());
+ native_widget_->Show(preferred_show_state, gfx::Rect());
}
}
@@ -683,12 +697,12 @@ bool Widget::IsActive() const {
return native_widget_->IsActive();
}
-void Widget::SetAlwaysOnTop(bool on_top) {
- native_widget_->SetAlwaysOnTop(on_top);
+void Widget::SetZOrderLevel(ui::ZOrderLevel order) {
+ native_widget_->SetZOrderLevel(order);
}
-bool Widget::IsAlwaysOnTop() const {
- return native_widget_->IsAlwaysOnTop();
+ui::ZOrderLevel Widget::GetZOrderLevel() const {
+ return native_widget_->GetZOrderLevel();
}
void Widget::SetVisibleOnAllWorkspaces(bool always_visible) {
@@ -808,7 +822,7 @@ ui::InputMethod* Widget::GetInputMethod() {
}
void Widget::RunShellDrag(View* view,
- const ui::OSExchangeData& data,
+ std::unique_ptr<ui::OSExchangeData> data,
const gfx::Point& location,
int operation,
ui::DragDropTypes::DragEventSource source) {
@@ -819,7 +833,8 @@ void Widget::RunShellDrag(View* view,
observer.OnWidgetDragWillStart(this);
WidgetDeletionObserver widget_deletion_observer(this);
- native_widget_->RunShellDrag(view, data, location, operation, source);
+ native_widget_->RunShellDrag(view, std::move(data), location, operation,
+ source);
// The widget may be destroyed during the drag operation.
if (!widget_deletion_observer.IsWidgetAlive())
@@ -1044,11 +1059,6 @@ void Widget::OnSizeConstraintsChanged() {
void Widget::OnOwnerClosing() {}
-void Widget::OnCanActivateChanged() {
- if (native_widget_)
- native_widget_->OnCanActivateChanged();
-}
-
std::string Widget::GetName() const {
return native_widget_->GetName();
}
@@ -1515,6 +1525,10 @@ void Widget::DestroyRootView() {
focus_manager_->SetFocusedView(nullptr);
NotifyWillRemoveView(root_view_.get());
non_client_view_ = nullptr;
+ // Remove all children before the unique_ptr reset so that
+ // GetWidget()->GetRootView() doesn't return nullptr while the views hierarchy
+ // is being torn down.
+ root_view_->RemoveAllChildViews(true);
root_view_.reset();
}
@@ -1638,8 +1652,8 @@ void Widget::UnlockPaintAsActive() {
}
void Widget::UpdatePaintAsActiveState(bool paint_as_active) {
- if (non_client_view())
- non_client_view()->frame_view()->PaintAsActiveChanged(paint_as_active);
+ if (non_client_view_)
+ non_client_view_->frame_view()->PaintAsActiveChanged(paint_as_active);
if (widget_delegate())
widget_delegate()->OnPaintAsActiveChanged(paint_as_active);
}
diff --git a/chromium/ui/views/widget/widget.h b/chromium/ui/views/widget/widget.h
index 8a073d74f34..83ba608199b 100644
--- a/chromium/ui/views/widget/widget.h
+++ b/chromium/ui/views/widget/widget.h
@@ -217,6 +217,10 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// case where |activatable| is |ACTIVATABLE_DEFAULT|.
bool CanActivate() const;
+ // Returns the z-order level, based on the overriding |z_order| but also
+ // taking into account special levels due to |type|.
+ ui::ZOrderLevel EffectiveZOrderLevel() const;
+
Type type;
// If null, a default implementation will be constructed. The default
// implementation deletes itself when the Widget closes.
@@ -234,7 +238,7 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
WindowOpacity opacity;
bool accept_events;
Activatable activatable;
- bool keep_on_top;
+ base::Optional<ui::ZOrderLevel> z_order;
bool visible_on_all_workspaces;
// See Widget class comment above.
Ownership ownership;
@@ -294,7 +298,6 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
std::string wm_class_class;
// If true then the widget uses software compositing. Defaults to false.
- // Only used on Windows.
bool force_software_compositing;
// Used if widget is not activatable to do determine if mouse events should
@@ -537,12 +540,11 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// Returns whether the Widget is the currently active window.
virtual bool IsActive() const;
- // Sets the widget to be on top of all other widgets in the windowing system.
- void SetAlwaysOnTop(bool on_top);
+ // Sets the z-order of the widget. This only applies to top-level widgets.
+ void SetZOrderLevel(ui::ZOrderLevel order);
- // Returns whether the widget has been set to be on top of most other widgets
- // in the windowing system.
- bool IsAlwaysOnTop() const;
+ // Gets the z-order of the widget. This only applies to top-level widgets.
+ ui::ZOrderLevel GetZOrderLevel() const;
// Sets the widget to be visible on all work spaces.
void SetVisibleOnAllWorkspaces(bool always_visible);
@@ -627,7 +629,7 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// OnDragDone() is called on it. |location| is in the widget's coordinate
// system.
void RunShellDrag(View* view,
- const ui::OSExchangeData& data,
+ std::unique_ptr<ui::OSExchangeData> data,
const gfx::Point& location,
int operation,
ui::DragDropTypes::DragEventSource source);
@@ -814,9 +816,6 @@ class VIEWS_EXPORT Widget : public internal::NativeWidgetDelegate,
// Called when the delegate's CanResize or CanMaximize changes.
void OnSizeConstraintsChanged();
- // Called when WidgetDelegate::CanActivate() changes.
- void OnCanActivateChanged();
-
// Notification that our owner is closing.
// NOTE: this is not invoked for aura as it's currently not needed there.
// Under aura menus close by way of activation getting reset when the owner
diff --git a/chromium/ui/views/widget/widget_delegate.cc b/chromium/ui/views/widget/widget_delegate.cc
index 570fefddf39..703ee49a88e 100644
--- a/chromium/ui/views/widget/widget_delegate.cc
+++ b/chromium/ui/views/widget/widget_delegate.cc
@@ -23,16 +23,7 @@ WidgetDelegate::~WidgetDelegate() {
}
void WidgetDelegate::SetCanActivate(bool can_activate) {
- if (can_activate == can_activate_)
- return;
-
- const bool previous_value = CanActivate();
can_activate_ = can_activate;
- if (previous_value != CanActivate()) {
- Widget* widget = GetWidget();
- if (widget)
- widget->OnCanActivateChanged();
- }
}
void WidgetDelegate::OnWidgetMove() {
@@ -190,8 +181,6 @@ bool WidgetDelegate::ShouldDescendIntoChildForEventHandling(
////////////////////////////////////////////////////////////////////////////////
// WidgetDelegateView:
-// static
-const char WidgetDelegateView::kViewClassName[] = "WidgetDelegateView";
WidgetDelegateView::WidgetDelegateView() {
// A WidgetDelegate should be deleted on DeleteDelegate.
@@ -216,8 +205,8 @@ views::View* WidgetDelegateView::GetContentsView() {
return this;
}
-const char* WidgetDelegateView::GetClassName() const {
- return kViewClassName;
-}
+BEGIN_METADATA(WidgetDelegateView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
} // namespace views
diff --git a/chromium/ui/views/widget/widget_delegate.h b/chromium/ui/views/widget/widget_delegate.h
index 1f827524f4b..77585733e69 100644
--- a/chromium/ui/views/widget/widget_delegate.h
+++ b/chromium/ui/views/widget/widget_delegate.h
@@ -212,8 +212,7 @@ class VIEWS_EXPORT WidgetDelegate {
// view's hierarchy and is expected to be deleted on DeleteDelegate call.
class VIEWS_EXPORT WidgetDelegateView : public WidgetDelegate, public View {
public:
- // Internal class name.
- static const char kViewClassName[];
+ METADATA_HEADER(WidgetDelegateView);
WidgetDelegateView();
~WidgetDelegateView() override;
@@ -224,9 +223,6 @@ class VIEWS_EXPORT WidgetDelegateView : public WidgetDelegate, public View {
const Widget* GetWidget() const override;
views::View* GetContentsView() override;
- // View:
- const char* GetClassName() const override;
-
private:
DISALLOW_COPY_AND_ASSIGN(WidgetDelegateView);
};
diff --git a/chromium/ui/views/widget/widget_hwnd_utils.cc b/chromium/ui/views/widget/widget_hwnd_utils.cc
index 5bcb8d8b9ba..9edfa2c00c4 100644
--- a/chromium/ui/views/widget/widget_hwnd_utils.cc
+++ b/chromium/ui/views/widget/widget_hwnd_utils.cc
@@ -45,7 +45,7 @@ void CalculateWindowStylesFromInitParams(
DCHECK_NE(Widget::InitParams::ACTIVATABLE_DEFAULT, params.activatable);
if (params.activatable == Widget::InitParams::ACTIVATABLE_NO)
*ex_style |= WS_EX_NOACTIVATE;
- if (params.keep_on_top)
+ if (params.EffectiveZOrderLevel() != ui::ZOrderLevel::kNormal)
*ex_style |= WS_EX_TOPMOST;
if (params.mirror_origin_in_rtl)
*ex_style |= l10n_util::GetExtendedTooltipStyles();
@@ -109,6 +109,9 @@ void CalculateWindowStylesFromInitParams(
case Widget::InitParams::TYPE_MENU:
*style |= WS_POPUP;
break;
+ case Widget::InitParams::TYPE_TOOLTIP:
+ *style |= WS_POPUP;
+ break;
default:
NOTREACHED();
}
diff --git a/chromium/ui/views/widget/widget_interactive_uitest.cc b/chromium/ui/views/widget/widget_interactive_uitest.cc
index afd98271104..75467723dfd 100644
--- a/chromium/ui/views/widget/widget_interactive_uitest.cc
+++ b/chromium/ui/views/widget/widget_interactive_uitest.cc
@@ -19,7 +19,6 @@
#include "base/timer/timer.h"
#include "base/win/windows_version.h"
#include "build/build_config.h"
-#include "ui/aura/window.h"
#include "ui/base/ime/input_method.h"
#include "ui/base/ime/text_input_client.h"
#include "ui/base/resource/resource_bundle.h"
@@ -45,6 +44,7 @@
#include "ui/wm/public/activation_client.h"
#if defined(OS_WIN)
+#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/views/widget/desktop_aura/desktop_native_widget_aura.h"
#include "ui/views/win/hwnd_util.h"
diff --git a/chromium/ui/views/widget/widget_unittest.cc b/chromium/ui/views/widget/widget_unittest.cc
index 9571a4f9477..64a5731a565 100644
--- a/chromium/ui/views/widget/widget_unittest.cc
+++ b/chromium/ui/views/widget/widget_unittest.cc
@@ -588,8 +588,8 @@ TEST_P(WidgetWithDestroyedNativeViewTest, Test) {
widget.Activate();
widget.Deactivate();
widget.IsActive();
- widget.SetAlwaysOnTop(true);
- widget.IsAlwaysOnTop();
+ widget.SetZOrderLevel(ui::ZOrderLevel::kNormal);
+ widget.GetZOrderLevel();
widget.Maximize();
widget.Minimize();
widget.Restore();
@@ -3692,14 +3692,14 @@ TEST_F(DesktopWidgetTest, DISABLED_DestroyInSysCommandNCLButtonDownOnCaption) {
#endif
-// Test that SetAlwaysOnTop and IsAlwaysOnTop are consistent.
-TEST_F(WidgetTest, AlwaysOnTop) {
+// Test that the z-order levels round-trip.
+TEST_F(WidgetTest, ZOrderLevel) {
WidgetAutoclosePtr widget(CreateTopLevelNativeWidget());
- EXPECT_FALSE(widget->IsAlwaysOnTop());
- widget->SetAlwaysOnTop(true);
- EXPECT_TRUE(widget->IsAlwaysOnTop());
- widget->SetAlwaysOnTop(false);
- EXPECT_FALSE(widget->IsAlwaysOnTop());
+ EXPECT_EQ(ui::ZOrderLevel::kNormal, widget->GetZOrderLevel());
+ widget->SetZOrderLevel(ui::ZOrderLevel::kFloatingWindow);
+ EXPECT_EQ(ui::ZOrderLevel::kFloatingWindow, widget->GetZOrderLevel());
+ widget->SetZOrderLevel(ui::ZOrderLevel::kNormal);
+ EXPECT_EQ(ui::ZOrderLevel::kNormal, widget->GetZOrderLevel());
}
namespace {
@@ -4201,7 +4201,7 @@ class CompositingWidgetTest : public DesktopWidgetTest {
const Widget::InitParams::WindowOpacity opacity) {
for (const auto& widget_type : widget_types_) {
#if defined(OS_MACOSX)
- // Tooltips are native on Mac. See BridgedNativeWidgetImpl::Init.
+ // Tooltips are native on Mac. See NativeWidgetNSWindowBridge::Init.
if (widget_type == Widget::InitParams::TYPE_TOOLTIP)
continue;
#elif defined(OS_WIN)
diff --git a/chromium/ui/views/widget/widget_utils_mac.mm b/chromium/ui/views/widget/widget_utils_mac.mm
index 8d843b8352b..6a3b1dce6ef 100644
--- a/chromium/ui/views/widget/widget_utils_mac.mm
+++ b/chromium/ui/views/widget/widget_utils_mac.mm
@@ -4,13 +4,13 @@
#include "ui/views/widget/widget_utils_mac.h"
-#import "components/remote_cocoa/app_shim/bridged_native_widget_impl.h"
+#import "components/remote_cocoa/app_shim/native_widget_ns_window_bridge.h"
namespace views {
gfx::Size GetWindowSizeForClientSize(Widget* widget, const gfx::Size& size) {
DCHECK(widget);
- return BridgedNativeWidgetImpl::GetWindowSizeForClientSize(
+ return remote_cocoa::NativeWidgetNSWindowBridge::GetWindowSizeForClientSize(
widget->GetNativeWindow().GetNativeNSWindow(), size);
}
diff --git a/chromium/ui/views/widget/window_reorderer.cc b/chromium/ui/views/widget/window_reorderer.cc
index 003f6549333..ce52ff296c5 100644
--- a/chromium/ui/views/widget/window_reorderer.cc
+++ b/chromium/ui/views/widget/window_reorderer.cc
@@ -168,19 +168,24 @@ void WindowReorderer::ReorderChildWindows() {
// windows not associated to a view are stacked above windows with an
// associated view.
for (View* view : base::Reversed(view_with_layer_order)) {
- ui::Layer* layer = view->layer();
+ std::vector<ui::Layer*> layers;
aura::Window* window = nullptr;
auto hosted_window_it = hosted_windows.find(view);
if (hosted_window_it != hosted_windows.end()) {
window = hosted_window_it->second;
- layer = window->layer();
+ layers.push_back(window->layer());
+ } else {
+ layers = view->GetLayersInOrder();
+ std::reverse(layers.begin(), layers.end());
}
- DCHECK(layer);
+ DCHECK(!layers.empty());
if (window)
parent_window_->StackChildAtBottom(window);
- children_layer_order.emplace_back(layer);
+
+ for (ui::Layer* layer : layers)
+ children_layer_order.emplace_back(layer);
}
std::reverse(children_layer_order.begin(), children_layer_order.end());
parent_window_->layer()->StackChildrenAtBottom(children_layer_order);
diff --git a/chromium/ui/views/widget/window_reorderer_unittest.cc b/chromium/ui/views/widget/window_reorderer_unittest.cc
index 856ee7e112e..32b8e67221a 100644
--- a/chromium/ui/views/widget/window_reorderer_unittest.cc
+++ b/chromium/ui/views/widget/window_reorderer_unittest.cc
@@ -259,5 +259,43 @@ TEST_F(WindowReordererTest, HostViewParentHasLayer) {
parent->Close();
}
+// Test that a layer added beneath a view is restacked correctly.
+TEST_F(WindowReordererTest, ViewWithLayerBeneath) {
+ std::unique_ptr<Widget> parent(
+ CreateControlWidget(root_window(), gfx::Rect(0, 0, 100, 100)));
+ parent->Show();
+
+ aura::Window* parent_window = parent->GetNativeWindow();
+
+ View* contents_view = new View;
+ parent->SetContentsView(contents_view);
+
+ View* view_with_layer_beneath =
+ contents_view->AddChildView(std::make_unique<View>());
+ ui::Layer layer_beneath;
+ view_with_layer_beneath->AddLayerBeneathView(&layer_beneath);
+
+ ASSERT_NE(nullptr, view_with_layer_beneath->layer());
+ view_with_layer_beneath->layer()->set_name("view");
+ layer_beneath.set_name("beneath");
+
+ // Verify that the initial ordering is correct.
+ EXPECT_EQ("beneath view",
+ ui::test::ChildLayerNamesAsString(*parent_window->layer()));
+
+ // Add a hosted window to make WindowReorderer::ReorderChildWindows() restack
+ // layers.
+ std::unique_ptr<Widget> child_widget(
+ CreateControlWidget(parent_window, gfx::Rect(gfx::Rect(0, 0, 50, 50))));
+ SetWindowAndLayerName(child_widget->GetNativeView(), "child_widget");
+ child_widget->Show();
+ View* host_view = contents_view->AddChildView(std::make_unique<View>());
+ child_widget->GetNativeView()->SetProperty(kHostViewKey, host_view);
+
+ // Verify the new order is correct.
+ EXPECT_EQ("beneath view child_widget",
+ ui::test::ChildLayerNamesAsString(*parent_window->layer()));
+}
+
} // namespace
} // namespace views
diff --git a/chromium/ui/views/win/hwnd_message_handler.cc b/chromium/ui/views/win/hwnd_message_handler.cc
index abde4d03cb3..4d674d15da3 100644
--- a/chromium/ui/views/win/hwnd_message_handler.cc
+++ b/chromium/ui/views/win/hwnd_message_handler.cc
@@ -18,6 +18,7 @@
#include "base/location.h"
#include "base/macros.h"
#include "base/message_loop/message_loop_current.h"
+#include "base/metrics/histogram_functions.h"
#include "base/single_thread_task_runner.h"
#include "base/threading/thread_task_runner_handle.h"
#include "base/time/time.h"
@@ -61,6 +62,7 @@
#include "ui/views/widget/widget_hwnd_utils.h"
#include "ui/views/win/fullscreen_handler.h"
#include "ui/views/win/hwnd_message_handler_delegate.h"
+#include "ui/views/win/hwnd_util.h"
#include "ui/views/win/scoped_fullscreen_visibility.h"
namespace views {
@@ -275,6 +277,49 @@ HitTest GetWindowResizeHitTest(UINT param) {
}
}
+void RecordDeltaBetweenTimeNowAndPerformanceCountHistogram(
+ base::TimeTicks event_time,
+ UINT64 performance_count,
+ POINTER_INPUT_TYPE pointer_input_type,
+ bool is_session_remote) {
+ // In remote session, sometimes |performance_count| drifts
+ // substantially in future compared to |TimeTicks::Now()| - enough to skew the
+ // histogram data. Additionally, user input over remote session already has
+ // lag, so user is less likely to be sensitive to the responsiveness of input
+ // in such case. So we are less concerned capturing the deltas in remote
+ // session scenario.
+ if (base::TimeTicks::IsHighResolution() && !is_session_remote) {
+ base::TimeTicks event_time_from_pointer =
+ base::TimeTicks::FromQPCValue(performance_count);
+
+ double delta_between_event_timestamps =
+ (event_time - event_time_from_pointer).InMicrosecondsF();
+ std::string pointer_type;
+ switch (pointer_input_type) {
+ case PT_PEN:
+ pointer_type = "Pen";
+ break;
+ case PT_TOUCH:
+ pointer_type = "Touch";
+ break;
+ default:
+ NOTREACHED();
+ }
+
+ std::string number_sign =
+ delta_between_event_timestamps >= 0 ? "Positive" : "Negative";
+ base::TimeDelta delta_sample_value = base::TimeDelta::FromMicroseconds(
+ std::abs(delta_between_event_timestamps));
+
+ base::UmaHistogramCustomMicrosecondsTimes(
+ base::StringPrintf("Event.%s.InputEventTimeStamp."
+ "DeltaBetweenTimeNowAndPerformanceCount.%s",
+ pointer_type.c_str(), number_sign.c_str()),
+ delta_sample_value, base::TimeDelta::FromMicroseconds(1),
+ base::TimeDelta::FromMilliseconds(30), 30);
+ }
+}
+
constexpr int kTouchDownContextResetTimeout = 500;
// Windows does not flag synthesized mouse messages from touch or pen in all
@@ -407,6 +452,7 @@ HWNDMessageHandler::HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate,
pointer_events_for_touch_(::features::IsUsingWMPointerForTouch()),
precision_touchpad_scroll_phase_enabled_(base::FeatureList::IsEnabled(
::features::kPrecisionTouchpadScrollPhase)),
+ is_remote_session_(base::win::IsCurrentSessionRemote()),
autohide_factory_(this) {}
HWNDMessageHandler::~HWNDMessageHandler() {
@@ -445,6 +491,16 @@ void HWNDMessageHandler::Init(HWND parent, const gfx::Rect& bounds) {
DCHECK(delegate_->GetHWNDMessageDelegateInputMethod());
delegate_->GetHWNDMessageDelegateInputMethod()->AddObserver(this);
+ // The usual way for UI Automation to obtain a fragment root is through
+ // WM_GETOBJECT. However, if there's a relation such as "Controller For"
+ // between element A in one window and element B in another window, UIA might
+ // call element A to discover the relation, receive a pointer to element B,
+ // then ask element B for its fragment root, without having sent WM_GETOBJECT
+ // to element B's window.
+ // So we create the fragment root now to ensure it's ready if asked for.
+ if (::switches::IsExperimentalAccessibilityPlatformUIAEnabled())
+ ax_fragment_root_ = std::make_unique<ui::AXFragmentRootWin>(hwnd(), this);
+
// Disable pen flicks (http://crbug.com/506977)
base::win::DisableFlicks(hwnd());
}
@@ -1216,6 +1272,14 @@ void HWNDMessageHandler::ApplyPanGestureFlingEnd() {
ui::ScrollEventPhase::kNone);
}
+gfx::NativeViewAccessible HWNDMessageHandler::GetChildOfAXFragmentRoot() {
+ return delegate_->GetNativeViewAccessible();
+}
+
+gfx::NativeViewAccessible HWNDMessageHandler::GetParentOfAXFragmentRoot() {
+ return nullptr;
+}
+
////////////////////////////////////////////////////////////////////////////////
// HWNDMessageHandler, private:
@@ -1769,9 +1833,6 @@ LRESULT HWNDMessageHandler::OnGetObject(UINT message,
if (is_uia_request &&
::switches::IsExperimentalAccessibilityPlatformUIAEnabled()) {
// Retrieve UIA object for the root view.
- if (!ax_fragment_root_)
- ax_fragment_root_ = std::make_unique<ui::AXFragmentRootWin>(
- hwnd(), delegate_->GetNativeViewAccessible());
Microsoft::WRL::ComPtr<IRawElementProviderSimple> root;
ax_fragment_root_->GetNativeViewAccessible()->QueryInterface(
IID_PPV_ARGS(&root));
@@ -2401,6 +2462,7 @@ void HWNDMessageHandler::OnSettingChange(UINT flags, const wchar_t* section) {
if (flags == SPI_SETWORKAREA)
delegate_->HandleWorkAreaChanged();
SetMsgHandled(FALSE);
+ is_remote_session_ = base::win::IsCurrentSessionRemote();
}
// If the work area is changing, then it could be as a result of the taskbar
@@ -2837,6 +2899,8 @@ LRESULT HWNDMessageHandler::HandleMouseEventInternal(UINT message,
}
if (message == WM_RBUTTONUP && is_right_mouse_pressed_on_caption_) {
+ // TODO(pkasting): Maybe handle this in DesktopWindowTreeHostWin, where we
+ // handle alt-space, or in the frame itself.
is_right_mouse_pressed_on_caption_ = false;
ReleaseCapture();
// |point| is in window coordinates, but WM_NCHITTEST and TrackPopupMenu()
@@ -2846,7 +2910,7 @@ LRESULT HWNDMessageHandler::HandleMouseEventInternal(UINT message,
w_param = SendMessage(hwnd(), WM_NCHITTEST, 0,
MAKELPARAM(screen_point.x, screen_point.y));
if (w_param == HTCAPTION || w_param == HTSYSMENU) {
- gfx::ShowSystemMenuAtPoint(hwnd(), gfx::Point(screen_point));
+ ShowSystemMenuAtScreenPixelLocation(hwnd(), gfx::Point(screen_point));
return 0;
}
} else if (message == WM_NCLBUTTONDOWN &&
@@ -3016,7 +3080,7 @@ LRESULT HWNDMessageHandler::HandlePointerEventTypeTouch(UINT message,
ui::GetModifiersFromKeyState());
event.latency()->AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, event_time, 1);
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, event_time);
// Release the pointer id for touch release events.
if (event_type == ui::ET_TOUCH_RELEASED)
@@ -3027,6 +3091,10 @@ LRESULT HWNDMessageHandler::HandlePointerEventTypeTouch(UINT message,
base::WeakPtr<HWNDMessageHandler> ref(msg_handler_weak_factory_.GetWeakPtr());
delegate_->HandleTouchEvent(&event);
+ RecordDeltaBetweenTimeNowAndPerformanceCountHistogram(
+ event_time, pointer_info.PerformanceCount, pointer_info.pointerType,
+ is_remote_session_);
+
if (ref) {
// Mark touch released events handled. These will usually turn into tap
// gestures, and doing this avoids propagating the event to other windows.
@@ -3076,12 +3144,16 @@ LRESULT HWNDMessageHandler::HandlePointerEventTypePen(UINT message,
// window, so use the weak ptr to check if destruction occured or not.
base::WeakPtr<HWNDMessageHandler> ref(msg_handler_weak_factory_.GetWeakPtr());
if (event) {
- if (event->IsTouchEvent())
+ if (event->IsTouchEvent()) {
delegate_->HandleTouchEvent(event->AsTouchEvent());
- else if (event->IsMouseEvent())
+ RecordDeltaBetweenTimeNowAndPerformanceCountHistogram(
+ event->time_stamp(), pointer_pen_info.pointerInfo.PerformanceCount,
+ pointer_pen_info.pointerInfo.pointerType, is_remote_session_);
+ } else if (event->IsMouseEvent()) {
delegate_->HandleMouseEvent(event->AsMouseEvent());
- else
+ } else {
NOTREACHED();
+ }
last_touch_or_pen_message_time_ = ::GetMessageTime();
}
@@ -3172,7 +3244,7 @@ void HWNDMessageHandler::GenerateTouchEvent(ui::EventType event_type,
event.set_flags(ui::GetModifiersFromKeyState());
event.latency()->AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, time_stamp, 1);
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, time_stamp);
touch_events->push_back(event);
}
diff --git a/chromium/ui/views/win/hwnd_message_handler.h b/chromium/ui/views/win/hwnd_message_handler.h
index 060aa2dc02a..7c8f2eb0019 100644
--- a/chromium/ui/views/win/hwnd_message_handler.h
+++ b/chromium/ui/views/win/hwnd_message_handler.h
@@ -22,6 +22,7 @@
#include "base/win/scoped_gdi_object.h"
#include "base/win/win_util.h"
#include "ui/accessibility/ax_enums.mojom.h"
+#include "ui/accessibility/platform/ax_fragment_root_delegate_win.h"
#include "ui/base/ime/input_method_observer.h"
#include "ui/base/ui_base_types.h"
#include "ui/base/win/window_event_target.h"
@@ -81,7 +82,8 @@ constexpr int WM_WINDOWSIZINGFINISHED = WM_USER;
// TODO(beng): This object should eventually *become* the WindowImpl.
class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl,
public ui::InputMethodObserver,
- public ui::WindowEventTarget {
+ public ui::WindowEventTarget,
+ public ui::AXFragmentRootDelegateWin {
public:
// See WindowImpl for details on |debugging_id|.
HWNDMessageHandler(HWNDMessageHandlerDelegate* delegate,
@@ -241,6 +243,10 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl,
void ApplyPanGestureFlingBegin() override;
void ApplyPanGestureFlingEnd() override;
+ // Overridden from AXFragmentRootDelegateWin.
+ gfx::NativeViewAccessible GetChildOfAXFragmentRoot() override;
+ gfx::NativeViewAccessible GetParentOfAXFragmentRoot() override;
+
void ApplyPanGestureEvent(int scroll_x,
int scroll_y,
ui::EventMomentumPhase momentum_phase,
@@ -759,6 +765,9 @@ class VIEWS_EXPORT HWNDMessageHandler : public gfx::WindowImpl,
// the first message after frame type changes.
bool needs_dwm_frame_clear_ = true;
+ // True if user is in remote session.
+ bool is_remote_session_;
+
// This is a map of the HMONITOR to full screeen window instance. It is safe
// to keep a raw pointer to the HWNDMessageHandler instance as we track the
// window destruction and ensure that the map is cleaned up.
diff --git a/chromium/ui/views/win/hwnd_util.h b/chromium/ui/views/win/hwnd_util.h
index 6e3e2f09ae0..1aaacb98715 100644
--- a/chromium/ui/views/win/hwnd_util.h
+++ b/chromium/ui/views/win/hwnd_util.h
@@ -5,6 +5,7 @@
#ifndef UI_VIEWS_WIN_HWND_UTIL_H_
#define UI_VIEWS_WIN_HWND_UTIL_H_
+#include "ui/gfx/geometry/point.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/native_widget_types.h"
#include "ui/views/views_export.h"
@@ -28,6 +29,12 @@ VIEWS_EXPORT HWND HWNDForNativeWindow(const gfx::NativeWindow window);
VIEWS_EXPORT gfx::Rect GetWindowBoundsForClientBounds(
View* view, const gfx::Rect& client_bounds);
+
+// Shows |window|'s system menu (at a specified |point| in screen physical
+// coordinates).
+VIEWS_EXPORT void ShowSystemMenuAtScreenPixelLocation(HWND window,
+ const gfx::Point& point);
+
} // namespace views
#endif // UI_VIEWS_WIN_HWND_UTIL_H_
diff --git a/chromium/ui/views/win/hwnd_util_aurawin.cc b/chromium/ui/views/win/hwnd_util_aurawin.cc
index cbd06d0f505..f404e7e2ed3 100644
--- a/chromium/ui/views/win/hwnd_util_aurawin.cc
+++ b/chromium/ui/views/win/hwnd_util_aurawin.cc
@@ -4,6 +4,7 @@
#include "ui/views/win/hwnd_util.h"
+#include "base/i18n/rtl.h"
#include "ui/aura/window.h"
#include "ui/aura/window_tree_host.h"
#include "ui/views/widget/widget.h"
@@ -44,4 +45,17 @@ gfx::Rect GetWindowBoundsForClientBounds(View* view,
return client_bounds;
}
+void ShowSystemMenuAtScreenPixelLocation(HWND window, const gfx::Point& point) {
+ UINT flags = TPM_LEFTALIGN | TPM_TOPALIGN | TPM_RIGHTBUTTON | TPM_RETURNCMD;
+ if (base::i18n::IsRTL())
+ flags |= TPM_RIGHTALIGN;
+ HMENU menu = GetSystemMenu(window, FALSE);
+
+ const int command =
+ TrackPopupMenu(menu, flags, point.x(), point.y(), 0, window, nullptr);
+
+ if (command)
+ SendMessage(window, WM_SYSCOMMAND, command, 0);
+}
+
} // namespace views
diff --git a/chromium/ui/views/win/pen_event_processor.cc b/chromium/ui/views/win/pen_event_processor.cc
index 6e8f488afee..36de1decc92 100644
--- a/chromium/ui/views/win/pen_event_processor.cc
+++ b/chromium/ui/views/win/pen_event_processor.cc
@@ -199,7 +199,7 @@ std::unique_ptr<ui::Event> PenEventProcessor::GenerateTouchEvent(
flags | ui::GetModifiersFromKeyState());
event->set_hovering(event_type == ui::ET_TOUCH_RELEASED);
event->latency()->AddLatencyNumberWithTimestamp(
- ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, event_time, 1);
+ ui::INPUT_EVENT_LATENCY_ORIGINAL_COMPONENT, event_time);
return event;
}
diff --git a/chromium/ui/views/window/client_view.cc b/chromium/ui/views/window/client_view.cc
index 88842b61df8..646b1ea8f54 100644
--- a/chromium/ui/views/window/client_view.cc
+++ b/chromium/ui/views/window/client_view.cc
@@ -12,10 +12,6 @@
namespace views {
-// static
-const char ClientView::kViewClassName[] =
- "ui/views/window/ClientView";
-
///////////////////////////////////////////////////////////////////////////////
// ClientView, public:
@@ -70,9 +66,6 @@ void ClientView::Layout() {
contents_view_->SetBounds(0, 0, width(), height());
}
-const char* ClientView::GetClassName() const {
- return kViewClassName;
-}
void ClientView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
node_data->role = ax::mojom::Role::kClient;
@@ -97,4 +90,8 @@ void ClientView::ViewHierarchyChanged(
}
}
+BEGIN_METADATA(ClientView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/window/client_view.h b/chromium/ui/views/window/client_view.h
index c0b4e5b1c44..b237a75462b 100644
--- a/chromium/ui/views/window/client_view.h
+++ b/chromium/ui/views/window/client_view.h
@@ -22,8 +22,7 @@ class Widget;
// "DialogClientView".
class VIEWS_EXPORT ClientView : public View {
public:
- // Internal class name
- static const char kViewClassName[];
+ METADATA_HEADER(ClientView);
// Constructs a ClientView object for the specified widget with the specified
// contents. Since this object is created during the process of creating
@@ -61,7 +60,6 @@ class VIEWS_EXPORT ClientView : public View {
gfx::Size GetMinimumSize() const override;
gfx::Size GetMaximumSize() const override;
void Layout() override;
- const char* GetClassName() const override;
protected:
// Overridden from View:
diff --git a/chromium/ui/views/window/custom_frame_view.cc b/chromium/ui/views/window/custom_frame_view.cc
index ad809569a9b..4be7f5a667c 100644
--- a/chromium/ui/views/window/custom_frame_view.cc
+++ b/chromium/ui/views/window/custom_frame_view.cc
@@ -16,6 +16,7 @@
#include "ui/base/resource/resource_bundle.h"
#include "ui/gfx/canvas.h"
#include "ui/gfx/font.h"
+#include "ui/gfx/font_list.h"
#include "ui/gfx/geometry/rect.h"
#include "ui/gfx/image/image.h"
#include "ui/strings/grit/ui_strings.h"
@@ -33,6 +34,7 @@
#if defined(OS_WIN)
#include "ui/display/win/screen_win.h"
+#include "ui/gfx/system_fonts_win.h"
#endif
namespace views {
@@ -67,12 +69,6 @@ constexpr SkColor kDefaultColorFrame = SkColorSetRGB(66, 116, 201);
constexpr SkColor kDefaultColorFrameInactive = SkColorSetRGB(161, 182, 228);
#endif
-const gfx::FontList& GetTitleFontList() {
- static const gfx::FontList title_font_list =
- internal::NativeWidgetPrivate::GetWindowTitleFontList();
- return title_font_list;
-}
-
void LayoutButton(ImageButton* button, const gfx::Rect& bounds) {
button->SetVisible(true);
button->SetImageVerticalAlignment(ImageButton::ALIGN_BOTTOM);
@@ -311,7 +307,7 @@ int CustomFrameView::IconSize() const {
#else
// The icon never shrinks below 16 px on a side.
constexpr int kIconMinimumSize = 16;
- return std::max(GetTitleFontList().GetHeight(), kIconMinimumSize);
+ return std::max(GetWindowTitleFontList().GetHeight(), kIconMinimumSize);
#endif
}
@@ -393,7 +389,7 @@ void CustomFrameView::PaintTitleBar(gfx::Canvas* canvas) {
gfx::Rect rect = title_bounds_;
rect.set_x(GetMirroredXForRect(title_bounds_));
- canvas->DrawStringRect(delegate->GetWindowTitle(), GetTitleFontList(),
+ canvas->DrawStringRect(delegate->GetWindowTitle(), GetWindowTitleFontList(),
SK_ColorWHITE, rect);
}
@@ -547,7 +543,7 @@ void CustomFrameView::LayoutTitleBar() {
// The offset between the window left edge and the title text.
int title_x = show_window_icon ? icon_bounds.right() + kTitleIconOffsetX
: icon_bounds.x();
- int title_height = GetTitleFontList().GetHeight();
+ int title_height = GetWindowTitleFontList().GetHeight();
// We bias the title position so that when the difference between the icon and
// title heights is odd, the extra pixel of the title is above the vertical
// midline rather than below. This compensates for how the icon is already
@@ -625,4 +621,13 @@ ImageButton* CustomFrameView::GetImageButton(views::FrameButton frame_button) {
return button;
}
+// static
+gfx::FontList CustomFrameView::GetWindowTitleFontList() {
+#if defined(OS_WIN)
+ return gfx::FontList(gfx::win::GetSystemFont(gfx::win::SystemFont::kCaption));
+#else
+ return gfx::FontList();
+#endif
+}
+
} // namespace views
diff --git a/chromium/ui/views/window/custom_frame_view.h b/chromium/ui/views/window/custom_frame_view.h
index e791aca92f4..759b9f3f864 100644
--- a/chromium/ui/views/window/custom_frame_view.h
+++ b/chromium/ui/views/window/custom_frame_view.h
@@ -14,6 +14,10 @@
#include "ui/views/window/frame_buttons.h"
#include "ui/views/window/non_client_view.h"
+namespace gfx {
+class FontList;
+}
+
namespace views {
class FrameBackground;
@@ -58,6 +62,10 @@ class VIEWS_EXPORT CustomFrameView : public NonClientFrameView,
// Overridden from ButtonListener:
void ButtonPressed(Button* sender, const ui::Event& event) override;
+ // Returns the font list to use in the window's title bar.
+ // TODO(https://crbug.com/968860): Move this into the typography provider.
+ static gfx::FontList GetWindowTitleFontList();
+
private:
friend class CustomFrameViewTest;
diff --git a/chromium/ui/views/window/dialog_client_view.cc b/chromium/ui/views/window/dialog_client_view.cc
index 84f4db075d0..4c946da528f 100644
--- a/chromium/ui/views/window/dialog_client_view.cc
+++ b/chromium/ui/views/window/dialog_client_view.cc
@@ -15,7 +15,6 @@
#include "ui/views/controls/button/image_button.h"
#include "ui/views/controls/button/label_button.h"
#include "ui/views/controls/button/md_text_button.h"
-#include "ui/views/event_utils.h"
#include "ui/views/layout/grid_layout.h"
#include "ui/views/layout/layout_provider.h"
#include "ui/views/style/platform_style.h"
@@ -77,8 +76,8 @@ DialogClientView::DialogClientView(Widget* owner, View* contents_view)
// Doing this now ensures this accelerator will have lower priority than
// one set by the contents view.
AddAccelerator(ui::Accelerator(ui::VKEY_ESCAPE, ui::EF_NONE));
- button_row_container_ = new ButtonRowContainer(this);
- AddChildView(button_row_container_);
+ button_row_container_ =
+ AddChildView(std::make_unique<ButtonRowContainer>(this));
}
DialogClientView::~DialogClientView() {
@@ -167,9 +166,7 @@ gfx::Size DialogClientView::GetMaximumSize() const {
void DialogClientView::VisibilityChanged(View* starting_from, bool is_visible) {
ClientView::VisibilityChanged(starting_from, is_visible);
-
- if (is_visible)
- view_shown_time_stamp_ = base::TimeTicks::Now();
+ input_protector_.VisibilityChanged(is_visible);
}
void DialogClientView::Layout() {
@@ -242,7 +239,7 @@ void DialogClientView::ButtonPressed(Button* sender, const ui::Event& event) {
if (!GetDialogDelegate())
return;
- if (IsPossiblyUnintendedInteraction(view_shown_time_stamp_, event))
+ if (input_protector_.IsPossiblyUnintendedInteraction(event))
return;
if (sender == ok_button_)
@@ -254,7 +251,7 @@ void DialogClientView::ButtonPressed(Button* sender, const ui::Event& event) {
}
void DialogClientView::ResetViewShownTimeStampForTesting() {
- view_shown_time_stamp_ = base::TimeTicks();
+ input_protector_.ResetForTesting();
}
////////////////////////////////////////////////////////////////////////////////
@@ -296,7 +293,7 @@ void DialogClientView::UpdateDialogButton(LabelButton** member,
// MdTextButton, make it so. Note that some overrides may not always update
// the title (they should). See http://crbug.com/697303 .
const base::string16 title = delegate->GetDialogButtonLabel(type);
- std::unique_ptr<LabelButton> button = nullptr;
+ std::unique_ptr<LabelButton> button;
const bool is_default = delegate->GetDefaultDialogButton() == type &&
(type != ui::DIALOG_BUTTON_CANCEL ||
@@ -311,7 +308,7 @@ void DialogClientView::UpdateDialogButton(LabelButton** member,
button->SetGroup(kButtonGroup);
- *member = button.release();
+ *member = button_row_container_->AddChildView(std::move(button));
}
delegate->UpdateButton(*member, type);
@@ -346,19 +343,26 @@ void DialogClientView::SetupLayout() {
// Clobber any existing LayoutManager since it has weak references to child
// Views which may be removed by SetupViews().
- GridLayout* layout = button_row_container_->SetLayoutManager(
- std::make_unique<views::GridLayout>(button_row_container_));
- layout->set_minimum_size(minimum_size_);
+ button_row_container_->SetLayoutManager(nullptr);
SetupViews();
+
const std::array<View*, kNumButtons> views = GetButtonRowViews();
// Visibility changes on |extra_view_| must be observed to re-Layout. However,
// when hidden it's not included in the button row (it can't influence layout)
// and it can't be added to |button_row_container_| (GridLayout complains).
// So add it, hidden, to |this| so it can be observed.
- if (extra_view_ && !views[0])
- AddChildView(extra_view_);
+ if (extra_view_) {
+ if (!views[0])
+ AddChildView(extra_view_);
+ else
+ button_row_container_->AddChildViewAt(extra_view_, 0);
+ }
+
+ GridLayout* layout = button_row_container_->SetLayoutManager(
+ std::make_unique<views::GridLayout>());
+ layout->set_minimum_size(minimum_size_);
if (std::count(views.begin(), views.end(), nullptr) == kNumButtons)
return;
@@ -402,7 +406,7 @@ void DialogClientView::SetupLayout() {
button_row_insets_.top());
for (size_t view_index = 0; view_index < kNumButtons; ++view_index) {
if (views[view_index]) {
- layout->AddView(views[view_index]);
+ layout->AddExistingView(views[view_index]);
link[link_index++] = kViewToColumnIndex[view_index];
} else {
layout->SkipColumns(1);
@@ -437,21 +441,24 @@ void DialogClientView::SetupLayout() {
}
void DialogClientView::SetupViews() {
- button_row_container_->RemoveAllChildViews(false /* delete children */);
- // If SetupLayout() "stored" a hidden |extra_view_| in |this|, ensure it can
- // be re-added to the layout when becoming visible.
- if (extra_view_)
- RemoveChildView(extra_view_);
-
- UpdateDialogButton(&ok_button_, ui::DIALOG_BUTTON_OK);
- UpdateDialogButton(&cancel_button_, ui::DIALOG_BUTTON_CANCEL);
+ if (PlatformStyle::kIsOkButtonLeading) {
+ UpdateDialogButton(&ok_button_, ui::DIALOG_BUTTON_OK);
+ UpdateDialogButton(&cancel_button_, ui::DIALOG_BUTTON_CANCEL);
+ } else {
+ UpdateDialogButton(&cancel_button_, ui::DIALOG_BUTTON_CANCEL);
+ UpdateDialogButton(&ok_button_, ui::DIALOG_BUTTON_OK);
+ }
if (extra_view_)
return;
- extra_view_ = GetDialogDelegate()->CreateExtraView();
+ extra_view_ = GetDialogDelegate()->CreateExtraView().release();
if (extra_view_ && Button::AsButton(extra_view_))
extra_view_->SetGroup(kButtonGroup);
}
+BEGIN_METADATA(DialogClientView)
+METADATA_PARENT_CLASS(ClientView)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/window/dialog_client_view.h b/chromium/ui/views/window/dialog_client_view.h
index e36af7a2038..fb557cbf4ff 100644
--- a/chromium/ui/views/window/dialog_client_view.h
+++ b/chromium/ui/views/window/dialog_client_view.h
@@ -10,6 +10,7 @@
#include "base/time/time.h"
#include "ui/base/ui_base_types.h"
#include "ui/views/controls/button/button.h"
+#include "ui/views/input_event_activation_protector.h"
#include "ui/views/window/client_view.h"
#include "ui/views/window/dialog_observer.h"
@@ -33,6 +34,8 @@ class VIEWS_EXPORT DialogClientView : public ClientView,
public ButtonListener,
public DialogObserver {
public:
+ METADATA_HEADER(DialogClientView);
+
DialogClientView(Widget* widget, View* contents_view);
~DialogClientView() override;
@@ -140,8 +143,7 @@ class VIEWS_EXPORT DialogClientView : public ClientView,
// SetupLayout(). Everything will be manually updated afterwards.
bool adding_or_removing_views_ = false;
- // Time when view has been shown.
- base::TimeTicks view_shown_time_stamp_;
+ InputEventActivationProtector input_protector_;
DISALLOW_COPY_AND_ASSIGN(DialogClientView);
};
diff --git a/chromium/ui/views/window/dialog_client_view_unittest.cc b/chromium/ui/views/window/dialog_client_view_unittest.cc
index a7be998428c..152917b805b 100644
--- a/chromium/ui/views/window/dialog_client_view_unittest.cc
+++ b/chromium/ui/views/window/dialog_client_view_unittest.cc
@@ -68,7 +68,9 @@ class DialogClientViewTest : public test::WidgetTest,
// DialogDelegateView would delete this, but |this| is owned by the test.
}
- View* CreateExtraView() override { return next_extra_view_.release(); }
+ std::unique_ptr<View> CreateExtraView() override {
+ return std::move(next_extra_view_);
+ }
bool GetExtraViewPadding(int* padding) override {
if (extra_view_padding_)
@@ -512,10 +514,11 @@ TEST_F(DialogClientViewTest, FocusChangingButtons) {
}
// Ensures that clicks are ignored for short time after view has been shown.
-TEST_F(DialogClientViewTest, IgnorePossiblyUnintendedClicks) {
+TEST_F(DialogClientViewTest, IgnorePossiblyUnintendedClicks_ClickAfterShown) {
widget()->Show();
SetDialogButtons(ui::DIALOG_BUTTON_CANCEL | ui::DIALOG_BUTTON_OK);
+ // Should ignore clicks right after the dialog is shown.
ui::MouseEvent mouse_event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
ui::EventTimeForNow(), ui::EF_NONE, ui::EF_NONE);
client_view()->ButtonPressed(client_view()->ok_button(), mouse_event);
@@ -531,4 +534,45 @@ TEST_F(DialogClientViewTest, IgnorePossiblyUnintendedClicks) {
EXPECT_TRUE(widget()->IsClosed());
}
+// Ensures that repeated clicks with short intervals after view has been shown
+// are also ignored.
+TEST_F(DialogClientViewTest, IgnorePossiblyUnintendedClicks_RepeatedClicks) {
+ widget()->Show();
+ SetDialogButtons(ui::DIALOG_BUTTON_CANCEL | ui::DIALOG_BUTTON_OK);
+
+ const base::TimeTicks kNow = ui::EventTimeForNow();
+ const base::TimeDelta kShortClickInterval =
+ base::TimeDelta::FromMilliseconds(GetDoubleClickInterval());
+
+ // Should ignore clicks right after the dialog is shown.
+ ui::MouseEvent mouse_event(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+ kNow, ui::EF_NONE, ui::EF_NONE);
+ client_view()->ButtonPressed(client_view()->ok_button(), mouse_event);
+ client_view()->ButtonPressed(client_view()->cancel_button(), mouse_event);
+ EXPECT_FALSE(widget()->IsClosed());
+
+ // Should ignore repeated clicks with short intervals, even though enough time
+ // has passed since the dialog was shown.
+ const base::TimeDelta kRepeatedClickInterval = kShortClickInterval / 2;
+ const size_t kNumClicks = 4;
+ ASSERT_TRUE(kNumClicks * kRepeatedClickInterval > kShortClickInterval);
+ base::TimeTicks event_time = kNow;
+ for (size_t i = 0; i < kNumClicks; i++) {
+ client_view()->ButtonPressed(
+ client_view()->cancel_button(),
+ ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+ event_time, ui::EF_NONE, ui::EF_NONE));
+ EXPECT_FALSE(widget()->IsClosed());
+ event_time += kRepeatedClickInterval;
+ }
+
+ // Sufficient time passed, events are now allowed.
+ event_time += kShortClickInterval;
+ client_view()->ButtonPressed(
+ client_view()->cancel_button(),
+ ui::MouseEvent(ui::ET_MOUSE_PRESSED, gfx::Point(), gfx::Point(),
+ event_time, ui::EF_NONE, ui::EF_NONE));
+ EXPECT_TRUE(widget()->IsClosed());
+}
+
} // namespace views
diff --git a/chromium/ui/views/window/dialog_delegate.cc b/chromium/ui/views/window/dialog_delegate.cc
index badb55d8df8..6f1ed11c1cf 100644
--- a/chromium/ui/views/window/dialog_delegate.cc
+++ b/chromium/ui/views/window/dialog_delegate.cc
@@ -122,7 +122,7 @@ bool DialogDelegate::IsDialogButtonEnabled(ui::DialogButton button) const {
return true;
}
-View* DialogDelegate::CreateExtraView() {
+std::unique_ptr<View> DialogDelegate::CreateExtraView() {
return nullptr;
}
@@ -130,7 +130,7 @@ bool DialogDelegate::GetExtraViewPadding(int* padding) {
return false;
}
-View* DialogDelegate::CreateFootnoteView() {
+std::unique_ptr<View> DialogDelegate::CreateFootnoteView() {
return nullptr;
}
diff --git a/chromium/ui/views/window/dialog_delegate.h b/chromium/ui/views/window/dialog_delegate.h
index 253777d0ba4..114e1f970ae 100644
--- a/chromium/ui/views/window/dialog_delegate.h
+++ b/chromium/ui/views/window/dialog_delegate.h
@@ -5,6 +5,8 @@
#ifndef UI_VIEWS_WINDOW_DIALOG_DELEGATE_H_
#define UI_VIEWS_WINDOW_DIALOG_DELEGATE_H_
+#include <memory>
+
#include "base/compiler_specific.h"
#include "base/macros.h"
#include "base/strings/string16.h"
@@ -68,7 +70,7 @@ class VIEWS_EXPORT DialogDelegate : public WidgetDelegate {
// Override this function to display an extra view adjacent to the buttons.
// Overrides may construct the view; this will only be called once per dialog.
- virtual View* CreateExtraView();
+ virtual std::unique_ptr<View> CreateExtraView();
// Override this function to adjust the padding between the extra view and
// the confirm/cancel buttons. Note that if there are no buttons, this will
@@ -78,7 +80,7 @@ class VIEWS_EXPORT DialogDelegate : public WidgetDelegate {
// Override this function to display a footnote view below the buttons.
// Overrides may construct the view; this will only be called once per dialog.
- virtual View* CreateFootnoteView();
+ virtual std::unique_ptr<View> CreateFootnoteView();
// For Dialog boxes, if there is a "Cancel" button or no dialog button at all,
// this is called when the user presses the "Cancel" button.
diff --git a/chromium/ui/views/window/non_client_view.cc b/chromium/ui/views/window/non_client_view.cc
index 3c583973553..167888d4b39 100644
--- a/chromium/ui/views/window/non_client_view.cc
+++ b/chromium/ui/views/window/non_client_view.cc
@@ -15,14 +15,11 @@
#include "ui/views/widget/widget.h"
#include "ui/views/window/client_view.h"
-namespace views {
-
-// static
-const char NonClientFrameView::kViewClassName[] =
- "ui/views/window/NonClientFrameView";
+#if defined(OS_WIN)
+#include "ui/display/win/screen_win.h"
+#endif
-const char NonClientView::kViewClassName[] =
- "ui/views/window/NonClientView";
+namespace views {
// The frame view and the client view are always at these specific indices,
// because the RootView message dispatch sends messages to items higher in the
@@ -40,6 +37,17 @@ bool NonClientFrameView::GetClientMask(const gfx::Size& size,
return false;
}
+#if defined(OS_WIN)
+gfx::Point NonClientFrameView::GetSystemMenuScreenPixelLocation() const {
+ gfx::Point point(GetMirroredXInView(GetBoundsForClientView().x()),
+ GetSystemMenuY());
+ View::ConvertPointToScreen(this, &point);
+ point = display::win::ScreenWin::DIPToScreenPoint(point);
+ // The native system menu seems to overlap the titlebar by 1 px. Match that.
+ return point - gfx::Vector2d(0, 1);
+}
+#endif
+
////////////////////////////////////////////////////////////////////////////////
// NonClientView, public:
@@ -195,10 +203,6 @@ void NonClientView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
node_data->SetName(accessible_name_);
}
-const char* NonClientView::GetClassName() const {
- return kViewClassName;
-}
-
View* NonClientView::GetTooltipHandlerForPoint(const gfx::Point& point) {
// The same logic as for |TargetForRect()| applies here.
if (frame_view_->parent() == this) {
@@ -244,6 +248,10 @@ View* NonClientView::TargetForRect(View* root, const gfx::Rect& rect) {
return ViewTargeterDelegate::TargetForRect(root, rect);
}
+BEGIN_METADATA(NonClientView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
////////////////////////////////////////////////////////////////////////////////
// NonClientFrameView, public:
@@ -308,10 +316,6 @@ void NonClientFrameView::GetAccessibleNodeData(ui::AXNodeData* node_data) {
node_data->role = ax::mojom::Role::kClient;
}
-const char* NonClientFrameView::GetClassName() const {
- return kViewClassName;
-}
-
void NonClientFrameView::OnThemeChanged() {
SchedulePaint();
}
@@ -333,4 +337,17 @@ bool NonClientFrameView::DoesIntersectRect(const View* target,
return !GetWidget()->client_view()->bounds().Intersects(rect);
}
+////////////////////////////////////////////////////////////////////////////////
+// NonClientFrameView, private:
+
+#if defined(OS_WIN)
+int NonClientFrameView::GetSystemMenuY() const {
+ return GetBoundsForClientView().y();
+}
+#endif
+
+BEGIN_METADATA(NonClientFrameView)
+METADATA_PARENT_CLASS(View)
+END_METADATA()
+
} // namespace views
diff --git a/chromium/ui/views/window/non_client_view.h b/chromium/ui/views/window/non_client_view.h
index 080e99d3938..a37c98cc9f6 100644
--- a/chromium/ui/views/window/non_client_view.h
+++ b/chromium/ui/views/window/non_client_view.h
@@ -6,6 +6,7 @@
#define UI_VIEWS_WINDOW_NON_CLIENT_VIEW_H_
#include "base/macros.h"
+#include "build/build_config.h"
#include "ui/views/view.h"
#include "ui/views/view_targeter_delegate.h"
@@ -23,8 +24,7 @@ class ClientView;
class VIEWS_EXPORT NonClientFrameView : public View,
public ViewTargeterDelegate {
public:
- // Internal class name.
- static const char kViewClassName[];
+ METADATA_HEADER(NonClientFrameView);
enum {
// Various edges of the frame border have a 1 px shadow along their edges;
@@ -66,6 +66,12 @@ class VIEWS_EXPORT NonClientFrameView : public View,
// used.
virtual bool GetClientMask(const gfx::Size& size, SkPath* mask) const;
+#if defined(OS_WIN)
+ // Returns the point in screen physical coordinates at which the system menu
+ // should be opened.
+ virtual gfx::Point GetSystemMenuScreenPixelLocation() const;
+#endif
+
// This function must ask the ClientView to do a hittest. We don't do this in
// the parent NonClientView because that makes it more difficult to calculate
// hittests for regions that are partially obscured by the ClientView, e.g.
@@ -89,7 +95,6 @@ class VIEWS_EXPORT NonClientFrameView : public View,
// View:
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
- const char* GetClassName() const override;
void OnThemeChanged() override;
protected:
@@ -100,6 +105,13 @@ class VIEWS_EXPORT NonClientFrameView : public View,
const gfx::Rect& rect) const override;
private:
+#if defined(OS_WIN)
+ // Returns the y coordinate, in local coordinates, at which the system menu
+ // should be opened. Since this is in DIP, it does not include the 1 px
+ // offset into the caption area; the caller will take care of this.
+ virtual int GetSystemMenuY() const;
+#endif
+
DISALLOW_COPY_AND_ASSIGN(NonClientFrameView);
};
@@ -141,8 +153,7 @@ class VIEWS_EXPORT NonClientFrameView : public View,
//
class VIEWS_EXPORT NonClientView : public View, public ViewTargeterDelegate {
public:
- // Internal class name.
- static const char kViewClassName[];
+ METADATA_HEADER(NonClientView);
NonClientView();
~NonClientView() override;
@@ -217,7 +228,6 @@ class VIEWS_EXPORT NonClientView : public View, public ViewTargeterDelegate {
gfx::Size GetMaximumSize() const override;
void Layout() override;
void GetAccessibleNodeData(ui::AXNodeData* node_data) override;
- const char* GetClassName() const override;
views::View* GetTooltipHandlerForPoint(const gfx::Point& point) override;